Browse Source

Define the GC runtime APIs to export (#2143)

Wenyong Huang 2 năm trước cách đây
mục cha
commit
74417d6de9

+ 330 - 0
core/iwasm/common/gc/gc_common.c

@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "../wasm_runtime_common.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+
+uint32
+wasm_get_defined_type_count(WASMModuleCommon *const module)
+{
+    /* TODO */
+    return 0;
+}
+
+WASMType *
+wasm_get_defined_type(WASMModuleCommon *const module, uint32 index)
+{
+    /* TODO */
+    return NULL;
+}
+
+bool
+wasm_defined_type_is_func_type(WASMType *const def_type)
+{
+    /* TODO */
+    return false;
+}
+
+bool
+wasm_defined_type_is_struct_type(WASMType *const def_type)
+{
+    /* TODO */
+    return false;
+}
+
+bool
+wasm_defined_type_is_array_type(WASMType *const def_type)
+{
+    /* TODO */
+    return false;
+}
+
+uint32
+wasm_func_type_get_param_count(WASMFuncType *const func_type)
+{
+    /* TODO */
+    return 0;
+}
+
+wasm_ref_type_t
+wasm_func_type_get_param_type(WASMFuncType *const func_type, uint32 param_idx)
+{
+    wasm_ref_type_t ref_type = { 0 };
+    /* TODO */
+    return ref_type;
+}
+
+uint32
+wasm_func_type_get_result_count(WASMFuncType *const func_type)
+{
+    /* TODO */
+    return 0;
+}
+
+wasm_ref_type_t
+wasm_func_type_get_result_type(WASMFuncType *const func_type, uint32 param_idx)
+{
+    wasm_ref_type_t ref_type = { 0 };
+    /* TODO */
+    return ref_type;
+}
+
+uint32
+wasm_struct_type_get_field_count(WASMStructType *const struct_type)
+{
+    /* TODO */
+    return 0;
+}
+
+wasm_ref_type_t
+wasm_struct_type_get_field_type(WASMStructType *const struct_type,
+                                uint32 field_idx, bool *p_is_mutable)
+{
+    wasm_ref_type_t ref_type = { 0 };
+    /* TODO */
+    return ref_type;
+}
+
+wasm_ref_type_t
+wasm_array_type_get_elem_type(WASMArrayType *const array_type,
+                              bool *p_is_mutable)
+{
+    wasm_ref_type_t ref_type = { 0 };
+    /* TODO */
+    return ref_type;
+}
+
+bool
+wasm_defined_type_equal(WASMType *const def_type1, WASMType *const def_type2,
+                        WASMModuleCommon *const module)
+{
+    /* TODO */
+    return false;
+}
+
+bool
+wasm_defined_type_is_subtype_of(WASMType *const def_type1,
+                                WASMType *const def_type2,
+                                WASMModuleCommon *const module)
+{
+    /* TODO */
+    return false;
+}
+
+void
+wasm_ref_type_set_type_idx(wasm_ref_type_t *ref_type, bool nullable,
+                           int32 type_idx)
+{
+    /* TODO */
+}
+
+void
+wasm_ref_type_set_heap_type(wasm_ref_type_t *ref_type, bool nullable,
+                            int32 heap_type)
+{
+    /* TODO */
+}
+
+bool
+wasm_ref_type_equal(const wasm_ref_type_t *ref_type1,
+                    const wasm_ref_type_t *ref_type2,
+                    WASMModuleCommon *const module)
+{
+    /* TODO */
+    return false;
+}
+
+bool
+wasm_ref_type_is_subtype_of(const wasm_ref_type_t *ref_type1,
+                            const wasm_ref_type_t *ref_type2,
+                            WASMModuleCommon *const module)
+{
+    /* TODO */
+    return false;
+}
+
+WASMStructObjectRef
+wasm_struct_obj_new_with_typeidx(WASMExecEnv *exec_env, uint32 type_idx)
+{
+    /* TODO */
+    return NULL;
+}
+
+WASMStructObjectRef
+wasm_struct_obj_new_with_type(WASMExecEnv *exec_env, WASMStructType *type)
+{
+    /* TODO */
+    return NULL;
+}
+
+WASMArrayObjectRef
+wasm_array_obj_new_with_typeidx(WASMExecEnv *exec_env, uint32 type_idx)
+{
+    /* TODO */
+    return NULL;
+}
+
+WASMArrayObjectRef
+wasm_array_obj_new_with_type(WASMExecEnv *exec_env, WASMArrayType *type)
+{
+    /* TODO */
+    return NULL;
+}
+
+WASMFuncObjectRef
+wasm_func_obj_new_with_typeidx(WASMExecEnv *exec_env, uint32 type_idx)
+{
+    /* TODO */
+    return NULL;
+}
+
+WASMFuncObjectRef
+wasm_func_obj_new_with_type(WASMExecEnv *exec_env, WASMFuncType *type)
+{
+    /* TODO */
+    return NULL;
+}
+
+bool
+wasm_obj_is_instance_of_defined_type(WASMObjectRef obj, WASMType *defined_type,
+                                     WASMModuleCommon *const module)
+{
+    /* TODO */
+    return false;
+}
+
+bool
+wasm_obj_is_instance_of_type_idx(WASMObjectRef obj, uint32 type_idx,
+                                 WASMModuleCommon *const module)
+{
+    /* TODO */
+    return false;
+}
+
+bool
+wasm_obj_is_instance_of_ref_type(const WASMObjectRef obj,
+                                 const wasm_ref_type_t *ref_type)
+{
+    /* TODO */
+    return false;
+}
+
+void
+wasm_runtime_push_local_object_ref(WASMExecEnv *exec_env,
+                                   WASMLocalObjectRef *ref)
+{
+    ref->val = NULL;
+    ref->prev = exec_env->cur_local_object_ref;
+    exec_env->cur_local_object_ref = ref;
+}
+
+WASMLocalObjectRef *
+wasm_runtime_pop_local_object_ref(WASMExecEnv *exec_env)
+{
+    WASMLocalObjectRef *local_ref = exec_env->cur_local_object_ref;
+    exec_env->cur_local_object_ref = exec_env->cur_local_object_ref->prev;
+    return local_ref;
+}
+
+void
+wasm_runtime_pop_local_object_refs(WASMExecEnv *exec_env, uint32 n)
+{
+    bh_assert(n > 0);
+
+    do {
+        exec_env->cur_local_object_ref = exec_env->cur_local_object_ref->prev;
+    } while (--n > 0);
+}
+
+void
+wasm_runtime_gc_prepare(WASMExecEnv *exec_env)
+{
+#if 0
+    /* TODO: implement wasm_runtime_gc_prepare for multi-thread */
+    exec_env->is_gc_reclaiming = false;
+    wasm_thread_suspend_all();
+    exec_env->is_gc_reclaim = 1;
+    exec_env->requesting_suspend = 0;
+#endif
+}
+
+void
+wasm_runtime_gc_finalize(WASMExecEnv *exec_env)
+{
+#if 0
+    /* TODO: implement wasm_runtime_gc_finalize for multi-thread */
+    wasm_thread_resume_all();
+    exec_env->doing_gc_reclaim = 0;
+#endif
+}
+
+bool
+wasm_runtime_get_wasm_object_ref_list(WASMObjectRef obj,
+                                      bool *p_is_compact_mode,
+                                      uint32 *p_ref_num, uint16 **p_ref_list,
+                                      uint32 *p_ref_start_offset)
+{
+    return wasm_object_get_ref_list(obj, p_is_compact_mode, p_ref_num,
+                                    p_ref_list, p_ref_start_offset);
+}
+
+bool
+wasm_runtime_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) {
+        return wasm_traverse_gc_rootset(exec_env, heap);
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (exec_env->module_inst->module_type == Wasm_Module_AoT) {
+        /* TODO */
+        /*return aot_traverse_gc_rootset(exec_env, heap);*/
+    }
+#endif
+    return false;
+}
+
+void
+wasm_runtime_set_gc_heap_handle(WASMModuleInstanceCommon *module_inst,
+                                void *gc_heap_handle)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode)
+        ((WASMModuleInstance *)module_inst)->e->gc_heap_handle = gc_heap_handle;
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        /* TODO */
+        /*
+        ((AOTModuleInstance *)module_inst)->e->gc_heap_handle.ptr =
+        gc_heap_handle;
+        */
+    }
+#endif
+}
+
+void *
+wasm_runtime_get_gc_heap_handle(WASMModuleInstanceCommon *module_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode)
+        return ((WASMModuleInstance *)module_inst)->e->gc_heap_handle;
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        /* TODO */
+        /*
+        return ((AOTModuleInstance *)module_inst)->e->gc_heap_handle.ptr;
+        */
+    }
+#endif
+    return NULL;
+}

