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

Reply via email to