dVAR;
const IV old_max = cxstack_max;
cxstack_max = GROW(cxstack_max);
- Renew(cxstack, cxstack_max + 1, PERL_CONTEXT); /* XXX should fix CXINC macro */
+ Renew(cxstack, cxstack_max + 1, PERL_CONTEXT);
/* Without any kind of initialising deep enough recursion
* will end up reading uninitialised PERL_CONTEXTs. */
PoisonNew(cxstack + old_max + 1, cxstack_max - old_max, PERL_CONTEXT);
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;
}
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);
PERL_ARGS_ASSERT_SAVE_BOOL;
- SSCHECK(3);
- SSPUSHBOOL(*boolp);
+ SSCHECK(2);
SSPUSHPTR(boolp);
- SSPUSHINT(SAVEt_BOOL);
+ SSPUSHUV(SAVEt_BOOL | (*boolp << 8));
}
void
SSCHECK(3);
SSPUSHINT(i);
SSPUSHPTR(ptr);
- SSPUSHINT(type);
+ SSPUSHUV(type);
}
void
Perl_save_int(pTHX_ int *intp)
{
dVAR;
+ const UV shifted = (UV)*intp << SAVE_TIGHT_SHIFT;
PERL_ARGS_ASSERT_SAVE_INT;
- save_pushi32ptr(*intp, intp, SAVEt_INT);
+ if ((int)(shifted >> SAVE_TIGHT_SHIFT) == *intp) {
+ SSCHECK(2);
+ SSPUSHPTR(intp);
+ SSPUSHUV(SAVEt_INT_SMALL | shifted);
+ } else
+ save_pushi32ptr(*intp, intp, SAVEt_INT);
}
void
PERL_ARGS_ASSERT_SAVE_I8;
- save_pushi32ptr(*bytep, bytep, SAVEt_I8);
+ SSCHECK(2);
+ SSPUSHPTR(bytep);
+ SSPUSHUV(SAVEt_I8 | ((UV)*bytep << 8));
}
void
PERL_ARGS_ASSERT_SAVE_I16;
- save_pushi32ptr(*intp, intp, SAVEt_I16);
+ SSCHECK(2);
+ SSPUSHPTR(intp);
+ SSPUSHUV(SAVEt_I16 | ((UV)*intp << 8));
}
void
Perl_save_I32(pTHX_ I32 *intp)
{
dVAR;
+ const UV shifted = (UV)*intp << SAVE_TIGHT_SHIFT;
PERL_ARGS_ASSERT_SAVE_I32;
- save_pushi32ptr(*intp, intp, SAVEt_I32);
+ if ((I32)(shifted >> SAVE_TIGHT_SHIFT) == *intp) {
+ SSCHECK(2);
+ SSPUSHPTR(intp);
+ SSPUSHUV(SAVEt_I32_SMALL | shifted);
+ } else
+ save_pushi32ptr(*intp, intp, SAVEt_I32);
}
/* Cannot use save_sptr() to store a char* since the SV** cast will
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 */
}
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
* 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;
* 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);
}
dVAR;
register const I32 start = pad + ((char*)&PL_savestack[PL_savestack_ix]
- (char*)PL_savestack);
- register const I32 elems = 1 + ((size + pad - 1) / sizeof(*PL_savestack));
+ const UV elems = 1 + ((size + pad - 1) / sizeof(*PL_savestack));
+ const UV elems_shifted = elems << SAVE_TIGHT_SHIFT;
+
+ if ((elems_shifted >> SAVE_TIGHT_SHIFT) != elems)
+ Perl_croak(aTHX_ "panic: save_alloc elems %"UVuf" out of range (%ld-%ld)",
+ elems, size, pad);
- SSGROW(elems + 2);
+ SSGROW(elems + 1);
PL_savestack_ix += elems;
- SSPUSHINT(elems);
- SSPUSHINT(SAVEt_ALLOC);
+ SSPUSHUV(SAVEt_ALLOC | elems_shifted);
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;
PL_localizing = 0;
}
break;
+ case SAVEt_INT_SMALL:
+ ptr = SSPOPPTR;
+ *(int*)ptr = (int)(uv >> SAVE_TIGHT_SHIFT);
+ break;
case SAVEt_INT: /* int reference */
ptr = SSPOPPTR;
*(int*)ptr = (int)SSPOPINT;
break;
case SAVEt_BOOL: /* bool reference */
ptr = SSPOPPTR;
- *(bool*)ptr = (bool)SSPOPBOOL;
+ *(bool*)ptr = cBOOL(uv >> 8);
+ break;
+ case SAVEt_I32_SMALL:
+ ptr = SSPOPPTR;
+ *(I32*)ptr = (I32)(uv >> SAVE_TIGHT_SHIFT);
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,
(*SSPOPDXPTR)(aTHX_ ptr);
break;
case SAVEt_REGCONTEXT:
+ /* regexp must have croaked */
case SAVEt_ALLOC:
- i = SSPOPINT;
- PL_savestack_ix -= i; /* regexp must have croaked */
+ PL_savestack_ix -= uv >> SAVE_TIGHT_SHIFT;
break;
case SAVEt_STACK_POS: /* Position on Perl stack */
i = SSPOPINT;
case SAVEt_I16: /* I16 reference */
ptr = SSPOPPTR;
- *(I16*)ptr = (I16)SSPOPINT;
+ *(I16*)ptr = (I16)(uv >> 8);
break;
case SAVEt_I8: /* I8 reference */
ptr = SSPOPPTR;
- *(I8*)ptr = (I8)SSPOPINT;
+ *(I8*)ptr = (I8)(uv >> 8);
break;
case SAVEt_DESTRUCTOR:
ptr = SSPOPPTR;
}
PL_tainted = was;
+
+ PERL_ASYNC_CHECK();
}
void