From aa8bf13a6828065f64197b78f976f3e37ffddf53 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 10 May 2004 03:41:49 +0000 Subject: [PATCH] Interpreter code conversion for relative pointer and copy opcodes; fix some bugs in stack-based register allocation. --- ChangeLog | 6 ++ jit/jit-reg-alloc.c | 45 +++++++++-- jit/jit-reg-alloc.h | 1 + jit/jit-rules-interp.c | 176 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 221 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index de55c3e..6b318dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ +2004-05-10 Rhys Weatherley + + * jit/jit-reg-alloc.c, jit/jit-reg-alloc.h, jit/jit-rules-interp.c: + interpreter code conversion for relative pointer and copy opcodes; + fix some bugs in stack-based register allocation. + 2004-05-08 Rhys Weatherley * jit/jit-cache.c, jit/jit-cache.h, jit/jit-dump.c, jit/jit-interp.h, diff --git a/jit/jit-reg-alloc.c b/jit/jit-reg-alloc.c index d2790e5..d77c00c 100644 --- a/jit/jit-reg-alloc.c +++ b/jit/jit-reg-alloc.c @@ -210,13 +210,6 @@ static void spill_all_between(jit_gencode_t gen, int first, int last) first_stack_reg = reg; } - /* Skip this register if there is nothing in it */ - if(gen->contents[reg].num_values == 0 && - !(gen->contents[reg].used_for_temp)) - { - continue; - } - /* If this is a stack register, then we need to find the register that contains the top-most stack position, because we must spill stack registers from top down. @@ -224,12 +217,23 @@ static void spill_all_between(jit_gencode_t gen, int first, int last) if((_jit_reg_info[reg].flags & JIT_REG_IN_STACK) != 0) { real_reg = gen->stack_map[first_stack_reg]; + if(real_reg == -1) + { + continue; + } } else { real_reg = reg; } + /* Skip this register if there is nothing in it */ + if(gen->contents[real_reg].num_values == 0 && + !(gen->contents[real_reg].used_for_temp)) + { + continue; + } + /* Get the other register in a long pair, if there is one */ if(gen->contents[real_reg].is_long_start) { @@ -1246,3 +1250,30 @@ int _jit_regs_num_used(jit_gencode_t gen, int type_reg) } return count; } + +/*@ + * @deftypefun int _jit_regs_new_top (jit_gencode_t gen, jit_value_t value, int type_reg) + * Record that the top of the stack indicated by @code{type_reg} now + * contains @code{value}. This is slightly different from + * @code{_jit_regs_set_value}, in that the register wasn't previously + * allocated to a temporary operand value. Returns the actual stack + * register that contains @code{value}. + * @end deftypefun +@*/ +int _jit_regs_new_top(jit_gencode_t gen, jit_value_t value, int type_reg) +{ + int reg; + + /* Create space for the value at the top of the stack */ + reg = create_stack_reg(gen, type_reg, 1); + + /* Record the "value" is now in this register */ + value->in_register = 1; + value->in_frame = 0; + value->reg = reg; + gen->contents[reg].values[0] = value; + gen->contents[reg].num_values = 1; + + /* Return the allocated register to the caller */ + return reg; +} diff --git a/jit/jit-reg-alloc.h b/jit/jit-reg-alloc.h index e44f280..b78adcc 100644 --- a/jit/jit-reg-alloc.h +++ b/jit/jit-reg-alloc.h @@ -52,6 +52,7 @@ void _jit_regs_load_to_top_three jit_value_t value3, int used_again1, int used_again2, int used_again3, int type_reg); int _jit_regs_num_used(jit_gencode_t gen, int type_reg); +int _jit_regs_new_top(jit_gencode_t gen, jit_value_t value, int type_reg); #ifdef __cplusplus }; diff --git a/jit/jit-rules-interp.c b/jit/jit-rules-interp.c index 7479933..91e5e61 100644 --- a/jit/jit-rules-interp.c +++ b/jit/jit-rules-interp.c @@ -870,6 +870,33 @@ static jit_label_t get_branch_dest(jit_block_t block, jit_insn_t insn) return label; } +/* + * Record that a destination is now in a particular register. + */ +static void record_dest(jit_gencode_t gen, jit_insn_t insn, int reg) +{ + if(insn->dest) + { + if((insn->flags & JIT_INSN_DEST_NEXT_USE) != 0) + { + /* Record that the destination is in "reg" */ + _jit_regs_set_value(gen, reg, insn->dest, 0); + } + else + { + /* No next use, so store to the destination */ + _jit_gen_spill_reg(gen, reg, -1, insn->dest); + insn->dest->in_frame = 1; + _jit_regs_free_reg(gen, reg, 1); + } + } + else + { + /* This is a note, with the result left on the stack */ + _jit_regs_free_reg(gen, reg, 1); + } +} + /*@ * @deftypefun void _jit_gen_insn (jit_gencode_t gen, jit_function_t func, jit_block_t block, jit_insn_t insn) * Generate native code for the specified @code{insn}. This function should @@ -884,6 +911,8 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, int reg; jit_label_t label; void **pc; + jit_nint offset; + jit_nint size; switch(insn->opcode) { @@ -1135,6 +1164,52 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, } break; + case JIT_OP_COPY_LOAD_SBYTE: + case JIT_OP_COPY_LOAD_UBYTE: + case JIT_OP_COPY_LOAD_SHORT: + case JIT_OP_COPY_LOAD_USHORT: + case JIT_OP_COPY_INT: + case JIT_OP_COPY_LONG: + case JIT_OP_COPY_FLOAT32: + case JIT_OP_COPY_FLOAT64: + case JIT_OP_COPY_NFLOAT: + case JIT_OP_COPY_STRUCT: + case JIT_OP_COPY_STORE_BYTE: + case JIT_OP_COPY_STORE_SHORT: + { + /* Copy a value from one temporary variable to another */ + reg = _jit_regs_load_to_top + (gen, insn->value1, + (insn->flags & (JIT_INSN_VALUE1_NEXT_USE | + JIT_INSN_VALUE1_LIVE)), 0); + record_dest(gen, insn, reg); + } + break; + + case JIT_OP_ADDRESS_OF: + { + /* Get the address of a local variable */ + if(_jit_regs_num_used(gen, 0) >= JIT_NUM_REGS) + { + _jit_regs_spill_all(gen); + } + _jit_gen_fix_value(insn->value1); + if(insn->value1->frame_offset >= 0) + { + jit_cache_opcode(&(gen->posn), JIT_OP_LDLOCA); + jit_cache_native(&(gen->posn), insn->value1->frame_offset); + } + else + { + jit_cache_opcode(&(gen->posn), JIT_OP_LDARGA); + jit_cache_native + (&(gen->posn), -(insn->value1->frame_offset + 1)); + } + reg = _jit_regs_new_top(gen, insn->dest, 0); + adjust_working(gen, 1); + } + break; + case JIT_OP_PUSH_INT: case JIT_OP_PUSH_LONG: case JIT_OP_PUSH_FLOAT32: @@ -1212,6 +1287,107 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, } break; + case JIT_OP_LOAD_RELATIVE_SBYTE: + case JIT_OP_LOAD_RELATIVE_UBYTE: + case JIT_OP_LOAD_RELATIVE_SHORT: + case JIT_OP_LOAD_RELATIVE_USHORT: + case JIT_OP_LOAD_RELATIVE_INT: + case JIT_OP_LOAD_RELATIVE_LONG: + case JIT_OP_LOAD_RELATIVE_FLOAT32: + case JIT_OP_LOAD_RELATIVE_FLOAT64: + case JIT_OP_LOAD_RELATIVE_NFLOAT: + { + /* Load a value from a relative pointer */ + reg = _jit_regs_load_to_top + (gen, insn->value1, + (insn->flags & (JIT_INSN_VALUE1_NEXT_USE | + JIT_INSN_VALUE1_LIVE)), 0); + offset = jit_value_get_nint_constant(insn->value2); + jit_cache_opcode(&(gen->posn), insn->opcode); + jit_cache_native(&(gen->posn), offset); + record_dest(gen, insn, reg); + } + break; + + case JIT_OP_LOAD_RELATIVE_STRUCT: + { + /* Load a structured value from a relative pointer */ + reg = _jit_regs_load_to_top + (gen, insn->value1, + (insn->flags & (JIT_INSN_VALUE1_NEXT_USE | + JIT_INSN_VALUE1_LIVE)), 0); + offset = jit_value_get_nint_constant(insn->value2); + size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest)); + jit_cache_opcode(&(gen->posn), insn->opcode); + jit_cache_native(&(gen->posn), offset); + jit_cache_native(&(gen->posn), size); + size = JIT_NUM_ITEMS_IN_STRUCT(size); + record_dest(gen, insn, reg); + adjust_working(gen, size - 1); + } + break; + + case JIT_OP_STORE_RELATIVE_BYTE: + case JIT_OP_STORE_RELATIVE_SHORT: + case JIT_OP_STORE_RELATIVE_INT: + case JIT_OP_STORE_RELATIVE_LONG: + case JIT_OP_STORE_RELATIVE_FLOAT32: + case JIT_OP_STORE_RELATIVE_FLOAT64: + case JIT_OP_STORE_RELATIVE_NFLOAT: + { + /* Store a value to a relative pointer */ + reg = _jit_regs_load_to_top_two + (gen, insn->dest, insn->value1, + (insn->flags & (JIT_INSN_DEST_NEXT_USE | + JIT_INSN_DEST_LIVE)), + (insn->flags & (JIT_INSN_VALUE1_NEXT_USE | + JIT_INSN_VALUE1_LIVE)), 0); + offset = jit_value_get_nint_constant(insn->value2); + jit_cache_opcode(&(gen->posn), insn->opcode); + jit_cache_native(&(gen->posn), offset); + _jit_regs_free_reg(gen, reg, 1); + adjust_working(gen, -2); + } + break; + + case JIT_OP_STORE_RELATIVE_STRUCT: + { + /* Store a structured value to a relative pointer */ + reg = _jit_regs_load_to_top_two + (gen, insn->dest, insn->value1, + (insn->flags & (JIT_INSN_DEST_NEXT_USE | + JIT_INSN_DEST_LIVE)), + (insn->flags & (JIT_INSN_VALUE1_NEXT_USE | + JIT_INSN_VALUE1_LIVE)), 0); + offset = jit_value_get_nint_constant(insn->value2); + size = (jit_nint)jit_type_get_size + (jit_value_get_type(insn->value1)); + jit_cache_opcode(&(gen->posn), insn->opcode); + jit_cache_native(&(gen->posn), offset); + jit_cache_native(&(gen->posn), size); + _jit_regs_free_reg(gen, reg, 1); + size = JIT_NUM_ITEMS_IN_STRUCT(size); + adjust_working(gen, -(size + 1)); + } + break; + + case JIT_OP_ADD_RELATIVE: + { + /* Add a relative offset to a pointer */ + reg = _jit_regs_load_to_top + (gen, insn->value1, + (insn->flags & (JIT_INSN_VALUE1_NEXT_USE | + JIT_INSN_VALUE1_LIVE)), 0); + offset = jit_value_get_nint_constant(insn->value2); + if(offset != 0) + { + jit_cache_opcode(&(gen->posn), insn->opcode); + jit_cache_native(&(gen->posn), offset); + } + record_dest(gen, insn, reg); + } + break; + default: { /* Whatever opcodes are left are ordinary operators, -- 2.47.3