]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Add "jit_insn_defer_pop_stack" and "jit_insn_flush_defer_pop",
authorRhys Weatherley <rweather@southern-storm.com.au>
Sun, 30 May 2004 09:05:05 +0000 (09:05 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Sun, 30 May 2004 09:05:05 +0000 (09:05 +0000)
to defer the popping of function call arguments as long as possible.

ChangeLog
include/jit/jit-insn.h
jit/jit-insn.c
jit/jit-internal.h
jit/jit-rules-x86.c

index f0a53b58942b4d01178a9b2fcdbc76afc2ba4bcb..cef811f7743ebb964387dd38bdcce530f892f1be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        tools/gen-sel-scanner.l: improve instruction selection for
        floating-point "push" operations.
 
+       * include/jit/jit-insn.h, jit/jit-insn.c, jit/jit-internal.h,
+       jit/jit-rules-x86.c: add "jit_insn_defer_pop_stack" and
+       "jit_insn_flush_defer_pop", to defer the popping of function
+       call arguments as long as possible.
+
 2004-05-29  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * jit/jit-insn.c, jit/jit-reg-alloc.c, jit/jit-reg-alloc.h,
index b67628d248dd737185ac0e11d4221f67d992c5e2..efed07f6ebc7694c9114b8729d2236cc46575326 100644 (file)
@@ -252,6 +252,10 @@ int jit_insn_push(jit_function_t func, jit_value_t value) JIT_NOTHROW;
 int jit_insn_push_ptr
        (jit_function_t func, jit_value_t value, jit_type_t type) JIT_NOTHROW;
 int jit_insn_pop_stack(jit_function_t func, jit_nint num_items) JIT_NOTHROW;
+int jit_insn_defer_pop_stack
+       (jit_function_t func, jit_nint num_items) JIT_NOTHROW;
+int jit_insn_flush_defer_pop
+       (jit_function_t func, jit_nint num_items) JIT_NOTHROW;
 int jit_insn_return(jit_function_t func, jit_value_t value) JIT_NOTHROW;
 int jit_insn_return_ptr
        (jit_function_t func, jit_value_t value, jit_type_t type) JIT_NOTHROW;
index c39ac9011083e51117d239e6eed9e83c50eee900..28bf18f4903c292fa35bb6c5537c50436c66e7cc 100644 (file)
@@ -1069,6 +1069,10 @@ int jit_insn_label(jit_function_t func, jit_label_t *label)
        {
                return 0;
        }
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
        current = func->builder->current_block;
        last = _jit_block_get_last(current);
        if(current->label == jit_label_undefined && !last)
@@ -3481,6 +3485,10 @@ int jit_insn_branch(jit_function_t func, jit_label_t *label)
        {
                return 0;
        }
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
        insn = _jit_block_add_insn(func->builder->current_block);
        if(!insn)
        {
@@ -3529,6 +3537,12 @@ int jit_insn_branch_if
                return 0;
        }
 
+       /* Flush any stack pops that were deferred previously */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Allocate a new label identifier, if necessary */
        if(*label == jit_label_undefined)
        {
@@ -3723,6 +3737,12 @@ int jit_insn_branch_if_not
                return 0;
        }
 
+       /* Flush any stack pops that were deferred previously */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Allocate a new label identifier, if necessary */
        if(*label == jit_label_undefined)
        {
@@ -5941,6 +5961,52 @@ int jit_insn_pop_stack(jit_function_t func, jit_nint num_items)
                 jit_value_create_nint_constant(func, jit_type_nint, num_items));
 }
 
