From 1c42d693461ddc927e40ad7842d1618bd374cced Mon Sep 17 00:00:00 2001 From: Aleksey Demakov Date: Wed, 22 Apr 2009 11:58:27 +0000 Subject: [PATCH] for function calls end basic block after the call rather than before and only if the call may throw --- ChangeLog | 9 ++ jit/jit-function.c | 139 ++++++++++++------------- jit/jit-insn.c | 251 +++++++++++++-------------------------------- 3 files changed, 151 insertions(+), 248 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60d1af1..3691eb0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-04-22 Aleksey Demakov + + * jit/jit-insn.c (jit_insn_call, jit_insn_call_indirect) + (jit_insn_call_indirect_vtable, jit_insn_call_native): don't end + basic block before a function call, rather end it after the call if + the call may throw some exception. + * jit/jit-function.c (compile_block): spill all registers before + calls. + 2009-04-21 Aleksey Demakov * jit/jit-dump.c (jit_dump_insn): fix "call_finally" dump. diff --git a/jit/jit-function.c b/jit/jit-function.c index 48d2db5..ba97c1a 100644 --- a/jit/jit-function.c +++ b/jit/jit-function.c @@ -491,8 +491,8 @@ jit_function_t jit_function_get_nested_parent(jit_function_t func) /* * Compile a single basic block within a function. */ -static void compile_block(jit_gencode_t gen, jit_function_t func, - jit_block_t block) +static void +compile_block(jit_gencode_t gen, jit_function_t func, jit_block_t block) { jit_insn_iter_t iter; jit_insn_t insn; @@ -514,100 +514,97 @@ static void compile_block(jit_gencode_t gen, jit_function_t func, switch(insn->opcode) { - case JIT_OP_NOP: break; /* Ignore NOP's */ + case JIT_OP_NOP: + /* Ignore NOP's */ + break; - case JIT_OP_CHECK_NULL: + case JIT_OP_CHECK_NULL: + /* Determine if we can optimize the null check away */ + if(!_jit_insn_check_is_redundant(&iter)) { - /* Determine if we can optimize the null check away */ - if(!_jit_insn_check_is_redundant(&iter)) - { - _jit_gen_insn(gen, func, block, insn); - } + _jit_gen_insn(gen, func, block, insn); } break; + case JIT_OP_CALL: + case JIT_OP_CALL_TAIL: + case JIT_OP_CALL_INDIRECT: + case JIT_OP_CALL_INDIRECT_TAIL: + case JIT_OP_CALL_VTABLE_PTR: + case JIT_OP_CALL_VTABLE_PTR_TAIL: + case JIT_OP_CALL_EXTERNAL: + case JIT_OP_CALL_EXTERNAL_TAIL: + /* Spill all caller-saved registers before a call */ + _jit_regs_spill_all(gen); + _jit_gen_insn(gen, func, block, insn); + break; + #ifndef JIT_BACKEND_INTERP - case JIT_OP_INCOMING_REG: - { - /* Assign a register to an incoming value */ - _jit_regs_set_incoming - (gen, (int)jit_value_get_nint_constant(insn->value2), - insn->value1); - _jit_gen_insn(gen, func, block, insn); - } + case JIT_OP_INCOMING_REG: + /* Assign a register to an incoming value */ + _jit_regs_set_incoming(gen, + (int)jit_value_get_nint_constant(insn->value2), + insn->value1); + _jit_gen_insn(gen, func, block, insn); break; #endif - case JIT_OP_INCOMING_FRAME_POSN: + case JIT_OP_INCOMING_FRAME_POSN: + /* Set the frame position for an incoming value */ + insn->value1->frame_offset = jit_value_get_nint_constant(insn->value2); + insn->value1->in_register = 0; + insn->value1->has_frame_offset = 1; + if(insn->value1->has_global_register) { - /* Set the frame position for an incoming value */ - insn->value1->frame_offset = - jit_value_get_nint_constant(insn->value2); - insn->value1->in_register = 0; - insn->value1->has_frame_offset = 1; - if(insn->value1->has_global_register) - { - insn->value1->in_global_register = 1; - _jit_gen_load_global(gen, insn->value1->global_reg, insn->value1); - } - else - { - insn->value1->in_frame = 1; - } + insn->value1->in_global_register = 1; + _jit_gen_load_global(gen, insn->value1->global_reg, insn->value1); + } + else + { + insn->value1->in_frame = 1; } break; #ifndef JIT_BACKEND_INTERP - case JIT_OP_OUTGOING_REG: - { - /* Copy a value into an outgoing register */ - _jit_regs_set_outgoing - (gen, (int)jit_value_get_nint_constant(insn->value2), - insn->value1); - } + case JIT_OP_OUTGOING_REG: + /* Copy a value into an outgoing register */ + _jit_regs_set_outgoing(gen, + (int)jit_value_get_nint_constant(insn->value2), + insn->value1); break; #endif - case JIT_OP_OUTGOING_FRAME_POSN: - { - /* Set the frame position for an outgoing value */ - insn->value1->frame_offset = - jit_value_get_nint_constant(insn->value2); - insn->value1->in_register = 0; - insn->value1->in_global_register = 0; - insn->value1->in_frame = 0; - insn->value1->has_frame_offset = 1; - insn->value1->has_global_register = 0; - } + case JIT_OP_OUTGOING_FRAME_POSN: + /* Set the frame position for an outgoing value */ + insn->value1->frame_offset = jit_value_get_nint_constant(insn->value2); + insn->value1->in_register = 0; + insn->value1->in_global_register = 0; + insn->value1->in_frame = 0; + insn->value1->has_frame_offset = 1; + insn->value1->has_global_register = 0; break; #ifndef JIT_BACKEND_INTERP - case JIT_OP_RETURN_REG: - { - /* Assign a register to a return value */ - _jit_regs_set_incoming - (gen, (int)jit_value_get_nint_constant(insn->value2), - insn->value1); - _jit_gen_insn(gen, func, block, insn); - } + case JIT_OP_RETURN_REG: + /* Assign a register to a return value */ + _jit_regs_set_incoming(gen, + (int)jit_value_get_nint_constant(insn->value2), + insn->value1); + _jit_gen_insn(gen, func, block, insn); break; #endif - case JIT_OP_MARK_OFFSET: - { - /* Mark the current code position as corresponding - to a particular bytecode offset */ - _jit_cache_mark_bytecode - (&(gen->posn), (unsigned long)(long) - jit_value_get_nint_constant(insn->value1)); - } + case JIT_OP_MARK_OFFSET: + /* Mark the current code position as corresponding + to a particular bytecode offset */ + _jit_cache_mark_bytecode(&gen->posn, + (unsigned long)(long) + jit_value_get_nint_constant(insn->value1)); break; - default: - { - /* Generate code for the instruction with the back end */ - _jit_gen_insn(gen, func, block, insn); - } + default: + /* Generate code for the instruction with the back end */ + _jit_gen_insn(gen, func, block, insn); break; } diff --git a/jit/jit-insn.c b/jit/jit-insn.c index 40c7df0..ef31fb8 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -5365,6 +5365,64 @@ static int create_call_setup_insns is_nested, nesting_level, struct_return, flags); } +static jit_value_t +handle_return(jit_function_t func, + jit_type_t signature, + int flags, int is_nested, + jit_value_t *args, unsigned int num_args, + jit_value_t return_value) +{ + /* If the function does not return, then end the current block. + The next block does not have "entered_via_top" set so that + it will be eliminated during later code generation */ + if((flags & (JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0) + { + func->builder->current_block->ends_in_dead = 1; + } + + /* If the function may throw an exceptions then end the current + basic block to account for exceptional control flow */ + if((flags & JIT_CALL_NOTHROW) == 0) + { + if(!jit_insn_new_block(func)) + { + return 0; + } + } + + /* Create space for the return value, if we don't already have one */ + if(!return_value) + { + return_value = jit_value_create(func, jit_type_get_return(signature)); + if(!return_value) + { + return 0; + } + } + + /* Create the instructions necessary to move the return value into place */ + if((flags & JIT_CALL_TAIL) == 0) + { + if(!_jit_create_call_return_insns(func, + signature, + args, num_args, + return_value, + is_nested)) + { + return 0; + } + } + + /* Restore exception frame information after the call */ + if(!restore_eh_frame_after_call(func, flags)) + { + return 0; + } + + /* Return the value containing the result to the caller */ + return return_value; +} + /*@ * @deftypefun jit_value_t jit_insn_call (jit_function_t @var{func}, const char *@var{name}, jit_function_t @var{jit_func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{flags}) * Call the function @var{jit_func}, which may or may not be translated yet. @@ -5513,7 +5571,7 @@ jit_value_t jit_insn_call return 0; } - /* Start a new block and output the "call" instruction */ + /* Output the "call" instruction */ if((flags & JIT_CALL_TAIL) != 0 && func == jit_func) { /* We are performing a tail call to ourselves, which we can @@ -5543,10 +5601,6 @@ jit_value_t jit_insn_call func->builder->non_leaf = 1; /* Performing a regular call, or a tail call to someone else */ - if(!jit_insn_new_block(func)) - { - return 0; - } insn = _jit_block_add_insn(func->builder->current_block); if(!insn) { @@ -5566,46 +5620,9 @@ jit_value_t jit_insn_call insn->value1 = (jit_value_t)name; } - /* If the function does not return, then end the current block. - The next block does not have "entered_via_top" set so that - it will be eliminated during later code generation */ - if((flags & (JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0) - { - func->builder->current_block->ends_in_dead = 1; - if(!jit_insn_new_block(func)) - { - return 0; - } - } - - /* Create space for the return value, if we don't already have one */ - if(!return_value) - { - return_value = jit_value_create(func, jit_type_get_return(signature)); - if(!return_value) - { - return 0; - } - } - - /* Create the instructions necessary to move the return value into place */ - if((flags & JIT_CALL_TAIL) == 0) - { - if(!_jit_create_call_return_insns - (func, signature, new_args, num_args, return_value, is_nested)) - { - return 0; - } - } - - /* Restore exception frame information after the call */ - if(!restore_eh_frame_after_call(func, flags)) - { - return 0; - } - - /* Return the value containing the result to the caller */ - return return_value; + /* Handle return to the caller */ + return handle_return(func, signature, flags, is_nested, + new_args, num_args, return_value); } /*@ @@ -5683,11 +5700,7 @@ jit_value_t jit_insn_call_indirect /* Functions that call out are not leaves */ func->builder->non_leaf = 1; - /* Start a new block and output the "call_indirect" instruction */ - if(!jit_insn_new_block(func)) - { - return 0; - } + /* Output the "call_indirect" instruction */ insn = _jit_block_add_insn(func->builder->current_block); if(!insn) { @@ -5707,46 +5720,9 @@ jit_value_t jit_insn_call_indirect insn->value1 = value; insn->value2 = (jit_value_t)jit_type_copy(signature); - /* If the function does not return, then end the current block. - The next block does not have "entered_via_top" set so that - it will be eliminated during later code generation */ - if((flags & (JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0) - { - func->builder->current_block->ends_in_dead = 1; - if(!jit_insn_new_block(func)) - { - return 0; - } - } - - /* Create space for the return value, if we don't already have one */ - if(!return_value) - { - return_value = jit_value_create(func, jit_type_get_return(signature)); - if(!return_value) - { - return 0; - } - } - - /* Create the instructions necessary to move the return value into place */ - if((flags & JIT_CALL_TAIL) == 0) - { - if(!_jit_create_call_return_insns - (func, signature, new_args, num_args, return_value, 0)) - { - return 0; - } - } - - /* Restore exception frame information after the call */ - if(!restore_eh_frame_after_call(func, flags)) - { - return 0; - } - - /* Return the value containing the result to the caller */ - return return_value; + /* Handle return to the caller */ + return handle_return(func, signature, flags, 0, + new_args, num_args, return_value); } /*@ @@ -5821,11 +5797,7 @@ jit_value_t jit_insn_call_indirect_vtable /* Functions that call out are not leaves */ func->builder->non_leaf = 1; - /* Start a new block and output the "call_vtable_ptr" instruction */ - if(!jit_insn_new_block(func)) - { - return 0; - } + /* Output the "call_vtable_ptr" instruction */ insn = _jit_block_add_insn(func->builder->current_block); if(!insn) { @@ -5843,46 +5815,9 @@ jit_value_t jit_insn_call_indirect_vtable } insn->value1 = value; - /* If the function does not return, then end the current block. - The next block does not have "entered_via_top" set so that - it will be eliminated during later code generation */ - if((flags & (JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0) - { - func->builder->current_block->ends_in_dead = 1; - if(!jit_insn_new_block(func)) - { - return 0; - } - } - - /* Create space for the return value, if we don't already have one */ - if(!return_value) - { - return_value = jit_value_create(func, jit_type_get_return(signature)); - if(!return_value) - { - return 0; - } - } - - /* Create the instructions necessary to move the return value into place */ - if((flags & JIT_CALL_TAIL) == 0) - { - if(!_jit_create_call_return_insns - (func, signature, new_args, num_args, return_value, 0)) - { - return 0; - } - } - - /* Restore exception frame information after the call */ - if(!restore_eh_frame_after_call(func, flags)) - { - return 0; - } - - /* Return the value containing the result to the caller */ - return return_value; + /* Handle return to the caller */ + return handle_return(func, signature, flags, 0, + new_args, num_args, return_value); } /*@ @@ -5956,11 +5891,7 @@ jit_value_t jit_insn_call_native /* Functions that call out are not leaves */ func->builder->non_leaf = 1; - /* Start a new block and output the "call_external" instruction */ - if(!jit_insn_new_block(func)) - { - return 0; - } + /* Output the "call_external" instruction */ insn = _jit_block_add_insn(func->builder->current_block); if(!insn) { @@ -5983,37 +5914,9 @@ jit_value_t jit_insn_call_native insn->value2 = (jit_value_t)jit_type_copy(signature); #endif - /* If the function does not return, then end the current block. - The next block does not have "entered_via_top" set so that - it will be eliminated during later code generation */ - if((flags & (JIT_CALL_NORETURN | JIT_CALL_TAIL)) != 0) - { - func->builder->current_block->ends_in_dead = 1; - if(!jit_insn_new_block(func)) - { - return 0; - } - } - - /* Create space for the return value, if we don't already have one */ - if(!return_value) - { - return_value = jit_value_create(func, jit_type_get_return(signature)); - if(!return_value) - { - return 0; - } - } - - /* Create the instructions necessary to move the return value into place */ - if((flags & JIT_CALL_TAIL) == 0) - { - if(!_jit_create_call_return_insns - (func, signature, new_args, num_args, return_value, 0)) - { - return 0; - } - } + /* Handle return to the caller */ + return_value = handle_return(func, signature, flags, 0, + new_args, num_args, return_value); /* Make sure that returned byte / short values get zero / sign extended */ return_type = jit_type_normalize(return_value->type); @@ -6041,12 +5944,6 @@ jit_value_t jit_insn_call_native break; } - /* Restore exception frame information after the call */ - if(!restore_eh_frame_after_call(func, flags)) - { - return 0; - } - /* Return the value containing the result to the caller */ return return_value; } -- 2.47.3