This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove context param from set_padlist
[perl5.git] / pad.c
diff --git a/pad.c b/pad.c
index 524082e..9da5536 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -167,16 +167,16 @@ sv_eq_pvn_flags(pTHX_ const SV *sv, const char* pv, const STRLEN pvlen, const U3
         STRLEN cur1     = SvCUR(sv);
         const char *pv2 = pv;
         STRLEN cur2     = pvlen;
-       if (PL_encoding) {
+       if (IN_ENCODING) {
               SV* svrecode = NULL;
              if (SvUTF8(sv)) {
                   svrecode = newSVpvn(pv2, cur2);
-                  sv_recode_to_utf8(svrecode, PL_encoding);
+                  sv_recode_to_utf8(svrecode, _get_encoding());
                   pv2      = SvPV_const(svrecode, cur2);
              }
              else {
                   svrecode = newSVpvn(pv1, cur1);
-                  sv_recode_to_utf8(svrecode, PL_encoding);
+                  sv_recode_to_utf8(svrecode, _get_encoding());
                   pv1      = SvPV_const(svrecode, cur1);
              }
               SvREFCNT_dec_NN(svrecode);
@@ -197,7 +197,7 @@ sv_eq_pvn_flags(pTHX_ const SV *sv, const char* pv, const STRLEN pvlen, const U3
 
 #ifdef DEBUGGING
 void
-Perl_set_padlist(pTHX_ CV * cv, PADLIST *padlist){
+Perl_set_padlist(CV * cv, PADLIST *padlist){
     PERL_ARGS_ASSERT_SET_PADLIST;
 #  if PTRSIZE == 8
     if((Size_t)padlist == UINT64_C(0xEFEFEFEFEFEFEFEF)){
@@ -504,8 +504,8 @@ Perl_cv_undef_flags(pTHX_ CV *cv, U32 flags)
        Safefree(padlist);
        CvPADLIST_set(&cvbody, NULL);
     }
-    else if (CvISXSUB(&cvbody)) /* future union */
-       CvRESERVED(&cvbody) = NULL;
+    else if (CvISXSUB(&cvbody))
+       CvHSCXT(&cvbody) = NULL;
     /* else is (!CvISXSUB(&cvbody) && !CvPADLIST(&cvbody)) {do nothing;} */
 
 
@@ -1233,31 +1233,8 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
                    fake_offset = offset; /* in case we don't find a real one */
                    continue;
                }
-               /* is seq within the range _LOW to _HIGH ?
-                * This is complicated by the fact that PL_cop_seqmax
-                * may have wrapped around at some point */
-               if (COP_SEQ_RANGE_LOW(namesv) == PERL_PADSEQ_INTRO)
-                   continue; /* not yet introduced */
-
-               if (COP_SEQ_RANGE_HIGH(namesv) == PERL_PADSEQ_INTRO) {
-                   /* in compiling scope */
-                   if (
-                       (seq >  COP_SEQ_RANGE_LOW(namesv))
-                       ? (seq - COP_SEQ_RANGE_LOW(namesv) < (U32_MAX >> 1))
-                       : (COP_SEQ_RANGE_LOW(namesv) - seq > (U32_MAX >> 1))
-                   )
-                      break;
-               }
-               else if (
-                   (COP_SEQ_RANGE_LOW(namesv) > COP_SEQ_RANGE_HIGH(namesv))
-                   ?
-                       (  seq >  COP_SEQ_RANGE_LOW(namesv)
-                       || seq <= COP_SEQ_RANGE_HIGH(namesv))
-
-                   :    (  seq >  COP_SEQ_RANGE_LOW(namesv)
-                        && seq <= COP_SEQ_RANGE_HIGH(namesv))
-               )
-               break;
+               if (PadnameIN_SCOPE(namesv, seq))
+                   break;
            }
        }
 
@@ -1568,8 +1545,14 @@ Perl_intro_my(pTHX)
     U32 seq;
 
     ASSERT_CURPAD_ACTIVE("intro_my");
+    if (PL_compiling.cop_seq) {
+       seq = PL_compiling.cop_seq;
+       PL_compiling.cop_seq = 0;
+    }
+    else
+       seq = PL_cop_seqmax;
     if (! PL_min_intro_pending)
-       return PL_cop_seqmax;
+       return seq;
 
     svp = AvARRAY(PL_comppad_name);
     for (i = PL_min_intro_pending; i <= PL_max_intro_pending; i++) {
@@ -1588,10 +1571,7 @@ Perl_intro_my(pTHX)
            );
        }
     }
-    seq = PL_cop_seqmax;
-    PL_cop_seqmax++;
-    if (PL_cop_seqmax == PERL_PADSEQ_INTRO) /* not a legal value */
-       PL_cop_seqmax++;
+    COP_SEQMAX_INC;
     PL_min_intro_pending = 0;
     PL_comppad_name_fill = PL_max_intro_pending; /* Needn't search higher */
     DEBUG_Xv(PerlIO_printf(Perl_debug_log,
@@ -1649,9 +1629,7 @@ Perl_pad_leavemy(pTHX)
            }
        }
     }
-    PL_cop_seqmax++;
-    if (PL_cop_seqmax == PERL_PADSEQ_INTRO) /* not a legal value */
-       PL_cop_seqmax++;
+    COP_SEQMAX_INC;
     DEBUG_Xv(PerlIO_printf(Perl_debug_log,
            "Pad leavemy: seq = %ld\n", (long)PL_cop_seqmax));
     return o;
