Explorar o código

GC: Implement opcode array.new_canon_data (#1968)

Wenyong Huang %!s(int64=2) %!d(string=hai) anos
pai
achega
de5b11c03e

+ 2 - 2
core/iwasm/common/wasm_application.c

@@ -698,7 +698,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                         WASMObjectRef obj = wasm_externref_obj_to_internal_obj(
                         WASMObjectRef obj = wasm_externref_obj_to_internal_obj(
                             (WASMExternrefObjectRef)gc_obj);
                             (WASMExternrefObjectRef)gc_obj);
                         if (wasm_obj_is_anyref_obj(obj))
                         if (wasm_obj_is_anyref_obj(obj))
-                            os_printf("%" PRIxPTR ":ref.extern",
+                            os_printf("0x%" PRIxPTR ":ref.extern",
                                       wasm_anyref_obj_get_value(
                                       wasm_anyref_obj_get_value(
                                           (WASMAnyrefObjectRef)obj));
                                           (WASMAnyrefObjectRef)obj));
                         else
                         else
@@ -713,7 +713,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                     else if (wasm_obj_is_eq_obj(gc_obj))
                     else if (wasm_obj_is_eq_obj(gc_obj))
                         os_printf("ref.eq");
                         os_printf("ref.eq");
                     else if (wasm_obj_is_anyref_obj(gc_obj))
                     else if (wasm_obj_is_anyref_obj(gc_obj))
-                        os_printf("%" PRIxPTR ":ref.host",
+                        os_printf("0x%" PRIxPTR ":ref.host",
                                   wasm_anyref_obj_get_value(
                                   wasm_anyref_obj_get_value(
                                       (WASMAnyrefObjectRef)gc_obj));
                                       (WASMAnyrefObjectRef)gc_obj));
                     else if (wasm_obj_is_internal_obj(gc_obj))
                     else if (wasm_obj_is_internal_obj(gc_obj))

+ 78 - 0
core/iwasm/interpreter/wasm_interp_classic.c

@@ -2188,6 +2188,84 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         HANDLE_OP_END();
                         HANDLE_OP_END();
                     }
                     }
                     case WASM_OP_ARRAY_NEW_CANON_DATA:
                     case WASM_OP_ARRAY_NEW_CANON_DATA:
