This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perlapi: Use C<> instead of I<> for parameter names, etc
[perl5.git] / pad.c
diff --git a/pad.c b/pad.c
index 4e675fa..d8cb545 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -79,11 +79,14 @@ the variable.  The COP_SEQ_RANGE_LOW and _HIGH fields form a range
 valid.  During compilation, these fields may hold the special value
 PERL_PADSEQ_INTRO to indicate various stages:
 
-   COP_SEQ_RANGE_LOW        _HIGH
-   -----------------        -----
-   PERL_PADSEQ_INTRO            0   variable not yet introduced:   { my ($x
-   valid-seq#   PERL_PADSEQ_INTRO   variable in scope:             { my ($x)
-   valid-seq#          valid-seq#   compilation of scope complete: { my ($x) }
+ COP_SEQ_RANGE_LOW        _HIGH
+ -----------------        -----
+ PERL_PADSEQ_INTRO            0   variable not yet introduced:
+                                  { my ($x
+ valid-seq#   PERL_PADSEQ_INTRO   variable in scope:
+                                  { my ($x)
+ valid-seq#          valid-seq#   compilation of scope complete:
+                                  { my ($x) }
 
 For typed lexicals PadnameTYPE points at the type stash.  For C<our>
 lexicals, PadnameOURSTASH points at the stash of the associated global (so
@@ -159,7 +162,7 @@ Perl_set_padlist(CV * cv, PADLIST *padlist){
 #  if PTRSIZE == 8
     assert((Size_t)padlist != UINT64_C(0xEFEFEFEFEFEFEFEF));
 #  elif PTRSIZE == 4
-    assert((Size_t)padlist != UINT64_C(0xEFEFEFEF));
+    assert((Size_t)padlist != 0xEFEFEFEF);
 #  else
 #    error unknown pointer size
 #  endif
@@ -497,11 +500,12 @@ finished its job, so it can forget the slab.
 void
 Perl_cv_forget_slab(pTHX_ CV *cv)
 {
-    const bool slabbed = !!CvSLABBED(cv);
+    bool slabbed;
     OPSLAB *slab = NULL;
 
-    PERL_ARGS_ASSERT_CV_FORGET_SLAB;
-
+    if (!cv)
+        return;
+    slabbed = cBOOL(CvSLABBED(cv));
     if (!slabbed) return;
 
     CvSLABBED_off(cv);
@@ -528,10 +532,10 @@ Perl_cv_forget_slab(pTHX_ CV *cv)
 
 Allocates a place in the currently-compiling
 pad (via L<perlapi/pad_alloc>) and
-then stores a name for that entry.  I<name> is adopted and
+then stores a name for that entry.  C<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
+string.  C<typestash> and C<ourstash> and the C<padadd_STATE>
+flag get added to C<name>.  None of the other
 processing of L<perlapi/pad_add_name_pvn>
 is done.  Returns the offset of the allocated pad slot.
 
@@ -576,15 +580,15 @@ variable.  Stores the name and other metadata in the name part of the
 pad, and makes preparations to manage the variable's lexical scoping.
 Returns the offset of the allocated pad slot.
 
-I<namepv>/I<namelen> specify the variable's name, including leading sigil.
-If I<typestash> is non-null, the name is for a typed lexical, and this
-identifies the type.  If I<ourstash> is non-null, it's a lexical reference
+C<namepv>/C<namelen> specify the variable's name, including leading sigil.
+If C<typestash> is non-null, the name is for a typed lexical, and this
+identifies the type.  If C<ourstash> is non-null, it's a lexical reference
 to a package variable, and this identifies the package.  The following
 flags can be OR'ed together:
 
   padadd_OUR          redundantly specifies if it's a package var
   padadd_STATE        variable will retain value persistently
   padadd_NO_DUP_CHECK skip check for lexical shadowing
+ padadd_OUR          redundantly specifies if it's a package var
+ padadd_STATE        variable will retain value persistently
+ padadd_NO_DUP_CHECK skip check for lexical shadowing
 
 =cut
 */
@@ -682,7 +686,7 @@ Perl_pad_add_name_sv(pTHX_ SV *name, U32 flags, HV *typestash, HV *ourstash)
 Allocates a place in the currently-compiling pad,
 returning the offset of the allocated pad slot.
 No name is initially attached to the pad slot.
-I<tmptype> is a set of flags indicating the kind of pad entry required,
+C<tmptype> is a set of flags indicating the kind of pad entry required,
 which will be set in the value SV for the allocated pad entry:
 
     SVs_PADMY    named lexical variable ("my", "our", "state")
@@ -695,7 +699,7 @@ does not cause the SV in the pad slot to be marked read-only, but simply
 tells C<pad_alloc> that it I<will> be made read-only (by the caller), or at
 least should be treated as such.
 
-I<optype> should be an opcode indicating the type of operation that the
+C<optype> should be an opcode indicating the type of operation that the
 pad entry is to support.  This doesn't affect operational semantics,
 but is used for debugging.
 
@@ -785,12 +789,12 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype)
 Allocates a place in the currently-compiling pad (via L</pad_alloc>)
 for an anonymous function that is lexically scoped inside the
 currently-compiling function.
-The function I<func> is linked into the pad, and its C<CvOUTSIDE> link
+The function C<func> is linked into the pad, and its C<CvOUTSIDE> link
 to the outer scope is weakened to avoid a reference loop.
 
 One reference count is stolen, so you may need to do C<SvREFCNT_inc(func)>.
 
-I<optype> should be an opcode indicating the type of operation that the
+C<optype> should be an opcode indicating the type of operation that the
 pad entry is to support.  This doesn't affect operational semantics,
 but is used for debugging.
 
@@ -932,8 +936,8 @@ S_pad_check_dup(pTHX_ PADNAME *name, U32 flags, const HV *ourstash)
 
 Given the name of a lexical variable, find its position in the
 currently-compiling pad.
-I<namepv>/I<namelen> specify the variable's name, including leading sigil.
-I<flags> is reserved and must be zero.
+C<namepv>/C<namelen> specify the variable's name, including leading sigil.
+C<flags> is reserved and must be zero.
 If it is not in the current pad but appears in the pad of any lexically
 enclosing scope, then a pseudo-entry for it is added in the current pad.
 Returns the offset in the current pad,
@@ -959,6 +963,10 @@ Perl_pad_findmy_pvn(pTHX_ const char *namepv, STRLEN namelen, U32 flags)
        Perl_croak(aTHX_ "panic: pad_findmy_pvn illegal flag bits 0x%" UVxf,
                   (UV)flags);
 
+    /* compilation errors can zero PL_compcv */
+    if (!PL_compcv)
+        return NOT_IN_PAD;
+
     offset = pad_findlex(namepv, namelen, flags,
                 PL_compcv, PL_cop_seqmax, 1, NULL, &out_pn, &out_flags);
     if ((PADOFFSET)offset != NOT_IN_PAD) 
@@ -1374,7 +1382,7 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
 /*
 =for apidoc Am|SV *|pad_sv|PADOFFSET po
 
-Get the value at offset I<po> in the current (compiling or executing) pad.
+Get the value at offset C<po> in the current (compiling or executing) pad.
 Use macro PAD_SV instead of calling this function directly.
 
 =cut
@@ -1397,7 +1405,7 @@ Perl_pad_sv(pTHX_ PADOFFSET po)
 /*
 =for apidoc Am|void|pad_setsv|PADOFFSET po|SV *sv
 
-Set the value at offset I<po> in the current (compiling or executing) pad.
+Set the value at offset C<po> in the current (compiling or executing) pad.
 Use the macro PAD_SETSV() rather than calling this function directly.
 
 =cut
@@ -1659,7 +1667,7 @@ S_pad_reset(pTHX)
 
 Tidy up a pad at the end of compilation of the code to which it belongs.
 Jobs performed here are: remove most stuff from the pads of anonsub
-prototypes; give it a @_; mark temporaries as such.  I<type> indicates
+prototypes; give it a @_; mark temporaries as such.  C<type> indicates
 the kind of subroutine:
 
     padtidy_SUB        ordinary subroutine
@@ -1931,7 +1939,7 @@ S_cv_dump(pTHX_ const CV *cv, const char *title)
 /*
 =for apidoc Am|CV *|cv_clone|CV *proto
 
-Clone a CV, making a lexical closure.  I<proto> supplies the prototype
+Clone a CV, making a lexical closure.  C<proto> supplies the prototype
 of the function: its code, pad structure, and other attributes.
 The prototype is combined with a capture of outer lexicals to which the
 code refers, which are taken from the currently-executing instance of
@@ -1940,10 +1948,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);
@@ -1955,7 +1964,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));
 
@@ -2042,7 +2052,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);
                    }
@@ -2088,12 +2100,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;
@@ -2186,7 +2256,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;
@@ -2221,7 +2291,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");
@@ -2239,7 +2309,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 */
@@ -2248,7 +2318,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);
 }
 
 /*
@@ -2263,7 +2333,7 @@ An SV may be passed as a second argument.  If so, the name will be assigned
 to it and it will be returned.  Otherwise the returned SV will be a new
 mortal.
 
-If the I<flags> include CV_NAME_NOTQUAL, then the package name will not be
+If the C<flags> include CV_NAME_NOTQUAL, then the package name will not be
 included.  If the first argument is neither a CV nor a GV, this flag is
 ignored (subject to change).
 
@@ -2712,7 +2782,7 @@ Perl_padnamelist_dup(pTHX_ PADNAMELIST *srcpad, CLONE_PARAMS *param)
 /*
 =for apidoc newPADNAMEpvn
 
-Constructs and returns a new pad name.  I<s> must be a UTF8 string.  Do not
+Constructs and returns a new pad name.  C<s> must be a UTF8 string.  Do not
 use this for pad names that point to outer lexicals.  See
 L</newPADNAMEouter>.
 
@@ -2743,7 +2813,7 @@ Perl_newPADNAMEpvn(const char *s, STRLEN len)
 =for apidoc newPADNAMEouter
 
 Constructs and returns a new pad name.  Only use this function for names
-that refer to outer lexicals.  (See also L</newPADNAMEpvn>.)  I<outer> is
+that refer to outer lexicals.  (See also L</newPADNAMEpvn>.)  C<outer> is
 the outer pad name that this one mirrors.  The returned pad name has the
 PADNAMEt_OUTER flag already set.
 
@@ -2830,11 +2900,5 @@ Perl_padname_dup(pTHX_ PADNAME *src, CLONE_PARAMS *param)
 #endif /* USE_ITHREADS */
 
 /*
- * Local variables:
- * c-indentation-style: bsd
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- *
  * ex: set ts=8 sts=4 sw=4 et:
  */