Signed-off-by: Tomek Grabiec <[email protected]>
---
arch/x86/insn-selector_32.brg | 38 ++++++++++++++++++++++-------
include/jit/expression.h | 6 ++++
include/jit/statement.h | 3 +-
jit/bytecode-to-ir.c | 1 -
jit/expression.c | 19 +++++++++++++++
jit/object-bc.c | 42 ++++++++++++--------------------
jit/statement.c | 1 -
jit/tree-printer.c | 25 +++++++++++++------
test/arch-x86/insn-selector-test_32.c | 29 ----------------------
test/jit/bc-test-utils.c | 16 ++++++------
test/jit/object-bc-test.c | 8 +----
test/jit/tree-printer-test.c | 25 +++++++++----------
12 files changed, 110 insertions(+), 103 deletions(-)
diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
index 7ba99c4..90f972f 100644
--- a/arch/x86/insn-selector_32.brg
+++ b/arch/x86/insn-selector_32.brg
@@ -744,6 +744,35 @@ reg: EXPR_NEWARRAY(reg)
method_args_cleanup(s, tree, 2);
}
+reg: EXPR_NULL_CHECK(reg)
+{
+ struct var_info *ref;
+
+ ref = state->left->reg1;
+ state->reg1 = ref;
+
+ select_insn(s, tree, membase_reg_insn(INSN_TEST_MEMBASE_REG, ref, 0,
ref));
+}
+
+reg: EXPR_NULL_CHECK(EXPR_LOCAL)
+{
+ struct var_info *reg;
+ struct stack_slot *slot;
+ struct expression *expr;
+ struct expression *local;
+
+ reg = get_var(s->b_parent);
+ state->reg1 = reg;
+
+ expr = to_expr(tree);
+ local = to_expr(expr->null_check_ref);
+
+ slot = get_local_slot(s->b_parent->stack_frame, local->local_index);
+
+ select_insn(s, tree, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG, slot,
reg));
+ select_insn(s, tree, membase_reg_insn(INSN_TEST_MEMBASE_REG, reg, 0,
reg));
+}
+
reg: EXPR_MULTIANEWARRAY(arg)
{
struct var_info *var;
@@ -1115,15 +1144,6 @@ stmt: STMT_ATHROW(reg)
select_insn(s, tree, insn(INSN_RET));
}
-stmt: STMT_NULL_CHECK(reg)
-{
- struct var_info *ref;
-
- ref = state->left->reg1;
-
- select_insn(s, tree, membase_reg_insn(INSN_TEST_MEMBASE_REG, ref, 0,
ref));
-}
-
array_check: EXPR_ARRAY_DEREF(reg, reg) 2
{
struct var_info *base, *index, *state_base, *state_index;
diff --git a/include/jit/expression.h b/include/jit/expression.h
index cca0fde..6319693 100644
--- a/include/jit/expression.h
+++ b/include/jit/expression.h
@@ -32,6 +32,7 @@ enum expression_type {
EXPR_ARRAYLENGTH,
EXPR_INSTANCEOF,
EXPR_EXCEPTION_REF,
+ EXPR_NULL_CHECK,
EXPR_LAST, /* Not a real type. Keep this last. */
};
@@ -225,6 +226,10 @@ struct expression {
struct tree_node *instanceof_ref;
struct object *instanceof_class;
};
+
+ /* EXPR_NULL_CHECK is used to assure that NullPointerException
+ will be thrown if reference is null. */
+ struct tree_node *null_check_ref;
};
};
@@ -276,6 +281,7 @@ struct expression *multianewarray_expr(struct object *);
struct expression *arraylength_expr(struct expression *);
struct expression *instanceof_expr(struct expression *, struct object *);
struct expression *exception_ref_expr(void);
+struct expression *null_check_expr(struct expression *);
unsigned long nr_args(struct expression *);
diff --git a/include/jit/statement.h b/include/jit/statement.h
index 9041e0d..99e84b1 100644
--- a/include/jit/statement.h
+++ b/include/jit/statement.h
@@ -13,7 +13,6 @@ enum statement_type {
STMT_RETURN,
STMT_VOID_RETURN,
STMT_EXPRESSION,
- STMT_NULL_CHECK,
STMT_ARRAY_CHECK,
STMT_ATHROW,
STMT_MONITOR_ENTER,
@@ -49,7 +48,7 @@ struct statement {
struct /* STMT_ATHROW */ {
struct tree_node *exception_ref;
};
- /* STMT_EXPRESSION, STMT_NULL_CHECK, STMT_ARRAY_CHECK */
+ /* STMT_EXPRESSION, STMT_ARRAY_CHECK */
struct tree_node *expression;
};
struct list_head stmt_list_node;
diff --git a/jit/bytecode-to-ir.c b/jit/bytecode-to-ir.c
index 1577359..386abbb 100644
--- a/jit/bytecode-to-ir.c
+++ b/jit/bytecode-to-ir.c
@@ -253,7 +253,6 @@ void convert_statement(struct parse_context *ctx, struct
statement *stmt)
tree_patch_bc_offset(stmt->return_value, bc_offset);
break;
case STMT_EXPRESSION:
- case STMT_NULL_CHECK:
case STMT_ARRAY_CHECK:
tree_patch_bc_offset(stmt->expression, bc_offset);
break;
diff --git a/jit/expression.c b/jit/expression.c
index e3a6932..d35b597 100644
--- a/jit/expression.c
+++ b/jit/expression.c
@@ -102,6 +102,9 @@ void free_expression(struct expression *expr)
case EXPR_EXCEPTION_REF:
/* nothing to do */
break;
+ case EXPR_NULL_CHECK:
+ expr_put(to_expr(expr->null_check_ref));
+ break;
case EXPR_LAST:
assert(!"EXPR_LAST is not a real type. Don't use it");
break;
@@ -361,3 +364,19 @@ struct expression *exception_ref_expr(void)
{
return alloc_expression(EXPR_EXCEPTION_REF, J_REFERENCE);
}
+
+struct expression *null_check_expr(struct expression *ref)
+{
+ struct expression *expr;
+
+ expr = alloc_expression(EXPR_NULL_CHECK, J_REFERENCE);
+ if (!expr)
+ return NULL;
+
+ assert(ref->vm_type == J_REFERENCE);
+
+ expr->bytecode_offset = ref->bytecode_offset;
+ expr->null_check_ref = &ref->node;
+
+ return expr;
+}
diff --git a/jit/object-bc.c b/jit/object-bc.c
index 377da0f..13c3afc 100644
--- a/jit/object-bc.c
+++ b/jit/object-bc.c
@@ -158,9 +158,9 @@ int convert_putfield(struct parse_context *ctx)
int convert_array_load(struct parse_context *ctx, enum vm_type type)
{
- struct expression *index, *arrayref;
+ struct expression *index, *arrayref, *arrayref_nullcheck;
struct expression *src_expr, *dest_expr;
- struct statement *store_stmt, *arraycheck, *nullcheck;
+ struct statement *store_stmt, *arraycheck;
struct var_info *temporary;
index = stack_pop(ctx->bb->mimic_stack);
@@ -170,7 +170,11 @@ int convert_array_load(struct parse_context *ctx, enum
vm_type type)
if (!store_stmt)
goto failed;
- src_expr = array_deref_expr(type, arrayref, index);
+ arrayref_nullcheck = null_check_expr(arrayref);
+ if (!arrayref_nullcheck)
+ goto failed_arrayref_nullcheck;
+
+ src_expr = array_deref_expr(type, arrayref_nullcheck, index);
temporary = get_var(ctx->cu);
dest_expr = temporary_expr(type, NULL, temporary);
@@ -188,22 +192,13 @@ int convert_array_load(struct parse_context *ctx, enum
vm_type type)
expr_get(src_expr);
arraycheck->expression = &src_expr->node;
- nullcheck = alloc_statement(STMT_NULL_CHECK);
- if (!nullcheck)
- goto failed_nullcheck;
-
- expr_get(arrayref);
- nullcheck->expression = &arrayref->node;
-
- convert_statement(ctx, nullcheck);
convert_statement(ctx, arraycheck);
convert_statement(ctx, store_stmt);
return 0;
- failed_nullcheck:
- free_statement(arraycheck);
failed_arraycheck:
+ failed_arrayref_nullcheck:
free_statement(store_stmt);
failed:
return -ENOMEM;
@@ -251,8 +246,8 @@ int convert_saload(struct parse_context *ctx)
static int convert_array_store(struct parse_context *ctx, enum vm_type type)
{
- struct expression *value, *index, *arrayref;
- struct statement *store_stmt, *arraycheck, *nullcheck;
+ struct expression *value, *index, *arrayref, *arrayref_nullcheck;
+ struct statement *store_stmt, *arraycheck;
struct expression *src_expr, *dest_expr;
value = stack_pop(ctx->bb->mimic_stack);
@@ -263,7 +258,11 @@ static int convert_array_store(struct parse_context *ctx,
enum vm_type type)
if (!store_stmt)
goto failed;
- dest_expr = array_deref_expr(type, arrayref, index);
+ arrayref_nullcheck = null_check_expr(arrayref);
+ if (!arrayref_nullcheck)
+ goto failed_arrayref_nullcheck;
+
+ dest_expr = array_deref_expr(type, arrayref_nullcheck, index);
src_expr = value;
store_stmt->store_dest = &dest_expr->node;
@@ -276,22 +275,13 @@ static int convert_array_store(struct parse_context *ctx,
enum vm_type type)
expr_get(dest_expr);
arraycheck->expression = &dest_expr->node;
- nullcheck = alloc_statement(STMT_NULL_CHECK);
- if (!nullcheck)
- goto failed_nullcheck;
-
- expr_get(arrayref);
- nullcheck->expression = &arrayref->node;
-
- convert_statement(ctx, nullcheck);
convert_statement(ctx, arraycheck);
convert_statement(ctx, store_stmt);
return 0;
- failed_nullcheck:
- free_statement(arraycheck);
failed_arraycheck:
+ failed_arrayref_nullcheck:
free_statement(store_stmt);
failed:
return -ENOMEM;
diff --git a/jit/statement.c b/jit/statement.c
index 60805e1..34b2725 100644
--- a/jit/statement.c
+++ b/jit/statement.c
@@ -49,7 +49,6 @@ void free_statement(struct statement *stmt)
case STMT_VOID_RETURN:
break;
case STMT_EXPRESSION:
- case STMT_NULL_CHECK:
case STMT_ARRAY_CHECK:
case STMT_MONITOR_ENTER:
case STMT_MONITOR_EXIT:
diff --git a/jit/tree-printer.c b/jit/tree-printer.c
index ceff2c6..c00954b 100644
--- a/jit/tree-printer.c
+++ b/jit/tree-printer.c
@@ -216,12 +216,6 @@ static int print_expression_stmt(int lvl, struct string
*str,
return print_expr_stmt(lvl, str, "EXPRESSION", stmt);
}
-static int print_null_check_stmt(int lvl, struct string *str,
- struct statement *stmt)
-{
- return print_expr_stmt(lvl, str, "NULL_CHECK", stmt);
-}
-
static int print_array_check_stmt(int lvl, struct string *str,
struct statement *stmt)
{
@@ -283,7 +277,6 @@ static print_stmt_fn stmt_printers[] = {
[STMT_RETURN] = print_return_stmt,
[STMT_VOID_RETURN] = print_void_return_stmt,
[STMT_EXPRESSION] = print_expression_stmt,
- [STMT_NULL_CHECK] = print_null_check_stmt,
[STMT_ARRAY_CHECK] = print_array_check_stmt,
[STMT_MONITOR_ENTER] = print_monitor_enter_stmt,
[STMT_MONITOR_EXIT] = print_monitor_exit_stmt,
@@ -721,6 +714,21 @@ static int print_exception_ref_expr(int lvl, struct string
*str, struct expressi
return str_append(str, "[exception object reference]\n");
}
+static int print_null_check_expr(int lvl, struct string *str,
+ struct expression *expr)
+{
+ int err;
+
+ err = append_formatted(lvl, str, "NULL_CHECK:\n");
+ if (err)
+ goto out;
+
+ err = append_tree_attr(lvl + 1, str, "ref", expr->null_check_ref);
+
+ out:
+ return err;
+}
+
typedef int (*print_expr_fn) (int, struct string * str, struct expression *);
static print_expr_fn expr_printers[] = {
@@ -745,7 +753,8 @@ static print_expr_fn expr_printers[] = {
[EXPR_MULTIANEWARRAY] = print_multianewarray_expr,
[EXPR_ARRAYLENGTH] = print_arraylength_expr,
[EXPR_INSTANCEOF] = print_instanceof_expr,
- [EXPR_EXCEPTION_REF] = print_exception_ref_expr
+ [EXPR_EXCEPTION_REF] = print_exception_ref_expr,
+ [EXPR_NULL_CHECK] = print_null_check_expr
};
static int print_expr(int lvl, struct tree_node *root, struct string *str)
diff --git a/test/arch-x86/insn-selector-test_32.c
b/test/arch-x86/insn-selector-test_32.c
index db43765..319b63a 100644
--- a/test/arch-x86/insn-selector-test_32.c
+++ b/test/arch-x86/insn-selector-test_32.c
@@ -1485,35 +1485,6 @@ void test_select_goto_stmt(void)
free_compilation_unit(cu);
}
-void test_select_null_check_stmt(void)
-{
- struct compilation_unit *cu;
- struct basic_block *bb;
- struct statement *stmt;
- struct expression *expr;
- struct insn *insn;
- enum machine_reg dreg1;
-
- expr = value_expr(J_REFERENCE, 0xcafebabe);
- stmt = alloc_statement(STMT_NULL_CHECK);
- stmt->expression = &expr->node;
-
- cu = alloc_compilation_unit(&method);
- bb = get_basic_block(cu, 0, 1);
- bb_add_stmt(bb, stmt);
-
- select_instructions(bb->b_parent);
-
- insn = list_first_entry(&bb->insn_list, struct insn, insn_list_node);
- dreg1 = mach_reg(&insn->dest.reg);
- assert_imm_reg_insn(INSN_MOV_IMM_REG, 0xcafebabe, dreg1, insn);
-
- insn = list_next_entry(&insn->insn_list_node, struct insn,
insn_list_node);
- assert_membase_reg_insn(INSN_TEST_MEMBASE_REG, dreg1, 0, dreg1, insn);
-
- free_compilation_unit(cu);
-}
-
void test_select_array_check_stmt(void)
{
struct compilation_unit *cu;
diff --git a/test/jit/bc-test-utils.c b/test/jit/bc-test-utils.c
index 088b408..a3a2657 100644
--- a/test/jit/bc-test-utils.c
+++ b/test/jit/bc-test-utils.c
@@ -99,6 +99,13 @@ void assert_temporary_expr(struct tree_node *node)
assert_int_equals(EXPR_TEMPORARY, expr_type(expr));
}
+void assert_null_check_expr(struct expression *expected,
+ struct expression *actual)
+{
+ assert_int_equals(EXPR_NULL_CHECK, expr_type(actual));
+ assert_ptr_equals(expected, to_expr(actual->null_check_ref));
+}
+
void assert_array_deref_expr(enum vm_type expected_vm_type,
struct expression *expected_arrayref,
struct expression *expected_index,
@@ -108,7 +115,7 @@ void assert_array_deref_expr(enum vm_type expected_vm_type,
assert_int_equals(EXPR_ARRAY_DEREF, expr_type(expr));
assert_int_equals(expected_vm_type, expr->vm_type);
- assert_ptr_equals(expected_arrayref, to_expr(expr->arrayref));
+ assert_null_check_expr(expected_arrayref, to_expr(expr->arrayref));
assert_ptr_equals(expected_index, to_expr(expr->array_index));
}
@@ -204,13 +211,6 @@ void assert_void_return_stmt(struct statement *stmt)
assert_ptr_equals(NULL, stmt->return_value);
}
-void assert_null_check_stmt(struct expression *expected,
- struct statement *actual)
-{
- assert_int_equals(STMT_NULL_CHECK, stmt_type(actual));
- assert_value_expr(J_REFERENCE, expected->value, actual->expression);
-}
-
void assert_arraycheck_stmt(enum vm_type expected_vm_type,
struct expression *expected_arrayref,
struct expression *expected_index,
diff --git a/test/jit/object-bc-test.c b/test/jit/object-bc-test.c
index aaf1016..703421f 100644
--- a/test/jit/object-bc-test.c
+++ b/test/jit/object-bc-test.c
@@ -239,11 +239,9 @@ static void assert_convert_array_load(enum vm_type
expected_type,
convert_to_ir(bb->b_parent);
stmt = stmt_entry(bb->stmt_list.next);
- struct statement *nullcheck = stmt;
- struct statement *arraycheck =
stmt_entry(nullcheck->stmt_list_node.next);
+ struct statement *arraycheck = stmt;
struct statement *store_stmt =
stmt_entry(arraycheck->stmt_list_node.next);
- assert_null_check_stmt(arrayref_expr, nullcheck);
assert_arraycheck_stmt(expected_type, arrayref_expr, index_expr,
arraycheck);
assert_store_stmt(store_stmt);
@@ -336,11 +334,9 @@ static void assert_convert_array_store(enum vm_type
expected_type,
convert_to_ir(bb->b_parent);
stmt = stmt_entry(bb->stmt_list.next);
- struct statement *nullcheck = stmt;
- struct statement *arraycheck =
stmt_entry(nullcheck->stmt_list_node.next);
+ struct statement *arraycheck = stmt;
struct statement *store_stmt =
stmt_entry(arraycheck->stmt_list_node.next);
- assert_null_check_stmt(arrayref_expr, nullcheck);
assert_arraycheck_stmt(expected_type, arrayref_expr, index_expr,
arraycheck);
diff --git a/test/jit/tree-printer-test.c b/test/jit/tree-printer-test.c
index 2793aad..1520d1f 100644
--- a/test/jit/tree-printer-test.c
+++ b/test/jit/tree-printer-test.c
@@ -114,19 +114,6 @@ void test_should_print_expression_statement(void)
assert_print_stmt("EXPRESSION:\n expression: [local int 0]\n", stmt);
}
-void test_should_print_nullcheck_statement(void)
-{
- struct expression *expression;
- struct statement *stmt;
-
- expression = local_expr(J_INT, 0);
-
- stmt = alloc_statement(STMT_NULL_CHECK);
- stmt->expression = &expression->node;
-
- assert_print_stmt("NULL_CHECK:\n expression: [local int 0]\n", stmt);
-}
-
void test_should_print_arraycheck_statement(void)
{
struct expression *expression;
@@ -589,3 +576,15 @@ void test_print_instanceof_expression(void)
" instanceof_ref: [value reference 0x55]\n",
instanceof_expr(value_expr(J_REFERENCE, 0x55), (void
*)0x55));
}
+
+void test_should_print_nullcheck_expression(void)
+{
+ struct expression *expression;
+ struct expression *expr;
+
+ expression = local_expr(J_REFERENCE, 0);
+
+ expr = null_check_expr(expression);
+
+ assert_print_expr("NULL_CHECK:\n ref: [local reference 0]\n", expr);
+}
--
1.6.0.6
------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, &
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel