This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Get chdir.t working under minitest
[perl5.git] / pad.c
diff --git a/pad.c b/pad.c
index 271a9d8..42f3734 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -745,13 +745,17 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype)
             * in outer subs contain values not marked PADMY.
             * Thus we must skip, not just pad values that are
             * marked as current pad values, but also those with names.
+            * If pad_reset is enabled, â€˜current’ means different
+            * things depending on whether we are allocating a con-
+            * stant or a target.  For a target, things marked PADTMP
+            * can be reused; not so for constants.
             */
            if (++retval <= names_fill &&
                   (sv = names[retval]) && sv != &PL_sv_undef)
                continue;
            sv = *av_fetch(PL_comppad, retval, TRUE);
            if (!(SvFLAGS(sv) &
-#ifdef USE_BROKEN_PAD_RESET
+#ifdef USE_PAD_RESET
                    (SVs_PADMY|(konst ? SVs_PADTMP : 0))
 #else
                    (SVs_PADMY|SVs_PADTMP)
@@ -1483,6 +1487,12 @@ Perl_pad_block_start(pTHX_ int full)
     PL_min_intro_pending = 0;
     SAVEI32(PL_comppad_name_fill);
     SAVEI32(PL_padix_floor);
+    /* PL_padix_floor is what PL_padix is reset to at the start of each
+       statement, by pad_reset().  We set it when entering a new scope
+       to keep things like this working:
+           print "$foo$bar", do { this(); that() . "foo" };
+       We must not let "$foo$bar" and the later concatenation share the
+       same target.  */
     PL_padix_floor = PL_padix;
     PL_pad_reset_pending = FALSE;
 }
@@ -1626,7 +1636,7 @@ Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust)
 
     /* if pad tmps aren't shared between ops, then there's no need to
      * create a new tmp when an existing op is freed */
-#ifdef USE_BROKEN_PAD_RESET
+#ifdef USE_PAD_RESET
     PL_curpad[po] = newSV(0);
     SvPADTMP_on(PL_curpad[po]);
 #else
@@ -1654,16 +1664,15 @@ Mark all the current temporaries for reuse
 =cut
 */
 
-/* XXX pad_reset() is currently disabled because it results in serious bugs.
- * It causes pad temp TARGs to be shared between OPs. Since TARGs are pushed
- * on the stack by OPs that use them, there are several ways to get an alias
- * to  a shared TARG.  Such an alias will change randomly and unpredictably.
- * We avoid doing this until we can think of a Better Way.
- * GSAR 97-10-29 */
+/* pad_reset() causes pad temp TARGs (operator targets) to be shared
+ * between OPs from different statements.  During compilation, at the start
+ * of each statement pad_reset resets PL_padix back to its previous value.
+ * When allocating a target, pad_alloc begins its scan through the pad at
+ * PL_padix+1.  */
 static void
 S_pad_reset(pTHX)
 {
-#ifdef USE_BROKEN_PAD_RESET
+#ifdef USE_PAD_RESET
     if (AvARRAY(PL_comppad) != PL_curpad)
        Perl_croak(aTHX_ "panic: pad_reset curpad, %p!=%p",
                   AvARRAY(PL_comppad), PL_curpad);
@@ -1822,7 +1831,7 @@ Free the SV at offset po in the current pad.
 void
 Perl_pad_free(pTHX_ PADOFFSET po)
 {
-#ifndef USE_BROKEN_PAD_RESET
+#ifndef USE_PAD_RESET
     SV *sv;
 #endif
     ASSERT_CURPAD_LEGAL("pad_free");
@@ -1839,14 +1848,14 @@ Perl_pad_free(pTHX_ PADOFFSET po)
            PTR2UV(PL_comppad), PTR2UV(PL_curpad), (long)po)
     );
 
-#ifndef USE_BROKEN_PAD_RESET
+#ifndef USE_PAD_RESET
     sv = PL_curpad[po];
     if (sv && sv != &PL_sv_undef && !SvPADMY(sv))
        SvFLAGS(sv) &= ~SVs_PADTMP;
-#endif
 
     if ((I32)po < PL_padix)
        PL_padix = po - 1;
+#endif
 }
 
 /*