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

Reply via email to