+ 237 - 11
core/iwasm/common/gc/gc_object.c

@@ -6,6 +6,12 @@
 #include "gc_object.h"
 #include "mem_alloc.h"
 #include "../wasm_runtime_common.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
 
 WASMRttTypeRef
 wasm_rtt_type_new(WASMType *defined_type, uint32 defined_type_idx,
@@ -51,9 +57,29 @@ gc_obj_malloc(void *heap_handle, uint64 size)
     return mem;
 }
 
+static void *
+get_gc_heap_handle(WASMExecEnv *exec_env)
+{
+    void *gc_heap_handle = NULL;
+    WASMModuleInstanceCommon *module_inst = exec_env->module_inst;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode)
+        gc_heap_handle = ((WASMModuleInstance *)module_inst)->e->gc_heap_handle;
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT)
+        gc_heap_handle = NULL; /* TODO */
+#endif
+
+    bh_assert(gc_heap_handle);
+    return gc_heap_handle;
+}
+
 WASMStructObjectRef
-wasm_struct_obj_new(void *heap_handle, WASMRttTypeRef rtt_type)
+wasm_struct_obj_new(WASMExecEnv *exec_env, WASMRttTypeRef rtt_type)
 {
+    void *heap_handle = get_gc_heap_handle(exec_env);
     WASMStructObjectRef struct_obj;
     WASMStructType *struct_type;
 
@@ -71,7 +97,7 @@ wasm_struct_obj_new(void *heap_handle, WASMRttTypeRef rtt_type)
 
 void
 wasm_struct_obj_set_field(WASMStructObjectRef struct_obj, uint32 field_idx,
-                          WASMValue *value)
+                          const WASMValue *value)
 {
     WASMRttTypeRef rtt_type =
         (WASMRttTypeRef)wasm_object_header((WASMObjectRef)struct_obj);
@@ -152,9 +178,10 @@ wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
 }
 
 WASMArrayObjectRef
-wasm_array_obj_new(void *heap_handle, WASMRttTypeRef rtt_type, uint32 length,
-                   WASMValue *init_value)
+wasm_array_obj_new(WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
+                   uint32 length, WASMValue *init_value)
 {
+    void *heap_handle = get_gc_heap_handle(exec_env);
     WASMArrayObjectRef array_obj;
     WASMArrayType *array_type;
     uint64 total_size;
@@ -214,7 +241,7 @@ wasm_array_obj_new(void *heap_handle, WASMRttTypeRef rtt_type, uint32 length,
 
 void
 wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
-                        WASMValue *value)
+                        const WASMValue *value)
 {
     uint8 *elem_data = wasm_array_obj_elem_addr(array_obj, elem_idx);
     uint32 elem_size = 1 << wasm_array_obj_elem_size_log(array_obj);
@@ -236,7 +263,7 @@ wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
 }
 
 void
-wasm_array_obj_get_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
+wasm_array_obj_get_elem(const WASMArrayObjectRef array_obj, uint32 elem_idx,
                         bool sign_extend, WASMValue *value)
 {
     uint8 *elem_data = wasm_array_obj_elem_addr(array_obj, elem_idx);
@@ -271,9 +298,28 @@ wasm_array_obj_copy(WASMArrayObjectRef dst_obj, uint32 dst_idx,
     bh_memmove_s(dst_data, elem_size * len, src_data, elem_size * len);
 }
 
+uint32
+wasm_array_obj_length(const WASMArrayObjectRef array_obj)
+{
+    return array_obj->length >> WASM_ARRAY_LENGTH_SHIFT;
+}
+
+void *
+wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj)
+{
+    return array_obj->elem_data;
+}
+
+void *
+wasm_array_obj_elem_addr(const WASMArrayObjectRef array_obj, uint32 elem_idx)
+{
+    return array_obj->elem_data
+           + (elem_idx << wasm_array_obj_elem_size_log(array_obj));
+}
+
 WASMFuncObjectRef
-wasm_func_obj_new(void *heap_handle, WASMRttTypeRef rtt_type,
-                  uint32 func_idx_bound)
+wasm_func_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type,
+                           uint32 func_idx_bound)
 {
     WASMFuncObjectRef func_obj;
     uint64 total_size;
@@ -291,9 +337,33 @@ wasm_func_obj_new(void *heap_handle, WASMRttTypeRef rtt_type,
     return func_obj;
 }
 
+WASMFuncObjectRef
+wasm_func_obj_new(WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
+                  uint32 func_idx_bound)
+{
+    void *heap_handle = get_gc_heap_handle(exec_env);
+    return wasm_func_obj_new_internal(heap_handle, rtt_type, func_idx_bound);
+}
+
+uint32
+wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj)
+{
+    return func_obj->func_idx_bound;
+}
+
+WASMFuncType *
+wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj)
+{
+    WASMRttTypeRef rtt_type =
+        (WASMRttTypeRef)wasm_object_header((WASMObjectRef)func_obj);
+    bh_assert(rtt_type->type_flag == WASM_TYPE_FUNC);
+    return (WASMFuncType *)rtt_type->defined_type;
+}
+
 WASMExternrefObjectRef
-wasm_externref_obj_new(WASMExecEnv *exec_env, void *heap_handle, void *host_obj)
+wasm_externref_obj_new(WASMExecEnv *exec_env, const void *host_obj)
 {
+    void *heap_handle = get_gc_heap_handle(exec_env);
     WASMAnyrefObjectRef anyref_obj;
     WASMExternrefObjectRef externref_obj;
     WASMLocalObjectRef local_ref;
@@ -323,8 +393,9 @@ wasm_externref_obj_new(WASMExecEnv *exec_env, void *heap_handle, void *host_obj)
 }
 
 WASMAnyrefObjectRef
