From 4cc783efe0ed9495ebcbefd8494083a4b6160e6f Mon Sep 17 00:00:00 2001 From: Daniel Dragan Date: Tue, 20 Nov 2012 17:36:54 -0500 Subject: [PATCH] refactor pp_stringify and pp_and pp_stringify: First, move all the SP/stack operations to before the first call in pp_stringify (sv_copypv), this allows SP to never be saved across any calls. SETTARG calls set magic, so that still has to be done. SETs does not ++/-- SP, so no need to do a PUTBACK. PL_op is read twice, once for TARG, once for NORMAL. No point in caching it through the sv_copypv call since its not worth saving a non-vol to C stack (x86) just to avoid 2 mem acesses. This opcode now only has 2 vars saved across sv_copypv, my_perl and TARG. pp_stringify dropped from 0x3F to 0x3C for me after these changes, 32 bit x86 VC 2003. pp_and: Do the PERL_ASYNC_CHECK before anything else, calcing SP before PERL_ASYNC_CHECK would mean saving it across the potential call. SvTRUE macro checks its param for NULL. This SV * came off the Perl stack, it will not be null since pp_and is not a core sub (see S_maybe_add_coresub) and will not be called from pp_coreargs (pp_coreargs places (SV *)NULLs on Perl stack). So create a SvTRUE_NN macro that does not check for NULL, this saves a branch. Since the Perl stack is only touched twice, don't create a local SP. See comment in code. This saves another variable to not be saved across the sv_2bool_flags and removed PUTBACK instructions. PL_op is only read once or twice (compiler choice) right before the 2 returns. There is only 1 variable saved across any calls in pp_and now, and that is my_perl. dSP also was not use to prevent an accidental use of a ++/-- SP macro in pp_and in the future since there is no PUTBACK now. I guess for a SPARC with register windowing and no direct memory instructions, accessing PL_stack_sp twice will take more instructions 2 reads and a write to PL_stack_sp vs 1 read and 1 write to PL_stack_sp with a dSP design. On SPARC, with a register window, cross call regs have no cost per reg cost aslong as you dont exceed their max number. For me, pp_and went from 0x112 to 0xFF after this commit. Prior to dSP removal, it was down to 0x109. SvTRUE_NN was named after SvREFCNT_inc_NN. There remains an inefficiency in pp_and on non-GCC compilers due to SvPVXtrue using PL_Xpv which will be dealt with in another commit. --- pp_hot.c | 31 +++++++++++++++++++++---------- sv.h | 1 + 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/pp_hot.c b/pp_hot.c index d535434..977e22f 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -85,9 +85,12 @@ PP(pp_pushmark) PP(pp_stringify) { dVAR; dSP; dTARGET; - sv_copypv(TARG,TOPs); - SETTARG; - RETURN; + SV * const sv = TOPs; + SETs(TARG); + sv_copypv(TARG, sv); + SvSETMAGIC(TARG); + /* no PUTBACK, SETs doesn't inc/dec SP */ + return NORMAL; } PP(pp_gv) @@ -99,14 +102,22 @@ PP(pp_gv) PP(pp_and) { - dVAR; dSP; + dVAR; PERL_ASYNC_CHECK(); - if (!SvTRUE(TOPs)) - RETURN; - else { - if (PL_op->op_type == OP_AND) - --SP; - RETURNOP(cLOGOP->op_other); + { + /* SP is not used to remove a variable that is saved across the + sv_2bool_flags call in SvTRUE_NN, if a RISC/CISC or low/high machine + register or load/store vs direct mem ops macro is introduced, this + should be a define block between direct PL_stack_sp and dSP operations, + presently, using PL_stack_sp is bias towards CISC cpus */ + SV * const sv = *PL_stack_sp; + if (!SvTRUE_NN(sv)) + return NORMAL; + else { + if (PL_op->op_type == OP_AND) + --PL_stack_sp; + return cLOGOP->op_other; + } } } diff --git a/sv.h b/sv.h index 902cae7..35b360f 100644 --- a/sv.h +++ b/sv.h @@ -1708,6 +1708,7 @@ Like sv_utf8_upgrade, but doesn't do magic on C. #define SvTRUE(sv) ((sv) && (SvGMAGICAL(sv) ? sv_2bool(sv) : SvTRUE_common(sv, sv_2bool_nomg(sv)))) #define SvTRUE_nomg(sv) ((sv) && ( SvTRUE_common(sv, sv_2bool_nomg(sv)))) +#define SvTRUE_NN(sv) (SvGMAGICAL(sv) ? sv_2bool(sv) : SvTRUE_common(sv, sv_2bool_nomg(sv))) #define SvTRUE_common(sv,fallback) ( \ !SvOK(sv) \ ? 0 \ -- 2.7.4