SunOS 4.1.4 is working, too.
[p5sagit/p5-mst-13.2.git] / scope.c
diff --git a/scope.c b/scope.c
index f738b5b..75f59cf 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -214,7 +214,7 @@ S_save_scalar_at(pTHX_ SV **sptr)
            PL_tainted = oldtainted;
        }
        SvMAGIC(sv) = SvMAGIC(osv);
-       SvFLAGS(sv) |= SvMAGICAL(osv);
+       SvFLAGS(sv) |= SvMAGICAL(osv) | SvREADONLY(osv);
        /* XXX SvMAGIC() is *shared* between osv and sv.  This can
         * lead to coredumps when both SVs are destroyed without one
         * of their SvMAGIC() slots being NULLed. */
@@ -281,6 +281,18 @@ Perl_save_shared_pvref(pTHX_ char **str)
     SSPUSHINT(SAVEt_SHARED_PVREF);
 }
 
+/* set the SvFLAGS specified by mask to the values in val */
+
+void
+Perl_save_set_svflags(pTHX_ SV* sv, U32 mask, U32 val)
+{
+    SSCHECK(4);
+    SSPUSHPTR(sv);
+    SSPUSHINT(mask);
+    SSPUSHINT(val);
+    SSPUSHINT(SAVEt_SET_SVFLAGS);
+}
+
 void
 Perl_save_gp(pTHX_ GV *gv, I32 empty)
 {
@@ -612,9 +624,6 @@ Perl_save_aelem(pTHX_ AV *av, I32 idx, SV **sptr)
     SSPUSHINT(idx);
     SSPUSHPTR(SvREFCNT_inc(*sptr));
     SSPUSHINT(SAVEt_AELEM);
-    /* if it gets reified later, the restore will have the wrong refcnt */
-    if (!AvREAL(av) && AvREIFY(av))
-       SvREFCNT_inc(*sptr);
     save_scalar_at(sptr);
     sv = *sptr;
     /* If we're localizing a tied array element, this new sv
@@ -697,7 +706,7 @@ Perl_leave_scope(pTHX_ I32 base)
            value = (SV*)SSPOPPTR;
            gv = (GV*)SSPOPPTR;
            ptr = &GvSV(gv);
-           av = (AV*)gv; /* what to refcnt_dec */
+           SvREFCNT_dec(gv);
            goto restore_sv;
        case SAVEt_GENERIC_PVREF:               /* generic pv */
            str = (char*)SSPOPPTR;
@@ -730,7 +739,6 @@ Perl_leave_scope(pTHX_ I32 base)
        case SAVEt_SVREF:                       /* scalar reference */
            value = (SV*)SSPOPPTR;
            ptr = SSPOPPTR;
-           av = Nullav; /* what to refcnt_dec */
        restore_sv:
            sv = *(SV**)ptr;
            DEBUG_S(PerlIO_printf(Perl_debug_log,
@@ -766,8 +774,6 @@ Perl_leave_scope(pTHX_ I32 base)
            SvSETMAGIC(value);
            PL_localizing = 0;
            SvREFCNT_dec(value);
-           if (av) /* actually an av, hv or gv */
-               SvREFCNT_dec(av);
            break;
        case SAVEt_AV:                          /* array reference */
            av = (AV*)SSPOPPTR;
@@ -945,7 +951,7 @@ Perl_leave_scope(pTHX_ I32 base)
                SvREFCNT_dec(sv);       /* Cast current value to the winds. */
                /* preserve pad nature, but also mark as not live
                 * for any closure capturing */
-               SvFLAGS(*(SV**)ptr) |= padflags & SVs_PADSTALE;
+               SvFLAGS(*(SV**)ptr) |= padflags | SVs_PADSTALE;
            }
            break;
        case SAVEt_DELETE:
@@ -977,14 +983,13 @@ Perl_leave_scope(pTHX_ I32 base)
            value = (SV*)SSPOPPTR;
            i = SSPOPINT;
            av = (AV*)SSPOPPTR;
-           if (!AvREAL(av) && AvREIFY(av)) /* undo reify guard */
-               SvREFCNT_dec(value);
            ptr = av_fetch(av,i,1);
            if (ptr) {
                sv = *(SV**)ptr;
                if (sv && sv != &PL_sv_undef) {
                    if (SvTIED_mg((SV*)av, PERL_MAGIC_tied))
                        (void)SvREFCNT_inc(sv);
+                   SvREFCNT_dec(av);
                    goto restore_sv;
                }
            }
@@ -1002,8 +1007,8 @@ Perl_leave_scope(pTHX_ I32 base)
                    ptr = &HeVAL((HE*)ptr);
                    if (SvTIED_mg((SV*)hv, PERL_MAGIC_tied))
                        (void)SvREFCNT_inc(*(SV**)ptr);
+                   SvREFCNT_dec(hv);
                    SvREFCNT_dec(sv);
-                   av = (AV*)hv; /* what to refcnt_dec */
                    goto restore_sv;
                }
            }
@@ -1036,6 +1041,15 @@ Perl_leave_scope(pTHX_ I32 base)
                    AvARRAY((PAD*)ptr)[off] = (SV*)SSPOPPTR;
            }
            break;
+       case SAVEt_SET_SVFLAGS:
+           {
+               U32 val  = (U32)SSPOPINT;
+               U32 mask = (U32)SSPOPINT;
+               sv = (SV*)SSPOPPTR;
+               SvFLAGS(sv) &= ~mask;
+               SvFLAGS(sv) |= val;
+           }
+           break;
        default:
            Perl_croak(aTHX_ "panic: leave_scope inconsistency");
        }