mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-27 03:11:18 +00:00 
			
		
		
		
	 c0e33f08b0
			
		
	
	
		c0e33f08b0
		
			
		
	
	
	
	
		
			
			Export API: ```C wasm_func_type_get_param_count wasm_func_type_get_param_valkind wasm_func_type_get_result_count wasm_func_type_get_result_valkind ``` And change wasm_import_type/wasm_export_type to wasm_import_t/wasm_export_t.
		
			
				
	
	
		
			995 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			995 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2019 Intel Corporation.  All rights reserved.
 | |
|  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
|  */
 | |
| 
 | |
| #include "../wasm_runtime_common.h"
 | |
| #include "gc_export.h"
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
| #include "../interpreter/wasm_runtime.h"
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
| #include "../aot/aot_runtime.h"
 | |
| #endif
 | |
| 
 | |
| static bool
 | |
| wasm_ref_type_normalize(wasm_ref_type_t *ref_type)
 | |
| {
 | |
|     wasm_value_type_t value_type = ref_type->value_type;
 | |
|     int32 heap_type = ref_type->heap_type;
 | |
| 
 | |
|     if (!((value_type >= VALUE_TYPE_I16 && value_type <= VALUE_TYPE_I32)
 | |
|           || ((value_type >= (uint8)REF_TYPE_ARRAYREF
 | |
|                && value_type <= (uint8)REF_TYPE_NULLFUNCREF)
 | |
|               || (value_type >= (uint8)REF_TYPE_HT_NULLABLE
 | |
|                   && value_type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
 | |
| #if WASM_ENABLE_STRINGREF != 0
 | |
|               || (value_type >= (uint8)REF_TYPE_STRINGVIEWWTF8
 | |
|                   && value_type <= (uint8)REF_TYPE_STRINGREF)
 | |
|               || (value_type >= (uint8)REF_TYPE_STRINGVIEWITER
 | |
|                   && value_type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
 | |
| #endif
 | |
|                   ))) {
 | |
|         return false;
 | |
|     }
 | |
|     if (value_type == VALUE_TYPE_HT_NULLABLE_REF
 | |
|         || value_type == VALUE_TYPE_HT_NON_NULLABLE_REF) {
 | |
|         if (heap_type < 0 && !wasm_is_valid_heap_type(heap_type)) {
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (value_type != REF_TYPE_HT_NULLABLE) {
 | |
|         ref_type->nullable = false;
 | |
|     }
 | |
|     else {
 | |
|         if (wasm_is_valid_heap_type(heap_type)) {
 | |
|             ref_type->value_type =
 | |
| #if WASM_ENABLE_STRINGREF != 0
 | |
|                 (uint8)(REF_TYPE_STRINGVIEWITER + heap_type
 | |
|                         - HEAP_TYPE_STRINGVIEWITER);
 | |
| #else
 | |
|                 (uint8)(REF_TYPE_ARRAYREF + heap_type - HEAP_TYPE_ARRAY);
 | |
| #endif
 | |
|             ref_type->nullable = false;
 | |
|             ref_type->heap_type = 0;
 | |
|         }
 | |
|         else {
 | |
|             ref_type->nullable = true;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| uint32
 | |
| wasm_get_defined_type_count(WASMModuleCommon *const module)
 | |
| {
 | |
|     uint32 type_count = 0;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
|         type_count = wasm_module->type_count;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
|         type_count = aot_module->type_count;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return type_count;
 | |
| }
 | |
| 
 | |
| WASMType *
 | |
| wasm_get_defined_type(WASMModuleCommon *const module, uint32 index)
 | |
| {
 | |
|     WASMType *type = NULL;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         bh_assert(index < wasm_module->type_count);
 | |
|         type = wasm_module->types[index];
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         bh_assert(index < aot_module->type_count);
 | |
|         type = aot_module->types[index];
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return type;
 | |
| }
 | |
| 
 | |
| WASMType *
 | |
| wasm_obj_get_defined_type(const WASMObjectRef obj)
 | |
| {
 | |
|     if ((!wasm_obj_is_struct_obj(obj)) && (!wasm_obj_is_array_obj(obj))
 | |
|         && (!wasm_obj_is_func_obj(obj))) {
 | |
|         bh_assert(false);
 | |
|     }
 | |
| 
 | |
|     return ((WASMRttTypeRef)(obj->header))->defined_type;
 | |
| }
 | |
| 
 | |
| int32
 | |
| wasm_obj_get_defined_type_idx(WASMModuleCommon *const module,
 | |
|                               const WASMObjectRef obj)
 | |
| {
 | |
|     WASMType *type = wasm_obj_get_defined_type(obj);
 | |
|     uint32 i, type_idx = (uint32)-1;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
|         uint32 type_count = wasm_module->type_count;
 | |
| 
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (wasm_module->types[i] == type) {
 | |
|                 type_idx = i;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(type_idx < type_count);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
|         uint32 type_count = aot_module->type_count;
 | |
| 
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (aot_module->types[i] == type) {
 | |
|                 type_idx = i;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(type_idx < type_count);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return type_idx;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_defined_type_is_func_type(WASMType *const def_type)
 | |
| {
 | |
|     return wasm_type_is_func_type(def_type);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_defined_type_is_struct_type(WASMType *const def_type)
 | |
| {
 | |
|     return wasm_type_is_struct_type(def_type);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_defined_type_is_array_type(WASMType *const def_type)
 | |
| {
 | |
|     return wasm_type_is_array_type(def_type);
 | |
| }
 | |
| 
 | |
| wasm_ref_type_t
 | |
| wasm_func_type_get_param_type(WASMFuncType *const func_type, uint32 param_idx)
 | |
| {
 | |
|     wasm_ref_type_t ref_type = { 0 };
 | |
| 
 | |
|     bh_assert(param_idx < func_type->param_count);
 | |
| 
 | |
|     ref_type.value_type = func_type->types[param_idx];
 | |
| 
 | |
|     if (wasm_is_type_multi_byte_type(func_type->types[param_idx])) {
 | |
|         WASMRefType *param_ref_type = wasm_reftype_map_find(
 | |
|             func_type->ref_type_maps, func_type->ref_type_map_count, param_idx);
 | |
|         bh_assert(param_ref_type);
 | |
|         ref_type.nullable = param_ref_type->ref_ht_common.nullable;
 | |
|         ref_type.heap_type = param_ref_type->ref_ht_common.heap_type;
 | |
|     }
 | |
| 
 | |
|     return ref_type;
 | |
| }
 | |
| 
 | |
| wasm_ref_type_t
 | |
| wasm_func_type_get_result_type(WASMFuncType *const func_type, uint32 result_idx)
 | |
| {
 | |
|     wasm_ref_type_t ref_type = { 0 };
 | |
|     uint32 result_idx_with_param;
 | |
| 
 | |
|     result_idx_with_param = func_type->param_count + result_idx;
 | |
|     bh_assert(result_idx < func_type->result_count);
 | |
| 
 | |
|     ref_type.value_type = func_type->types[result_idx_with_param];
 | |
| 
 | |
|     if (wasm_is_type_multi_byte_type(func_type->types[result_idx_with_param])) {
 | |
|         WASMRefType *result_ref_type = wasm_reftype_map_find(
 | |
|             func_type->ref_type_maps, func_type->ref_type_map_count,
 | |
|             result_idx_with_param);
 | |
|         bh_assert(result_ref_type);
 | |
|         ref_type.nullable = result_ref_type->ref_ht_common.nullable;
 | |
|         ref_type.heap_type = result_ref_type->ref_ht_common.heap_type;
 | |
|     }
 | |
| 
 | |
|     return ref_type;
 | |
| }
 | |
| 
 | |
| uint32
 | |
| wasm_struct_type_get_field_count(WASMStructType *const struct_type)
 | |
| {
 | |
|     bh_assert(struct_type->base_type.type_flag == WASM_TYPE_STRUCT);
 | |
|     return struct_type->field_count;
 | |
| }
 | |
| 
 | |
| 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 };
 | |
|     WASMStructFieldType field;
 | |
| 
 | |
|     bh_assert(struct_type->base_type.type_flag == WASM_TYPE_STRUCT);
 | |
|     bh_assert(field_idx < struct_type->field_count);
 | |
| 
 | |
|     field = struct_type->fields[field_idx];
 | |
|     ref_type.value_type = field.field_type;
 | |
| 
 | |
|     if (wasm_is_type_multi_byte_type(field.field_type)) {
 | |
|         WASMRefType *field_ref_type =
 | |
|             wasm_reftype_map_find(struct_type->ref_type_maps,
 | |
|                                   struct_type->ref_type_map_count, field_idx);
 | |
|         bh_assert(field_ref_type);
 | |
|         ref_type.nullable = field_ref_type->ref_ht_common.nullable;
 | |
|         ref_type.heap_type = field_ref_type->ref_ht_common.heap_type;
 | |
|     }
 | |
| 
 | |
|     if (p_is_mutable) {
 | |
|         *p_is_mutable = field.field_flags & 1;
 | |
|     }
 | |
| 
 | |
|     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 };
 | |
| 
 | |
|     ref_type.value_type = array_type->elem_type;
 | |
| 
 | |
|     if (wasm_is_type_multi_byte_type(array_type->elem_type)) {
 | |
|         WASMRefType *elem_ref_type = array_type->elem_ref_type;
 | |
|         ref_type.nullable = elem_ref_type->ref_ht_common.nullable;
 | |
|         ref_type.heap_type = elem_ref_type->ref_ht_common.heap_type;
 | |
|     }
 | |
| 
 | |
|     if (p_is_mutable) {
 | |
|         *p_is_mutable = array_type->elem_flags & 1;
 | |
|     }
 | |
| 
 | |
|     return ref_type;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_defined_type_equal(WASMType *const def_type1, WASMType *const def_type2,
 | |
|                         WASMModuleCommon *const module)
 | |
| {
 | |
|     WASMTypePtr *types = NULL;
 | |
|     uint32 type_count = 0;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         types = wasm_module->types;
 | |
|         type_count = wasm_module->type_count;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         types = aot_module->types;
 | |
|         type_count = aot_module->type_count;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     bh_assert(types);
 | |
| 
 | |
|     return wasm_type_equal(def_type1, def_type2, types, type_count);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_defined_type_is_subtype_of(WASMType *const def_type1,
 | |
|                                 WASMType *const def_type2,
 | |
|                                 WASMModuleCommon *const module)
 | |
| {
 | |
|     WASMTypePtr *types = NULL;
 | |
|     uint32 type_count = 0;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         types = wasm_module->types;
 | |
|         type_count = wasm_module->type_count;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         types = aot_module->types;
 | |
|         type_count = aot_module->type_count;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     bh_assert(types);
 | |
| 
 | |
|     return wasm_type_is_subtype_of(def_type1, def_type2, types, type_count);
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_ref_type_set_type_idx(wasm_ref_type_t *ref_type, bool nullable,
 | |
|                            int32 type_idx)
 | |
| {
 | |
|     bh_assert(type_idx >= 0);
 | |
|     ref_type->value_type =
 | |
|         nullable ? VALUE_TYPE_HT_NULLABLE_REF : VALUE_TYPE_HT_NON_NULLABLE_REF;
 | |
|     ref_type->nullable = nullable;
 | |
|     ref_type->heap_type = type_idx;
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_ref_type_set_heap_type(wasm_ref_type_t *ref_type, bool nullable,
 | |
|                             int32 heap_type)
 | |
| {
 | |
|     bool ret;
 | |
| 
 | |
|     bh_assert(heap_type <= HEAP_TYPE_FUNC && heap_type >= HEAP_TYPE_NONE);
 | |
|     ref_type->value_type =
 | |
|         nullable ? VALUE_TYPE_HT_NULLABLE_REF : VALUE_TYPE_HT_NON_NULLABLE_REF;
 | |
|     ref_type->nullable = nullable;
 | |
|     ref_type->heap_type = heap_type;
 | |
|     ret = wasm_ref_type_normalize(ref_type);
 | |
|     bh_assert(ret);
 | |
|     (void)ret;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_ref_type_equal(const wasm_ref_type_t *ref_type1,
 | |
|                     const wasm_ref_type_t *ref_type2,
 | |
|                     WASMModuleCommon *const module)
 | |
| {
 | |
|     wasm_ref_type_t ref_type1_norm = { 0 };
 | |
|     wasm_ref_type_t ref_type2_norm = { 0 };
 | |
|     uint32 type_count = 0;
 | |
|     WASMTypePtr *types = NULL;
 | |
|     uint8 type1;
 | |
|     uint8 type2;
 | |
| 
 | |
|     bh_memcpy_s(&ref_type1_norm, (uint32)sizeof(wasm_ref_type_t), ref_type1,
 | |
|                 (uint32)sizeof(wasm_ref_type_t));
 | |
|     bh_memcpy_s(&ref_type2_norm, (uint32)sizeof(wasm_ref_type_t), ref_type2,
 | |
|                 (uint32)sizeof(wasm_ref_type_t));
 | |
|     if (!wasm_ref_type_normalize(&ref_type1_norm)) {
 | |
|         return false;
 | |
|     }
 | |
|     if (!wasm_ref_type_normalize(&ref_type2_norm)) {
 | |
|         return false;
 | |
|     }
 | |
|     type1 = ref_type1_norm.value_type;
 | |
|     type2 = ref_type2_norm.value_type;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         types = ((WASMModule *)module)->types;
 | |
|         type_count = wasm_get_defined_type_count(module);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         types = ((AOTModule *)module)->types;
 | |
|         type_count = wasm_get_defined_type_count(module);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return wasm_reftype_equal(type1, (WASMRefType *)&ref_type1_norm, type2,
 | |
|                               (WASMRefType *)&ref_type2_norm, types,
 | |
|                               type_count);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_ref_type_is_subtype_of(const wasm_ref_type_t *ref_type1,
 | |
|                             const wasm_ref_type_t *ref_type2,
 | |
|                             WASMModuleCommon *const module)
 | |
| {
 | |
|     wasm_ref_type_t ref_type1_norm = { 0 };
 | |
|     wasm_ref_type_t ref_type2_norm = { 0 };
 | |
|     uint8 type1;
 | |
|     uint8 type2;
 | |
|     WASMTypePtr *types = NULL;
 | |
|     uint32 type_count = 0;
 | |
| 
 | |
|     bh_memcpy_s(&ref_type1_norm, (uint32)sizeof(wasm_ref_type_t), ref_type1,
 | |
|                 (uint32)sizeof(wasm_ref_type_t));
 | |
|     bh_memcpy_s(&ref_type2_norm, (uint32)sizeof(wasm_ref_type_t), ref_type2,
 | |
|                 (uint32)sizeof(wasm_ref_type_t));
 | |
|     if (!wasm_ref_type_normalize(&ref_type1_norm)) {
 | |
|         return false;
 | |
|     }
 | |
|     if (!wasm_ref_type_normalize(&ref_type2_norm)) {
 | |
|         return false;
 | |
|     }
 | |
|     type1 = ref_type1_norm.value_type;
 | |
|     type2 = ref_type2_norm.value_type;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         types = ((WASMModule *)module)->types;
 | |
|         type_count = wasm_get_defined_type_count(module);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         types = ((AOTModule *)module)->types;
 | |
|         type_count = wasm_get_defined_type_count(module);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     bh_assert(types);
 | |
| 
 | |
|     return wasm_reftype_is_subtype_of(type1, (WASMRefType *)&ref_type1_norm,
 | |
|                                       type2, (WASMRefType *)&ref_type2_norm,
 | |
|                                       types, type_count);
 | |
| }
 | |
| 
 | |
| WASMStructObjectRef
 | |
| wasm_struct_obj_new_with_typeidx(WASMExecEnv *exec_env, uint32 type_idx)
 | |
| {
 | |
|     WASMStructObjectRef struct_obj;
 | |
|     WASMModuleInstanceCommon *module_inst =
 | |
|         wasm_runtime_get_module_inst(exec_env);
 | |
|     WASMType *type = NULL;
 | |
|     WASMRttTypeRef rtt_type = NULL;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module_inst->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
 | |
| 
 | |
|         bh_assert(type_idx < module->type_count);
 | |
|         type = module->types[type_idx];
 | |
|         bh_assert(wasm_defined_type_is_struct_type(type));
 | |
|         rtt_type =
 | |
|             wasm_rtt_type_new(type, type_idx, module->rtt_types,
 | |
|                               module->type_count, &module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module_inst->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *module =
 | |
|             (AOTModule *)((AOTModuleInstance *)module_inst)->module;
 | |
| 
 | |
|         bh_assert(type_idx < module->type_count);
 | |
|         type = module->types[type_idx];
 | |
|         bh_assert(wasm_defined_type_is_struct_type(type));
 | |
|         rtt_type =
 | |
|             wasm_rtt_type_new(type, type_idx, module->rtt_types,
 | |
|                               module->type_count, &module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     if (!rtt_type) {
 | |
|         return NULL;
 | |
|     }
 | |
|     struct_obj = wasm_struct_obj_new(exec_env, rtt_type);
 | |
| 
 | |
|     return struct_obj;
 | |
| }
 | |
| 
 | |
| WASMStructObjectRef
 | |
| wasm_struct_obj_new_with_type(WASMExecEnv *exec_env, WASMStructType *type)
 | |
| {
 | |
|     WASMStructObjectRef struct_obj;
 | |
|     WASMModuleInstanceCommon *module_inst =
 | |
|         wasm_runtime_get_module_inst(exec_env);
 | |
|     WASMRttTypeRef rtt_type = NULL;
 | |
|     uint32 i = 0;
 | |
|     uint32 type_count = 0;
 | |
| 
 | |
|     bh_assert(type->base_type.type_flag == WASM_TYPE_STRUCT);
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module_inst->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
 | |
| 
 | |
|         type_count = module->type_count;
 | |
| 
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (module->types[i] == (WASMType *)type) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(i < type_count);
 | |
|         rtt_type =
 | |
|             wasm_rtt_type_new((WASMType *)type, i, module->rtt_types,
 | |
|                               module->type_count, &module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module_inst->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *module =
 | |
|             (AOTModule *)((AOTModuleInstance *)module_inst)->module;
 | |
| 
 | |
|         type_count = module->type_count;
 | |
| 
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (module->types[i] == (AOTType *)type) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(i < type_count);
 | |
|         rtt_type =
 | |
|             wasm_rtt_type_new((AOTType *)type, i, module->rtt_types,
 | |
|                               module->type_count, &module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     if (!rtt_type) {
 | |
|         return NULL;
 | |
|     }
 | |
|     struct_obj = wasm_struct_obj_new(exec_env, rtt_type);
 | |
| 
 | |
|     return struct_obj;
 | |
| }
 | |
| 
 | |
| WASMArrayObjectRef
 | |
| wasm_array_obj_new_with_typeidx(WASMExecEnv *exec_env, uint32 type_idx,
 | |
|                                 uint32 length, wasm_value_t *init_value)
 | |
| {
 | |
|     WASMArrayObjectRef array_obj;
 | |
|     WASMModuleCommon *module = wasm_exec_env_get_module(exec_env);
 | |
|     WASMType *defined_type = wasm_get_defined_type(module, type_idx);
 | |
|     WASMRttTypeRef rtt_type = NULL;
 | |
| 
 | |
|     bh_assert(wasm_defined_type_is_array_type(defined_type));
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         rtt_type = wasm_rtt_type_new(
 | |
|             defined_type, type_idx, wasm_module->rtt_types,
 | |
|             wasm_module->type_count, &wasm_module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         rtt_type = wasm_rtt_type_new(
 | |
|             defined_type, type_idx, aot_module->rtt_types,
 | |
|             aot_module->type_count, &aot_module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     if (!rtt_type) {
 | |
|         return NULL;
 | |
|     }
 | |
|     array_obj = wasm_array_obj_new(exec_env, rtt_type, length, init_value);
 | |
| 
 | |
|     return array_obj;
 | |
| }
 | |
| 
 | |
| WASMArrayObjectRef
 | |
| wasm_array_obj_new_with_type(WASMExecEnv *exec_env, WASMArrayType *type,
 | |
|                              uint32 length, wasm_value_t *init_value)
 | |
| {
 | |
|     WASMArrayObjectRef array_obj;
 | |
|     uint32 i, type_count, type_idx = 0;
 | |
|     WASMModuleCommon *module = wasm_exec_env_get_module(exec_env);
 | |
| 
 | |
|     bh_assert(type->base_type.type_flag == WASM_TYPE_ARRAY);
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         type_count = wasm_module->type_count;
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (wasm_module->types[i] == (WASMType *)type) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(i < wasm_module->type_count);
 | |
| 
 | |
|         type_idx = i;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         type_count = aot_module->type_count;
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (aot_module->types[i] == (AOTType *)type) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(i < aot_module->type_count);
 | |
| 
 | |
|         type_idx = i;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     array_obj =
 | |
|         wasm_array_obj_new_with_typeidx(exec_env, type_idx, length, init_value);
 | |
| 
 | |
|     return array_obj;
 | |
| }
 | |
| 
 | |
| WASMFuncObjectRef
 | |
| wasm_func_obj_new_with_typeidx(WASMExecEnv *exec_env, uint32 type_idx,
 | |
|                                uint32 func_idx_bound)
 | |
| {
 | |
|     WASMFuncObjectRef func_obj;
 | |
|     WASMRttTypeRef rtt_type = NULL;
 | |
|     WASMModuleCommon *module = wasm_exec_env_get_module(exec_env);
 | |
|     WASMType *defined_type = wasm_get_defined_type(module, type_idx);
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         rtt_type = wasm_rtt_type_new(
 | |
|             defined_type, type_idx, wasm_module->rtt_types,
 | |
|             wasm_module->type_count, &wasm_module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         rtt_type = wasm_rtt_type_new(
 | |
|             defined_type, type_idx, aot_module->rtt_types,
 | |
|             aot_module->type_count, &aot_module->rtt_type_lock);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     if (!rtt_type) {
 | |
|         return NULL;
 | |
|     }
 | |
|     func_obj = wasm_func_obj_new(exec_env, rtt_type, func_idx_bound);
 | |
| 
 | |
|     return func_obj;
 | |
| }
 | |
| 
 | |
| WASMFuncObjectRef
 | |
| wasm_func_obj_new_with_type(WASMExecEnv *exec_env, WASMFuncType *type,
 | |
|                             uint32 func_idx_bound)
 | |
| {
 | |
|     WASMFuncObjectRef func_obj;
 | |
|     uint32 i, type_count, type_idx = 0;
 | |
|     WASMModuleCommon *module = wasm_exec_env_get_module(exec_env);
 | |
| 
 | |
|     bh_assert(type->base_type.type_flag == WASM_TYPE_FUNC);
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         type_count = wasm_module->type_count;
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (wasm_module->types[i] == (WASMType *)type) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(i < wasm_module->type_count);
 | |
| 
 | |
|         type_idx = i;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         type_count = aot_module->type_count;
 | |
|         for (i = 0; i < type_count; i++) {
 | |
|             if (aot_module->types[i] == (AOTType *)type) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         bh_assert(i < aot_module->type_count);
 | |
| 
 | |
|         type_idx = i;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     func_obj =
 | |
|         wasm_func_obj_new_with_typeidx(exec_env, type_idx, func_idx_bound);
 | |
| 
 | |
|     return func_obj;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_runtime_call_func_ref(WASMExecEnv *exec_env,
 | |
|                            const WASMFuncObjectRef func_obj, uint32 argc,
 | |
|                            uint32 argv[])
 | |
| {
 | |
|     WASMFunctionInstanceCommon *func_inst = NULL;
 | |
|     uint32 func_idx = wasm_func_obj_get_func_idx_bound(func_obj);
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     AOTFunctionInstance aot_func_inst = { 0 };
 | |
| #endif
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMFunctionInstance *wasm_func_inst;
 | |
|         WASMModuleInstance *module_inst =
 | |
|             (WASMModuleInstance *)exec_env->module_inst;
 | |
| 
 | |
|         bh_assert(func_idx < module_inst->module->import_function_count
 | |
|                                  + module_inst->module->function_count);
 | |
|         wasm_func_inst = module_inst->e->functions + func_idx;
 | |
|         func_inst = (WASMFunctionInstanceCommon *)wasm_func_inst;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (exec_env->module_inst->module_type == Wasm_Module_AoT) {
 | |
|         uint32 func_type_idx;
 | |
|         AOTModuleInstance *module_inst =
 | |
|             (AOTModuleInstance *)exec_env->module_inst;
 | |
|         AOTModule *module = (AOTModule *)module_inst->module;
 | |
|         (void)module_inst;
 | |
| 
 | |
|         bh_assert(func_idx < module->import_func_count + module->func_count);
 | |
| 
 | |
|         aot_func_inst.func_name = "";
 | |
|         aot_func_inst.func_index = func_idx;
 | |
|         aot_func_inst.is_import_func = false;
 | |
|         func_type_idx =
 | |
|             module->func_type_indexes[func_idx - module->import_func_count];
 | |
|         aot_func_inst.u.func.func_type =
 | |
|             (AOTFuncType *)module->types[func_type_idx];
 | |
|         aot_func_inst.u.func.func_ptr =
 | |
|             module->func_ptrs[func_idx - module->import_func_count];
 | |
| 
 | |
|         func_inst = (WASMFunctionInstanceCommon *)(&aot_func_inst);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     bh_assert(func_inst);
 | |
|     return wasm_runtime_call_wasm(exec_env, func_inst, argc, argv);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_runtime_call_func_ref_a(WASMExecEnv *exec_env,
 | |
|                              const WASMFuncObjectRef func_obj,
 | |
|                              uint32 num_results, wasm_val_t results[],
 | |
|                              uint32 num_args, wasm_val_t *args)
 | |
| {
 | |
|     /* TODO */
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_runtime_call_func_ref_v(wasm_exec_env_t exec_env,
 | |
|                              const WASMFuncObjectRef func_obj,
 | |
|                              uint32 num_results, wasm_val_t results[],
 | |
|                              uint32 num_args, ...)
 | |
| {
 | |
|     /* TODO */
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_obj_is_instance_of_defined_type(WASMObjectRef obj, WASMType *defined_type,
 | |
|                                      WASMModuleCommon *const module)
 | |
| {
 | |
|     WASMType **types = NULL;
 | |
|     uint32 type_count = 0;
 | |
|     uint32 type_idx = 0;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         type_count = wasm_module->type_count;
 | |
|         types = wasm_module->types;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         type_count = aot_module->type_count;
 | |
|         types = (WASMType **)aot_module->types;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     for (type_idx = 0; type_idx < type_count; type_idx++) {
 | |
|         if (types[type_idx] == defined_type) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     bh_assert(type_idx < type_count);
 | |
| 
 | |
|     return wasm_obj_is_instance_of(obj, type_idx, types, type_count);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_obj_is_instance_of_type_idx(WASMObjectRef obj, uint32 type_idx,
 | |
|                                  WASMModuleCommon *const module)
 | |
| {
 | |
|     WASMType **types = NULL;
 | |
|     uint32 type_count = 0;
 | |
| 
 | |
| #if WASM_ENABLE_INTERP != 0
 | |
|     if (module->module_type == Wasm_Module_Bytecode) {
 | |
|         WASMModule *wasm_module = (WASMModule *)module;
 | |
| 
 | |
|         types = wasm_module->types;
 | |
|     }
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module->module_type == Wasm_Module_AoT) {
 | |
|         AOTModule *aot_module = (AOTModule *)module;
 | |
| 
 | |
|         types = (WASMType **)aot_module->types;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     bh_assert(types);
 | |
| 
 | |
|     return wasm_obj_is_instance_of(obj, type_idx, types, type_count);
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_obj_is_instance_of_ref_type(const WASMObjectRef obj,
 | |
|                                  const wasm_ref_type_t *ref_type)
 | |
| {
 | |
|     int32 heap_type = ref_type->heap_type;
 | |
|     return wasm_obj_is_type_of(obj, heap_type);
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_runtime_push_local_obj_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_obj_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_obj_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);
 | |
| }
 | |
| 
 | |
| WASMLocalObjectRef *
 | |
| wasm_runtime_get_cur_local_obj_ref(WASMExecEnv *exec_env)
 | |
| {
 | |
|     WASMLocalObjectRef *local_ref = exec_env->cur_local_object_ref;
 | |
| 
 | |
|     bh_assert(local_ref);
 | |
|     return local_ref;
 | |
| }
 | |
| 
 | |
| 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) {
 | |
|         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->common.gc_heap_handle =
 | |
|             gc_heap_handle;
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module_inst->module_type == Wasm_Module_AoT) {
 | |
|         AOTModuleInstanceExtra *e =
 | |
|             (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
 | |
|         e->common.gc_heap_handle = 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->common.gc_heap_handle;
 | |
| #endif
 | |
| #if WASM_ENABLE_AOT != 0
 | |
|     if (module_inst->module_type == Wasm_Module_AoT) {
 | |
|         AOTModuleInstanceExtra *e =
 | |
|             (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
 | |
|         return e->common.gc_heap_handle;
 | |
|     }
 | |
| #endif
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| bool
 | |
| wasm_runtime_get_wasm_object_extra_info_flag(WASMObjectRef obj)
 | |
| {
 | |
|     return obj->header & WASM_OBJ_EXTRA_INFO_FLAG;
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_runtime_set_wasm_object_extra_info_flag(WASMObjectRef obj, bool set)
 | |
| {
 | |
|     if (set) {
 | |
|         obj->header |= WASM_OBJ_EXTRA_INFO_FLAG;
 | |
|     }
 | |
|     else {
 | |
|         obj->header &= ~WASM_OBJ_EXTRA_INFO_FLAG;
 | |
|     }
 | |
| }
 |