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