This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
gv.c: Added gv_fetchmeth_(sv|pv|pvn)_autoload.
[perl5.git] / gv.c
diff --git a/gv.c b/gv.c
index d009850..1da1a90 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -16,7 +16,7 @@
  * history of Middle-earth and Over-heaven and of the Sundering Seas,'
  * laughed Pippin.
  *
- *     [p.599 of _The Lord of the Rings_, III/xi: "The Palantír"]
+ *     [p.599 of _The Lord of the Rings_, III/xi: "The Palantír"]
  */
 
 /*
@@ -59,11 +59,7 @@ Perl_gv_add_by_type(pTHX_ GV *gv, svtype type)
             * if it walks like a dirhandle, then let's assume that
             * this is a dirhandle.
             */
-           what = PL_op->op_type ==  OP_READDIR ||
-               PL_op->op_type ==  OP_TELLDIR ||
-               PL_op->op_type ==  OP_SEEKDIR ||
-               PL_op->op_type ==  OP_REWINDDIR ||
-               PL_op->op_type ==  OP_CLOSEDIR ?
+           what = OP_IS_DIRHOP(PL_op->op_type) ?
                "dirhandle" : "filehandle";
            /* diag_listed_as: Bad symbol for filehandle */
        } else if (type == SVt_PVHV) {
@@ -252,8 +248,67 @@ Perl_cvstash_set(pTHX_ CV *cv, HV *st)
        Perl_sv_add_backref(aTHX_ MUTABLE_SV(st), MUTABLE_SV(cv));
 }
 
+/*
+=for apidoc gv_init_pvn
+
+Converts a scalar into a typeglob.  This is an incoercible typeglob;
+assigning a reference to it will assign to one of its slots, instead of
+overwriting it as happens with typeglobs created by SvSetSV.  Converting
+any scalar that is SvOK() may produce unpredictable results and is reserved
+for perl's internal use.
+
+C<gv> is the scalar to be converted.
+
+C<stash> is the parent stash/package, if any.
+
+C<name> and C<len> give the name.  C<flags> can be set to SVf_UTF8 for a
+UTF8 string, or the return value of SvUTF8(sv).  The name must be unqualified; that is, it must not include the package name.  If C<gv> is a
+stash element, it is the caller's responsibility to ensure that the name
+passed to this function matches the name of the element.  If it does not
+match, perl's internal bookkeeping will get out of sync.
+
+C<multi>, when set to a true value, means to pretend that the GV has been
+seen before (i.e., suppress "Used once" warnings).
+
+=for apidoc gv_init
+
+The old form of gv_init_pvn().  It does not work with UTF8 strings, as it
+has no flags parameter.
+
+=for apidoc gv_init_pv
+
+Same as gv_init_pvn(), but takes a nul-terminated string for the name
+instead of separate char * and length parameters.
+
+=for apidoc gv_init_sv
+
+Same as gv_init_pvn(), but takes an SV * for the name instead of separate
+char * and length parameters.  C<flags> is currently unused.
+
+=cut
+*/
+
+void
+Perl_gv_init_sv(pTHX_ GV *gv, HV *stash, SV* namesv, int multi, U32 flags)
+{
+   char *namepv;
+   STRLEN namelen;
+   PERL_ARGS_ASSERT_GV_INIT_SV;
+   namepv = SvPV(namesv, namelen);
+   if (SvUTF8(namesv))
+       flags |= SVf_UTF8;
+   gv_init_pvn(gv, stash, namepv, namelen, multi, flags);
+}
+
 void
-Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
+Perl_gv_init_pv(pTHX_ GV *gv, HV *stash, const char *name, int multi, U32 flags)
+{
+   PERL_ARGS_ASSERT_GV_INIT_PV;
+   gv_init_pvn(gv, stash, name, strlen(name), multi, flags);
+}
+
+void
+Perl_gv_init_pvn(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi, U32 flags)
 {
     dVAR;
     const U32 old_type = SvTYPE(gv);
@@ -263,7 +318,7 @@ Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
     SV *const has_constant = doproto && SvROK(gv) ? SvRV(gv) : NULL;
     const U32 exported_constant = has_constant ? SvPCS_IMPORTED(gv) : 0;
 
-    PERL_ARGS_ASSERT_GV_INIT;
+    PERL_ARGS_ASSERT_GV_INIT_PVN;
     assert (!(proto && has_constant));
 
     if (has_constant) {
@@ -348,9 +403,9 @@ Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
 }
 
 STATIC void
-S_gv_init_sv(pTHX_ GV *gv, const svtype sv_type)
+S_gv_init_svtype(pTHX_ GV *gv, const svtype sv_type)
 {
-    PERL_ARGS_ASSERT_GV_INIT_SV;
+    PERL_ARGS_ASSERT_GV_INIT_SVTYPE;
 
     switch (sv_type) {
     case SVt_PVIO:
@@ -378,9 +433,171 @@ S_gv_init_sv(pTHX_ GV *gv, const svtype sv_type)
     }
 }
 
+static void core_xsub(pTHX_ CV* cv);
+
+static GV *
+S_maybe_add_coresub(pTHX_ HV * const stash, GV *gv,
+                          const char * const name, const STRLEN len,
+                          const char * const fullname, STRLEN const fullen)
+{
+    const int code = keyword(name, len, 1);
+    static const char file[] = __FILE__;
+    CV *cv, *oldcompcv;
+    int opnum = 0;
+    SV *opnumsv;
+    bool ampable = TRUE; /* &{}-able */
+    COP *oldcurcop;
+    yy_parser *oldparser;
+    I32 oldsavestack_ix;
+
+    assert(gv || stash);
+    assert(name);
+    assert(stash || fullname);
+
+    if (!fullname && !HvENAME(stash)) return NULL; /* pathological case
+                                                     that would require
+                                                    inlining newATTRSUB */
+    if (code >= 0) return NULL; /* not overridable */
+    switch (-code) {
+     /* no support for \&CORE::infix;
+        no support for funcs that take labels, as their parsing is
+        weird  */
+    case KEY_and: case KEY_cmp: case KEY_CORE: case KEY_dump:
+    case KEY_eq: case KEY_ge:
+    case KEY_gt: case KEY_le: case KEY_lt: case KEY_ne:
+    case KEY_or: case KEY_x: case KEY_xor:
+       return NULL;
+    case KEY_chdir:
+    case KEY_chomp: case KEY_chop:
+    case KEY_each: case KEY_eof: case KEY_exec:
+    case KEY_keys:
+    case KEY_lstat:
+    case KEY_pop:
+    case KEY_push:
+    case KEY_shift:
+    case KEY_splice:
+    case KEY_stat:
+    case KEY_system:
+    case KEY_truncate: case KEY_unlink:
+    case KEY_unshift:
+    case KEY_values:
+       ampable = FALSE;
+    }
+    if (!gv) {
+       gv = (GV *)newSV(0);
+       gv_init(gv, stash, name, len, TRUE);
+    }
+    if (ampable) {
+       ENTER;
+       oldcurcop = PL_curcop;
+       oldparser = PL_parser;
+       lex_start(NULL, NULL, 0);
+       oldcompcv = PL_compcv;
+       PL_compcv = NULL; /* Prevent start_subparse from setting
+                            CvOUTSIDE. */
+       oldsavestack_ix = start_subparse(FALSE,0);
+       cv = PL_compcv;
+    }
+    else {
+       /* Avoid calling newXS, as it calls us, and things start to
+          get hairy. */
+       cv = MUTABLE_CV(newSV_type(SVt_PVCV));
+       GvCV_set(gv,cv);
+       GvCVGEN(gv) = 0;
+       mro_method_changed_in(GvSTASH(gv));
+       CvISXSUB_on(cv);
+       CvXSUB(cv) = core_xsub;
+    }
+    CvGV_set(cv, gv); /* This stops new ATTRSUB from setting CvFILE
+                         from PL_curcop. */
+    (void)gv_fetchfile(file);
+    CvFILE(cv) = (char *)file;
+    /* XXX This is inefficient, as doing things this order causes
+           a prototype check in newATTRSUB.  But we have to do
+           it this order as we need an op number before calling
+           new ATTRSUB. */
+    (void)core_prototype((SV *)cv, name, code, &opnum);
+    if (stash && (fullname || !fullen))
+       (void)hv_store(stash,name,len,(SV *)gv,0);
+    if (ampable) {
+       SV *tmpstr;
+       CvLVALUE_on(cv);
+       if (!fullname) {
+           tmpstr = newSVhek(HvENAME_HEK(stash));
+           sv_catpvs(tmpstr, "::");
+           sv_catpvn(tmpstr,name,len);
+       }
+       else tmpstr = newSVpvn_share(fullname,fullen,0);
+       newATTRSUB(oldsavestack_ix,
+                  newSVOP(OP_CONST, 0, tmpstr),
+                  NULL,NULL,
+                  coresub_op(
+                    opnum
+                      ? newSVuv((UV)opnum)
+                      : newSVpvn(name,len),
+                    code, opnum
+                  )
+       );
+       assert(GvCV(gv) == cv);
+       if (opnum != OP_VEC && opnum != OP_SUBSTR)
+           CvLVALUE_off(cv); /* Now *that* was a neat trick. */
+       LEAVE;
+       PL_parser = oldparser;
+       PL_curcop = oldcurcop;
+       PL_compcv = oldcompcv;
+    }
+    opnumsv = opnum ? newSVuv((UV)opnum) : (SV *)NULL;
+    cv_set_call_checker(
+       cv, Perl_ck_entersub_args_core, opnumsv ? opnumsv : (SV *)cv
+    );
+    SvREFCNT_dec(opnumsv);
+    return gv;
+}
+
 /*
 =for apidoc gv_fetchmeth
 
+Like L</gv_fetchmeth_pvn>, but lacks a flags parameter.
+
+=for apidoc gv_fetchmeth_sv
+
+Exactly like L</gv_fetchmeth_pvn>, but takes the name string in the form
+of an SV instead of a string/length pair.
+
+=cut
+*/
+
+GV *
+Perl_gv_fetchmeth_sv(pTHX_ HV *stash, SV *namesv, I32 level, U32 flags)
+{
+   char *namepv;
+   STRLEN namelen;
+   PERL_ARGS_ASSERT_GV_FETCHMETH_SV;
+   namepv = SvPV(namesv, namelen);
+   if (SvUTF8(namesv))
+       flags |= SVf_UTF8;
+   return gv_fetchmeth_pvn(stash, namepv, namelen, level, flags);
+}
+
+/*
+=for apidoc gv_fetchmeth_pv
+
+Exactly like L</gv_fetchmeth_pvn>, but takes a nul-terminated string 
+instead of a string/length pair.
+
+=cut
+*/
+
+GV *
+Perl_gv_fetchmeth_pv(pTHX_ HV *stash, const char *name, I32 level, U32 flags)
+{
+    PERL_ARGS_ASSERT_GV_FETCHMETH_PV;
+    return gv_fetchmeth_pvn(stash, name, strlen(name), level, flags);
+}
+
+/*
+=for apidoc gv_fetchmeth_pvn
+
 Returns the glob with the given C<name> and a defined subroutine or
 C<NULL>.  The glob lives in the given C<stash>, or in the stashes
 accessible via @ISA and UNIVERSAL::.
@@ -390,6 +607,8 @@ side-effect creates a glob with the given C<name> in the given C<stash>
 which in the case of success contains an alias for the subroutine, and sets
 up caching info for this glob.
 
+Currently, the only significant value for C<flags> is SVf_UTF8.
+
 This function grants C<"SUPER"> token as a postfix of the stash name. The
 GV returned from C<gv_fetchmeth> may be a method cache entry, which is not
 visible to Perl code.  So when calling C<call_sv>, you should not use
@@ -402,7 +621,7 @@ obtained from the GV with the C<GvCV> macro.
 /* NOTE: No support for tied ISA */
 
 GV *
-Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
+Perl_gv_fetchmeth_pvn(pTHX_ HV *stash, const char *name, STRLEN len, I32 level, U32 flags)
 {
     dVAR;
     GV** gvp;
@@ -419,7 +638,7 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
     STRLEN packlen;
     U32 topgen_cmp;
 
-    PERL_ARGS_ASSERT_GV_FETCHMETH;
+    PERL_ARGS_ASSERT_GV_FETCHMETH_PVN;
 
     /* UNIVERSAL methods should be callable without a stash */
     if (!stash) {
@@ -445,6 +664,7 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
     gvp = (GV**)hv_fetch(stash, name, len, create);
     if(gvp) {
         topgv = *gvp;
+      have_gv:
         assert(topgv);
         if (SvTYPE(topgv) != SVt_PVGV)
             gv_init(topgv, stash, name, len, TRUE);
@@ -465,6 +685,10 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
             /* cache indicates no such method definitively */
             return 0;
         }
+       else if (len > 1 /* shortest is uc */ && HvNAMELEN_get(stash) == 4
+              && strnEQ(hvname, "CORE", 4)
+              && S_maybe_add_coresub(aTHX_ stash,topgv,name,len,0,1))
+           goto have_gv;
     }
 
     packlen = HvNAMELEN_get(stash);
@@ -494,8 +718,19 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
         assert(cstash);
 
         gvp = (GV**)hv_fetch(cstash, name, len, 0);
-        if (!gvp) continue;
-        candidate = *gvp;
+        if (!gvp) {
+            if (len > 1 && HvNAMELEN_get(cstash) == 4) {
+                const char *hvname = HvNAME(cstash); assert(hvname);
+                if (strnEQ(hvname, "CORE", 4)
+                 && (candidate =
+                      S_maybe_add_coresub(aTHX_ cstash,NULL,name,len,0,0)
+                    ))
+                    goto have_candidate;
+            }
+            continue;
+        }
+        else candidate = *gvp;
+       have_candidate:
         assert(candidate);
         if (SvTYPE(candidate) != SVt_PVGV) gv_init(candidate, cstash, name, len, TRUE);
         if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
@@ -517,7 +752,7 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
 
     /* Check UNIVERSAL without caching */
     if(level == 0 || level == -1) {
-        candidate = gv_fetchmeth(NULL, name, len, 1);
+        candidate = gv_fetchmeth_pvn(NULL, name, len, 1, flags);
         if(candidate) {
             cand_cv = GvCV(candidate);
             if (topgv && (GvREFCNT(topgv) == 1) && (CvROOT(cand_cv) || CvXSUB(cand_cv))) {
@@ -540,24 +775,63 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
 }
 
 /*
-=for apidoc gv_fetchmeth_autoload
+=for apidoc gv_fetchmeth_sv_autoload
+
+Exactly like L</gv_fetchmeth_pvn_autoload>, but takes the name string in the form
+of an SV instead of a string/length pair.
+
+=cut
+*/
+
+GV *
+Perl_gv_fetchmeth_sv_autoload(pTHX_ HV *stash, SV *namesv, I32 level, U32 flags)
+{
+   char *namepv;
+   STRLEN namelen;
+   PERL_ARGS_ASSERT_GV_FETCHMETH_SV_AUTOLOAD;
+   namepv = SvPV(namesv, namelen);
+   if (SvUTF8(namesv))
+       flags |= SVf_UTF8;
+   return gv_fetchmeth_pvn_autoload(stash, namepv, namelen, level, flags);
+}
+
+/*
+=for apidoc gv_fetchmeth_pv_autoload
+
+Exactly like L</gv_fetchmeth_pvn_autoload>, but takes a nul-terminated string
+instead of a string/length pair.
+
+=cut
+*/
+
+GV *
+Perl_gv_fetchmeth_pv_autoload(pTHX_ HV *stash, const char *name, I32 level, U32 flags)
+{
+    PERL_ARGS_ASSERT_GV_FETCHMETH_PV_AUTOLOAD;
+    return gv_fetchmeth_pvn_autoload(stash, name, strlen(name), level, flags);
+}
+
+/*
+=for apidoc gv_fetchmeth_pvn_autoload
 
-Same as gv_fetchmeth(), but looks for autoloaded subroutines too.
+Same as gv_fetchmeth_pvn(), but looks for autoloaded subroutines too.
 Returns a glob for the subroutine.
 
 For an autoloaded subroutine without a GV, will create a GV even
 if C<level < 0>.  For an autoloaded subroutine without a stub, GvCV()
 of the result may be zero.
 
+Currently, the only significant value for C<flags> is SVf_UTF8.
+
 =cut
 */
 
 GV *
-Perl_gv_fetchmeth_autoload(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
+Perl_gv_fetchmeth_pvn_autoload(pTHX_ HV *stash, const char *name, STRLEN len, I32 level, U32 flags)
 {
-    GV *gv = gv_fetchmeth(stash, name, len, level);
+    GV *gv = gv_fetchmeth_pvn(stash, name, len, level, 0);
 
-    PERL_ARGS_ASSERT_GV_FETCHMETH_AUTOLOAD;
+    PERL_ARGS_ASSERT_GV_FETCHMETH_PVN_AUTOLOAD;
 
     if (!gv) {
        CV *cv;
@@ -567,14 +841,14 @@ Perl_gv_fetchmeth_autoload(pTHX_ HV *stash, const char *name, STRLEN len, I32 le
            return NULL;        /* UNIVERSAL::AUTOLOAD could cause trouble */
        if (len == S_autolen && memEQ(name, S_autoload, S_autolen))
            return NULL;
-       if (!(gv = gv_fetchmeth(stash, S_autoload, S_autolen, FALSE)))
+       if (!(gv = gv_fetchmeth_pvn(stash, S_autoload, S_autolen, FALSE, flags)))
            return NULL;
        cv = GvCV(gv);
        if (!(CvROOT(cv) || CvXSUB(cv)))
            return NULL;
        /* Have an autoload */
        if (level < 0)  /* Cannot do without a stub */
-           gv_fetchmeth(stash, name, len, 0);
+           gv_fetchmeth_pvn(stash, name, len, 0, flags);
        gvp = (GV**)hv_fetch(stash, name, len, (level >= 0));
        if (!gvp)
            return NULL;
@@ -711,7 +985,7 @@ Perl_gv_fetchmethod_flags(pTHX_ HV *stash, const char *name, U32 flags)
        ostash = stash;
     }
 
-    gv = gv_fetchmeth(stash, name, nend - name, 0);
+    gv = gv_fetchmeth_pvn(stash, name, nend - name, 0, 0);
     if (!gv) {
        if (strEQ(name,"import") || strEQ(name,"unimport"))
            gv = MUTABLE_GV(&PL_sv_yes);
@@ -731,7 +1005,7 @@ Perl_gv_fetchmethod_flags(pTHX_ HV *stash, const char *name, U32 flags)
                                       HV_FETCH_ISEXISTS, NULL, 0)
                ) {
                    require_pv("IO/File.pm");
-                   gv = gv_fetchmeth(stash, name, nend - name, 0);
+                   gv = gv_fetchmeth_pvn(stash, name, nend - name, 0, 0);
                    if (gv)
                        return gv;
                }
@@ -806,7 +1080,7 @@ Perl_gv_autoload4(pTHX_ HV *stash, const char *name, STRLEN len, I32 method)
            packname_len = HvNAMELEN_get(stash);
        }
     }
-    if (!(gv = gv_fetchmeth(stash, S_autoload, S_autolen, FALSE)))
+    if (!(gv = gv_fetchmeth_pvn(stash, S_autoload, S_autolen, FALSE, 0)))
        return NULL;
     cv = GvCV(gv);
 
@@ -1004,7 +1278,8 @@ Perl_gv_fetchpv(pTHX_ const char *nambeg, I32 add, const svtype sv_type) {
 GV *
 Perl_gv_fetchsv(pTHX_ SV *name, I32 flags, const svtype sv_type) {
     STRLEN len;
-    const char * const nambeg = SvPV_const(name, len);
+    const char * const nambeg =
+       SvPV_flags_const(name, len, flags & GV_NO_SVGMAGIC ? 0 : SV_GMAGIC);
     PERL_ARGS_ASSERT_GV_FETCHSV;
     return gv_fetchpvn_flags(nambeg, len, flags | SvUTF8(name), sv_type);
 }
@@ -1034,8 +1309,6 @@ S_gv_magicalize_overload(pTHX_ GV *gv)
     hv_magic(hv, NULL, PERL_MAGIC_overload);
 }
 
-static void core_xsub(pTHX_ CV* cv);
-
 GV *
 Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
                       const svtype sv_type)
@@ -1050,6 +1323,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
     const I32 no_init = flags & (GV_NOADD_NOINIT | GV_NOINIT);
     const I32 no_expand = flags & GV_NOEXPAND;
     const I32 add = flags & ~GV_NOADD_MASK;
+    bool addmg = !!(flags & GV_ADDMG);
     const char *const name_end = nambeg + full_len;
     const char *const name_em1 = name_end - 1;
     U32 faking_it;
@@ -1253,13 +1527,18 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
        return NULL;
 
     gvp = (GV**)hv_fetch(stash,name,len,add);
-    if (!gvp || *gvp == (const GV *)&PL_sv_undef)
-       return NULL;
-    gv = *gvp;
+    if (!gvp || *gvp == (const GV *)&PL_sv_undef) {
+       if (addmg) gv = (GV *)newSV(0);
+       else return NULL;
+    }
+    else gv = *gvp, addmg = 0;
+    /* From this point on, addmg means gv has not been inserted in the
+       symtab yet. */
+
     if (SvTYPE(gv) == SVt_PVGV) {
        if (add) {
            GvMULTI_on(gv);
-           gv_init_sv(gv, sv_type);
+           gv_init_svtype(gv, sv_type);
            if (len == 1 && stash == PL_defstash
                && (sv_type == SVt_PVHV || sv_type == SVt_PVGV)) {
                if (*name == '!')
@@ -1274,8 +1553,10 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
        }
        return gv;
     } else if (no_init) {
+       assert(!addmg);
        return gv;
     } else if (no_expand && SvROK(gv)) {
+       assert(!addmg);
        return gv;
     }
 
@@ -1291,7 +1572,6 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
     if (add & GV_ADDWARN)
        Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL), "Had to create %s unexpectedly", nambeg);
     gv_init(gv, stash, name, len, add & GV_ADDMULTI);
-    gv_init_sv(gv, faking_it ? SVt_PVCV : sv_type);
 
     if (isALPHA(name[0]) && ! (isLEXWARN_on ? ckWARN(WARN_ONCE)
                                            : (PL_dowarn & G_WARN_ON ) ) )
@@ -1324,50 +1604,17 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
            default:
                goto try_core;
            }
-           return gv;
+           goto add_magical_gv;
        }
       try_core:
        if (len > 1 /* shortest is uc */ && HvNAMELEN_get(stash) == 4) {
          /* Avoid null warning: */
          const char * const stashname = HvNAME(stash); assert(stashname);
-         if (strnEQ(stashname, "CORE", 4)) {
-           const int code = keyword(name, len, 1);
-           static const char file[] = __FILE__;
-           CV *cv;
-           int opnum = 0;
-           SV *opnumsv;
-           if (code >= 0) return gv; /* not overridable */
-            /* no support for \&CORE::infix;
-               no support for &CORE::not or &CORE::getprotobynumber
-               either, yet, as we cannot get the precedence right;
-               no support for funcs that take labels, as their parsing is
-               weird  */
-           switch (-code) {
-           case KEY_and: case KEY_cmp: case KEY_CORE: case KEY_dump:
-           case KEY_eq: case KEY_ge:
-           case KEY_getprotobynumber: case KEY_gt: case KEY_le:
-           case KEY_lt: case KEY_ne: case KEY_not:
-           case KEY_or: case KEY_x: case KEY_xor:
-               return gv;
-           }
-           /* Avoid calling newXS, as it calls us, and things start to
-              get hairy. */
-           cv = MUTABLE_CV(newSV_type(SVt_PVCV));
-           GvCV_set(gv,cv);
-           GvCVGEN(gv) = 0;
-           mro_method_changed_in(GvSTASH(gv));
-           CvGV_set(cv, gv);
-           (void)gv_fetchfile(file);
-           CvFILE(cv) = (char *)file;
-           CvISXSUB_on(cv);
-           CvXSUB(cv) = core_xsub;
-           (void)core_prototype((SV *)cv, name, code, &opnum, 0);
-           opnumsv = opnum ? newSVuv((UV)opnum) : (SV *)NULL;
-           cv_set_call_checker(
-              cv, Perl_ck_entersub_args_core, opnumsv ? opnumsv : (SV *)cv
-           );
-           SvREFCNT_dec(opnumsv);
-         }
+         if (strnEQ(stashname, "CORE", 4)
+          && S_maybe_add_coresub(aTHX_
+               addmg ? stash : 0, gv, name, len, nambeg, full_len
+             ))
+           addmg = 0;
        }
     }
     else if (len > 1) {
@@ -1494,7 +1741,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
                /* This snippet is taken from is_gv_magical */
                const char *end = name + len;
                while (--end > name) {
-                   if (!isDIGIT(*end)) return gv;
+                   if (!isDIGIT(*end)) goto add_magical_gv;
                }
                goto magicalize;
            }