-wasm_anyref_obj_new(WASMExecEnv *exec_env, void *heap_handle, void *host_obj)
+wasm_anyref_obj_new(WASMExecEnv *exec_env, const void *host_obj)
 {
+    void *heap_handle = get_gc_heap_handle(exec_env);
     WASMAnyrefObjectRef anyref_obj;
 
     if (!(anyref_obj = gc_obj_malloc(heap_handle, sizeof(WASMAnyrefObject)))) {
@@ -344,9 +415,10 @@ wasm_externref_obj_to_internal_obj(WASMExternrefObjectRef externref_obj)
 }
 
 WASMExternrefObjectRef
-wasm_internal_obj_to_externref_obj(void *heap_handle,
+wasm_internal_obj_to_externref_obj(WASMExecEnv *exec_env,
                                    WASMObjectRef internal_obj)
 {
+    void *heap_handle = get_gc_heap_handle(exec_env);
     WASMExternrefObjectRef externref_obj;
 
     if (!(externref_obj =
@@ -360,6 +432,160 @@ wasm_internal_obj_to_externref_obj(void *heap_handle,
     return externref_obj;
 }
 
+const void *
+wasm_anyref_obj_get_value(WASMAnyrefObjectRef anyref_obj)
+{
+    return anyref_obj->host_obj;
+}
+
+const void *
+wasm_externref_obj_get_value(const WASMExternrefObjectRef externref_obj)
+{
+    if (wasm_obj_is_anyref_obj(externref_obj->internal_obj))
+        return ((WASMAnyrefObjectRef)externref_obj->internal_obj)->host_obj;
+    else
+        return externref_obj->internal_obj;
+}
+
+WASMI31ObjectRef
+wasm_i31_obj_new(uint32 i31_value)
+{
+    return (WASMI31ObjectRef)((i31_value << 1) | 1);
+}
+
+uint32
+wasm_i31_obj_get_value(WASMI31ObjectRef i31_obj, bool sign_extend)
+{
+    uint32 i31_value = (uint32)(((uintptr_t)i31_obj) >> 1);
+    if (sign_extend && (i31_value & 0x40000000)) /* bit 30 is 1 */
+        /* set bit 31 to 1 */
+        i31_value |= 0x80000000;
+    return i31_value;
+}
+
+bool
+wasm_obj_is_i31_obj(WASMObjectRef obj)
+{
+    bh_assert(obj);
+    return (((uintptr_t)obj) & 1) ? true : false;
+}
+
+bool
+wasm_obj_is_externref_obj(WASMObjectRef obj)
+{
+    bh_assert(obj);
+    return (!wasm_obj_is_i31_obj(obj)
+            && (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG))
+               ? true
+               : false;
+}
+
+bool
+wasm_obj_is_anyref_obj(WASMObjectRef obj)
+{
+    bh_assert(obj);
+    return (!wasm_obj_is_i31_obj(obj)
+            && (obj->header & WASM_OBJ_ANYREF_OBJ_FLAG))
+               ? true
+               : false;
+}
+
+bool
+wasm_obj_is_i31_externref_or_anyref_obj(WASMObjectRef obj)
+{
+    bh_assert(obj);
+    return (wasm_obj_is_i31_obj(obj)
+            || (obj->header
+                & (WASM_OBJ_EXTERNREF_OBJ_FLAG | WASM_OBJ_ANYREF_OBJ_FLAG)))
+               ? true
+               : false;
+}
+
+bool
+wasm_obj_is_struct_obj(WASMObjectRef obj)
+{
+    WASMRttTypeRef rtt_type;
+
+    bh_assert(obj);
+
+    if (wasm_obj_is_i31_externref_or_anyref_obj(obj))
+        return false;
+
+    rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
+    return rtt_type->type_flag == WASM_TYPE_STRUCT ? true : false;
+}
+
+bool
+wasm_obj_is_array_obj(WASMObjectRef obj)
+{
+    WASMRttTypeRef rtt_type;
+
+    bh_assert(obj);
+
+    if (wasm_obj_is_i31_externref_or_anyref_obj(obj))
+        return false;
+
+    rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
+    return rtt_type->type_flag == WASM_TYPE_ARRAY ? true : false;
+}
+
+bool
+wasm_obj_is_func_obj(WASMObjectRef obj)
+{
+    WASMRttTypeRef rtt_type;
+
+    bh_assert(obj);
+
+    if (wasm_obj_is_i31_externref_or_anyref_obj(obj))
+        return false;
+
+    rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
+    return rtt_type->type_flag == WASM_TYPE_FUNC ? true : false;
+}
+
+bool
+wasm_obj_is_internal_obj(WASMObjectRef obj)
+{
+    WASMRttTypeRef rtt_type;
+
+    bh_assert(obj);
+
+    if (wasm_obj_is_i31_obj(obj))
+        return true;
+    else if (obj->header & WASM_OBJ_ANYREF_OBJ_FLAG)
+        return true;
+    else if (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG)
+        return false;
+    else {
+        rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
+        return (rtt_type->type_flag == WASM_TYPE_STRUCT
+                || rtt_type->type_flag == WASM_TYPE_ARRAY)
+                   ? true
+                   : false;
+    }
+}
+
+bool
+wasm_obj_is_eq_obj(WASMObjectRef obj)
+{
+    WASMRttTypeRef rtt_type;
+
+    bh_assert(obj);
+
+    if (wasm_obj_is_i31_obj(obj))
+        return true;
+    else if ((obj->header & WASM_OBJ_ANYREF_OBJ_FLAG)
+             || (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG))
+        return false;
+    else {
+        rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
+        return (rtt_type->type_flag == WASM_TYPE_STRUCT
+                || rtt_type->type_flag == WASM_TYPE_ARRAY)
+                   ? true
+                   : false;
+    }
+}
+
 bool
 wasm_obj_is_created_from_heap(WASMObjectRef obj)
 {

+ 53 - 188
core/iwasm/common/gc/gc_object.h

@@ -60,7 +60,7 @@ typedef struct WASMExternrefObject {
 typedef struct WASMAnyrefObject {
     /* bits[1] must be 1, denotes an anyref object */
     WASMObjectHeader header;
-    void *host_obj;
+    const void *host_obj;
 } WASMAnyrefObject, *WASMAnyrefObjectRef;
 
 /**
@@ -119,26 +119,26 @@ wasm_rtt_type_get_defined_type(const WASMRttTypeRef rtt_type)
 }
 
 WASMStructObjectRef
-wasm_struct_obj_new(void *heap_handle, WASMRttTypeRef rtt_type);
+wasm_struct_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type);
 
 void
 wasm_struct_obj_set_field(WASMStructObjectRef struct_obj, uint32 field_idx,
-                          WASMValue *value);
+                          const WASMValue *value);
 
 void
 wasm_struct_obj_get_field(const WASMStructObjectRef struct_obj,
                           uint32 field_idx, bool sign_extend, WASMValue *value);
 
 WASMArrayObjectRef
-wasm_array_obj_new(void *heap_handle, WASMRttTypeRef rtt_type, uint32 length,
-                   WASMValue *init_value);
+wasm_array_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
+                   uint32 length, WASMValue *init_value);
 
 void
 wasm_array_obj_set_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
-                        WASMValue *value);
+                        const WASMValue *value);
 
 void
-wasm_array_obj_get_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
+wasm_array_obj_get_elem(const WASMArrayObjectRef array_obj, uint32 elem_idx,
                         bool sign_extend, WASMValue *value);
 
 void
@@ -165,11 +165,8 @@ wasm_array_obj_elem_size_log(const WASMArrayObjectRef array_obj)
  *
  * @return the length of the array
  */
-inline static uint32
-wasm_array_obj_length(const WASMArrayObjectRef array_obj)
-{
-    return array_obj->length >> WASM_ARRAY_LENGTH_SHIFT;
-}
+uint32
+wasm_array_obj_length(const WASMArrayObjectRef array_obj);
 
 /**
  * Return the address of the first element of an array object.
@@ -178,11 +175,8 @@ wasm_array_obj_length(const WASMArrayObjectRef array_obj)
  *
  * @return the address of the first element of the array object
  */
-inline static void *
-wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj)
-{
-    return array_obj->elem_data;
-}
+void *
+wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj);
 
 /**
  * Return the address of the i-th element of an array object.
@@ -192,205 +186,76 @@ wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj)
  *
  * @return the address of the i-th element of the array object
  */
-inline static void *
-wasm_array_obj_elem_addr(const WASMArrayObjectRef array_obj, uint32 elem_idx)
-{
-    return array_obj->elem_data
-           + (elem_idx << wasm_array_obj_elem_size_log(array_obj));
-}
+void *
+wasm_array_obj_elem_addr(const WASMArrayObjectRef array_obj, uint32 elem_idx);
+
+WASMFuncObjectRef
+wasm_func_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type,
+                           uint32 func_idx_bound);
 
 WASMFuncObjectRef
-wasm_func_obj_new(void *heap_handle, WASMRttTypeRef rtt_type,
+wasm_func_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
                   uint32 func_idx_bound);
 
-inline static uint32
-wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj)
-{
-    return func_obj->func_idx_bound;
-}
+uint32
+wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj);
 
-inline static WASMFuncType *
-wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj)
-{
-    WASMRttTypeRef rtt_type =
-        (WASMRttTypeRef)wasm_object_header((WASMObjectRef)func_obj);
-    bh_assert(rtt_type->type_flag == WASM_TYPE_FUNC);
-    return (WASMFuncType *)rtt_type->defined_type;
-}
+WASMFuncType *
+wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj);
 
 WASMExternrefObjectRef
