summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2016-08-11 12:07:07 +0100
committerDavid Mitchell <davem@iabyn.com>2016-08-11 12:28:24 +0100
commit9a2fefd6ac80d3f6deaec2c6314b286ac7bb8e7e (patch)
treeda3b27558afb2eedf19523fcc51c5dd07090af38
parent403e0607fe50a0d1535b6f4223c24f97643cedbb (diff)
downloadperl-9a2fefd6ac80d3f6deaec2c6314b286ac7bb8e7e.tar.gz
leave_scope(): pop args in each branch
About 4 years ago I heavily refactored Perl_leave_scope(). One of the things I did was to pop the args for each action once at the top of the loop. This involved a number of nested condtionals. This commit makes each action (i.e. each switch branch) responsible for copying its own args off the save stack, while the top of loop is still responsible for decrementing PL_savestack_ix. The gain is marginal, but it makes the code cleaner and the object code smaller.
-rw-r--r--scope.c157
-rw-r--r--scope.h8
2 files changed, 128 insertions, 37 deletions
diff --git a/scope.c b/scope.c
index 408c6f3d25..a2d9709735 100644
--- a/scope.c
+++ b/scope.c
@@ -783,6 +783,63 @@ Perl_save_alloc(pTHX_ I32 size, I32 pad)
}
+static U8 arg_counts[] = {
+ 0, /* SAVEt_ALLOC */
+ 0, /* SAVEt_CLEARPADRANGE */
+ 0, /* SAVEt_CLEARSV */
+ 0, /* SAVEt_REGCONTEXT */
+ 1, /* SAVEt_TMPSFLOOR */
+ 1, /* SAVEt_BOOL */
+ 1, /* SAVEt_COMPILE_WARNINGS */
+ 1, /* SAVEt_COMPPAD */
+ 1, /* SAVEt_FREECOPHH */
+ 1, /* SAVEt_FREEOP */
+ 1, /* SAVEt_FREEPV */
+ 1, /* SAVEt_FREESV */
+ 1, /* SAVEt_I16 */
+ 1, /* SAVEt_I32_SMALL */
+ 1, /* SAVEt_I8 */
+ 1, /* SAVEt_INT_SMALL */
+ 1, /* SAVEt_MORTALIZESV */
+ 1, /* SAVEt_NSTAB */
+ 1, /* SAVEt_OP */
+ 1, /* SAVEt_PARSER */
+ 1, /* SAVEt_STACK_POS */
+ 1, /* SAVEt_READONLY_OFF */
+ 1, /* SAVEt_FREEPADNAME */
+ 2, /* SAVEt_AV */
+ 2, /* SAVEt_DESTRUCTOR */
+ 2, /* SAVEt_DESTRUCTOR_X */
+ 2, /* SAVEt_GENERIC_PVREF */
+ 2, /* SAVEt_GENERIC_SVREF */
+ 2, /* SAVEt_GP */
+ 2, /* SAVEt_GVSV */
+ 2, /* SAVEt_HINTS */
+ 2, /* SAVEt_HPTR */
+ 2, /* SAVEt_HV */
+ 2, /* SAVEt_I32 */
+ 2, /* SAVEt_INT */
+ 2, /* SAVEt_ITEM */
+ 2, /* SAVEt_IV */
+ 2, /* SAVEt_LONG */
+ 2, /* SAVEt_PPTR */
+ 2, /* SAVEt_SAVESWITCHSTACK */
+ 2, /* SAVEt_SHARED_PVREF */
+ 2, /* SAVEt_SPTR */
+ 2, /* SAVEt_STRLEN */
+ 2, /* SAVEt_SV */
+ 2, /* SAVEt_SVREF */
+ 2, /* SAVEt_VPTR */
+ 2, /* SAVEt_ADELETE */
+ 2, /* SAVEt_APTR */
+ 3, /* SAVEt_HELEM */
+ 3, /* SAVEt_PADSV_AND_MORTALIZE*/
+ 3, /* SAVEt_SET_SVFLAGS */
+ 3, /* SAVEt_GVSLOT */
+ 3, /* SAVEt_AELEM */
+ 3 /* SAVEt_DELETE */
+};
+
#define ARG0_SV MUTABLE_SV(arg0.any_ptr)
#define ARG0_AV MUTABLE_AV(arg0.any_ptr)
@@ -813,17 +870,6 @@ Perl_leave_scope(pTHX_ I32 base)
/* Localise the effects of the TAINT_NOT inside the loop. */
bool was = TAINT_get;
- I32 i;
- SV *sv;
-
- 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 (UNLIKELY(base < -1))
Perl_croak(aTHX_ "panic: corrupt saved stack index %ld", (long) base);
DEBUG_l(Perl_deb(aTHX_ "savestack: releasing items %ld -> %ld\n",
@@ -831,33 +877,29 @@ Perl_leave_scope(pTHX_ I32 base)
while (PL_savestack_ix > base) {
UV uv;
U8 type;
-
SV *refsv;
SV **svp;
+ I32 i;
+ ANY *ap; /* arg pointer */
+ ANY arg0, arg1, arg2;
TAINT_NOT;
{
+ U8 argcount;
I32 ix = PL_savestack_ix - 1;
- ANY *p = &PL_savestack[ix];
- uv = p->any_uv;
+
+ ap = &PL_savestack[ix];
+ uv = ap->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;
+ argcount = arg_counts[type];
+ PL_savestack_ix = ix - argcount;
+ ap -= argcount;
}
switch (type) {
case SAVEt_ITEM: /* normal string */
+ arg0 = ap[1]; arg1 = ap[0];
sv_replace(ARG1_SV, ARG0_SV);
if (UNLIKELY(SvSMAGICAL(ARG1_SV))) {
PL_localizing = 2;
@@ -869,11 +911,13 @@ Perl_leave_scope(pTHX_ I32 base)
/* 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 */
+ arg0 = ap[1]; arg1 = ap[0];
svp = ARG1_SVP;
refsv = NULL; /* what to refcnt_dec */
goto restore_sv;
case SAVEt_SV: /* scalar reference */
+ arg0 = ap[1]; arg1 = ap[0];
svp = &GvSV(ARG1_GV);
refsv = ARG1_SV; /* what to refcnt_dec */
restore_sv:
@@ -900,12 +944,14 @@ Perl_leave_scope(pTHX_ I32 base)
break;
}
case SAVEt_GENERIC_PVREF: /* generic pv */
+ arg0 = ap[1]; arg1 = ap[0];
if (*ARG0_PVP != ARG1_PV) {
Safefree(*ARG0_PVP);
*ARG0_PVP = ARG1_PV;
}
break;
case SAVEt_SHARED_PVREF: /* shared pv */
+ arg0 = ap[1]; arg1 = ap[0];
if (*ARG1_PVP != ARG0_PV) {
#ifdef NETWARE
PerlMem_free(*ARG1_PVP);
@@ -916,9 +962,11 @@ Perl_leave_scope(pTHX_ I32 base)
}
break;
case SAVEt_GVSV: /* scalar slot in GV */
+ arg0 = ap[1]; arg1 = ap[0];
svp = &GvSV(ARG1_GV);
goto restore_svp;
case SAVEt_GENERIC_SVREF: /* generic sv */
+ arg0 = ap[1]; arg1 = ap[0];
svp = ARG1_SVP;
restore_svp:
{
@@ -930,7 +978,9 @@ Perl_leave_scope(pTHX_ I32 base)
}
case SAVEt_GVSLOT: /* any slot in GV */
{
- HV *const hv = GvSTASH(ARG2_GV);
+ HV * hv;
+ arg0 = ap[2]; arg1 = ap[1]; arg2 = ap[0];
+ hv = GvSTASH(ARG2_GV);
svp = ARG1_SVP;
if (hv && HvENAME(hv) && (
(ARG0_SV && SvTYPE(ARG0_SV) == SVt_PVCV)
@@ -946,6 +996,7 @@ Perl_leave_scope(pTHX_ I32 base)
goto restore_svp;
}
case SAVEt_AV: /* array reference */
+ arg0 = ap[1]; arg1 = ap[0];
SvREFCNT_dec(GvAV(ARG1_GV));
GvAV(ARG1_GV) = ARG0_AV;
avhv_common:
@@ -963,23 +1014,29 @@ Perl_leave_scope(pTHX_ I32 base)
SvREFCNT_dec_NN(ARG1_GV);
break;
case SAVEt_HV: /* hash reference */
+ arg0 = ap[1]; arg1 = ap[0];
SvREFCNT_dec(GvHV(ARG1_GV));
GvHV(ARG1_GV) = ARG0_HV;
goto avhv_common;
case SAVEt_INT_SMALL:
+ arg0 = ap[0];
*(int*)ARG0_PTR = (int)(uv >> SAVE_TIGHT_SHIFT);
break;
case SAVEt_INT: /* int reference */
+ arg0 = ap[1]; arg1 = ap[0];
*(int*)ARG0_PTR = (int)ARG1_I32;
break;
case SAVEt_STRLEN: /* STRLEN/size_t ref */
+ arg0 = ap[1]; arg1 = ap[0];
*(STRLEN*)ARG0_PTR = (STRLEN)arg1.any_iv;
break;
case SAVEt_TMPSFLOOR: /* restore PL_tmps_floor */
+ arg0 = ap[0];
PL_tmps_floor = (SSize_t)arg0.any_iv;
break;
case SAVEt_BOOL: /* bool reference */
+ arg0 = ap[0];
*(bool*)ARG0_PTR = cBOOL(uv >> 8);
#ifdef NO_TAINT_SUPPORT
PERL_UNUSED_VAR(was);
@@ -995,32 +1052,41 @@ Perl_leave_scope(pTHX_ I32 base)
#endif
break;
case SAVEt_I32_SMALL:
+ arg0 = ap[0];
*(I32*)ARG0_PTR = (I32)(uv >> SAVE_TIGHT_SHIFT);
break;
case SAVEt_I32: /* I32 reference */
+ arg0 = ap[1]; arg1 = ap[0];
#ifdef PERL_DEBUG_READONLY_OPS
if (*(I32*)ARG0_PTR != ARG1_I32)
#endif
*(I32*)ARG0_PTR = ARG1_I32;
break;
case SAVEt_SPTR: /* SV* reference */
+ arg0 = ap[1]; arg1 = ap[0];
*(SV**)(ARG0_PTR)= ARG1_SV;
break;
case SAVEt_VPTR: /* random* reference */
case SAVEt_PPTR: /* char* reference */
+ arg0 = ap[1]; arg1 = ap[0];
*ARG0_PVP = ARG1_PV;
break;
case SAVEt_HPTR: /* HV* reference */
+ arg0 = ap[1]; arg1 = ap[0];
*(HV**)ARG0_PTR = MUTABLE_HV(ARG1_PTR);
break;
case SAVEt_APTR: /* AV* reference */
+ arg0 = ap[1]; arg1 = ap[0];
*(AV**)ARG0_PTR = ARG1_AV;
break;
case SAVEt_GP: /* scalar reference */
{
HV *hv;
+ bool had_method;
+
+ arg0 = ap[1]; arg1 = ap[0];
/* possibly taking a method out of circulation */
- const bool had_method = !!GvCVu(ARG1_GV);
+ had_method = !!GvCVu(ARG1_GV);
gp_free(ARG1_GV);
GvGP_set(ARG1_GV, (GP*)ARG0_PTR);
if ((hv=GvSTASH(ARG1_GV)) && HvENAME_get(hv)) {
@@ -1036,22 +1102,28 @@ Perl_leave_scope(pTHX_ I32 base)
break;
}
case SAVEt_FREESV:
+ arg0 = ap[0];
SvREFCNT_dec(ARG0_SV);
break;
case SAVEt_FREEPADNAME:
+ arg0 = ap[0];
PadnameREFCNT_dec((PADNAME *)ARG0_PTR);
break;
case SAVEt_FREECOPHH:
+ arg0 = ap[0];
cophh_free((COPHH *)ARG0_PTR);
break;
case SAVEt_MORTALIZESV:
+ arg0 = ap[0];
sv_2mortal(ARG0_SV);
break;
case SAVEt_FREEOP:
+ arg0 = ap[0];
ASSERT_CURPAD_LEGAL("SAVEt_FREEOP");
op_free((OP*)ARG0_PTR);
break;
case SAVEt_FREEPV:
+ arg0 = ap[0];
Safefree(ARG0_PTR);
break;
@@ -1065,7 +1137,7 @@ Perl_leave_scope(pTHX_ I32 base)
i = 1;
clearsv:
for (; i; i--, svp--) {
- sv = *svp;
+ SV *sv = *svp;
DEBUG_Xv(PerlIO_printf(Perl_debug_log,
"Pad 0x%"UVxf"[0x%"UVxf"] clearsv: %ld sv=0x%"UVxf"<%"IVdf"> %s\n",
@@ -1175,15 +1247,18 @@ Perl_leave_scope(pTHX_ I32 base)
}
break;
case SAVEt_DELETE:
+ arg0 = ap[2]; arg1 = ap[1]; arg2 = ap[0];
(void)hv_delete(ARG0_HV, ARG2_PV, ARG1_I32, G_DISCARD);
SvREFCNT_dec(ARG0_HV);
Safefree(arg2.any_ptr);
break;
case SAVEt_ADELETE:
+ arg0 = ap[1]; arg1 = ap[0];
(void)av_delete(ARG0_AV, arg1.any_iv, G_DISCARD);
SvREFCNT_dec(ARG0_AV);
break;
case SAVEt_DESTRUCTOR_X:
+ arg0 = ap[1]; arg1 = ap[0];
(*arg1.any_dxptr)(aTHX_ ARG0_PTR);
break;
case SAVEt_REGCONTEXT:
@@ -1192,9 +1267,11 @@ Perl_leave_scope(pTHX_ I32 base)
PL_savestack_ix -= uv >> SAVE_TIGHT_SHIFT;
break;
case SAVEt_STACK_POS: /* Position on Perl stack */
+ arg0 = ap[0];
PL_stack_sp = PL_stack_base + arg0.any_i32;
break;
case SAVEt_AELEM: /* array element */
+ arg0 = ap[2]; arg1 = ap[1]; arg2 = ap[0];
svp = av_fetch(ARG2_AV, arg1.any_iv, 1);
if (UNLIKELY(!AvREAL(ARG2_AV) && AvREIFY(ARG2_AV))) /* undo reify guard */
SvREFCNT_dec(ARG0_SV);
@@ -1212,7 +1289,10 @@ Perl_leave_scope(pTHX_ I32 base)
break;
case SAVEt_HELEM: /* hash element */
{
- HE * const he = hv_fetch_ent(ARG2_HV, ARG1_SV, 1, 0);
+ HE *he;
+
+ arg0 = ap[2]; arg1 = ap[1]; arg2 = ap[0];
+ he = hv_fetch_ent(ARG2_HV, ARG1_SV, 1, 0);
SvREFCNT_dec(ARG1_SV);
if (LIKELY(he)) {
const SV * const oval = HeVAL(he);
@@ -1229,9 +1309,11 @@ Perl_leave_scope(pTHX_ I32 base)
break;
}
case SAVEt_OP:
+ arg0 = ap[0];
PL_op = (OP*)ARG0_PTR;
break;
case SAVEt_HINTS:
+ arg0 = ap[1]; arg1 = ap[0];
if ((PL_hints & HINT_LOCALIZE_HH)) {
while (GvHV(PL_hintgv)) {
HV *hv = GvHV(PL_hintgv);
@@ -1256,6 +1338,7 @@ Perl_leave_scope(pTHX_ I32 base)
assert(GvHV(PL_hintgv));
break;
case SAVEt_COMPPAD:
+ arg0 = ap[0];
PL_comppad = (PAD*)ARG0_PTR;
if (LIKELY(PL_comppad))
PL_curpad = AvARRAY(PL_comppad);
@@ -1265,6 +1348,8 @@ Perl_leave_scope(pTHX_ I32 base)
case SAVEt_PADSV_AND_MORTALIZE:
{
SV **svp;
+
+ arg0 = ap[2]; arg1 = ap[1]; arg2 = ap[0];
assert (ARG1_PTR);
svp = AvARRAY((PAD*)ARG1_PTR) + (PADOFFSET)arg0.any_uv;
/* This mortalizing used to be done by CX_POOPLOOP() via
@@ -1279,45 +1364,57 @@ Perl_leave_scope(pTHX_ I32 base)
case SAVEt_SAVESWITCHSTACK:
{
dSP;
+
+ arg0 = ap[1]; arg1 = ap[0];
SWITCHSTACK(ARG0_AV, ARG1_AV);
PL_curstackinfo->si_stack = ARG1_AV;
}
break;
case SAVEt_SET_SVFLAGS:
+ arg0 = ap[2]; arg1 = ap[1]; arg2 = ap[0];
SvFLAGS(ARG2_SV) &= ~((U32)ARG1_I32);
SvFLAGS(ARG2_SV) |= (U32)ARG0_I32;
break;
/* These are only saved in mathoms.c */
case SAVEt_NSTAB:
+ arg0 = ap[0];
(void)sv_clear(ARG0_SV);
break;
case SAVEt_LONG: /* long reference */
+ arg0 = ap[1]; arg1 = ap[0];
*(long*)ARG0_PTR = arg1.any_long;
break;
case SAVEt_IV: /* IV reference */
+ arg0 = ap[1]; arg1 = ap[0];
*(IV*)ARG0_PTR = arg1.any_iv;
break;
case SAVEt_I16: /* I16 reference */
+ arg0 = ap[0];
*(I16*)ARG0_PTR = (I16)(uv >> 8);
break;
case SAVEt_I8: /* I8 reference */
+ arg0 = ap[0];
*(I8*)ARG0_PTR = (I8)(uv >> 8);
break;
case SAVEt_DESTRUCTOR:
+ arg0 = ap[1]; arg1 = ap[0];
(*arg1.any_dptr)(ARG0_PTR);
break;
case SAVEt_COMPILE_WARNINGS:
+ arg0 = ap[0];
if (!specialWARN(PL_compiling.cop_warnings))
PerlMemShared_free(PL_compiling.cop_warnings);
PL_compiling.cop_warnings = (STRLEN*)ARG0_PTR;
break;
case SAVEt_PARSER:
+ arg0 = ap[0];
parser_free((yy_parser *) ARG0_PTR);
break;
case SAVEt_READONLY_OFF:
+ arg0 = ap[0];
SvREADONLY_off(ARG0_SV);
break;
default:
diff --git a/scope.h b/scope.h
index 9a504f1bfd..ad276a94a7 100644
--- a/scope.h
+++ b/scope.h
@@ -8,7 +8,7 @@
*
*/
-/* *** these are ordered by number of of auto-popped args */
+/* *** Update arg_counts[] in scope.c if you modify these */
/* zero args */
@@ -17,8 +17,6 @@
#define SAVEt_CLEARSV 2
#define SAVEt_REGCONTEXT 3
-#define SAVEt_ARG0_MAX 3
-
/* one arg */
#define SAVEt_TMPSFLOOR 4
@@ -41,8 +39,6 @@
#define SAVEt_READONLY_OFF 21
#define SAVEt_FREEPADNAME 22
-#define SAVEt_ARG1_MAX 22
-
/* two args */
#define SAVEt_AV 23
@@ -71,8 +67,6 @@
#define SAVEt_ADELETE 46
#define SAVEt_APTR 47
-#define SAVEt_ARG2_MAX 47
-
/* three args */
#define SAVEt_HELEM 48