This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Avoid reifying GVs in rv2cv
authorFather Chrysostomos <sprout@cpan.org>
Thu, 11 Sep 2014 03:29:19 +0000 (20:29 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 15 Sep 2014 13:19:33 +0000 (06:19 -0700)
\&foo no longer reifies GVs in the stash:

$ ./miniperl -e 'sub foo{} warn $::{foo}; \&foo; warn $::{foo}'
CODE(0x7fab6282ad98) at -e line 1.
CODE(0x7fab6282ad98) at -e line 1.

Sub calls still reify them though, because of the way ck_subr cur-
rently works.

Constant proxies are still upgraded to full GVs for now, just to mini-
mise the churn per patch.

This makes it possible for OP_GVs to point to things other than GVs,
and these things are stored in the pad under threads.  Hence, pad_tidy
could turn on PADTMP, and then IS_PADGV becomes true when it is
upgraded to a glob, so refgen will fail assertions.  There is actually
no need to turn on PADTMP in pad_tidy, since it will already be on for
op targets.  (We need to get rid of IS_PADGV one of these days.  It
doesn’t actually do anything.)

op.c
pad.c

diff --git a/op.c b/op.c
index f4c73e6..b08ddcd 100644 (file)
--- a/op.c
+++ b/op.c
@@ -9022,7 +9022,7 @@ Perl_ck_rvconst(pTHX_ OP *o)
         * or we get possible typo warnings.  OPpCONST_ENTERED says
         * whether the lexer already added THIS instance of this symbol.
         */
-       iscv = (o->op_type == OP_RV2CV) * 2;
+       iscv = o->op_type == OP_RV2CV ? GV_NOEXPAND|GV_ADDMULTI : 0;
        gv = gv_fetchsv(kidsv,
                o->op_type == OP_RV2CV
                        && o->op_private & OPpMAY_RETURN_CONSTANT
@@ -9038,6 +9038,13 @@ Perl_ck_rvconst(pTHX_ OP *o)
                                ? SVt_PVHV
                                : SVt_PVGV);
        if (gv) {
+           if (!isGV(gv)) {
+               assert(iscv);
+               assert(SvROK(gv));
+               if (!(o->op_private & OPpMAY_RETURN_CONSTANT)
+                 && SvTYPE(SvRV(gv)) != SVt_PVCV)
+                   gv_fetchsv(kidsv, GV_ADDMULTI, SVt_PVCV);
+           }
            kid->op_type = OP_GV;
            SvREFCNT_dec(kid->op_sv);
 #ifdef USE_ITHREADS
diff --git a/pad.c b/pad.c
index 285c204..eb42ab8 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -1794,9 +1794,7 @@ Perl_pad_tidy(pTHX_ padtidy_type type)
            if (!PL_curpad[ix] || SvIMMORTAL(PL_curpad[ix])
                 || IS_PADGV(PL_curpad[ix]) || IS_PADCONST(PL_curpad[ix]))
                continue;
-           if (!SvPADMY(PL_curpad[ix])) {
-               SvPADTMP_on(PL_curpad[ix]);
-           } else if (!SvFAKE(namep[ix])) {
+           if (SvPADMY(PL_curpad[ix]) && !SvFAKE(namep[ix])) {
                /* This is a work around for how the current implementation of
                   ?{ } blocks in regexps interacts with lexicals.