instance of EXPR_ARRAY_DEREF that was connected to STMT_STORE and
STMT_ARRAY_CHECK could have side effects. We must make sure that
we create EXPR_ARRAY_DEREF with pure expressions as arrayref and index.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 jit/object-bc.c           |   62 +++++++++++++++++++++++++++++++-------------
 test/jit/bc-test-utils.c  |    4 +-
 test/jit/object-bc-test.c |   48 +++++++++++++++++++++++++++-------
 3 files changed, 83 insertions(+), 31 deletions(-)

diff --git a/jit/object-bc.c b/jit/object-bc.c
index 76d5b1d..8b8658b 100644
--- a/jit/object-bc.c
+++ b/jit/object-bc.c
@@ -23,6 +23,20 @@
 #include <string.h>
 #include <errno.h>
 
+/**
+ * Returns a pure expression for given expression. If @expr is not
+ * pure we need to save it's value to a temporary and return the
+ * temporary.
+ */
+static struct expression *
+get_pure_expr(struct parse_context *ctx, struct expression *expr)
+{
+       if (expr_is_pure(expr))
+               return expr;
+
+       return dup_expr(ctx, expr);
+}
+
 static char *class_name_to_array_name(const char *class_name)
 {
        char *array_name = malloc(strlen(class_name) + 4);
@@ -158,23 +172,31 @@ int convert_putfield(struct parse_context *ctx)
 
 int convert_array_load(struct parse_context *ctx, enum vm_type type)
 {
-       struct expression *index, *arrayref, *arrayref_nullcheck;
+       struct expression *index, *arrayref;
        struct expression *src_expr, *dest_expr;
        struct statement *store_stmt, *arraycheck;
        struct var_info *temporary;
+       struct expression *arrayref_pure;
+       struct expression *index_pure;
 
        index = stack_pop(ctx->bb->mimic_stack);
-       arrayref = stack_pop(ctx->bb->mimic_stack);
+       arrayref = null_check_expr(stack_pop(ctx->bb->mimic_stack));
+       if (!arrayref)
+               goto failed;
 
        store_stmt = alloc_statement(STMT_STORE);
        if (!store_stmt)
                goto failed;
 
-       arrayref_nullcheck = null_check_expr(arrayref);
-       if (!arrayref_nullcheck)
-               goto failed_arrayref_nullcheck;
-
-       src_expr = array_deref_expr(type, arrayref_nullcheck, index);
+       /*
+        * We have to assure that arrayref and index expressions
+        * passed to array_deref_expr() do not have side effects
+        * because src_expr is connected to both STMT_STORE and
+        * STMT_ARRAY_CHECK.
+        */
+       arrayref_pure = get_pure_expr(ctx, arrayref);
+       index_pure = get_pure_expr(ctx, index);
+       src_expr = array_deref_expr(type, arrayref_pure, index_pure);
 
        temporary = get_var(ctx->cu);
        dest_expr = temporary_expr(type, NULL, temporary);
@@ -198,7 +220,6 @@ int convert_array_load(struct parse_context *ctx, enum 
vm_type type)
        return 0;
 
       failed_arraycheck:
-      failed_arrayref_nullcheck:
        free_statement(store_stmt);
       failed:
        return -ENOMEM;
@@ -246,25 +267,30 @@ 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, *arrayref_nullcheck;
+       struct expression *value, *index, *arrayref;
        struct statement *store_stmt, *arraycheck;
        struct statement *array_store_check_stmt;
        struct expression *src_expr, *dest_expr;
+       struct expression *arrayref_pure;
+       struct expression *index_pure;
 
        value = stack_pop(ctx->bb->mimic_stack);
        index = stack_pop(ctx->bb->mimic_stack);
-       arrayref = stack_pop(ctx->bb->mimic_stack);
+
+       arrayref = null_check_expr(stack_pop(ctx->bb->mimic_stack));
+       if (!arrayref)
+               goto failed;
 
        store_stmt = alloc_statement(STMT_STORE);
        if (!store_stmt)
                goto failed;
 
-       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;
+       arrayref_pure = get_pure_expr(ctx, arrayref);
+       index_pure = get_pure_expr(ctx, index);
+       dest_expr = array_deref_expr(type, arrayref_pure, index_pure);
+
+       src_expr = dup_expr(ctx, value);
 
        store_stmt->store_dest = &dest_expr->node;
        store_stmt->store_src = &src_expr->node;
@@ -282,9 +308,8 @@ static int convert_array_store(struct parse_context *ctx, 
enum vm_type type)
 
        expr_get(src_expr);
        array_store_check_stmt->store_check_src = &src_expr->node;
-       expr_get(arrayref_nullcheck);
-       array_store_check_stmt->store_check_array = &arrayref_nullcheck->node;
-
+       expr_get(arrayref_pure);
+       array_store_check_stmt->store_check_array = &arrayref_pure->node;
 
        convert_statement(ctx, arraycheck);
        convert_statement(ctx, array_store_check_stmt);
@@ -295,7 +320,6 @@ static int convert_array_store(struct parse_context *ctx, 
enum vm_type type)
       failed_array_store_check_stmt:
        free_statement(arraycheck);
       failed_arraycheck:
-      failed_arrayref_nullcheck:
        free_statement(store_stmt);
       failed:
        return -ENOMEM;
diff --git a/test/jit/bc-test-utils.c b/test/jit/bc-test-utils.c
index 12bbaf6..f2eb480 100644
--- a/test/jit/bc-test-utils.c
+++ b/test/jit/bc-test-utils.c
@@ -134,7 +134,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_null_check_expr(expected_arrayref, to_expr(expr->arrayref));
+       assert_ptr_equals(expected_arrayref, to_expr(expr->arrayref));
        assert_ptr_equals(expected_index, to_expr(expr->array_index));
 }
 
@@ -238,7 +238,7 @@ void assert_array_store_check_stmt(struct statement *stmt,
                                   struct tree_node *store_src)
 {
        assert_int_equals(STMT_ARRAY_STORE_CHECK, stmt_type(stmt));
-       assert_null_check_expr(arrayref, to_expr(stmt->store_check_array));
+       assert_ptr_equals(arrayref, to_expr(stmt->store_check_array));
        assert_ptr_equals(store_src, stmt->store_check_src);
 }
 
diff --git a/test/jit/object-bc-test.c b/test/jit/object-bc-test.c
index 1569f08..f60f66c 100644
--- a/test/jit/object-bc-test.c
+++ b/test/jit/object-bc-test.c
@@ -247,13 +247,24 @@ 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 *arraycheck = stmt;
-       struct statement *store_stmt = 
stmt_entry(arraycheck->stmt_list_node.next);
+       struct statement *arrayref_pure_stmt = stmt;
+       struct statement *arraycheck_stmt = 
stmt_entry(arrayref_pure_stmt->stmt_list_node.next);
+       struct statement *store_stmt = 
stmt_entry(arraycheck_stmt->stmt_list_node.next);
 
-       assert_arraycheck_stmt(expected_type, arrayref_expr, index_expr, 
arraycheck);
+       assert_store_stmt(arrayref_pure_stmt);
+       assert_nullcheck_value_expr(J_REFERENCE, arrayref,
+                                   arrayref_pure_stmt->store_src);
+       assert_temporary_expr(arrayref_pure_stmt->store_dest);
+
+       assert_arraycheck_stmt(expected_type,
+                              to_expr(arrayref_pure_stmt->store_dest),
+                              index_expr,
+                              arraycheck_stmt);
 
        assert_store_stmt(store_stmt);
-       assert_array_deref_expr(expected_type, arrayref_expr, index_expr,
+       assert_array_deref_expr(expected_type,
+                               to_expr(arrayref_pure_stmt->store_dest),
+                               index_expr,
                                store_stmt->store_src);
 
        temporary_expr = stack_pop(bb->mimic_stack);
@@ -342,16 +353,33 @@ 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 *arraycheck = stmt;
-       struct statement *storecheck_stmt = 
stmt_entry(arraycheck->stmt_list_node.next);
+       struct statement *arrayref_pure_stmt = stmt;
+       struct statement *value_dup_stmt = 
stmt_entry(arrayref_pure_stmt->stmt_list_node.next);
+       struct statement *arraycheck_stmt = 
stmt_entry(value_dup_stmt->stmt_list_node.next);
+       struct statement *storecheck_stmt = 
stmt_entry(arraycheck_stmt->stmt_list_node.next);
        struct statement *store_stmt = 
stmt_entry(storecheck_stmt->stmt_list_node.next);
 
-       assert_arraycheck_stmt(expected_type, arrayref_expr, index_expr,
-                              arraycheck);
-       assert_array_store_check_stmt(storecheck_stmt, arrayref_expr,
+       assert_store_stmt(arrayref_pure_stmt);
+       assert_nullcheck_value_expr(J_REFERENCE, arrayref,
+                                   arrayref_pure_stmt->store_src);
+       assert_temporary_expr(arrayref_pure_stmt->store_dest);
+
+       assert_store_stmt(value_dup_stmt);
+       assert_ptr_equals(&expr->node, value_dup_stmt->store_src);
+       assert_temporary_expr(value_dup_stmt->store_dest);
+
+       assert_arraycheck_stmt(expected_type,
+                              to_expr(arrayref_pure_stmt->store_dest),
+                              index_expr,
+                              arraycheck_stmt);
+
+       assert_array_store_check_stmt(storecheck_stmt,
+                                     to_expr(arrayref_pure_stmt->store_dest),
                                      store_stmt->store_src);
        assert_store_stmt(store_stmt);
-       assert_array_deref_expr(expected_type, arrayref_expr, index_expr,
+       assert_array_deref_expr(expected_type,
+                               to_expr(arrayref_pure_stmt->store_dest),
+                               index_expr,
                                store_stmt->store_dest);
        assert_temporary_expr(store_stmt->store_src);
 
-- 
1.6.0.6


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

Reply via email to