/*
=head1 GV Functions
-
A GV is a structure which corresponds to to a Perl typeglob, ie *foo.
It is a structure that holds a pointer to a scalar, an array, a hash etc,
corresponding to $foo, @foo, %foo.
case SVt_PVIO:
Perl_croak(aTHX_ "Cannot convert a reference to %s to typeglob",
sv_reftype(has_constant, 0));
+
default: NOOP;
}
SvRV_set(gv, NULL);
case 'b':
if (len == 1 && sv_type == SVt_PV)
GvMULTI_on(gv);
- /* FALL THROUGH */
+ /* FALLTHROUGH */
default:
goto try_core;
}
case '\023': /* $^S */
ro_magicalize:
SvREADONLY_on(GvSVn(gv));
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case '0': /* $0 */
case '^': /* $^ */
case '~': /* $~ */
gv_fullname4(sv, egv ? egv : gv, prefix, keepmain);
}
+
+/* recursively scan a stash and any nested stashes looking for entries
+ * that need the "only used once" warning raised
+ */
+
void
Perl_gv_check(pTHX_ HV *stash)
{
dVAR;
I32 i;
- struct xpvhv_aux *aux;
PERL_ARGS_ASSERT_GV_CHECK;
return;
assert(SvOOK(stash));
- aux = HvAUX(stash);
for (i = 0; i <= (I32) HvMAX(stash); i++) {
const HE *entry;
/* mark stash is being scanned, to avoid recursing */
- aux->xhv_aux_flags |= HvAUXf_SCAN_STASH;
+ HvAUX(stash)->xhv_aux_flags |= HvAUXf_SCAN_STASH;
for (entry = HvARRAY(stash)[i]; entry; entry = HeNEXT(entry)) {
GV *gv;
HV *hv;
HEKfARG(GvNAME_HEK(gv)));
}
}
- aux->xhv_aux_flags &= ~HvAUXf_SCAN_STASH;
+ HvAUX(stash)->xhv_aux_flags &= ~HvAUXf_SCAN_STASH;
}
}
Somehow gp->gp_hv can end up pointing at freed garbage. */
if (hv && SvTYPE(hv) == SVt_PVHV) {
const HEK *hvname_hek = HvNAME_HEK(hv);
- DEBUG_o(Perl_deb(aTHX_ "gp_free clearing PL_stashcache for '%"HEKf"'\n", hvname_hek));
+ DEBUG_o(Perl_deb(aTHX_ "gp_free clearing PL_stashcache for '%"HEKf"'\n", HEKfARG(hvname_hek)));
if (PL_stashcache && hvname_hek)
(void)hv_deletehek(PL_stashcache, hvname_hek, G_DISCARD);
SvREFCNT_dec(hv);
{
int filled = 0;
int i;
+ bool deref_seen = 0;
+
/* Work with "fallback" key, which we assume to be first in PL_AMG_names */
filled = 1;
}
+ assert(SvOOK(stash));
+ /* initially assume the worst */
+ HvAUX(stash)->xhv_aux_flags &= ~HvAUXf_NO_DEREF;
+
for (i = 1; i < NofAMmeth; i++) {
const char * const cooky = PL_AMG_names[i];
/* Human-readable form, for debugging: */
filled = 1;
}
amt.table[i]=MUTABLE_CV(SvREFCNT_inc_simple(cv));
+
+ if (gv) {
+ switch (i) {
+ case to_sv_amg:
+ case to_av_amg:
+ case to_hv_amg:
+ case to_gv_amg:
+ case to_cv_amg:
+ case nomethod_amg:
+ deref_seen = 1;
+ break;
+ }
+ }
}
+ if (!deref_seen)
+ /* none of @{} etc overloaded; we can do $obj->[N] quicker.
+ * NB - aux var invalid here, HvARRAY() could have been
+ * reallocated since it was assigned to */
+ HvAUX(stash)->xhv_aux_flags |= HvAUXf_NO_DEREF;
+
if (filled) {
AMT_AMAGIC_on(&amt);
sv_magic(MUTABLE_SV(stash), 0, PERL_MAGIC_overload_table,
SV *
Perl_amagic_deref_call(pTHX_ SV *ref, int method) {
SV *tmpsv = NULL;
+ HV *stash;
PERL_ARGS_ASSERT_AMAGIC_DEREF_CALL;
- while (SvAMAGIC(ref) &&
- (tmpsv = amagic_call(ref, &PL_sv_undef, method,
+ if (!SvAMAGIC(ref))
+ return ref;
+ /* return quickly if none of the deref ops are overloaded */
+ stash = SvSTASH(SvRV(ref));
+ assert(SvOOK(stash));
+ if (HvAUX(stash)->xhv_aux_flags & HvAUXf_NO_DEREF)
+ return ref;
+
+ while ((tmpsv = amagic_call(ref, &PL_sv_undef, method,
AMGf_noright | AMGf_unary))) {
if (!SvROK(tmpsv))
Perl_croak(aTHX_ "Overloaded dereference did not return a reference");
return tmpsv;
}
ref = tmpsv;
+ if (!SvAMAGIC(ref))
+ break;
}
return tmpsv ? tmpsv : ref;
}
case regexp_amg:
/* FAIL safe */
return NULL; /* Delegate operation to standard mechanisms. */
- break;
+
case to_sv_amg:
case to_av_amg:
case to_hv_amg:
case to_cv_amg:
/* FAIL safe */
return left; /* Delegate operation to standard mechanisms. */
- break;
+
default:
goto not_found;
}
case to_cv_amg:
/* FAIL safe */
return left; /* Delegate operation to standard mechanisms. */
- break;
}
if (ocvp && (cv=ocvp[nomethod_amg])) { /* Call report method */
notfound = 1; lr = -1;