Signed-off-by: Arthur Huillet <arthur.huil...@free.fr> --- Hi,
this is my work in progress patch. It does not make substringtest work yet, and I'm afraid I won't be able to get it done today as I was planning to. I am not sure what went wrong yet. Anyway you have my complete patch, including some debug code, some review would be appreciated, keeping in mind that it doesn't work yet. Thanks. Makefile | 1 + arch/x86/include/arch/instruction.h | 18 ++++++- include/jit/basic-block.h | 2 + jit/basic-block.c | 10 ++++ jit/spill-reload.c | 93 +++++++++++++++++++++++++++++------ regression/jvm/PrintTest.java | 3 +- test/include/arch/instruction.h | 13 +++++ 7 files changed, 121 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 579afa6..d7c338d 100644 --- a/Makefile +++ b/Makefile @@ -257,6 +257,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/x86/include/arch/instruction.h b/arch/x86/include/arch/instruction.h index 5ac90d3..49cbb9e 100644 --- a/arch/x86/include/arch/instruction.h +++ b/arch/x86/include/arch/instruction.h @@ -180,7 +180,7 @@ struct insn *membase_insn(enum insn_type, struct var_info *, long); * These functions are used by generic code to insert spill/reload * instructions. */ - +#include <stdio.h> static inline struct insn * spill_insn(struct var_info *var, struct stack_slot *slot) { @@ -188,8 +188,10 @@ spill_insn(struct var_info *var, struct stack_slot *slot) return reg_memlocal_insn(INSN_MOV_REG_MEMLOCAL, var, slot); else if (var->type == REG_TYPE_FPU) return reg_memlocal_insn(INSN_MOV_FREG_MEMLOCAL, var, slot); - else + else { + printf("trying to spill insn of type %d\n", var->type); return NULL; + } } static inline struct insn * @@ -203,6 +205,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/include/jit/basic-block.h b/include/jit/basic-block.h index 74ee47d..28ca6b2 100644 --- a/include/jit/basic-block.h +++ b/include/jit/basic-block.h @@ -70,6 +70,8 @@ void free_basic_block(struct basic_block *); struct basic_block *bb_split(struct basic_block *, unsigned long); void bb_add_stmt(struct basic_block *, struct statement *); void bb_add_insn(struct basic_block *, struct insn *); +struct insn *bb_first_insn(struct basic_block *); +struct insn *bb_last_insn(struct basic_block *); int bb_add_successor(struct basic_block *, struct basic_block *); int bb_add_mimic_stack_expr(struct basic_block *, struct expression *); struct statement *bb_remove_last_stmt(struct basic_block *bb); diff --git a/jit/basic-block.c b/jit/basic-block.c index bd1cbe1..0a13062 100644 --- a/jit/basic-block.c +++ b/jit/basic-block.c @@ -147,6 +147,16 @@ void bb_add_insn(struct basic_block *bb, struct insn *insn) list_add_tail(&insn->insn_list_node, &bb->insn_list); } +struct insn *bb_first_insn(struct basic_block *bb) +{ + return list_entry(bb->insn_list.next, struct insn, insn_list_node); +} + +struct insn *bb_last_insn(struct basic_block *bb) +{ + return list_entry(bb->insn_list.prev, struct insn, insn_list_node); +} + static int __bb_add_neighbor(void *new, void **array, unsigned long *nb) { unsigned long new_size; diff --git a/jit/spill-reload.c b/jit/spill-reload.c index 4d1c409..d3f47b4 100644 --- a/jit/spill-reload.c +++ b/jit/spill-reload.c @@ -53,12 +53,11 @@ static struct insn *last_insn(struct live_interval *interval) return ret; } -static struct stack_slot *spill_interval(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 stack_slot *slot; struct var_info *reg; struct insn *spill; - struct insn *last = last_insn(interval); /* * We've already done register allocation, so use fixed registers for * spilling and reloading. @@ -82,7 +81,7 @@ static struct stack_slot *spill_interval(struct live_interval *interval, struct static int insert_spill_insn(struct live_interval *interval, struct compilation_unit *cu) { - interval->spill_slot = spill_interval(interval, cu); + interval->spill_slot = spill_interval(interval, cu, last_insn(interval)); if (!interval->spill_slot) return -ENOMEM; @@ -100,9 +99,8 @@ static struct insn *first_insn(struct live_interval *interval) return ret; } -static int insert_reload_insn(struct live_interval *interval, struct compilation_unit *cu, struct stack_slot *from) +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; @@ -118,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; @@ -126,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, interval->spill_parent->spill_slot); + err = insert_reload_insn(interval, cu, interval->spill_parent->spill_slot, first_insn(interval)); if (err) goto out; } @@ -148,6 +167,13 @@ static void maybe_add_mov_for_vreg(struct compilation_unit *cu, struct basic_blo 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. @@ -155,32 +181,69 @@ static void maybe_add_mov_for_vreg(struct compilation_unit *cu, struct basic_blo if (!from_it || !to_it) return; - if (from_it != to_it) { - printf("vreg %lu at position %lu is not in the same interval...\n", vreg, from->end); + /* 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)++; - } } -static void insert_mov_insns(struct compilation_unit *cu, struct live_interval_mapping *mappings, int 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\n", (unsigned int)mappings[i].from, (unsigned int)mappings[i].to); + 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); + 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) { - NOT_IMPLEMENTED; + 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]); + insert_reload_insn(mappings[i].from, cu, slots[i], reload_at_insn); } } } @@ -208,7 +271,7 @@ static void resolve_data_flow(struct compilation_unit *cu) } } - insert_mov_insns(cu, mappings, nrmapped); + insert_mov_insns(cu, mappings, nrmapped, this, succ); } } } 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/include/arch/instruction.h b/test/include/arch/instruction.h index 54ec353..4283da7 100644 --- a/test/include/arch/instruction.h +++ b/test/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; -- 1.5.6.3 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel