summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2011-04-11 20:25:04 +0100
committerNicholas Clark <nick@ccl4.org>2011-05-19 08:55:56 +0100
commit523a0f0c39e20d3c9a00a9efa8a965d0cf7ed035 (patch)
treecbc254864a93286b62f144eb9d6f7748c6982941 /op.c
parent8ae73bce341cb300ba81a3680bab34352ff2c2ba (diff)
downloadperl-523a0f0c39e20d3c9a00a9efa8a965d0cf7ed035.tar.gz
In S_fold_constants() under MAD, need to copy the SV representing the result.
For the non-MAD case (the historical default), it was fine to use pad_swipe() (which doesn't adjust any part of the OS), because the OS was freed soon after. However, the MAD code doesn't free the OS, hence as-was, without this change, the OS still thought that it owned the pad slot, and much jollity resulted as two different parts of the code fought over whichever SV had the bad luck to next be billeted there.
Diffstat (limited to 'op.c')
-rw-r--r--op.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/op.c b/op.c
index 8591c4be14..4960d228b9 100644
--- a/op.c
+++ b/op.c
@@ -2683,8 +2683,16 @@ S_fold_constants(pTHX_ register OP *o)
case 0:
CALLRUNOPS(aTHX);
sv = *(PL_stack_sp--);
- if (o->op_targ && sv == PAD_SV(o->op_targ)) /* grab pad temp? */
+ if (o->op_targ && sv == PAD_SV(o->op_targ)) { /* grab pad temp? */
+#ifdef PERL_MAD
+ /* Can't simply swipe the SV from the pad, because that relies on
+ the op being freed "real soon now". Under MAD, this doesn't
+ happen (see the #ifdef below). */
+ sv = newSVsv(sv);
+#else
pad_swipe(o->op_targ, FALSE);
+#endif
+ }
else if (SvTEMP(sv)) { /* grab mortal temp? */
SvREFCNT_inc_simple_void(sv);
SvTEMP_off(sv);