Enable shared memory && add pthread support (#282)

This commit is contained in:
Xu Jun
2020-06-15 19:04:04 +08:00
committed by GitHub
parent f4d4d69736
commit d98ab63e5c
41 changed files with 3081 additions and 289 deletions

View File

@ -939,6 +939,18 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#define CHECK_SUSPEND_FLAGS() do { \
if (exec_env->suspend_flags != 0) { \
if (exec_env->suspend_flags & 0x01) { \
/* terminate current thread */ \
return; \
} \
/* TODO: support suspend and breakpoint */ \
} \
} while (0)
#endif
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OP(opcode) HANDLE_##opcode
@ -989,6 +1001,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 local_idx, local_offset, global_idx;
uint8 local_type, *global_addr;
uint32 cache_index;
int32 aux_stack_top_global_idx = -1;
/* If the aux stack information is resolved,
we will check the aux stack boundary */
if (module->module->llvm_aux_stack_size) {
aux_stack_top_global_idx = module->module->llvm_aux_stack_global_index;
}
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
@ -1103,11 +1122,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_BR):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
read_leb_uint32(frame_ip, frame_ip_end, depth);
POP_CSP_N(depth);
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_BR_IF):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
read_leb_uint32(frame_ip, frame_ip_end, depth);
cond = (uint32)POP_I32();
if (cond)
@ -1115,6 +1140,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_BR_TABLE):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
read_leb_uint32(frame_ip, frame_ip_end, count);
if (count <= BR_TABLE_TMP_BUF_LEN)
depths = depth_buf;
@ -1150,6 +1178,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto return_func;
HANDLE_OP (WASM_OP_CALL):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
read_leb_uint32(frame_ip, frame_ip_end, fidx);
#if WASM_ENABLE_MULTI_MODULE != 0
if (fidx >= module->function_count) {
@ -1166,6 +1197,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMType *cur_type, *cur_func_type;
WASMTableInstance *cur_table_inst;
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
/**
* type check. compiler will make sure all like
* (call_indirect (type $x) (i32.const 1))
@ -1406,6 +1441,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
switch (global->type) {
case VALUE_TYPE_I32:
/* Check aux stack boundary */
if ((global_idx == (uint32)aux_stack_top_global_idx)
&& (*(uint32*)(frame_sp - 1) < exec_env->aux_stack_boundary))
goto out_of_bounds;
case VALUE_TYPE_F32:
*(int32*)global_addr = POP_I32();
break;

View File

@ -877,6 +877,18 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
}
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#define CHECK_SUSPEND_FLAGS() do { \
if (exec_env->suspend_flags != 0) { \
if (exec_env->suspend_flags & 0x01) { \
/* terminate current thread */ \
return; \
} \
/* TODO: support suspend and breakpoint */ \
} \
} while (0)
#endif
#if WASM_ENABLE_OPCODE_COUNTER != 0
typedef struct OpcodeInfo {
char *name;
@ -978,6 +990,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint8 *maddr = NULL;
uint32 local_idx, local_offset, global_idx;
uint8 opcode, local_type, *global_addr;
int32 aux_stack_top_global_idx = -1;
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
@ -991,6 +1004,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#endif
#endif
/* If the aux stack information is resolved,
we will check the aux stack boundary */
if (module->module->llvm_aux_stack_size) {
aux_stack_top_global_idx = module->module->llvm_aux_stack_global_index;
}
#if WASM_ENABLE_LABELS_AS_VALUES == 0
while (frame_ip < frame_ip_end) {
opcode = *frame_ip++;
@ -1024,10 +1043,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_BR):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
RECOVER_BR_INFO();
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_BR_IF):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
cond = frame_lp[GET_OFFSET()];
if (cond)
@ -1039,6 +1064,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP_END ();
HANDLE_OP (WASM_OP_BR_TABLE):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
count = GET_OPERAND(uint32, 0);
didx = GET_OPERAND(uint32, 2);
frame_ip += 4;
@ -1064,6 +1092,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMType *cur_type, *cur_func_type;
WASMTableInstance *cur_table_inst;
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
tidx = GET_OPERAND(int32, 0);
val = GET_OPERAND(int32, 2);
frame_ip += 4;
@ -1245,6 +1277,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
switch (global->type) {
case VALUE_TYPE_I32:
/* Check aux stack boundary */
if ((global_idx == (uint32)aux_stack_top_global_idx)
&& (frame_lp[addr1] < exec_env->aux_stack_boundary))
goto out_of_bounds;
case VALUE_TYPE_F32:
*(int32*)global_addr = frame_lp[addr1];
break;
@ -2482,6 +2518,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto call_func_from_entry;
HANDLE_OP (WASM_OP_CALL):
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
fidx = frame_lp[GET_OFFSET()];
#if WASM_ENABLE_MULTI_MODULE != 0
if (fidx >= module->function_count) {

View File

@ -1117,6 +1117,12 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table,
else
table->max_size = 0x10000;
if ((table->flags & 1) && table->init_size > table->max_size) {
set_error_buf(error_buf, error_buf_size,
"size minimum must not be greater than maximum");
return false;
}
*p_buf = p;
return true;
}
@ -2349,8 +2355,6 @@ load_from_sections(WASMModule *module, WASMSection *sections,
WASMGlobal *llvm_stack_top_global = NULL, *global;
uint32 llvm_data_end = UINT32_MAX, llvm_heap_base = UINT32_MAX;
uint32 llvm_stack_top = UINT32_MAX, global_index, i;
uint32 data_end_global_index = UINT32_MAX;
uint32 heap_base_global_index = UINT32_MAX;
uint32 stack_top_global_index = UINT32_MAX;
BlockAddr *block_addr_cache;
uint64 total_size;
@ -2462,67 +2466,93 @@ load_from_sections(WASMModule *module, WASMSection *sections,
wasm_runtime_free(block_addr_cache);
/* Resolve llvm auxiliary data/stack/heap info and reset memory info */
if (!module->possible_memory_grow) {
export = module->exports;
for (i = 0; i < module->export_count; i++, export++) {
if (export->kind == EXPORT_KIND_GLOBAL) {
if (!strcmp(export->name, "__heap_base")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
heap_base_global_index = global_index;
llvm_heap_base_global = global;
llvm_heap_base = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __heap_base global, value: %d\n",
llvm_heap_base);
}
}
else if (!strcmp(export->name, "__data_end")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
data_end_global_index = global_index;
llvm_data_end_global = global;
llvm_data_end = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __data_end global, value: %d\n",
llvm_data_end);
llvm_data_end = align_uint(llvm_data_end, 16);
}
}
if (llvm_data_end_global && llvm_heap_base_global) {
if ((data_end_global_index == heap_base_global_index + 1
&& (int32)data_end_global_index > 1)
|| (heap_base_global_index == data_end_global_index + 1
&& (int32)heap_base_global_index > 1)) {
global_index =
data_end_global_index < heap_base_global_index
? data_end_global_index - 1 : heap_base_global_index - 1;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
llvm_stack_top_global = global;
llvm_stack_top = global->init_expr.u.i32;
stack_top_global_index = global_index;
LOG_VERBOSE("found llvm stack top global, "
"value: %d, global index: %d\n",
llvm_stack_top, global_index);
}
}
break;
export = module->exports;
for (i = 0; i < module->export_count; i++, export++) {
if (export->kind == EXPORT_KIND_GLOBAL) {
if (!strcmp(export->name, "__heap_base")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
llvm_heap_base_global = global;
llvm_heap_base = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __heap_base global, value: %d\n",
llvm_heap_base);
}
}
}
else if (!strcmp(export->name, "__data_end")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
llvm_data_end_global = global;
llvm_data_end = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __data_end global, value: %d\n",
llvm_data_end);
llvm_data_end = align_uint(llvm_data_end, 16);
}
}
/* For module compiled with -pthread option, the global is:
[0] stack_top <-- 0
[1] tls_pointer
[2] tls_size
[3] data_end <-- 3
[4] global_base
[5] heap_base <-- 5
[6] dso_handle
For module compiled without -pthread option:
[0] stack_top <-- 0
[1] data_end <-- 1
[2] global_base
[3] heap_base <-- 3
[4] dso_handle
*/
if (llvm_data_end_global && llvm_heap_base_global) {
/* Resolve aux stack top global */
for (global_index = 0; global_index < module->global_count; global_index++) {
global = module->globals + global_index;
if (global != llvm_data_end_global
&& global != llvm_heap_base_global
&& global->type == VALUE_TYPE_I32
&& global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST
&& (global->init_expr.u.i32 ==
llvm_heap_base_global->init_expr.u.i32
|| global->init_expr.u.i32 ==
llvm_data_end_global->init_expr.u.i32)) {
llvm_stack_top_global = global;
llvm_stack_top = global->init_expr.u.i32;
stack_top_global_index = global_index;
LOG_VERBOSE("found llvm stack top global, "
"value: %d, global index: %d\n",
llvm_stack_top, global_index);
break;
}
}
module->llvm_aux_data_end = llvm_data_end;
module->llvm_aux_stack_bottom = llvm_stack_top;
module->llvm_aux_stack_size = llvm_stack_top > llvm_data_end
? llvm_stack_top - llvm_data_end
: llvm_stack_top;
module->llvm_aux_stack_global_index = stack_top_global_index;
LOG_VERBOSE("aux stack bottom: %d, size: %d\n",
module->llvm_aux_stack_bottom,
module->llvm_aux_stack_size);
break;
}
}
}
if (!module->possible_memory_grow) {
if (llvm_data_end_global
&& llvm_heap_base_global
&& llvm_stack_top_global
@ -2557,16 +2587,6 @@ load_from_sections(WASMModule *module, WASMSection *sections,
LOG_VERBOSE("reset memory size to %d\n", shrunk_memory_size);
}
}
module->llvm_aux_data_end = llvm_data_end;
module->llvm_aux_stack_bottom = llvm_stack_top;
module->llvm_aux_stack_size = llvm_stack_top > llvm_data_end
? llvm_stack_top - llvm_data_end
: llvm_stack_top;
module->llvm_aux_stack_global_index = stack_top_global_index;
LOG_VERBOSE("aux stack bottom: %d, size: %d\n",
module->llvm_aux_stack_bottom,
module->llvm_aux_stack_size);
}
}
@ -3485,6 +3505,7 @@ fail:
return false;
}
static bool
check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type,
char *error_buf, uint32 error_buf_size)

