Implement multi-module feature and bulk-memory feature (#271)
Refine wasm loader and aot loader Fix potential issue of os_mmap/os_munmap Update document
This commit is contained in:
@ -22,6 +22,8 @@ extern "C" {
|
||||
#define VALUE_TYPE_VOID 0x40
|
||||
/* Used by AOT */
|
||||
#define VALUE_TYPE_I1 0x41
|
||||
/* Used by loader to represent any type of i32/i64/f32/f64 */
|
||||
#define VALUE_TYPE_ANY 0x42
|
||||
|
||||
/* Table Element Type */
|
||||
#define TABLE_ELEM_TYPE_ANY_FUNC 0x70
|
||||
@ -50,6 +52,9 @@ extern "C" {
|
||||
#define SECTION_TYPE_ELEM 9
|
||||
#define SECTION_TYPE_CODE 10
|
||||
#define SECTION_TYPE_DATA 11
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
#define SECTION_TYPE_DATACOUNT 12
|
||||
#endif
|
||||
|
||||
#define IMPORT_KIND_FUNC 0
|
||||
#define IMPORT_KIND_TABLE 1
|
||||
@ -66,6 +71,10 @@ extern "C" {
|
||||
#define BLOCK_TYPE_IF 2
|
||||
#define BLOCK_TYPE_FUNCTION 3
|
||||
|
||||
typedef struct WASMModule WASMModule;
|
||||
typedef struct WASMFunction WASMFunction;
|
||||
typedef struct WASMGlobal WASMGlobal;
|
||||
|
||||
typedef union WASMValue {
|
||||
int32 i32;
|
||||
uint32 u32;
|
||||
@ -119,6 +128,10 @@ typedef struct WASMTableImport {
|
||||
uint32 init_size;
|
||||
/* specified if (flags & 1), else it is 0x10000 */
|
||||
uint32 max_size;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *import_module;
|
||||
WASMTable *import_table_linked;
|
||||
#endif
|
||||
} WASMTableImport;
|
||||
|
||||
typedef struct WASMMemoryImport {
|
||||
@ -128,6 +141,10 @@ typedef struct WASMMemoryImport {
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 init_page_count;
|
||||
uint32 max_page_count;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *import_module;
|
||||
WASMMemory *import_memory_linked;
|
||||
#endif
|
||||
} WASMMemoryImport;
|
||||
|
||||
typedef struct WASMFunctionImport {
|
||||
@ -135,13 +152,17 @@ typedef struct WASMFunctionImport {
|
||||
char *field_name;
|
||||
/* function type */
|
||||
WASMType *func_type;
|
||||
/* function pointer after linked */
|
||||
/* native function pointer after linked */
|
||||
void *func_ptr_linked;
|
||||
/* signature from registered native symbols */
|
||||
const char *signature;
|
||||
/* attachment */
|
||||
void *attachment;
|
||||
bool call_conv_raw;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModule *import_module;
|
||||
WASMFunction *import_func_linked;
|
||||
#endif
|
||||
} WASMFunctionImport;
|
||||
|
||||
typedef struct WASMGlobalImport {
|
||||
@ -151,6 +172,12 @@ typedef struct WASMGlobalImport {
|
||||
bool is_mutable;
|
||||
/* global data after linked */
|
||||
WASMValue global_data_linked;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* imported function pointer after linked */
|
||||
// TODO: remove if not necessary
|
||||
WASMModule *import_module;
|
||||
WASMGlobal *import_global_linked;
|
||||
#endif
|
||||
} WASMGlobalImport;
|
||||
|
||||
typedef struct WASMImport {
|
||||
@ -223,6 +250,9 @@ typedef struct WASMDataSeg {
|
||||
uint32 memory_index;
|
||||
InitializerExpression base_offset;
|
||||
uint32 data_length;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
bool is_passive;
|
||||
#endif
|
||||
uint8 *data;
|
||||
} WASMDataSeg;
|
||||
|
||||
@ -266,7 +296,12 @@ typedef struct WASMModule {
|
||||
uint32 global_count;
|
||||
uint32 export_count;
|
||||
uint32 table_seg_count;
|
||||
/* data seg count read from data segment section */
|
||||
uint32 data_seg_count;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
/* data count read from datacount section */
|
||||
uint32 data_seg_count1;
|
||||
#endif
|
||||
|
||||
uint32 import_function_count;
|
||||
uint32 import_table_count;
|
||||
@ -308,6 +343,12 @@ typedef struct WASMModule {
|
||||
WASIArguments wasi_args;
|
||||
bool is_wasi_module;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
// TODO: mutex ? mutli-threads ?
|
||||
bh_list import_module_list_head;
|
||||
bh_list *import_module_list;
|
||||
#endif
|
||||
} WASMModule;
|
||||
|
||||
typedef struct WASMBranchBlock {
|
||||
@ -430,5 +471,4 @@ wasm_type_equal(const WASMType *type1, const WASMType *type2)
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_H_ */
|
||||
|
||||
#endif /* end of _WASM_H_ */
|
||||
@ -236,6 +236,15 @@ LOAD_I16(void *addr)
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) do { \
|
||||
uint64 offset1 = (int32)(start); \
|
||||
if (offset1 + bytes <= linear_mem_size) \
|
||||
/* App heap space is not valid space for bulk memory operation */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
|
||||
static inline uint32
|
||||
rotl32(uint32 n, uint32 c)
|
||||
{
|
||||
@ -877,6 +886,59 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
||||
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static void
|
||||
wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame);
|
||||
|
||||
static void
|
||||
wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMModuleInstance *sub_module_inst = cur_func->import_module_inst;
|
||||
WASMFunctionInstance *sub_func_inst = cur_func->import_func_inst;
|
||||
WASMFunctionImport *func_import = cur_func->u.func_import;
|
||||
uint8 *ip = prev_frame->ip;
|
||||
char buf[128];
|
||||
|
||||
if (!sub_func_inst) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
func_import->module_name, func_import->field_name);
|
||||
wasm_set_exception(module_inst, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set ip NULL to make call_func_bytecode return after executing
|
||||
this function */
|
||||
prev_frame->ip = NULL;
|
||||
|
||||
/* replace exec_env's module_inst with sub_module_inst so we can
|
||||
call it */
|
||||
exec_env->module_inst = (WASMModuleInstanceCommon *)sub_module_inst;
|
||||
|
||||
/* call function of sub-module*/
|
||||
wasm_interp_call_func_bytecode(sub_module_inst, exec_env,
|
||||
sub_func_inst, prev_frame);
|
||||
|
||||
/* restore ip and module_inst */
|
||||
prev_frame->ip = ip;
|
||||
exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
|
||||
|
||||
/* transfer exception if it is thrown */
|
||||
if (wasm_get_exception(sub_module_inst)) {
|
||||
bh_memcpy_s(module_inst->cur_exception,
|
||||
sizeof(module_inst->cur_exception),
|
||||
sub_module_inst->cur_exception,
|
||||
sizeof(sub_module_inst->cur_exception));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||
|
||||
#define HANDLE_OP(opcode) HANDLE_##opcode
|
||||
@ -902,6 +964,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count
|
||||
- heap_base_offset : 0;
|
||||
uint8 *global_data = module->global_data;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
#endif
|
||||
WASMTableInstance *table = module->default_table;
|
||||
WASMGlobalInstance *globals = module->globals;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
@ -1086,14 +1151,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
HANDLE_OP (WASM_OP_CALL):
|
||||
read_leb_uint32(frame_ip, frame_ip_end, fidx);
|
||||
bh_assert(fidx < module->function_count);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
|
||||
cur_func = module->functions + fidx;
|
||||
goto call_func_from_interp;
|
||||
|
||||
HANDLE_OP (WASM_OP_CALL_INDIRECT):
|
||||
{
|
||||
WASMType *cur_type, *cur_func_type;
|
||||
WASMTableInstance *cur_table_inst;
|
||||
|
||||
/**
|
||||
* type check. compiler will make sure all like
|
||||
* (call_indirect (type $x) (i32.const 1))
|
||||
* the function type has to be defined in the module also
|
||||
* no matter it is used or not
|
||||
*/
|
||||
read_leb_uint32(frame_ip, frame_ip_end, tidx);
|
||||
if (tidx >= module->module->type_count) {
|
||||
wasm_set_exception(module, "type index is overflow");
|
||||
@ -1105,27 +1183,48 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
frame_ip++;
|
||||
val = POP_I32();
|
||||
|
||||
if (val < 0 || val >= (int32)table->cur_size) {
|
||||
/* careful, it might be a table in another module */
|
||||
cur_table_inst = table;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (table->table_inst_linked) {
|
||||
cur_table_inst = table->table_inst_linked;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (val < 0 || val >= (int32)cur_table_inst->cur_size) {
|
||||
wasm_set_exception(module, "undefined element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32*)table->base_addr)[val];
|
||||
fidx = ((uint32*)cur_table_inst->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
|
||||
if (cur_func->is_import_func)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
if (cur_func->is_import_func
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
&& !cur_func->import_func_inst
|
||||
#endif
|
||||
)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
cur_func_type = cur_func->u.func->func_type;
|
||||
if (!wasm_type_equal(cur_type, cur_func_type)) {
|
||||
wasm_set_exception(module, "indirect call type mismatch");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
goto call_func_from_interp;
|
||||
}
|
||||
|
||||
@ -1264,7 +1363,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
bh_assert(global_idx < module->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = global_data + global->data_offset;
|
||||
global_addr =
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
global->import_global_inst
|
||||
? global->import_module_inst->global_data
|
||||
+ global->import_global_inst->data_offset
|
||||
:
|
||||
#endif
|
||||
global_data + global->data_offset;
|
||||
|
||||
switch (global->type) {
|
||||
case VALUE_TYPE_I32:
|
||||
@ -1289,7 +1395,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
bh_assert(global_idx < module->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = global_data + global->data_offset;
|
||||
global_addr =
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
global->import_global_inst
|
||||
? global->import_module_inst->global_data
|
||||
+ global->import_global_inst->data_offset
|
||||
:
|
||||
#endif
|
||||
global_data + global->data_offset;
|
||||
|
||||
switch (global->type) {
|
||||
case VALUE_TYPE_I32:
|
||||
@ -1521,6 +1634,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
memory = module->default_memory;
|
||||
total_mem_size = num_bytes_per_page * memory->cur_page_count
|
||||
- heap_base_offset;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)reserved;
|
||||
@ -2357,6 +2473,78 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
DEF_OP_TRUNC_SAT_F64(-1.0f, 18446744073709551616.0,
|
||||
false, false);
|
||||
break;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
case WASM_OP_MEMORY_INIT:
|
||||
{
|
||||
uint32 addr, segment;
|
||||
uint64 bytes, offset, seg_len;
|
||||
uint8* data;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, segment);
|
||||
/* skip memory index */
|
||||
frame_ip++;
|
||||
|
||||
bytes = (uint64)(uint32)POP_I32();
|
||||
offset = (uint64)(uint32)POP_I32();
|
||||
addr = (uint32)POP_I32();
|
||||
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr);
|
||||
|
||||
seg_len = (uint64)module->module->data_segments[segment]->data_length;
|
||||
data = module->module->data_segments[segment]->data;
|
||||
if (offset + bytes > seg_len)
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memcpy_s(maddr, linear_mem_size - addr,
|
||||
data + offset, bytes);
|
||||
break;
|
||||
}
|
||||
case WASM_OP_DATA_DROP:
|
||||
{
|
||||
uint32 segment;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, segment);
|
||||
module->module->data_segments[segment]->data_length = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case WASM_OP_MEMORY_COPY:
|
||||
{
|
||||
uint32 dst, src, len;
|
||||
uint8 *mdst, *msrc;
|
||||
|
||||
frame_ip += 2;
|
||||
|
||||
len = POP_I32();
|
||||
src = POP_I32();
|
||||
dst = POP_I32();
|
||||
|
||||
CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc);
|
||||
CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
|
||||
|
||||
/* allowing the destination and source to overlap */
|
||||
bh_memmove_s(mdst, linear_mem_size - dst,
|
||||
msrc, len);
|
||||
|
||||
break;
|
||||
}
|
||||
case WASM_OP_MEMORY_FILL:
|
||||
{
|
||||
uint32 dst, len;
|
||||
uint8 val, *mdst;
|
||||
frame_ip++;
|
||||
|
||||
len = POP_I32();
|
||||
val = POP_I32();
|
||||
dst = POP_I32();
|
||||
|
||||
CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
|
||||
|
||||
memset(mdst, val, len);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_BULK_MEMORY */
|
||||
default:
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
@ -2430,14 +2618,25 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
call_func_from_entry:
|
||||
{
|
||||
if (cur_func->is_import_func) {
|
||||
wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame);
|
||||
prev_frame = frame->prev_frame;
|
||||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (cur_func->import_func_inst) {
|
||||
wasm_interp_call_func_import(module, exec_env, cur_func,
|
||||
prev_frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
wasm_interp_call_func_native(module, exec_env, cur_func,
|
||||
prev_frame);
|
||||
}
|
||||
|
||||
memory = module->default_memory;
|
||||
if (wasm_get_exception(module))
|
||||
goto got_exception;
|
||||
prev_frame = frame->prev_frame;
|
||||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
|
||||
memory = module->default_memory;
|
||||
if (wasm_get_exception(module))
|
||||
goto got_exception;
|
||||
}
|
||||
else {
|
||||
WASMFunction *cur_wasm_func = cur_func->u.func;
|
||||
@ -2521,6 +2720,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
WASMFunctionInstance *function,
|
||||
uint32 argc, uint32 argv[])
|
||||
{
|
||||
// TODO: since module_inst = exec_env->module_inst, shall we remove the 1st arg?
|
||||
WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
|
||||
WASMInterpFrame *frame, *outs_area;
|
||||
|
||||
@ -2559,15 +2759,44 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
if (function->is_import_func)
|
||||
wasm_interp_call_func_native(module_inst, exec_env, function, frame);
|
||||
else
|
||||
if (function->is_import_func) {
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (function->import_module_inst) {
|
||||
LOG_DEBUG("it is a function of a sub module");
|
||||
wasm_interp_call_func_import(module_inst,
|
||||
exec_env,
|
||||
function,
|
||||
frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LOG_DEBUG("it is an native function");
|
||||
/* it is a native function */
|
||||
wasm_interp_call_func_native(module_inst,
|
||||
exec_env,
|
||||
function,
|
||||
frame);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_DEBUG("it is a function of the module itself");
|
||||
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
|
||||
}
|
||||
|
||||
/* Output the return value to the caller */
|
||||
if (!wasm_get_exception(module_inst)) {
|
||||
for (i = 0; i < function->ret_cell_num; i++)
|
||||
for (i = 0; i < function->ret_cell_num; i++) {
|
||||
argv[i] = *(frame->sp + i - function->ret_cell_num);
|
||||
}
|
||||
|
||||
if (function->ret_cell_num) {
|
||||
LOG_DEBUG("first return value argv[0]=%d", argv[0]);
|
||||
} else {
|
||||
LOG_DEBUG("no return value");
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst));
|
||||
}
|
||||
|
||||
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
||||
|
||||
@ -238,6 +238,15 @@ LOAD_I16(void *addr)
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) do { \
|
||||
uint64 offset1 = (int32)(start); \
|
||||
if (offset1 + bytes <= linear_mem_size) \
|
||||
/* App heap space is not valid space for bulk memory operation */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
|
||||
static inline uint32
|
||||
rotl32(uint32 n, uint32 c)
|
||||
{
|
||||
@ -815,6 +824,59 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
||||
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static void
|
||||
wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame);
|
||||
|
||||
static void
|
||||
wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMModuleInstance *sub_module_inst = cur_func->import_module_inst;
|
||||
WASMFunctionInstance *sub_func_inst = cur_func->import_func_inst;
|
||||
WASMFunctionImport *func_import = cur_func->u.func_import;
|
||||
uint8 *ip = prev_frame->ip;
|
||||
char buf[128];
|
||||
|
||||
if (!sub_func_inst) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"fail to call unlinked import function (%s, %s)",
|
||||
func_import->module_name, func_import->field_name);
|
||||
wasm_set_exception(module_inst, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set ip NULL to make call_func_bytecode return after executing
|
||||
this function */
|
||||
prev_frame->ip = NULL;
|
||||
|
||||
/* replace exec_env's module_inst with sub_module_inst so we can
|
||||
call it */
|
||||
exec_env->module_inst = (WASMModuleInstanceCommon *)sub_module_inst;
|
||||
|
||||
/* call function of sub-module*/
|
||||
wasm_interp_call_func_bytecode(sub_module_inst, exec_env,
|
||||
sub_func_inst, prev_frame);
|
||||
|
||||
/* restore ip and module_inst */
|
||||
prev_frame->ip = ip;
|
||||
exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
|
||||
|
||||
/* transfer exception if it is thrown */
|
||||
if (wasm_get_exception(sub_module_inst)) {
|
||||
bh_memcpy_s(module_inst->cur_exception,
|
||||
sizeof(module_inst->cur_exception),
|
||||
sub_module_inst->cur_exception,
|
||||
sizeof(sub_module_inst->cur_exception));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_OPCODE_COUNTER != 0
|
||||
typedef struct OpcodeInfo {
|
||||
char *name;
|
||||
@ -894,6 +956,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count
|
||||
- heap_base_offset : 0;
|
||||
uint8 *global_data = module->global_data;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
#endif
|
||||
WASMTableInstance *table = module->default_table;
|
||||
WASMGlobalInstance *globals = module->globals;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
@ -997,6 +1062,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
HANDLE_OP (WASM_OP_CALL_INDIRECT):
|
||||
{
|
||||
WASMType *cur_type, *cur_func_type;
|
||||
WASMTableInstance *cur_table_inst;
|
||||
|
||||
tidx = GET_OPERAND(int32, 0);
|
||||
val = GET_OPERAND(int32, 2);
|
||||
@ -1008,21 +1074,41 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
}
|
||||
cur_type = module->module->types[tidx];
|
||||
|
||||
if (val < 0 || val >= (int32)table->cur_size) {
|
||||
/* careful, it might be a table in another module */
|
||||
cur_table_inst = table;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (table->table_inst_linked) {
|
||||
cur_table_inst = table->table_inst_linked;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (val < 0 || val >= (int32)cur_table_inst->cur_size) {
|
||||
wasm_set_exception(module, "undefined element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32*)table->base_addr)[val];
|
||||
fidx = ((uint32*)cur_table_inst->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
|
||||
if (cur_func->is_import_func)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
if (cur_func->is_import_func
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
&& !cur_func->import_func_inst
|
||||
#endif
|
||||
)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
cur_func_type = cur_func->u.func->func_type;
|
||||
if (!wasm_type_equal(cur_type, cur_func_type)) {
|
||||
@ -1115,7 +1201,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
bh_assert(global_idx < module->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = global_data + global->data_offset;
|
||||
global_addr =
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
global->import_global_inst
|
||||
? global->import_module_inst->global_data
|
||||
+ global->import_global_inst->data_offset
|
||||
:
|
||||
#endif
|
||||
global_data + global->data_offset;
|
||||
|
||||
switch (global->type) {
|
||||
case VALUE_TYPE_I32:
|
||||
@ -1141,7 +1234,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
bh_assert(global_idx < module->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = global_data + global->data_offset;
|
||||
global_addr =
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
global->import_global_inst
|
||||
? global->import_module_inst->global_data
|
||||
+ global->import_global_inst->data_offset
|
||||
:
|
||||
#endif
|
||||
global_data + global->data_offset;
|
||||
|
||||
switch (global->type) {
|
||||
case VALUE_TYPE_I32:
|
||||
@ -1429,6 +1529,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
memory = module->default_memory;
|
||||
total_mem_size = num_bytes_per_page * memory->cur_page_count
|
||||
- heap_base_offset;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)reserved;
|
||||
@ -2295,6 +2398,76 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
DEF_OP_TRUNC_SAT_F64(-1.0, 18446744073709551616.0,
|
||||
false, false);
|
||||
break;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
case WASM_OP_MEMORY_INIT:
|
||||
{
|
||||
uint32 addr, segment;
|
||||
uint64 bytes, offset, seg_len;
|
||||
uint8* data;
|
||||
|
||||
segment = GET_OPERAND(uint32, 0);
|
||||
frame_ip += 2;
|
||||
|
||||
bytes = (uint64)POP_I32();
|
||||
offset = (uint64)POP_I32();
|
||||
addr = POP_I32();
|
||||
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr);
|
||||
|
||||
seg_len = (uint64)module->module->data_segments[segment]->data_length;
|
||||
data = module->module->data_segments[segment]->data;
|
||||
if (offset + bytes > seg_len)
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memcpy_s(maddr, linear_mem_size - addr,
|
||||
data + offset, bytes);
|
||||
break;
|
||||
}
|
||||
case WASM_OP_DATA_DROP:
|
||||
{
|
||||
uint32 segment;
|
||||
|
||||
segment = GET_OPERAND(uint32, 0);
|
||||
frame_ip += 2;
|
||||
|
||||
module->module->data_segments[segment]->data_length = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case WASM_OP_MEMORY_COPY:
|
||||
{
|
||||
uint32 dst, src, len;
|
||||
uint8 *mdst, *msrc;
|
||||
|
||||
len = POP_I32();
|
||||
src = POP_I32();
|
||||
dst = POP_I32();
|
||||
|
||||
CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc);
|
||||
CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
|
||||
|
||||
/* allowing the destination and source to overlap */
|
||||
bh_memmove_s(mdst, linear_mem_size - dst,
|
||||
msrc, len);
|
||||
|
||||
break;
|
||||
}
|
||||
case WASM_OP_MEMORY_FILL:
|
||||
{
|
||||
uint32 dst, len;
|
||||
uint8 val, *mdst;
|
||||
|
||||
len = POP_I32();
|
||||
val = POP_I32();
|
||||
dst = POP_I32();
|
||||
|
||||
CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
|
||||
|
||||
memset(mdst, val, len);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_BULK_MEMORY */
|
||||
default:
|
||||
wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
|
||||
goto got_exception;
|
||||
@ -2310,7 +2483,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
|
||||
HANDLE_OP (WASM_OP_CALL):
|
||||
fidx = frame_lp[GET_OFFSET()];
|
||||
bh_assert(fidx < module->function_count);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
cur_func = module->functions + fidx;
|
||||
goto call_func_from_interp;
|
||||
|
||||
@ -2383,7 +2561,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
GET_OPERAND(int64, (2 * (cur_func->param_count - i - 1)));
|
||||
outs_area->lp += 2;
|
||||
} else {
|
||||
*(outs_area->lp) = GET_OPERAND(int32, (2 * (cur_func->param_count - i - 1)));;
|
||||
*(outs_area->lp) = GET_OPERAND(int32, (2 * (cur_func->param_count - i - 1)));
|
||||
outs_area->lp ++;
|
||||
}
|
||||
}
|
||||
@ -2397,14 +2575,25 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
call_func_from_entry:
|
||||
{
|
||||
if (cur_func->is_import_func) {
|
||||
wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame);
|
||||
prev_frame = frame->prev_frame;
|
||||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (cur_func->import_func_inst) {
|
||||
wasm_interp_call_func_import(module, exec_env, cur_func,
|
||||
prev_frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
wasm_interp_call_func_native(module, exec_env, cur_func,
|
||||
prev_frame);
|
||||
}
|
||||
|
||||
memory = module->default_memory;
|
||||
if (wasm_get_exception(module))
|
||||
goto got_exception;
|
||||
prev_frame = frame->prev_frame;
|
||||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
|
||||
memory = module->default_memory;
|
||||
if (wasm_get_exception(module))
|
||||
goto got_exception;
|
||||
}
|
||||
else {
|
||||
WASMFunction *cur_wasm_func = cur_func->u.func;
|
||||
@ -2528,10 +2717,28 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
|
||||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
if (function->is_import_func)
|
||||
wasm_interp_call_func_native(module_inst, exec_env, function, frame);
|
||||
else
|
||||
if (function->is_import_func) {
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (function->import_module_inst) {
|
||||
LOG_DEBUG("it is a function of a sub module");
|
||||
wasm_interp_call_func_import(module_inst,
|
||||
exec_env,
|
||||
function,
|
||||
frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LOG_DEBUG("it is an native function");
|
||||
wasm_interp_call_func_native(module_inst,
|
||||
exec_env,
|
||||
function,
|
||||
frame);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
|
||||
}
|
||||
|
||||
/* Output the return value to the caller */
|
||||
if (!wasm_get_exception(module_inst)) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -262,7 +262,7 @@ typedef enum WASMOpcode {
|
||||
WASM_OP_MISC_PREFIX = 0xfc,
|
||||
} WASMOpcode;
|
||||
|
||||
typedef enum WASMEXTOpcode {
|
||||
typedef enum WASMMiscEXTOpcode {
|
||||
WASM_OP_I32_TRUNC_SAT_S_F32 = 0x00,
|
||||
WASM_OP_I32_TRUNC_SAT_U_F32 = 0x01,
|
||||
WASM_OP_I32_TRUNC_SAT_S_F64 = 0x02,
|
||||
@ -271,7 +271,16 @@ typedef enum WASMEXTOpcode {
|
||||
WASM_OP_I64_TRUNC_SAT_U_F32 = 0x05,
|
||||
WASM_OP_I64_TRUNC_SAT_S_F64 = 0x06,
|
||||
WASM_OP_I64_TRUNC_SAT_U_F64 = 0x07,
|
||||
} WASMEXTOpcode;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
WASM_OP_MEMORY_INIT = 0x08,
|
||||
WASM_OP_DATA_DROP = 0x09,
|
||||
WASM_OP_MEMORY_COPY = 0x0a,
|
||||
WASM_OP_MEMORY_FILL = 0x0b,
|
||||
WASM_OP_TABLE_INIT = 0x0c,
|
||||
WASM_OP_ELEM_DROP = 0x0d,
|
||||
WASM_OP_TABLE_COPY = 0x0e
|
||||
#endif
|
||||
} WASMMiscEXTOpcode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct WASMModuleInstance WASMModuleInstance;
|
||||
typedef struct WASMFunctionInstance WASMFunctionInstance;
|
||||
typedef struct WASMMemoryInstance WASMMemoryInstance;
|
||||
typedef struct WASMTableInstance WASMTableInstance;
|
||||
typedef struct WASMGlobalInstance WASMGlobalInstance;
|
||||
|
||||
typedef struct WASMMemoryInstance {
|
||||
/* Number bytes per page */
|
||||
uint32 num_bytes_per_page;
|
||||
@ -36,6 +42,10 @@ typedef struct WASMMemoryInstance {
|
||||
/* End address of memory */
|
||||
uint8 *end_addr;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* to indicate which module instance create it */
|
||||
WASMModuleInstance *owner;
|
||||
#endif
|
||||
/* Base address, the layout is:
|
||||
heap_data + memory data
|
||||
memory data init size is: num_bytes_per_page * cur_page_count
|
||||
@ -52,6 +62,10 @@ typedef struct WASMTableInstance {
|
||||
uint32 cur_size;
|
||||
/* Maximum size */
|
||||
uint32 max_size;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* just for import, keep the reference here */
|
||||
WASMTableInstance *table_inst_linked;
|
||||
#endif
|
||||
/* Base address */
|
||||
uint8 base_addr[1];
|
||||
} WASMTableInstance;
|
||||
@ -65,6 +79,11 @@ typedef struct WASMGlobalInstance {
|
||||
uint32 data_offset;
|
||||
/* initial value */
|
||||
WASMValue initial_value;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* just for import, keep the reference here */
|
||||
WASMModuleInstance *import_module_inst;
|
||||
WASMGlobalInstance *import_global_inst;
|
||||
#endif
|
||||
} WASMGlobalInstance;
|
||||
|
||||
typedef struct WASMFunctionInstance {
|
||||
@ -93,6 +112,10 @@ typedef struct WASMFunctionInstance {
|
||||
WASMFunctionImport *func_import;
|
||||
WASMFunction *func;
|
||||
} u;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModuleInstance *import_module_inst;
|
||||
WASMFunctionInstance *import_func_inst;
|
||||
#endif
|
||||
} WASMFunctionInstance;
|
||||
|
||||
typedef struct WASMExportFuncInstance {
|
||||
@ -100,6 +123,23 @@ typedef struct WASMExportFuncInstance {
|
||||
WASMFunctionInstance *function;
|
||||
} WASMExportFuncInstance;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
typedef struct WASMExportGlobInstance {
|
||||
char *name;
|
||||
WASMGlobalInstance *global;
|
||||
} WASMExportGlobInstance;
|
||||
|
||||
typedef struct WASMExportTabInstance {
|
||||
char *name;
|
||||
WASMTableInstance *table;
|
||||
} WASMExportTabInstance;
|
||||
|
||||
typedef struct WASMExportMemInstance {
|
||||
char *name;
|
||||
WASMMemoryInstance *memory;
|
||||
} WASMExportMemInstance;
|
||||
#endif
|
||||
|
||||
typedef struct WASMModuleInstance {
|
||||
/* Module instance type, for module instance loaded from
|
||||
WASM bytecode binary, this field is Wasm_Module_Bytecode;
|
||||
@ -112,13 +152,25 @@ typedef struct WASMModuleInstance {
|
||||
uint32 table_count;
|
||||
uint32 global_count;
|
||||
uint32 function_count;
|
||||
|
||||
uint32 export_func_count;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
uint32 export_glob_count;
|
||||
uint32 export_mem_count;
|
||||
uint32 export_tab_count;
|
||||
#endif
|
||||
|
||||
WASMMemoryInstance **memories;
|
||||
WASMTableInstance **tables;
|
||||
WASMGlobalInstance *globals;
|
||||
WASMFunctionInstance *functions;
|
||||
|
||||
WASMExportFuncInstance *export_functions;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMExportGlobInstance *export_globals;
|
||||
WASMExportMemInstance *export_memories;
|
||||
WASMExportTabInstance *export_tables;
|
||||
#endif
|
||||
|
||||
WASMMemoryInstance *default_memory;
|
||||
WASMTableInstance *default_table;
|
||||
@ -148,11 +200,26 @@ typedef struct WASMModuleInstance {
|
||||
|
||||
/* Main exec env */
|
||||
WASMExecEnv *main_exec_env;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
// TODO: mutex ? mutli-threads ?
|
||||
bh_list sub_module_inst_list_head;
|
||||
bh_list *sub_module_inst_list;
|
||||
#endif
|
||||
} WASMModuleInstance;
|
||||
|
||||
struct WASMInterpFrame;
|
||||
typedef struct WASMInterpFrame WASMRuntimeFrame;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
typedef struct WASMSubModInstNode {
|
||||
bh_list_link l;
|
||||
/* point to a string pool */
|
||||
const char *module_name;
|
||||
WASMModuleInstance *module_inst;
|
||||
} WASMSubModInstNode;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return the code block of a function.
|
||||
*
|
||||
@ -182,10 +249,11 @@ wasm_get_func_code_end(WASMFunctionInstance *func)
|
||||
{
|
||||
#if WASM_ENABLE_FAST_INTERP == 0
|
||||
return func->is_import_func
|
||||
? NULL : func->u.func->code + func->u.func->code_size;
|
||||
? NULL : func->u.func->code + func->u.func->code_size;
|
||||
#else
|
||||
return func->is_import_func
|
||||
? NULL : func->u.func->code_compiled + func->u.func->code_compiled_size;
|
||||
? NULL
|
||||
: func->u.func->code_compiled + func->u.func->code_compiled_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -212,6 +280,17 @@ WASMFunctionInstance *
|
||||
wasm_lookup_function(const WASMModuleInstance *module_inst,
|
||||
const char *name, const char *signature);
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMGlobalInstance *
|
||||
wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name);
|
||||
|
||||
WASMTableInstance *
|
||||
wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name);
|
||||
#endif
|
||||
|
||||
bool
|
||||
wasm_call_function(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function,
|
||||
|
||||
Reference in New Issue
Block a user