@@ -2032,7 +2010,7 @@ the immediately surrounding code.
 
 static CV *S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside);
 
-static void
+static CV *
 S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
 {
     I32 ix;
@@ -2189,6 +2167,92 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, bool newcv)
 
     if (newcv) SvREFCNT_inc_simple_void_NN(cv);
     LEAVE;
+
+    if (CvCONST(cv)) {
+       /* Constant sub () { $x } closing over $x:
+        * The prototype was marked as a candiate for const-ization,
+        * so try to grab the current const value, and if successful,
+        * turn into a const sub:
+        */
+       SV* const_sv;
+       OP *o = CvSTART(cv);
+       assert(newcv);
+       for (; o; o = o->op_next)
+           if (o->op_type == OP_PADSV)
+               break;
+       ASSUME(o->op_type == OP_PADSV);
+       const_sv = PAD_BASE_SV(CvPADLIST(cv), o->op_targ);
+       /* the candidate should have 1 ref from this pad and 1 ref
+        * from the parent */
+       if (const_sv && SvREFCNT(const_sv) == 2) {
+           const bool was_method = cBOOL(CvMETHOD(cv));
+           bool copied = FALSE;
+           if (outside) {
+               PADNAME * const pn =
+                   PadlistNAMESARRAY(CvPADLIST(outside))
+                       [PARENT_PAD_INDEX(PadlistNAMESARRAY(
+                           CvPADLIST(cv))[o->op_targ])];
+               assert(PadnameOUTER(PadlistNAMESARRAY(CvPADLIST(cv))
+                                       [o->op_targ]));
+               if (PadnameLVALUE(pn)) {
+                   /* We have a lexical that is potentially modifiable
+                      elsewhere, so making a constant will break clo-
+                      sure behaviour.  If this is a ‘simple lexical
+                      op tree’, i.e., sub(){$x}, emit a deprecation
+                      warning, but continue to exhibit the old behav-
+                      iour of making it a constant based on the ref-
+                      count of the candidate variable.
+
+                      A simple lexical op tree looks like this:
+
+                        leavesub
+                          lineseq
+                            nextstate
+                            padsv
+                    */
+                   if (OP_SIBLING(
+                        cUNOPx(cUNOPx(CvROOT(cv))->op_first)->op_first
+                       ) == o
+                    && !OP_SIBLING(o))
+                   {
+                       Perl_ck_warner_d(aTHX_
+                                         packWARN(WARN_DEPRECATED),
+                                        "Constants from lexical "
+                                        "variables potentially "
+                                        "modified elsewhere are "
+                                        "deprecated");
+                       /* We *copy* the lexical variable, and donate the
+                          copy to newCONSTSUB.  Yes, this is ugly, and
+                          should be killed.  We need to do this for the
+                          time being, however, because turning on SvPADTMP
+                          on a lexical will have observable effects
+                          elsewhere.  */
+                       const_sv = newSVsv(const_sv);
+                       copied = TRUE;
+                   }
+                   else
+                       goto constoff;
+               }
+           }
+           if (!copied)
+               SvREFCNT_inc_simple_void_NN(const_sv);
+           /* If the lexical is not used elsewhere, it is safe to turn on
+              SvPADTMP, since it is only when it is used in lvalue con-
+              text that the difference is observable.  */
+           SvREADONLY_on(const_sv);
+           SvPADTMP_on(const_sv);
+           SvREFCNT_dec_NN(cv);
+           cv = newCONSTSUB(CvSTASH(proto), NULL, const_sv);
+           if (was_method)
+               CvMETHOD_on(cv);
+       }
+       else {
+         constoff:
+           CvCONST_off(cv);
+       }
+    }
+
+    return cv;
 }
 
 static CV *
@@ -2226,7 +2290,8 @@ S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside)
     if (SvMAGIC(proto))
        mg_copy((SV *)proto, (SV *)cv, 0, 0);
 
-    if (CvPADLIST(proto)) S_cv_clone_pad(aTHX_ proto, cv, outside, newcv);
+    if (CvPADLIST(proto))
+       cv = S_cv_clone_pad(aTHX_ proto, cv, outside, newcv);
 
     DEBUG_Xv(
        PerlIO_printf(Perl_debug_log, "\nPad CV clone\n");
@@ -2235,25 +2300,6 @@ S_cv_clone(pTHX_ CV *proto, CV *cv, CV *outside)
        cv_dump(cv,      "To");
     );
 
-    if (CvCONST(cv)) {
-       /* Constant sub () { $x } closing over $x - see lib/constant.pm:
-        * The prototype was marked as a candiate for const-ization,
-        * so try to grab the current const value, and if successful,
-        * turn into a const sub:
-        */
-       SV* const const_sv = op_const_sv(CvSTART(cv), cv);
-       if (const_sv) {
-           SvREFCNT_dec_NN(cv);
-            /* For this calling case, op_const_sv returns a *copy*, which we
-               donate to newCONSTSUB. Yes, this is ugly, and should be killed.
-               Need to fix how lib/constant.pm works to eliminate this.  */
-           cv = newCONSTSUB(CvSTASH(proto), NULL, const_sv);
-       }
-       else {
-           CvCONST_off(cv);
-       }
-    }
-
     return cv;
 }