@@ -1623,7 +1870,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
            break;
        case ']':               /* $] */
        {
-           SV * const sv = GvSVn(gv);
+           SV * const sv = GvSV(gv);
            if (!sv_derived_from(PL_patchlevel, "version"))
                upg_version(PL_patchlevel, TRUE);
            GvSV(gv) = vnumify(PL_patchlevel);
@@ -1633,7 +1880,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
        break;
        case '\026':    /* $^V */
        {
-           SV * const sv = GvSVn(gv);
+           SV * const sv = GvSV(gv);
            GvSV(gv) = new_version(PL_patchlevel);
            SvREADONLY_on(GvSV(gv));
            SvREFCNT_dec(sv);
@@ -1641,6 +1888,15 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
        break;
        }
     }
+  add_magical_gv:
+    if (addmg) {
+       if (GvAV(gv) || GvHV(gv) || GvIO(gv) || GvCV(gv) || (
+            GvSV(gv) && (SvOK(GvSV(gv)) || SvMAGICAL(GvSV(gv)))
+          ))
+           (void)hv_store(stash,name,len,(SV *)gv,0);
+       else SvREFCNT_dec(gv), gv = NULL;
+    }
+    if (gv) gv_init_svtype(gv, faking_it ? SVt_PVCV : sv_type);
     return gv;
 }
 
