Просмотр исходного кода

Fix GC AOT struct/array/i31/exception issues (#2664)

Refactor the exception IDs for GC feature.
Wenyong Huang 2 лет назад
Родитель
Сommit
52328f0565

+ 1 - 1
core/iwasm/aot/aot_runtime.c

@@ -2821,7 +2821,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
         if (func_indexes[i] != UINT32_MAX) {
             if (!(func_obj = aot_create_func_obj(module_inst, func_indexes[i],
                                                  true, NULL, 0))) {
-                aot_set_exception_with_id(module_inst, EXCE_NULL_GC_REF);
+                aot_set_exception_with_id(module_inst, EXCE_NULL_FUNC_OBJ);
                 return;
             }
             table_elems[i] = func_obj;

+ 12 - 4
core/iwasm/common/wasm_runtime_common.c

@@ -2492,10 +2492,18 @@ static const char *exception_msgs[] = {
     "out of bounds table access",     /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
     "wasm operand stack overflow",    /* EXCE_OPERAND_STACK_OVERFLOW */
     "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
-    "null GC object",                 /* EXCE_NULL_GC_REF */
-    "failed to cast GC object",       /* EXCE_TYPE_NONCASTABLE */
-    "GC array index out of bounds",   /* EXCE_ARRAY_OOB */
-    "failed to create GC object",     /* EXCE_FAILED_TO_CREATE_GC_OBJ */
+    /* GC related exceptions */
+    "null function object",           /* EXCE_NULL_FUNC_OBJ */
+    "null structure object",          /* EXCE_NULL_STRUCT_OBJ */
+    "null array object",              /* EXCE_NULL_ARRAY_OBJ */
+    "null i31 reference",             /* EXCE_NULL_I31_OBJ */
+    "null reference",                 /* EXCE_NULL_REFERENCE */
+    "create rtt type failed",         /* EXCE_FAILED_TO_CREATE_RTT_TYPE */
+    "create struct object failed",    /* EXCE_FAILED_TO_CREATE_STRUCT_OBJ */
+    "create array object failed",     /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */
+    "create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
+    "cast failure",                   /* EXCE_CAST_FAILURE */
+    "array index out of bounds",      /* EXCE_ARRAY_IDX_OOB */
     "",                               /* EXCE_ALREADY_THROWN */
 };
 /* clang-format on */

+ 22 - 5
core/iwasm/compilation/aot_emit_function.c

@@ -882,7 +882,11 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     if (func_type->result_count > 0) {
         /* Push the first result to stack */
-        PUSH(value_ret, func_type->types[func_type->param_count]);
+        if (comp_ctx->enable_gc
+            && aot_is_type_gc_reftype(func_type->types[func_type->param_count]))
+            PUSH_GC_REF(value_ret);
+        else
+            PUSH(value_ret, func_type->types[func_type->param_count]);
         /* Load extra result from its address and push to stack */
         for (i = 0; i < ext_ret_count; i++) {
             snprintf(buf, sizeof(buf), "func%d_ext_ret%d", func_idx, i);
@@ -892,7 +896,10 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 aot_set_last_error("llvm build load failed.");
                 goto fail;
             }
-            PUSH(ext_ret, ext_ret_types[i]);
+            if (comp_ctx->enable_gc && aot_is_type_gc_reftype(ext_ret_types[i]))
+                PUSH_GC_REF(ext_ret);
+            else
+                PUSH(ext_ret, ext_ret_types[i]);
         }
     }
 
@@ -1635,7 +1642,12 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block_return);
 
     for (i = 0; i < func_result_count; i++) {
-        PUSH(result_phis[i], func_type->types[func_param_count + i]);
+        if (comp_ctx->enable_gc
+            && aot_is_type_gc_reftype(
+                func_type->types[func_type->param_count + i]))
+            PUSH_GC_REF(result_phis[i]);
+        else
+            PUSH(result_phis[i], func_type->types[func_param_count + i]);
     }
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
@@ -1799,7 +1811,7 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMMoveBasicBlockAfter(check_func_obj_succ,
                             LLVMGetInsertBlock(comp_ctx->builder));
 
-    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true,
+    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_FUNC_OBJ, true,
                              cmp_func_obj, check_func_obj_succ)))
         goto fail;
 
@@ -2122,7 +2134,12 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block_return);
 
     for (i = 0; i < func_result_count; i++) {
-        PUSH(result_phis[i], func_type->types[func_param_count + i]);
+        if (comp_ctx->enable_gc
+            && aot_is_type_gc_reftype(
+                func_type->types[func_type->param_count + i]))
+            PUSH_GC_REF(result_phis[i]);
+        else
+            PUSH(result_phis[i], func_type->types[func_param_count + i]);
     }
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)

+ 164 - 173
core/iwasm/compilation/aot_emit_gc.c

@@ -250,7 +250,7 @@ aot_compile_op_ref_as_non_null(AOTCompContext *comp_ctx,
     MOVE_BLOCK_AFTER_CURR(check_gc_obj_succ);
 
     /*  Throw exception if it is NULL */
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_REFERENCE, true,
                             cmp_gc_obj, check_gc_obj_succ))
         goto fail;
 
@@ -446,7 +446,7 @@ static bool
 struct_new_canon_init_fields(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                              uint32 type_index, LLVMValueRef struct_obj)
 {
-    LLVMValueRef field_value;
+    LLVMValueRef field_value = NULL;
     /* Used in compile time, to distinguish what type of AOTValue POP,
      * field_data offset, size  */
     WASMStructType *compile_time_struct_type =
@@ -507,8 +507,8 @@ aot_compile_op_struct_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER_CURR(check_rtt_type_succ);
 
     BUILD_ISNULL(rtt_type, cmp, "cmp_rtt_type");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
-                            check_rtt_type_succ))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_RTT_TYPE,
+                            true, cmp, check_rtt_type_succ))
         goto fail;
 
     /* Generate call wasm_struct_obj_new and check for exception */
@@ -520,7 +520,8 @@ aot_compile_op_struct_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER(check_struct_obj_succ, check_rtt_type_succ);
 
     BUILD_ISNULL(struct_obj, cmp, "cmp_struct_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx,
+                            EXCE_FAILED_TO_CREATE_STRUCT_OBJ, true, cmp,
                             check_struct_obj_succ))
         goto fail;
 
@@ -569,7 +570,7 @@ aot_compile_op_struct_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER_CURR(check_struct_obj_succ);
 
     BUILD_ISNULL(struct_obj, cmp, "cmp_struct_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_STRUCT_OBJ, true, cmp,
                             check_struct_obj_succ))
         goto fail;
 
@@ -606,7 +607,7 @@ bool
 aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                           uint32 type_index, uint32 field_idx)
 {
-    LLVMValueRef struct_obj, cmp, field_value;
+    LLVMValueRef struct_obj, cmp, field_value = NULL;
     LLVMBasicBlockRef check_struct_obj_succ;
     /* Used in compile time, to distinguish what type of AOTValue POP,
      * field_data offset, size  */
@@ -650,7 +651,7 @@ aot_compile_op_struct_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER_CURR(check_struct_obj_succ);
 
     BUILD_ISNULL(struct_obj, cmp, "cmp_struct_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_STRUCT_OBJ, true, cmp,
                             check_struct_obj_succ))
         goto fail;
 
@@ -744,10 +745,10 @@ aot_array_obj_elem_size_log(AOTCompContext *comp_ctx, uint8 array_elem_type)
 static bool
 aot_array_obj_elem_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                         LLVMValueRef array_obj, LLVMValueRef elem_idx,
