From: Arthur Huillet <arthur.huil...@free.fr> DO NOT MERGE THIS !!!
Signed-off-by: Arthur Huillet <arthur.huil...@free.fr> diff --git a/Makefile b/Makefile index 58ad9db..55de435 100644 --- a/Makefile +++ b/Makefile @@ -256,6 +256,7 @@ REGRESSION_TEST_SUITE_CLASSES = \ regression/jvm/PutstaticTest.class \ regression/jvm/RegisterAllocatorTortureTest.class \ regression/jvm/StringTest.class \ + regression/jvm/SubstringTest.class \ regression/jvm/SynchronizationExceptionsTest.class \ regression/jvm/SynchronizationTest.class \ regression/jvm/TestCase.class \ diff --git a/arch/mmix/include/arch/instruction.h b/arch/mmix/include/arch/instruction.h index 54ec353..0ce9377 100644 --- a/arch/mmix/include/arch/instruction.h +++ b/arch/mmix/include/arch/instruction.h @@ -88,6 +88,19 @@ reload_insn(struct stack_slot *slot, struct var_info *var) } static inline struct insn * +push_slot_insn(struct stack_slot *slot) +{ + /* XXX */ + return NULL; +} + +static inline struct insn * +pop_slot_insn(struct stack_slot *slot) +{ + return NULL; +} + +static inline struct insn * exception_spill_insn(struct stack_slot *slot) { return NULL; @@ -99,6 +112,11 @@ void free_insn(struct insn *); bool insn_defs(struct insn *, struct var_info *); bool insn_uses(struct insn *, struct var_info *); +static inline const char *reg_name(enum machine_reg reg) +{ + return "<unknown>"; +} + #define for_each_insn(insn, insn_list) list_for_each_entry(insn, insn_list, insn_list_node) #endif /* __ARCH_INSTRUCTION_H */ diff --git a/arch/x86/include/arch/instruction.h b/arch/x86/include/arch/instruction.h index aa29bbe..f8c474f 100644 --- a/arch/x86/include/arch/instruction.h +++ b/arch/x86/include/arch/instruction.h @@ -208,6 +208,18 @@ reload_insn(struct stack_slot *slot, struct var_info *var) return NULL; } +static inline struct insn * +push_slot_insn(struct stack_slot *from) +{ + return memlocal_insn(INSN_PUSH_MEMLOCAL, from); +} + +static inline struct insn * +pop_slot_insn(struct stack_slot *to) +{ + return memlocal_insn(INSN_POP_MEMLOCAL, to); +} + struct insn *alloc_insn(enum insn_type); void free_insn(struct insn *); diff --git a/jit/spill-reload.c b/jit/spill-reload.c index 94d2af7..e8eede4 100644 --- a/jit/spill-reload.c +++ b/jit/spill-reload.c @@ -30,8 +30,17 @@ #include "arch/instruction.h" +#include "lib/bitset.h" + #include <errno.h> +#include <stdio.h> +#include <string.h> + +struct live_interval_mapping { + struct live_interval *from, *to; +}; + static struct insn *last_insn(struct live_interval *interval) { unsigned long end; @@ -44,13 +53,11 @@ static struct insn *last_insn(struct live_interval *interval) return ret; } -static int insert_spill_insn(struct live_interval *interval, struct compilation_unit *cu) +static struct stack_slot *spill_interval(struct live_interval *interval, struct compilation_unit *cu, struct insn *last) { - struct insn *last = last_insn(interval); struct stack_slot *slot; struct var_info *reg; struct insn *spill; - /* * We've already done register allocation, so use fixed registers for * spilling and reloading. @@ -59,18 +66,26 @@ static int insert_spill_insn(struct live_interval *interval, struct compilation_ slot = get_spill_slot_32(cu->stack_frame); if (!slot) - return -ENOMEM; + return NULL; spill = spill_insn(reg, slot); if (!spill) - return -ENOMEM; - - interval->spill_slot = slot; + return NULL; spill->bytecode_offset = last->bytecode_offset; list_add(&spill->insn_list_node, &last->insn_list_node); + return slot; +} + +static int insert_spill_insn(struct live_interval *interval, struct compilation_unit *cu) +{ + interval->spill_slot = spill_interval(interval, cu, last_insn(interval)); + + if (!interval->spill_slot) + return -ENOMEM; + return 0; } @@ -84,14 +99,13 @@ static struct insn *first_insn(struct live_interval *interval) return ret; } -static int insert_reload_insn(struct live_interval *interval, struct compilation_unit *cu) +static int insert_reload_insn(struct live_interval *interval, struct compilation_unit *cu, struct stack_slot *from, struct insn *first) { - struct insn *first = first_insn(interval); struct insn *reload; struct var_info *reg; reg = get_fixed_var(cu, interval->reg); - reload = reload_insn(interval->spill_parent->spill_slot, reg); + reload = reload_insn(from, reg); if (!reload) return -ENOMEM; @@ -102,6 +116,27 @@ static int insert_reload_insn(struct live_interval *interval, struct compilation return 0; } +static int insert_copy_slot_insn(struct live_interval *interval, struct compilation_unit *cu, struct stack_slot *from, struct stack_slot *to, + struct insn *push_at_insn, struct insn *pop_at_insn) +{ + struct insn *push, *pop; + + printf("insert_copy_slot_insn from %#x to %#x\n", (unsigned int)from, (unsigned int)to); + push = push_slot_insn(from); + pop = pop_slot_insn(to); + if (!push || !pop) + return -ENOMEM; + + push->bytecode_offset = 666;//>bytecode_offset; + pop->bytecode_offset = 666;//>bytecode_offset; + + list_add(&push->insn_list_node, &push_at_insn->insn_list_node); + list_add(&pop->insn_list_node, &push->insn_list_node); + + return 0; + +} + static int __insert_spill_reload_insn(struct live_interval *interval, struct compilation_unit *cu) { int err = 0; @@ -110,7 +145,7 @@ static int __insert_spill_reload_insn(struct live_interval *interval, struct com goto out; if (interval->need_reload) { - err = insert_reload_insn(interval, cu); + err = insert_reload_insn(interval, cu, interval->spill_parent->spill_slot, first_insn(interval)); if (err) goto out; } @@ -124,6 +159,125 @@ out: return err; } +static void maybe_add_mov_for_vreg(struct compilation_unit *cu, struct basic_block *from, struct basic_block *to, unsigned long vreg, struct live_interval_mapping *mappings, int *nrmapped) +{ + struct live_interval *parent_it; + struct live_interval *from_it, *to_it; + + parent_it = vreg_start_interval(cu, vreg); + from_it = interval_child_at(parent_it, from->end); + to_it = interval_child_at(parent_it, to->start); + + /* The intervals are the same on both sides of the basic block edge: + * nothing to do + */ + if (from_it == to_it) { + return; + } + + /* We seem to have some vregs that are alive at the beginning of a bb, + * but have no interval covering them. In that case, no mov is to be inserted. + */ + if (!from_it || !to_it) { + printf("from it %#x to it %#x, from end %lu, to start %lu, vreg %d\n", (unsigned int)from_it, (unsigned int)to_it, (unsigned long) from->end, (unsigned long)to->start, (int)parent_it->var_info->vreg); + return; + } + + /* If any of the intervals have no register assigned at this point, + * it is because the register allocator found out the interval is useless. + * In that case, we need to find what the *real* destination interval is. + */ + while (to_it->reg == REG_UNASSIGNED) { + printf("to it is unassigned, start %lu, vreg %d\n", (unsigned long) to_it->range.start, (int)to_it->var_info->vreg); + + to_it = to_it->next_child; + assert(to_it); + + printf("picked it start %lu, reg %s\n", (unsigned long) to_it->range.start, reg_name(to_it->reg)); + } + + if (from_it->reg == REG_UNASSIGNED) { + printf("from it is unassigned, start %lu, vreg %d\n", (unsigned long) from_it->range.start, (int)from_it->var_info->vreg); + return; + from_it = from_it->spill_parent; + assert(from_it); + } + + printf("vreg %lu at position %lu is not in the same interval as in position %lu...\n", vreg, from->end, to->start); + mappings[*nrmapped].from = from_it; + mappings[*nrmapped].to = to_it; + (*nrmapped)++; +} + +#include "jit/lir-printer.h" +#include "lib/buffer.h" +#include "lib/string.h" + +static void insert_mov_insns(struct compilation_unit *cu, struct live_interval_mapping *mappings, int nrmapped, + struct basic_block *from_bb, struct basic_block *to_bb) +{ + int i; + struct stack_slot *slots[nrmapped]; + struct insn *spill_at_insn, *reload_at_insn; + + /* Spill all intervals that have to be resolved */ + for (i = 0; i < nrmapped; i++) { + printf("mapping it %#x to it %#x frombb %#x tobb %#x\n", (unsigned int)mappings[i].from, (unsigned int)mappings[i].to, (unsigned int)from_bb, (unsigned int)to_bb); + spill_at_insn = bb_last_insn(from_bb); + struct string *str = alloc_str(); + lir_print(spill_at_insn, str); + printf("aezraezr %s\n", str->value); + free_str(str); + + if (mappings[i].from->need_spill) + slots[i] = mappings[i].from->spill_slot; + else + slots[i] = spill_interval(mappings[i].from, cu, spill_at_insn); + + /* Reload those intervals into their new location */ + reload_at_insn = bb_first_insn(to_bb); + str = alloc_str(); + lir_print(reload_at_insn, str); + printf("aezreload %s\n", str->value); + free_str(str); + + if (mappings[i].to->need_reload) { + printf("inserting copy slot insn\n"); + insert_copy_slot_insn(mappings[i].to, cu, slots[i], mappings[i].to->spill_parent->spill_slot, spill_at_insn, reload_at_insn); + } else { + insert_reload_insn(mappings[i].from, cu, slots[i], reload_at_insn); + } + } +} + +static void resolve_data_flow(struct compilation_unit *cu) +{ + struct basic_block *this, *succ; + unsigned int isucc; + unsigned long vreg; + + /* This implements the algorithm ResolveDataFlow described by + * Christian Wimmer in 2004 */ + for_each_basic_block(this, &cu->bb_list) { + for (isucc = 0; isucc < this->nr_successors; isucc++) { + struct live_interval_mapping mappings[this->nr_predecessors]; + int nrmapped = 0; + + memset(mappings, 0, this->nr_predecessors * sizeof(struct live_interval_mapping)); + + succ = this->successors[isucc]; + + for (vreg = 0; vreg < cu->nr_vregs; vreg++) { + if (test_bit(succ->live_in_set->bits, vreg)) { + maybe_add_mov_for_vreg(cu, this, succ, vreg, mappings, &nrmapped); + } + } + + insert_mov_insns(cu, mappings, nrmapped, this, succ); + } + } +} + int insert_spill_reload_insns(struct compilation_unit *cu) { struct var_info *var; @@ -138,5 +292,9 @@ int insert_spill_reload_insns(struct compilation_unit *cu) break; } } + + /* Make sure intervals spilled across basic block boundaries will + * be reloaded correctly */ + resolve_data_flow(cu); return err; } diff --git a/regression/jvm/PrintTest.java b/regression/jvm/PrintTest.java index d0789e6..3018829 100644 --- a/regression/jvm/PrintTest.java +++ b/regression/jvm/PrintTest.java @@ -31,7 +31,6 @@ package jvm; public class PrintTest extends TestCase { public static void main(String[] args) { /* FIXME - System.out.write(4); -*/ +*/ System.out.println("ae"); } } diff --git a/test/jit/Makefile b/test/jit/Makefile index 80151f7..b410520 100644 --- a/test/jit/Makefile +++ b/test/jit/Makefile @@ -27,6 +27,7 @@ OBJS = \ ../../jit/interval.o \ ../../jit/invoke-bc.o \ ../../jit/linear-scan.o \ + ../../jit/lir-printer.o \ ../../jit/liveness.o \ ../../jit/load-store-bc.o \ ../../jit/method.o \ ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel