Hi, if you apply this series, you can help me work on the bug.
On Thu, 23 Jul 2009 23:24:50 +0200 Arthur HUILLET <arthur.huil...@free.fr> wrote: > 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 \ > -- Greetings, A. Huillet ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel