[PATCH 2/3] x86: make insn_is_branch() return true for INSN_RET

2009-08-19 Thread Tomek Grabiec
INSN_RET should be considered a branch because it jumps to different
basic block. It is used in LIR for athrow.

Signed-off-by: Tomek Grabiec tgrab...@gmail.com
---
 arch/x86/include/arch/instruction.h |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/arch/instruction.h 
b/arch/x86/include/arch/instruction.h
index b9d71b9..962dc0a 100644
--- a/arch/x86/include/arch/instruction.h
+++ b/arch/x86/include/arch/instruction.h
@@ -321,6 +321,7 @@ static inline bool insn_is_branch(struct insn *insn)
case INSN_JMP_MEMBASE:
case INSN_JMP_MEMINDEX:
case INSN_JNE_BRANCH:
+   case INSN_RET:
return true;
default:
return false;
-- 
1.6.3.3


--
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
___
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel


[RFC][PATCH 3/3] jit: fix data flow resolution code in presence of empty basic blocks.

2009-08-19 Thread Tomek Grabiec
Data flow resolution code assumed that basic blocks always contain
some struct insn, before which spill/reload instructions can be
put. When data flow resolution was run on empty basic block, it worked
on invalid struct insn pointer and entered infinite loop.

This patch also fixes another bug. Data flow resolution didn't work
correctly when basic block in which spill occurs was not ended by a
branch. That's because in this case spill was inserted after the last
instruction, which is correct, but the corresponding spill slot moves
(push+pop) were inserted before last instruction - before the slot was
assigned a correct value.

Empty basic blocks can be a result of the following bytecode:

  iconst_0
  iconst_1
  ifeq lab
  pop  // This and the next instruction generate no
  iconst_1 // LIR instructions.
lab:
  

Cc: Arthur HUILLET arthur.huil...@free.fr
Signed-off-by: Tomek Grabiec tgrab...@gmail.com
---
 include/jit/basic-block.h |1 -
 jit/basic-block.c |   19 
 jit/spill-reload.c|   70 ++---
 3 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/include/jit/basic-block.h b/include/jit/basic-block.h
index e50f6c6..d5452a4 100644
--- a/include/jit/basic-block.h
+++ b/include/jit/basic-block.h
@@ -81,7 +81,6 @@ 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 6de5c3f..bcb2866 100644
--- a/jit/basic-block.c
+++ b/jit/basic-block.c
@@ -174,25 +174,6 @@ 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)
-{
-   struct insn *this = list_entry(bb-insn_list.prev, struct insn, 
insn_list_node);
-
-   /*
-* We want to return the last real instruction of the basic block. 
Taking the
-* last of the insn_list will not work in case a live interval has been 
spilled
-* right after the final jump of the basic block.
-* This is a side effect of the linear scan algorithm.
-*
-* As a result, we browse instructions starting from the last, in order 
to find the one
-* that has a LIR position matching the position for the end of the 
block.
-*/
-   while (this-lir_pos != bb-end_insn - 1) {
-   this = list_entry(this-insn_list_node.prev, struct insn, 
insn_list_node);
-   }
-   return this;
-}
-
 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 5ced80e..af50046 100644
--- a/jit/spill-reload.c
+++ b/jit/spill-reload.c
@@ -25,6 +25,7 @@
  */
 
 #include jit/compilation-unit.h
+#include jit/instruction.h
 #include jit/stack-slot.h
 #include jit/compiler.h
 
@@ -65,10 +66,40 @@ static struct insn *last_insn(struct compilation_unit *cu, 
struct live_interval
return ret;
 }
 
+/**
+ * Returns the node before which spill instructions should be inserted
+ * when they are supposed to be executed just before control leaves
+ * given basic block. When basic block is ended with a branch
+ * instruction it returns node of that branch; otherwise it returns
+ * the next node.
+ */
+static struct list_head *bb_last_spill_node(struct basic_block *bb)
+{
+   struct insn *last;
+
+   /*
+* basic block's instruction list might not be empty and
+* contain only spill/reload instructions. In this situation
+* we also consider basic block as empty (no lir positions) so
+* we don't rely on -insn_list here.
+*/
+   if (bb-end_insn == bb-start_insn)
+   return bb-insn_list;
+
+   last = radix_tree_lookup(bb-b_parent-lir_insn_map, bb-end_insn - 1);
+   assert(last);
+
+   if (insn_is_branch(last))
+   return last-insn_list_node;
+
+   return last-insn_list_node.next;
+}
+
 static struct stack_slot *
 spill_interval(struct live_interval *interval,
   struct compilation_unit *cu,
-  struct insn *last)
+  struct list_head *spill_before,
+  unsigned long bc_offset)
 {
struct stack_slot *slot;
struct insn *spill;
@@ -81,21 +112,23 @@ spill_interval(struct live_interval *interval,
if (!spill)
return NULL;
 
-   spill-bytecode_offset = last-bytecode_offset;
-
-   if (insn_is_branch(last))
-   list_add_tail(spill-insn_list_node,