View File

@ -1545,67 +1545,76 @@ load_from_sections(WASMModule *module, WASMSection *sections,
wasm_runtime_free(block_addr_cache);
/* Resolve llvm auxiliary data/stack/heap info and reset memory info */
if (!module->possible_memory_grow) {
export = module->exports;
for (i = 0; i < module->export_count; i++, export++) {
if (export->kind == EXPORT_KIND_GLOBAL) {
if (!strcmp(export->name, "__heap_base")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
heap_base_global_index = global_index;
llvm_heap_base_global = global;
llvm_heap_base = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __heap_base global, value: %d\n",
llvm_heap_base);
}
}
else if (!strcmp(export->name, "__data_end")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
data_end_global_index = global_index;
llvm_data_end_global = global;
llvm_data_end = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __data_end global, value: %d\n",
llvm_data_end);
llvm_data_end = align_uint(llvm_data_end, 16);
}
}
if (llvm_data_end_global && llvm_heap_base_global) {
if ((data_end_global_index == heap_base_global_index + 1
&& (int32)data_end_global_index > 1)
|| (heap_base_global_index == data_end_global_index + 1
&& (int32)heap_base_global_index > 1)) {
global_index =
data_end_global_index < heap_base_global_index
? data_end_global_index - 1 : heap_base_global_index - 1;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
llvm_stack_top_global = global;
llvm_stack_top = global->init_expr.u.i32;
stack_top_global_index = global_index;
LOG_VERBOSE("found llvm stack top global, "
"value: %d, global index: %d\n",
llvm_stack_top, global_index);
}
}
break;
export = module->exports;
for (i = 0; i < module->export_count; i++, export++) {
if (export->kind == EXPORT_KIND_GLOBAL) {
if (!strcmp(export->name, "__heap_base")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
heap_base_global_index = global_index;
llvm_heap_base_global = global;
llvm_heap_base = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __heap_base global, value: %d\n",
llvm_heap_base);
}
}
}
else if (!strcmp(export->name, "__data_end")) {
global_index = export->index - module->import_global_count;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& !global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
data_end_global_index = global_index;
llvm_data_end_global = global;
llvm_data_end = global->init_expr.u.i32;
LOG_VERBOSE("found llvm __data_end global, value: %d\n",
llvm_data_end);
llvm_data_end = align_uint(llvm_data_end, 16);
}
}
if (llvm_data_end_global && llvm_heap_base_global) {
if ((data_end_global_index == heap_base_global_index + 1
&& (int32)data_end_global_index > 1)
|| (heap_base_global_index == data_end_global_index + 1
&& (int32)heap_base_global_index > 1)) {
global_index =
data_end_global_index < heap_base_global_index
? data_end_global_index - 1 : heap_base_global_index - 1;
global = module->globals + global_index;
if (global->type == VALUE_TYPE_I32
&& global->is_mutable
&& global->init_expr.init_expr_type ==
INIT_EXPR_TYPE_I32_CONST) {
llvm_stack_top_global = global;
llvm_stack_top = global->init_expr.u.i32;
stack_top_global_index = global_index;
LOG_VERBOSE("found llvm stack top global, "
"value: %d, global index: %d\n",
llvm_stack_top, global_index);
}
}
module->llvm_aux_data_end = llvm_data_end;
module->llvm_aux_stack_bottom = llvm_stack_top;
module->llvm_aux_stack_size = llvm_stack_top > llvm_data_end
? llvm_stack_top - llvm_data_end
: llvm_stack_top;
module->llvm_aux_stack_global_index = stack_top_global_index;
LOG_VERBOSE("aux stack bottom: %d, size: %d\n",
module->llvm_aux_stack_bottom,
module->llvm_aux_stack_size);
break;
}
}
}
if (!module->possible_memory_grow) {
if (llvm_data_end_global
&& llvm_heap_base_global
&& llvm_stack_top_global
@ -1640,16 +1649,6 @@ load_from_sections(WASMModule *module, WASMSection *sections,
LOG_VERBOSE("reset memory size to %d\n", shrunk_memory_size);
}
}
module->llvm_aux_data_end = llvm_data_end;
module->llvm_aux_stack_bottom = llvm_stack_top;
module->llvm_aux_stack_size = llvm_stack_top > llvm_data_end
? llvm_stack_top - llvm_data_end
: llvm_stack_top;
module->llvm_aux_stack_global_index = stack_top_global_index;
LOG_VERBOSE("aux stack bottom: %d, size: %d\n",
module->llvm_aux_stack_bottom,
module->llvm_aux_stack_size);
}
}

