if (PL_scopestack_ix == PL_scopestack_max) {
PL_scopestack_max = GROW(PL_scopestack_max);
Renew(PL_scopestack, PL_scopestack_max, I32);
+#ifdef DEBUGGING
+ Renew(PL_scopestack_name, PL_scopestack_max, const char*);
+#endif
}
+#ifdef DEBUGGING
+ PL_scopestack_name[PL_scopestack_ix] = "unknown";
+#endif
PL_scopestack[PL_scopestack_ix++] = PL_savestack_ix;
}
S_save_scalar_at(pTHX_ SV **sptr, const U32 flags)
{
dVAR;
- SV * const osv = *sptr;
- register SV * const sv = *sptr = newSV(0);
+ SV * osv;
+ register SV *sv;
PERL_ARGS_ASSERT_SAVE_SCALAR_AT;
+ osv = *sptr;
+ sv = (flags & SAVEf_KEEPOLDELEM) ? osv : (*sptr = newSV(0));
+
if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv) && SvTYPE(osv) != SVt_PVGV) {
if (SvGMAGICAL(osv)) {
const bool oldtainted = PL_tainted;
(SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
PL_tainted = oldtainted;
}
- mg_localize(osv, sv, (flags & SAVEf_SETMAGIC) != 0);
+ if (!(flags & SAVEf_KEEPOLDELEM))
+ mg_localize(osv, sv, (flags & SAVEf_SETMAGIC) != 0);
}
+
return sv;
}
-static void
-S_save_pushptrptr(pTHX_ void *const ptr1, void *const ptr2, const int type)
+void
+Perl_save_pushptrptr(pTHX_ void *const ptr1, void *const ptr2, const int type)
{
dVAR;
SSCHECK(3);
}
void
-Perl_save_int(pTHX_ int *intp)
+Perl_save_bool(pTHX_ bool *boolp)
{
dVAR;
- PERL_ARGS_ASSERT_SAVE_INT;
+ PERL_ARGS_ASSERT_SAVE_BOOL;
SSCHECK(3);
- SSPUSHINT(*intp);
- SSPUSHPTR(intp);
- SSPUSHINT(SAVEt_INT);
+ SSPUSHBOOL(*boolp);
+ SSPUSHPTR(boolp);
+ SSPUSHINT(SAVEt_BOOL);
}
void
-Perl_save_bool(pTHX_ bool *boolp)
+Perl_save_pushi32ptr(pTHX_ const I32 i, void *const ptr, const int type)
+{
+ dVAR;
+ SSCHECK(3);
+ SSPUSHINT(i);
+ SSPUSHPTR(ptr);
+ SSPUSHINT(type);
+}
+
+void
+Perl_save_int(pTHX_ int *intp)
{
dVAR;
- PERL_ARGS_ASSERT_SAVE_BOOL;
+ PERL_ARGS_ASSERT_SAVE_INT;
- SSCHECK(3);
- SSPUSHBOOL(*boolp);
- SSPUSHPTR(boolp);
- SSPUSHINT(SAVEt_BOOL);
+ save_pushi32ptr(*intp, intp, SAVEt_INT);
}
void
PERL_ARGS_ASSERT_SAVE_I8;
- SSCHECK(3);
- SSPUSHINT(*bytep);
- SSPUSHPTR(bytep);
- SSPUSHINT(SAVEt_I8);
+ save_pushi32ptr(*bytep, bytep, SAVEt_I8);
}
void
PERL_ARGS_ASSERT_SAVE_I16;
- SSCHECK(3);
- SSPUSHINT(*intp);
- SSPUSHPTR(intp);
- SSPUSHINT(SAVEt_I16);
+ save_pushi32ptr(*intp, intp, SAVEt_I16);
}
void
PERL_ARGS_ASSERT_SAVE_I32;
- SSCHECK(3);
- SSPUSHINT(*intp);
- SSPUSHPTR(intp);
- SSPUSHINT(SAVEt_I32);
+ save_pushi32ptr(*intp, intp, SAVEt_I32);
}
/* Cannot use save_sptr() to store a char* since the SV** cast will
PERL_ARGS_ASSERT_SAVE_DELETE;
- SSCHECK(4);
- SSPUSHINT(klen);
- SSPUSHPTR(key);
- SSPUSHPTR(SvREFCNT_inc_simple(hv));
- SSPUSHINT(SAVEt_DELETE);
+ save_pushptri32ptr(key, klen, SvREFCNT_inc_simple(hv), SAVEt_DELETE);
+}
+
+void
+Perl_save_hdelete(pTHX_ HV *hv, SV *keysv)
+{
+ STRLEN len;
+ I32 klen;
+ const char *key;
+
+ PERL_ARGS_ASSERT_SAVE_HDELETE;
+
+ key = SvPV_const(keysv, len);
+ klen = SvUTF8(keysv) ? -(I32)len : (I32)len;
+ SvREFCNT_inc_simple_void_NN(hv);
+ save_pushptri32ptr(savepvn(key, len), klen, hv, SAVEt_DELETE);
+}
+
+void
+Perl_save_adelete(pTHX_ AV *av, I32 key)
+{
+ dVAR;
+
+ PERL_ARGS_ASSERT_SAVE_ADELETE;
+
+ SvREFCNT_inc_void(av);
+ save_pushi32ptr(key, av, SAVEt_ADELETE);
}
void
}
void
-Perl_save_aelem(pTHX_ AV *av, I32 idx, SV **sptr)
+Perl_save_hints(pTHX)
+{
+ dVAR;
+ if (PL_compiling.cop_hints_hash) {
+ HINTS_REFCNT_LOCK;
+ PL_compiling.cop_hints_hash->refcounted_he_refcnt++;
+ HINTS_REFCNT_UNLOCK;
+ }
+ if (PL_hints & HINT_LOCALIZE_HH) {
+ save_pushptri32ptr(GvHV(PL_hintgv), PL_hints,
+ PL_compiling.cop_hints_hash, SAVEt_HINTS);
+ GvHV(PL_hintgv) = Perl_hv_copy_hints_hv(aTHX_ GvHV(PL_hintgv));
+ } else {
+ save_pushi32ptr(PL_hints, PL_compiling.cop_hints_hash, SAVEt_HINTS);
+ }
+}
+
+static void
+S_save_pushptri32ptr(pTHX_ void *const ptr1, const I32 i, void *const ptr2,
+ const int type)
+{
+ SSCHECK(4);
+ SSPUSHPTR(ptr1);
+ SSPUSHINT(i);
+ SSPUSHPTR(ptr2);
+ SSPUSHINT(type);
+}
+
+void
+Perl_save_aelem_flags(pTHX_ AV *av, I32 idx, SV **sptr, const U32 flags)
{
dVAR;
SV *sv;
- PERL_ARGS_ASSERT_SAVE_AELEM;
+ PERL_ARGS_ASSERT_SAVE_AELEM_FLAGS;
SvGETMAGIC(*sptr);
- SSCHECK(4);
- SSPUSHPTR(SvREFCNT_inc_simple(av));
- SSPUSHINT(idx);
- SSPUSHPTR(SvREFCNT_inc(*sptr));
- SSPUSHINT(SAVEt_AELEM);
+ save_pushptri32ptr(SvREFCNT_inc_simple(av), idx, SvREFCNT_inc(*sptr),
+ SAVEt_AELEM);
/* if it gets reified later, the restore will have the wrong refcnt */
if (!AvREAL(av) && AvREIFY(av))
SvREFCNT_inc_void(*sptr);
- save_scalar_at(sptr, SAVEf_SETMAGIC); /* XXX - FIXME - see #60360 */
+ save_scalar_at(sptr, flags); /* XXX - FIXME - see #60360 */
+ if (flags & SAVEf_KEEPOLDELEM)
+ return;
sv = *sptr;
/* If we're localizing a tied array element, this new sv
* won't actually be stored in the array - so it won't get
SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_HELEM);
save_scalar_at(sptr, flags);
+ if (flags & SAVEf_KEEPOLDELEM)
+ return;
sv = *sptr;
/* If we're localizing a tied hash element, this new sv
* won't actually be stored in the hash - so it won't get
void* ptr;
register char* str;
I32 i;
+ /* Localise the effects of the TAINT_NOT inside the loop. */
+ const bool was = PL_tainted;
if (base < -1)
Perl_croak(aTHX_ "panic: corrupt saved stack index");
case SAVEt_AV: /* array reference */
av = MUTABLE_AV(SSPOPPTR);
gv = MUTABLE_GV(SSPOPPTR);
- if (GvAV(gv)) {
- SvREFCNT_dec(GvAV(gv));
- }
+ SvREFCNT_dec(GvAV(gv));
GvAV(gv) = av;
if (SvMAGICAL(av)) {
PL_localizing = 2;
case SAVEt_HV: /* hash reference */
hv = MUTABLE_HV(SSPOPPTR);
gv = MUTABLE_GV(SSPOPPTR);
- if (GvHV(gv)) {
- SvREFCNT_dec(GvHV(gv));
- }
+ SvREFCNT_dec(GvHV(gv));
GvHV(gv) = hv;
if (SvMAGICAL(hv)) {
PL_localizing = 2;
case SAVEt_DELETE:
ptr = SSPOPPTR;
hv = MUTABLE_HV(ptr);
+ i = SSPOPINT;
ptr = SSPOPPTR;
- (void)hv_delete(hv, (char*)ptr, (I32)SSPOPINT, G_DISCARD);
+ (void)hv_delete(hv, (char*)ptr, i, G_DISCARD);
SvREFCNT_dec(hv);
Safefree(ptr);
break;
+ case SAVEt_ADELETE:
+ ptr = SSPOPPTR;
+ av = MUTABLE_AV(ptr);
+ i = SSPOPINT;
+ (void)av_delete(av, i, G_DISCARD);
+ SvREFCNT_dec(av);
+ break;
case SAVEt_DESTRUCTOR_X:
ptr = SSPOPPTR;
(*SSPOPDXPTR)(aTHX_ ptr);
sv = MUTABLE_SV(SSPOPPTR);
hv = MUTABLE_HV(SSPOPPTR);
ptr = hv_fetch_ent(hv, sv, 1, 0);
+ SvREFCNT_dec(sv);
if (ptr) {
const SV * const oval = HeVAL((HE*)ptr);
if (oval && oval != &PL_sv_undef) {
ptr = &HeVAL((HE*)ptr);
if (SvTIED_mg((const SV *)hv, PERL_MAGIC_tied))
SvREFCNT_inc_void(*(SV**)ptr);
- SvREFCNT_dec(sv);
av = MUTABLE_AV(hv); /* what to refcnt_dec */
goto restore_sv;
}
}
SvREFCNT_dec(hv);
- SvREFCNT_dec(sv);
SvREFCNT_dec(value);
break;
case SAVEt_OP:
SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
GvHV(PL_hintgv) = NULL;
}
- *(I32*)&PL_hints = (I32)SSPOPINT;
Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
PL_compiling.cop_hints_hash = (struct refcounted_he *) SSPOPPTR;
+ *(I32*)&PL_hints = (I32)SSPOPINT;
if (PL_hints & HINT_LOCALIZE_HH) {
SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
GvHV(PL_hintgv) = MUTABLE_HV(SSPOPPTR);
Perl_croak(aTHX_ "panic: leave_scope inconsistency");
}
}
+
+ PL_tainted = was;
}
void