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

Reply via email to