summaryrefslogtreecommitdiff
path: root/op.h
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-11-26 22:23:53 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-11-27 07:05:04 -0800
commitf5a0fd1e07ceb4866d2eee4eb9283498cd3ef1be (patch)
tree7fd7e62795659db2b78aac0c5bb39f136c398e9d /op.h
parente1b145039d15f6202e21cd23abb95117153eb816 (diff)
downloadperl-f5a0fd1e07ceb4866d2eee4eb9283498cd3ef1be.tar.gz
Don’t share TARGs between recursive ops
I had to change the definition of IS_PADCONST to account for the SVf_IsCOW flag. Previously, anything marked READONLY would be consid- ered a pad constant, to be shared by pads of different recursion lev- els. Some of those READONLY things were not actually read-only, as they were copy-on-write scalars, which are never read-only. So I changed the definition of IS_PADCONST in e3918bb703c to accept COWs as well as read-only scalars, since I was removing the READONLY flag from COWs. With the new copy-on-write scheme, it is easy for a TARG to turn into a COW. If that happens and then the same subroutine calls itself recursively for the first time after that, pad_push will see that this is a pad ‘constant’ and allow the next recursion level to share it. If pp_concat calls itself recursively, the recursive call can modify the scalar the outer call is in the middle of using, causing the return value to be doubled up (‘tmptmp’) in the test case added here. Since pad constants are marked PADTMP (I would like to change that eventually), there is no way to distinguish them from TARGs when the are COWs, except for the fact that pad constants that are COWs are always shared hash keys (SvLEN==0).
Diffstat (limited to 'op.h')
-rw-r--r--op.h3
1 files changed, 2 insertions, 1 deletions
diff --git a/op.h b/op.h
index 935e126c67..97228b1ce2 100644
--- a/op.h
+++ b/op.h
@@ -570,7 +570,8 @@ struct loop {
# define cGVOPx_gv(o) ((GV*)PAD_SVl(cPADOPx(o)->op_padix))
# define IS_PADGV(v) (v && SvTYPE(v) == SVt_PVGV && isGV_with_GP(v) \
&& GvIN_PAD(v))
-# define IS_PADCONST(v) (v && (SvREADONLY(v) || SvIsCOW(v)))
+# define IS_PADCONST(v) \
+ (v && (SvREADONLY(v) || (SvIsCOW(v) && !SvLEN(v))))
# define cSVOPx_sv(v) (cSVOPx(v)->op_sv \
? cSVOPx(v)->op_sv : PAD_SVl((v)->op_targ))
# define cSVOPx_svp(v) (cSVOPx(v)->op_sv \