View File

@ -10,6 +10,9 @@
#include "bh_log.h"
#include "mem_alloc.h"
#include "../common/wasm_runtime_common.h"
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
#endif
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
@ -86,6 +89,19 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
#if WASM_ENABLE_MULTI_MODULE != 0
if (memories[i]->owner != module_inst)
continue;
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memories[i]->is_shared) {
int32 ref_count =
shared_memory_dec_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count >= 0);
/* if the reference count is not zero,
don't free the memory */
if (ref_count > 0)
continue;
}
#endif
if (memories[i]->heap_handle) {
mem_allocator_destroy(memories[i]->heap_handle);
@ -99,16 +115,45 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
}
static WASMMemoryInstance*
memory_instantiate(uint32 num_bytes_per_page,
memory_instantiate(WASMModuleInstance *module_inst,
uint32 num_bytes_per_page,
uint32 init_page_count, uint32 max_page_count,
uint32 heap_size,
uint32 heap_size, uint32 flags,
char *error_buf, uint32 error_buf_size)
{
WASMMemoryInstance *memory;
uint64 total_size = offsetof(WASMMemoryInstance, base_addr) +
(uint64)heap_size +
uint64 heap_and_inst_size = offsetof(WASMMemoryInstance, base_addr) +
(uint64)heap_size;
uint64 total_size = heap_and_inst_size +
num_bytes_per_page * (uint64)init_page_count;
#if WASM_ENABLE_SHARED_MEMORY != 0
bool is_shared_memory = flags & 0x02 ? true : false;
/* shared memory */
if (is_shared_memory) {
WASMSharedMemNode *node =
wasm_module_get_shared_memory(
(WASMModuleCommon *)module_inst->module);
/* If the memory of this module has been instantiated,
return the memory instance directly */
if (node) {
uint32 ref_count;
ref_count = shared_memory_inc_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count > 0);
memory = shared_memory_get_memory_inst(node);
bh_assert(memory);
(void)ref_count;
return memory;
}
/* Allocate max page for shared memory */
total_size = heap_and_inst_size +
num_bytes_per_page * (uint64)max_page_count;
}
#endif
/* Allocate memory space, addr data and global data */
if (!(memory = runtime_malloc(total_size,
error_buf, error_buf_size))) {
@ -121,8 +166,17 @@ memory_instantiate(uint32 num_bytes_per_page,
memory->heap_data = memory->base_addr;
memory->memory_data = memory->heap_data + heap_size;
memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->cur_page_count;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->max_page_count;
}
else
#endif
{
memory->end_addr = memory->memory_data +
num_bytes_per_page * memory->cur_page_count;
}
bh_assert(memory->end_addr - (uint8*)memory == (uint32)total_size);
@ -134,10 +188,20 @@ memory_instantiate(uint32 num_bytes_per_page,
return NULL;
}
#if WASM_ENABLE_SPEC_TEST == 0
memory->heap_base_offset = -(int32)heap_size;
#else
memory->heap_base_offset = 0;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory->is_shared = true;
if (!shared_memory_set_memory_inst(
(WASMModuleCommon *)module_inst->module, memory)) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed:"
"allocate memory failed.");
wasm_runtime_free(memory);
return NULL;
}
}
#endif
return memory;
}
@ -169,6 +233,7 @@ memories_instantiate(const WASMModule *module,
uint32 num_bytes_per_page = import->u.memory.num_bytes_per_page;
uint32 init_page_count = import->u.memory.init_page_count;
uint32 max_page_count = import->u.memory.max_page_count;
uint32 flags = import->u.memory.flags;
uint32 actual_heap_size = heap_size;
#if WASM_ENABLE_MULTI_MODULE != 0
@ -197,8 +262,9 @@ memories_instantiate(const WASMModule *module,
#endif
{
if (!(memory = memories[mem_index++] = memory_instantiate(
num_bytes_per_page, init_page_count, max_page_count,
actual_heap_size, error_buf, error_buf_size))) {
module_inst, num_bytes_per_page, init_page_count,
max_page_count, actual_heap_size, flags,
error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: "
"allocate memory failed.");
@ -213,10 +279,12 @@ memories_instantiate(const WASMModule *module,
/* instantiate memories from memory section */
for (i = 0; i < module->memory_count; i++) {
if (!(memory = memories[mem_index++] =
memory_instantiate(module->memories[i].num_bytes_per_page,
memory_instantiate(module_inst,
module->memories[i].num_bytes_per_page,
module->memories[i].init_page_count,
module->memories[i].max_page_count,
heap_size, error_buf, error_buf_size))) {
heap_size, module->memories[i].flags,
error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: "
"allocate memory failed.");
@ -236,7 +304,7 @@ memories_instantiate(const WASMModule *module,
* for wasm code
*/
if (!(memory = memories[mem_index++] =
memory_instantiate(0, 0, 0, heap_size,
memory_instantiate(module_inst, 0, 0, 0, heap_size, 0,
error_buf, error_buf_size))) {
set_error_buf(error_buf, error_buf_size,
"Instantiate memory failed: "
@ -792,6 +860,36 @@ execute_post_inst_function(WASMModuleInstance *module_inst)
0, NULL);
}
#if WASM_ENABLE_BULK_MEMORY != 0
static bool
execute_memory_init_function(WASMModuleInstance *module_inst)
{
WASMFunctionInstance *memory_init_func = NULL;
WASMType *memory_init_func_type;
uint32 i;
for (i = 0; i < module_inst->export_func_count; i++)
if (!strcmp(module_inst->export_functions[i].name, "__wasm_call_ctors")) {
memory_init_func = module_inst->export_functions[i].function;
break;
}
if (!memory_init_func)
/* Not found */
return true;
memory_init_func_type = memory_init_func->u.func->func_type;
if (memory_init_func_type->param_count != 0
|| memory_init_func_type->result_count != 0)
/* Not a valid function type, ignore it */
return true;
return wasm_create_exec_env_and_call_function(module_inst,
memory_init_func,
0, NULL);
}
#endif
static bool
execute_start_function(WASMModuleInstance *module_inst)
{
@ -819,7 +917,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
while (sub_module_list_node) {
WASMModule *sub_module = (WASMModule*)sub_module_list_node->module;
WASMModuleInstance *sub_module_inst = wasm_instantiate(
sub_module, stack_size, heap_size, error_buf, error_buf_size);
sub_module, false, stack_size, heap_size, error_buf, error_buf_size);
if (!sub_module_inst) {
LOG_DEBUG("instantiate %s failed",
sub_module_list_node->module_name);
@ -833,7 +931,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
if (!sub_module_inst_list_node) {
LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
sizeof(WASMSubModInstNode));
wasm_deinstantiate(sub_module_inst);
wasm_deinstantiate(sub_module_inst, false);
return false;
}
@ -859,7 +957,7 @@ sub_module_deinstantiate(WASMModuleInstance *module_inst)
while (node) {
WASMSubModInstNode *next_node = bh_list_elem_next(node);
bh_list_remove(list, node);
wasm_deinstantiate(node->module_inst);
wasm_deinstantiate(node->module_inst, false);
node = next_node;
}
}
@ -869,7 +967,7 @@ sub_module_deinstantiate(WASMModuleInstance *module_inst)
* Instantiate module
*/
WASMModuleInstance*
wasm_instantiate(WASMModule *module,
wasm_instantiate(WASMModule *module, bool is_sub_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
@ -887,10 +985,6 @@ wasm_instantiate(WASMModule *module,
/* Check heap size */
heap_size = align_uint(heap_size, 8);
if (heap_size == 0)
heap_size = APP_HEAP_SIZE_DEFAULT;
if (heap_size < APP_HEAP_SIZE_MIN)
heap_size = APP_HEAP_SIZE_MIN;
if (heap_size > APP_HEAP_SIZE_MAX)
heap_size = APP_HEAP_SIZE_MAX;
@ -904,6 +998,8 @@ wasm_instantiate(WASMModule *module,
memset(module_inst, 0, (uint32)sizeof(WASMModuleInstance));
module_inst->module = module;
#if WASM_ENABLE_MULTI_MODULE != 0
module_inst->sub_module_inst_list =
&module_inst->sub_module_inst_list_head;
@ -911,7 +1007,7 @@ wasm_instantiate(WASMModule *module,
error_buf, error_buf_size);
if (!ret) {
LOG_DEBUG("build a sub module list failed");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
#endif
@ -922,7 +1018,7 @@ wasm_instantiate(WASMModule *module,
module,
module_inst,
&global_data_size, error_buf, error_buf_size))) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
module_inst->global_count = global_count;
@ -946,7 +1042,7 @@ wasm_instantiate(WASMModule *module,
if (global_count > 0) {
if (!(module_inst->global_data = runtime_malloc
(global_data_size, error_buf, error_buf_size))) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
}
@ -978,7 +1074,7 @@ wasm_instantiate(WASMModule *module,
error_buf, error_buf_size)))
#endif
) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -989,7 +1085,7 @@ wasm_instantiate(WASMModule *module,
*/
if (!globals_instantiate_fix(globals, module,
error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1063,7 +1159,7 @@ wasm_instantiate(WASMModule *module,
memory_size);
set_error_buf(error_buf, error_buf_size,
"data segment does not fit.");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1075,7 +1171,7 @@ wasm_instantiate(WASMModule *module,
set_error_buf(
error_buf, error_buf_size,
"Instantiate module failed: data segment does not fit.");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1121,7 +1217,7 @@ wasm_instantiate(WASMModule *module,
table_seg->base_offset.u.i32, table->cur_size);
set_error_buf(error_buf, error_buf_size,
"elements segment does not fit");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1132,7 +1228,7 @@ wasm_instantiate(WASMModule *module,
table_seg->base_offset.u.i32, length, table->cur_size);
set_error_buf(error_buf, error_buf_size,
"elements segment does not fit");
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
@ -1149,18 +1245,22 @@ wasm_instantiate(WASMModule *module,
}
#if WASM_ENABLE_LIBC_WASI != 0
if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst,
module->wasi_args.dir_list,
module->wasi_args.dir_count,
module->wasi_args.map_dir_list,
module->wasi_args.map_dir_count,
module->wasi_args.env,
module->wasi_args.env_count,
module->wasi_args.argv,
module->wasi_args.argc,
error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst);
return NULL;
/* The sub-instance will get the wasi_ctx from main-instance */
if (!is_sub_inst) {
if (heap_size > 0
&& !wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst,
module->wasi_args.dir_list,
module->wasi_args.dir_count,
module->wasi_args.map_dir_list,
module->wasi_args.map_dir_count,
module->wasi_args.env,
module->wasi_args.env_count,
module->wasi_args.argv,
module->wasi_args.argc,
error_buf, error_buf_size)) {
wasm_deinstantiate(module_inst, false);
return NULL;
}
}
#endif
@ -1171,8 +1271,6 @@ wasm_instantiate(WASMModule *module,
&module_inst->functions[module->start_function];
}
module_inst->module = module;
/* module instance type */
module_inst->module_type = Wasm_Module_Bytecode;
@ -1190,16 +1288,36 @@ wasm_instantiate(WASMModule *module,
|| !execute_start_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
wasm_deinstantiate(module_inst);
wasm_deinstantiate(module_inst, false);
return NULL;
}
#if WASM_ENABLE_BULK_MEMORY != 0
#if WASM_ENABLE_LIBC_WASI != 0
if (!module->is_wasi_module) {
#endif
/* Only execute the memory init function for main instance because
the data segments will be dropped once initialized.
*/
if (!is_sub_inst) {
if (!execute_memory_init_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
wasm_deinstantiate(module_inst, false);
return NULL;
}
}
#if WASM_ENABLE_LIBC_WASI != 0
}
#endif
#endif
(void)global_data_end;
return module_inst;
}
void
wasm_deinstantiate(WASMModuleInstance *module_inst)
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
{
if (!module_inst)
return;
@ -1213,7 +1331,9 @@ wasm_deinstantiate(WASMModuleInstance *module_inst)
wasi contex are allocated from app heap, and if app heap is freed,
these fields will be set to NULL, we cannot free their internal data
which may allocated from global heap. */
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst);
/* Only destroy wasi ctx in the main module instance */
if (!is_sub_inst)
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst);
#endif
if (module_inst->memory_count > 0)
@ -1299,8 +1419,9 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
WASMExecEnv *exec_env;
bool ret;
if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst,
module_inst->default_wasm_stack_size))) {
if (!(exec_env = wasm_exec_env_create(
(WASMModuleInstanceCommon*)module_inst,
module_inst->default_wasm_stack_size))) {
wasm_set_exception(module_inst, "allocate memory failed.");
return false;
}
@ -1518,6 +1639,15 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
return false;
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memory->is_shared) {
/* For shared memory, we have reserved the maximum spaces during
instantiate, only change the cur_page_count here */
memory->cur_page_count = total_page_count;
return true;
}
#endif
if (heap_size > 0) {
/* Destroy heap's lock firstly, if its memory is re-allocated,
we cannot access its lock again. */
@ -1612,3 +1742,66 @@ wasm_call_indirect(WASMExecEnv *exec_env,
got_exception:
return false;
}
#if WASM_ENABLE_THREAD_MGR != 0
bool
wasm_set_aux_stack(WASMExecEnv *exec_env,
uint32 start_offset, uint32 size)
{
WASMModuleInstance *module_inst =
(WASMModuleInstance*)exec_env->module_inst;
uint32 stack_top_idx =
module_inst->module->llvm_aux_stack_global_index;
uint32 data_end =
module_inst->module->llvm_aux_data_end;
uint32 stack_bottom =
module_inst->module->llvm_aux_stack_bottom;
bool is_stack_before_data =
stack_bottom < data_end ? true : false;
/* Check the aux stack space, currently we don't allocate space in heap */
if ((is_stack_before_data && (size > start_offset))
|| ((!is_stack_before_data) && (start_offset - data_end < size)))
return false;
if (stack_bottom) {
/* The aux stack top is a wasm global,
set the initial value for the global */
uint8 *global_addr =
module_inst->global_data +
module_inst->globals[stack_top_idx].data_offset;
*(int32*)global_addr = start_offset;
/* The aux stack boundary is a constant value,
set the value to exec_env */
exec_env->aux_stack_boundary = start_offset - size;
return true;
}
return false;
}
bool
wasm_get_aux_stack(WASMExecEnv *exec_env,
uint32 *start_offset, uint32 *size)
{
WASMModuleInstance *module_inst =
(WASMModuleInstance*)exec_env->module_inst;
/* The aux stack information is resolved in loader
and store in module */
uint32 stack_bottom =
module_inst->module->llvm_aux_stack_bottom;
uint32 total_aux_stack_size =
module_inst->module->llvm_aux_stack_size;
if (stack_bottom != 0 && total_aux_stack_size != 0) {
if (start_offset)
*start_offset = stack_bottom;
if (size)
*size = total_aux_stack_size;
return true;
}
return false;
}
#endif

View File

@ -22,6 +22,10 @@ typedef struct WASMTableInstance WASMTableInstance;
typedef struct WASMGlobalInstance WASMGlobalInstance;
typedef struct WASMMemoryInstance {
#if WASM_ENABLE_SHARED_MEMORY != 0
/* shared memory flag */
bool is_shared;
#endif
/* Number bytes per page */
uint32 num_bytes_per_page;
/* Current page count */
@ -269,12 +273,12 @@ void
wasm_unload(WASMModule *module);
WASMModuleInstance *
wasm_instantiate(WASMModule *module,
wasm_instantiate(WASMModule *module, bool is_sub_inst,
uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size);
void
wasm_deinstantiate(WASMModuleInstance *module_inst);
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
WASMFunctionInstance *
wasm_lookup_function(const WASMModuleInstance *module_inst,
@ -358,6 +362,16 @@ wasm_call_indirect(WASMExecEnv *exec_env,
uint32_t element_indices,
uint32_t argc, uint32_t argv[]);
#if WASM_ENABLE_THREAD_MGR != 0
bool
wasm_set_aux_stack(WASMExecEnv *exec_env,
uint32 start_offset, uint32 size);
bool
wasm_get_aux_stack(WASMExecEnv *exec_env,
uint32 *start_offset, uint32 *size);
#endif
#ifdef __cplusplus
}
#endif