This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add fixes for testing EBCDIC to blead
[perl5.git] / pad.c
diff --git a/pad.c b/pad.c
index a27c684..057a502 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -59,12 +59,13 @@ AV which is @_.  Other entries are storage for variables and op targets.
 
 Iterating over the PADNAMELIST iterates over all possible pad
 items.  Pad slots for targets (SVs_PADTMP)
-and GVs end up having &PL_sv_undef
-"names", while slots for constants have &PL_sv_no "names" (see
-pad_alloc()).  That &PL_sv_no is used is an implementation detail subject
-to change.  To test for it, use C<PadnamePV(name) && !PadnameLEN(name)>.
+and GVs end up having &PL_padname_undef "names", while slots for constants 
+have &PL_padname_const "names" (see pad_alloc()).  That &PL_padname_undef
+and &PL_padname_const are used is an implementation detail subject to
+change.  To test for them, use C<!PadnamePV(name)> and C<PadnamePV(name)
+&& !PadnameLEN(name)>, respectively.
 
-Only my/our variable (SvPADMY/PADNAME_isOUR) slots get valid names.
+Only my/our variable slots get valid names.
 The rest are op targets/GVs/constants which are statically allocated
 or resolved at compile time.  These don't have names by which they
 can be looked up from Perl code at run time through eval"" the way
@@ -72,10 +73,10 @@ my/our variables can be.  Since they can't be looked up by "name"
 but only by their index allocated at compile time (which is usually
 in PL_op->op_targ), wasting a name SV for them doesn't make sense.
 
-The SVs in the names AV have their PV being the name of the variable.
-xlow+1..xhigh inclusive in the NV union is a range of cop_seq numbers for
-which the name is valid (accessed through the macros COP_SEQ_RANGE_LOW and
-_HIGH).  During compilation, these fields may hold the special value
+The pad names in the PADNAMELIST have their PV holding the name of
+the variable.  The COP_SEQ_RANGE_LOW and _HIGH fields form a range
+(low+1..high inclusive) of cop_seq numbers for which the name is
+valid.  During compilation, these fields may hold the special value
 PERL_PADSEQ_INTRO to indicate various stages:
 
    COP_SEQ_RANGE_LOW        _HIGH
@@ -84,27 +85,24 @@ PERL_PADSEQ_INTRO to indicate various stages:
    valid-seq#   PERL_PADSEQ_INTRO   variable in scope:             { my ($x)
    valid-seq#          valid-seq#   compilation of scope complete: { my ($x) }
 
-For typed lexicals name SV is SVt_PVMG and SvSTASH
-points at the type.  For C<our> lexicals, the type is also SVt_PVMG, with the
-SvOURSTASH slot pointing at the stash of the associated global (so that
-duplicate C<our> declarations in the same package can be detected).  SvUVX is
-sometimes hijacked to store the generation number during compilation.
-
-If PADNAME_OUTER (SvFAKE) is set on the
-name SV, then that slot in the frame AV is
-a REFCNT'ed reference to a lexical from "outside".  In this case,
-the name SV does not use xlow and xhigh to store a cop_seq range, since it is
-in scope throughout.  Instead xhigh stores some flags containing info about
+For typed lexicals PadnameTYPE points at the type stash.  For C<our>
+lexicals, PadnameOURSTASH points at the stash of the associated global (so
+that duplicate C<our> declarations in the same package can be detected).
+PadnameGEN is sometimes used to store the generation number during
+compilation.
+
+If PadnameOUTER is set on the pad name, then that slot in the frame AV
+is a REFCNT'ed reference to a lexical from "outside".  Such entries
+are sometimes referred to as 'fake'.  In this case, the name does not
+use 'low' and 'high' to store a cop_seq range, since it is in scope
+throughout.  Instead 'high' stores some flags containing info about
 the real lexical (is it declared in an anon, and is it capable of being
-instantiated multiple times?), and for fake ANONs, xlow contains the index
+instantiated multiple times?), and for fake ANONs, 'low' contains the index
 within the parent's pad where the lexical's value is stored, to make
 cloning quicker.
 
 If the 'name' is '&' the corresponding entry in the PAD
 is a CV representing a possible closure.
-(PADNAME_OUTER and name of '&' is not a
-meaningful combination currently but could
-become so if C<my sub foo {}> is implemented.)
 
 Note that formats are treated as anon subs, and are cloned each time
 write is called (if necessary).
