remove 1 read of interp var from PUSHMARK
authorDaniel Dragan <bulk88@hotmail.com>
Thu, 5 Jun 2014 03:17:39 +0000 (23:17 -0400)
committerTony Cook <tony@develop-help.com>
Mon, 9 Jun 2014 00:11:19 +0000 (10:11 +1000)
PL_markstack_ptr was read once to do the ++ and comparison. Then after
the markstack_grow call, or not, depending on the branch. The code reads
PL_markstack_ptr a 2nd time. It has to be reread in case (or always does)
markstack_grow reallocs the mark stack. markstack_grow has a void retval.
That is a waste of a register. Let us put it to use to return the new
PL_markstack_ptr. In markstack_grow the contents that will be assigned to
PL_markstack_ptr are already in a register. So let the I32* flow out from
markstack_grow to its caller.

In VC2003 32 bit asm, mark_stack_entry is register eax. The retval of
markstack_grow is in eax. So the assignment "=" in
"mark_stack_entry = markstack_grow();" has no overhead. Since the other,
not extend branch, is function call free,
"(mark_stack_entry = ++PL_markstack_ptr)" assigns to eax. Ultimatly with
this patch a 3 byte mov instruction is saved for each instance of PUSHMARK,
and 1 interp var read is removed. I observed 42 callers of markstack_grow
with my disassembler, so theoretically 3*42 bytes of machine code was
removed for me.

Perl_pp_pushmark dropped from 0x2b to 0x28 bytes of x86 VC 2003
machine code. [perl #122034]

embed.fnc
pp.h
proto.h
scope.c

index 50bb964..22205d8 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -851,7 +851,7 @@ p   |int    |magic_wipepack |NN SV* sv|NN MAGIC* mg
 pod    |SV*    |magic_methcall |NN SV *sv|NN const MAGIC *mg \
                                |NN SV *meth|U32 flags \
                                |U32 argc|...
-Ap     |void   |markstack_grow
+Ap     |I32 *  |markstack_grow
 #if defined(USE_LOCALE_COLLATE)
 p      |int    |magic_setcollxfrm|NN SV* sv|NN MAGIC* mg
 : Defined in locale.c, used only in sv.c
diff --git a/pp.h b/pp.h
index 3623a38..a7e936c 100644 (file)
--- a/pp.h
+++ b/pp.h
@@ -57,9 +57,10 @@ Refetch the stack pointer.  Used after a callback.  See L<perlcall>.
 
 #define PUSHMARK(p)    \
        STMT_START {                                    \
-           if (UNLIKELY(++PL_markstack_ptr == PL_markstack_max))       \
-           markstack_grow();                           \
-           *PL_markstack_ptr = (I32)((p) - PL_stack_base);\
+           I32 * mark_stack_entry;                     \
+           if (UNLIKELY((mark_stack_entry = ++PL_markstack_ptr) == PL_markstack_max))  \
+           mark_stack_entry = markstack_grow();                                        \
+           *mark_stack_entry  = (I32)((p) - PL_stack_base);                            \
        } STMT_END
 
 #define TOPMARK                (*PL_markstack_ptr)
diff --git a/proto.h b/proto.h
index 3b882d8..27981e9 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -2535,7 +2535,7 @@ PERL_CALLCONV Malloc_t    Perl_malloc(MEM_SIZE nbytes)
                        __attribute__malloc__
                        __attribute__warn_unused_result__;
 
-PERL_CALLCONV void     Perl_markstack_grow(pTHX);
+PERL_CALLCONV I32 *    Perl_markstack_grow(pTHX);
 PERL_CALLCONV SV*      Perl_mess(pTHX_ const char* pat, ...)
                        __attribute__format__(__printf__,pTHX_1,pTHX_2)
                        __attribute__nonnull__(pTHX_1);
diff --git a/scope.c b/scope.c
index 07f24b7..76e023a 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -110,7 +110,7 @@ Perl_pop_scope(pTHX)
     LEAVE_SCOPE(oldsave);
 }
 
-void
+I32 *
 Perl_markstack_grow(pTHX)
 {
     dVAR;
@@ -118,8 +118,9 @@ Perl_markstack_grow(pTHX)
     const I32 newmax = GROW(oldmax);
 
     Renew(PL_markstack, newmax, I32);
-    PL_markstack_ptr = PL_markstack + oldmax;
     PL_markstack_max = PL_markstack + newmax;
+    PL_markstack_ptr = PL_markstack + oldmax;
+    return PL_markstack_ptr;
 }
 
 void