In S_fold_constants() under MAD, need to copy the SV representing the result.
authorNicholas Clark <nick@ccl4.org>
Mon, 11 Apr 2011 19:25:04 +0000 (20:25 +0100)
committerNicholas Clark <nick@ccl4.org>
Thu, 19 May 2011 07:55:56 +0000 (08:55 +0100)
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.

op.c

diff --git a/op.c b/op.c
index 8591c4b..4960d22 100644 (file)
--- 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);