summaryrefslogtreecommitdiff
path: root/pad.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-07-02 18:18:13 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-07-25 23:48:02 -0700
commit5d7191988b7898f8bbf2cb7fe55bcad6416c3e9c (patch)
treeec28f973d92efbf6cb283c49c6f9fd9cbe5b1835 /pad.c
parent137da2b05b4b7628115049f343163bdaf2c30dbb (diff)
downloadperl-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.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/pad.c b/pad.c
index 83082a5c90..e44083b01e 100644
--- a/pad.c
+++ b/pad.c
@@ -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 {