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

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