@@ -238,6 +236,7 @@ Perl_pad_new(pTHX_ int flags)
        PadnamelistREFCNT(padname = PL_comppad_name)++;
     }
     else {
+       padlist->xpadl_id = PL_padlist_generation++;
        av_store(pad, 0, NULL);
        padname = newPADNAMELIST(0);
        padnamelist_store(padname, 0, &PL_padname_undef);
@@ -418,7 +417,9 @@ Perl_cv_undef_flags(pTHX_ CV *cv, U32 flags)
                        }
 
                        /* in use, not just a prototype */
-                       if (inner_rc && (CvOUTSIDE(innercv) == cv)) {
+                       if (inner_rc && SvTYPE(innercv) == SVt_PVCV
+                        && (CvOUTSIDE(innercv) == cv))
+                       {
                            assert(CvWEAKOUTSIDE(innercv));
                            /* don't relink to grandfather if he's being freed */
                            if (outercv && SvREFCNT(outercv)) {
@@ -523,14 +524,14 @@ Perl_cv_forget_slab(pTHX_ CV *cv)
 }
 
 /*
-=for apidoc m|PADOFFSET|pad_alloc_name|SV *namesv|U32 flags|HV *typestash|HV *ourstash
+=for apidoc m|PADOFFSET|pad_alloc_name|PADNAME *name|U32 flags|HV *typestash|HV *ourstash
 
 Allocates a place in the currently-compiling
 pad (via L<perlapi/pad_alloc>) and
-then stores a name for that entry.  I<namesv> is adopted and becomes the
-name entry; it must already contain the name string and be sufficiently
-upgraded.  I<typestash> and I<ourstash> and the C<padadd_STATE> flag get
-added to I<namesv>.  None of the other
+then stores a name for that entry.  I<name> is adopted and
+becomes the name entry; it must already contain the name
+string.  I<typestash> and I<ourstash> and the C<padadd_STATE>
+flag get added to I<name>.  None of the other
 processing of L<perlapi/pad_add_name_pvn>
 is done.  Returns the offset of the allocated pad slot.
 
@@ -562,7 +563,8 @@ S_pad_alloc_name(pTHX_ PADNAME *name, U32 flags, HV *typestash,
     }
 
     padnamelist_store(PL_comppad_name, offset, name);
-    PadnamelistMAXNAMED(PL_comppad_name) = offset;
+    if (PadnameLEN(name) > 1)
+       PadnamelistMAXNAMED(PL_comppad_name) = offset;
     return offset;
 }
 
@@ -802,6 +804,7 @@ Perl_pad_add_anon(pTHX_ CV* func, I32 optype)
     PADNAME * const name = newPADNAMEpvn("&", 1);
 
     PERL_ARGS_ASSERT_PAD_ADD_ANON;
+    assert (SvTYPE(func) == SVt_PVCV);
 
     pad_peg("add_anon");
     /* These two aren't used; just make sure they're not equal to
@@ -811,18 +814,11 @@ Perl_pad_add_anon(pTHX_ CV* func, I32 optype)
     ix = pad_alloc(optype, SVs_PADMY);
     padnamelist_store(PL_comppad_name, ix, name);
     /* XXX DAPM use PL_curpad[] ? */
-    if (SvTYPE(func) == SVt_PVCV || !CvOUTSIDE(func))
-       av_store(PL_comppad, ix, (SV*)func);
-    else {
-       SV *rv = newRV_noinc((SV *)func);
-       sv_rvweaken(rv);
-       assert (SvTYPE(func) == SVt_PVFM);
-       av_store(PL_comppad, ix, rv);
-    }
+    av_store(PL_comppad, ix, (SV*)func);
 
     /* to avoid ref loops, we never have parent + child referencing each
      * other simultaneously */
-    if (CvOUTSIDE(func) && SvTYPE(func) == SVt_PVCV) {
+    if (CvOUTSIDE(func)) {
        assert(!CvWEAKOUTSIDE(func));
        CvWEAKOUTSIDE_on(func);
        SvREFCNT_dec_NN(CvOUTSIDE(func));
@@ -830,6 +826,24 @@ Perl_pad_add_anon(pTHX_ CV* func, I32 optype)
     return ix;
 }
 
+void
+Perl_pad_add_weakref(pTHX_ CV* func)
+{
+    const PADOFFSET ix = pad_alloc(OP_NULL, SVs_PADMY);
+    PADNAME * const name = newPADNAMEpvn("&", 1);
+    SV * const rv = newRV_inc((SV *)func);
+
+    PERL_ARGS_ASSERT_PAD_ADD_WEAKREF;
+
+    /* These two aren't used; just make sure they're not equal to
+     * PERL_PADSEQ_INTRO.  They should be 0 by default.  */
+    assert(COP_SEQ_RANGE_LOW (name) != PERL_PADSEQ_INTRO);
+    assert(COP_SEQ_RANGE_HIGH(name) != PERL_PADSEQ_INTRO);
+    padnamelist_store(PL_comppad_name, ix, name);
+    sv_rvweaken(rv);
+    av_store(PL_comppad, ix, rv);
+}
+
 /*
 =for apidoc pad_check_dup
 
@@ -1086,13 +1100,13 @@ to match against.  If warn is true, print appropriate warnings.  The out_*
 vars return values, and so are pointers to where the returned values
 should be stored.  out_capture, if non-null, requests that the innermost
 instance of the lexical is captured; out_name is set to the innermost
-matched namesv or fake namesv; out_flags returns the flags normally
-associated with the IVX field of a fake namesv.
+matched pad name or fake pad name; out_flags returns the flags normally
+associated with the PARENT_FAKELEX_FLAGS field of a fake pad name.
 
 Note that pad_findlex() is recursive; it recurses up the chain of CVs,
 then comes back down, adding fake entries
 as it goes.  It has to be this way
-because fake namesvs in anon protoypes have to store in xlow the index into
+because fake names in anon protoypes have to store in xlow the index into
 the parent pad.
 
 =cut
@@ -1306,10 +1320,6 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
        return 0; /* this dummy (and invalid) value isnt used by the caller */
 
     {
-       /* This relies on sv_setsv_flags() upgrading the destination to the same
-          type as the source, independent of the flags set, and on it being
-          "good" and only copying flag bits and pointers that it understands.
-       */
        PADNAME *new_name = newPADNAMEouter(*out_name);
        PADNAMELIST * const ocomppad_name = PL_comppad_name;
        PAD * const ocomppad = PL_comppad;
@@ -1930,10 +1940,11 @@ the immediately surrounding code.
 =cut
 */
 
-static CV *S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside);
+static CV *S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned);
 
 static CV *
-S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
+S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned,
+                    bool newcv)
 {
     I32 ix;
     PADLIST* const protopadlist = CvPADLIST(proto);
@@ -1945,7 +1956,8 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
     const I32 fpad = AvFILLp(protopad);
     SV** outpad;
     long depth;
-    bool subclones = FALSE;
+    U32 subclones = 0;
+    bool trouble = FALSE;
 
     assert(!CvUNIQUE(proto));
 
@@ -1966,8 +1978,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
        outside = CvOUTSIDE(proto);
        if ((CvCLONE(outside) && ! CvCLONED(outside))
            || !CvPADLIST(outside)
-           || PadlistNAMES(CvPADLIST(outside))
-                != protopadlist->xpadl_outid) {
+           || CvPADLIST(outside)->xpadl_id != protopadlist->xpadl_outid) {
            outside = find_runcv_where(
                FIND_RUNCV_padid_eq, PTR2IV(protopadlist->xpadl_outid), NULL
            );
@@ -1990,6 +2001,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
     SAVESPTR(PL_comppad_name);
     PL_comppad_name = protopad_name;
     CvPADLIST_set(cv, pad_new(padnew_CLONE|padnew_SAVE));
+    CvPADLIST(cv)->xpadl_id = protopadlist->xpadl_id;
 
     av_fill(PL_comppad, fpad);
 
@@ -1998,8 +2010,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
     outpad = outside && CvPADLIST(outside)
        ? AvARRAY(PadlistARRAY(CvPADLIST(outside))[depth])
        : NULL;
-    if (outpad)
-       CvPADLIST(cv)->xpadl_outid = PadlistNAMES(CvPADLIST(outside));
+    if (outpad) CvPADLIST(cv)->xpadl_outid = CvPADLIST(outside)->xpadl_id;
 
     for (ix = fpad; ix > 0; ix--) {
        PADNAME* const namesv = (ix <= fname) ? pname[ix] : NULL;
@@ -2033,7 +2044,9 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
                       second pass. */
                    if (SvPAD_STATE(namesv) && !CvCLONED(ppad[ix])) {
                        assert(SvTYPE(ppad[ix]) == SVt_PVCV);
-                       subclones = 1;
+                       subclones ++;
+                       if (CvOUTSIDE(ppad[ix]) != proto)
+                            trouble = TRUE;
                        sv = newSV_type(SVt_PVCV);
                        CvLEXICAL_on(sv);
                    }
@@ -2079,12 +2092,70 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
     }
 
     if (subclones)
-       for (ix = fpad; ix > 0; ix--) {
+    {
+       if (trouble || cloned) {
+           /* Uh-oh, we have trouble!  At least one of the state subs here
+              has its CvOUTSIDE pointer pointing somewhere unexpected.  It
+              could be pointing to another state protosub that we are
+              about to clone.  So we have to track which sub clones come
+              from which protosubs.  If the CvOUTSIDE pointer for a parti-
+              cular sub points to something we have not cloned yet, we
+              delay cloning it.  We must loop through the pad entries,
+              until we get a full pass with no cloning.  If any uncloned
+              subs remain (probably nested inside anonymous or ‘my’ subs),
+              then they get cloned in a final pass.
+            */
+           bool cloned_in_this_pass;
+           if (!cloned)
+               cloned = (HV *)sv_2mortal((SV *)newHV());
+           do {
+               cloned_in_this_pass = FALSE;
+               for (ix = fpad; ix > 0; ix--) {
+                   PADNAME * const name =
+                       (ix <= fname) ? pname[ix] : NULL;
+                   if (name && name != &PL_padname_undef
+                    && !PadnameOUTER(name) && PadnamePV(name)[0] == '&'
+                    && PadnameIsSTATE(name) && !CvCLONED(PL_curpad[ix]))
+                   {
+                       CV * const protokey = CvOUTSIDE(ppad[ix]);
+                       CV ** const cvp = protokey == proto
+                           ? &cv
+                           : (CV **)hv_fetch(cloned, (char *)&protokey,
+                                             sizeof(CV *), 0);
+                       if (cvp && *cvp) {
+                           S_cv_clone(aTHX_ (CV *)ppad[ix],
+                                            (CV *)PL_curpad[ix],
+                                            *cvp, cloned);
+                           (void)hv_store(cloned, (char *)&ppad[ix],
+                                    sizeof(CV *),
+                                    SvREFCNT_inc_simple_NN(PL_curpad[ix]),
+                                    0);
+                           subclones--;
+                           cloned_in_this_pass = TRUE;
+                       }
+                   }
+               }
+           } while (cloned_in_this_pass);
+           if (subclones)
+               for (ix = fpad; ix > 0; ix--) {
+                   PADNAME * const name =
+                       (ix <= fname) ? pname[ix] : NULL;
+                   if (name && name != &PL_padname_undef
+                    && !PadnameOUTER(name) && PadnamePV(name)[0] == '&'
+                    && PadnameIsSTATE(name) && !CvCLONED(PL_curpad[ix]))
+                       S_cv_clone(aTHX_ (CV *)ppad[ix],
+                                        (CV *)PL_curpad[ix],
+                                        CvOUTSIDE(ppad[ix]), cloned);
+               }
+       }
+       else for (ix = fpad; ix > 0; ix--) {
            PADNAME * const name = (ix <= fname) ? pname[ix] : NULL;
            if (name && name != &PL_padname_undef && !PadnameOUTER(name)
             && PadnamePV(name)[0] == '&' && PadnameIsSTATE(name))
-               S_cv_clone(aTHX_ (CV *)ppad[ix], (CV *)PL_curpad[ix], cv);
+               S_cv_clone(aTHX_ (CV *)ppad[ix], (CV *)PL_curpad[ix], cv,
+                                NULL);
        }
+    }
 
     if (newcv) SvREFCNT_inc_simple_void_NN(cv);
     LEAVE;
@@ -2131,10 +2202,10 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
                             nextstate
                             padsv
                     */
-                   if (OP_SIBLING(
+                   if (OpSIBLING(
                         cUNOPx(cUNOPx(CvROOT(cv))->op_first)->op_first
                        ) == o
-                    && !OP_SIBLING(o))
+                    && !OpSIBLING(o))
                    {
                        Perl_ck_warner_d(aTHX_
                                          packWARN(WARN_DEPRECATED),
@@ -2177,7 +2248,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
 }
 
 static CV *
-S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside)
+S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned)
 {
 #ifdef USE_ITHREADS
     dVAR;
@@ -2212,7 +2283,7 @@ S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside)
        mg_copy((SV *)proto, (SV *)cv, 0, 0);
 
     if (CvPADLIST(proto))
-       cv = S_cv_clone_pad(aTHX_ proto, cv, outside, newcv);
+       cv = S_cv_clone_pad(aTHX_ proto, cv, outside, cloned, newcv);
 
     DEBUG_Xv(
        PerlIO_printf(Perl_debug_log, "\nPad CV clone\n");
@@ -2230,7 +2301,7 @@ Perl_cv_clone(pTHX_ CV *proto)
     PERL_ARGS_ASSERT_CV_CLONE;
 
     if (!CvPADLIST(proto)) Perl_croak(aTHX_ "panic: no pad in cv_clone");
-    return S_cv_clone(aTHX_ proto, NULL, NULL);
+    return S_cv_clone(aTHX_ proto, NULL, NULL, NULL);
 }
 
 /* Called only by pp_clonecv */
@@ -2239,7 +2310,7 @@ Perl_cv_clone_into(pTHX_ CV *proto, CV *target)
 {
     PERL_ARGS_ASSERT_CV_CLONE_INTO;
     cv_undef(target);
-    return S_cv_clone(aTHX_ proto, target, NULL);
+    return S_cv_clone(aTHX_ proto, target, NULL, NULL);
 }
 
 /*
@@ -2314,18 +2385,30 @@ Perl_pad_fixup_inner_anons(pTHX_ PADLIST *padlist, CV *old_cv, CV *new_cv)
     PERL_UNUSED_ARG(old_cv);
 
     for (ix = PadnamelistMAX(comppad_name); ix > 0; ix--) {
-        const PADNAME * const name = namepad[ix];
-       if (name && name != &PL_padname_undef && !PadnameIsSTATE(name)
+        const PADNAME *name = namepad[ix];
+       if (name && name != &PL_padname_undef && !PadnameIsOUR(name)
            && *PadnamePV(name) == '&')
        {
-         if (SvTYPE(curpad[ix]) == SVt_PVCV) {
+         CV *innercv = MUTABLE_CV(curpad[ix]);
+         if (UNLIKELY(PadnameOUTER(name))) {
+           CV *cv = new_cv;
+           PADNAME **names = namepad;
+           PADOFFSET i = ix;
+           while (PadnameOUTER(name)) {
+               cv = CvOUTSIDE(cv);
+               names = PadlistNAMESARRAY(CvPADLIST(cv));
+               i = PARENT_PAD_INDEX(name);
+               name = names[i];
+           }
+           innercv = (CV *)PadARRAY(PadlistARRAY(CvPADLIST(cv))[1])[i];
+         }
+         if (SvTYPE(innercv) == SVt_PVCV) {
            /* XXX 0afba48f added code here to check for a proto CV
                   attached to the pad entry by magic.  But shortly there-
                   after 81df9f6f95 moved the magic to the pad name.  The
                   code here was never updated, so it wasn’t doing anything
                   and got deleted when PADNAME became a distinct type.  Is
                   there any bug as a result?  */
-           CV * const innercv = MUTABLE_CV(curpad[ix]);
            if (CvOUTSIDE(innercv) == old_cv) {
                if (!CvWEAKOUTSIDE(innercv)) {
                    SvREFCNT_dec(old_cv);
@@ -2433,7 +2516,7 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param)
 
     PERL_ARGS_ASSERT_PADLIST_DUP;
 
-    cloneall = param->flags & CLONEf_COPY_STACKS;
+    cloneall = cBOOL(param->flags & CLONEf_COPY_STACKS);
     assert (SvREFCNT(PadlistARRAY(srcpad)[1]) == 1);
 
     max = cloneall ? PadlistMAX(srcpad) : 1;
@@ -2567,7 +2650,7 @@ is allocated.
 */
 
 PADNAMELIST *
-Perl_newPADNAMELIST(pTHX_ size_t max)
+Perl_newPADNAMELIST(size_t max)
 {
     PADNAMELIST *pnl;
     Newx(pnl, 1, PADNAMELIST);
@@ -2622,7 +2705,7 @@ Fetches the pad name from the given index.
 */
 
 PADNAME *
-Perl_padnamelist_fetch(pTHX_ PADNAMELIST *pnl, SSize_t key)
+Perl_padnamelist_fetch(PADNAMELIST *pnl, SSize_t key)
 {
     PERL_ARGS_ASSERT_PADNAMELIST_FETCH;
     ASSUME(key >= 0);
@@ -2699,7 +2782,7 @@ L</newPADNAMEouter>.
 */
 
 PADNAME *
-Perl_newPADNAMEpvn(pTHX_ const char *s, STRLEN len)
+Perl_newPADNAMEpvn(const char *s, STRLEN len)
 {
     struct padname_with_str *alloc;
     char *alloc2; /* for Newxz */
@@ -2730,7 +2813,7 @@ PADNAMEt_OUTER flag already set.
 */
 
 PADNAME *
-Perl_newPADNAMEouter(pTHX_ PADNAME *outer)
+Perl_newPADNAMEouter(PADNAME *outer)
 {
     PADNAME *pn;
     PERL_ARGS_ASSERT_NEWPADNAMEOUTER;