Reduce scope of local SP and remove excessive reads and writes to
PL_stack_sp in Perl_eval_sv/Perl_call_sv. EXTEND macro refetches the
possibly realloced SP on its own, Perl_stack_grow returns the new SP as a
retval and therefore in a register. By using PL_stack_sp instead of
Perl_stack_grow, an extra redundant mem read is done. Also dont keep
SP around for long periods unused, it wastes a C stack slot or non-vol
reg and makes the callframe bigger. The EXTEND could be placed
in the !(flags & G_METHOD_NAMED) branch, but that will be done in another
patch for bisectability.
VC 2003 -O1 machine code sizes of the functions
Perl_eval_sv before 0x28a after 0x286
Perl_call_sv before 0x3cd after 0x3cb
The savings look small since in x86 "*var+=4" and "var+=4" are the same
number of bytes to encode the instruction, only the mod R/M bitfield vals
are different. RISC CPUs benefit more from this patch.
commit
c106c2be8b "G_METHOD_NAMED flag for call_method and call_sv"
added skipping the push SV onto stack
The EXTEND and PL_stack_sp direct manipulation code is from
commit
a0d0e21ea6 "perl 5.000". The reason is unknown why it did
"SV** sp = stack_sp;" and later "EXTEND(stack_sp, 1);" instead of using
SP, since EXTEND at that time, and to this day requires C auto sp be in
scope.
Perl_call_sv(pTHX_ SV *sv, VOL I32 flags)
/* See G_* flags in cop.h */
{
- dVAR; dSP;
+ dVAR;
LOGOP myop; /* fake syntax tree node */
METHOP method_op;
I32 oldmark;
SAVEOP();
PL_op = (OP*)&myop;
- EXTEND(PL_stack_sp, 1);
- if (!(flags & G_METHOD_NAMED))
- *++PL_stack_sp = sv;
+ {
+ dSP;
+ EXTEND(SP, 1);
+ if (!(flags & G_METHOD_NAMED)) {
+ PUSHs(sv);
+ PUTBACK;
+ }
+ }
oldmark = TOPMARK;
oldscope = PL_scopestack_ix;
/* See G_* flags in cop.h */
{
dVAR;
- dSP;
UNOP myop; /* fake syntax tree node */
- VOL I32 oldmark = SP - PL_stack_base;
+ VOL I32 oldmark;
VOL I32 retval = 0;
int ret;
OP* const oldop = PL_op;
SAVEOP();
PL_op = (OP*)&myop;
Zero(&myop, 1, UNOP);
- EXTEND(PL_stack_sp, 1);
- *++PL_stack_sp = sv;
+ {
+ dSP;
+ oldmark = SP - PL_stack_base;
+ EXTEND(SP, 1);
+ PUSHs(sv);
+ PUTBACK;
+ }
if (!(flags & G_NOARGS))
myop.op_flags = OPf_STACKED;