diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-07-02 18:18:13 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-07-25 23:48:02 -0700 |
commit | 5d7191988b7898f8bbf2cb7fe55bcad6416c3e9c (patch) | |
tree | ec28f973d92efbf6cb283c49c6f9fd9cbe5b1835 /pad.c | |
parent | 137da2b05b4b7628115049f343163bdaf2c30dbb (diff) | |
download | perl-5d7191988b7898f8bbf2cb7fe55bcad6416c3e9c.tar.gz |
Stop shared hash key TARGs from being shared
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.
Diffstat (limited to 'pad.c')
-rw-r--r-- | pad.c | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -2309,7 +2309,7 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth) SvPADMY_on(sv); } } - 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 { |