Mimic stack is now correctly spilled and reloaded at basic block
boundaries.

Signed-off-by: Arthur HUILLET <arthur.huil...@free.fr>
---
 jit/bytecode-to-ir.c |  155 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 141 insertions(+), 14 deletions(-)

diff --git a/jit/bytecode-to-ir.c b/jit/bytecode-to-ir.c
index 862a335..52d872f 100644
--- a/jit/bytecode-to-ir.c
+++ b/jit/bytecode-to-ir.c
@@ -102,28 +102,24 @@ void convert_statement(struct parse_context *ctx, struct 
statement *stmt)
 
 static int spill_expression(struct basic_block *bb,
                            struct stack *reload_stack,
-                           struct expression *expr)
+                           struct expression *expr, int slotnb)
 {
-       struct compilation_unit *cu = bb->b_parent;
-       struct var_info *tmp_low, *tmp_high;
        struct statement *store, *branch;
-       struct expression *tmp;
+       struct expression *exit_tmp, *entry_tmp;
 
-       tmp_low = get_var(cu);
-       if (expr->vm_type == J_LONG)
-               tmp_high = get_var(cu);
-       else
-               tmp_high = NULL;
+       exit_tmp = mimic_stack_expr(expr->vm_type, 0, slotnb);
+       entry_tmp = mimic_stack_expr(expr->vm_type, 1, slotnb);
 
-       tmp = temporary_expr(expr->vm_type, tmp_high, tmp_low);
-       if (!tmp)
+       if (!exit_tmp || !entry_tmp)
                return -ENOMEM;
 
+       bb_add_mimic_stack_expr(bb, exit_tmp);
+
        store = alloc_statement(STMT_STORE);
        if (!store)
                return -ENOMEM;
 
-       store->store_dest = &tmp->node;
+       store->store_dest = &exit_tmp->node;
        store->store_src = &expr->node;
 
        if (bb->has_branch)
@@ -143,7 +139,7 @@ static int spill_expression(struct basic_block *bb,
         * And add a reload expression that is put on the mimic stack of
         * successor basic blocks.
         */
-       stack_push(reload_stack, expr_get(tmp));
+       stack_push(reload_stack, expr_get(entry_tmp));
 
        return 0;
 }
@@ -160,15 +156,18 @@ static struct stack *spill_mimic_stack(struct basic_block 
*bb)
         * The reload stack contains elements in reverse order of the mimic
         * stack.
         */
+       int spillcount = 0;
        while (!stack_is_empty(bb->mimic_stack)) {
                struct expression *expr;
                int err;
 
                expr = stack_pop(bb->mimic_stack);
 
-               err = spill_expression(bb, reload_stack, expr);
+               err = spill_expression(bb, reload_stack, expr, spillcount);
                if (err)
                        goto error_oom;
+
+               spillcount++;
        }
        return reload_stack;
 error_oom:
@@ -259,6 +258,8 @@ static int convert_bb_to_ir(struct basic_block *bb)
 
                        expr_get(expr);
 
+                       bb_add_mimic_stack_expr(s, expr);
+
                        stack_push(s->mimic_stack, expr);
                }
                expr_put(expr);
@@ -276,6 +277,121 @@ out:
        return err;
 }
 