+                    {
+                        WASMModule *wasm_module = module->module;
+                        WASMArrayType *array_type;
+                        WASMRttType *rtt_type;
+                        WASMValue array_elem = { 0 };
+                        WASMDataSeg *data_seg;
+                        uint8 *array_elem_base;
+                        uint32 array_len, data_seg_idx, data_seg_offset;
+                        uint32 elem_size = 0;
+                        uint64 total_size;
+
+                        read_leb_uint32(frame_ip, frame_ip_end, type_index);
+                        read_leb_uint32(frame_ip, frame_ip_end, data_seg_idx);
+                        data_seg = wasm_module->data_segments[data_seg_idx];
+
+                        array_type =
+                            (WASMArrayType *)wasm_module->types[type_index];
+
+                        if (!(rtt_type = wasm_rtt_type_new(
+                                  (WASMType *)array_type, type_index,
+                                  wasm_module->rtt_types,
+                                  wasm_module->type_count,
+                                  &wasm_module->rtt_type_lock))) {
+                            wasm_set_exception(module,
+                                               "create rtt type failed");
+                            goto got_exception;
+                        }
+
+                        array_len = POP_I32();
+                        data_seg_offset = POP_I32();
+
+                        switch (array_type->elem_type) {
+                            case PACKED_TYPE_I8:
+                                elem_size = 1;
+                                break;
+                            case PACKED_TYPE_I16:
+                                elem_size = 2;
+                                break;
+                            case VALUE_TYPE_I32:
+                            case VALUE_TYPE_F32:
+                                elem_size = 4;
+                                break;
+                            case VALUE_TYPE_I64:
+                            case VALUE_TYPE_F64:
+                                elem_size = 8;
+                                break;
+                            default:
+                                bh_assert(0);
+                        }
+
+                        total_size = (uint64)elem_size * array_len;
+                        if (data_seg_offset >= data_seg->data_length
+                            || total_size
+                                   > data_seg->data_length - data_seg_offset) {
+                            wasm_set_exception(module,
+                                               "data segment out of bounds");
+                            goto got_exception;
+                        }
+
+                        SYNC_ALL_TO_FRAME();
+                        array_obj = wasm_array_obj_new(
+                            module->e->gc_heap_handle, rtt_type, array_len,
+                            &array_elem);
+                        if (!array_obj) {
+                            wasm_set_exception(module,
+                                               "create array object failed");
+                            goto got_exception;
+                        }
+
+                        array_elem_base =
+                            (uint8 *)wasm_array_obj_first_elem_addr(array_obj);
+                        bh_memcpy_s(array_elem_base, (uint32)total_size,
+                                    data_seg->data + data_seg_offset,
+                                    (uint32)total_size);
+
+                        PUSH_REF(array_obj);
+                        HANDLE_OP_END();
+                    }
                     case WASM_OP_ARRAY_NEW_CANON_ELEM:
                     case WASM_OP_ARRAY_NEW_CANON_ELEM:
                     {
                     {
                         /* TODO */
                         /* TODO */

+ 41 - 6
core/iwasm/interpreter/wasm_loader.c

@@ -11389,6 +11389,8 @@ re_scan:
                     case WASM_OP_ARRAY_NEW_CANON_DATA:
                     case WASM_OP_ARRAY_NEW_CANON_DATA:
                     case WASM_OP_ARRAY_NEW_CANON_ELEM:
                     case WASM_OP_ARRAY_NEW_CANON_ELEM:
                     {
                     {
+                        WASMArrayType *array_type;
+                        uint8 elem_type;
                         uint32 u32 = 0;
                         uint32 u32 = 0;
 
 
                         read_leb_uint32(p, p_end, type_idx);
                         read_leb_uint32(p, p_end, type_idx);
@@ -11420,12 +11422,11 @@ re_scan:
                             POP_I32();
                             POP_I32();
                         }
                         }
 
 
+                        array_type = (WASMArrayType *)module->types[type_idx];
+                        elem_type = array_type->elem_type;
+
                         if (opcode1 == WASM_OP_ARRAY_NEW_CANON
                         if (opcode1 == WASM_OP_ARRAY_NEW_CANON
                             || opcode1 == WASM_OP_ARRAY_NEW_CANON_FIXED) {
                             || opcode1 == WASM_OP_ARRAY_NEW_CANON_FIXED) {
-                            WASMArrayType *array_type =
-                                (WASMArrayType *)module->types[type_idx];
-                            uint8 elem_type = array_type->elem_type;
-
                             if (wasm_is_type_multi_byte_type(elem_type)) {
                             if (wasm_is_type_multi_byte_type(elem_type)) {
                                 bh_memcpy_s(&wasm_ref_type, sizeof(WASMRefType),
                                 bh_memcpy_s(&wasm_ref_type, sizeof(WASMRefType),
                                             array_type->elem_ref_type,
                                             array_type->elem_ref_type,
@@ -11444,9 +11445,43 @@ re_scan:
                             else
                             else
                                 POP_REF(elem_type);
                                 POP_REF(elem_type);
                         }
                         }
-                        else if (opcode1 == WASM_OP_ARRAY_NEW_CANON_DATA
-                                 || opcode1 == WASM_OP_ARRAY_NEW_CANON_ELEM) {
+                        else if (opcode1 == WASM_OP_ARRAY_NEW_CANON_DATA) {
+                            /* offset of data segment */
+                            POP_I32();
+
+                            if (u32 >= module->data_seg_count) {
+                                set_error_buf(error_buf, error_buf_size,
+                                              "unknown data segement");
+                                goto fail;
+                            }
+
+                            if (wasm_is_type_reftype(elem_type)) {
+                                set_error_buf(error_buf, error_buf_size,
+                                              "array elem type mismatch");
+                                goto fail;
+                            }
+                        }
+                        else if (opcode1 == WASM_OP_ARRAY_NEW_CANON_ELEM) {
+                            WASMTableSeg *table_seg =
+                                module->table_segments + u32;
+
+                            /* offset of element segment */
                             POP_I32();
                             POP_I32();
+
+                            if (u32 >= module->table_seg_count) {
+                                set_error_buf(error_buf, error_buf_size,
+                                              "unknown element segement");
+                                goto fail;
+                            }
+                            if (!wasm_reftype_is_subtype_of(
+                                    table_seg->elem_type,
+                                    table_seg->elem_ref_type, elem_type,
+                                    array_type->elem_ref_type, module->types,
+                                    module->type_count)) {
+                                set_error_buf(error_buf, error_buf_size,
+                                              "array elem type mismatch");
+                                goto fail;
+                            }
                         }
                         }
 
 
                         /* PUSH array obj, (ref $t) */
                         /* PUSH array obj, (ref $t) */

+ 16 - 20
tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch

@@ -82,7 +82,7 @@ index 57457286..5c0bd457 100644
  (assert_return (invoke $module1 "call-9") (i32.const 70))
  (assert_return (invoke $module1 "call-9") (i32.const 70))
 +;)
 +;)
 diff --git a/test/core/gc/array.wast b/test/core/gc/array.wast
 diff --git a/test/core/gc/array.wast b/test/core/gc/array.wast
-index 7ee75b20..f2287add 100644
+index 7ee75b20..e3e0f635 100644
 --- a/test/core/gc/array.wast
 --- a/test/core/gc/array.wast
 +++ b/test/core/gc/array.wast
 +++ b/test/core/gc/array.wast
 @@ -35,10 +35,10 @@
 @@ -35,10 +35,10 @@
@@ -136,15 +136,7 @@ index 7ee75b20..f2287add 100644
  (assert_return (invoke "get" (i32.const 0)) (f32.const 1))
  (assert_return (invoke "get" (i32.const 0)) (f32.const 1))
  (assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7))
  (assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7))
  (assert_return (invoke "len") (i32.const 2))
  (assert_return (invoke "len") (i32.const 2))
-@@ -148,6 +148,7 @@
- (assert_trap (invoke "get" (i32.const 10)) "out of bounds")
- (assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds")
- 
-+(; ;; TODO: support array.new_canon_data
- (module
-   (type $vec (array i8))
-   (type $mvec (array (mut i8)))
-@@ -185,14 +186,16 @@
+@@ -185,7 +185,7 @@
  )
  )
  
  
  (assert_return (invoke "new") (ref.array))
  (assert_return (invoke "new") (ref.array))
@@ -153,25 +145,29 @@ index 7ee75b20..f2287add 100644
  (assert_return (invoke "get" (i32.const 0)) (i32.const 1))
  (assert_return (invoke "get" (i32.const 0)) (i32.const 1))
  (assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7))
  (assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7))
  (assert_return (invoke "len") (i32.const 3))
  (assert_return (invoke "len") (i32.const 3))
+@@ -201,8 +201,8 @@
+   (type $avec (array (mut anyref)))
+ 
+   (elem $e (ref $bvec)
+-    (array.new_canon $bvec (i32.const 7) (i32.const 3))
+-    (array.new_canon_fixed $bvec 2 (i32.const 1) (i32.const 2))
++    ;;(array.new_canon $bvec (i32.const 7) (i32.const 3))
++    ;;(array.new_canon_fixed $bvec 2 (i32.const 1) (i32.const 2))
+   )
  
  
- (assert_trap (invoke "get" (i32.const 10)) "out of bounds")
- (assert_trap (invoke "set_get" (i32.const 10) (i32.const 7)) "out of bounds")
-+;)
- 
-+(; ;; TODO: support array.new_canon_elem
- (module
-   (type $bvec (array i8))
-   (type $vec (array (ref $bvec)))
-@@ -243,7 +246,7 @@
+   (func $new (export "new") (result (ref $vec))
+@@ -242,8 +242,9 @@
+   )
  )
  )
  
  