@@ -1902,7 +2158,7 @@ Perl_Gv_AMupdate(pTHX_ HV *stash, bool destructing)
     /* Work with "fallback" key, which we assume to be first in PL_AMG_names */
 
     /* Try to find via inheritance. */
-    GV *gv = gv_fetchmeth(stash, PL_AMG_names[0], 2, -1);
+    GV *gv = gv_fetchmeth_pvn(stash, PL_AMG_names[0], 2, -1, 0);
     SV * const sv = gv ? GvSV(gv) : NULL;
     CV* cv;
 
@@ -1936,14 +2192,15 @@ Perl_Gv_AMupdate(pTHX_ HV *stash, bool destructing)
           But if B overloads "bool", we may want to use it for
           numifying instead of C's "+0". */
        if (i >= DESTROY_amg)
-           gv = Perl_gv_fetchmeth_autoload(aTHX_ stash, cooky, l, 0);
+           gv = Perl_gv_fetchmeth_pvn_autoload(aTHX_ stash, cooky, l, 0, 0);
        else                            /* Autoload taken care of below */
-           gv = Perl_gv_fetchmeth(aTHX_ stash, cooky, l, -1);
+           gv = Perl_gv_fetchmeth_pvn(aTHX_ stash, cooky, l, -1, 0);
         cv = 0;
         if (gv && (cv = GvCV(gv))) {
-           const char *hvname;
-           if (GvNAMELEN(CvGV(cv)) == 3 && strEQ(GvNAME(CvGV(cv)), "nil")
-               && strEQ(hvname = HvNAME_get(GvSTASH(CvGV(cv))), "overload")) {
+           if(GvNAMELEN(CvGV(cv)) == 3 && strEQ(GvNAME(CvGV(cv)), "nil")){
+             const char * const hvname = HvNAME_get(GvSTASH(CvGV(cv)));
+             if (hvname && HEK_LEN(HvNAME_HEK(GvSTASH(CvGV(cv)))) == 8
+              && strEQ(hvname, "overload")) {
                /* This is a hack to support autoloading..., while
                   knowing *which* methods were declared as overloaded. */
                /* GvSV contains the name of the method. */
@@ -1952,7 +2209,7 @@ Perl_Gv_AMupdate(pTHX_ HV *stash, bool destructing)
 
                DEBUG_o( Perl_deb(aTHX_ "Resolving method \"%"SVf256\
                        "\" for overloaded \"%s\" in package \"%.256s\"\n",
-                            (void*)GvSV(gv), cp, hvname) );
+                            (void*)GvSV(gv), cp, HvNAME(stash)) );
                if (!gvsv || !SvPOK(gvsv)
                    || !(ngv = gv_fetchmethod_autoload(stash, SvPVX_const(gvsv),
                                                       FALSE)))
@@ -1967,10 +2224,11 @@ Perl_Gv_AMupdate(pTHX_ HV *stash, bool destructing)
                                    "in package \"%.256s\"",
                                   (GvCVGEN(gv) ? "Stub found while resolving"
                                    : "Can't resolve"),
-                                  name, cp, hvname);
+                                  name, cp, HvNAME(stash));
                    }
                }
                cv = GvCV(gv = ngv);