-                        LLVMValueRef *elem_data, uint8 array_elem_type)
+                        LLVMValueRef *p_elem_data, uint8 array_elem_type)
 {
     uint32 elem_size_log = 0;
-    LLVMValueRef start_offset, elem_offset;
+    LLVMValueRef start_offset, elem_offset, elem_data;
 
     elem_size_log = aot_array_obj_elem_size_log(comp_ctx, array_elem_type);
 
@@ -773,13 +774,14 @@ aot_array_obj_elem_addr(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
-    if (!(*elem_data = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
-                                             array_obj, &elem_offset, 1,
-                                             "array_obj_elem_data_i8p"))) {
+    if (!(elem_data = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+                                            array_obj, &elem_offset, 1,
+                                            "array_obj_elem_data_i8p"))) {
         aot_set_last_error("llvm build gep failed.");
         goto fail;
     }
 
+    *p_elem_data = elem_data;
     return true;
 fail:
     return false;
@@ -791,35 +793,49 @@ aot_array_obj_set_elem(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                        LLVMValueRef array_elem, uint8 array_elem_type)
 {
     bool trunc = false;
-    uint32 elem_size;
     LLVMValueRef elem_data_ptr;
-    LLVMTypeRef elem_data_type = NULL;
+    LLVMTypeRef elem_data_type = NULL, elem_data_ptr_type = NULL;
 
     if (!aot_array_obj_elem_addr(comp_ctx, func_ctx, array_obj, elem_idx,
                                  &elem_data_ptr, array_elem_type))
         goto fail;
 
-    elem_size = 1 << aot_array_obj_elem_size_log(comp_ctx, array_elem_type);
-
-    switch (elem_size) {
-        case 1:
-            elem_data_type = INT8_TYPE;
-            trunc = true;
-            break;
-        case 2:
-            elem_data_type = INT16_TYPE;
-            trunc = true;
-            break;
-        case 4:
-            elem_data_type = I32_TYPE;
-            break;
-        case 8:
-            elem_data_type = I64_TYPE;
-            break;
-        default:
-            bh_assert(0);
-            break;
+    if (wasm_is_type_reftype(array_elem_type)) {
+        elem_data_type = GC_REF_TYPE;
+        elem_data_ptr_type = GC_REF_PTR_TYPE;
     }
+    else
+        switch (array_elem_type) {
+            case PACKED_TYPE_I8:
+                elem_data_type = INT8_TYPE;
+                elem_data_ptr_type = INT8_PTR_TYPE;
+                trunc = true;
+                break;
+            case PACKED_TYPE_I16:
+                elem_data_type = INT16_TYPE;
+                elem_data_ptr_type = INT16_PTR_TYPE;
+                trunc = true;
+                break;
+            case VALUE_TYPE_I32:
+                elem_data_type = I32_TYPE;
+                elem_data_ptr_type = INT32_PTR_TYPE;
+                break;
+            case VALUE_TYPE_I64:
+                elem_data_type = I64_TYPE;
+                elem_data_ptr_type = INT64_PTR_TYPE;
+                break;
+            case VALUE_TYPE_F32:
+                elem_data_type = F32_TYPE;
+                elem_data_ptr_type = F32_PTR_TYPE;
+                break;
+            case VALUE_TYPE_F64:
+                elem_data_type = F64_TYPE;
+                elem_data_ptr_type = F64_PTR_TYPE;
+                break;
+            default:
+                bh_assert(0);
+                break;
+        }
 
     /* Based on elem_size, trunc array_elem if necessary */
     if (trunc) {
@@ -831,20 +847,10 @@ aot_array_obj_set_elem(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
 
-    /* Ensure correct alignment for some platforms when field_size == 8 */
-    if (elem_size == 8) {
-        if (!(elem_data_ptr =
-                  LLVMBuildBitCast(comp_ctx->builder, elem_data_ptr,
-                                   INT32_PTR_TYPE, "elem_data_ptr_align"))) {
-            aot_set_last_error("llvm build bitcast failed.");
-            goto fail;
-        }
-    }
-
     /* Cast to the field data type ptr */
-    if (!(elem_data_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_data_ptr,
-                                           LLVMPointerType(elem_data_type, 0),
-                                           "elem_data_ptr"))) {
+    if (!(elem_data_ptr =
+              LLVMBuildBitCast(comp_ctx->builder, elem_data_ptr,
+                               elem_data_ptr_type, "elem_data_ptr"))) {
         aot_set_last_error("llvm build bitcast failed.");
         goto fail;
     }
@@ -899,7 +905,7 @@ aot_call_aot_array_init_with_data(
     }
 
     BUILD_ICMP(LLVMIntEQ, res, I8_ZERO, cmp, "array_init_ret");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_OOB, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_IDX_OOB, true, cmp,
                             init_success))
         goto fail;
 
@@ -911,80 +917,86 @@ fail:
 static bool
 aot_call_wasm_array_get_elem(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                              LLVMValueRef array_obj, LLVMValueRef elem_idx,
-                             LLVMValueRef *array_elem, uint8 array_elem_type,
+                             LLVMValueRef *p_array_elem, uint8 array_elem_type,
                              bool sign)
 {
     bool extend = false;
-    uint32 elem_size;
-    LLVMValueRef elem_data_ptr;
-    LLVMTypeRef elem_data_type = NULL;
+    LLVMValueRef elem_data_ptr, array_elem;
+    LLVMTypeRef elem_data_type = NULL, elem_data_ptr_type = NULL;
 
     if (!aot_array_obj_elem_addr(comp_ctx, func_ctx, array_obj, elem_idx,
                                  &elem_data_ptr, array_elem_type))
         goto fail;
 
-    elem_size = 1 << aot_array_obj_elem_size_log(comp_ctx, array_elem_type);
-
-    switch (elem_size) {
-        case 1:
-            elem_data_type = INT8_TYPE;
-            extend = true;
-            break;
-        case 2:
-            elem_data_type = INT16_TYPE;
-            extend = true;
-            break;
-        case 4:
-            elem_data_type = I32_TYPE;
-            break;
-        case 8:
-            elem_data_type = I64_TYPE;
-            break;
-        default:
-            bh_assert(0);
-            break;
+    if (wasm_is_type_reftype(array_elem_type)) {
+        elem_data_type = GC_REF_TYPE;
+        elem_data_ptr_type = GC_REF_PTR_TYPE;
     }
-
-    /* Ensure correct alignment for some platforms when field_size == 8 */
-    if (elem_size == 8) {
-        if (!(elem_data_ptr =
-                  LLVMBuildBitCast(comp_ctx->builder, elem_data_ptr,
-                                   INT32_PTR_TYPE, "elem_data_ptr_align"))) {
-            aot_set_last_error("llvm build bitcast failed.");
-            goto fail;
+    else
+        switch (array_elem_type) {
+            case PACKED_TYPE_I8:
+                elem_data_type = INT8_TYPE;
+                elem_data_ptr_type = INT8_PTR_TYPE;
+                extend = true;
+                break;
+            case PACKED_TYPE_I16:
+                elem_data_type = INT16_TYPE;
+                elem_data_ptr_type = INT16_PTR_TYPE;
+                extend = true;
+                break;
+            case VALUE_TYPE_I32:
+                elem_data_type = I32_TYPE;
+                elem_data_ptr_type = INT32_PTR_TYPE;
+                break;
+            case VALUE_TYPE_I64:
+                elem_data_type = I64_TYPE;
+                elem_data_ptr_type = INT64_PTR_TYPE;
+                break;
+            case VALUE_TYPE_F32:
+                elem_data_type = F32_TYPE;
+                elem_data_ptr_type = F32_PTR_TYPE;
+                break;
+            case VALUE_TYPE_F64:
+                elem_data_type = F64_TYPE;
+                elem_data_ptr_type = F64_PTR_TYPE;
+                break;
+            default:
+                bh_assert(0);
+                break;
         }
-    }
 
-    if (!(elem_data_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_data_ptr,
-                                           LLVMPointerType(elem_data_type, 0),
-                                           "elem_data_ptr"))) {
+    /* Based on elem_size, trunc array_elem if necessary */
+    if (!(elem_data_ptr =
+              LLVMBuildBitCast(comp_ctx->builder, elem_data_ptr,
+                               elem_data_ptr_type, "elem_data_ptr"))) {
         aot_set_last_error("llvm build bitcast failed.");
         goto fail;
     }
 
-    if (!(*array_elem = LLVMBuildLoad2(comp_ctx->builder, elem_data_type,
-                                       elem_data_ptr, "array_elem"))) {
+    if (!(array_elem = LLVMBuildLoad2(comp_ctx->builder, elem_data_type,
+                                      elem_data_ptr, "array_elem"))) {
         aot_set_last_error("llvm build load failed.");
         goto fail;
     }
 
     if (extend) {
         if (sign) {
-            if (!(*array_elem = LLVMBuildSExt(comp_ctx->builder, *array_elem,
-                                              I32_TYPE, "array_elem_sext"))) {
+            if (!(array_elem = LLVMBuildSExt(comp_ctx->builder, array_elem,
+                                             I32_TYPE, "array_elem_sext"))) {
                 aot_set_last_error("llvm build signed ext failed.");
                 goto fail;
             }
         }
         else {
-            if (!(*array_elem = LLVMBuildZExt(comp_ctx->builder, *array_elem,
-                                              I32_TYPE, "array_elem_zext"))) {
+            if (!(array_elem = LLVMBuildZExt(comp_ctx->builder, array_elem,
+                                             I32_TYPE, "array_elem_zext"))) {
                 aot_set_last_error("llvm build unsigned ext failed.");
                 goto fail;
             }
         }
     }
 
+    *p_array_elem = array_elem;
     return true;
 fail:
     return false;
@@ -993,9 +1005,9 @@ fail:
 /* array_obj->length >> WASM_ARRAY_LENGTH_SHIFT */
 static bool
 aot_array_obj_length(AOTCompContext *comp_ctx, LLVMValueRef array_obj,
-                     LLVMValueRef *array_len)
+                     LLVMValueRef *p_array_len)
 {
-    LLVMValueRef offset;
+    LLVMValueRef offset, array_len;
 
     /* Get the length of the WASMArrayObject, the offset may be
      * different in 32-bit runtime and 64-bit runtime since WASMObjectHeader
@@ -1006,33 +1018,34 @@ aot_array_obj_length(AOTCompContext *comp_ctx, LLVMValueRef array_obj,
         goto fail;
     }
 
-    if (!(*array_len =
+    if (!(array_len =
               LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, array_obj,
                                     &offset, 1, "array_obj_length_i8p"))) {
         aot_set_last_error("llvm build gep failed.");
         goto fail;
     }
 
-    if (!(*array_len =
-              LLVMBuildBitCast(comp_ctx->builder, *array_len, INT32_PTR_TYPE,
+    if (!(array_len =
+              LLVMBuildBitCast(comp_ctx->builder, array_len, INT32_PTR_TYPE,
                                "array_obj_length_i32ptr"))) {
         aot_set_last_error("llvm build bitcast failed.");
         goto fail;
     }
 
-    if (!(*array_len = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, *array_len,
-                                      "array_obj_length"))) {
+    if (!(array_len = LLVMBuildLoad2(comp_ctx->builder, I32_TYPE, array_len,
+                                     "array_obj_length"))) {
         aot_set_last_error("llvm build load failed.");
         goto fail;
     }
 
-    if (!(*array_len = LLVMBuildLShr(comp_ctx->builder, *array_len,
-                                     I32_CONST(WASM_ARRAY_LENGTH_SHIFT),
-                                     "array_obj_length_shr"))) {
+    if (!(array_len = LLVMBuildLShr(comp_ctx->builder, array_len,
+                                    I32_CONST(WASM_ARRAY_LENGTH_SHIFT),
+                                    "array_obj_length_shr"))) {
         aot_set_last_error("llvm build lshr failed.");
         goto fail;
     }
 
+    *p_array_len = array_len;
     return true;
 fail:
     return false;
@@ -1043,7 +1056,8 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 type_index, bool init_with_default,
                          bool fixed_size, uint32 array_len)
 {
-    LLVMValueRef array_length, rtt_type, array_elem, array_obj, cmp, elem_idx;
+    LLVMValueRef array_length, array_elem = NULL, array_obj;
+    LLVMValueRef rtt_type, cmp, elem_idx;
     LLVMBasicBlockRef check_rtt_type_succ, check_array_obj_succ;
     /* Use for distinguish what type of AOTValue POP */
     WASMArrayType *compile_time_array_type =
@@ -1060,8 +1074,8 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER_CURR(check_rtt_type_succ);
 
     BUILD_ISNULL(rtt_type, cmp, "cmp_rtt_type");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
-                            check_rtt_type_succ))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_RTT_TYPE,
+                            true, cmp, check_rtt_type_succ))
         goto fail;
 
     if (!fixed_size)
@@ -1107,8 +1121,8 @@ aot_compile_op_array_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER(check_array_obj_succ, check_rtt_type_succ);
 
     BUILD_ISNULL(array_obj, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
-                            check_array_obj_succ))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_ARRAY_OBJ,
+                            true, cmp, check_array_obj_succ))
         goto fail;
 
     if (fixed_size) {
@@ -1176,8 +1190,8 @@ aot_compile_op_array_new_data(AOTCompContext *comp_ctx,
     MOVE_BLOCK_AFTER_CURR(check_rtt_type_succ);
 
     BUILD_ISNULL(rtt_type, cmp, "cmp_rtt_type");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
-                            check_rtt_type_succ))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_RTT_TYPE,
+                            true, cmp, check_rtt_type_succ))
         goto fail;
 
     POP_I32(array_length);