-wasm_externref_obj_new(struct WASMExecEnv *exec_env, void *heap_handle,
-                       void *host_obj);
+wasm_externref_obj_new(struct WASMExecEnv *exec_env, const void *host_obj);
 
 WASMAnyrefObjectRef
-wasm_anyref_obj_new(struct WASMExecEnv *exec_env, void *heap_handle,
-                    void *host_obj);
+wasm_anyref_obj_new(struct WASMExecEnv *exec_env, const void *host_obj);
 
 /* Implementation of opcode extern.internalize */
 WASMObjectRef
-wasm_externref_obj_to_internal_obj(WASMExternrefObjectRef externref_obj);
+wasm_externref_obj_to_internal_obj(const WASMExternrefObjectRef externref_obj);
 
 /* Implementation of opcode extern.externalize */
 WASMExternrefObjectRef
-wasm_internal_obj_to_externref_obj(void *heap_handle,
-                                   WASMObjectRef internal_obj);
-
-inline static bool
-wasm_obj_is_anyref_obj(WASMObjectRef obj);
-
-inline static void *
-wasm_anyref_obj_get_value(WASMAnyrefObjectRef anyref_obj)
-{
-    return anyref_obj->host_obj;
-}
-
-inline static void *
-wasm_externref_obj_get_value(const WASMExternrefObjectRef externref_obj)
-{
-    if (wasm_obj_is_anyref_obj(externref_obj->internal_obj))
-        return ((WASMAnyrefObjectRef)externref_obj->internal_obj)->host_obj;
-    else
-        return externref_obj->internal_obj;
-}
-
-inline static WASMI31ObjectRef
-wasm_i31_obj_new(uint32 i31_value)
-{
-    return (WASMI31ObjectRef)((i31_value << 1) | 1);
-}
-
-inline static uint32
-wasm_i31_obj_get_value(WASMI31ObjectRef i31_obj, bool sign_extend)
-{
-    uint32 i31_value = (uint32)(((uintptr_t)i31_obj) >> 1);
-    if (sign_extend && (i31_value & 0x40000000)) /* bit 30 is 1 */
-        /* set bit 31 to 1 */
-        i31_value |= 0x80000000;
-    return i31_value;
-}
-
-inline static bool
-wasm_obj_is_i31_obj(WASMObjectRef obj)
-{
-    bh_assert(obj);
-    return (((uintptr_t)obj) & 1) ? true : false;
-}
-
-inline static bool
-wasm_obj_is_externref_obj(WASMObjectRef obj)
-{
-    bh_assert(obj);
-    return (!wasm_obj_is_i31_obj(obj)
-            && (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG))
-               ? true
-               : false;
-}
-
-inline static bool
-wasm_obj_is_anyref_obj(WASMObjectRef obj)
-{
-    bh_assert(obj);
-    return (!wasm_obj_is_i31_obj(obj)
-            && (obj->header & WASM_OBJ_ANYREF_OBJ_FLAG))
-               ? true
-               : false;
-}
-
-inline static bool
-wasm_obj_is_i31_externref_or_anyref_obj(WASMObjectRef obj)
-{
-    bh_assert(obj);
-    return (wasm_obj_is_i31_obj(obj)
-            || (obj->header
-                & (WASM_OBJ_EXTERNREF_OBJ_FLAG | WASM_OBJ_ANYREF_OBJ_FLAG)))
-               ? true
-               : false;
-}
+wasm_internal_obj_to_externref_obj(struct WASMExecEnv *exec_env,
+                                   const WASMObjectRef internal_obj);
 
-inline static bool
-wasm_obj_is_struct_obj(WASMObjectRef obj)
-{
-    WASMRttTypeRef rtt_type;
+const void *
+wasm_anyref_obj_get_value(const WASMAnyrefObjectRef anyref_obj);
 
-    bh_assert(obj);
+const void *
+wasm_externref_obj_get_value(const WASMExternrefObjectRef externref_obj);
 
-    if (wasm_obj_is_i31_externref_or_anyref_obj(obj))
-        return false;
+WASMI31ObjectRef
+wasm_i31_obj_new(uint32 i31_value);
 
-    rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
-    return rtt_type->type_flag == WASM_TYPE_STRUCT ? true : false;
-}
+uint32
+wasm_i31_obj_get_value(WASMI31ObjectRef i31_obj, bool sign_extend);
 
-inline static bool
-wasm_obj_is_array_obj(WASMObjectRef obj)
-{
-    WASMRttTypeRef rtt_type;
-
-    bh_assert(obj);
+bool
+wasm_obj_is_i31_obj(WASMObjectRef obj);
 
-    if (wasm_obj_is_i31_externref_or_anyref_obj(obj))
-        return false;
+bool
+wasm_obj_is_externref_obj(WASMObjectRef obj);
 
-    rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
-    return rtt_type->type_flag == WASM_TYPE_ARRAY ? true : false;
-}
+bool
+wasm_obj_is_anyref_obj(WASMObjectRef obj);
 
-inline static bool
-wasm_obj_is_func_obj(WASMObjectRef obj)
-{
-    WASMRttTypeRef rtt_type;
+bool
+wasm_obj_is_i31_externref_or_anyref_obj(WASMObjectRef obj);
 
-    bh_assert(obj);
+bool
+wasm_obj_is_struct_obj(WASMObjectRef obj);
 
-    if (wasm_obj_is_i31_externref_or_anyref_obj(obj))
-        return false;
+bool
+wasm_obj_is_array_obj(WASMObjectRef obj);
 
-    rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
-    return rtt_type->type_flag == WASM_TYPE_FUNC ? true : false;
-}
+bool
+wasm_obj_is_func_obj(WASMObjectRef obj);
 
