remove repeated PL_stack_sp derefs in Perl_eval_sv/Perl_call_sv
authorDaniel Dragan <bulk88@hotmail.com>
Fri, 25 Sep 2015 20:38:11 +0000 (16:38 -0400)
committerTony Cook <tony@develop-help.com>
Mon, 12 Oct 2015 23:10:23 +0000 (10:10 +1100)
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.c

diff --git a/perl.c b/perl.c
index 69cdf8e..bf4d549 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -2699,7 +2699,7 @@ I32
 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;
@@ -2729,9 +2729,14 @@ Perl_call_sv(pTHX_ SV *sv, VOL I32 flags)
     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;
 
@@ -2842,9 +2847,8 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
                        /* 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;
@@ -2860,8 +2864,13 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
     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;