@@ -1216,8 +1230,8 @@ aot_compile_op_array_new_data(AOTCompContext *comp_ctx,
     MOVE_BLOCK_AFTER(check_array_obj_succ, check_rtt_type_succ);
 
     BUILD_ISNULL(array_obj, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
-                            check_array_obj_succ))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_ARRAY_OBJ,
+                            true, cmp, check_array_obj_succ))
         goto fail;
 
     if (!aot_call_aot_array_init_with_data(
@@ -1250,10 +1264,11 @@ aot_compile_op_array_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER_CURR(check_array_obj_succ);
 
     BUILD_ISNULL(array_obj, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_ARRAY_OBJ, true, cmp,
                             check_array_obj_succ))
         goto fail;
 
+    SET_BUILDER_POS(check_array_obj_succ);
     if (!aot_array_obj_length(comp_ctx, array_obj, &array_len))
         goto fail;
 
@@ -1261,10 +1276,11 @@ aot_compile_op_array_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER(check_boundary_succ, check_array_obj_succ);
 
     BUILD_ICMP(LLVMIntUGE, elem_idx, array_len, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_OOB, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_IDX_OOB, true, cmp,
                             check_boundary_succ))
         goto fail;
 
+    SET_BUILDER_POS(check_boundary_succ);
     if (!aot_call_wasm_array_get_elem(comp_ctx, func_ctx, array_obj, elem_idx,
                                       &array_elem, array_elem_type, sign))
         goto fail;