-inline static bool
-wasm_obj_is_internal_obj(WASMObjectRef obj)
-{
-    WASMRttTypeRef rtt_type;
-
-    bh_assert(obj);
-
-    if (wasm_obj_is_i31_obj(obj))
-        return true;
-    else if (obj->header & WASM_OBJ_ANYREF_OBJ_FLAG)
-        return true;
-    else if (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG)
-        return false;
-    else {
-        rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
-        return (rtt_type->type_flag == WASM_TYPE_STRUCT
-                || rtt_type->type_flag == WASM_TYPE_ARRAY)
-                   ? true
-                   : false;
-    }
-}
+bool
+wasm_obj_is_internal_obj(WASMObjectRef obj);
 
-inline static bool
-wasm_obj_is_eq_obj(WASMObjectRef obj)
-{
-    WASMRttTypeRef rtt_type;
-
-    bh_assert(obj);
-
-    if (wasm_obj_is_i31_obj(obj))
-        return true;
-    else if ((obj->header & WASM_OBJ_ANYREF_OBJ_FLAG)
-             || (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG))
-        return false;
-    else {
-        rtt_type = (WASMRttTypeRef)wasm_object_header(obj);
-        return (rtt_type->type_flag == WASM_TYPE_STRUCT
-                || rtt_type->type_flag == WASM_TYPE_ARRAY)
-                   ? true
-                   : false;
-    }
-}
+bool
+wasm_obj_is_eq_obj(WASMObjectRef obj);
 
 inline static bool
 wasm_obj_is_null_obj(WASMObjectRef obj)

+ 1 - 13
core/iwasm/common/wasm_application.c

