From 48fa89fa967d583d29842dba637f608f7ae1f634 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Sun, 30 May 2004 09:05:05 +0000 Subject: [PATCH] Add "jit_insn_defer_pop_stack" and "jit_insn_flush_defer_pop", to defer the popping of function call arguments as long as possible. --- ChangeLog | 5 +++ include/jit/jit-insn.h | 4 ++ jit/jit-insn.c | 96 ++++++++++++++++++++++++++++++++++++++++++ jit/jit-internal.h | 3 ++ jit/jit-rules-x86.c | 10 ++++- 5 files changed, 117 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f0a53b5..cef811f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,11 @@ 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 * jit/jit-insn.c, jit/jit-reg-alloc.c, jit/jit-reg-alloc.h, diff --git a/include/jit/jit-insn.h b/include/jit/jit-insn.h index b67628d..efed07f 100644 --- a/include/jit/jit-insn.h +++ b/include/jit/jit-insn.h @@ -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; diff --git a/jit/jit-insn.c b/jit/jit-insn.c index c39ac90..28bf18f 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -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) diff --git a/jit/jit-internal.h b/jit/jit-internal.h index d044b46..92e3a26 100644 --- a/jit/jit-internal.h +++ b/jit/jit-internal.h @@ -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; + }; /* diff --git a/jit/jit-rules-x86.c b/jit/jit-rules-x86.c index adb1574..745c7c7 100644 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@ -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; } -- 2.47.3