+/*@
+ * @deftypefun int jit_insn_defer_pop_stack (jit_function_t func, jit_nint num_items)
+ * This is similar to @code{jit_insn_pop_stack}, except that it tries to
+ * defer the pop as long as possible.  Multiple subroutine calls may
+ * result in parameters collecting up on the stack, and only being popped
+ * at the next branch or label instruction.  You normally wouldn't
+ * call this yourself - it is used by CPU back ends.
+ * @end deftypefun
+@*/
+int jit_insn_defer_pop_stack(jit_function_t func, jit_nint num_items)
+{
+       if(!_jit_function_ensure_builder(func))
+       {
+               return 0;
+       }
+       func->builder->deferred_items += num_items;
+       return 1;
+}
+
+/*@
+ * @deftypefun int jit_insn_flush_defer_pop (jit_function_t func, jit_nint num_items)
+ * Flush any deferred items that were scheduled for popping by
+ * @code{jit_insn_defer_pop_stack} if there are @code{num_items}
+ * or more items scheduled.  You normally wouldn't call this
+ * yourself - it is used by CPU back ends to clean up the stack just
+ * prior to a subroutine call when too many items have collected up.
+ * Calling @code{jit_insn_flush_defer_pop(func, 0)} will flush
+ * all deferred items.
+ * @end deftypefun
+@*/
+int jit_insn_flush_defer_pop(jit_function_t func, jit_nint num_items)
+{
+       jit_nint current_items;
+       if(!_jit_function_ensure_builder(func))
+       {
+               return 0;
+       }
+       current_items = func->builder->deferred_items;
+       if(current_items >= num_items && current_items > 0)
+       {
+               func->builder->deferred_items = 0;
+               return jit_insn_pop_stack(func, current_items);
+       }
+       return 1;
+}
+
 /*@
  * @deftypefun int jit_insn_return (jit_function_t func, jit_value_t value)
  * Output an instruction to return @code{value} as the function's result.
@@ -6556,6 +6622,12 @@ int jit_insn_branch_if_pc_not_in_range
                return 0;
        }
 
+       /* Flush any stack pops that were deferred previously */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Get the location where the exception occurred in this function */
 #if defined(JIT_BACKEND_INTERP)
        value1 = create_dest_note
@@ -6786,6 +6858,12 @@ jit_value_t jit_insn_call_filter
                return 0;
        }
 
+       /* Flush any stack pops that were deferred previously */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Allocate the label number if necessary */
        if(*label == jit_label_undefined)
        {
@@ -6865,6 +6943,12 @@ int jit_insn_memset
 @*/
 jit_value_t jit_insn_alloca(jit_function_t func, jit_value_t size)
 {
+       /* Make sure that all deferred pops have been done */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Round the size to the best alignment boundary on this platform */
        size = jit_insn_convert(func, size, jit_type_nuint, 0);
        size = jit_insn_add
@@ -6946,6 +7030,12 @@ int jit_insn_move_blocks_to_end
        jit_block_t block;
        jit_block_t next;
 
+       /* Make sure that deferred stack pops are flushed */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Find the first block that needs to be moved */
        first_block = jit_block_from_label(func, from_label);
        if(!first_block)
@@ -6988,6 +7078,12 @@ int jit_insn_move_blocks_to_start
        jit_block_t next;
        int move_current;
 
+       /* Make sure that deferred stack pops are flushed */
+       if(!jit_insn_flush_defer_pop(func, 0))
+       {
+               return 0;
+       }
+
        /* Find the first block that needs to be moved */
        first_block = jit_block_from_label(func, from_label);
        if(!first_block)
index d044b46e21f3a81cd6e704156791a44769238fab..92e3a2688a0b073b017ce45671679e7b879881df 100644 (file)
@@ -323,6 +323,9 @@ struct _jit_builder
        /* Current size of the local variable frame (used by the back end) */
        jit_nint                        frame_size;
 
+       /* Number of stack items that are queued for a deferred pop */
+       jit_nint                        deferred_items;
+
 };
 
 /*
index adb1574c6d5ef50b688b7e096272b04567381506..745c7c7ed7ffedec4f904351d87f7661745f6f0d 100644 (file)
@@ -399,6 +399,14 @@ int _jit_create_call_setup_insns
                num_stack_args = num_args;
        }
 
+       /* Flush deferred stack pops from previous calls if too many
+          parameters have collected up on the stack since last time */
+       if(!jit_insn_flush_defer_pop
+                       (func, 32 - (jit_nint)(num_stack_args * sizeof(void *))))
+       {
+               return 0;
+       }
+
        /* Push all of the stacked arguments in reverse order */
        while(num_stack_args > 0)
        {
@@ -623,7 +631,7 @@ int _jit_create_call_return_insns
        /* Pop the bytes from the system stack */
        if(pop_bytes > 0)
        {
-               if(!jit_insn_pop_stack(func, pop_bytes))
+               if(!jit_insn_defer_pop_stack(func, pop_bytes))
                {
                        return 0;
                }