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;
}
SSCHECK(3);
SSPUSHPTR(ptr1);
SSPUSHPTR(ptr2);
- SSPUSHINT(type);
+ SSPUSHUV(type);
}
SV *
SSPUSHPTR(sv);
SSPUSHINT(mask);
SSPUSHINT(val);
- SSPUSHINT(SAVEt_SET_SVFLAGS);
+ SSPUSHUV(SAVEt_SET_SVFLAGS);
}
void
PERL_ARGS_ASSERT_SAVE_GP;
- save_pushptrptr(SvREFCNT_inc(gv), GvGP(gv), SAVEt_GP);
+ SSCHECK(4);
+ SSPUSHINT(SvFAKE(gv));
+ SSPUSHPTR(GvGP(gv));
+ SSPUSHPTR(SvREFCNT_inc(gv));
+ SSPUSHUV(SAVEt_GP);
+
+ /* Don't let the localized GV coerce into non-glob, otherwise we would
+ * not be able to restore GP upon leave from context if that happened */
+ SvFAKE_off(gv);
if (empty) {
GP *gp = Perl_newGP(aTHX_ gv);
SSCHECK(3);
SSPUSHBOOL(*boolp);
SSPUSHPTR(boolp);
- SSPUSHINT(SAVEt_BOOL);
+ SSPUSHUV(SAVEt_BOOL);
}
void
SSCHECK(3);
SSPUSHINT(i);
SSPUSHPTR(ptr);
- SSPUSHINT(type);
+ SSPUSHUV(type);
}
void
SSPUSHPTR(SvREFCNT_inc_simple_NN(PL_curpad[off]));
SSPUSHPTR(PL_comppad);
SSPUSHLONG((long)off);
- SSPUSHINT(SAVEt_PADSV_AND_MORTALIZE);
+ SSPUSHUV(SAVEt_PADSV_AND_MORTALIZE);
}
void
dVAR;
SSCHECK(2);
SSPUSHPTR(ptr);
- SSPUSHINT(type);
+ SSPUSHUV(type);
}
void
Perl_save_clearsv(pTHX_ SV **svp)
{
dVAR;
+ const UV offset = svp - PL_curpad;
+ const UV offset_shifted = offset << SAVE_TIGHT_SHIFT;
PERL_ARGS_ASSERT_SAVE_CLEARSV;
ASSERT_CURPAD_ACTIVE("save_clearsv");
- SSCHECK(2);
- SSPUSHLONG((long)(svp-PL_curpad));
- SSPUSHINT(SAVEt_CLEARSV);
+ if ((offset_shifted >> SAVE_TIGHT_SHIFT) != offset)
+ Perl_croak(aTHX_ "panic: pad offset %"UVuf" out of range (%p-%p)",
+ offset, svp, PL_curpad);
+
+ SSCHECK(1);
+ SSPUSHUV(offset_shifted | SAVEt_CLEARSV);
SvPADSTALE_off(*svp); /* mark lexical as active */
}
}
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;
SSCHECK(3);
SSPUSHDPTR(f);
SSPUSHPTR(p);
- SSPUSHINT(SAVEt_DESTRUCTOR);
+ SSPUSHUV(SAVEt_DESTRUCTOR);
}
void
SSCHECK(3);
SSPUSHDXPTR(f);
SSPUSHPTR(p);
- SSPUSHINT(SAVEt_DESTRUCTOR_X);
+ SSPUSHUV(SAVEt_DESTRUCTOR_X);
}
void
SSPUSHPTR(ptr1);
SSPUSHINT(i);
SSPUSHPTR(ptr2);
- SSPUSHINT(type);
+ SSPUSHUV(type);
}
void
if (!AvREAL(av) && AvREIFY(av))
SvREFCNT_inc_void(*sptr);
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
* reaped when the localize ends. Ensure it gets reaped by
* mortifying it instead. DAPM */
- if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
+ if (SvTIED_mg((const SV *)av, PERL_MAGIC_tied))
sv_2mortal(sv);
}
SSPUSHPTR(SvREFCNT_inc_simple(hv));
SSPUSHPTR(newSVsv(key));
SSPUSHPTR(SvREFCNT_inc(*sptr));
- SSPUSHINT(SAVEt_HELEM);
+ SSPUSHUV(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
* reaped when the localize ends. Ensure it gets reaped by
* mortifying it instead. DAPM */
- if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
+ if (SvTIED_mg((const SV *)hv, PERL_MAGIC_tied))
sv_2mortal(sv);
}
PL_savestack_ix += elems;
SSPUSHINT(elems);
- SSPUSHINT(SAVEt_ALLOC);
+ SSPUSHUV(SAVEt_ALLOC);
return start;
}
if (base < -1)
Perl_croak(aTHX_ "panic: corrupt saved stack index");
+ DEBUG_l(Perl_deb(aTHX_ "savestack: releasing items %ld -> %ld\n",
+ (long)PL_savestack_ix, (long)base));
while (PL_savestack_ix > base) {
+ UV uv = SSPOPUV;
+ const U8 type = (U8)uv & SAVE_MASK;
TAINT_NOT;
- switch (SSPOPINT) {
+ switch (type) {
case SAVEt_ITEM: /* normal string */
value = MUTABLE_SV(SSPOPPTR);
sv = MUTABLE_SV(SSPOPPTR);
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;
break;
case SAVEt_BOOL: /* bool reference */
ptr = SSPOPPTR;
- *(bool*)ptr = (bool)SSPOPBOOL;
+ *(bool*)ptr = cBOOL(SSPOPBOOL);
break;
case SAVEt_I32: /* I32 reference */
ptr = SSPOPPTR;
*(AV**)ptr = MUTABLE_AV(SSPOPPTR);
break;
case SAVEt_GP: /* scalar reference */
- ptr = SSPOPPTR;
gv = MUTABLE_GV(SSPOPPTR);
gp_free(gv);
- GvGP(gv) = (GP*)ptr;
+ GvGP(gv) = (GP*)SSPOPPTR;
+ if (SSPOPINT)
+ SvFAKE_on(gv);
/* putting a method back into circulation ("local")*/
if (GvCVu(gv) && (hv=GvSTASH(gv)) && HvNAME_get(hv))
mro_method_changed_in(hv);
Safefree(ptr);
break;
case SAVEt_CLEARSV:
- ptr = (void*)&PL_curpad[SSPOPLONG];
+ ptr = (void*)&PL_curpad[uv >> SAVE_TIGHT_SHIFT];
sv = *(SV**)ptr;
DEBUG_Xv(PerlIO_printf(Perl_debug_log,
}
PL_tainted = was;
+
+ PERL_ASYNC_CHECK();
}
void