Implement GC (Garbage Collection) feature for interpreter, AOT and LLVM-JIT (#3125)

Implement the GC (Garbage Collection) feature for interpreter mode,
AOT mode and LLVM-JIT mode, and support most features of the latest
spec proposal, and also enable the stringref feature.

Use `cmake -DWAMR_BUILD_GC=1/0` to enable/disable the feature,
and `wamrc --enable-gc` to generate the AOT file with GC supported.

And update the AOT file version from 2 to 3 since there are many AOT
ABI breaks, including the changes of AOT file format, the changes of
AOT module/memory instance layouts, the AOT runtime APIs for the
AOT code to invoke and so on.
This commit is contained in:
Wenyong Huang
2024-02-06 20:47:11 +08:00
committed by GitHub
parent 5931aaacbe
commit 16a4d71b34
98 changed files with 33469 additions and 3159 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _GC_OBJECT_H_
#define _GC_OBJECT_H_
#include "gc_type.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Object header of a WASM object, as the adddress of allocated memory
* must be 8-byte aligned, the lowest 3 bits are zero, we use them to
* mark the object:
* bits[0] is 1: the object is an externref object
* bits[1] is 1: the object is an anyref object
* bits[2] is 1: the object has extra information
* if both bits[0] and bits[1] are 0, then this object header must
* be a pointer of a WASMRttType, denotes that the object is a
* struct object, or an array object, or a function object
*/
typedef uintptr_t WASMObjectHeader;
#define WASM_OBJ_HEADER_MASK (~((uintptr_t)7))
#define WASM_OBJ_EXTERNREF_OBJ_FLAG (((uintptr_t)1) << 0)
#define WASM_OBJ_ANYREF_OBJ_FLAG (((uintptr_t)1) << 1)
#define WASM_OBJ_EXTRA_INFO_FLAG (((uintptr_t)1) << 2)
/* Representation of WASM objects */
typedef struct WASMObject {
WASMObjectHeader header;
} WASMObject, *WASMObjectRef;
/* Representation of WASM rtt types */
typedef struct WASMRttType {
/* type_flag must be WASM_TYPE_FUNC/STRUCT/ARRAY to
denote an object of func, struct or array */
uint32 type_flag;
uint32 inherit_depth;
WASMType *defined_type;
WASMType *root_type;
} WASMRttType, *WASMRttTypeRef;
/* Representation of WASM externref objects */
typedef struct WASMExternrefObject {
/* bits[0] must be 1, denotes an externref object */
WASMObjectHeader header;
/* an object of WASMAnyrefObjectRef which encapsulates the external
object passed from host, or other internal objects passed to
opcode extern.externalize */
WASMObjectRef internal_obj;
} WASMExternrefObject, *WASMExternrefObjectRef;
/* Representation of WASM anyref objects which encapsulate the
external object passed from host */
typedef struct WASMAnyrefObject {
/* bits[1] must be 1, denotes an anyref object */
WASMObjectHeader header;
const void *host_obj;
} WASMAnyrefObject, *WASMAnyrefObjectRef;
/**
* Representation of WASM i31 objects, the lowest bit is 1:
* for a pointer of WASMObjectRef, if the lowest bit is 1, then it is an
* i31 object and bits[1..31] stores the actual i31 value, otherwise
* it is a normal object of rtt/externref/struct/array/func */
typedef uintptr_t WASMI31ObjectRef;
/* Representation of WASM struct objects */
typedef struct WASMStructObject {
/* Must be pointer of WASMRttObject of struct type */
WASMObjectHeader header;
uint8 field_data[1];
} WASMStructObject, *WASMStructObjectRef;
/* Representation of WASM array objects */
typedef struct WASMArrayObject {
/* Must be pointer of WASMRttObject of array type */
WASMObjectHeader header;
/* (<array length> << 2) | <array element size>,
* elem_count = lenght >> 2
* elem_size = 2 ^ (length & 0x3)
*/
uint32 length;
uint8 elem_data[1];
} WASMArrayObject, *WASMArrayObjectRef;
#define WASM_ARRAY_LENGTH_SHIFT 2
#define WASM_ARRAY_ELEM_SIZE_MASK 3
/* Representation of WASM function objects */
typedef struct WASMFuncObject {
/* must be pointer of WASMRttObject of func type */
WASMObjectHeader header;
uint32 func_idx_bound;
} WASMFuncObject, *WASMFuncObjectRef;
/* Representation of WASM stringref objects */
typedef struct WASMStringrefObject {
WASMObjectHeader header;
const void *str_obj;
} WASMStringrefObject, *WASMStringrefObjectRef;
typedef struct WASMStringviewWTF8Object {
WASMObjectHeader header;
const void *str_obj;
} WASMStringviewWTF8Object, *WASMStringviewWTF8ObjectRef;
typedef struct WASMStringviewWTF16Object {
WASMObjectHeader header;
const void *str_obj;
} WASMStringviewWTF16Object, *WASMStringviewWTF16ObjectRef;
typedef struct WASMStringviewIterObject {
WASMObjectHeader header;
const void *str_obj;
int32 pos;
} WASMStringviewIterObject, *WASMStringviewIterObjectRef;
struct WASMExecEnv;
inline static WASMObjectHeader
wasm_object_header(const WASMObjectRef obj)
{
return (obj->header & WASM_OBJ_HEADER_MASK);
}
WASMRttTypeRef
wasm_rtt_type_new(WASMType *defined_type, uint32 defined_type_idx,
WASMRttType **rtt_types, uint32 rtt_type_count,
korp_mutex *rtt_type_lock);
inline static WASMType *
wasm_rtt_type_get_defined_type(const WASMRttTypeRef rtt_type)
{
return rtt_type->defined_type;
}
WASMStructObjectRef
wasm_struct_obj_new_internal(void *heap_handle, WASMRttTypeRef rtt_type);
WASMStructObjectRef
wasm_struct_obj_new(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type);
void
wasm_struct_obj_set_field(WASMStructObjectRef struct_obj, uint32 field_idx,
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_internal(void *heap_handle, WASMRttTypeRef rtt_type,
uint32 length, WASMValue *init_value);
WASMArrayObjectRef
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,
const WASMValue *value);
void
wasm_array_obj_get_elem(const WASMArrayObjectRef array_obj, uint32 elem_idx,
bool sign_extend, WASMValue *value);
void
wasm_array_obj_fill(const WASMArrayObjectRef array_obj, uint32 elem_idx,
uint32 len, WASMValue *value);
void
wasm_array_obj_copy(WASMArrayObjectRef dst_obj, uint32 dst_idx,
WASMArrayObjectRef src_obj, uint32 src_idx, uint32 len);
/**
* Return the logarithm of the size of array element.
*
* @param array the WASM array object
*
* @return log(size of the array element)
*/
inline static uint32
wasm_array_obj_elem_size_log(const WASMArrayObjectRef array_obj)
{
return (array_obj->length & WASM_ARRAY_ELEM_SIZE_MASK);
}
/**
* Return the length of the array.
*
* @param array_obj the WASM array object
*
* @return the length of the array
*/
uint32
wasm_array_obj_length(const WASMArrayObjectRef array_obj);
/**
* Return the address of the first element of an array object.
*
* @param array_obj the WASM array object
*
* @return the address of the first element of the array object
*/
void *
wasm_array_obj_first_elem_addr(const WASMArrayObjectRef array_obj);
/**
* Return the address of the i-th element of an array object.
*
* @param array_obj the WASM array object
* @param index the index of the element
*
* @return the address of the i-th element of the array object
*/
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(struct WASMExecEnv *exec_env, WASMRttTypeRef rtt_type,
uint32 func_idx_bound);
uint32
wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj);
WASMFuncType *
wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj);
WASMExternrefObjectRef
wasm_externref_obj_new(struct WASMExecEnv *exec_env, const void *host_obj);
WASMAnyrefObjectRef
wasm_anyref_obj_new(struct WASMExecEnv *exec_env, const void *host_obj);
/* Implementation of opcode extern.internalize */
WASMObjectRef
wasm_externref_obj_to_internal_obj(const WASMExternrefObjectRef externref_obj);
/* Implementation of opcode extern.externalize */
WASMExternrefObjectRef
wasm_internal_obj_to_externref_obj(struct WASMExecEnv *exec_env,
const WASMObjectRef internal_obj);
const void *
wasm_anyref_obj_get_value(const WASMAnyrefObjectRef anyref_obj);
const void *
wasm_externref_obj_get_value(const WASMExternrefObjectRef externref_obj);
WASMI31ObjectRef
wasm_i31_obj_new(uint32 i31_value);
uint32
wasm_i31_obj_get_value(WASMI31ObjectRef i31_obj, bool sign_extend);
bool
wasm_obj_is_i31_obj(WASMObjectRef obj);
bool
wasm_obj_is_externref_obj(WASMObjectRef obj);
bool
wasm_obj_is_anyref_obj(WASMObjectRef obj);
bool
wasm_obj_is_i31_externref_or_anyref_obj(WASMObjectRef obj);
bool
wasm_obj_is_struct_obj(WASMObjectRef obj);
bool
wasm_obj_is_array_obj(WASMObjectRef obj);
bool
wasm_obj_is_func_obj(WASMObjectRef obj);
bool
wasm_obj_is_internal_obj(WASMObjectRef obj);
bool
wasm_obj_is_eq_obj(WASMObjectRef obj);
inline static bool
wasm_obj_is_null_obj(WASMObjectRef obj)
{
return obj == NULL_REF ? true : false;
}
inline static bool
wasm_obj_is_created_from_heap(WASMObjectRef obj)
{
if (obj == NULL || (((uintptr_t)obj) & 1))
/* null object or i31 object */
return false;
return true;
}
bool
wasm_obj_is_instance_of(WASMObjectRef obj, uint32 type_idx, WASMType **types,
uint32 type_count);
bool
wasm_obj_is_type_of(WASMObjectRef obj, int32 heap_type);
bool
wasm_obj_equal(WASMObjectRef obj1, WASMObjectRef obj2);
bool
wasm_object_get_ref_list(WASMObjectRef obj, bool *p_is_compact_mode,
uint32 *p_ref_num, uint16 **p_ref_list,
uint32 *p_ref_start_offset);
#if WASM_ENABLE_STRINGREF != 0
WASMStringrefObjectRef
wasm_stringref_obj_new(struct WASMExecEnv *exec_env, const void *str_obj);
WASMStringviewWTF8ObjectRef
wasm_stringview_wtf8_obj_new(struct WASMExecEnv *exec_env, const void *str_obj);
WASMStringviewWTF16ObjectRef
wasm_stringview_wtf16_obj_new(struct WASMExecEnv *exec_env,
const void *str_obj);
WASMStringviewIterObjectRef
wasm_stringview_iter_obj_new(struct WASMExecEnv *exec_env, const void *str_obj,
int32 pos);
const void *
wasm_stringref_obj_get_value(WASMStringrefObjectRef stringref_obj);
const void *
wasm_stringview_wtf8_obj_get_value(
WASMStringviewWTF8ObjectRef stringview_wtf8_obj);
const void *
wasm_stringview_wtf16_obj_get_value(
WASMStringviewWTF16ObjectRef stringview_wtf16_obj);
const void *
wasm_stringview_iter_obj_get_value(
WASMStringviewIterObjectRef stringview_iter_obj);
int32
wasm_stringview_iter_obj_get_pos(
WASMStringviewIterObjectRef stringview_iter_obj);
void
wasm_stringview_iter_obj_update_pos(
WASMStringviewIterObjectRef stringview_iter_obj, int32 pos);
bool
wasm_obj_is_stringref_obj(WASMObjectRef obj);
bool
wasm_obj_is_stringview_wtf8_obj(WASMObjectRef obj);
bool
wasm_obj_is_stringview_wtf16_obj(WASMObjectRef obj);
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* end of _GC_OBJECT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _GC_TYPE_H_
#define _GC_TYPE_H_
#include "../interpreter/wasm.h"
#ifdef __cplusplus
extern "C" {
#endif
void
wasm_dump_value_type(uint8 type, const WASMRefType *ref_type);
void
wasm_dump_func_type(const WASMFuncType *type);
void
wasm_dump_struct_type(const WASMStructType *type);
void
wasm_dump_array_type(const WASMArrayType *type);
/* Whether a group of value types is subtype of
another group of value types */
bool
wasm_value_types_is_subtype_of(const uint8 *types1,
const WASMRefTypeMap *ref_type_maps1,
const uint8 *types2,
const WASMRefTypeMap *ref_type_maps2,
uint32 value_type_count,
const WASMTypePtr *types, uint32 type_count);
/* Operations of function type */
/* Whether two function types are equal */
bool
wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether func type1 is subtype of func type2 */
bool
wasm_func_type_is_subtype_of(const WASMFuncType *type1,
const WASMFuncType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether func type1's result types are subtype of
func type2's result types */
bool
wasm_func_type_result_is_subtype_of(const WASMFuncType *type,
const WASMFuncType *type2,
const WASMTypePtr *types,
uint32 type_count);
/* Operations of struct type */
/* Whether two struct types are equal */
bool
wasm_struct_type_equal(const WASMStructType *type1, const WASMStructType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether struct type1 is subtype of struct type2 */
bool
wasm_struct_type_is_subtype_of(const WASMStructType *type1,
const WASMStructType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Operations of array type */
/* Whether two array types are equal */
bool
wasm_array_type_equal(const WASMArrayType *type1, const WASMArrayType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether array type1 is subtype of array type2 */
bool
wasm_array_type_is_subtype_of(const WASMArrayType *type1,
const WASMArrayType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Operations of wasm type */
/* Whether a wasm type is a function type */
inline static bool
wasm_type_is_func_type(const WASMType *type)
{
return type->type_flag == WASM_TYPE_FUNC ? true : false;
}
/* Whether a wasm type is a struct type */
inline static bool
wasm_type_is_struct_type(const WASMType *type)
{
return type->type_flag == WASM_TYPE_STRUCT ? true : false;
}
/* Whether a wasm type is an array type */
inline static bool
wasm_type_is_array_type(const WASMType *type)
{
return type->type_flag == WASM_TYPE_ARRAY ? true : false;
}
/* Whether two wasm types are equal */
bool
wasm_type_equal(const WASMType *type1, const WASMType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether wasm type1 is subtype of wasm type2 */
bool
wasm_type_is_subtype_of(const WASMType *type1, const WASMType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Operations of reference type */
/* Whether a value type is a reference type */
inline static bool
wasm_is_type_reftype(uint8 type)
{
return ((type >= (uint8)REF_TYPE_ARRAYREF
&& type <= (uint8)REF_TYPE_NULLFUNCREF)
|| (type >= (uint8)REF_TYPE_HT_NULLABLE
&& type <= (uint8)REF_TYPE_HT_NON_NULLABLE)
#if WASM_ENABLE_STRINGREF != 0
|| (type >= (uint8)REF_TYPE_STRINGVIEWWTF8
&& type <= (uint8)REF_TYPE_STRINGREF)
|| (type >= (uint8)REF_TYPE_STRINGVIEWITER
&& type <= (uint8)REF_TYPE_STRINGVIEWWTF16)
#endif
)
? true
: false;
}
/* Whether a negative value is a valid heap type */
inline static bool
wasm_is_valid_heap_type(int32 heap_type)
{
return ((heap_type <= HEAP_TYPE_NOFUNC && heap_type >= HEAP_TYPE_ARRAY)
#if WASM_ENABLE_STRINGREF != 0
|| heap_type == HEAP_TYPE_STRINGREF
|| heap_type == HEAP_TYPE_STRINGVIEWWTF8
|| heap_type == HEAP_TYPE_STRINGVIEWWTF16
|| heap_type == HEAP_TYPE_STRINGVIEWITER
#endif
)
? true
: false;
}
/* Whether a value type is multi-byte type, or, requires ref type map
to retrieve extra info */
inline static bool
wasm_is_type_multi_byte_type(uint8 type)
{
return (type == (uint8)REF_TYPE_HT_NULLABLE
|| type == (uint8)REF_TYPE_HT_NON_NULLABLE)
? true
: false;
}
/* Whether a reference type is a funcref type */
inline static bool
wasm_is_reftype_funcref(uint8 type)
{
return type == (uint8)REF_TYPE_FUNCREF ? true : false;
}
/* Whether a reference type is an externref type */
inline static bool
wasm_is_reftype_externref(uint8 type)
{
return type == (uint8)REF_TYPE_EXTERNREF ? true : false;
}
/* Whether a reference type is an anyref type */
inline static bool
wasm_is_reftype_anyref(uint8 type)
{
return type == (uint8)REF_TYPE_ANYREF ? true : false;
}
/* Whether a reference type is an eqref type */
inline static bool
wasm_is_reftype_eqref(uint8 type)
{
return type == (uint8)REF_TYPE_EQREF ? true : false;
}
/* Whether a reference type is a (ref null ht) type */
inline static bool
wasm_is_reftype_htref_nullable(uint8 type)
{
return type == (uint8)REF_TYPE_HT_NULLABLE ? true : false;
}
/* Whether a reference type is a (ref ht) type */
inline static bool
wasm_is_reftype_htref_non_nullable(uint8 type)
{
return type == (uint8)REF_TYPE_HT_NON_NULLABLE ? true : false;
}
/* Whether a reference type is an i31ref type */
inline static bool
wasm_is_reftype_i31ref(uint8 type)
{
return type == (uint8)REF_TYPE_I31REF ? true : false;
}
/* Whether a reference type is a structref type */
inline static bool
wasm_is_reftype_structref(uint8 type)
{
return type == (uint8)REF_TYPE_STRUCTREF ? true : false;
}
/* Whether a reference type is an arrayref type */
inline static bool
wasm_is_reftype_arrayref(uint8 type)
{
return type == (uint8)REF_TYPE_ARRAYREF ? true : false;
}
/* Whether a reference type is a nullref type */
inline static bool
wasm_is_reftype_nullref(uint8 type)
{
return type == (uint8)REF_TYPE_NULLREF ? true : false;
}
/* Whether a reference type is a nullfuncref type */
inline static bool
wasm_is_reftype_nullfuncref(uint8 type)
{
return type == (uint8)REF_TYPE_NULLFUNCREF ? true : false;
}
/* Whether a reference type is a nullexternref type */
inline static bool
wasm_is_reftype_nullexternref(uint8 type)
{
return type == (uint8)REF_TYPE_NULLEXTERNREF ? true : false;
}
/* Return the size of a reference type */
uint32
wasm_reftype_size(uint8 type);
/* Return the actual WASMRefType struct size required of a reference type */
uint32
wasm_reftype_struct_size(const WASMRefType *ref_type);
/* Operations of ref heap type */
/* Whether a ref heap type is (type i), i : typeidx, >= 0 */
inline static bool
wasm_is_refheaptype_typeidx(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type >= 0 ? true : false;
}
/* Whether a ref heap type is a common type: func/any/eq/i31/data,
not (type i) or (rtt n i) or (rtt i) */
inline static bool
wasm_is_refheaptype_common(const RefHeapType_Common *ref_heap_type)
{
return ((ref_heap_type->heap_type >= (int32)HEAP_TYPE_ARRAY
&& ref_heap_type->heap_type <= (int32)HEAP_TYPE_NONE)
#if WASM_ENABLE_STRINGREF != 0
|| (ref_heap_type->heap_type >= (int32)HEAP_TYPE_STRINGVIEWITER
&& ref_heap_type->heap_type <= (int32)HEAP_TYPE_I31)
#endif
)
? true
: false;
}
/* Whether a ref heap type is a func type */
inline static bool
wasm_is_refheaptype_func(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type == (int32)HEAP_TYPE_FUNC ? true : false;
}
/* Whether a ref heap type is an any type */
inline static bool
wasm_is_refheaptype_any(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type == (int32)HEAP_TYPE_ANY ? true : false;
}
/* Whether a ref heap type is an eq type */
inline static bool
wasm_is_refheaptype_eq(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type == (int32)HEAP_TYPE_EQ ? true : false;
}
/* Whether a ref heap type is an i31 type */
inline static bool
wasm_is_refheaptype_i31(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type == (int32)HEAP_TYPE_I31 ? true : false;
}
/* Whether a ref heap type is an array type */
inline static bool
wasm_is_refheaptype_array(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type == (int32)HEAP_TYPE_ARRAY ? true : false;
}
#if WASM_ENABLE_STRINGREF != 0
inline static bool
wasm_is_refheaptype_stringrefs(const RefHeapType_Common *ref_heap_type)
{
return ref_heap_type->heap_type <= (int32)HEAP_TYPE_STRINGREF
&& ref_heap_type->heap_type >= HEAP_TYPE_STRINGVIEWITER
? true
: false;
}
#endif
/* Whether two ref heap types are equal */
bool
wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
const RefHeapType_Common *ref_heap_type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether two ref types are equal */
bool
wasm_reftype_equal(uint8 type1, const WASMRefType *reftype1, uint8 type2,
const WASMRefType *reftype2, const WASMTypePtr *types,
uint32 type_count);
/* Whether ref type1 is subtype of ref type2 */
bool
wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *reftype1,
uint8 type2, const WASMRefType *reftype2,
const WASMTypePtr *types, uint32 type_count);
/* Returns a new reference type which is a duplication of ref_type,
the caller should use wasm_runtime_free() to free the new ref type */
WASMRefType *
wasm_reftype_dup(const WASMRefType *ref_type);
/* Set fields of RefHeapType_TypeIdx */
void
wasm_set_refheaptype_typeidx(RefHeapType_TypeIdx *ref_ht_typeidx, bool nullable,
int32 type_idx);
/* Set fields of RefHeapType_Common */
void
wasm_set_refheaptype_common(RefHeapType_Common *ref_ht_common, bool nullable,
int32 heap_type);
/* Find the related reftype in reftype map array with index */
WASMRefType *
wasm_reftype_map_find(WASMRefTypeMap *ref_type_maps, uint32 ref_type_map_count,
uint32 index_to_find);
/* Create a new hash set of reference type */
HashMap *
wasm_reftype_set_create(uint32 size);
/* Insert a reference type into the hash set */
WASMRefType *
wasm_reftype_set_insert(HashMap *ref_type_set, const WASMRefType *ref_type);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* end of _GC_TYPE_H_ */

View File

@ -0,0 +1,36 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (IWASM_GC_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions (-DWASM_ENABLE_GC=1)
if (WAMR_TEST_GC EQUAL 1)
add_definitions (-DGC_MANUALLY=1 -DGC_IN_EVERY_ALLOCATION=1)
endif ()
include_directories (${IWASM_GC_DIR})
file (GLOB source_all ${IWASM_GC_DIR}/*.c)
set (IWASM_GC_SOURCE ${source_all})
if (WAMR_BUILD_STRINGREF EQUAL 1)
set (IWASM_STRINGREF_DIR ${CMAKE_CURRENT_LIST_DIR}/stringref)
add_definitions (-DWASM_ENABLE_STRINGREF=1)
include_directories (${IWASM_STRINGREF_DIR})
if (NOT DEFINED WAMR_STRINGREF_IMPL_SOURCE)
message(FATAL_ERROR "stringref feature enabled, but WAMR_STRINGREF_IMPL_SOURCE not set" )
else ()
if (${WAMR_STRINGREF_IMPL_SOURCE} STREQUAL "STUB")
set (IWASM_STRINGREF_SOURCE ${IWASM_STRINGREF_DIR}/stringref_stub.c)
else()
set (IWASM_STRINGREF_SOURCE ${WAMR_STRINGREF_IMPL_SOURCE})
endif()
endif ()
set (IWASM_GC_SOURCE ${IWASM_GC_SOURCE} ${IWASM_STRINGREF_SOURCE})
endif ()

View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _STRING_OBJECT_H_
#define _STRING_OBJECT_H_
#include "wasm.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum EncodingFlag {
UTF8,
WTF8,
WTF16,
LOSSY_UTF8,
} EncodingFlag;
typedef enum StringViewType {
STRING_VIEW_WTF8,
STRING_VIEW_WTF16,
STRING_VIEW_ITER,
} StringViewType;
typedef enum ErrorCode {
Insufficient_Space = -3,
Encode_Fail = -2,
Isolated_Surrogate = -1,
} ErrorCode;
/******************* gc finalizer *****************/
void
wasm_string_destroy(WASMString str_obj);
/******************* opcode functions *****************/
/* string.const */
WASMString
wasm_string_new_const(const char *content, uint32 length);
/* string.new_xx8/new_wtf16 */
/* string.new_xx8_array */
/* string.new_wtf16_array */
WASMString
wasm_string_new_with_encoding(void *addr, uint32 count, EncodingFlag flag);
/* string.measure */
int32
wasm_string_measure(WASMString str_obj, EncodingFlag flag);
/* stringview_wtf16.length */
int32
wasm_string_wtf16_get_length(WASMString str_obj);
/* string.encode_xx8 */
/* string.encode_wtf16 */
/* stringview_wtf8.encode_xx */
/* stringview_wtf16.encode */
/* string.encode_xx8_array */
/* string.encode_wtf16_array */
int32
wasm_string_encode(WASMString str_obj, uint32 pos, uint32 count, void *addr,
uint32 *next_pos, EncodingFlag flag);
/* string.concat */
WASMString
wasm_string_concat(WASMString str_obj1, WASMString str_obj2);
/* string.eq */
int32
wasm_string_eq(WASMString str_obj1, WASMString str_obj2);
/* string.is_usv_sequence */
int32
wasm_string_is_usv_sequence(WASMString str_obj);
/* string.as_wtf8 */
/* string.as_wtf16 */
/* string.as_iter */
WASMString
wasm_string_create_view(WASMString str_obj, StringViewType type);
/* stringview_wtf8.advance */
/* stringview_iter.advance */
int32
wasm_string_advance(WASMString str_obj, uint32 pos, uint32 count,
uint32 *target_pos);
/* stringview_wtf8.slice */
/* stringview_wtf16.slice */
/* stringview_iter.slice */
WASMString
wasm_string_slice(WASMString str_obj, uint32 start, uint32 end,
StringViewType type);
/* stringview_wtf16.get_codeunit */
int16
wasm_string_get_wtf16_codeunit(WASMString str_obj, int32 pos);
/* stringview_iter.next */
uint32
wasm_string_next_codepoint(WASMString str_obj, uint32 pos);
/* stringview_iter.rewind */
uint32
wasm_string_rewind(WASMString str_obj, uint32 pos, uint32 count,
uint32 *target_pos);
/******************* application functions *****************/
void
wasm_string_dump(WASMString str_obj);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* end of _STRING_OBJECT_H_ */

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2023 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/* This file is the stub for stringref implementation, only used for wamrc
* compiler. The runtime embedder SHOULD NOT use this file */
#include "string_object.h"
/******************* gc finalizer *****************/
void
wasm_string_destroy(WASMString str_obj)
{}
/******************* opcode functions *****************/
/* string.const */
WASMString
wasm_string_new_const(const char *str, uint32 length)
{
return NULL;
}
/* string.new_xx8 */
/* string.new_wtf16 */
/* string.new_xx8_array */
/* string.new_wtf16_array */
WASMString
wasm_string_new_with_encoding(void *addr, uint32 count, EncodingFlag flag)
{
return NULL;
}
/* string.measure */
/* stringview_wtf16.length */
int32
wasm_string_measure(WASMString str_obj, EncodingFlag flag)
{
return 0;
}
/* stringview_wtf16.length */
int32
wasm_string_wtf16_get_length(WASMString str_obj)
{
return 0;
}
/* string.encode_xx8 */
/* string.encode_wtf16 */
/* stringview_wtf8.encode_xx */
/* stringview_wtf16.encode */
/* string.encode_xx8_array */
/* string.encode_wtf16_array */
int32
wasm_string_encode(WASMString str_obj, uint32 pos, uint32 count, void *addr,
uint32 *next_pos, EncodingFlag flag)
{
return 0;
}
/* string.concat */
WASMString
wasm_string_concat(WASMString str_obj1, WASMString str_obj2)
{
return NULL;
}
/* string.eq */
int32
wasm_string_eq(WASMString str_obj1, WASMString str_obj2)
{
return 0;
}
/* string.is_usv_sequence */
int32
wasm_string_is_usv_sequence(WASMString str_obj)
{
return 0;
}
/* string.as_wtf8 */
/* string.as_wtf16 */
/* string.as_iter */
WASMString
wasm_string_create_view(WASMString str_obj, StringViewType type)
{
return NULL;
}
/* stringview_wtf8.advance */
/* stringview_iter.advance */
int32
wasm_string_advance(WASMString str_obj, uint32 pos, uint32 count,
uint32 *consumed)
{
return 0;
}
/* stringview_wtf8.slice */
/* stringview_wtf16.slice */
/* stringview_iter.slice */
WASMString
wasm_string_slice(WASMString str_obj, uint32 start, uint32 end,
StringViewType type)
{
return NULL;
}
/* stringview_wtf16.get_codeunit */
int16
wasm_string_get_wtf16_codeunit(WASMString str_obj, int32 pos)
{
return 0;
}
/* stringview_iter.next */
uint32
wasm_string_next_codepoint(WASMString str_obj, uint32 pos)
{
return 0;
}
/* stringview_iter.rewind */
uint32
wasm_string_rewind(WASMString str_obj, uint32 pos, uint32 count,
uint32 *consumed)
{
return 0;
}
void
wasm_string_dump(WASMString str_obj)
{}

View File

@ -13,6 +13,15 @@
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#endif
#if WASM_ENABLE_GC != 0
#include "gc/gc_object.h"
#if WASM_ENABLE_STRINGREF != 0
#include "string_object.h"
#endif
#if WASM_ENABLE_GC_PERF_PROFILING != 0
#include "../../shared/mem-alloc/mem_alloc.h"
#endif
#endif
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
@ -52,7 +61,7 @@ static union {
* Implementation of wasm_application_execute_main()
*/
static bool
check_main_func_type(const WASMType *type)
check_main_func_type(const WASMFuncType *type)
{
if (!(type->param_count == 0 || type->param_count == 2)
|| type->result_count > 1) {
@ -83,7 +92,7 @@ static bool
execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
{
WASMFunctionInstanceCommon *func;
WASMType *func_type = NULL;
WASMFuncType *func_type = NULL;
WASMExecEnv *exec_env = NULL;
uint32 argc1 = 0, argv1[2] = { 0 };
uint32 total_argv_size = 0;
@ -244,6 +253,11 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
}
#endif
#if WASM_ENABLE_GC_PERF_PROFILING != 0
void *handle = wasm_runtime_get_gc_heap_handle(module_inst);
mem_allocator_dump_perf_profiling(handle);
#endif
#if WASM_ENABLE_PERF_PROFILING != 0
wasm_runtime_dump_perf_profiling(module_inst);
#endif
@ -304,10 +318,15 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
int32 argc, char *argv[])
{
WASMFunctionInstanceCommon *target_func;
WASMType *type = NULL;
WASMFuncType *type = NULL;
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_GC != 0
WASMRefTypeMap *ref_type_map;
WASMLocalObjectRef *local_ref;
uint32 num_local_ref_pushed = 0;
#endif
uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
uint32 param_size_in_double_world = 0, result_size_in_double_world = 0;
#endif
int32 i, p, module_type;
@ -337,7 +356,14 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
goto fail;
}
#if WASM_ENABLE_REF_TYPES != 0
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (!exec_env) {
wasm_runtime_set_exception(module_inst,
"create singleton exec_env failed");
goto fail;
}
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
for (i = 0; i < type->param_count; i++) {
param_size_in_double_world +=
wasm_value_type_cell_num_outside(type->types[i]);
@ -360,6 +386,9 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
goto fail;
}
#if WASM_ENABLE_GC != 0
ref_type_map = type->ref_type_maps;
#endif
/* Parse arguments */
for (i = 0, p = 0; i < argc; i++) {
char *endptr = NULL;
@ -482,8 +511,11 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
break;
}
#endif /* WASM_ENABLE_SIMD != 0 */
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#if UINTPTR_MAX == UINT32_MAX
case VALUE_TYPE_EXTERNREF:
#endif
{
if (strncasecmp(argv[i], "null", 4) == 0) {
argv1[p++] = (uint32)-1;
@ -493,16 +525,9 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
}
break;
}
#if UINTPTR_MAX == UINT64_MAX
case VALUE_TYPE_EXTERNREF:
{
#if UINTPTR_MAX == UINT32_MAX
if (strncasecmp(argv[i], "null", 4) == 0) {
argv1[p++] = (uint32)-1;
}
else {
argv1[p++] = strtoul(argv[i], &endptr, 0);
}
#else
union {
uintptr_t val;
uint32 parts[2];
@ -515,13 +540,97 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
}
argv1[p++] = u.parts[0];
argv1[p++] = u.parts[1];
#endif
break;
}
#endif /* WASM_ENABLE_REF_TYPES */
#endif
#endif /* WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 */
default:
{
#if WASM_ENABLE_GC != 0
bool is_extern_ref = false;
bool is_anyref = false;
if (wasm_is_type_reftype(type->types[i])) {
if (strncasecmp(argv[i], "null", 4) == 0) {
PUT_REF_TO_ADDR(argv1 + p, NULL_REF);
p += REF_CELL_NUM;
break;
}
else if (type->types[i] == VALUE_TYPE_EXTERNREF) {
is_extern_ref = true;
}
else if (type->types[i] == VALUE_TYPE_ANYREF) {
is_anyref = true;
}
if (wasm_is_type_multi_byte_type(
type->types[type->param_count + i])) {
WASMRefType *ref_type = ref_type_map->ref_type;
if (wasm_is_refheaptype_common(
&ref_type->ref_ht_common)) {
int32 heap_type = ref_type->ref_ht_common.heap_type;
if (heap_type == HEAP_TYPE_EXTERN) {
is_extern_ref = true;
}
else if (heap_type == HEAP_TYPE_ANY) {
is_anyref = true;
}
}
ref_type_map++;
}
if (is_extern_ref) {
WASMExternrefObjectRef gc_obj;
void *extern_obj =
(void *)(uintptr_t)strtoull(argv[i], &endptr, 0);
gc_obj = wasm_externref_obj_new(exec_env, extern_obj);
if (!gc_obj) {
wasm_runtime_set_exception(
module_inst, "create extern object failed");
goto fail;
}
if (!(local_ref =
runtime_malloc(sizeof(WASMLocalObjectRef),
module_inst, NULL, 0))) {
goto fail;
}
wasm_runtime_push_local_obj_ref(exec_env, local_ref);
local_ref->val = (WASMObjectRef)gc_obj;
num_local_ref_pushed++;
PUT_REF_TO_ADDR(argv1 + p, gc_obj);
p += REF_CELL_NUM;
}
else if (is_anyref) {
/* If a parameter type is (ref null? any) and its value
* is not null, then we treat the value as host ptr */
WASMAnyrefObjectRef gc_obj;
void *host_obj =
(void *)(uintptr_t)strtoull(argv[i], &endptr, 0);
gc_obj = wasm_anyref_obj_new(exec_env, host_obj);
if (!gc_obj) {
wasm_runtime_set_exception(
module_inst, "create anyref object failed");
goto fail;
}
if (!(local_ref =
runtime_malloc(sizeof(WASMLocalObjectRef),
module_inst, NULL, 0))) {
goto fail;
}
wasm_runtime_push_local_obj_ref(exec_env, local_ref);
local_ref->val = (WASMObjectRef)gc_obj;
num_local_ref_pushed++;
PUT_REF_TO_ADDR(argv1 + p, gc_obj);
p += REF_CELL_NUM;
}
break;
}
#endif /* end of WASM_ENABLE_GC != 0 */
bh_assert(0);
break;
}
}
if (endptr && *endptr != '\0' && *endptr != '_') {
snprintf(buf, sizeof(buf), "invalid input argument %" PRId32 ": %s",
@ -532,21 +641,17 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
}
wasm_runtime_set_exception(module_inst, NULL);
#if WASM_ENABLE_REF_TYPES == 0
#if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0
bh_assert(p == (int32)argc1);
#endif
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (!exec_env) {
wasm_runtime_set_exception(module_inst,
"create singleton exec_env failed");
goto fail;
}
if (!wasm_runtime_call_wasm(exec_env, target_func, argc1, argv1)) {
goto fail;
}
#if WASM_ENABLE_GC != 0
ref_type_map = type->result_ref_type_maps;
#endif
/* print return value */
for (j = 0; j < type->result_count; j++) {
switch (type->types[type->param_count + j]) {
@ -586,7 +691,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
os_printf("%.7g:f64", u.val);
break;
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
if (argv1[k] != NULL_REF)
@ -619,7 +724,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
#endif
break;
}
#endif
#endif /* end of WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 */
#if WASM_ENABLE_SIMD != 0
case VALUE_TYPE_V128:
{
@ -631,14 +736,117 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
}
#endif /* WASM_ENABLE_SIMD != 0 */
default:
{
#if WASM_ENABLE_GC != 0
if (wasm_is_type_reftype(type->types[type->param_count + j])) {
void *gc_obj = GET_REF_FROM_ADDR(argv1 + k);
k += REF_CELL_NUM;
if (!gc_obj) {
uint8 type1 = type->types[type->param_count + j];
WASMRefType *ref_type1 = NULL;
WASMType **types = NULL;
uint32 type_count = 0;
if (wasm_is_type_multi_byte_type(
type->types[type->param_count + j]))
ref_type1 = ref_type_map->ref_type;
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
WASMModule *module =
((WASMModuleInstance *)module_inst)->module;
types = module->types;
type_count = module->type_count;
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
AOTModule *module =
(AOTModule *)((AOTModuleInstance *)module_inst)
->module;
types = module->types;
type_count = module->type_count;
}
#endif
bh_assert(type);
if (wasm_reftype_is_subtype_of(type1, ref_type1,
REF_TYPE_ANYREF, NULL,
types, type_count))
os_printf("any:");
else if (wasm_reftype_is_subtype_of(
type1, ref_type1, REF_TYPE_FUNCREF, NULL,
types, type_count))
os_printf("func:");
if (wasm_reftype_is_subtype_of(type1, ref_type1,
REF_TYPE_EXTERNREF, NULL,
types, type_count))
os_printf("extern:");
os_printf("ref.null");
}
else if (wasm_obj_is_func_obj(gc_obj))
os_printf("ref.func");
#if WASM_ENABLE_STRINGREF != 0
else if (wasm_obj_is_stringref_obj(gc_obj)
|| wasm_obj_is_stringview_wtf8_obj(gc_obj)) {
wasm_string_dump(
(WASMString)wasm_stringref_obj_get_value(gc_obj));
}
else if (wasm_obj_is_stringview_wtf16_obj(gc_obj)) {
wasm_string_dump(
(WASMString)wasm_stringview_wtf16_obj_get_value(
gc_obj));
}
#endif
else if (wasm_obj_is_externref_obj(gc_obj)) {
#if WASM_ENABLE_SPEC_TEST != 0
WASMObjectRef obj = wasm_externref_obj_to_internal_obj(
(WASMExternrefObjectRef)gc_obj);
if (wasm_obj_is_anyref_obj(obj))
os_printf("0x%" PRIxPTR ":ref.extern",
(uintptr_t)wasm_anyref_obj_get_value(
(WASMAnyrefObjectRef)obj));
else
#endif
os_printf("ref.extern");
}
else if (wasm_obj_is_i31_obj(gc_obj))
os_printf("ref.i31");
else if (wasm_obj_is_array_obj(gc_obj))
os_printf("ref.array");
else if (wasm_obj_is_struct_obj(gc_obj))
os_printf("ref.struct");
else if (wasm_obj_is_eq_obj(gc_obj))
os_printf("ref.eq");
else if (wasm_obj_is_anyref_obj(gc_obj))
os_printf("0x%" PRIxPTR ":ref.host",
(uintptr_t)wasm_anyref_obj_get_value(
(WASMAnyrefObjectRef)gc_obj));
else if (wasm_obj_is_internal_obj(gc_obj))
os_printf("ref.any");
if (wasm_is_type_multi_byte_type(
type->types[type->param_count + j]))
ref_type_map++;
break;
}
#endif /* endof WASM_ENABLE_GC != 0 */
bh_assert(0);
break;
}
}
if (j < (uint32)(type->result_count - 1))
os_printf(",");
}
os_printf("\n");
#if WASM_ENABLE_GC != 0
for (j = 0; j < num_local_ref_pushed; j++) {
local_ref = wasm_runtime_pop_local_obj_ref(exec_env);
wasm_runtime_free(local_ref);
}
#endif
wasm_runtime_free(argv1);
return true;
@ -646,6 +854,13 @@ fail:
if (argv1)
wasm_runtime_free(argv1);
#if WASM_ENABLE_GC != 0
for (j = 0; j < num_local_ref_pushed; j++) {
local_ref = wasm_runtime_pop_local_obj_ref(exec_env);
wasm_runtime_free(local_ref);
}
#endif
bh_assert(wasm_runtime_get_exception(module_inst));
return false;
}
@ -668,6 +883,11 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
}
#endif
#if WASM_ENABLE_GC_PERF_PROFILING != 0
void *handle = wasm_runtime_get_gc_heap_handle(module_inst);
mem_allocator_dump_perf_profiling(handle);
#endif
#if WASM_ENABLE_PERF_PROFILING != 0
wasm_runtime_dump_perf_profiling(module_inst);
#endif

View File

@ -774,7 +774,7 @@ wasm_valtype_new(wasm_valkind_t kind)
wasm_valtype_t *val_type;
if (kind > WASM_F64 && WASM_FUNCREF != kind
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
&& WASM_ANYREF != kind
#endif
) {
@ -811,7 +811,7 @@ wasm_valtype_kind(const wasm_valtype_t *val_type)
}
static wasm_functype_t *
wasm_functype_new_internal(WASMType *type_rt)
wasm_functype_new_internal(WASMFuncType *type_rt)
{
wasm_functype_t *type = NULL;
wasm_valtype_t *param_type = NULL, *result_type = NULL;
@ -827,7 +827,7 @@ wasm_functype_new_internal(WASMType *type_rt)
type->extern_kind = WASM_EXTERN_FUNC;
/* WASMType->types[0 : type_rt->param_count) -> type->params */
/* WASMFuncType->types[0 : type_rt->param_count) -> type->params */
INIT_VEC(type->params, wasm_valtype_vec_new_uninitialized,
type_rt->param_count);
for (i = 0; i < type_rt->param_count; ++i) {
@ -841,7 +841,7 @@ wasm_functype_new_internal(WASMType *type_rt)
}
}
/* WASMType->types[type_rt->param_count : type_rt->result_count) ->
/* WASMFuncType->types[type_rt->param_count : type_rt->result_count) ->
* type->results */
INIT_VEC(type->results, wasm_valtype_vec_new_uninitialized,
type_rt->result_count);
@ -983,7 +983,7 @@ cmp_val_kind_with_val_type(wasm_valkind_t v_k, uint8 v_t)
*/
static bool
wasm_functype_same_internal(const wasm_functype_t *type,
const WASMType *type_intl)
const WASMFuncType *type_intl)
{
uint32 i = 0;
@ -1132,7 +1132,7 @@ wasm_tabletype_new(own wasm_valtype_t *val_type, const wasm_limits_t *limits)
}
if (wasm_valtype_kind(val_type) != WASM_FUNCREF
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
&& wasm_valtype_kind(val_type) != WASM_ANYREF
#endif
) {
@ -1646,7 +1646,7 @@ rt_val_to_wasm_val(const uint8 *data, uint8 val_type_rt, wasm_val_t *out)
out->kind = WASM_F64;
out->of.f64 = *((float64 *)data);
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
out->kind = WASM_ANYREF;
if (NULL_REF == *(uint32 *)data) {
@ -1687,7 +1687,7 @@ wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt,
bh_assert(WASM_F64 == v->kind);
*((float64 *)data) = v->of.f64;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
bh_assert(WASM_ANYREF == v->kind);
ret =
@ -2470,7 +2470,7 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
if (i < import_func_count) {
wasm_functype_t *type = NULL;
WASMType *type_rt = NULL;
WASMFuncType *type_rt = NULL;
#if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode) {
@ -2715,13 +2715,13 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
goto failed;
}
/* WASMExport -> (WASMType, (uint8, bool)) -> (wasm_functype_t,
/* WASMExport -> (WASMFuncType, (uint8, bool)) -> (wasm_functype_t,
* wasm_globaltype_t) -> wasm_externtype_t*/
switch (export->kind) {
case EXPORT_KIND_FUNC:
{
wasm_functype_t *type = NULL;
WASMType *type_rt;
WASMFuncType *type_rt;
if (!wasm_runtime_get_export_func_type(*module, export,
&type_rt)) {
@ -2776,12 +2776,22 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
{
wasm_tabletype_t *type = NULL;
uint8 elem_type_rt = 0;
#if WASM_ENABLE_GC != 0
WASMRefType *elem_ref_type_rt;
#endif
uint32 min_size = 0, max_size = 0;
if (!wasm_runtime_get_export_table_type(
*module, export, &elem_type_rt, &min_size, &max_size)) {
if (!wasm_runtime_get_export_table_type(*module, export,
&elem_type_rt,
#if WASM_ENABLE_GC != 0
&elem_ref_type_rt,
#endif
&min_size, &max_size)) {
goto failed;
}
#if WASM_ENABLE_GC != 0
(void)elem_ref_type_rt; /* TODO */
#endif
if (!(type = wasm_tabletype_new_internal(elem_type_rt, min_size,
max_size))) {
@ -3032,7 +3042,7 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
WASMModuleInstanceCommon *inst_comm_rt)
{
wasm_func_t *func = NULL;
WASMType *type_rt = NULL;
WASMFuncType *type_rt = NULL;
bh_assert(singleton_engine);
@ -3070,9 +3080,9 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
}
else {
type_rt =
module_aot->func_types[module_aot->func_type_indexes
[func_idx_rt
- module_aot->import_func_count]];
(AOTFuncType *)module_aot
->types[module_aot->func_type_indexes
[func_idx_rt - module_aot->import_func_count]];
}
}
#endif
@ -3204,8 +3214,7 @@ params_to_argv(const wasm_val_vec_t *params,
*(int64 *)argv = param->of.i64;
argv += 2;
break;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case WASM_ANYREF:
*(uintptr_t *)argv = (uintptr_t)param->of.ref;
argv += sizeof(uintptr_t) / sizeof(uint32);
@ -3247,7 +3256,7 @@ argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
result->of.i64 = *(int64 *)argv;
argv += 2;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case WASM_ANYREF:
result->of.ref = (struct wasm_ref_t *)(*(uintptr_t *)argv);
argv += sizeof(uintptr_t) / sizeof(uint32);
@ -3830,6 +3839,9 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
{
wasm_table_t *table = NULL;
uint8 val_type_rt = 0;
#if WASM_ENABLE_GC != 0
WASMRefType *val_ref_type_rt;
#endif
uint32 init_size = 0, max_size = 0;
bh_assert(singleton_engine);
@ -3845,14 +3857,21 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
table->store = store;
table->kind = WASM_EXTERN_TABLE;
if (!wasm_runtime_get_table_inst_elem_type(
inst_comm_rt, table_idx_rt, &val_type_rt, &init_size, &max_size)) {
if (!wasm_runtime_get_table_inst_elem_type(inst_comm_rt, table_idx_rt,
&val_type_rt,
#if WASM_ENABLE_GC != 0
&val_ref_type_rt,
#endif
&init_size, &max_size)) {
/*
* a wrong combination of module filetype and compilation flags
* leads to below branch
*/
goto failed;
}
#if WASM_ENABLE_GC != 0
(void)val_ref_type_rt; /* TODO */
#endif
if (!(table->type =
wasm_tabletype_new_internal(val_type_rt, init_size, max_size))) {
@ -3922,6 +3941,7 @@ wasm_table_type(const wasm_table_t *table)
return wasm_tabletype_copy(table->type);
}
#if WASM_ENABLE_GC == 0
own wasm_ref_t *
wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
{
@ -4010,7 +4030,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
return false;
}
p_ref_idx = table_interp->elems + index;
p_ref_idx = (uint32 *)(table_interp->elems + index);
function_count =
((WASMModuleInstance *)table->inst_comm_rt)->e->function_count;
}
@ -4026,7 +4046,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
return false;
}
p_ref_idx = table_aot->elems + index;
p_ref_idx = (uint32 *)(table_aot->elems + index);
function_count = module_aot->func_count;
}
#endif
@ -4062,6 +4082,22 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
return true;
}
#else /* else of WASM_ENABLE_GC == 0 */
own wasm_ref_t *
wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
{
/* TODO */
return NULL;
}
bool
wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
own wasm_ref_t *ref)
{
/* TODO */
return false;
}
#endif /* end of WASM_ENABLE_GC == 0 */
wasm_table_size_t
wasm_table_size(const wasm_table_t *table)

View File

@ -5,6 +5,9 @@
#include "wasm_exec_env.h"
#include "wasm_runtime_common.h"
#if WASM_ENABLE_GC != 0
#include "mem_alloc.h"
#endif
#if WASM_ENABLE_INTERP != 0
#include "../interpreter/wasm_runtime.h"
#endif
@ -28,7 +31,7 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size)
{
uint64 total_size =
offsetof(WASMExecEnv, wasm_stack.s.bottom) + (uint64)stack_size;
offsetof(WASMExecEnv, wasm_stack_u.bottom) + (uint64)stack_size;
WASMExecEnv *exec_env;
if (total_size >= UINT32_MAX
@ -65,9 +68,10 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
exec_env->module_inst = module_inst;
exec_env->wasm_stack_size = stack_size;
exec_env->wasm_stack.s.top_boundary =
exec_env->wasm_stack.s.bottom + stack_size;
exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
exec_env->wasm_stack.bottom = exec_env->wasm_stack_u.bottom;
exec_env->wasm_stack.top_boundary =
exec_env->wasm_stack.bottom + stack_size;
exec_env->wasm_stack.top = exec_env->wasm_stack.bottom;
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
@ -134,6 +138,9 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
#endif
WASMExecEnv *exec_env =
wasm_exec_env_create_internal(module_inst, stack_size);
#if WASM_ENABLE_GC != 0
void *gc_heap_handle = NULL;
#endif
if (!exec_env)
return NULL;
@ -145,6 +152,10 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
exec_env->aux_stack_boundary.boundary =
module->aux_stack_bottom - module->aux_stack_size;
#if WASM_ENABLE_GC != 0
gc_heap_handle =
((WASMModuleInstance *)module_inst)->e->common.gc_heap_pool;
#endif
}
#endif
#if WASM_ENABLE_AOT != 0
@ -155,6 +166,11 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
exec_env->aux_stack_boundary.boundary =
module->aux_stack_bottom - module->aux_stack_size;
#if WASM_ENABLE_GC != 0
gc_heap_handle =
((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
->common.gc_heap_handle;
#endif
}
#endif
@ -164,6 +180,13 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
wasm_exec_env_destroy_internal(exec_env);
return NULL;
}
#if WASM_ENABLE_GC != 0
mem_allocator_enable_gc_reclaim(gc_heap_handle, cluster);
#endif
#else
#if WASM_ENABLE_GC != 0
mem_allocator_enable_gc_reclaim(gc_heap_handle, exec_env);
#endif
#endif /* end of WASM_ENABLE_THREAD_MGR */
return exec_env;

View File

@ -38,8 +38,8 @@ typedef struct WASMExecEnv {
/* Next thread's exec env of a WASM module instance. */
struct WASMExecEnv *next;
/* Previous thread's exec env of a WASM module instance. */
struct WASMExecEnv *prev;
/* Current interpreter/AOT frame of current thread */
struct WASMInterpFrame *cur_frame;
/* Note: field module_inst, argv_buf, native_stack_boundary,
suspend_flags, aux_stack_boundary, aux_stack_bottom, and
@ -84,6 +84,15 @@ typedef struct WASMExecEnv {
*/
uint8 *native_stack_top_min;
struct {
/* The top boundary of the stack. */
uint8 *top_boundary;
/* The top to of the wasm stack which is free. */
uint8 *top;
/* The bottom of the wasm stack. */
uint8 *bottom;
} wasm_stack;
#if WASM_ENABLE_FAST_JIT != 0
/**
* Cache for
@ -116,6 +125,11 @@ typedef struct WASMExecEnv {
bool thread_is_detached;
#endif
#if WASM_ENABLE_GC != 0
/* Current local object reference variable */
struct WASMLocalObjectRef *cur_local_object_ref;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
WASMCurrentEnvStatus *current_status;
#endif
@ -125,9 +139,6 @@ typedef struct WASMExecEnv {
void *user_data;
/* Current interpreter frame of current thread */
struct WASMInterpFrame *cur_frame;
/* The native thread handle of current thread */
korp_tid handle;
@ -151,18 +162,9 @@ typedef struct WASMExecEnv {
/* The WASM stack of current thread */
union {
uint64 __make_it_8_byte_aligned_;
struct {
/* The top boundary of the stack. */
uint8 *top_boundary;
/* Top cell index which is free. */
uint8 *top;
/* The WASM stack. */
uint8 bottom[1];
} s;
} wasm_stack;
/* The WASM stack. */
uint8 bottom[1];
} wasm_stack_u;
} WASMExecEnv;
#if WASM_ENABLE_MEMORY_PROFILING != 0
@ -209,7 +211,7 @@ wasm_exec_env_is_aux_stack_managed_by_runtime(WASMExecEnv *exec_env)
static inline void *
wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
{
uint8 *addr = exec_env->wasm_stack.s.top;
uint8 *addr = exec_env->wasm_stack.top;
bh_assert(!(size & 3));
@ -220,17 +222,17 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
frame size, we should check again before putting the function arguments
into the outs area. */
if (size * 2
> (uint32)(uintptr_t)(exec_env->wasm_stack.s.top_boundary - addr)) {
> (uint32)(uintptr_t)(exec_env->wasm_stack.top_boundary - addr)) {
/* WASM stack overflow. */
return NULL;
}
exec_env->wasm_stack.s.top += size;
exec_env->wasm_stack.top += size;
#if WASM_ENABLE_MEMORY_PROFILING != 0
{
uint32 wasm_stack_used =
exec_env->wasm_stack.s.top - exec_env->wasm_stack.s.bottom;
exec_env->wasm_stack.top - exec_env->wasm_stack.bottom;
if (wasm_stack_used > exec_env->max_wasm_stack_used)
exec_env->max_wasm_stack_used = wasm_stack_used;
}
@ -241,8 +243,8 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
static inline void
wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top)
{
bh_assert((uint8 *)prev_top >= exec_env->wasm_stack.s.bottom);
exec_env->wasm_stack.s.top = (uint8 *)prev_top;
bh_assert((uint8 *)prev_top >= exec_env->wasm_stack.bottom);
exec_env->wasm_stack.top = (uint8 *)prev_top;
}
/**
@ -255,7 +257,7 @@ wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top)
static inline void *
wasm_exec_env_wasm_stack_top(WASMExecEnv *exec_env)
{
return exec_env->wasm_stack.s.top;
return exec_env->wasm_stack.top;
}
/**

View File

@ -81,7 +81,17 @@ compare_type_with_signautre(uint8 type, const char signature)
}
#if WASM_ENABLE_REF_TYPES != 0
if ('r' == signature && type == VALUE_TYPE_EXTERNREF)
if ('r' == signature
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
&& (type >= REF_TYPE_STRINGVIEWITER && type <= REF_TYPE_FUNCREF)
#else
&& (type >= REF_TYPE_NULLREF && type <= REF_TYPE_FUNCREF)
#endif
#else
&& type == VALUE_TYPE_EXTERNREF
#endif
)
return true;
#endif
@ -90,7 +100,7 @@ compare_type_with_signautre(uint8 type, const char signature)
}
static bool
check_symbol_signature(const WASMType *type, const char *signature)
check_symbol_signature(const WASMFuncType *type, const char *signature)
{
const char *p = signature, *p_end;
char sig;
@ -189,8 +199,9 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
*/
void *
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
const WASMType *func_type, const char **p_signature,
void **p_attachment, bool *p_call_conv_raw)
const WASMFuncType *func_type,
const char **p_signature, void **p_attachment,
bool *p_call_conv_raw)
{
NativeSymbolsNode *node, *node_next;
const char *signature = NULL;
@ -1442,7 +1453,7 @@ quick_aot_entry_init()
}
void *
wasm_native_lookup_quick_aot_entry(const WASMType *func_type)
wasm_native_lookup_quick_aot_entry(const WASMFuncType *func_type)
{
char signature[16] = { 0 };
uint32 param_count = func_type->param_count;

View File

@ -51,8 +51,9 @@ wasm_native_lookup_libc_builtin_global(const char *module_name,
*/
void *
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
const WASMType *func_type, const char **p_signature,
void **p_attachment, bool *p_call_conv_raw);
const WASMFuncType *func_type,
const char **p_signature, void **p_attachment,
bool *p_call_conv_raw);
bool
wasm_native_register_natives(const char *module_name,
@ -106,7 +107,7 @@ wasm_native_destroy();
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
void *
wasm_native_lookup_quick_aot_entry(const WASMType *func_type);
wasm_native_lookup_quick_aot_entry(const WASMFuncType *func_type);
#endif
#ifdef __cplusplus

View File

@ -19,6 +19,9 @@
#include "../aot/debug/jit_debug.h"
#endif
#endif
#if WASM_ENABLE_GC != 0
#include "gc/gc_object.h"
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#if WASM_ENABLE_DEBUG_INTERP != 0
@ -88,7 +91,7 @@ wasm_runtime_destroy_registered_module_list();
#define E_TYPE_XIP 4
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
/* Initialize externref hashmap */
static bool
wasm_externref_map_init();
@ -96,7 +99,7 @@ wasm_externref_map_init();
/* Destroy externref hashmap */
static void
wasm_externref_map_destroy();
#endif /* WASM_ENABLE_REF_TYPES */
#endif /* end of WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 */
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
@ -163,6 +166,10 @@ static JitCompOptions jit_options = { 0 };
static LLVMJITOptions llvm_jit_options = { 3, 3, 0, false };
#endif
#if WASM_ENABLE_GC != 0
static uint32 gc_heap_size_default = GC_HEAP_SIZE_DEFAULT;
#endif
static RunningMode runtime_running_mode = Mode_Default;
#ifdef OS_ENABLE_HW_BOUND_CHECK
@ -469,7 +476,7 @@ wasm_runtime_env_init()
#endif
#endif
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
if (!wasm_externref_map_init()) {
goto fail8;
}
@ -510,11 +517,11 @@ fail10:
#endif
#if WASM_ENABLE_FAST_JIT != 0
fail9:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
wasm_externref_map_destroy();
#endif
#endif
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
fail8:
#endif
#if WASM_ENABLE_AOT != 0
@ -552,9 +559,9 @@ static bool
wasm_runtime_exec_env_check(WASMExecEnv *exec_env)
{
return exec_env && exec_env->module_inst && exec_env->wasm_stack_size > 0
&& exec_env->wasm_stack.s.top_boundary
== exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size
&& exec_env->wasm_stack.s.top <= exec_env->wasm_stack.s.top_boundary;
&& exec_env->wasm_stack.top_boundary
== exec_env->wasm_stack.bottom + exec_env->wasm_stack_size
&& exec_env->wasm_stack.top <= exec_env->wasm_stack.top_boundary;
}
bool
@ -574,7 +581,7 @@ wasm_runtime_init()
void
wasm_runtime_destroy()
{
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
wasm_externref_map_destroy();
#endif
@ -647,6 +654,14 @@ wasm_runtime_get_llvm_jit_options(void)
}
#endif
#if WASM_ENABLE_GC != 0
uint32
wasm_runtime_get_gc_heap_size_default(void)
{
return gc_heap_size_default;
}
#endif
bool
wasm_runtime_full_init(RuntimeInitArgs *init_args)
{
@ -663,6 +678,10 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
#endif
#if WASM_ENABLE_GC != 0
gc_heap_size_default = init_args->gc_heap_size;
#endif
#if WASM_ENABLE_JIT != 0
llvm_jit_options.size_level = init_args->llvm_jit_size_level;
llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
@ -1572,11 +1591,11 @@ void
wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env)
{
uint32 total_size =
offsetof(WASMExecEnv, wasm_stack.s.bottom) + exec_env->wasm_stack_size;
offsetof(WASMExecEnv, wasm_stack_u.bottom) + exec_env->wasm_stack_size;
os_printf("Exec env memory consumption, total size: %u\n", total_size);
os_printf(" exec env struct size: %u\n",
offsetof(WASMExecEnv, wasm_stack.s.bottom));
offsetof(WASMExecEnv, wasm_stack_u.bottom));
#if WASM_ENABLE_INTERP != 0 && WASM_ENABLE_FAST_INTERP == 0
os_printf(" block addr cache size: %u\n",
sizeof(exec_env->block_addr_cache));
@ -1637,7 +1656,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
app_heap_peak_size = gc_get_heap_highmark_size(heap_handle);
}
total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
total_size = offsetof(WASMExecEnv, wasm_stack_u.bottom)
+ exec_env->wasm_stack_size + module_mem_consps.total_size
+ module_inst_mem_consps.total_size;
@ -1771,11 +1790,11 @@ wasm_runtime_access_exce_check_guard_page()
}
#endif
WASMType *
WASMFuncType *
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
uint32 module_type)
{
WASMType *type = NULL;
WASMFuncType *type = NULL;
#if WASM_ENABLE_INTERP != 0
if (module_type == Wasm_Module_Bytecode) {
@ -1816,7 +1835,7 @@ uint32
wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst,
WASMModuleInstanceCommon *const module_inst)
{
WASMType *type =
WASMFuncType *type =
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
bh_assert(type);
@ -1827,7 +1846,7 @@ uint32
wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst,
WASMModuleInstanceCommon *const module_inst)
{
WASMType *type =
WASMFuncType *type =
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
bh_assert(type);
@ -1861,7 +1880,7 @@ wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst,
WASMModuleInstanceCommon *const module_inst,
wasm_valkind_t *param_types)
{
WASMType *type =
WASMFuncType *type =
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
uint32 i;
@ -1877,7 +1896,7 @@ wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst,
WASMModuleInstanceCommon *const module_inst,
wasm_valkind_t *result_types)
{
WASMType *type =
WASMFuncType *type =
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
uint32 i;
@ -1889,7 +1908,7 @@ wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst,
}
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
/* (uintptr_t)externref -> (uint32)index */
/* argv -> *ret_argv */
static bool
@ -1903,7 +1922,7 @@ wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
result_i = 0;
bool need_param_transform = false, need_result_transform = false;
uint64 size = 0;
WASMType *func_type = wasm_runtime_get_function_type(
WASMFuncType *func_type = wasm_runtime_get_function_type(
function, exec_env->module_inst->module_type);
bh_assert(func_type);
@ -1996,7 +2015,7 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
uint32 *argv, uint32 argc, uint32 *ret_argv)
{
uint32 argv_i = 0, result_i = 0, ret_argv_i = 0;
WASMType *func_type;
WASMFuncType *func_type;
bh_assert((argv && ret_argv) || (argc == 0));
@ -2058,7 +2077,7 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
{
bool ret = false;
uint32 *new_argv = NULL, param_argc;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
uint32 result_argc = 0;
#endif
@ -2067,7 +2086,7 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
return false;
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
if (!wasm_runtime_prepare_call_function(exec_env, function, argv, argc,
&new_argv, &param_argc,
&result_argc)) {
@ -2097,7 +2116,7 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
return false;
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
if (!wasm_runtime_finalize_call_function(exec_env, function, new_argv,
result_argc, argv)) {
wasm_runtime_set_exception(exec_env->module_inst,
@ -2110,7 +2129,8 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
}
static void
parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
parse_args_to_uint32_array(WASMFuncType *type, wasm_val_t *args,
uint32 *out_argv)
{
uint32 i, p;
@ -2152,11 +2172,15 @@ parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
break;
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0
case WASM_FUNCREF:
{
out_argv[p++] = args[i].of.i32;
break;
}
#else
case WASM_FUNCREF:
#endif
case WASM_ANYREF:
{
#if UINTPTR_MAX == UINT32_MAX
@ -2182,7 +2206,7 @@ parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
}
static void
parse_uint32_array_to_results(WASMType *type, uint32 *argv,
parse_uint32_array_to_results(WASMFuncType *type, uint32 *argv,
wasm_val_t *out_results)
{
uint32 i, p;
@ -2229,6 +2253,7 @@ parse_uint32_array_to_results(WASMType *type, uint32 *argv,
break;
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0
case VALUE_TYPE_FUNCREF:
{
out_results[i].kind = WASM_I32;
@ -2236,6 +2261,20 @@ parse_uint32_array_to_results(WASMType *type, uint32 *argv,
break;
}
case VALUE_TYPE_EXTERNREF:
#else
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#endif /* end of WASM_ENABLE_GC == 0 */
{
#if UINTPTR_MAX == UINT32_MAX
out_results[i].kind = WASM_ANYREF;
@ -2252,7 +2291,7 @@ parse_uint32_array_to_results(WASMType *type, uint32 *argv,
#endif
break;
}
#endif
#endif /* end of WASM_ENABLE_REF_TYPES != 0 */
default:
bh_assert(0);
break;
@ -2267,11 +2306,11 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
uint32 num_args, wasm_val_t args[])
{
uint32 argc, argv_buf[16] = { 0 }, *argv = argv_buf, cell_num, module_type;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
uint32 i, param_size_in_double_world = 0, result_size_in_double_world = 0;
#endif
uint64 total_size;
WASMType *type;
WASMFuncType *type;
bool ret = false;
module_type = exec_env->module_inst->module_type;
@ -2283,7 +2322,7 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
goto fail1;
}
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
for (i = 0; i < type->param_count; i++) {
param_size_in_double_world +=
wasm_value_type_cell_num_outside(type->types[i]);
@ -2341,7 +2380,7 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
uint32 num_args, ...)
{
wasm_val_t args_buf[8] = { 0 }, *args = args_buf;
WASMType *type = NULL;
WASMFuncType *type = NULL;
bool ret = false;
uint64 total_size;
uint32 i = 0, module_type;
@ -2389,7 +2428,7 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
args[i].kind = WASM_F64;
args[i].of.f64 = va_arg(vargs, float64);
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
args[i].kind = WASM_FUNCREF;
@ -2506,6 +2545,23 @@ static const char *exception_msgs[] = {
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
/* GC related exceptions */
"null function object", /* EXCE_NULL_FUNC_OBJ */
"null structure object", /* EXCE_NULL_STRUCT_OBJ */
"null array reference", /* EXCE_NULL_ARRAY_OBJ */
"null i31 reference", /* EXCE_NULL_I31_OBJ */
"null reference", /* EXCE_NULL_REFERENCE */
"create rtt type failed", /* EXCE_FAILED_TO_CREATE_RTT_TYPE */
"create struct object failed", /* EXCE_FAILED_TO_CREATE_STRUCT_OBJ */
"create array object failed", /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */
"create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
"cast failure", /* EXCE_CAST_FAILURE */
"out of bounds array access", /* EXCE_ARRAY_IDX_OOB */
/* stringref related exceptions */
"create string object failed", /* EXCE_FAILED_TO_CREATE_STRING */
"create stringref failed", /* EXCE_FAILED_TO_CREATE_STRINGREF */
"create stringview failed", /* EXCE_FAILED_TO_CREATE_STRINGVIEW */
"encode failed", /* EXCE_FAILED_TO_ENCODE_STRING */
"", /* EXCE_ALREADY_THROWN */
};
/* clang-format on */
@ -3568,9 +3624,9 @@ wasm_runtime_unregister_natives(const char *module_name,
bool
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment, uint32 *argv, uint32 argc,
uint32 *argv_ret)
const WASMFuncType *func_type,
const char *signature, void *attachment,
uint32 *argv, uint32 argc, uint32 *argv_ret)
{
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *);
@ -3595,7 +3651,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++, argv_dst++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
@ -3640,7 +3696,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_F32:
*(float32 *)argv_dst = *(float32 *)argv_src++;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx = *argv_src++;
@ -3654,6 +3710,32 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
sizeof(uintptr_t));
break;
}
#endif
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
{
bh_memcpy_s(argv_dst, sizeof(uintptr_t), argv_src,
sizeof(uintptr_t));
argv_src += sizeof(uintptr_t) / sizeof(uint32);
break;
}
#endif
default:
bh_assert(0);
@ -3668,7 +3750,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
if (func_type->result_count > 0) {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
argv_ret[0] = *(uint32 *)argv1;
@ -3681,7 +3763,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1,
sizeof(uint64));
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx;
@ -3697,6 +3779,31 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
argv_ret[0] = externref_idx;
break;
}
#endif
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
{
bh_memcpy_s(argv_ret, sizeof(uintptr_t), argv1,
sizeof(uintptr_t));
break;
}
#endif
default:
bh_assert(0);
@ -3751,7 +3858,7 @@ static volatile VoidFuncPtr invokeNative_Void =
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
const WASMFuncType *func_type, const char *signature,
void *attachment, uint32 *argv, uint32 argc,
uint32 *argv_ret)
{
@ -3764,7 +3871,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
@ -3781,7 +3888,27 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
@ -3925,7 +4052,27 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
@ -4082,7 +4229,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
#endif /* BUILD_TARGET_RISCV32_ILP32D */
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx = *argv_src++;
@ -4128,7 +4275,27 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
else {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
argv_ret[0] =
@ -4146,7 +4313,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
PUT_F64_TO_ADDR(
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
if (is_aot_func) {
@ -4223,7 +4390,7 @@ word_copy(uint32 *dest, uint32 *src, unsigned num)
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
const WASMFuncType *func_type, const char *signature,
void *attachment, uint32 *argv, uint32 argc,
uint32 *argv_ret)
{
@ -4234,7 +4401,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
uint64 size;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
@ -4260,7 +4427,27 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
@ -4311,7 +4498,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_F32:
argv1[j++] = *argv++;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx = *argv++;
@ -4346,7 +4533,27 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
else {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
argv_ret[0] =
@ -4364,7 +4571,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
PUT_F64_TO_ADDR(argv_ret,
invokeNative_Float64(func_ptr, argv1, argc1));
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
if (is_aot_func) {
@ -4491,7 +4698,7 @@ __attribute__((no_sanitize_address))
#endif
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
const WASMFuncType *func_type, const char *signature,
void *attachment, uint32 *argv, uint32 argc,
uint32 *argv_ret)
{
@ -4503,7 +4710,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#ifndef BUILD_TARGET_RISCV64_LP64
@ -4555,7 +4762,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
@ -4595,6 +4802,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
case VALUE_TYPE_I64:
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *(uint64 *)argv_src;
else
@ -4618,7 +4845,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
}
argv_src += 2;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx = *argv_src++;
@ -4677,13 +4904,33 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
/* Invoke the native function and get the first result value */
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
argv_ret[0] =
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
break;
case VALUE_TYPE_I64:
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
case REF_TYPE_ANYREF:
case REF_TYPE_EQREF:
case REF_TYPE_HT_NULLABLE:
case REF_TYPE_HT_NON_NULLABLE:
case REF_TYPE_I31REF:
case REF_TYPE_NULLFUNCREF:
case REF_TYPE_NULLEXTERNREF:
case REF_TYPE_STRUCTREF:
case REF_TYPE_ARRAYREF:
case REF_TYPE_NULLREF:
#if WASM_ENABLE_STRINGREF != 0
case REF_TYPE_STRINGREF:
case REF_TYPE_STRINGVIEWWTF8:
case REF_TYPE_STRINGVIEWWTF16:
case REF_TYPE_STRINGVIEWITER:
#endif
#endif
PUT_I64_TO_ADDR(argv_ret,
invokeNative_Int64(func_ptr, argv1, n_stacks));
break;
@ -4695,7 +4942,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
PUT_F64_TO_ADDR(
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
if (is_aot_func) {
@ -4887,7 +5134,7 @@ wasm_runtime_join_thread(wasm_thread_t tid, void **retval)
#endif /* end of WASM_ENABLE_THREAD_MGR */
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
static korp_mutex externref_lock;
static uint32 externref_global_id = 1;
@ -5167,7 +5414,8 @@ mark_externref(uint32 externref_idx)
static void
interp_mark_all_externrefs(WASMModuleInstance *module_inst)
{
uint32 i, j, externref_idx, *table_data;
uint32 i, j, externref_idx;
table_elem_type_t *table_data;
uint8 *global_data = module_inst->global_data;
WASMGlobalInstance *global;
WASMTableInstance *table;
@ -5289,7 +5537,7 @@ wasm_externref_retain(uint32 externref_idx)
os_mutex_unlock(&externref_lock);
return false;
}
#endif /* end of WASM_ENABLE_REF_TYPES */
#endif /* end of WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 */
#if WASM_ENABLE_DUMP_CALL_STACK != 0
uint32
@ -5405,6 +5653,9 @@ wasm_runtime_dump_pgo_prof_data_to_buf(WASMModuleInstanceCommon *module_inst,
bool
wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
uint32 table_idx, uint8 *out_elem_type,
#if WASM_ENABLE_GC != 0
WASMRefType **out_ref_type,
#endif
uint32 *out_min_size, uint32 *out_max_size)
{
#if WASM_ENABLE_INTERP != 0
@ -5415,6 +5666,9 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
WASMTableImport *import_table =
&((module->import_tables + table_idx)->u.table);
*out_elem_type = import_table->elem_type;
#if WASM_ENABLE_GC != 0
*out_ref_type = import_table->elem_ref_type;
#endif
*out_min_size = import_table->init_size;
*out_max_size = import_table->max_size;
}
@ -5422,6 +5676,9 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
WASMTable *table =
module->tables + (table_idx - module->import_table_count);
*out_elem_type = table->elem_type;
#if WASM_ENABLE_GC != 0
*out_ref_type = table->elem_ref_type;
#endif
*out_min_size = table->init_size;
*out_max_size = table->max_size;
}
@ -5435,7 +5692,10 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
if (table_idx < module->import_table_count) {
AOTImportTable *import_table = module->import_tables + table_idx;
*out_elem_type = VALUE_TYPE_FUNCREF;
*out_elem_type = import_table->elem_type;
#if WASM_ENABLE_GC != 0
*out_ref_type = NULL; /* TODO */
#endif
*out_min_size = import_table->table_init_size;
*out_max_size = import_table->table_max_size;
}
@ -5443,6 +5703,9 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
AOTTable *table =
module->tables + (table_idx - module->import_table_count);
*out_elem_type = table->elem_type;
#if WASM_ENABLE_GC != 0
*out_ref_type = NULL; /* TODO */
#endif
*out_min_size = table->table_init_size;
*out_max_size = table->table_max_size;
}
@ -5456,31 +5719,28 @@ wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
bool
wasm_runtime_get_table_inst_elem_type(
const WASMModuleInstanceCommon *module_inst_comm, uint32 table_idx,
uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size)
uint8 *out_elem_type,
#if WASM_ENABLE_GC != 0
WASMRefType **out_ref_type,
#endif
uint32 *out_min_size, uint32 *out_max_size)
{
#if WASM_ENABLE_INTERP != 0
if (module_inst_comm->module_type == Wasm_Module_Bytecode) {
WASMModuleInstance *module_inst =
(WASMModuleInstance *)module_inst_comm;
return wasm_runtime_get_table_elem_type(
(WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
out_min_size, out_max_size);
}
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
return wasm_runtime_get_table_elem_type(
(WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
#if WASM_ENABLE_GC != 0
out_ref_type,
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst_comm->module_type == Wasm_Module_AoT) {
AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
return wasm_runtime_get_table_elem_type(
(WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
out_min_size, out_max_size);
}
#endif
return false;
out_min_size, out_max_size);
}
bool
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
const WASMExport *export, WASMType **out)
const WASMExport *export, WASMFuncType **out)
{
#if WASM_ENABLE_INTERP != 0
if (module_comm->module_type == Wasm_Module_Bytecode) {
@ -5503,13 +5763,14 @@ wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
AOTModule *module = (AOTModule *)module_comm;
if (export->index < module->import_func_count) {
*out = module->func_types[module->import_funcs[export->index]
.func_type_index];
*out = (WASMFuncType *)
module->types[module->import_funcs[export->index]
.func_type_index];
}
else {
*out = module->func_types
[module->func_type_indexes[export->index
- module->import_func_count]];
*out = (WASMFuncType *)module
->types[module->func_type_indexes
[export->index - module->import_func_count]];
}
return true;
}
@ -5615,15 +5876,23 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
bool
wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
const WASMExport *export,
uint8 *out_elem_type, uint32 *out_min_size,
uint32 *out_max_size)
uint8 *out_elem_type,
#if WASM_ENABLE_GC != 0
WASMRefType **out_ref_type,
#endif
uint32 *out_min_size, uint32 *out_max_size)
{
return wasm_runtime_get_table_elem_type(
module_comm, export->index, out_elem_type, out_min_size, out_max_size);
return wasm_runtime_get_table_elem_type(module_comm, export->index,
out_elem_type,
#if WASM_ENABLE_GC != 0
out_ref_type,
#endif
out_min_size, out_max_size);
}
static inline bool
argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
argv_to_params(wasm_val_t *out_params, const uint32 *argv,
WASMFuncType *func_type)
{
wasm_val_t *param = out_params;
uint32 i = 0, *u32;
@ -5650,7 +5919,7 @@ argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
u32[0] = *argv++;
u32[1] = *argv++;
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
param->kind = WASM_ANYREF;
@ -5672,7 +5941,7 @@ argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
static inline bool
results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
const wasm_val_t *results, WASMType *func_type)
const wasm_val_t *results, WASMFuncType *func_type)
{
const wasm_val_t *result = results;
uint32 *argv = out_argv, *u32, i;
@ -5690,10 +5959,11 @@ results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
*argv++ = u32[0];
*argv++ = u32[1];
break;
#if WASM_ENABLE_REF_TYPES != 0
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
if (!wasm_externref_obj2ref(module_inst,
(void *)result->of.foreign, argv)) {
(void *)result->of.foreign,
(uint32 *)argv)) {
return false;
}
argv++;
@ -5709,7 +5979,7 @@ results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
bool
wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
void *func_ptr, WASMType *func_type,
void *func_ptr, WASMFuncType *func_type,
uint32 argc, uint32 *argv, bool with_env,
void *wasm_c_api_env)
{

View File

@ -12,6 +12,9 @@
#include "wasm_native.h"
#include "../include/wasm_export.h"
#include "../interpreter/wasm.h"
#if WASM_ENABLE_GC != 0
#include "gc/gc_object.h"
#endif
#if WASM_ENABLE_LIBC_WASI != 0
#if WASM_ENABLE_UVWASI == 0
@ -38,9 +41,14 @@ extern "C" {
do { \
*(float64 *)(addr) = (float64)(value); \
} while (0)
#define PUT_REF_TO_ADDR(addr, value) \
do { \
*(void **)(addr) = (void *)(value); \
} while (0)
#define GET_I64_FROM_ADDR(addr) (*(int64 *)(addr))
#define GET_F64_FROM_ADDR(addr) (*(float64 *)(addr))
#define GET_REF_FROM_ADDR(addr) (*(void **)(addr))
/* For STORE opcodes */
#define STORE_I64 PUT_I64_TO_ADDR
@ -97,6 +105,24 @@ STORE_U8(void *addr, uint8_t value)
addr_u32[0] = u.parts[0]; \
addr_u32[1] = u.parts[1]; \
} while (0)
#if UINTPTR_MAX == UINT64_MAX
#define PUT_REF_TO_ADDR(addr, value) \
do { \
uint32 *addr_u32 = (uint32 *)(addr); \
union { \
void *val; \
uint32 parts[2]; \
} u; \
u.val = (void *)(value); \
addr_u32[0] = u.parts[0]; \
addr_u32[1] = u.parts[1]; \
} while (0)
#else
#define PUT_REF_TO_ADDR(addr, value) \
do { \
*(void **)(addr) = (void *)(value); \
} while (0)
#endif
static inline int64
GET_I64_FROM_ADDR(uint32 *addr)
@ -122,6 +148,22 @@ GET_F64_FROM_ADDR(uint32 *addr)
return u.val;
}
#if UINTPTR_MAX == UINT64_MAX
static inline void *
GET_REF_FROM_ADDR(uint32 *addr)
{
union {
void *val;
uint32 parts[2];
} u;
u.parts[0] = addr[0];
u.parts[1] = addr[1];
return u.val;
}
#else
#define GET_REF_FROM_ADDR(addr) (*(void **)(addr))
#endif
/* For STORE opcodes */
#define STORE_I64(addr, value) \
do { \
@ -426,6 +468,10 @@ typedef struct wasm_frame_t {
uint32 func_index;
uint32 func_offset;
const char *func_name_wp;
uint32 *sp;
uint8 *frame_ref;
uint32 *lp;
} WASMCApiFrame;
#if WASM_ENABLE_JIT != 0
@ -471,6 +517,12 @@ LLVMJITOptions *
wasm_runtime_get_llvm_jit_options(void);
#endif
#if WASM_ENABLE_GC != 0
/* Internal API */
uint32
wasm_runtime_get_gc_heap_size_default(void);
#endif
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_full_init(RuntimeInitArgs *init_args);
@ -551,7 +603,7 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
const char *name, const char *signature);
/* Internal API */
WASMType *
WASMFuncType *
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
uint32 module_type);
@ -918,6 +970,15 @@ wasm_runtime_set_wasi_ns_lookup_pool(wasm_module_t module,
uint32 ns_lookup_pool_size);
#endif /* end of WASM_ENABLE_LIBC_WASI */
#if WASM_ENABLE_GC != 0
void
wasm_runtime_set_gc_heap_handle(WASMModuleInstanceCommon *module_inst,
void *gc_heap_handle);
void *
wasm_runtime_get_gc_heap_handle(WASMModuleInstanceCommon *module_inst);
#endif
#if WASM_ENABLE_REF_TYPES != 0
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
@ -1011,15 +1072,15 @@ wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key);
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
const WASMFuncType *func_type, const char *signature,
void *attachment, uint32 *argv, uint32 argc,
uint32 *ret);
bool
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment, uint32 *argv, uint32 argc,
uint32 *ret);
const WASMFuncType *func_type,
const char *signature, void *attachment,
uint32 *argv, uint32 argc, uint32 *ret);
void
wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2);
@ -1037,16 +1098,24 @@ wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
bool
wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
uint32 table_idx, uint8 *out_elem_type,
#if WASM_ENABLE_GC != 0
WASMRefType **out_ref_type,
#endif
uint32 *out_min_size, uint32 *out_max_size);
bool
wasm_runtime_get_table_inst_elem_type(
const WASMModuleInstanceCommon *module_inst_comm, uint32 table_idx,
uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size);
uint8 *out_elem_type,
#if WASM_ENABLE_GC != 0
WASMRefType **out_ref_type,
#endif
uint32 *out_min_size, uint32 *out_max_size);
bool
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
const WASMExport *export_, WASMType **out);
const WASMExport *export_,
WASMFuncType **out);
bool
wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm,
@ -1061,12 +1130,15 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
bool
wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
const WASMExport *export_,
uint8 *out_elem_type, uint32 *out_min_size,
uint32 *out_max_size);
uint8 *out_elem_type,
#if WASM_ENABLE_GC != 0
WASMRefType **out_ref_type,
#endif
uint32 *out_min_size, uint32 *out_max_size);
bool
wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
void *func_ptr, WASMType *func_type,
void *func_ptr, WASMFuncType *func_type,
uint32 argc, uint32 *argv, bool with_env,
void *wasm_c_api_env);