+static void assign_temporary(struct basic_block *bb, int entry, int slotnb,
+               struct var_info *tmp_high, struct var_info *tmp_low)
+{
+               unsigned int i;
+               struct expression *expr;
+
+               for (i = 0; i < bb->nr_mimic_stack_expr; i++) {
+                       expr = bb->mimic_stack_expr[i];
+
+                       if (expr_type(expr) != EXPR_MIMIC_STACK_SLOT)
+                               continue;
+
+                       if (expr->entry != entry ||
+                                       expr->slotnb != slotnb)
+                               continue;
+
+                       expr_set_type(expr, EXPR_TEMPORARY);
+                       expr->tmp_high = tmp_high;
+                       expr->tmp_low = tmp_low;
+               }
+}
+
+static void pick_and_propagate_temporaries(struct basic_block *bb, int entry)
+{
+       struct expression *expr;
+       struct var_info *tmp_high, *tmp_low;
+       struct basic_block **neighbors;
+       int neighbors_nr;
+       unsigned int i;
+       int slotnb;
+
+       if (entry) {
+               neighbors = bb->predecessors;
+               neighbors_nr = bb->nr_predecessors;
+       } else {
+               neighbors = bb->successors;
+               neighbors_nr = bb->nr_successors;
+       }
+
+       for (i = 0; i < bb->nr_mimic_stack_expr; i++) {
+               expr = bb->mimic_stack_expr[i];
+
+               /* Skip expressions that already been transformed */
+               if (expr_type(expr) != EXPR_MIMIC_STACK_SLOT)
+                       continue;
+
+               /* Skip slots related to the exit when treating entrance
+                * and vice versa */
+               if (expr->entry != entry)
+                       continue;
+
+               tmp_low = get_var(bb->b_parent);
+               if (expr->vm_type == J_LONG)
+                       tmp_high = get_var(bb->b_parent);
+               else tmp_high = NULL;
+
+               /* Save the slot number */
+               slotnb = expr->slotnb;
+
+               /* Assign this temporary to same mimic stack expressions in 
this block */
+               assign_temporary(bb, entry, expr->slotnb, tmp_high, tmp_low);
+
+               int b;
+               for (b = 0; b < neighbors_nr; b++)
+                       assign_temporary(neighbors[b], !entry, slotnb, 
tmp_high, tmp_low);
+       }
+}
+
+static int __do_resolve_mimic_stack_slots(int nr_neighbors, struct basic_block 
**neighbors,
+               int entry)
+{
+       /* No successors? We have nothing to do */
+       if (!nr_neighbors) {
+               return 0;
+       }
+
+       /* Are we a slave? */
+       if (nr_neighbors == 1) {
+               struct basic_block *n = neighbors[0];
+               int nr_connect;
+
+               if (entry)
+                       nr_connect = n->nr_successors;
+               else
+                       nr_connect = n->nr_predecessors;
+
+               if (nr_connect == 1) {
+                       /* Slave-slave relationship, we can pick a temporary */
+                       return 1;
+               } else {
+                       /* Slave-master, do nothing */
+                       return 0;
+               }
+       } else {
+               /* A master always picks his temporaries */
+               return 1;
+       }
+}
+
+/**
+ * resolve_mimic_stack_slots - Transform the mimic stack slots expressions
+ * of the basic bloc into temporary expressions, based on
+ * master/slave properties depending on the number of successors and 
predecessors.
+ */
+static int resolve_mimic_stack_slots(struct basic_block *bb)
+{
+       if (__do_resolve_mimic_stack_slots(bb->nr_successors, bb->successors, 
0))
+               pick_and_propagate_temporaries(bb, 0);
+
+       if (__do_resolve_mimic_stack_slots(bb->nr_predecessors, 
bb->predecessors, 1))
+               pick_and_propagate_temporaries(bb, 1);
+
+       return 0;
+}
+
 /**
  *     convert_to_ir - Convert bytecode to intermediate representation.
  *     @compilation_unit: compilation unit to convert.
@@ -305,5 +421,16 @@ int convert_to_ir(struct compilation_unit *cu)
                if (err)
                        break;
        }
+
+       /*
+        * Connect mimic stacks between basic blocks by changing
+        * each EXPR_MIMIC_STACK_SLOT into an EXPR_TEMPORARY
+        */
+       for_each_basic_block(bb, &cu->bb_list) {
+               err = resolve_mimic_stack_slots(bb);
+               if (err)
+                       break;
+       }
+
        return err;
 }
-- 
1.6.2.2



------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to