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:
wenyongh
2020-06-02 14:53:06 +08:00
committed by GitHub
parent e81f72d41f
commit 752826a667
57 changed files with 4902 additions and 818 deletions

View File

@ -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_ */

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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,