+             }
            }
            DEBUG_o( Perl_deb(aTHX_ "Overloading \"%s\" in package \"%.256s\" via \"%.256s::%.256s\"\n",
                         cp, HvNAME_get(stash), HvNAME_get(GvSTASH(CvGV(cv))),
@@ -2593,148 +2851,6 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
   }
 }
 
-/*
-=for apidoc is_gv_magical_sv
-
-Returns C<TRUE> if given the name of a magical GV.
-
-Currently only useful internally when determining if a GV should be
-created even in rvalue contexts.
-
-C<flags> is not used at present but available for future extension to
-allow selecting particular classes of magical variable.
-
-Currently assumes that C<name> is NUL terminated (as well as len being valid).
-This assumption is met by all callers within the perl core, which all pass
-pointers returned by SvPV.
-
-=cut
-*/
-
-bool
-Perl_is_gv_magical_sv(pTHX_ SV *const name_sv, U32 flags)
-{
-    STRLEN len;
-    const char *const name = SvPV_const(name_sv, len);
-
-    PERL_UNUSED_ARG(flags);
-    PERL_ARGS_ASSERT_IS_GV_MAGICAL_SV;
-
-    if (len > 1) {
-       const char * const name1 = name + 1;
-       switch (*name) {
-       case 'I':
-           if (len == 3 && name[1] == 'S' && name[2] == 'A')
-               goto yes;
-           break;
-       case 'O':
-           if (len == 8 && strEQ(name1, "VERLOAD"))
-               goto yes;
-           break;
-       case 'S':
-           if (len == 3 && name[1] == 'I' && name[2] == 'G')
-               goto yes;
-           break;
-           /* Using ${^...} variables is likely to be sufficiently rare that
-              it seems sensible to avoid the space hit of also checking the
-              length.  */
-       case '\017':   /* ${^OPEN} */
-           if (strEQ(name1, "PEN"))
-               goto yes;
-           break;
-       case '\024':   /* ${^TAINT} */
-           if (strEQ(name1, "AINT"))
-               goto yes;
-           break;
-       case '\025':    /* ${^UNICODE} */
-           if (strEQ(name1, "NICODE"))
-               goto yes;
-           if (strEQ(name1, "TF8LOCALE"))
-               goto yes;
-           break;
-       case '\027':   /* ${^WARNING_BITS} */
-           if (strEQ(name1, "ARNING_BITS"))
-               goto yes;
-           break;
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       {
-           const char *end = name + len;
-           while (--end > name) {
-               if (!isDIGIT(*end))
-                   return FALSE;
-           }
-           goto yes;
-       }
-       }
-    } else {
-       /* Because we're already assuming that name is NUL terminated
-          below, we can treat an empty name as "\0"  */
-       switch (*name) {
-       case '&':
-       case '`':
-       case '\'':
-       case ':':
-       case '?':
-       case '!':
-       case '-':
-       case '#':
-       case '[':
-       case '^':
-       case '~':
-       case '=':
-       case '%':
-       case '.':
-       case '(':
-       case ')':
-       case '<':
-       case '>':
-       case '\\':
-       case '/':
-       case '|':
-       case '+':
-       case ';':
-       case ']':
-       case '\001':   /* $^A */
-       case '\003':   /* $^C */
-       case '\004':   /* $^D */
-       case '\005':   /* $^E */
-       case '\006':   /* $^F */
-       case '\010':   /* $^H */
-       case '\011':   /* $^I, NOT \t in EBCDIC */
-       case '\014':   /* $^L */
-       case '\016':   /* $^N */
-       case '\017':   /* $^O */
-       case '\020':   /* $^P */
-       case '\023':   /* $^S */
-       case '\024':   /* $^T */
-       case '\026':   /* $^V */
-       case '\027':   /* $^W */
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       yes:
-           return TRUE;
-       default:
-           break;
-       }
-    }
-    return FALSE;
-}
-
 void
 Perl_gv_name_set(pTHX_ GV *gv, const char *name, U32 len, U32 flags)
 {