This is a live mirror of the Perl 5 development currently hosted at
Stop shared hash key TARGs from being shared
authorFather Chrysostomos <>
Wed, 3 Jul 2013 01:18:13 +0000 (18:18 -0700)
committerFather Chrysostomos <>
Fri, 26 Jul 2013 06:48:02 +0000 (23:48 -0700)
A CV has a list of pads containing a different pad for each recursion
level.  pad_push, which adds a new pad to the list, copies some items
from pad no. 1 but not others.  In particular op targets¹ are created
anew, but, under ithreads, constants² are not.  Historically, these
were distinguished from each other by flags on the value.  Any read-
only or shared hash key scalar was considered to be a constant, and
hence shared between pads.  The target returned by ref() is a shared
hash key scalar, so it was being shared between recursion levels.
Recent commits have made it possible to distinguish between constants
and targets based on the name.  Formerly, both were nameless pad
entries.  Now constants have zero-length names (PadnamePV(name) &&
!PadnameLEN(name)).  So we can use that to fix this bug.

¹ Many operators return the same scalar each time, for efficiency.
  This is stored in the pad, and is known as the target, or TARG.
² Constanst are stored in the pad under ithreads, instead of being
  attached directly to ops, as they are under non-threaded builds.


diff --git a/pad.c b/pad.c
index 83082a5..e44083b 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -2309,7 +2309,7 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth)
-           else if (IS_PADGV(oldpad[ix]) || IS_PADCONST(oldpad[ix])) {
+           else if (IS_PADGV(oldpad[ix]) || PadnamePV(names[ix])) {
                av_store(newpad, ix, SvREFCNT_inc_NN(oldpad[ix]));
            else {
index 56bbaae..53eae4a 100644 (file)
@@ -118,10 +118,8 @@ sub b {
     push @scratch, (ref $o, $depth||b($pack,$depth+1))[0];
-$::TODO = "not fixed yet" if $Config::Config{useithreads};
 is "@scratch", "o n", 
    'recursive calls do not share shared-hash-key TARGs (2)';
-undef $::TODO;
 # [perl #78194] @_ aliasing op return values
 sub { is \$_[0], \$_[0],