++(; ;; TODO: support array.new_canon_elem
  (assert_return (invoke "new") (ref.array))
  (assert_return (invoke "new") (ref.array))
 -(assert_return (invoke "new") (ref.eq))
 -(assert_return (invoke "new") (ref.eq))
 +;;(assert_return (invoke "new") (ref.eq))
 +;;(assert_return (invoke "new") (ref.eq))
  (assert_return (invoke "get" (i32.const 0) (i32.const 0)) (i32.const 7))
  (assert_return (invoke "get" (i32.const 0) (i32.const 0)) (i32.const 7))
  (assert_return (invoke "get" (i32.const 1) (i32.const 0)) (i32.const 1))
  (assert_return (invoke "get" (i32.const 1) (i32.const 0)) (i32.const 1))
  (assert_return (invoke "set_get" (i32.const 0) (i32.const 1) (i32.const 1)) (i32.const 2))
  (assert_return (invoke "set_get" (i32.const 0) (i32.const 1) (i32.const 1)) (i32.const 2))
-@@ -251,6 +254,7 @@
+@@ -251,6 +252,7 @@
  
  
  (assert_trap (invoke "get" (i32.const 10) (i32.const 0)) "out of bounds")
  (assert_trap (invoke "get" (i32.const 10) (i32.const 0)) "out of bounds")
  (assert_trap (invoke "set_get" (i32.const 10) (i32.const 0) (i32.const 0)) "out of bounds")
  (assert_trap (invoke "set_get" (i32.const 10) (i32.const 0) (i32.const 0)) "out of bounds")