DEBUG_o( Perl_deb(aTHX_ "Looking for method %s in package %s\n",name,hvname) );
- topgen_cmp = HvMROMETA(stash)->sub_generation + PL_sub_generation;
+ topgen_cmp = HvMROMETA(stash)->cache_gen + PL_sub_generation;
/* check locally for a real method or a cache entry */
gvp = (GV**)hv_fetch(stash, name, len, create);
assert(linear_sv);
cstash = gv_stashsv(linear_sv, 0);
- /* mg.c:Perl_magic_setisa sets the fake flag on packages it had
- to create that the user did not. The "package" statement
- clears it. We also check if there's anything in the symbol
- table at all, which would indicate a previously "fake" package
- where someone adding things via $Foo::Bar = 1 without ever
- using a "package" statement.
- This was all neccesary because magic_setisa needs a place to
- keep isarev information on packages that aren't yet defined,
- yet we still need to issue this warning when appropriate.
- */
- if (!cstash || (HvMROMETA(cstash)->fake && !HvFILL(cstash))) {
- if (ckWARN(WARN_MISC))
- Perl_warner(aTHX_ packWARN(WARN_MISC), "Can't locate package %"SVf" for @%s::ISA",
+ if (!cstash) {
+ if (ckWARN(WARN_SYNTAX))
+ Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Can't locate package %"SVf" for @%s::ISA",
SVfARG(linear_sv), hvname);
continue;
}
=cut
*/
+STATIC HV*
+S_gv_get_super_pkg(pTHX_ const char* name, I32 namelen)
+{
+ AV* superisa;
+ GV** gvp;
+ GV* gv;
+ HV* stash;
+
+ stash = gv_stashpvn(name, namelen, 0);
+ if(stash) return stash;
+
+ /* If we must create it, give it an @ISA array containing
+ the real package this SUPER is for, so that it's tied
+ into the cache invalidation code correctly */
+ stash = gv_stashpvn(name, namelen, GV_ADD);
+ gvp = (GV**)hv_fetchs(stash, "ISA", TRUE);
+ gv = *gvp;
+ gv_init(gv, stash, "ISA", 3, TRUE);
+ superisa = GvAVn(gv);
+ GvMULTI_on(gv);
+ sv_magic((SV*)superisa, (SV*)gv, PERL_MAGIC_isa, NULL, 0);
+ av_push(superisa, newSVpv(CopSTASHPV(PL_curcop), 0));
+
+ return stash;
+}
+
GV *
Perl_gv_fetchmethod_autoload(pTHX_ HV *stash, const char *name, I32 autoload)
{
SV * const tmpstr = sv_2mortal(Perl_newSVpvf(aTHX_ "%s::SUPER",
CopSTASHPV(PL_curcop)));
/* __PACKAGE__::SUPER stash should be autovivified */
- stash = gv_stashpvn(SvPVX_const(tmpstr), SvCUR(tmpstr), GV_ADD);
+ stash = gv_get_super_pkg(SvPVX_const(tmpstr), SvCUR(tmpstr));
DEBUG_o( Perl_deb(aTHX_ "Treating %s as %s::%s\n",
origname, HvNAME_get(stash), name) );
}
if (!stash && (nsplit - origname) >= 7 &&
strnEQ(nsplit - 7, "::SUPER", 7) &&
gv_stashpvn(origname, nsplit - origname - 7, 0))
- stash = gv_stashpvn(origname, nsplit - origname, GV_ADD);
+ stash = gv_get_super_pkg(origname, nsplit - origname);
}
ostash = stash;
}
if (*name == '!')
require_tie_mod(gv, "!", newSVpvs("Errno"), "TIEHASH", 1);
else if (*name == '-' || *name == '+')
- require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "FETCH", 0);
+ require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "TIEHASH", 0);
}
}
return gv;
break;
case '\015': /* $^MATCH */
if (strEQ(name2, "ATCH"))
- goto ro_magicalize;
+ goto magicalize;
case '\017': /* $^OPEN */
if (strEQ(name2, "PEN"))
goto magicalize;
break;
case '\020': /* $^PREMATCH $^POSTMATCH */
if (strEQ(name2, "REMATCH") || strEQ(name2, "OSTMATCH"))
- goto ro_magicalize;
+ goto magicalize;
case '\024': /* ${^TAINT} */
if (strEQ(name2, "AINT"))
goto ro_magicalize;
case '8':
case '9':
{
- /* ensures variable is only digits */
- /* ${"1foo"} fails this test (and is thus writeable) */
- /* added by japhy, but borrowed from is_gv_magical */
+ /* Ensures that we have an all-digit variable, ${"1foo"} fails
+ this test */
+ /* This snippet is taken from is_gv_magical */
const char *end = name + len;
while (--end > name) {
- if (!isDIGIT(*end)) return gv;
+ if (!isDIGIT(*end)) return gv;
}
- goto ro_magicalize;
+ goto magicalize;
}
}
}
sv_type == SVt_PVIO
) { break; }
PL_sawampersand = TRUE;
- goto ro_magicalize;
+ goto magicalize;
case ':':
sv_setpv(GvSVn(gv),PL_chopset);
SvREADONLY_on(av);
if (sv_type == SVt_PVHV || sv_type == SVt_PVGV)
- require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "FETCH", 0);
+ require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "TIEHASH", 0);
break;
}
case '*':
case '#':
- if (sv_type == SVt_PV && ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
+ if (sv_type == SVt_PV && ckWARN2_d(WARN_DEPRECATED, WARN_SYNTAX))
Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
"$%c is no longer supported", *name);
break;
}
goto magicalize;
case '\023': /* $^S */
+ ro_magicalize:
+ SvREADONLY_on(GvSVn(gv));
+ /* FALL THROUGH */
case '1':
case '2':
case '3':
case '7':
case '8':
case '9':
- ro_magicalize:
- SvREADONLY_on(GvSVn(gv));
- /* FALL THROUGH */
case '[':
case '^':
case '~':
gp->gp_cv = NULL;
gp->gp_cvgen = 0;
}
- /* XXX if anyone finds a method cache regression with
- the "mro" stuff, turning this else block back on
- is probably the first place to look --blblack
- */
- /*
- else {
- PL_sub_generation++;
- }
- */
}
return gp;
}
pTHX__FORMAT pTHX__VALUE);
return;
}
- if (gp->gp_cv) {
- /* Deleting the name of a subroutine invalidates method cache */
- PL_sub_generation++;
- }
if (--gp->gp_refcnt > 0) {
if (gp->gp_egv == gv)
gp->gp_egv = 0;
if (gp->gp_hv && SvTYPE(gp->gp_hv) == SVt_PVHV) {
const char *hvname = HvNAME_get(gp->gp_hv);
if (PL_stashcache && hvname)
- hv_delete(PL_stashcache, hvname, HvNAMELEN_get(gp->gp_hv),
+ (void)hv_delete(PL_stashcache, hvname, HvNAMELEN_get(gp->gp_hv),
G_DISCARD);
SvREFCNT_dec(gp->gp_hv);
}
dVAR;
MAGIC* const mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
AMT amt;
+ const struct mro_meta* stash_meta = HvMROMETA(stash);
U32 newgen;
- newgen = PL_sub_generation + HvMROMETA(stash)->sub_generation;
+ newgen = PL_sub_generation + stash_meta->pkg_gen + stash_meta->cache_gen;
if (mg) {
const AMT * const amtp = (AMT*)mg->mg_ptr;
if (amtp->was_ok_am == PL_amagic_generation
MAGIC *mg;
AMT *amtp;
U32 newgen;
+ struct mro_meta* stash_meta;
if (!stash || !HvNAME_get(stash))
return NULL;
- newgen = PL_sub_generation + HvMROMETA(stash)->sub_generation;
+ stash_meta = HvMROMETA(stash);
+ newgen = PL_sub_generation + stash_meta->pkg_gen + stash_meta->cache_gen;
mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
if (!mg) {