@@ -510,21 +510,9 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
                     }
                     else if (type->types[i] == VALUE_TYPE_EXTERNREF) {
                         WASMExternrefObjectRef gc_obj;
-                        void *gc_heap_handle = NULL;
                         void *extern_obj =
                             (void *)(uintptr_t)strtoull(argv[i], &endptr, 0);
-#if WASM_ENABLE_INTERP != 0
-                        if (module_inst->module_type == Wasm_Module_Bytecode)
-                            gc_heap_handle = ((WASMModuleInstance *)module_inst)
-                                                 ->e->gc_heap_handle;
-#endif
-#if WASM_ENABLE_AOT != 0
-                        if (module_inst->module_type == Wasm_Module_AoT)
-                            gc_heap_handle = NULL; /* TODO */
-#endif
-                        bh_assert(gc_heap_handle);
-                        gc_obj = wasm_externref_obj_new(
-                            exec_env, gc_heap_handle, extern_obj);
+                        gc_obj = wasm_externref_obj_new(exec_env, extern_obj);
                         if (!gc_obj) {
                             wasm_runtime_set_exception(
                                 module_inst, "create extern object failed");

+ 0 - 115
core/iwasm/common/wasm_runtime_common.c

@@ -3285,121 +3285,6 @@ wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
 }
 #endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
 
-#if WASM_ENABLE_GC != 0
-void
-wasm_runtime_push_local_object_ref(WASMExecEnv *exec_env,
-                                   WASMLocalObjectRef *ref)
-{
-    ref->val = NULL;
-    ref->prev = exec_env->cur_local_object_ref;
-    exec_env->cur_local_object_ref = ref;
-}
-
-WASMLocalObjectRef *
-wasm_runtime_pop_local_object_ref(WASMExecEnv *exec_env)
-{
-    WASMLocalObjectRef *local_ref = exec_env->cur_local_object_ref;
-    exec_env->cur_local_object_ref = exec_env->cur_local_object_ref->prev;
-    return local_ref;
-}
-
-void
-wasm_runtime_pop_local_object_refs(WASMExecEnv *exec_env, uint32 n)
-{
-    bh_assert(n > 0);
-
-    do {
-        exec_env->cur_local_object_ref = exec_env->cur_local_object_ref->prev;
-    } while (--n > 0);
-}
-
-void
-wasm_runtime_gc_prepare(WASMExecEnv *exec_env)
-{
-#if 0
-    /* TODO: implement wasm_runtime_gc_prepare for multi-thread */
-    exec_env->is_gc_reclaiming = false;
-    wasm_thread_suspend_all();
-    exec_env->is_gc_reclaim = 1;
-    exec_env->requesting_suspend = 0;
-#endif
-}
-
-void
-wasm_runtime_gc_finalize(WASMExecEnv *exec_env)
-{
-#if 0
-    /* TODO: implement wasm_runtime_gc_finalize for multi-thread */
-    wasm_thread_resume_all();
-    exec_env->doing_gc_reclaim = 0;
-#endif
-}
-
-bool
-wasm_runtime_get_wasm_object_ref_list(WASMObjectRef obj,
-                                      bool *p_is_compact_mode,
-                                      uint32 *p_ref_num, uint16 **p_ref_list,
-                                      uint32 *p_ref_start_offset)
-{
-    return wasm_object_get_ref_list(obj, p_is_compact_mode, p_ref_num,
-                                    p_ref_list, p_ref_start_offset);
-}
-
-bool
-wasm_runtime_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap)
-{
-#if WASM_ENABLE_INTERP != 0
-    if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) {
-        return wasm_traverse_gc_rootset(exec_env, heap);
-    }
-#endif
-#if WASM_ENABLE_AOT != 0
-    if (exec_env->module_inst->module_type == Wasm_Module_AoT) {
-        /* TODO */
-        /*return aot_traverse_gc_rootset(exec_env, heap);*/
-    }
-#endif
-    return false;
-}
-
-void
-wasm_runtime_set_gc_heap_handle(WASMModuleInstanceCommon *module_inst,
-                                void *gc_heap_handle)
-{
-#if WASM_ENABLE_INTERP != 0
-    if (module_inst->module_type == Wasm_Module_Bytecode)
-        ((WASMModuleInstance *)module_inst)->e->gc_heap_handle = gc_heap_handle;
-#endif
-#if WASM_ENABLE_AOT != 0
-    if (module_inst->module_type == Wasm_Module_AoT) {
-        /* TODO */
-        /*
-        ((AOTModuleInstance *)module_inst)->e->gc_heap_handle.ptr =
-        gc_heap_handle;
-        */
-    }
-#endif
-}
-
-void *
-wasm_runtime_get_gc_heap_handle(WASMModuleInstanceCommon *module_inst)
-{
-#if WASM_ENABLE_INTERP != 0
-    if (module_inst->module_type == Wasm_Module_Bytecode)
-        return ((WASMModuleInstance *)module_inst)->e->gc_heap_handle;
-#endif
-#if WASM_ENABLE_AOT != 0
-    if (module_inst->module_type == Wasm_Module_AoT) {
-        /* TODO */
-        /*
-        return ((AOTModuleInstance *)module_inst)->e->gc_heap_handle.ptr;
-        */
-    }
-#endif
-    return NULL;
-}
-#endif /* end of WASM_ENABLE_GC != 0 */
-
 static union {
     int a;
     char b;

+ 0 - 28
core/iwasm/common/wasm_runtime_common.h

@@ -458,34 +458,6 @@ typedef struct wasm_frame_t {
     const char *func_name_wp;
 } WASMCApiFrame;
 
-#if WASM_ENABLE_GC != 0
-/**
- * Local object reference that can be traced when GC occurs. All
- * native functions that need to hold WASM objects which may not be
- * referenced from other elements of GC root set must be hold with
- * this type of variable so that they can be traced when GC occurs.
- * Before using such a variable, it must be pushed onto the stack
- * (implemented as a chain) of such variables, and before leaving the
- * frame of the variables, they must be poped from the stack.
- */
-typedef struct WASMLocalObjectRef {
-    /* Previous local object reference variable on the stack. */
-    struct WASMLocalObjectRef *prev;
-    /* The reference of WASM object hold by this variable. */
-    WASMObjectRef val;
-} WASMLocalObjectRef;
-
-void
-wasm_runtime_push_local_object_ref(WASMExecEnv *exec_env,
-                                   WASMLocalObjectRef *ref);
-
-WASMLocalObjectRef *
-wasm_runtime_pop_local_object_ref(WASMExecEnv *exec_env);
-
-void
-wasm_runtime_pop_local_object_refs(WASMExecEnv *exec_env, uint32 n);
-#endif /* end of WASM_ENABLE_GC != 0 */
-
 #ifdef WASM_ENABLE_JIT
 typedef struct LLVMJITOptions {
     uint32 opt_level;

+ 513 - 0
core/iwasm/include/gc_export.h

@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _GC_EXPORT_H
+#define _GC_EXPORT_H
+
+#include "wasm_export.h"
+
+typedef uint8_t wasm_value_type_t;
+
+typedef enum wasm_value_type_enum {
+    VALUE_TYPE_I32 = 0x7F,
+    VALUE_TYPE_I64 = 0x7E,
+    VALUE_TYPE_F32 = 0x7D,
+    VALUE_TYPE_F64 = 0x7C,
+    VALUE_TYPE_V128 = 0x7B,
+    VALUE_TYPE_FUNCREF = 0x70,
+    VALUE_TYPE_EXTERNREF = 0x6F,
+    VALUE_TYPE_ANYREF = 0x6E,
+    VALUE_TYPE_EQREF = 0x6D,
+    VALUE_TYPE_HT_NULLABLE_REF = 0x6C,
+    VALUE_TYPE_HT_NON_NULLABLE_REF = 0x6B,
+    VALUE_TYPE_I31REF = 0x6A,
+    VALUE_TYPE_NULLFUNCREF = 0x69,
+    VALUE_TYPE_NULLEXTERNREF = 0x68,
+    VALUE_TYPE_STRUCTREF = 0x67,
+    VALUE_TYPE_ARRAYREF = 0x66,
+    VALUE_TYPE_NULLREF = 0x65,
+} wasm_value_type_enum;
+
+typedef int32_t wasm_heap_type_t;
+
+enum wasm_heap_type_enum {
+    HEAP_TYPE_FUNC = -0x10,
+    HEAP_TYPE_EXTERN = -0x11,
+    HEAP_TYPE_ANY = -0x12,
+    HEAP_TYPE_EQ = -0x13,
+    HEAP_TYPE_I31 = -0x16,
+    HEAP_TYPE_NOFUNC = -0x17,
+    HEAP_TYPE_NOEXTERN = -0x18,
+    HEAP_TYPE_STRUCT = -0x19,
+    HEAP_TYPE_ARRAY = -0x1A,
+    HEAP_TYPE_NONE = -0x1B
+} wasm_heap_type_enum;
+
+struct WASMObject;
+typedef struct WASMObject *wasm_obj_t;
+
+#ifndef WASM_VALUE_DEFINED
+#define WASM_VALUE_DEFINED
+typedef union V128 {
+    int8_t i8x16[16];
+    int16_t i16x8[8];
+    int32_t i32x8[4];
+    int64_t i64x2[2];
+    float f32x4[4];
+    double f64x2[2];
+} V128;
+
+typedef union WASMValue {
+    int32_t i32;
+    uint32_t u32;
+    uint32_t global_index;
+    uint32_t ref_index;
+    int64_t i64;
+    uint64_t u64;
+    float f32;
+    double f64;
+    V128 v128;
+    wasm_obj_t *gc_obj;
+    uint32_t type_index;
+    struct {
+        uint32_t type_index;
+        uint32_t N;
+    } array_new_canon_fixed;
+} WASMValue;
+#endif /* end of WASM_VALUE_DEFINED */
+
+typedef union WASMValue wasm_value_t;
+
+/* Reference type, the layout is same as WasmRefType in wasm.h */
+typedef struct wasm_ref_type_t {
+    wasm_value_type_t value_type;
+    bool nullable;
+    int32_t heap_type;
+} wasm_ref_type_t;
+
+/**
+ * Local object reference that can be traced when GC occurs. All
+ * native functions that need to hold WASM objects which may not be
+ * referenced from other elements of GC root set may be hold with
+ * this type of variable so that they can be traced when GC occurs.
+ * Before using such a variable, it must be pushed onto the stack
+ * (implemented as a chain) of such variables, and before leaving the
+ * frame of the variables, they must be popped from the stack.
+ */
+typedef struct WASMLocalObjectRef {
+    /* Previous local object reference variable on the stack */
+    struct WASMLocalObjectRef *prev;
+    /* The reference of WASM object hold by this variable */
+    wasm_obj_t val;
+} WASMLocalObjectRef, wasm_local_obj_ref_t;
+
+struct WASMType;
+struct WASMFuncType;
+struct WASMStructType;
+struct WASMArrayType;
+
+typedef struct WASMType *wasm_defined_type_t;
+typedef struct WASMFuncType *wasm_func_type_t;
+typedef struct WASMStructType *wasm_struct_type_t;
+typedef struct WASMArrayType *wasm_array_type_t;
+
+struct WASMExternrefObject;
+struct WASMAnyrefObject;
+struct WASMStructObject;
+struct WASMArrayObject;
+struct WASMFuncObject;
+
+typedef struct WASMExternrefObject *wasm_externref_obj_t;
+typedef struct WASMAnyrefObject *wasm_anyref_obj_t;
+typedef struct WASMStructObject *wasm_struct_obj_t;
+typedef struct WASMArrayObject *wasm_array_obj_t;
+typedef struct WASMFuncObject *wasm_func_obj_t;
+typedef uintptr_t wasm_i31_obj_t;
+
+/* Defined type related operations */
+
+/**
+ * Get the defined type count of a WASM module
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_get_defined_type_count(const wasm_module_t module);
+
+/**
+ * Get the specified defined type of a WASM module
+ */
+WASM_RUNTIME_API_EXTERN wasm_defined_type_t
+wasm_get_defined_type(const wasm_module_t module, uint32_t index);
+
+/**
+ * Check whether a defined type is a function type
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_defined_type_is_func_type(const wasm_defined_type_t def_type);
+
+/**
+ * Check whether a defined type is a struct type
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_defined_type_is_struct_type(const wasm_defined_type_t def_type);
+
+/**
+ * Check whether a defined type is an array type
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_defined_type_is_array_type(const wasm_defined_type_t def_type);
+
+/**
+ * Get parameter count of a function type
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_func_type_get_param_count(const wasm_func_type_t func_type);
+
+/**
+ * Get type of a specified parameter of a function type
+ */
+WASM_RUNTIME_API_EXTERN wasm_ref_type_t
+wasm_func_type_get_param_type(const wasm_func_type_t func_type,
+                              uint32_t param_idx);
+
+/**
+ * Get result count of a function type
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_func_type_get_result_count(const wasm_func_type_t func_type);
+
+/**
+ * Get type of a specified result of a function type
+ */
+WASM_RUNTIME_API_EXTERN wasm_ref_type_t
+wasm_func_type_get_result_type(const wasm_func_type_t func_type,
+                               uint32_t result_idx);
+
+/**
+ * Get field count of a struct type
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_struct_type_get_field_count(const wasm_struct_type_t struct_type);
+
+/**
+ * Get type of a specified field of a struct type
+ */
+WASM_RUNTIME_API_EXTERN wasm_ref_type_t
+wasm_struct_type_get_field_type(const wasm_struct_type_t struct_type,
+                                uint32_t field_idx, bool *p_is_mutable);
+
+/**
+ * Get element type of an array type
+ */
+WASM_RUNTIME_API_EXTERN wasm_ref_type_t
+wasm_array_type_get_elem_type(const wasm_array_type_t array_type,
+                              bool *p_is_mutable);
+
+/**
+ * Check whether two defined types are equal
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_defined_type_equal(const wasm_defined_type_t def_type1,
+                        const wasm_defined_type_t def_type2,
+                        const wasm_module_t module);
+
+/**
+ * Check whether def_type1 is subtype of def_type2
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_defined_type_is_subtype_of(const wasm_defined_type_t def_type1,
+                                const wasm_defined_type_t def_type2,
+                                const wasm_module_t module);
+
+/* ref type related operations */
+
+/**
+ * Set the ref_type to be (ref null? type_idx)
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_ref_type_set_type_idx(wasm_ref_type_t *ref_type, bool nullable,
+                           int32_t type_idx);
+
+/**
+ * Set the ref_type to be (ref null? func/extern/any/eq/i31/struct/array/..)
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_ref_type_set_heap_type(wasm_ref_type_t *ref_type, bool nullable,
+                            int32_t heap_type);
+
+/**
+ * Check whether two ref types are equal
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_ref_type_equal(const wasm_ref_type_t *ref_type1,
+                    const wasm_ref_type_t *ref_type2,
+                    const wasm_module_t module);
+
+/**
+ * Check whether ref_type1 is subtype of ref_type2
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_ref_type_is_subtype_of(const wasm_ref_type_t *ref_type1,
+                            const wasm_ref_type_t *ref_type2,
+                            const wasm_module_t module);
+
+/* wasm object related operations */
+
+/**
+ * Create a struct object with the index of defined type
+ */
+WASM_RUNTIME_API_EXTERN wasm_struct_obj_t
+wasm_struct_obj_new_with_typeidx(wasm_exec_env_t exec_env, uint32_t type_idx);
+
+/**
+ * Create a struct object with the struct type
+ */
+WASM_RUNTIME_API_EXTERN wasm_struct_obj_t
+wasm_struct_obj_new_with_type(wasm_exec_env_t exec_env,
+                              const wasm_struct_type_t type);
+
+/**
+ * Set the field value of a struct object
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_struct_obj_set_field(wasm_struct_obj_t obj, uint32_t field_idx,
+                          const wasm_value_t *value);
+
+/**
+ * Get the field value of a struct object
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_struct_obj_get_field(const wasm_struct_obj_t obj, uint32_t field_idx,
+                          bool sign_extend, wasm_value_t *value);
+
+/**
+ * Create an array object with the index of defined type
+ */
+WASM_RUNTIME_API_EXTERN wasm_array_obj_t
+wasm_array_obj_new_with_typeidx(wasm_exec_env_t exec_env, uint32_t type_idx);
+
+/**
+ * Create an array object with the array type
+ */
+WASM_RUNTIME_API_EXTERN wasm_array_obj_t
+wasm_array_obj_new_with_type(wasm_exec_env_t exec_env,
+                             const wasm_array_type_t type);
+
+/**
+ * Set the specified element's value of an array object
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_array_obj_set_elem(wasm_array_obj_t array_obj, uint32_t elem_idx,
+                        const wasm_value_t *value);
+
+/**
+ * Get the specified element's value of an array object
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_array_obj_get_elem(const wasm_array_obj_t array_obj, uint32_t elem_idx,
+                        bool sign_extend, wasm_value_t *value);
+
+/**
+ * Copy elements from one array to another
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_array_obj_copy(wasm_array_obj_t dst_obj, uint32_t dst_idx,
+                    const wasm_array_obj_t src_obj, uint32_t src_idx,
+                    uint32_t len);
+
+/**
+ * Return the length of an array object
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_array_obj_length(const wasm_array_obj_t array_obj);
+
+/**
+ * Get the address of the first element of an array object
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_array_obj_first_elem_addr(const wasm_array_obj_t array_obj);
+
+/**
+ * Get the address of the i-th element of an array object
+ */
+WASM_RUNTIME_API_EXTERN void *
+wasm_array_obj_elem_addr(const wasm_array_obj_t array_obj, uint32_t elem_idx);
+
+/**
+ * Create a function object with the index of defined type
+ */
+WASM_RUNTIME_API_EXTERN wasm_func_obj_t
+wasm_func_obj_new_with_typeidx(wasm_exec_env_t exec_env, uint32_t type_idx);
+
+/**
+ * Create a function object with the function type
+ */
+WASM_RUNTIME_API_EXTERN wasm_func_obj_t
+wasm_func_obj_new_with_type(wasm_exec_env_t exec_env, wasm_func_type_t type);
+
+/**
+ * Get the function index bound of a function object
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_func_obj_get_func_idx_bound(const wasm_func_obj_t func_obj);
+
+/**
+ * Get the function type of a function object
+ */
+WASM_RUNTIME_API_EXTERN wasm_func_type_t
+wasm_func_obj_get_func_type(const wasm_func_obj_t func_obj);
+
+/**
+ * Create an externref object with host object
+ */
+WASM_RUNTIME_API_EXTERN wasm_externref_obj_t
+wasm_externref_obj_new(wasm_exec_env_t exec_env, const void *host_obj);
+
+/**
+ * Get the host value of an externref object
+ */
+WASM_RUNTIME_API_EXTERN const void *
+wasm_externref_obj_get_value(const wasm_externref_obj_t externref_obj);
+
+/**
+ * Create an anyref object with host object
+ */
+WASM_RUNTIME_API_EXTERN wasm_anyref_obj_t
+wasm_anyref_obj_new(wasm_exec_env_t exec_env, const void *host_obj);
+
+/**
+ * Get the host object value of an anyref object
+ */
+WASM_RUNTIME_API_EXTERN const void *
+wasm_anyref_obj_get_value(const wasm_anyref_obj_t anyref_obj);
+
+/**
+ * Get the internal object inside the externref object, same as
+ * the operation of opcode extern.internalize
+ */
+WASM_RUNTIME_API_EXTERN wasm_obj_t
+wasm_externref_obj_to_internal_obj(const wasm_externref_obj_t externref_obj);
+
+/**
+ * Create an externref object from an internal object, same as
+ * the operation of opcode extern.externalize
+ */
+WASM_RUNTIME_API_EXTERN wasm_externref_obj_t
+wasm_internal_obj_to_externref_obj(wasm_exec_env_t exec_env,
+                                   const wasm_obj_t internal_obj);
+
+/**
+ * Create an i31 object
+ */
+WASM_RUNTIME_API_EXTERN wasm_i31_obj_t
+wasm_i31_obj_new(uint32_t i31_value);
+
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_i31_obj_get_value(wasm_i31_obj_t i31_obj, bool sign_extend);
+
+/**
+ * Pin an object to make it traced during GC
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_pin_object(wasm_exec_env_t exec_env, wasm_obj_t obj);
+
+/**
+ * Unpin an object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_unpin_object(wasm_exec_env_t exec_env, wasm_obj_t obj);
+
+/**
+ * Check whether an object is a struct object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_struct_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is an array object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_array_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is a function object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_func_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is an i31 object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_i31_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is an externref object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_externref_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is an anyref object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_anyref_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is a struct object, or, an i31/struct/array object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_internal_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is an eq object
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_eq_obj(const wasm_obj_t obj);
+
+/**
+ * Check whether an object is an instance of a defined type
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_instance_of_defined_type(const wasm_obj_t obj,
+                                     const wasm_defined_type_t defined_type,
+                                     const wasm_module_t module);
+
+/**
+ * Check whether an object is an instance of a defined type with
+ * index type_idx
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_instance_of_type_idx(const wasm_obj_t obj, uint32_t type_idx,
+                                 const wasm_module_t module);
+
+/**
+ * Check whether an object is an instance of a ref type
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_obj_is_instance_of_ref_type(const wasm_obj_t obj,
+                                 const wasm_ref_type_t *ref_type);
+
+/**
+ * Push a local object ref into stack, note that we should set its value
+ * after pushing to retain it during GC, and should pop it from stack
+ * before returning from the current function
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_push_local_object_ref(wasm_exec_env_t exec_env,
+                                   wasm_local_obj_ref_t *local_obj_ref);
+
+/**
+ * Pop a local object ref from stack
+ */
+WASM_RUNTIME_API_EXTERN wasm_local_obj_ref_t *
+wasm_runtime_pop_local_object_ref(wasm_exec_env_t exec_env);
+
+/**
+ * Pop n local object refs from stack
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_pop_local_object_refs(wasm_exec_env_t exec_env, uint32_t n);
+
+#endif /* end of _GC_EXPORT_H */

+ 7 - 1
core/iwasm/interpreter/wasm.h

@@ -9,6 +9,9 @@
 #include "bh_platform.h"
 #include "bh_hashmap.h"
 #include "bh_assert.h"
+#if WASM_ENABLE_GC != 0
+#include "gc_export.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -152,6 +155,8 @@ typedef struct WASMModule WASMModule;
 typedef struct WASMFunction WASMFunction;
 typedef struct WASMGlobal WASMGlobal;
 
+#ifndef WASM_VALUE_DEFINED
+#define WASM_VALUE_DEFINED
 typedef union V128 {
     int8 i8x16[16];
     int16 i16x8[8];
@@ -172,7 +177,7 @@ typedef union WASMValue {
     float64 f64;
     V128 v128;
 #if WASM_ENABLE_GC != 0
-    void *gc_obj;
+    wasm_obj_t *gc_obj;
     uint32 type_index;
     struct {
         uint32 type_index;
@@ -180,6 +185,7 @@ typedef union WASMValue {
     } array_new_canon_fixed;
 #endif
 } WASMValue;
+#endif /* end of WASM_VALUE_DEFINED */
 
 typedef struct InitializerExpression {
     /* type of INIT_EXPR_TYPE_XXX, which is an instruction of

+ 6 - 9
core/iwasm/interpreter/wasm_interp_classic.c

@@ -2006,8 +2006,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
 
                         SYNC_ALL_TO_FRAME();
-                        struct_obj = wasm_struct_obj_new(
-                            module->e->gc_heap_handle, rtt_type);
+                        struct_obj = wasm_struct_obj_new(exec_env, rtt_type);
                         if (!struct_obj) {
                             wasm_set_exception(module,
                                                "create struct object failed");
@@ -2177,9 +2176,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
 
                         SYNC_ALL_TO_FRAME();
-                        array_obj = wasm_array_obj_new(
-                            module->e->gc_heap_handle, rtt_type, array_len,
-                            &array_elem);
+                        array_obj = wasm_array_obj_new(exec_env, rtt_type,
+                                                       array_len, &array_elem);
                         if (!array_obj) {
                             wasm_set_exception(module,
                                                "create array object failed");
@@ -2273,9 +2271,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
 
                         SYNC_ALL_TO_FRAME();
-                        array_obj = wasm_array_obj_new(
-                            module->e->gc_heap_handle, rtt_type, array_len,
-                            &array_elem);
+                        array_obj = wasm_array_obj_new(exec_env, rtt_type,
+                                                       array_len, &array_elem);
                         if (!array_obj) {
                             wasm_set_exception(module,
                                                "create array object failed");
@@ -2583,7 +2580,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         else {
                             if (!(externref_obj =
                                       wasm_internal_obj_to_externref_obj(
-                                          module->e->gc_heap_handle, gc_obj))) {
+                                          exec_env, gc_obj))) {
                                 wasm_set_exception(
                                     module, "create externref object failed");
                                 goto got_exception;

+ 6 - 9
core/iwasm/interpreter/wasm_interp_fast.c

@@ -1839,8 +1839,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
 
                         SYNC_ALL_TO_FRAME();
-                        struct_obj = wasm_struct_obj_new(
-                            module->e->gc_heap_handle, rtt_type);
+                        struct_obj = wasm_struct_obj_new(exec_env, rtt_type);
                         if (!struct_obj) {
                             wasm_set_exception(module,
                                                "create struct object failed");
@@ -2010,9 +2009,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
 
                         SYNC_ALL_TO_FRAME();
-                        array_obj = wasm_array_obj_new(
-                            module->e->gc_heap_handle, rtt_type, array_len,
-                            &array_elem);
+                        array_obj = wasm_array_obj_new(exec_env, rtt_type,
+                                                       array_len, &array_elem);
                         if (!array_obj) {
                             wasm_set_exception(module,
                                                "create array object failed");
@@ -2106,9 +2104,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         }
 
                         SYNC_ALL_TO_FRAME();
-                        array_obj = wasm_array_obj_new(
-                            module->e->gc_heap_handle, rtt_type, array_len,
-                            &array_elem);
+                        array_obj = wasm_array_obj_new(exec_env, rtt_type,
+                                                       array_len, &array_elem);
                         if (!array_obj) {
                             wasm_set_exception(module,
                                                "create array object failed");
@@ -2426,7 +2423,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         else {
                             if (!(externref_obj =
                                       wasm_internal_obj_to_externref_obj(
-                                          module->e->gc_heap_handle, gc_obj))) {
+                                          exec_env, gc_obj))) {
                                 wasm_set_exception(
                                     module, "create externref object failed");
                                 goto got_exception;

+ 2 - 2
core/iwasm/interpreter/wasm_runtime.c

@@ -1554,8 +1554,8 @@ wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx,
         return NULL;
     }
 
-    if (!(func_obj = wasm_func_obj_new(module_inst->e->gc_heap_handle, rtt_type,
-                                       func_idx))) {
+    if (!(func_obj = wasm_func_obj_new_internal(module_inst->e->gc_heap_handle,
+                                                rtt_type, func_idx))) {
         set_error_buf(error_buf, error_buf_size, "create func object failed");
         return NULL;
     }