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:
@ -9,12 +9,15 @@
|
||||
#include "bh_platform.h"
|
||||
#include "bh_hashmap.h"
|
||||
#include "bh_assert.h"
|
||||
#if WASM_ENABLE_GC != 0
|
||||
#include "gc_export.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Value Type */
|
||||
/* Value Type */
|
||||
#define VALUE_TYPE_I32 0x7F
|
||||
#define VALUE_TYPE_I64 0X7E
|
||||
#define VALUE_TYPE_F32 0x7D
|
||||
@ -23,29 +26,99 @@ extern "C" {
|
||||
#define VALUE_TYPE_FUNCREF 0x70
|
||||
#define VALUE_TYPE_EXTERNREF 0x6F
|
||||
#define VALUE_TYPE_VOID 0x40
|
||||
|
||||
/* Packed Types */
|
||||
#define PACKED_TYPE_I8 0x78
|
||||
#define PACKED_TYPE_I16 0x77
|
||||
|
||||
/* Reference Types */
|
||||
#define REF_TYPE_NULLFUNCREF 0x73
|
||||
#define REF_TYPE_NULLEXTERNREF 0x72
|
||||
#define REF_TYPE_NULLREF 0x71
|
||||
#define REF_TYPE_FUNCREF VALUE_TYPE_FUNCREF /* 0x70 */
|
||||
#define REF_TYPE_EXTERNREF VALUE_TYPE_EXTERNREF /* 0x6F */
|
||||
#define REF_TYPE_ANYREF 0x6E
|
||||
#define REF_TYPE_EQREF 0x6D
|
||||
#define REF_TYPE_I31REF 0x6C
|
||||
#define REF_TYPE_STRUCTREF 0x6B
|
||||
#define REF_TYPE_ARRAYREF 0x6A
|
||||
#define REF_TYPE_HT_NON_NULLABLE 0x64
|
||||
#define REF_TYPE_HT_NULLABLE 0x63
|
||||
#define REF_TYPE_STRINGREF VALUE_TYPE_STRINGREF /* 0x67 */
|
||||
#define REF_TYPE_STRINGVIEWWTF8 VALUE_TYPE_STRINGVIEWWTF8 /* 0x66 */
|
||||
#define REF_TYPE_STRINGVIEWWTF16 VALUE_TYPE_STRINGVIEWWTF16 /* 0x62 */
|
||||
#define REF_TYPE_STRINGVIEWITER VALUE_TYPE_STRINGVIEWITER /* 0x61 */
|
||||
|
||||
/* Heap Types */
|
||||
#define HEAP_TYPE_NOFUNC (-0x0D)
|
||||
#define HEAP_TYPE_NOEXTERN (-0x0E)
|
||||
#define HEAP_TYPE_NONE (-0x0F)
|
||||
#define HEAP_TYPE_FUNC (-0x10)
|
||||
#define HEAP_TYPE_EXTERN (-0x11)
|
||||
#define HEAP_TYPE_ANY (-0x12)
|
||||
#define HEAP_TYPE_EQ (-0x13)
|
||||
#define HEAP_TYPE_I31 (-0x14)
|
||||
#define HEAP_TYPE_STRUCT (-0x15)
|
||||
#define HEAP_TYPE_ARRAY (-0x16)
|
||||
#define HEAP_TYPE_STRINGREF (-0x19)
|
||||
#define HEAP_TYPE_STRINGVIEWWTF8 (-0x1A)
|
||||
#define HEAP_TYPE_STRINGVIEWWTF16 (-0x1E)
|
||||
#define HEAP_TYPE_STRINGVIEWITER (-0x1F)
|
||||
|
||||
/* Defined Types */
|
||||
#define DEFINED_TYPE_FUNC 0x60
|
||||
#define DEFINED_TYPE_STRUCT 0x5F
|
||||
#define DEFINED_TYPE_ARRAY 0x5E
|
||||
#define DEFINED_TYPE_SUB 0x50
|
||||
#define DEFINED_TYPE_SUB_FINAL 0x4F
|
||||
#define DEFINED_TYPE_REC 0x4E
|
||||
|
||||
/* Used by AOT */
|
||||
#define VALUE_TYPE_I1 0x41
|
||||
/* Used by loader to represent any type of i32/i64/f32/f64 */
|
||||
/**
|
||||
* Used by loader to represent any type of i32/i64/f32/f64/v128
|
||||
* and ref types, including funcref, externref, anyref, eqref,
|
||||
* (ref null $ht), (ref $ht), i31ref, structref, arrayref,
|
||||
* nullfuncref, nullexternref, nullref and stringref
|
||||
*/
|
||||
#define VALUE_TYPE_ANY 0x42
|
||||
/**
|
||||
* Used by wamr compiler to represent object ref types,
|
||||
* including func object ref, externref object ref,
|
||||
* internal object ref, eq obect ref, i31 object ref,
|
||||
* struct object ref, array obect ref
|
||||
*/
|
||||
#define VALUE_TYPE_GC_REF 0x43
|
||||
|
||||
#define DEFAULT_NUM_BYTES_PER_PAGE 65536
|
||||
#define DEFAULT_MAX_PAGES 65536
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
typedef uintptr_t table_elem_type_t;
|
||||
#define NULL_REF (0xFFFFFFFF)
|
||||
#else
|
||||
typedef void *table_elem_type_t;
|
||||
#define NULL_REF (NULL)
|
||||
#define REF_CELL_NUM ((uint32)sizeof(uintptr_t) / sizeof(uint32))
|
||||
#endif
|
||||
|
||||
#define TABLE_MAX_SIZE (1024)
|
||||
|
||||
#define INIT_EXPR_NONE 0x00
|
||||
#define INIT_EXPR_TYPE_I32_CONST 0x41
|
||||
#define INIT_EXPR_TYPE_I64_CONST 0x42
|
||||
#define INIT_EXPR_TYPE_F32_CONST 0x43
|
||||
#define INIT_EXPR_TYPE_F64_CONST 0x44
|
||||
#define INIT_EXPR_TYPE_V128_CONST 0xFD
|
||||
/* = WASM_OP_REF_FUNC */
|
||||
#define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
|
||||
/* = WASM_OP_REF_NULL */
|
||||
#define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
|
||||
#define INIT_EXPR_TYPE_GET_GLOBAL 0x23
|
||||
#define INIT_EXPR_TYPE_ERROR 0xff
|
||||
#define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
|
||||
#define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
|
||||
#define INIT_EXPR_TYPE_STRUCT_NEW 0xD3
|
||||
#define INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT 0xD4
|
||||
#define INIT_EXPR_TYPE_ARRAY_NEW 0xD5
|
||||
#define INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT 0xD6
|
||||
#define INIT_EXPR_TYPE_ARRAY_NEW_FIXED 0xD7
|
||||
#define INIT_EXPR_TYPE_I31_NEW 0xD8
|
||||
#define INIT_EXPR_TYPE_ANY_CONVERT_EXTERN 0xD9
|
||||
#define INIT_EXPR_TYPE_EXTERN_CONVERT_ANY 0xDA
|
||||
|
||||
#define WASM_MAGIC_NUMBER 0x6d736100
|
||||
#define WASM_CURRENT_VERSION 1
|
||||
@ -68,6 +141,9 @@ extern "C" {
|
||||
#if WASM_ENABLE_TAGS != 0
|
||||
#define SECTION_TYPE_TAG 13
|
||||
#endif
|
||||
#if WASM_ENABLE_STRINGREF != 0
|
||||
#define SECTION_TYPE_STRINGREF 14
|
||||
#endif
|
||||
|
||||
#define SUB_SECTION_TYPE_MODULE 0
|
||||
#define SUB_SECTION_TYPE_FUNC 1
|
||||
@ -99,6 +175,21 @@ extern "C" {
|
||||
#define LABEL_TYPE_CATCH_ALL 6
|
||||
#endif
|
||||
|
||||
#define WASM_TYPE_FUNC 0
|
||||
#define WASM_TYPE_STRUCT 1
|
||||
#define WASM_TYPE_ARRAY 2
|
||||
|
||||
#if WASM_ENABLE_STRINGREF != 0
|
||||
#define WASM_TYPE_STRINGREF 3
|
||||
#define WASM_TYPE_STRINGVIEWWTF8 4
|
||||
#define WASM_TYPE_STRINGVIEWWTF16 5
|
||||
#define WASM_TYPE_STRINGVIEWITER 6
|
||||
#endif
|
||||
|
||||
/* In WasmGC, a table can start with [0x40 0x00] to indicate it has an
|
||||
* initializer */
|
||||
#define TABLE_INIT_EXPR_FLAG 0x40
|
||||
|
||||
typedef struct WASMModule WASMModule;
|
||||
typedef struct WASMFunction WASMFunction;
|
||||
typedef struct WASMGlobal WASMGlobal;
|
||||
@ -106,6 +197,8 @@ typedef struct WASMGlobal WASMGlobal;
|
||||
typedef struct WASMTag WASMTag;
|
||||
#endif
|
||||
|
||||
#ifndef WASM_VALUE_DEFINED
|
||||
#define WASM_VALUE_DEFINED
|
||||
typedef union V128 {
|
||||
int8 i8x16[16];
|
||||
int16 i16x8[8];
|
||||
@ -124,44 +217,268 @@ typedef union WASMValue {
|
||||
uint64 u64;
|
||||
float32 f32;
|
||||
float64 f64;
|
||||
uintptr_t addr;
|
||||
V128 v128;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
wasm_obj_t gc_obj;
|
||||
uint32 type_index;
|
||||
struct {
|
||||
uint32 type_index;
|
||||
uint32 length;
|
||||
} array_new_default;
|
||||
/* pointer to a memory space holding more data, current usage:
|
||||
* struct.new init value: WASMStructNewInitValues *
|
||||
* array.new init value: WASMArrayNewInitValues *
|
||||
*/
|
||||
void *data;
|
||||
#endif
|
||||
} WASMValue;
|
||||
#endif /* end of WASM_VALUE_DEFINED */
|
||||
|
||||
typedef struct WASMStructNewInitValues {
|
||||
uint8 type_idx;
|
||||
uint32 count;
|
||||
WASMValue fields[1];
|
||||
} WASMStructNewInitValues;
|
||||
|
||||
typedef struct WASMArrayNewInitValues {
|
||||
uint8 type_idx;
|
||||
uint32 length;
|
||||
WASMValue elem_data[1];
|
||||
} WASMArrayNewInitValues;
|
||||
|
||||
typedef struct InitializerExpression {
|
||||
/* type of INIT_EXPR_TYPE_XXX */
|
||||
/* it actually is instr, in some places, requires constant only */
|
||||
/* type of INIT_EXPR_TYPE_XXX, which is an instruction of
|
||||
constant expression */
|
||||
uint8 init_expr_type;
|
||||
WASMValue u;
|
||||
} InitializerExpression;
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/**
|
||||
* Reference type of (ref null ht) or (ref ht),
|
||||
* and heap type is defined type (type i), i >= 0
|
||||
*/
|
||||
typedef struct RefHeapType_TypeIdx {
|
||||
/* ref_type is REF_TYPE_HT_NULLABLE or
|
||||
REF_TYPE_HT_NON_NULLABLE, (0x6C or 0x6B) */
|
||||
uint8 ref_type;
|
||||
/* true if ref_type is REF_TYPE_HT_NULLABLE */
|
||||
bool nullable;
|
||||
/* heap type is defined type: type_index >= 0 */
|
||||
int32 type_idx;
|
||||
} RefHeapType_TypeIdx;
|
||||
|
||||
/**
|
||||
* Reference type of (ref null ht) or (ref ht),
|
||||
* and heap type is non-defined type
|
||||
*/
|
||||
typedef struct RefHeapType_Common {
|
||||
/* ref_type is REF_TYPE_HT_NULLABLE or
|
||||
REF_TYPE_HT_NON_NULLABLE (0x6C or 0x6B) */
|
||||
uint8 ref_type;
|
||||
/* true if ref_type is REF_TYPE_HT_NULLABLE */
|
||||
bool nullable;
|
||||
/* Common heap type (not defined type):
|
||||
-0x10 (func), -0x11 (extern), -0x12 (any), -0x13 (eq),
|
||||
-0x16 (i31), -0x17 (nofunc), -0x18 (noextern),
|
||||
-0x19 (struct), -0x20 (array), -0x21 (none) */
|
||||
int32 heap_type;
|
||||
} RefHeapType_Common;
|
||||
|
||||
/**
|
||||
* Reference type
|
||||
*/
|
||||
typedef union WASMRefType {
|
||||
uint8 ref_type;
|
||||
RefHeapType_TypeIdx ref_ht_typeidx;
|
||||
RefHeapType_Common ref_ht_common;
|
||||
} WASMRefType;
|
||||
|
||||
typedef struct WASMRefTypeMap {
|
||||
/**
|
||||
* The type index of a type array, which only stores
|
||||
* the first byte of the type, e.g. WASMFuncType.types,
|
||||
* WASMStructType.fields
|
||||
*/
|
||||
uint16 index;
|
||||
/* The full type info if the type cannot be described
|
||||
with one byte */
|
||||
WASMRefType *ref_type;
|
||||
} WASMRefTypeMap;
|
||||
#endif /* end of WASM_ENABLE_GC */
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
typedef struct WASMFuncType WASMType;
|
||||
typedef WASMType *WASMTypePtr;
|
||||
#else
|
||||
/**
|
||||
* Common type, store the same fields of
|
||||
* WASMFuncType, WASMStructType and WASMArrayType
|
||||
*/
|
||||
typedef struct WASMType {
|
||||
/**
|
||||
* type_flag must be WASM_TYPE_FUNC/STRUCT/ARRAY to
|
||||
* denote that it is a WASMFuncType, WASMStructType or
|
||||
* WASMArrayType
|
||||
*/
|
||||
uint16 type_flag;
|
||||
|
||||
bool is_sub_final;
|
||||
/* The inheritance depth */
|
||||
uint32 inherit_depth;
|
||||
/* The root type */
|
||||
struct WASMType *root_type;
|
||||
/* The parent type */
|
||||
struct WASMType *parent_type;
|
||||
uint32 parent_type_idx;
|
||||
|
||||
/* number of internal types in the current rec group, if the type is not in
|
||||
* a recursive group, rec_count = 0 */
|
||||
uint16 rec_count;
|
||||
uint16 rec_idx;
|
||||
} WASMType, *WASMTypePtr;
|
||||
#endif /* end of WASM_ENABLE_GC */
|
||||
|
||||
/* Function type */
|
||||
typedef struct WASMFuncType {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMType base_type;
|
||||
#endif
|
||||
|
||||
uint16 param_count;
|
||||
uint16 result_count;
|
||||
uint16 param_cell_num;
|
||||
uint16 ret_cell_num;
|
||||
uint16 ref_count;
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||
&& WASM_ENABLE_LAZY_JIT != 0
|
||||
/* Code block to call llvm jit functions of this
|
||||
kind of function type from fast jit jitted code */
|
||||
void *call_to_llvm_jit_from_fast_jit;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint16 ref_type_map_count;
|
||||
WASMRefTypeMap *ref_type_maps;
|
||||
WASMRefTypeMap *result_ref_type_maps;
|
||||
/* minimal type index of the type equal to this type,
|
||||
used in type equal check in call_indirect opcode */
|
||||
uint32 min_type_idx_normalized;
|
||||
#else
|
||||
uint16 ref_count;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
|
||||
/* Quick AOT/JIT entry of this func type */
|
||||
void *quick_aot_entry;
|
||||
#endif
|
||||
/* types of params and results */
|
||||
|
||||
/* types of params and results, only store the first byte
|
||||
* of the type, if it cannot be described with one byte,
|
||||
* then the full type info is stored in ref_type_maps */
|
||||
uint8 types[1];
|
||||
} WASMType;
|
||||
} WASMFuncType;
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
typedef struct WASMStructFieldType {
|
||||
uint16 field_flags;
|
||||
uint8 field_type;
|
||||
uint8 field_size;
|
||||
uint32 field_offset;
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
|
||||
/*
|
||||
* The field size and field offset of a wasm struct may vary
|
||||
* in 32-bit target and 64-bit target, e.g., the size of a
|
||||
* GC reference is 4 bytes in the former and 8 bytes in the
|
||||
* latter, the AOT compiler needs to use the correct field
|
||||
* offset according to the target info.
|
||||
*/
|
||||
uint8 field_size_64bit;
|
||||
uint8 field_size_32bit;
|
||||
uint32 field_offset_64bit;
|
||||
uint32 field_offset_32bit;
|
||||
#endif
|
||||
} WASMStructFieldType;
|
||||
|
||||
typedef struct WASMStructType {
|
||||
WASMType base_type;
|
||||
|
||||
/* total size of this struct object */
|
||||
uint32 total_size;
|
||||
uint16 field_count;
|
||||
|
||||
uint16 ref_type_map_count;
|
||||
WASMRefTypeMap *ref_type_maps;
|
||||
|
||||
/* Offsets of reference fields that need to be traced during GC.
|
||||
The first element of the table is the number of such offsets. */
|
||||
uint16 *reference_table;
|
||||
|
||||
/* Field info, note that fields[i]->field_type only stores
|
||||
* the first byte of the field type, if it cannot be described
|
||||
* with one byte, then the full field type info is stored in
|
||||
* ref_type_maps */
|
||||
WASMStructFieldType fields[1];
|
||||
} WASMStructType;
|
||||
|
||||
typedef struct WASMArrayType {
|
||||
WASMType base_type;
|
||||
|
||||
uint16 elem_flags;
|
||||
uint8 elem_type;
|
||||
/* The full elem type info if the elem type cannot be
|
||||
described with one byte */
|
||||
WASMRefType *elem_ref_type;
|
||||
} WASMArrayType;
|
||||
|
||||
#if WASM_ENABLE_STRINGREF != 0
|
||||
/* stringref representation, we define it as a void * pointer here, the
|
||||
* stringref implementation can use any structure */
|
||||
/*
|
||||
WasmGC heap
|
||||
+-----------------------+
|
||||
| |
|
||||
| stringref |
|
||||
| +----------+ | external string representation
|
||||
| | host_ptr |--------o------+----->+------------+
|
||||
| +----------+ | | | |
|
||||
| | | +------------+
|
||||
| stringview_wtf8/16 | |
|
||||
| +----------+ | |
|
||||
| | host_ptr |--------o------+
|
||||
| +----------+ | |
|
||||
| | |
|
||||
| stringview_iter | |
|
||||
| +----------+ | |
|
||||
| | host_ptr |--------o------+
|
||||
| +----------+ |
|
||||
| | pos | |
|
||||
| +----------+ |
|
||||
| |
|
||||
+-----------------------+
|
||||
*/
|
||||
typedef void *WASMString;
|
||||
|
||||
#endif /* end of WASM_ENABLE_STRINGREF != 0 */
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
||||
typedef struct WASMTable {
|
||||
uint8 elem_type;
|
||||
uint32 flags;
|
||||
/**
|
||||
* 0: no max size and not shared
|
||||
* 1: hax max size
|
||||
* 2: shared
|
||||
*/
|
||||
uint8 flags;
|
||||
bool possible_grow;
|
||||
uint32 init_size;
|
||||
/* specified if (flags & 1), else it is 0x10000 */
|
||||
uint32 max_size;
|
||||
bool possible_grow;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *elem_ref_type;
|
||||
/* init expr for the whole table */
|
||||
InitializerExpression init_expr;
|
||||
#endif
|
||||
} WASMTable;
|
||||
|
||||
typedef struct WASMMemory {
|
||||
@ -174,12 +491,16 @@ typedef struct WASMMemory {
|
||||
typedef struct WASMTableImport {
|
||||
char *module_name;
|
||||
char *field_name;
|
||||
/* 0: no max size, 1: has max size */
|
||||
uint8 elem_type;
|
||||
uint32 flags;
|
||||
uint8 flags;
|
||||
bool possible_grow;
|
||||
uint32 init_size;
|
||||
/* specified if (flags & 1), else it is 0x10000 */
|
||||
uint32 max_size;
|
||||
bool possible_grow;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *elem_ref_type;
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *import_module;
|
||||
WASMTable *import_table_linked;
|
||||
@ -203,19 +524,23 @@ typedef struct WASMFunctionImport {
|
||||
char *module_name;
|
||||
char *field_name;
|
||||
/* function type */
|
||||
WASMType *func_type;
|
||||
WASMFuncType *func_type;
|
||||
/* native function pointer after linked */
|
||||
void *func_ptr_linked;
|
||||
/* signature from registered native symbols */
|
||||
const char *signature;
|
||||
/* attachment */
|
||||
void *attachment;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* the type index of this function's func_type */
|
||||
uint32 type_idx;
|
||||
#endif
|
||||
bool call_conv_raw;
|
||||
bool call_conv_wasm_c_api;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *import_module;
|
||||
WASMFunction *import_func_linked;
|
||||
#endif
|
||||
bool call_conv_wasm_c_api;
|
||||
} WASMFunctionImport;
|
||||
|
||||
#if WASM_ENABLE_TAGS != 0
|
||||
@ -241,9 +566,12 @@ typedef struct WASMGlobalImport {
|
||||
char *field_name;
|
||||
uint8 type;
|
||||
bool is_mutable;
|
||||
bool is_linked;
|
||||
/* global data after linked */
|
||||
WASMValue global_data_linked;
|
||||
bool is_linked;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *ref_type;
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* imported function pointer after linked */
|
||||
/* TODO: remove if not needed */
|
||||
@ -278,9 +606,13 @@ struct WASMFunction {
|
||||
char *field_name;
|
||||
#endif
|
||||
/* the type of function */
|
||||
WASMType *func_type;
|
||||
WASMFuncType *func_type;
|
||||
uint32 local_count;
|
||||
uint8 *local_types;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint16 local_ref_type_map_count;
|
||||
WASMRefTypeMap *local_ref_type_maps;
|
||||
#endif
|
||||
|
||||
/* cell num of parameters */
|
||||
uint16 param_cell_num;
|
||||
@ -303,6 +635,11 @@ struct WASMFunction {
|
||||
uint32 const_cell_num;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* the type index of this function's func_type */
|
||||
uint32 type_idx;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||
uint32 exception_handler_count;
|
||||
#endif
|
||||
@ -347,6 +684,9 @@ struct WASMTag {
|
||||
struct WASMGlobal {
|
||||
uint8 type;
|
||||
bool is_mutable;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *ref_type;
|
||||
#endif
|
||||
InitializerExpression init_expr;
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
/* The data offset of current global in global data */
|
||||
@ -365,11 +705,14 @@ typedef struct WASMTableSeg {
|
||||
uint32 mode;
|
||||
/* funcref or externref, elemkind will be considered as funcref */
|
||||
uint32 elem_type;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *elem_ref_type;
|
||||
#endif
|
||||
/* optional, only for active */
|
||||
uint32 table_index;
|
||||
InitializerExpression base_offset;
|
||||
uint32 function_count;
|
||||
uint32 *func_indexes;
|
||||
uint32 value_count;
|
||||
InitializerExpression *init_values;
|
||||
} WASMTableSeg;
|
||||
|
||||
typedef struct WASMDataSeg {
|
||||
@ -481,6 +824,13 @@ struct WASMModule {
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
/* data count read from datacount section */
|
||||
uint32 data_seg_count1;
|
||||
#endif
|
||||
#if WASM_ENABLE_GC != 0
|
||||
#if WASM_ENABLE_STRINGREF != 0
|
||||
uint32 string_literal_count;
|
||||
uint32 *string_literal_lengths;
|
||||
const uint8 **string_literal_ptrs;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32 import_function_count;
|
||||
@ -564,13 +914,31 @@ struct WASMModule {
|
||||
bh_list import_module_list_head;
|
||||
bh_list *import_module_list;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* Ref types hash set */
|
||||
HashMap *ref_type_set;
|
||||
struct WASMRttType **rtt_types;
|
||||
korp_mutex rtt_type_lock;
|
||||
#if WASM_ENABLE_STRINGREF != 0
|
||||
/* special rtts for stringref types
|
||||
- stringref
|
||||
- stringview_wtf8
|
||||
- stringview_wtf16
|
||||
- stringview_iter
|
||||
*/
|
||||
struct WASMRttType *stringref_rtts[4];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0
|
||||
bh_list fast_opcode_list;
|
||||
uint8 *buf_code;
|
||||
uint64 buf_code_size;
|
||||
#endif
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0 \
|
||||
|| WASM_ENABLE_FAST_JIT != 0
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_FAST_JIT != 0 \
|
||||
|| WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_JIT != 0
|
||||
uint8 *load_addr;
|
||||
uint64 load_size;
|
||||
#endif
|
||||
@ -671,6 +1039,12 @@ struct WASMModule {
|
||||
functions in that group */
|
||||
uint32 fast_jit_ready_groups;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||
bool is_simd_used;
|
||||
bool is_ref_types_used;
|
||||
bool is_bulk_memory_used;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct BlockType {
|
||||
@ -679,8 +1053,13 @@ typedef struct BlockType {
|
||||
* by a type index of module.
|
||||
*/
|
||||
union {
|
||||
uint8 value_type;
|
||||
WASMType *type;
|
||||
struct {
|
||||
uint8 type;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefTypeMap ref_type_map;
|
||||
#endif
|
||||
} value_type;
|
||||
WASMFuncType *type;
|
||||
} u;
|
||||
bool is_value_type;
|
||||
} BlockType;
|
||||
@ -755,33 +1134,72 @@ wasm_string_equal(const char *s1, const char *s2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the byte size of value type.
|
||||
* Return the byte size of value type with specific pointer size.
|
||||
*
|
||||
* Note: Please use wasm_value_type_size for interpreter, only aot compiler
|
||||
* can use this API directly to calculate type size for different target
|
||||
*/
|
||||
inline static uint32
|
||||
wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
|
||||
{
|
||||
if (value_type == VALUE_TYPE_VOID)
|
||||
return 0;
|
||||
else if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_F32
|
||||
|| value_type == VALUE_TYPE_ANY)
|
||||
return sizeof(int32);
|
||||
else if (value_type == VALUE_TYPE_I64 || value_type == VALUE_TYPE_F64)
|
||||
return sizeof(int64);
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
else if (value_type == VALUE_TYPE_V128)
|
||||
return sizeof(int64) * 2;
|
||||
#endif
|
||||
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
|
||||
else if (value_type == VALUE_TYPE_FUNCREF
|
||||
|| value_type == VALUE_TYPE_EXTERNREF)
|
||||
return sizeof(uint32);
|
||||
#elif WASM_ENABLE_GC != 0
|
||||
else if ((value_type >= (uint8)REF_TYPE_ARRAYREF /* 0x6A */
|
||||
&& value_type <= (uint8)REF_TYPE_NULLFUNCREF) /* 0x73 */
|
||||
|| (value_type >= (uint8)REF_TYPE_HT_NULLABLE /* 0x63 */
|
||||
&& value_type <= (uint8)REF_TYPE_HT_NON_NULLABLE) /* 0x64 */
|
||||
#if WASM_ENABLE_STRINGREF != 0
|
||||
|| (value_type >= (uint8)REF_TYPE_STRINGVIEWWTF8 /* 0x66 */
|
||||
&& value_type <= (uint8)REF_TYPE_STRINGREF) /* 0x67 */
|
||||
|| (value_type >= (uint8)REF_TYPE_STRINGVIEWITER /* 0x61 */
|
||||
&& value_type <= (uint8)REF_TYPE_STRINGVIEWWTF16) /* 0x62 */
|
||||
#endif
|
||||
)
|
||||
return pointer_size;
|
||||
else if (value_type == PACKED_TYPE_I8)
|
||||
return sizeof(int8);
|
||||
else if (value_type == PACKED_TYPE_I16)
|
||||
return sizeof(int16);
|
||||
#endif
|
||||
else {
|
||||
bh_assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cell num of value type with specific pointer size.
|
||||
*
|
||||
* Note: Please use wasm_value_type_cell_num for interpreter, only aot compiler
|
||||
* can use this API directly to calculate type cell num for different target
|
||||
*/
|
||||
inline static uint16
|
||||
wasm_value_type_cell_num_internal(uint8 value_type, uint8 pointer_size)
|
||||
{
|
||||
return wasm_value_type_size_internal(value_type, pointer_size) / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the byte size of value type.
|
||||
*/
|
||||
inline static uint32
|
||||
wasm_value_type_size(uint8 value_type)
|
||||
{
|
||||
switch (value_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
return sizeof(int32);
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
return sizeof(int64);
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
case VALUE_TYPE_V128:
|
||||
return sizeof(int64) * 2;
|
||||
#endif
|
||||
case VALUE_TYPE_VOID:
|
||||
return 0;
|
||||
default:
|
||||
bh_assert(0);
|
||||
}
|
||||
return 0;
|
||||
return wasm_value_type_size_internal(value_type, sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
inline static uint16
|
||||
@ -813,70 +1231,152 @@ wasm_value_type_cell_num_outside(uint8 value_type)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
inline static bool
|
||||
wasm_type_equal(const WASMType *type1, const WASMType *type2)
|
||||
wasm_type_equal(const WASMType *type1, const WASMType *type2,
|
||||
const WASMTypePtr *types, uint32 type_count)
|
||||
{
|
||||
const WASMFuncType *func_type1 = (const WASMFuncType *)type1;
|
||||
const WASMFuncType *func_type2 = (const WASMFuncType *)type2;
|
||||
|
||||
if (type1 == type2) {
|
||||
return true;
|
||||
}
|
||||
return (type1->param_count == type2->param_count
|
||||
&& type1->result_count == type2->result_count
|
||||
&& memcmp(type1->types, type2->types,
|
||||
(uint32)(type1->param_count + type1->result_count))
|
||||
|
||||
return (func_type1->param_count == func_type2->param_count
|
||||
&& func_type1->result_count == func_type2->result_count
|
||||
&& memcmp(
|
||||
func_type1->types, func_type2->types,
|
||||
(uint32)(func_type1->param_count + func_type1->result_count))
|
||||
== 0)
|
||||
? true
|
||||
: false;
|
||||
(void)types;
|
||||
(void)type_count;
|
||||
}
|
||||
#else
|
||||
/* implemented in gc_type.c */
|
||||
bool
|
||||
wasm_type_equal(const WASMType *type1, const WASMType *type2,
|
||||
const WASMTypePtr *types, uint32 type_count);
|
||||
#endif
|
||||
|
||||
inline static uint32
|
||||
wasm_get_smallest_type_idx(WASMType **types, uint32 type_count,
|
||||
wasm_get_smallest_type_idx(const WASMTypePtr *types, uint32 type_count,
|
||||
uint32 cur_type_idx)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < cur_type_idx; i++) {
|
||||
if (wasm_type_equal(types[cur_type_idx], types[i]))
|
||||
if (wasm_type_equal(types[cur_type_idx], types[i], types, type_count))
|
||||
return i;
|
||||
}
|
||||
(void)type_count;
|
||||
return cur_type_idx;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
static inline uint32
|
||||
block_type_get_param_types(BlockType *block_type, uint8 **p_param_types)
|
||||
#else
|
||||
static inline uint32
|
||||
block_type_get_param_types(BlockType *block_type, uint8 **p_param_types,
|
||||
WASMRefTypeMap **p_param_reftype_maps,
|
||||
uint32 *p_param_reftype_map_count)
|
||||
#endif
|
||||
{
|
||||
uint32 param_count = 0;
|
||||
if (!block_type->is_value_type) {
|
||||
WASMType *wasm_type = block_type->u.type;
|
||||
*p_param_types = wasm_type->types;
|
||||
param_count = wasm_type->param_count;
|
||||
WASMFuncType *func_type = block_type->u.type;
|
||||
*p_param_types = func_type->types;
|
||||
param_count = func_type->param_count;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
*p_param_reftype_maps = func_type->ref_type_maps;
|
||||
*p_param_reftype_map_count =
|
||||
func_type->result_ref_type_maps - func_type->ref_type_maps;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*p_param_types = NULL;
|
||||
param_count = 0;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
*p_param_reftype_maps = NULL;
|
||||
*p_param_reftype_map_count = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return param_count;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
static inline uint32
|
||||
block_type_get_result_types(BlockType *block_type, uint8 **p_result_types)
|
||||
#else
|
||||
static inline uint32
|
||||
block_type_get_result_types(BlockType *block_type, uint8 **p_result_types,
|
||||
WASMRefTypeMap **p_result_reftype_maps,
|
||||
uint32 *p_result_reftype_map_count)
|
||||
#endif
|
||||
{
|
||||
uint32 result_count = 0;
|
||||
uint8 *result_types = NULL;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint8 type;
|
||||
uint32 result_reftype_map_count = 0;
|
||||
WASMRefTypeMap *result_reftype_maps = NULL;
|
||||
#endif
|
||||
|
||||
if (block_type->is_value_type) {
|
||||
if (block_type->u.value_type != VALUE_TYPE_VOID) {
|
||||
*p_result_types = &block_type->u.value_type;
|
||||
if (block_type->u.value_type.type != VALUE_TYPE_VOID) {
|
||||
result_types = &block_type->u.value_type.type;
|
||||
result_count = 1;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
type = block_type->u.value_type.type;
|
||||
if (type == (uint8)REF_TYPE_HT_NULLABLE
|
||||
|| type == (uint8)REF_TYPE_HT_NON_NULLABLE) {
|
||||
result_reftype_maps = &block_type->u.value_type.ref_type_map;
|
||||
result_reftype_map_count = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
WASMType *wasm_type = block_type->u.type;
|
||||
*p_result_types = wasm_type->types + wasm_type->param_count;
|
||||
result_count = wasm_type->result_count;
|
||||
WASMFuncType *func_type = block_type->u.type;
|
||||
result_types = func_type->types + func_type->param_count;
|
||||
result_count = func_type->result_count;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
result_reftype_maps = func_type->result_ref_type_maps;
|
||||
result_reftype_map_count = (uint32)(func_type->ref_type_map_count
|
||||
- (func_type->result_ref_type_maps
|
||||
- func_type->ref_type_maps));
|
||||
#endif
|
||||
}
|
||||
*p_result_types = result_types;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
*p_result_reftype_maps = result_reftype_maps;
|
||||
*p_result_reftype_map_count = result_reftype_map_count;
|
||||
#endif
|
||||
return result_count;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
block_type_get_arity(const BlockType *block_type, uint8 label_type)
|
||||
{
|
||||
if (label_type == LABEL_TYPE_LOOP) {
|
||||
if (block_type->is_value_type)
|
||||
return 0;
|
||||
else
|
||||
return block_type->u.type->param_count;
|
||||
}
|
||||
else {
|
||||
if (block_type->is_value_type) {
|
||||
return block_type->u.value_type.type != VALUE_TYPE_VOID ? 1 : 0;
|
||||
}
|
||||
else
|
||||
return block_type->u.type->result_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
@ -47,8 +47,11 @@ typedef struct WASMInterpFrame {
|
||||
the callee will put return values here continuously */
|
||||
uint32 ret_offset;
|
||||
uint32 *lp;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint8 *frame_ref;
|
||||
#endif
|
||||
uint32 operand[1];
|
||||
#else
|
||||
#else /* else of WASM_ENABLE_FAST_INTERP != 0 */
|
||||
/* Operand stack top pointer of the current frame. The bottom of
|
||||
the stack is the next cell after the last local variable. */
|
||||
uint32 *sp_bottom;
|
||||
@ -64,10 +67,12 @@ typedef struct WASMInterpFrame {
|
||||
* lp: parameters and local variables
|
||||
* sp_bottom to sp_boundary: wasm operand stack
|
||||
* csp_bottom to csp_boundary: wasm label stack
|
||||
* frame ref flags: only available for GC
|
||||
* whether each cell in local and stack area is a GC obj
|
||||
* jit spill cache: only available for fast jit
|
||||
*/
|
||||
uint32 lp[1];
|
||||
#endif
|
||||
#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */
|
||||
} WASMInterpFrame;
|
||||
|
||||
/**
|
||||
@ -84,7 +89,12 @@ wasm_interp_interp_frame_size(unsigned all_cell_num)
|
||||
unsigned frame_size;
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP == 0
|
||||
#if WASM_ENABLE_GC == 0
|
||||
frame_size = (uint32)offsetof(WASMInterpFrame, lp) + all_cell_num * 4;
|
||||
#else
|
||||
frame_size =
|
||||
(uint32)offsetof(WASMInterpFrame, lp) + align_uint(all_cell_num * 5, 4);
|
||||
#endif
|
||||
#else
|
||||
frame_size = (uint32)offsetof(WASMInterpFrame, operand) + all_cell_num * 4;
|
||||
#endif
|
||||
@ -97,6 +107,14 @@ wasm_interp_call_wasm(struct WASMModuleInstance *module_inst,
|
||||
struct WASMFunctionInstance *function, uint32 argc,
|
||||
uint32 argv[]);
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
bool
|
||||
wasm_interp_traverse_gc_rootset(struct WASMExecEnv *exec_env, void *heap);
|
||||
|
||||
uint8 *
|
||||
wasm_interp_get_frame_ref(WASMInterpFrame *frame);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -194,6 +194,29 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void *
|
||||
memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
uint8 *mem_new;
|
||||
bh_assert(size_new > size_old);
|
||||
if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
|
||||
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
||||
memset(mem_new + size_old, 0, size_new - size_old);
|
||||
wasm_runtime_free(mem_old);
|
||||
}
|
||||
return mem_new;
|
||||
}
|
||||
|
||||
#define MEM_REALLOC(mem, size_old, size_new) \
|
||||
do { \
|
||||
void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \
|
||||
error_buf_size); \
|
||||
if (!mem_new) \
|
||||
goto fail; \
|
||||
mem = mem_new; \
|
||||
} while (0)
|
||||
|
||||
static char *
|
||||
const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
|
||||
bool is_load_from_file_buf, char *error_buf,
|
||||
@ -252,7 +275,7 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_wasm_type(WASMType *type)
|
||||
destroy_wasm_type(WASMFuncType *type)
|
||||
{
|
||||
if (type->ref_count > 1) {
|
||||
/* The type is referenced by other types
|
||||
@ -271,80 +294,256 @@ destroy_wasm_type(WASMType *type)
|
||||
}
|
||||
|
||||
static bool
|
||||
load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
|
||||
check_function_index(const WASMModule *module, uint32 function_index,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
return (function_index
|
||||
< module->import_function_count + module->function_count);
|
||||
}
|
||||
|
||||
typedef struct InitValue {
|
||||
uint8 type;
|
||||
uint8 flag;
|
||||
WASMValue value;
|
||||
} InitValue;
|
||||
|
||||
typedef struct ConstExprContext {
|
||||
uint32 sp;
|
||||
uint32 size;
|
||||
WASMModule *module;
|
||||
InitValue *stack;
|
||||
InitValue data[WASM_CONST_EXPR_STACK_SIZE];
|
||||
} ConstExprContext;
|
||||
|
||||
static void
|
||||
init_const_expr_stack(ConstExprContext *ctx, WASMModule *module)
|
||||
{
|
||||
ctx->sp = 0;
|
||||
ctx->module = module;
|
||||
ctx->stack = ctx->data;
|
||||
ctx->size = WASM_CONST_EXPR_STACK_SIZE;
|
||||
}
|
||||
|
||||
static bool
|
||||
push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
|
||||
WASMValue *value, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
InitValue *cur_value;
|
||||
|
||||
if (ctx->sp >= ctx->size) {
|
||||
if (ctx->stack != ctx->data) {
|
||||
MEM_REALLOC(ctx->stack, ctx->size * sizeof(InitValue),
|
||||
(ctx->size + 4) * sizeof(InitValue));
|
||||
}
|
||||
else {
|
||||
if (!(ctx->stack =
|
||||
loader_malloc((ctx->size + 4) * (uint64)sizeof(InitValue),
|
||||
error_buf, error_buf_size))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ctx->size += 4;
|
||||
}
|
||||
|
||||
cur_value = &ctx->stack[ctx->sp++];
|
||||
cur_value->type = type;
|
||||
cur_value->flag = flag;
|
||||
cur_value->value = *value;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
|
||||
WASMValue *p_value, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
InitValue *cur_value;
|
||||
|
||||
if (ctx->sp == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_value = &ctx->stack[--ctx->sp];
|
||||
|
||||
if (cur_value->type != type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_flag)
|
||||
*p_flag = cur_value->flag;
|
||||
if (p_value)
|
||||
*p_value = cur_value->value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_const_expr_stack(ConstExprContext *ctx)
|
||||
{
|
||||
if (ctx->stack != ctx->data) {
|
||||
wasm_runtime_free(ctx->stack);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||
InitializerExpression *init_expr, uint8 type, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||
uint8 flag, end_byte, *p_float;
|
||||
uint8 flag, *p_float;
|
||||
uint32 i;
|
||||
ConstExprContext const_expr_ctx = { 0 };
|
||||
WASMValue cur_value = { 0 };
|
||||
|
||||
init_const_expr_stack(&const_expr_ctx, module);
|
||||
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
init_expr->init_expr_type = read_uint8(p);
|
||||
flag = init_expr->init_expr_type;
|
||||
flag = read_uint8(p);
|
||||
|
||||
while (flag != WASM_OP_END) {
|
||||
switch (flag) {
|
||||
/* i32.const */
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
read_leb_int32(p, p_end, cur_value.i32);
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_I32, &cur_value,
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
break;
|
||||
/* i64.const */
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
read_leb_int64(p, p_end, cur_value.i64);
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_I64, &cur_value,
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
break;
|
||||
/* f32.const */
|
||||
case INIT_EXPR_TYPE_F32_CONST:
|
||||
CHECK_BUF(p, p_end, 4);
|
||||
p_float = (uint8 *)&cur_value.f32;
|
||||
for (i = 0; i < sizeof(float32); i++)
|
||||
*p_float++ = *p++;
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_F32, &cur_value,
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
break;
|
||||
/* f64.const */
|
||||
case INIT_EXPR_TYPE_F64_CONST:
|
||||
CHECK_BUF(p, p_end, 8);
|
||||
p_float = (uint8 *)&cur_value.f64;
|
||||
for (i = 0; i < sizeof(float64); i++)
|
||||
*p_float++ = *p++;
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_F64, &cur_value,
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
break;
|
||||
|
||||
switch (flag) {
|
||||
/* i32.const */
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
bh_assert(type == VALUE_TYPE_I32);
|
||||
read_leb_int32(p, p_end, init_expr->u.i32);
|
||||
break;
|
||||
/* i64.const */
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
bh_assert(type == VALUE_TYPE_I64);
|
||||
read_leb_int64(p, p_end, init_expr->u.i64);
|
||||
break;
|
||||
/* f32.const */
|
||||
case INIT_EXPR_TYPE_F32_CONST:
|
||||
bh_assert(type == VALUE_TYPE_F32);
|
||||
CHECK_BUF(p, p_end, 4);
|
||||
p_float = (uint8 *)&init_expr->u.f32;
|
||||
for (i = 0; i < sizeof(float32); i++)
|
||||
*p_float++ = *p++;
|
||||
break;
|
||||
/* f64.const */
|
||||
case INIT_EXPR_TYPE_F64_CONST:
|
||||
bh_assert(type == VALUE_TYPE_F64);
|
||||
CHECK_BUF(p, p_end, 8);
|
||||
p_float = (uint8 *)&init_expr->u.f64;
|
||||
for (i = 0; i < sizeof(float64); i++)
|
||||
*p_float++ = *p++;
|
||||
break;
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
{
|
||||
bh_assert(type == VALUE_TYPE_FUNCREF);
|
||||
read_leb_uint32(p, p_end, init_expr->u.ref_index);
|
||||
break;
|
||||
/* ref.func */
|
||||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
{
|
||||
uint32 func_idx;
|
||||
read_leb_uint32(p, p_end, func_idx);
|
||||
cur_value.ref_index = func_idx;
|
||||
if (!check_function_index(module, func_idx, error_buf,
|
||||
error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_FUNCREF, &cur_value,
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* ref.null */
|
||||
case INIT_EXPR_TYPE_REFNULL_CONST:
|
||||
{
|
||||
uint8 type1;
|
||||
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
type1 = read_uint8(p);
|
||||
|
||||
cur_value.ref_index = UINT32_MAX;
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
|
||||
&cur_value, error_buf,
|
||||
error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_REF_TYPES != 0 */
|
||||
|
||||
/* get_global */
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
{
|
||||
uint32 global_idx;
|
||||
uint8 global_type;
|
||||
|
||||
read_leb_uint32(p, p_end, cur_value.global_index);
|
||||
global_idx = cur_value.global_index;
|
||||
|
||||
bh_assert(global_idx < module->import_global_count);
|
||||
bh_assert(
|
||||
!module->import_globals[global_idx].u.global.is_mutable);
|
||||
|
||||
if (global_idx < module->import_global_count) {
|
||||
global_type =
|
||||
module->import_globals[global_idx].u.global.type;
|
||||
}
|
||||
else {
|
||||
global_type =
|
||||
module
|
||||
->globals[global_idx - module->import_global_count]
|
||||
.type;
|
||||
}
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, global_type,
|
||||
&cur_value, error_buf,
|
||||
error_buf_size))
|
||||
bh_assert(0);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
}
|
||||
}
|
||||
case INIT_EXPR_TYPE_REFNULL_CONST:
|
||||
{
|
||||
uint8 reftype;
|
||||
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
reftype = read_uint8(p);
|
||||
|
||||
bh_assert(type == reftype);
|
||||
|
||||
init_expr->u.ref_index = NULL_REF;
|
||||
(void)reftype;
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
||||
/* get_global */
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
read_leb_uint32(p, p_end, init_expr->u.global_index);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
flag = read_uint8(p);
|
||||
}
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
end_byte = read_uint8(p);
|
||||
bh_assert(end_byte == 0x0b);
|
||||
*p_buf = p;
|
||||
|
||||
(void)end_byte;
|
||||
/* There should be only one value left on the init value stack */
|
||||
if (!pop_const_expr_stack(&const_expr_ctx, &flag, type, &cur_value,
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
}
|
||||
|
||||
bh_assert(const_expr_ctx.sp == 0);
|
||||
|
||||
init_expr->init_expr_type = flag;
|
||||
init_expr->u = cur_value;
|
||||
|
||||
*p_buf = p;
|
||||
destroy_const_expr_stack(&const_expr_ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -357,13 +556,13 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
uint32 param_cell_num, ret_cell_num;
|
||||
uint64 total_size;
|
||||
uint8 flag;
|
||||
WASMType *type;
|
||||
WASMFuncType *type;
|
||||
|
||||
read_leb_uint32(p, p_end, type_count);
|
||||
|
||||
if (type_count) {
|
||||
module->type_count = type_count;
|
||||
total_size = sizeof(WASMType *) * (uint64)type_count;
|
||||
total_size = sizeof(WASMFuncType *) * (uint64)type_count;
|
||||
if (!(module->types =
|
||||
loader_malloc(total_size, error_buf, error_buf_size))) {
|
||||
return false;
|
||||
@ -386,7 +585,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
|
||||
bh_assert(param_count <= UINT16_MAX && result_count <= UINT16_MAX);
|
||||
|
||||
total_size = offsetof(WASMType, types)
|
||||
total_size = offsetof(WASMFuncType, types)
|
||||
+ sizeof(uint8) * (uint64)(param_count + result_count);
|
||||
if (!(type = module->types[i] =
|
||||
loader_malloc(total_size, error_buf, error_buf_size))) {
|
||||
@ -424,7 +623,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
|
||||
/* If there is already a same type created, use it instead */
|
||||
for (j = 0; j < i; ++j) {
|
||||
if (wasm_type_equal(type, module->types[j])) {
|
||||
if (wasm_type_equal(type, module->types[j], module->types, i)) {
|
||||
bh_assert(module->types[j]->ref_count != UINT16_MAX);
|
||||
destroy_wasm_type(type);
|
||||
module->types[i] = module->types[j];
|
||||
@ -444,8 +643,9 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
static void
|
||||
adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size)
|
||||
{
|
||||
uint32 default_max_size =
|
||||
init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE;
|
||||
uint32 default_max_size = init_size * 2 > WASM_TABLE_MAX_SIZE
|
||||
? init_size * 2
|
||||
: WASM_TABLE_MAX_SIZE;
|
||||
|
||||
if (max_size_flag) {
|
||||
/* module defines the table limitation */
|
||||
@ -471,7 +671,7 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||
{
|
||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||
uint32 declare_type_index = 0;
|
||||
WASMType *declare_func_type = NULL;
|
||||
WASMFuncType *declare_func_type = NULL;
|
||||
WASMFunction *linked_func = NULL;
|
||||
const char *linked_signature = NULL;
|
||||
void *linked_attachment = NULL;
|
||||
@ -911,7 +1111,7 @@ static bool
|
||||
init_function_local_offsets(WASMFunction *func, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
WASMType *param_type = func->func_type;
|
||||
WASMFuncType *param_type = func->func_type;
|
||||
uint32 param_count = param_type->param_count;
|
||||
uint8 *param_types = param_type->types;
|
||||
uint32 local_count = func->local_count;
|
||||
@ -1065,14 +1265,6 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_function_index(const WASMModule *module, uint32 function_index,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
return (function_index
|
||||
< module->import_function_count + module->function_count);
|
||||
}
|
||||
|
||||
static bool
|
||||
load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
@ -1151,8 +1343,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
|
||||
read_leb_uint32(p, p_end, global_count);
|
||||
|
||||
module->global_count = 0;
|
||||
if (global_count) {
|
||||
module->global_count = global_count;
|
||||
total_size = sizeof(WASMGlobal) * (uint64)global_count;
|
||||
if (!(module->globals =
|
||||
loader_malloc(total_size, error_buf, error_buf_size))) {
|
||||
@ -1169,8 +1361,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
global->is_mutable = mutable ? true : false;
|
||||
|
||||
/* initialize expression */
|
||||
if (!load_init_expr(&p, p_end, &(global->init_expr), global->type,
|
||||
error_buf, error_buf_size))
|
||||
if (!load_init_expr(module, &p, p_end, &(global->init_expr),
|
||||
global->type, error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
if (INIT_EXPR_TYPE_GET_GLOBAL == global->init_expr.init_expr_type) {
|
||||
@ -1190,7 +1382,10 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
< module->import_function_count
|
||||
+ module->function_count);
|
||||
}
|
||||
|
||||
module->global_count++;
|
||||
}
|
||||
bh_assert(module->global_count == global_count);
|
||||
}
|
||||
|
||||
bh_assert(p == p_end);
|
||||
@ -1341,52 +1536,78 @@ load_elem_type(const uint8 **p_buf, const uint8 *buf_end, uint32 *p_elem_type,
|
||||
static bool
|
||||
load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
|
||||
WASMModule *module, WASMTableSeg *table_segment,
|
||||
bool use_init_expr, char *error_buf, uint32 error_buf_size)
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||
uint32 function_count, function_index = 0, i;
|
||||
uint64 total_size;
|
||||
|
||||
read_leb_uint32(p, p_end, function_count);
|
||||
table_segment->function_count = function_count;
|
||||
total_size = sizeof(uint32) * (uint64)function_count;
|
||||
table_segment->value_count = function_count;
|
||||
total_size = sizeof(InitializerExpression) * (uint64)function_count;
|
||||
if (total_size > 0
|
||||
&& !(table_segment->func_indexes = (uint32 *)loader_malloc(
|
||||
total_size, error_buf, error_buf_size))) {
|
||||
&& !(table_segment->init_values =
|
||||
(InitializerExpression *)loader_malloc(total_size, error_buf,
|
||||
error_buf_size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < function_count; i++) {
|
||||
InitializerExpression init_expr = { 0 };
|
||||
InitializerExpression *init_expr = &table_segment->init_values[i];
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
if (!use_init_expr) {
|
||||
read_leb_uint32(p, p_end, function_index);
|
||||
}
|
||||
else {
|
||||
if (!load_init_expr(&p, p_end, &init_expr, table_segment->elem_type,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
function_index = init_expr.u.ref_index;
|
||||
}
|
||||
#else
|
||||
read_leb_uint32(p, p_end, function_index);
|
||||
#endif
|
||||
|
||||
/* since we are using -1 to indicate ref.null */
|
||||
if (init_expr.init_expr_type != INIT_EXPR_TYPE_REFNULL_CONST
|
||||
&& !check_function_index(module, function_index, error_buf,
|
||||
error_buf_size)) {
|
||||
if (!check_function_index(module, function_index, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
table_segment->func_indexes[i] = function_index;
|
||||
|
||||
init_expr->init_expr_type = INIT_EXPR_TYPE_FUNCREF_CONST;
|
||||
init_expr->u.ref_index = function_index;
|
||||
}
|
||||
|
||||
*p_buf = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
static bool
|
||||
load_init_expr_vec(const uint8 **p_buf, const uint8 *buf_end,
|
||||
WASMModule *module, WASMTableSeg *table_segment,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||
uint32 ref_count, i;
|
||||
uint64 total_size;
|
||||
|
||||
read_leb_uint32(p, p_end, ref_count);
|
||||
table_segment->value_count = ref_count;
|
||||
total_size = sizeof(InitializerExpression) * (uint64)ref_count;
|
||||
if (total_size > 0
|
||||
&& !(table_segment->init_values =
|
||||
(InitializerExpression *)loader_malloc(total_size, error_buf,
|
||||
error_buf_size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < ref_count; i++) {
|
||||
InitializerExpression *init_expr = &table_segment->init_values[i];
|
||||
|
||||
if (!load_init_expr(module, &p, p_end, init_expr,
|
||||
table_segment->elem_type, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
|
||||
bh_assert(
|
||||
(init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL)
|
||||
|| (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST)
|
||||
|| (init_expr->init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST));
|
||||
}
|
||||
|
||||
*p_buf = p;
|
||||
return true;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_REF_TYPES != 0 */
|
||||
|
||||
static bool
|
||||
load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||
WASMModule *module, char *error_buf,
|
||||
@ -1426,16 +1647,25 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
if (!load_init_expr(&p, p_end, &table_segment->base_offset,
|
||||
VALUE_TYPE_I32, error_buf,
|
||||
error_buf_size))
|
||||
if (!load_init_expr(
|
||||
module, &p, p_end, &table_segment->base_offset,
|
||||
VALUE_TYPE_I32, error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
if (!load_func_index_vec(&p, p_end, module, table_segment,
|
||||
table_segment->mode == 0 ? false
|
||||
: true,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
if (table_segment->mode == 0) {
|
||||
/* vec(funcidx) */
|
||||
if (!load_func_index_vec(&p, p_end, module,
|
||||
table_segment, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* vec(expr) */
|
||||
if (!load_init_expr_vec(&p, p_end, module,
|
||||
table_segment, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
/* elemkind + passive/declarative */
|
||||
case 1:
|
||||
@ -1443,8 +1673,9 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||
if (!load_elem_type(&p, p_end, &table_segment->elem_type,
|
||||
true, error_buf, error_buf_size))
|
||||
return false;
|
||||
/* vec(funcidx) */
|
||||
if (!load_func_index_vec(&p, p_end, module, table_segment,
|
||||
false, error_buf, error_buf_size))
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
break;
|
||||
/* elemkind/elemtype + table_idx + active */
|
||||
@ -1454,27 +1685,37 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||
&table_segment->table_index,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
if (!load_init_expr(&p, p_end, &table_segment->base_offset,
|
||||
VALUE_TYPE_I32, error_buf,
|
||||
error_buf_size))
|
||||
if (!load_init_expr(
|
||||
module, &p, p_end, &table_segment->base_offset,
|
||||
VALUE_TYPE_I32, error_buf, error_buf_size))
|
||||
return false;
|
||||
if (!load_elem_type(&p, p_end, &table_segment->elem_type,
|
||||
table_segment->mode == 2 ? true : false,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
if (!load_func_index_vec(&p, p_end, module, table_segment,
|
||||
table_segment->mode == 2 ? false
|
||||
: true,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
if (table_segment->mode == 2) {
|
||||
/* vec(funcidx) */
|
||||
if (!load_func_index_vec(&p, p_end, module,
|
||||
table_segment, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* vec(expr) */
|
||||
if (!load_init_expr_vec(&p, p_end, module,
|
||||
table_segment, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
if (!load_elem_type(&p, p_end, &table_segment->elem_type,
|
||||
false, error_buf, error_buf_size))
|
||||
return false;
|
||||
if (!load_func_index_vec(&p, p_end, module, table_segment,
|
||||
true, error_buf, error_buf_size))
|
||||
/* vec(expr) */
|
||||
if (!load_init_expr_vec(&p, p_end, module, table_segment,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
@ -1489,10 +1730,10 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||
&table_segment->table_index, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
if (!load_init_expr(&p, p_end, &table_segment->base_offset,
|
||||
if (!load_init_expr(module, &p, p_end, &table_segment->base_offset,
|
||||
VALUE_TYPE_I32, error_buf, error_buf_size))
|
||||
return false;
|
||||
if (!load_func_index_vec(&p, p_end, module, table_segment, false,
|
||||
if (!load_func_index_vec(&p, p_end, module, table_segment,
|
||||
error_buf, error_buf_size))
|
||||
return false;
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
||||
@ -1569,8 +1810,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
if (!is_passive)
|
||||
#endif
|
||||
if (!load_init_expr(&p, p_end, &init_expr, VALUE_TYPE_I32,
|
||||
error_buf, error_buf_size))
|
||||
if (!load_init_expr(module, &p, p_end, &init_expr,
|
||||
VALUE_TYPE_I32, error_buf, error_buf_size))
|
||||
return false;
|
||||
|
||||
read_leb_uint32(p, p_end, data_seg_len);
|
||||
@ -1650,7 +1891,7 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
WASMType *type;
|
||||
WASMFuncType *type;
|
||||
uint32 start_function;
|
||||
|
||||
read_leb_uint32(p, p_end, start_function);
|
||||
@ -1843,6 +2084,7 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||
AOTCompOption option = { 0 };
|
||||
char *aot_last_error;
|
||||
uint64 size;
|
||||
bool gc_enabled = false; /* GC hasn't been enabled in mini loader */
|
||||
|
||||
if (module->function_count == 0)
|
||||
return true;
|
||||
@ -1869,7 +2111,7 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||
(bool *)((uint8 *)module->func_ptrs
|
||||
+ sizeof(void *) * module->function_count);
|
||||
|
||||
module->comp_data = aot_create_comp_data(module);
|
||||
module->comp_data = aot_create_comp_data(module, NULL, gc_enabled);
|
||||
if (!module->comp_data) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
@ -1900,10 +2142,15 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||
option.enable_ref_types = true;
|
||||
#endif
|
||||
option.enable_aux_stack_check = true;
|
||||
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||
#if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
|
||||
|| WASM_ENABLE_AOT_STACK_FRAME != 0
|
||||
option.enable_aux_stack_frame = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_PERF_PROFILING != 0
|
||||
option.enable_perf_profiling = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
option.enable_memory_profiling = true;
|
||||
option.enable_stack_estimation = true;
|
||||
#endif
|
||||
|
||||
@ -2299,7 +2546,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||
uint32 aux_stack_top = (uint32)-1, global_index, func_index, i;
|
||||
uint32 aux_data_end_global_index = (uint32)-1;
|
||||
uint32 aux_heap_base_global_index = (uint32)-1;
|
||||
WASMType *func_type;
|
||||
WASMFuncType *func_type;
|
||||
|
||||
/* Find code and function sections if have */
|
||||
while (section) {
|
||||
@ -2936,7 +3183,8 @@ wasm_loader_load(uint8 *buf, uint32 size, char *error_buf,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
|
||||
|| WASM_ENABLE_JIT != 0
|
||||
module->load_addr = (uint8 *)buf;
|
||||
module->load_size = size;
|
||||
#endif
|
||||
@ -3045,8 +3293,8 @@ wasm_loader_unload(WASMModule *module)
|
||||
|
||||
if (module->table_segments) {
|
||||
for (i = 0; i < module->table_seg_count; i++) {
|
||||
if (module->table_segments[i].func_indexes)
|
||||
wasm_runtime_free(module->table_segments[i].func_indexes);
|
||||
if (module->table_segments[i].init_values)
|
||||
wasm_runtime_free(module->table_segments[i].init_values);
|
||||
}
|
||||
wasm_runtime_free(module->table_segments);
|
||||
}
|
||||
@ -3689,29 +3937,6 @@ typedef struct Const {
|
||||
uint8 value_type;
|
||||
} Const;
|
||||
|
||||
static void *
|
||||
memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
uint8 *mem_new;
|
||||
bh_assert(size_new > size_old);
|
||||
if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
|
||||
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
||||
memset(mem_new + size_old, 0, size_new - size_old);
|
||||
wasm_runtime_free(mem_old);
|
||||
}
|
||||
return mem_new;
|
||||
}
|
||||
|
||||
#define MEM_REALLOC(mem, size_old, size_new) \
|
||||
do { \
|
||||
void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \
|
||||
error_buf_size); \
|
||||
if (!mem_new) \
|
||||
goto fail; \
|
||||
mem = mem_new; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_CSP_PUSH() \
|
||||
do { \
|
||||
if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
|
||||
@ -5393,7 +5618,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
|
||||
uint32 i;
|
||||
BranchBlock *block = loader_ctx->frame_csp - 1;
|
||||
BlockType *block_type = &block->block_type;
|
||||
WASMType *wasm_type = block_type->u.type;
|
||||
WASMFuncType *wasm_type = block_type->u.type;
|
||||
uint32 param_count = block_type->u.type->param_count;
|
||||
int16 condition_offset = 0;
|
||||
bool disable_emit = false;
|
||||
@ -5637,7 +5862,7 @@ re_scan:
|
||||
* 0x40/0x7F/0x7E/0x7D/0x7C, take it as the type of
|
||||
* the single return value. */
|
||||
block_type.is_value_type = true;
|
||||
block_type.u.value_type = value_type;
|
||||
block_type.u.value_type.type = value_type;
|
||||
}
|
||||
else {
|
||||
uint32 type_index;
|
||||
@ -5658,7 +5883,7 @@ re_scan:
|
||||
|
||||
/* Pop block parameters from stack */
|
||||
if (BLOCK_HAS_PARAM(block_type)) {
|
||||
WASMType *wasm_type = block_type.u.type;
|
||||
WASMFuncType *wasm_type = block_type.u.type;
|
||||
|
||||
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
@ -5861,19 +6086,11 @@ re_scan:
|
||||
uint32 block_param_count = 0, block_ret_count = 0;
|
||||
uint8 *block_param_types = NULL, *block_ret_types = NULL;
|
||||
BlockType *cur_block_type = &cur_block->block_type;
|
||||
if (cur_block_type->is_value_type) {
|
||||
if (cur_block_type->u.value_type != VALUE_TYPE_VOID) {
|
||||
block_ret_count = 1;
|
||||
block_ret_types = &cur_block_type->u.value_type;
|
||||
}
|
||||
}
|
||||
else {
|
||||
block_param_count = cur_block_type->u.type->param_count;
|
||||
block_ret_count = cur_block_type->u.type->result_count;
|
||||
block_param_types = cur_block_type->u.type->types;
|
||||
block_ret_types =
|
||||
cur_block_type->u.type->types + block_param_count;
|
||||
}
|
||||
|
||||
block_param_count = block_type_get_param_types(
|
||||
cur_block_type, &block_param_types);
|
||||
block_ret_count = block_type_get_result_types(
|
||||
cur_block_type, &block_ret_types);
|
||||
bh_assert(block_param_count == block_ret_count
|
||||
&& (!block_param_count
|
||||
|| !memcmp(block_param_types, block_ret_types,
|
||||
@ -5881,6 +6098,7 @@ re_scan:
|
||||
(void)block_ret_types;
|
||||
(void)block_ret_count;
|
||||
(void)block_param_types;
|
||||
(void)block_param_count;
|
||||
}
|
||||
|
||||
POP_CSP();
|
||||
@ -6043,7 +6261,7 @@ re_scan:
|
||||
case WASM_OP_RETURN_CALL:
|
||||
#endif
|
||||
{
|
||||
WASMType *func_type;
|
||||
WASMFuncType *func_type;
|
||||
uint32 func_idx;
|
||||
int32 idx;
|
||||
|
||||
@ -6115,7 +6333,7 @@ re_scan:
|
||||
#endif
|
||||
{
|
||||
int32 idx;
|
||||
WASMType *func_type;
|
||||
WASMFuncType *func_type;
|
||||
uint32 type_idx, table_idx;
|
||||
|
||||
bh_assert(module->import_table_count + module->table_count > 0);
|
||||
@ -6531,8 +6749,9 @@ re_scan:
|
||||
is passive, active or declarative. */
|
||||
for (i = 0; i < module->table_seg_count; i++, table_seg++) {
|
||||
if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
|
||||
for (j = 0; j < table_seg->function_count; j++) {
|
||||
if (table_seg->func_indexes[j] == func_idx) {
|
||||
for (j = 0; j < table_seg->value_count; j++) {
|
||||
if (table_seg->init_values[j].u.ref_index
|
||||
== func_idx) {
|
||||
func_declared = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -35,9 +35,9 @@ typedef enum WASMOpcode {
|
||||
WASM_OP_CALL_INDIRECT = 0x11, /* call_indirect */
|
||||
WASM_OP_RETURN_CALL = 0x12, /* return_call */
|
||||
WASM_OP_RETURN_CALL_INDIRECT = 0x13, /* return_call_indirect */
|
||||
WASM_OP_CALL_REF = 0x14, /* call_ref */
|
||||
WASM_OP_RETURN_CALL_REF = 0x15, /* return_call_ref */
|
||||
|
||||
WASM_OP_UNUSED_0x14 = 0x14,
|
||||
WASM_OP_UNUSED_0x15 = 0x15,
|
||||
WASM_OP_UNUSED_0x16 = 0x16,
|
||||
WASM_OP_UNUSED_0x17 = 0x17,
|
||||
|
||||
@ -259,27 +259,124 @@ typedef enum WASMOpcode {
|
||||
|
||||
WASM_OP_IMPDEP = 0xcf,
|
||||
|
||||
WASM_OP_REF_NULL = 0xd0, /* ref.null */
|
||||
WASM_OP_REF_IS_NULL = 0xd1, /* ref.is_null */
|
||||
WASM_OP_REF_FUNC = 0xd2, /* ref.func */
|
||||
WASM_OP_REF_NULL = 0xd0, /* ref.null */
|
||||
WASM_OP_REF_IS_NULL = 0xd1, /* ref.is_null */
|
||||
WASM_OP_REF_FUNC = 0xd2, /* ref.func */
|
||||
WASM_OP_REF_EQ = 0xd3, /* ref.eq */
|
||||
WASM_OP_REF_AS_NON_NULL = 0xd4, /* ref.as_non_null */
|
||||
WASM_OP_BR_ON_NULL = 0xd5, /* br_on_null */
|
||||
WASM_OP_BR_ON_NON_NULL = 0xd6, /* br_on_non_null */
|
||||
|
||||
EXT_OP_BLOCK = 0xd3, /* block with blocktype */
|
||||
EXT_OP_LOOP = 0xd4, /* loop with blocktype */
|
||||
EXT_OP_IF = 0xd5, /* if with blocktype */
|
||||
EXT_OP_BR_TABLE_CACHE = 0xd6, /* br_table from cache */
|
||||
EXT_OP_BLOCK = 0xd7, /* block with blocktype */
|
||||
EXT_OP_LOOP = 0xd8, /* loop with blocktype */
|
||||
EXT_OP_IF = 0xd9, /* if with blocktype */
|
||||
EXT_OP_BR_TABLE_CACHE = 0xda, /* br_table from cache */
|
||||
|
||||
EXT_OP_TRY = 0xd7, /* try block with blocktype */
|
||||
EXT_OP_TRY = 0xdb, /* try block with blocktype */
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
DEBUG_OP_BREAK = 0xd8, /* debug break point */
|
||||
DEBUG_OP_BREAK = 0xdc, /* debug break point */
|
||||
#endif
|
||||
|
||||
/* Post-MVP extend op prefix */
|
||||
WASM_OP_GC_PREFIX = 0xfb,
|
||||
WASM_OP_MISC_PREFIX = 0xfc,
|
||||
WASM_OP_SIMD_PREFIX = 0xfd,
|
||||
WASM_OP_ATOMIC_PREFIX = 0xfe,
|
||||
} WASMOpcode;
|
||||
|
||||
typedef enum WASMGCEXTOpcode {
|
||||
WASM_OP_STRUCT_NEW = 0x00, /* struct.new */
|
||||
WASM_OP_STRUCT_NEW_DEFAULT = 0x01, /* struct.new_default */
|
||||
WASM_OP_STRUCT_GET = 0x02, /* struct.get */
|
||||
WASM_OP_STRUCT_GET_S = 0x03, /* struct.get_s */
|
||||
WASM_OP_STRUCT_GET_U = 0x04, /* struct.get_u */
|
||||
WASM_OP_STRUCT_SET = 0x05, /* struct.set */
|
||||
|
||||
WASM_OP_ARRAY_NEW = 0x06, /* array.new */
|
||||
WASM_OP_ARRAY_NEW_DEFAULT = 0x07, /* array.new_default */
|
||||
WASM_OP_ARRAY_NEW_FIXED = 0x08, /* array.new_fixed */
|
||||
WASM_OP_ARRAY_NEW_DATA = 0x09, /* array.new_data */
|
||||
WASM_OP_ARRAY_NEW_ELEM = 0x0A, /* array.new_elem */
|
||||
WASM_OP_ARRAY_GET = 0x0B, /* array.get */
|
||||
WASM_OP_ARRAY_GET_S = 0x0C, /* array.get_s */
|
||||
WASM_OP_ARRAY_GET_U = 0x0D, /* array.get_u */
|
||||
WASM_OP_ARRAY_SET = 0x0E, /* array.set */
|
||||
WASM_OP_ARRAY_LEN = 0x0F, /* array.len */
|
||||
WASM_OP_ARRAY_FILL = 0x10, /* array.fill */
|
||||
WASM_OP_ARRAY_COPY = 0x11, /* array.copy */
|
||||
WASM_OP_ARRAY_INIT_DATA = 0x12,
|
||||
/* array.init_data */ /* TODO */
|
||||
WASM_OP_ARRAY_INIT_ELEM = 0x13,
|
||||
/* array.init_elem */ /* TODO */
|
||||
|
||||
WASM_OP_REF_TEST = 0x14, /* ref.test */
|
||||
WASM_OP_REF_TEST_NULLABLE = 0x15, /* ref.test_nullable */
|
||||
WASM_OP_REF_CAST = 0x16, /* ref.cast */
|
||||
WASM_OP_REF_CAST_NULLABLE = 0x17, /* ref.cast_nullable */
|
||||
|
||||
WASM_OP_BR_ON_CAST = 0x18, /* br_on_cast */
|
||||
WASM_OP_BR_ON_CAST_FAIL = 0x19, /* br_on_cast_fail */
|
||||
|
||||
WASM_OP_ANY_CONVERT_EXTERN = 0x1A, /* any.convert_extern */
|
||||
WASM_OP_EXTERN_CONVERT_ANY = 0x1B, /* extern.covert_any */
|
||||
|
||||
WASM_OP_REF_I31 = 0x1C, /* ref.i31 */
|
||||
WASM_OP_I31_GET_S = 0x1D, /* i31.get_s */
|
||||
WASM_OP_I31_GET_U = 0x1E, /* i31.get_u */
|
||||
|
||||
/* stringref related opcoded */
|
||||
WASM_OP_STRING_NEW_UTF8 = 0x80, /* string.new_utf8 */
|
||||
WASM_OP_STRING_NEW_WTF16 = 0x81, /* string.new_wtf16 */
|
||||
WASM_OP_STRING_CONST = 0x82, /* string.const */
|
||||
WASM_OP_STRING_MEASURE_UTF8 = 0x83, /* string.measure_utf8 */
|
||||
WASM_OP_STRING_MEASURE_WTF8 = 0x84, /* string.measure_wtf8 */
|
||||
WASM_OP_STRING_MEASURE_WTF16 = 0x85, /* string.measure_wtf16 */
|
||||
WASM_OP_STRING_ENCODE_UTF8 = 0x86, /* string.encode_utf8 */
|
||||
WASM_OP_STRING_ENCODE_WTF16 = 0x87, /* string.encode_wtf16 */
|
||||
WASM_OP_STRING_CONCAT = 0x88, /* string.concat */
|
||||
WASM_OP_STRING_EQ = 0x89, /* string.eq */
|
||||
WASM_OP_STRING_IS_USV_SEQUENCE = 0x8a, /* string.is_usv_sequence */
|
||||
WASM_OP_STRING_NEW_LOSSY_UTF8 = 0x8b, /* string.new_lossy_utf8 */
|
||||
WASM_OP_STRING_NEW_WTF8 = 0x8c, /* string.new_wtf8 */
|
||||
WASM_OP_STRING_ENCODE_LOSSY_UTF8 = 0x8d, /* string.encode_lossy_utf8 */
|
||||
WASM_OP_STRING_ENCODE_WTF8 = 0x8e, /* string.encode_wtf8 */
|
||||
|
||||
WASM_OP_STRING_AS_WTF8 = 0x90, /* string.as_wtf8 */
|
||||
WASM_OP_STRINGVIEW_WTF8_ADVANCE = 0x91, /* stringview_wtf8.advance */
|
||||
WASM_OP_STRINGVIEW_WTF8_ENCODE_UTF8 =
|
||||
0x92, /* stringview_wtf8.encode_utf8 */
|
||||
WASM_OP_STRINGVIEW_WTF8_SLICE = 0x93, /* stringview_wtf8.slice */
|
||||
WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8 =
|
||||
0x94, /* stringview_wtf8.encode_lossy_utf8 */
|
||||
WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8 =
|
||||
0x95, /* stringview_wtf8.encode_wtf8 */
|
||||
|
||||
WASM_OP_STRING_AS_WTF16 = 0x98, /* string.as_wtf16 */
|
||||
WASM_OP_STRINGVIEW_WTF16_LENGTH = 0x99, /* stringview_wtf16.length */
|
||||
WASM_OP_STRINGVIEW_WTF16_GET_CODEUNIT =
|
||||
0x9a, /* stringview_wtf16.get_codeunit */
|
||||
WASM_OP_STRINGVIEW_WTF16_ENCODE = 0x9b, /* stringview_wtf16.encode */
|
||||
WASM_OP_STRINGVIEW_WTF16_SLICE = 0x9c, /* stringview_wtf16.slice */
|
||||
|
||||
WASM_OP_STRING_AS_ITER = 0xa0, /* string.as_iter */
|
||||
WASM_OP_STRINGVIEW_ITER_NEXT = 0xa1, /* stringview_iter.next */
|
||||
WASM_OP_STRINGVIEW_ITER_ADVANCE = 0xa2, /* stringview_iter.advance */
|
||||
WASM_OP_STRINGVIEW_ITER_REWIND = 0xa3, /* stringview_iter.rewind */
|
||||
WASM_OP_STRINGVIEW_ITER_SLICE = 0xa4, /* stringview_iter.slice */
|
||||
|
||||
WASM_OP_STRING_NEW_UTF8_ARRAY = 0xb0, /* string.new_utf8_array */
|
||||
WASM_OP_STRING_NEW_WTF16_ARRAY = 0xb1, /* string.new_wtf16_array */
|
||||
WASM_OP_STRING_ENCODE_UTF8_ARRAY = 0xb2, /* string.encode_utf8_array */
|
||||
WASM_OP_STRING_ENCODE_WTF16_ARRAY = 0xb3, /* string.encode_wtf16_array */
|
||||
WASM_OP_STRING_NEW_LOSSY_UTF8_ARRAY =
|
||||
0xb4, /* string.new_lossy_utf8_array */
|
||||
WASM_OP_STRING_NEW_WTF8_ARRAY = 0xb5, /* string.new_wtf8_array */
|
||||
WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY =
|
||||
0xb6, /* string.encode_lossy_utf8_array */
|
||||
WASM_OP_STRING_ENCODE_WTF8_ARRAY = 0xb7, /* string.encode_wtf8_array */
|
||||
} WASMGCEXTOpcode;
|
||||
|
||||
typedef enum WASMMiscEXTOpcode {
|
||||
WASM_OP_I32_TRUNC_SAT_S_F32 = 0x00,
|
||||
WASM_OP_I32_TRUNC_SAT_U_F32 = 0x01,
|
||||
@ -678,7 +775,7 @@ typedef enum WASMAtomicEXTOpcode {
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
#define DEF_DEBUG_BREAK_HANDLE() \
|
||||
[DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK), /* 0xd7 */
|
||||
[DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK), /* 0xdb */
|
||||
#else
|
||||
#define DEF_DEBUG_BREAK_HANDLE()
|
||||
#endif
|
||||
@ -719,8 +816,8 @@ typedef enum WASMAtomicEXTOpcode {
|
||||
HANDLE_OPCODE(WASM_OP_CALL_INDIRECT), /* 0x11 */ \
|
||||
HANDLE_OPCODE(WASM_OP_RETURN_CALL), /* 0x12 */ \
|
||||
HANDLE_OPCODE(WASM_OP_RETURN_CALL_INDIRECT), /* 0x13 */ \
|
||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x14), /* 0x14 */ \
|
||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x15), /* 0x15 */ \
|
||||
HANDLE_OPCODE(WASM_OP_CALL_REF), /* 0x14 */ \
|
||||
HANDLE_OPCODE(WASM_OP_RETURN_CALL_REF), /* 0x15 */ \
|
||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x16), /* 0x16 */ \
|
||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x17), /* 0x17 */ \
|
||||
HANDLE_OPCODE(WASM_OP_DELEGATE), /* 0x18 */ \
|
||||
@ -910,11 +1007,16 @@ typedef enum WASMAtomicEXTOpcode {
|
||||
HANDLE_OPCODE(WASM_OP_REF_NULL), /* 0xd0 */ \
|
||||
HANDLE_OPCODE(WASM_OP_REF_IS_NULL), /* 0xd1 */ \
|
||||
HANDLE_OPCODE(WASM_OP_REF_FUNC), /* 0xd2 */ \
|
||||
HANDLE_OPCODE(EXT_OP_BLOCK), /* 0xd3 */ \
|
||||
HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \
|
||||
HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \
|
||||
HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \
|
||||
HANDLE_OPCODE(EXT_OP_TRY), /* 0xd7 */ \
|
||||
HANDLE_OPCODE(WASM_OP_REF_EQ), /* 0xd3 */ \
|
||||
HANDLE_OPCODE(WASM_OP_REF_AS_NON_NULL), /* 0xd4 */ \
|
||||
HANDLE_OPCODE(WASM_OP_BR_ON_NULL), /* 0xd5 */ \
|
||||
HANDLE_OPCODE(WASM_OP_BR_ON_NON_NULL), /* 0xd6 */ \
|
||||
HANDLE_OPCODE(EXT_OP_BLOCK), /* 0xd7 */ \
|
||||
HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd8 */ \
|
||||
HANDLE_OPCODE(EXT_OP_IF), /* 0xd9 */ \
|
||||
HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xda */ \
|
||||
HANDLE_OPCODE(EXT_OP_TRY), /* 0xdb */ \
|
||||
SET_GOTO_TABLE_ELEM(WASM_OP_GC_PREFIX), /* 0xfb */ \
|
||||
SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \
|
||||
SET_GOTO_TABLE_SIMD_PREFIX_ELEM() /* 0xfd */ \
|
||||
SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -71,6 +71,22 @@ typedef enum WASMExceptionID {
|
||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
EXCE_OPERAND_STACK_OVERFLOW,
|
||||
EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
|
||||
/* GC related exceptions */
|
||||
EXCE_NULL_FUNC_OBJ,
|
||||
EXCE_NULL_STRUCT_OBJ,
|
||||
EXCE_NULL_ARRAY_OBJ,
|
||||
EXCE_NULL_I31_OBJ,
|
||||
EXCE_NULL_REFERENCE,
|
||||
EXCE_FAILED_TO_CREATE_RTT_TYPE,
|
||||
EXCE_FAILED_TO_CREATE_STRUCT_OBJ,
|
||||
EXCE_FAILED_TO_CREATE_ARRAY_OBJ,
|
||||
EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ,
|
||||
EXCE_CAST_FAILURE,
|
||||
EXCE_ARRAY_IDX_OOB,
|
||||
EXCE_FAILED_TO_CREATE_STRING,
|
||||
EXCE_FAILED_TO_CREATE_STRINGREF,
|
||||
EXCE_FAILED_TO_CREATE_STRINGVIEW,
|
||||
EXCE_FAILED_TO_ENCODE_STRING,
|
||||
EXCE_ALREADY_THROWN,
|
||||
EXCE_NUM,
|
||||
} WASMExceptionID;
|
||||
@ -129,13 +145,29 @@ struct WASMMemoryInstance {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* WASMTableInstance is used to represent table instance in
|
||||
* runtime, to compute the table element address with index
|
||||
* we need to know the element type and the element ref type.
|
||||
* For pointer type, it's 32-bit or 64-bit, align up to 8 bytes
|
||||
* to simplify the computation.
|
||||
* And each struct member should be 4-byte or 8-byte aligned.
|
||||
*/
|
||||
struct WASMTableInstance {
|
||||
/* The element type */
|
||||
uint8 elem_type;
|
||||
uint8 __padding__[7];
|
||||
union {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *elem_ref_type;
|
||||
#endif
|
||||
uint64 __padding__;
|
||||
} elem_ref_type;
|
||||
/* Current size */
|
||||
uint32 cur_size;
|
||||
/* Maximum size */
|
||||
uint32 max_size;
|
||||
/* Table elements */
|
||||
uint32 elems[1];
|
||||
table_elem_type_t elems[1];
|
||||
};
|
||||
|
||||
struct WASMGlobalInstance {
|
||||
@ -147,6 +179,9 @@ struct WASMGlobalInstance {
|
||||
uint32 data_offset;
|
||||
/* initial value */
|
||||
WASMValue initial_value;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *ref_type;
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* just for import, keep the reference here */
|
||||
WASMModuleInstance *import_module_inst;
|
||||
@ -271,6 +306,13 @@ typedef struct WASMModuleInstanceExtraCommon {
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
bh_bitmap *elem_dropped;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* The gc heap memory pool */
|
||||
uint8 *gc_heap_pool;
|
||||
/* The gc heap created */
|
||||
void *gc_heap_handle;
|
||||
#endif
|
||||
} WASMModuleInstanceExtraCommon;
|
||||
|
||||
/* Extra info of WASM module instance for interpreter/jit mode */
|
||||
@ -598,7 +640,7 @@ void
|
||||
wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module,
|
||||
WASMModuleInstMemConsumption *mem_conspn);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
|
||||
static inline bool
|
||||
wasm_elem_is_active(uint32 mode)
|
||||
{
|
||||
@ -619,8 +661,18 @@ wasm_elem_is_declarative(uint32 mode)
|
||||
|
||||
bool
|
||||
wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx,
|
||||
uint32 inc_entries, uint32 init_val);
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
||||
uint32 inc_entries, table_elem_type_t init_val);
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
void *
|
||||
wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx,
|
||||
bool throw_exce, char *error_buf, uint32 error_buf_size);
|
||||
|
||||
bool
|
||||
wasm_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap);
|
||||
|
||||
#endif
|
||||
|
||||
static inline WASMTableInstance *
|
||||
wasm_get_table_inst(const WASMModuleInstance *module_inst, uint32 tbl_idx)
|
||||
@ -723,19 +775,42 @@ llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx,
|
||||
|
||||
void
|
||||
llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 length, uint32 val, uint32 data_offset);
|
||||
uint32 length, uintptr_t val, uint32 data_offset);
|
||||
|
||||
uint32
|
||||
llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 inc_entries, uint32 init_val);
|
||||
uint32 inc_entries, uintptr_t init_val);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0 \
|
||||
|| WASM_ENABLE_AOT_STACK_FRAME != 0
|
||||
bool
|
||||
llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
|
||||
|
||||
void
|
||||
llvm_jit_free_frame(WASMExecEnv *exec_env);
|
||||
|
||||
void
|
||||
llvm_jit_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
void *
|
||||
llvm_jit_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx,
|
||||
bool throw_exce, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
|
||||
bool
|
||||
llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
|
||||
WASMObjectRef gc_obj, uint32 type_index);
|
||||
|
||||
WASMRttTypeRef
|
||||
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index);
|
||||
|
||||
bool
|
||||
llvm_array_init_with_data(WASMModuleInstance *module_inst, uint32 seg_index,
|
||||
uint32 data_seg_offset, WASMArrayObjectRef array_obj,
|
||||
uint32 elem_size, uint32 array_len);
|
||||
#endif
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user