summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2012-11-25 23:08:11 +0000
committerDavid Mitchell <davem@iabyn.com>2012-12-04 10:22:20 +0000
commit03dba56127506a6979ee0298da57d71840dee39d (patch)
tree9ea5b5599689de08be766807e2adba6105d1dc59
parentd172696c35223548e4cde3868d91bd72b7c7c195 (diff)
downloadperl-03dba56127506a6979ee0298da57d71840dee39d.tar.gz
refactor Perl_leave_scope
This is a large and hot function. The main problem with it is that there is code to pop a few args repeated in just about every branch. Also, there are a whole bunch of local vars (sv, av, hv, gv etc) that are never all used simultaneously, but are really just there for casting convenience. Together, they defeat the compiler's register allocation algorithms (well, they did for gcc anyway). We fix this by just declaring three general vars, arg0,1,2 of type ANY, and move the popping code to above the switch(). We sort the SAVEt_* indices in order of number of args, so it's quick to determine how many args we need to pop for a particular type. Together with the previous commits which added the SS_ADD_* macros, this reduces the size of scope.o (-O2, gcc x86_64) by about 9% (threaded) or 17% (unthreaded), and seems to speed up simple loops / function calls by around 5%.
-rw-r--r--scope.c400
-rw-r--r--scope.h123
2 files changed, 267 insertions, 256 deletions
diff --git a/scope.c b/scope.c
index c11ce03dcc..f9d94c3c6f 100644
--- a/scope.c
+++ b/scope.c
@@ -497,7 +497,7 @@ Perl_save_padsv_and_mortalize(pTHX_ PADOFFSET off)
ASSERT_CURPAD_ACTIVE("save_padsv");
SS_ADD_PTR(SvREFCNT_inc_simple_NN(PL_curpad[off]));
SS_ADD_PTR(PL_comppad);
- SS_ADD_LONG((long)off);
+ SS_ADD_UV((UV)off);
SS_ADD_UV(SAVEt_PADSV_AND_MORTALIZE);
SS_ADD_END(4);
}
@@ -732,226 +732,257 @@ Perl_save_alloc(pTHX_ I32 size, I32 pad)
return start;
}
+
+
+#define ARG0_SV MUTABLE_SV(arg0.any_ptr)
+#define ARG0_AV MUTABLE_AV(arg0.any_ptr)
+#define ARG0_HV MUTABLE_HV(arg0.any_ptr)
+#define ARG0_PTR arg0.any_ptr
+#define ARG0_PV (char*)(arg0.any_ptr)
+#define ARG0_PVP (char**)(arg0.any_ptr)
+#define ARG0_I32 (arg0.any_i32)
+
+#define ARG1_SV MUTABLE_SV(arg1.any_ptr)
+#define ARG1_AV MUTABLE_AV(arg1.any_ptr)
+#define ARG1_GV MUTABLE_GV(arg1.any_ptr)
+#define ARG1_SVP (SV**)(arg1.any_ptr)
+#define ARG1_PVP (char**)(arg1.any_ptr)
+#define ARG1_PTR arg1.any_ptr
+#define ARG1_PV (char*)(arg1.any_ptr)
+#define ARG1_I32 (arg1.any_i32)
+
+#define ARG2_SV MUTABLE_SV(arg2.any_ptr)
+#define ARG2_AV MUTABLE_AV(arg2.any_ptr)
+#define ARG2_HV MUTABLE_HV(arg2.any_ptr)
+#define ARG2_GV MUTABLE_GV(arg2.any_ptr)
+#define ARG2_PV (char*)(arg2.any_ptr)
+
void
Perl_leave_scope(pTHX_ I32 base)
{
dVAR;
- SV *sv;
- SV *value;
- GV *gv;
- AV *av;
- HV *hv;
- void* ptr;
- char* str;
- I32 i;
+
/* Localise the effects of the TAINT_NOT inside the loop. */
bool was = TAINT_get;
+ ANY arg0, arg1, arg2;
+
+ /* these initialisations are logically unnecessary, but they shut up
+ * spurious 'may be used uninitialized' compiler warnings */
+ arg0.any_ptr = NULL;
+ arg1.any_ptr = NULL;
+ arg2.any_ptr = NULL;
+
if (base < -1)
Perl_croak(aTHX_ "panic: corrupt saved stack index %ld", (long) base);
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;
+ UV uv;
+ U8 type;
+
+ SV *refsv;
+ SV **svp;
+
TAINT_NOT;
+ {
+ I32 ix = PL_savestack_ix - 1;
+ ANY *p = &PL_savestack[ix];
+ uv = p->any_uv;
+ type = (U8)uv & SAVE_MASK;
+ if (type > SAVEt_ARG0_MAX) {
+ ANY *p0 = p;
+ arg0 = *--p;
+ if (type > SAVEt_ARG1_MAX) {
+ arg1 = *--p;
+ if (type > SAVEt_ARG2_MAX) {
+ arg2 = *--p;
+ }
+ }
+ ix -= (p0 - p);
+ }
+ PL_savestack_ix = ix;
+ }
+
switch (type) {
case SAVEt_ITEM: /* normal string */
- value = MUTABLE_SV(SSPOPPTR);
- sv = MUTABLE_SV(SSPOPPTR);
- sv_replace(sv,value);
+ sv_replace(ARG1_SV, ARG0_SV);
PL_localizing = 2;
- SvSETMAGIC(sv);
+ SvSETMAGIC(ARG1_SV);
PL_localizing = 0;
break;
+
+ /* This would be a mathom, but Perl_save_svref() calls a static
+ function, S_save_scalar_at(), so has to stay in this file. */
+ case SAVEt_SVREF: /* scalar reference */
+ svp = ARG1_SVP;
+ refsv = NULL; /* what to refcnt_dec */
+ goto restore_sv;
+
case SAVEt_SV: /* scalar reference */
- value = MUTABLE_SV(SSPOPPTR);
- gv = MUTABLE_GV(SSPOPPTR);
- ptr = &GvSV(gv);
- av = MUTABLE_AV(gv); /* what to refcnt_dec */
+ svp = &GvSV(ARG1_GV);
+ refsv = ARG1_SV; /* what to refcnt_dec */
restore_sv:
- sv = *(SV**)ptr;
- *(SV**)ptr = value;
+ {
+ SV * const sv = *svp;
+ *svp = ARG0_SV;
SvREFCNT_dec(sv);
PL_localizing = 2;
- SvSETMAGIC(value);
+ SvSETMAGIC(ARG0_SV);
PL_localizing = 0;
- SvREFCNT_dec(value);
- SvREFCNT_dec(av); /* av may actually be an AV, HV or GV */
+ SvREFCNT_dec(ARG0_SV);
+ SvREFCNT_dec(refsv);
break;
+ }
case SAVEt_GENERIC_PVREF: /* generic pv */
- ptr = SSPOPPTR;
- str = (char*)SSPOPPTR;
- if (*(char**)ptr != str) {
- Safefree(*(char**)ptr);
- *(char**)ptr = str;
+ if (*ARG0_PVP != ARG1_PV) {
+ Safefree(*ARG0_PVP);
+ *ARG0_PVP = ARG1_PV;
}
break;
case SAVEt_SHARED_PVREF: /* shared pv */
- str = (char*)SSPOPPTR;
- ptr = SSPOPPTR;
- if (*(char**)ptr != str) {
+ if (*ARG1_PVP != ARG0_PV) {
#ifdef NETWARE
- PerlMem_free(*(char**)ptr);
+ PerlMem_free(*ARG1_PVP);
#else
- PerlMemShared_free(*(char**)ptr);
+ PerlMemShared_free(*ARG1_PVP);
#endif
- *(char**)ptr = str;
+ *ARG1_PVP = ARG0_PV;
}
break;
case SAVEt_GVSV: /* scalar slot in GV */
- value = MUTABLE_SV(SSPOPPTR);
- gv = MUTABLE_GV(SSPOPPTR);
- ptr = &GvSV(gv);
+ svp = &GvSV(ARG1_GV);
goto restore_svp;
case SAVEt_GENERIC_SVREF: /* generic sv */
- value = MUTABLE_SV(SSPOPPTR);
- ptr = SSPOPPTR;
+ svp = ARG1_SVP;
restore_svp:
- sv = *(SV**)ptr;
- *(SV**)ptr = value;
+ {
+ SV * const sv = *svp;
+ *svp = ARG0_SV;
SvREFCNT_dec(sv);
- SvREFCNT_dec(value);
+ SvREFCNT_dec(ARG0_SV);
break;
+ }
case SAVEt_GVSLOT: /* any slot in GV */
- value = MUTABLE_SV(SSPOPPTR);
- ptr = SSPOPPTR;
- gv = MUTABLE_GV(SSPOPPTR);
- hv = GvSTASH(gv);
+ {
+ HV *const hv = GvSTASH(ARG2_GV);
+ svp = ARG1_SVP;
if (hv && HvENAME(hv) && (
- (value && SvTYPE(value) == SVt_PVCV)
- || (*(SV **)ptr && SvTYPE(*(SV**)ptr) == SVt_PVCV)
+ (ARG0_SV && SvTYPE(ARG0_SV) == SVt_PVCV)
+ || (*svp && SvTYPE(*svp) == SVt_PVCV)
))
{
- if ((char *)ptr < (char *)GvGP(gv)
- || (char *)ptr > (char *)GvGP(gv) + sizeof(struct gp)
- || GvREFCNT(gv) > 1)
+ if ((char *)svp < (char *)GvGP(ARG2_GV)
+ || (char *)svp > (char *)GvGP(ARG2_GV) + sizeof(struct gp)
+ || GvREFCNT(ARG2_GV) > 1)
PL_sub_generation++;
else mro_method_changed_in(hv);
}
goto restore_svp;
+ }
case SAVEt_AV: /* array reference */
- av = MUTABLE_AV(SSPOPPTR);
- gv = MUTABLE_GV(SSPOPPTR);
- SvREFCNT_dec(GvAV(gv));
- GvAV(gv) = av;
- if (SvMAGICAL(av)) {
+ SvREFCNT_dec(GvAV(ARG1_GV));
+ GvAV(ARG1_GV) = ARG0_AV;
+ if (SvMAGICAL(ARG0_AV)) {
PL_localizing = 2;
- SvSETMAGIC(MUTABLE_SV(av));
+ SvSETMAGIC(MUTABLE_SV(ARG0_AV));
PL_localizing = 0;
}
- SvREFCNT_dec(gv);
+ SvREFCNT_dec(ARG1_GV);
break;
case SAVEt_HV: /* hash reference */
- hv = MUTABLE_HV(SSPOPPTR);
- gv = MUTABLE_GV(SSPOPPTR);
- SvREFCNT_dec(GvHV(gv));
- GvHV(gv) = hv;
- if (SvMAGICAL(hv)) {
+ SvREFCNT_dec(GvHV(ARG1_GV));
+ GvHV(ARG1_GV) = ARG0_HV;
+ if (SvMAGICAL(ARG0_HV)) {
PL_localizing = 2;
- SvSETMAGIC(MUTABLE_SV(hv));
+ SvSETMAGIC(MUTABLE_SV(ARG0_HV));
PL_localizing = 0;
}
- SvREFCNT_dec(gv);
+ SvREFCNT_dec(ARG1_GV);
break;
case SAVEt_INT_SMALL:
- ptr = SSPOPPTR;
- *(int*)ptr = (int)(uv >> SAVE_TIGHT_SHIFT);
+ *(int*)ARG0_PTR = (int)(uv >> SAVE_TIGHT_SHIFT);
break;
case SAVEt_INT: /* int reference */
- ptr = SSPOPPTR;
- *(int*)ptr = (int)SSPOPINT;
+ *(int*)ARG0_PTR = (int)ARG1_I32;
break;
case SAVEt_BOOL: /* bool reference */
- ptr = SSPOPPTR;
- *(bool*)ptr = cBOOL(uv >> 8);
+ *(bool*)ARG0_PTR = cBOOL(uv >> 8);
#if !NO_TAINT_SUPPORT
- if (ptr == &(TAINT_get)) {
+ if (ARG0_PTR == &(TAINT_get)) {
/* If we don't update <was>, to reflect what was saved on the
* stack for PL_tainted, then we will overwrite this attempt to
* restore it when we exit this routine. Note that this won't
* work if this value was saved in a wider-than necessary type,
* such as I32 */
- was = *(bool*)ptr;
+ was = *(bool*)ARG0_PTR;
}
#endif
break;
case SAVEt_I32_SMALL:
- ptr = SSPOPPTR;
- *(I32*)ptr = (I32)(uv >> SAVE_TIGHT_SHIFT);
+ *(I32*)ARG0_PTR = (I32)(uv >> SAVE_TIGHT_SHIFT);
break;
case SAVEt_I32: /* I32 reference */
- ptr = SSPOPPTR;
#ifdef PERL_DEBUG_READONLY_OPS
- {
- const I32 val = SSPOPINT;
- if (*(I32*)ptr != val)
- *(I32*)ptr = val;
- }
-#else
- *(I32*)ptr = (I32)SSPOPINT;
+ if (*(I32*)ARG0_PTR != ARG1_I32)
#endif
+ *(I32*)ARG0_PTR = ARG1_I32;
break;
case SAVEt_SPTR: /* SV* reference */
- ptr = SSPOPPTR;
- *(SV**)ptr = MUTABLE_SV(SSPOPPTR);
+ *(SV**)(ARG0_PTR)= ARG1_SV;
break;
case SAVEt_VPTR: /* random* reference */
case SAVEt_PPTR: /* char* reference */
- ptr = SSPOPPTR;
- *(char**)ptr = (char*)SSPOPPTR;
+ *ARG0_PVP = ARG1_PV;
break;
case SAVEt_HPTR: /* HV* reference */
- ptr = SSPOPPTR;
- *(HV**)ptr = MUTABLE_HV(SSPOPPTR);
+ *(HV**)ARG0_PTR = MUTABLE_HV(ARG1_PTR);
break;
case SAVEt_APTR: /* AV* reference */
- ptr = SSPOPPTR;
- *(AV**)ptr = MUTABLE_AV(SSPOPPTR);
+ *(AV**)ARG0_PTR = ARG1_AV;
break;
case SAVEt_GP: /* scalar reference */
- ptr = SSPOPPTR;
- gv = MUTABLE_GV(SSPOPPTR);
- {
- /* possibly taking a method out of circulation */
- const bool had_method = !!GvCVu(gv);
- gp_free(gv);
- GvGP_set(gv, (GP*)ptr);
- if ((hv=GvSTASH(gv)) && HvENAME_get(hv)) {
- if (GvNAMELEN(gv) == 3 && strnEQ(GvNAME(gv), "ISA", 3))
- mro_isa_changed_in(hv);
- else if (had_method || GvCVu(gv))
- /* putting a method back into circulation ("local")*/
- gv_method_changed(gv);
- }
+ {
+ HV *hv;
+ /* possibly taking a method out of circulation */
+ const bool had_method = !!GvCVu(ARG1_GV);
+ gp_free(ARG1_GV);
+ GvGP_set(ARG1_GV, (GP*)ARG0_PTR);
+ if ((hv=GvSTASH(ARG1_GV)) && HvENAME_get(hv)) {
+ if ( GvNAMELEN(ARG1_GV) == 3
+ && strnEQ(GvNAME(ARG1_GV), "ISA", 3)
+ )
+ mro_isa_changed_in(hv);
+ else if (had_method || GvCVu(ARG1_GV))
+ /* putting a method back into circulation ("local")*/
+ gv_method_changed(ARG1_GV);
}
- SvREFCNT_dec(gv);
+ SvREFCNT_dec(ARG1_GV);
break;
+ }
case SAVEt_FREESV:
- ptr = SSPOPPTR;
- SvREFCNT_dec(MUTABLE_SV(ptr));
+ SvREFCNT_dec(ARG0_SV);
break;
case SAVEt_FREECOPHH:
- ptr = SSPOPPTR;
- cophh_free((COPHH *)ptr);
+ cophh_free((COPHH *)ARG0_PTR);
break;
case SAVEt_MORTALIZESV:
- ptr = SSPOPPTR;
- sv_2mortal(MUTABLE_SV(ptr));
+ sv_2mortal(ARG0_SV);
break;
case SAVEt_FREEOP:
- ptr = SSPOPPTR;
ASSERT_CURPAD_LEGAL("SAVEt_FREEOP");
- op_free((OP*)ptr);
+ op_free((OP*)ARG0_PTR);
break;
case SAVEt_FREEPV:
- ptr = SSPOPPTR;
- Safefree(ptr);
+ Safefree(ARG0_PTR);
break;
{
SV **svp;
+ I32 i;
+ SV *sv;
+
case SAVEt_CLEARPADRANGE:
i = (I32)((uv >> SAVE_TIGHT_SHIFT) & OPpPADRANGE_COUNTMASK);
svp = &PL_curpad[uv >>
@@ -1045,24 +1076,16 @@ Perl_leave_scope(pTHX_ I32 base)
break;
}
case SAVEt_DELETE:
- ptr = SSPOPPTR;
- hv = MUTABLE_HV(ptr);
- i = SSPOPINT;
- ptr = SSPOPPTR;
- (void)hv_delete(hv, (char*)ptr, i, G_DISCARD);
- SvREFCNT_dec(hv);
- Safefree(ptr);
+ (void)hv_delete(ARG0_HV, ARG2_PV, ARG1_I32, G_DISCARD);
+ SvREFCNT_dec(ARG0_HV);
+ Safefree(arg2.any_ptr);
break;
case SAVEt_ADELETE:
- ptr = SSPOPPTR;
- av = MUTABLE_AV(ptr);
- i = SSPOPINT;
- (void)av_delete(av, i, G_DISCARD);
- SvREFCNT_dec(av);
+ (void)av_delete(ARG0_AV, ARG1_I32, G_DISCARD);
+ SvREFCNT_dec(ARG0_AV);
break;
case SAVEt_DESTRUCTOR_X:
- ptr = SSPOPPTR;
- (*SSPOPDXPTR)(aTHX_ ptr);
+ (*arg1.any_dxptr)(aTHX_ ARG0_PTR);
break;
case SAVEt_REGCONTEXT:
/* regexp must have croaked */
@@ -1070,52 +1093,47 @@ Perl_leave_scope(pTHX_ I32 base)
PL_savestack_ix -= uv >> SAVE_TIGHT_SHIFT;
break;
case SAVEt_STACK_POS: /* Position on Perl stack */
- i = SSPOPINT;
- PL_stack_sp = PL_stack_base + i;
+ PL_stack_sp = PL_stack_base + arg0.any_i32;
break;
case SAVEt_STACK_CXPOS: /* blk_oldsp on context stack */
- i = SSPOPINT;
- cxstack[i].blk_oldsp = SSPOPINT;
+ cxstack[ARG0_I32].blk_oldsp = ARG1_I32;
break;
case SAVEt_AELEM: /* array element */
- value = MUTABLE_SV(SSPOPPTR);
- i = SSPOPINT;
- av = MUTABLE_AV(SSPOPPTR);
- ptr = av_fetch(av,i,1);
- if (!AvREAL(av) && AvREIFY(av)) /* undo reify guard */
- SvREFCNT_dec(value);
- if (ptr) {
- sv = *(SV**)ptr;
+ svp = av_fetch(ARG2_AV, ARG1_I32, 1);
+ if (!AvREAL(ARG2_AV) && AvREIFY(ARG2_AV)) /* undo reify guard */
+ SvREFCNT_dec(ARG0_SV);
+ if (svp) {
+ SV * const sv = *svp;
if (sv && sv != &PL_sv_undef) {
- if (SvTIED_mg((const SV *)av, PERL_MAGIC_tied))
+ if (SvTIED_mg((const SV *)ARG2_AV, PERL_MAGIC_tied))
SvREFCNT_inc_void_NN(sv);
+ refsv = ARG2_SV;
goto restore_sv;
}
}
- SvREFCNT_dec(av);
- SvREFCNT_dec(value);
+ SvREFCNT_dec(ARG2_AV);
+ SvREFCNT_dec(ARG0_SV);
break;
case SAVEt_HELEM: /* hash element */
- value = MUTABLE_SV(SSPOPPTR);
- 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);
+ {
+ HE * const he = hv_fetch_ent(ARG2_HV, ARG1_SV, 1, 0);
+ SvREFCNT_dec(ARG1_SV);
+ if (he) {
+ const SV * const oval = HeVAL(he);
if (oval && oval != &PL_sv_undef) {
- ptr = &HeVAL((HE*)ptr);
- if (SvTIED_mg((const SV *)hv, PERL_MAGIC_tied))
- SvREFCNT_inc_void(*(SV**)ptr);
- av = MUTABLE_AV(hv); /* what to refcnt_dec */
+ svp = &HeVAL(he);
+ if (SvTIED_mg((const SV *)ARG2_HV, PERL_MAGIC_tied))
+ SvREFCNT_inc_void(*svp);
+ refsv = ARG2_SV; /* what to refcnt_dec */
goto restore_sv;
}
}
- SvREFCNT_dec(hv);
- SvREFCNT_dec(value);
+ SvREFCNT_dec(ARG2_HV);
+ SvREFCNT_dec(ARG0_SV);
break;
+ }
case SAVEt_OP:
- PL_op = (OP*)SSPOPPTR;
+ PL_op = (OP*)ARG0_PTR;
break;
case SAVEt_HINTS:
if ((PL_hints & HINT_LOCALIZE_HH)) {
@@ -1126,8 +1144,8 @@ Perl_leave_scope(pTHX_ I32 base)
}
}
cophh_free(CopHINTHASH_get(&PL_compiling));
- CopHINTHASH_set(&PL_compiling, (COPHH*)SSPOPPTR);
- *(I32*)&PL_hints = (I32)SSPOPINT;
+ CopHINTHASH_set(&PL_compiling, (COPHH*)ARG0_PTR);
+ *(I32*)&PL_hints = ARG1_I32;
if (PL_hints & HINT_LOCALIZE_HH) {
SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
GvHV(PL_hintgv) = MUTABLE_HV(SSPOPPTR);
@@ -1142,7 +1160,7 @@ Perl_leave_scope(pTHX_ I32 base)
assert(GvHV(PL_hintgv));
break;
case SAVEt_COMPPAD:
- PL_comppad = (PAD*)SSPOPPTR;
+ PL_comppad = (PAD*)ARG0_PTR;
if (PL_comppad)
PL_curpad = AvARRAY(PL_comppad);
else
@@ -1150,78 +1168,53 @@ Perl_leave_scope(pTHX_ I32 base)
break;
case SAVEt_PADSV_AND_MORTALIZE:
{
- const PADOFFSET off = (PADOFFSET)SSPOPLONG;
SV **svp;
- ptr = SSPOPPTR;
- assert (ptr);
- svp = AvARRAY((PAD*)ptr) + off;
+ assert (ARG1_PTR);
+ svp = AvARRAY((PAD*)ARG1_PTR) + (PADOFFSET)arg0.any_uv;
/* This mortalizing used to be done by POPLOOP() via itersave.
But as we have all the information here, we can do it here,
save even having to have itersave in the struct. */
sv_2mortal(*svp);
- *svp = MUTABLE_SV(SSPOPPTR);
+ *svp = ARG2_SV;
}
break;
case SAVEt_SAVESWITCHSTACK:
{
dSP;
- AV *const t = MUTABLE_AV(SSPOPPTR);
- AV *const f = MUTABLE_AV(SSPOPPTR);
- SWITCHSTACK(t,f);
- PL_curstackinfo->si_stack = f;
+ SWITCHSTACK(ARG0_AV, ARG1_AV);
+ PL_curstackinfo->si_stack = ARG1_AV;
}
break;
case SAVEt_SET_SVFLAGS:
- {
- const U32 val = (U32)SSPOPINT;
- const U32 mask = (U32)SSPOPINT;
- sv = MUTABLE_SV(SSPOPPTR);
- SvFLAGS(sv) &= ~mask;
- SvFLAGS(sv) |= val;
- }
+ SvFLAGS(ARG2_SV) &= ~((U32)ARG1_I32);
+ SvFLAGS(ARG2_SV) |= (U32)ARG0_I32;
break;
- /* This would be a mathom, but Perl_save_svref() calls a static
- function, S_save_scalar_at(), so has to stay in this file. */
- case SAVEt_SVREF: /* scalar reference */
- value = MUTABLE_SV(SSPOPPTR);
- ptr = SSPOPPTR;
- av = NULL; /* what to refcnt_dec */
- goto restore_sv;
-
/* These are only saved in mathoms.c */
case SAVEt_NSTAB:
- gv = MUTABLE_GV(SSPOPPTR);
- (void)sv_clear(MUTABLE_SV(gv));
+ (void)sv_clear(ARG0_SV);
break;
case SAVEt_LONG: /* long reference */
- ptr = SSPOPPTR;
- *(long*)ptr = (long)SSPOPLONG;
+ *(long*)ARG0_PTR = arg1.any_long;
break;
case SAVEt_IV: /* IV reference */
- ptr = SSPOPPTR;
- *(IV*)ptr = (IV)SSPOPIV;
+ *(IV*)ARG0_PTR = arg1.any_iv;
break;
case SAVEt_I16: /* I16 reference */
- ptr = SSPOPPTR;
- *(I16*)ptr = (I16)(uv >> 8);
+ *(I16*)ARG0_PTR = (I16)(uv >> 8);
break;
case SAVEt_I8: /* I8 reference */
- ptr = SSPOPPTR;
- *(I8*)ptr = (I8)(uv >> 8);
+ *(I8*)ARG0_PTR = (I8)(uv >> 8);
break;
case SAVEt_DESTRUCTOR:
- ptr = SSPOPPTR;
- (*SSPOPDPTR)(ptr);
+ (*arg1.any_dptr)(ARG0_PTR);
break;
case SAVEt_COMPILE_WARNINGS:
- ptr = SSPOPPTR;
-
if (!specialWARN(PL_compiling.cop_warnings))
PerlMemShared_free(PL_compiling.cop_warnings);
- PL_compiling.cop_warnings = (STRLEN*)ptr;
+ PL_compiling.cop_warnings = (STRLEN*)ARG0_PTR;
break;
case SAVEt_RE_STATE:
{
@@ -1238,8 +1231,7 @@ Perl_leave_scope(pTHX_ I32 base)
}
break;
case SAVEt_PARSER:
- ptr = SSPOPPTR;
- parser_free((yy_parser *) ptr);
+ parser_free((yy_parser *) ARG0_PTR);
break;
default:
Perl_croak(aTHX_ "panic: leave_scope inconsistency %u", type);
diff --git a/scope.h b/scope.h
index 5854850e4c..22c728d1be 100644
--- a/scope.h
+++ b/scope.h
@@ -8,58 +8,77 @@
*
*/
-#define SAVEt_ITEM 0
-#define SAVEt_SV 1
-#define SAVEt_AV 2
-#define SAVEt_HV 3
-#define SAVEt_INT 4
-#define SAVEt_LONG 5
-#define SAVEt_I32 6
-#define SAVEt_IV 7
-#define SAVEt_SPTR 8
-#define SAVEt_APTR 9
-#define SAVEt_HPTR 10
-#define SAVEt_PPTR 11
-#define SAVEt_NSTAB 12
-#define SAVEt_SVREF 13
-#define SAVEt_GP 14
-#define SAVEt_FREESV 15
-#define SAVEt_FREEOP 16
-#define SAVEt_FREEPV 17
-#define SAVEt_CLEARSV 18
-#define SAVEt_DELETE 19
-#define SAVEt_DESTRUCTOR 20
-#define SAVEt_REGCONTEXT 21
-#define SAVEt_STACK_POS 22
-#define SAVEt_I16 23
-#define SAVEt_AELEM 24
-#define SAVEt_HELEM 25
-#define SAVEt_OP 26
-#define SAVEt_HINTS 27
-#define SAVEt_ALLOC 28
-#define SAVEt_GENERIC_SVREF 29
-#define SAVEt_DESTRUCTOR_X 30
-#define SAVEt_VPTR 31
-#define SAVEt_I8 32
-#define SAVEt_COMPPAD 33
-#define SAVEt_GENERIC_PVREF 34
-#define SAVEt_PADSV_AND_MORTALIZE 35
-#define SAVEt_MORTALIZESV 36
-#define SAVEt_SHARED_PVREF 37
-#define SAVEt_BOOL 38
-#define SAVEt_SET_SVFLAGS 39
-#define SAVEt_SAVESWITCHSTACK 40
-#define SAVEt_RE_STATE 42
-#define SAVEt_COMPILE_WARNINGS 43
-#define SAVEt_STACK_CXPOS 44
-#define SAVEt_PARSER 45
-#define SAVEt_ADELETE 46
-#define SAVEt_I32_SMALL 47
-#define SAVEt_INT_SMALL 48
-#define SAVEt_GVSV 49
-#define SAVEt_FREECOPHH 50
-#define SAVEt_CLEARPADRANGE 51
-#define SAVEt_GVSLOT 52
+/* *** these are ordered by number of of auto-popped args */
+
+/* zero args */
+
+#define SAVEt_ALLOC 0
+#define SAVEt_CLEARPADRANGE 1
+#define SAVEt_CLEARSV 2
+#define SAVEt_REGCONTEXT 3
+#define SAVEt_RE_STATE 4
+
+#define SAVEt_ARG0_MAX 4
+
+/* one arg */
+
+#define SAVEt_BOOL 5
+#define SAVEt_COMPILE_WARNINGS 6
+#define SAVEt_COMPPAD 7
+#define SAVEt_FREECOPHH 8
+#define SAVEt_FREEOP 9
+#define SAVEt_FREEPV 10
+#define SAVEt_FREESV 11
+#define SAVEt_I16 12
+#define SAVEt_I32_SMALL 13
+#define SAVEt_I8 14
+#define SAVEt_INT_SMALL 15
+#define SAVEt_MORTALIZESV 16
+#define SAVEt_NSTAB 17
+#define SAVEt_OP 18
+#define SAVEt_PARSER 19
+#define SAVEt_STACK_POS 20
+
+#define SAVEt_ARG1_MAX 20
+
+/* two args */
+
+#define SAVEt_ADELETE 21
+#define SAVEt_APTR 22
+#define SAVEt_AV 23
+#define SAVEt_DESTRUCTOR 24
+#define SAVEt_DESTRUCTOR_X 25
+#define SAVEt_GENERIC_PVREF 26
+#define SAVEt_GENERIC_SVREF 27
+#define SAVEt_GP 28
+#define SAVEt_GVSV 29
+#define SAVEt_HINTS 30
+#define SAVEt_HPTR 31
+#define SAVEt_HV 32
+#define SAVEt_I32 33
+#define SAVEt_INT 34
+#define SAVEt_ITEM 35
+#define SAVEt_IV 36
+#define SAVEt_LONG 37
+#define SAVEt_PPTR 38
+#define SAVEt_SAVESWITCHSTACK 39
+#define SAVEt_SHARED_PVREF 40
+#define SAVEt_SPTR 41
+#define SAVEt_STACK_CXPOS 42
+#define SAVEt_SV 43
+#define SAVEt_SVREF 44
+#define SAVEt_VPTR 45
+
+#define SAVEt_ARG2_MAX 45
+
+/* three args */
+
+#define SAVEt_AELEM 46
+#define SAVEt_DELETE 47
+#define SAVEt_HELEM 48
+#define SAVEt_PADSV_AND_MORTALIZE 49
+#define SAVEt_SET_SVFLAGS 50
+#define SAVEt_GVSLOT 51
#define SAVEf_SETMAGIC 1
#define SAVEf_KEEPOLDELEM 2