@@ -1299,7 +1315,7 @@ bool
 aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 type_index)
 {
-    LLVMValueRef elem_idx, array_obj, cmp, array_len, array_elem;
+    LLVMValueRef elem_idx, array_obj, cmp, array_len, array_elem = NULL;
     LLVMBasicBlockRef check_array_obj_succ, check_boundary_succ;
     /* Use for distinguish what type of AOTValue POP */
     WASMArrayType *compile_time_array_type =
@@ -1335,10 +1351,11 @@ aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER_CURR(check_array_obj_succ);
 
     BUILD_ISNULL(array_obj, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_ARRAY_OBJ, true, cmp,
                             check_array_obj_succ))
         goto fail;
 
+    SET_BUILDER_POS(check_array_obj_succ);
     if (!aot_array_obj_length(comp_ctx, array_obj, &array_len))
         goto fail;
 
@@ -1346,11 +1363,12 @@ aot_compile_op_array_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     MOVE_BLOCK_AFTER(check_boundary_succ, check_array_obj_succ);
 
     BUILD_ICMP(LLVMIntUGE, elem_idx, array_len, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_OOB, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_IDX_OOB, true, cmp,
                             check_boundary_succ))
         goto fail;
 
-    if (!aot_array_obj_set_elem(comp_ctx, func_ctx, array_elem, elem_idx,
+    SET_BUILDER_POS(check_boundary_succ);
+    if (!aot_array_obj_set_elem(comp_ctx, func_ctx, array_obj, elem_idx,
                                 array_elem, array_elem_type)) {
         aot_set_last_error("llvm build alloca failed.");
         goto fail;
@@ -1479,8 +1497,8 @@ aot_compile_op_array_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
 
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_OOB, true, cmp[0],
-                            inner_else))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_ARRAY_IDX_OOB, true,
+                            cmp[0], inner_else))
         goto fail;
 
     if (!aot_call_wasm_obj_copy(comp_ctx, func_ctx, dst_obj, dst_offset,
@@ -1505,7 +1523,7 @@ aot_compile_op_array_len(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
     MOVE_BLOCK_AFTER_CURR(check_array_obj_succ);
 
     BUILD_ISNULL(array_obj, cmp, "cmp_array_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true, cmp,
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_ARRAY_OBJ, true, cmp,
                             check_array_obj_succ))
         goto fail;
 
@@ -1526,30 +1544,21 @@ aot_compile_op_i31_new(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 
     POP_I32(i31_val);
 
-    /* Equivalent to wasm_i31_obj_new: ((i31_value << 1) | 1) */
-    if (!(i31_obj = LLVMBuildShl(comp_ctx->builder, i31_val, I32_ONE,
+    /* i31_val <<= 1 */
+    if (!(i31_val = LLVMBuildShl(comp_ctx->builder, i31_val, I32_ONE,
                                  "i31_val_shl"))) {
         aot_set_last_error("llvm build shl failed.");
         goto fail;
     }
 
-    if (!(i31_obj =
-              LLVMBuildOr(comp_ctx->builder, i31_obj, I32_ONE, "i31_val_or"))) {
+    /* i31_val |= 1 */
+    if (!(i31_val =
+              LLVMBuildOr(comp_ctx->builder, i31_val, I32_ONE, "i31_val_or"))) {
         aot_set_last_error("llvm build or failed.");
         goto fail;
     }
 
-    /* if uintptr_t is 64 bits, extend i32 to i64, equivalent to:
-       (WASMI31ObjectRef)((i31_value << 1) | 1)  */
-    if (comp_ctx->pointer_size == sizeof(uint64)) {
-        if (!(i31_obj = LLVMBuildZExt(comp_ctx->builder, i31_obj, I64_TYPE,
-                                      "i31_val_zext"))) {
-            aot_set_last_error("llvm build zext failed.");
-            goto fail;
-        }
-    }
-
-    if (!(i31_obj = LLVMBuildIntToPtr(comp_ctx->builder, i31_obj, GC_REF_TYPE,
+    if (!(i31_obj = LLVMBuildIntToPtr(comp_ctx->builder, i31_val, GC_REF_TYPE,
                                       "i31_obj"))) {
         aot_set_last_error("llvm build bit cast failed.");
         goto fail;
@@ -1566,8 +1575,7 @@ bool
 aot_compile_op_i31_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                        bool sign)
 {
-    LLVMValueRef i31_obj, i31_val, cmp_i31_obj, bit_30, bit_30_is_set,
-        i31_sign_val;
+    LLVMValueRef i31_obj, i31_val, cmp_i31_obj;
     LLVMBasicBlockRef check_i31_obj_succ;
 
     POP_GC_REF(i31_obj);
@@ -1577,46 +1585,28 @@ aot_compile_op_i31_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     /* Check if i31 object is NULL, throw exception if it is */
     BUILD_ISNULL(i31_obj, cmp_i31_obj, "cmp_i31_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_GC_REF, true,
-                            cmp_i31_obj, check_i31_obj_succ))
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NULL_I31_OBJ, true,
+                            cmp_i31_obj, check_i31_obj_succ)) {
         goto fail;
-
-    /* if uintptr_t is 64 bits, trunc i64 to i32 */
-    if (comp_ctx->pointer_size == sizeof(uint64)) {
-        if (!(i31_val = LLVMBuildTrunc(comp_ctx->builder, i31_obj, I32_TYPE,
-                                       "trunc uintptr_t to i32"))) {
-            aot_set_last_error("llvm build trunc failed.");
-            goto fail;
-        }
-    }
-    else {
-        i31_val = i31_obj;
     }
 
-    /* i31_val = i31_val >> 1 */
-    if (!(i31_val = LLVMBuildLShr(comp_ctx->builder, i31_val, I32_ONE,
-                                  "i31_value"))) {
-        aot_set_last_error("llvm build lshr failed.");
+    if (!(i31_val = LLVMBuildPtrToInt(comp_ctx->builder, i31_obj, I32_TYPE,
+                                      "i31_val"))) {
+        aot_set_last_error("llvm build ptr to init failed.");
         goto fail;
     }
 
-    if (sign) {
-        /* i31_val = i31_val & 0x40000000 ? i31_val |= 0x80000000 : i31_val */
-        if (!(bit_30 = LLVMBuildAnd(comp_ctx->builder, i31_val,
-                                    I32_CONST(0x40000000), "bit30"))) {
-            aot_set_last_error("llvm build and failed.");
+    if (!sign) {
+        if (!(i31_val = LLVMBuildLShr(comp_ctx->builder, i31_val, I32_ONE,
+                                      "i31_value"))) {
+            aot_set_last_error("llvm build lshr failed.");
             goto fail;
         }
-        BUILD_ICMP(LLVMIntNE, bit_30, I32_ZERO, bit_30_is_set, "bit30_is_set");
-        if (!(i31_sign_val = LLVMBuildOr(comp_ctx->builder, i31_val,
-                                         I32_CONST(0x80000000), "or"))) {
-            aot_set_last_error("llvm build or failed.");
-            goto fail;
-        }
-        if (!(i31_val =
-                  LLVMBuildSelect(comp_ctx->builder, bit_30_is_set,
-                                  i31_sign_val, i31_val, "final_value"))) {
-            aot_set_last_error("llvm build select failed.");
+    }
+    else {
+        if (!(i31_val = LLVMBuildAShr(comp_ctx->builder, i31_val, I32_ONE,
+                                      "i31_value"))) {
+            aot_set_last_error("llvm build ashr failed.");
             goto fail;
         }
     }
@@ -1718,7 +1708,7 @@ aot_compile_op_ref_cast(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         BUILD_COND_BR(cmp, block_end, block_obj_non_null);
     }
     else {
-        if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_TYPE_NONCASTABLE, true,
+        if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_CAST_FAILURE, true,
                                 cmp, block_obj_non_null)) {
             return false;
         }
@@ -1743,8 +1733,8 @@ aot_compile_op_ref_cast(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return false;
     }
 
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_TYPE_NONCASTABLE, true,
-                            cmp, block_end)) {
+    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_CAST_FAILURE, true, cmp,
+                            block_end)) {
         return false;
     }
 
@@ -1909,8 +1899,9 @@ aot_compile_op_extern_externalize(AOTCompContext *comp_ctx,
 
     /* Check whether failed to externalize */
     BUILD_ISNULL(externref_obj, cmp, "cmp_externref_obj");
-    if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_FAILED_TO_CREATE_GC_OBJ,
-                            true, cmp, block_end)) {
+    if (!aot_emit_exception(comp_ctx, func_ctx,
+                            EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ, true, cmp,
+                            block_end)) {
         return false;
     }
 

+ 5 - 13
core/iwasm/interpreter/wasm_interp_classic.c

@@ -2147,11 +2147,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             wasm_set_exception(module, "null structure object");
                             goto got_exception;
                         }
-                        if (field_idx >= struct_type->field_count) {
-                            wasm_set_exception(
-                                module, "struct field index out of bounds");
-                            goto got_exception;
-                        }
 
                         wasm_struct_obj_get_field(
                             struct_obj, field_idx,
@@ -2208,11 +2203,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             wasm_set_exception(module, "null structure object");
                             goto got_exception;
                         }
-                        if (field_idx >= struct_type->field_count) {
-                            wasm_set_exception(
-                                module, "struct field index out of bounds");
-                            goto got_exception;
-                        }
 
                         wasm_struct_obj_set_field(struct_obj, field_idx,
                                                   &field_value);
@@ -2540,9 +2530,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             wasm_set_exception(module, "null i31 reference");
                             goto got_exception;
                         }
-                        i31_val = wasm_i31_obj_get_value(
-                            i31_obj,
-                            opcode == WASM_OP_I31_GET_S ? true : false);
+                        i31_val = (uint32)(((uintptr_t)i31_obj) >> 1);
+                        if (opcode == WASM_OP_I31_GET_S
+                            && (i31_val & 0x40000000) /* bit 30 is 1 */)
+                            /* set bit 31 to 1 */
+                            i31_val |= 0x80000000;
                         PUSH_I32(i31_val);
                         HANDLE_OP_END();
                     }

+ 5 - 13
core/iwasm/interpreter/wasm_interp_fast.c

@@ -2070,11 +2070,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             wasm_set_exception(module, "null structure object");
                             goto got_exception;
                         }
-                        if (field_idx >= struct_type->field_count) {
-                            wasm_set_exception(
-                                module, "struct field index out of bounds");
-                            goto got_exception;
-                        }
 
                         wasm_struct_obj_get_field(
                             struct_obj, field_idx,
@@ -2131,11 +2126,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             wasm_set_exception(module, "null structure object");
                             goto got_exception;
                         }
-                        if (field_idx >= struct_type->field_count) {
-                            wasm_set_exception(
-                                module, "struct field index out of bounds");
-                            goto got_exception;
-                        }
 
                         wasm_struct_obj_set_field(struct_obj, field_idx,
                                                   &field_value);
@@ -2461,9 +2451,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             wasm_set_exception(module, "null i31 reference");
                             goto got_exception;
                         }
-                        i31_val = wasm_i31_obj_get_value(
-                            i31_obj,
-                            opcode == WASM_OP_I31_GET_S ? true : false);
+                        i31_val = (uint32)(((uintptr_t)i31_obj) >> 1);
+                        if (opcode == WASM_OP_I31_GET_S
+                            && (i31_val & 0x40000000) /* bit 30 is 1 */)
+                            /* set bit 31 to 1 */
+                            i31_val |= 0x80000000;
                         PUSH_I32(i31_val);
                         HANDLE_OP_END();
                     }

+ 12 - 4
core/iwasm/interpreter/wasm_runtime.h

@@ -67,10 +67,18 @@ typedef enum WASMExceptionID {
     EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
     EXCE_OPERAND_STACK_OVERFLOW,
     EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
-    EXCE_NULL_GC_REF,
-    EXCE_TYPE_NONCASTABLE,
-    EXCE_ARRAY_OOB,
-    EXCE_FAILED_TO_CREATE_GC_OBJ,
+    /* GC related exceptions */
+    EXCE_NULL_FUNC_OBJ,
+    EXCE_NULL_STRUCT_OBJ,
+    EXCE_NULL_ARRAY_OBJ,
+    EXCE_NULL_I31_OBJ,
+    EXCE_NULL_REFERENCE,
+    EXCE_FAILED_TO_CREATE_RTT_TYPE,
+    EXCE_FAILED_TO_CREATE_STRUCT_OBJ,
+    EXCE_FAILED_TO_CREATE_ARRAY_OBJ,
+    EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ,
+    EXCE_CAST_FAILURE,
+    EXCE_ARRAY_IDX_OOB,
     EXCE_ALREADY_THROWN,
     EXCE_NUM,
 } WASMExceptionID;