diff --git a/.clang-format b/.clang-format index aa4cde60..f0ecd63b 100644 --- a/.clang-format +++ b/.clang-format @@ -44,7 +44,7 @@ BinPackParameters: false BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom BraceWrapping: - AfterCaseLabel: false + AfterCaseLabel: true AfterClass: true AfterControlStatement: false AfterEnum: false @@ -76,6 +76,7 @@ KeepEmptyLinesAtTheStartOfBlocks: false NamespaceIndentation: None PointerAlignment: Right ReflowComments: false +SortIncludes: false Standard: Auto StatementMacros: - Q_UNUSED diff --git a/assembly-script/package-lock.json b/assembly-script/package-lock.json index 97d4e290..0750cc05 100644 --- a/assembly-script/package-lock.json +++ b/assembly-script/package-lock.json @@ -5,24 +5,24 @@ "requires": true, "dependencies": { "assemblyscript": { - "version": "0.8.1", - "resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.8.1.tgz", - "integrity": "sha1-xcYnSSQG5th/QmiXs9kr0qUz9/4=", + "version": "0.17.4", + "resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.17.4.tgz", + "integrity": "sha1-1GEduJpClDNa1H7DxmYaJqRCh3E=", "dev": true, "requires": { - "binaryen": "89.0.0-nightly.20191113", + "binaryen": "98.0.0-nightly.20201109", "long": "^4.0.0" } }, "binaryen": { - "version": "89.0.0-nightly.20191113", - "resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-89.0.0-nightly.20191113.tgz", - "integrity": "sha1-oNORTzXJKXhzQeApELf/rrfYl6k=", + "version": "98.0.0-nightly.20201109", + "resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-98.0.0-nightly.20201109.tgz", + "integrity": "sha1-USv2yhXGe/dAIURzSkg25jmTqgU=", "dev": true }, "long": { "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flong%2Fdownload%2Flong-4.0.0.tgz", "integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=", "dev": true } diff --git a/assembly-script/package.json b/assembly-script/package.json index 00aaaaf9..56a64f3d 100644 --- a/assembly-script/package.json +++ b/assembly-script/package.json @@ -5,16 +5,16 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize --use abort=", - "build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize --use abort=", - "build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize --use abort=", - "build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize --use abort=", - "build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize --use abort=", + "build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --optimize --use abort=", + "build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --optimize --use abort=", + "build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --optimize --use abort=", + "build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --optimize --use abort=", + "build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --optimize --use abort=", "build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher" }, "author": "", "license": "ISC", "devDependencies": { - "assemblyscript": "^0.8.1" + "assemblyscript": "^0.17.4" } } diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 5bf2453d..5493b0c7 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -1681,6 +1681,7 @@ load_from_sections(AOTModule *module, AOTSection *sections, /* Resolve malloc and free function */ module->malloc_func_index = (uint32)-1; module->free_func_index = (uint32)-1; + module->retain_func_index = (uint32)-1; exports = module->exports; for (i = 0; i < module->export_count; i++) { @@ -1694,21 +1695,73 @@ load_from_sections(AOTModule *module, AOTSection *sections, && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { + bh_assert(module->malloc_func_index == (uint32)-1); module->malloc_func_index = func_index; - LOG_VERBOSE("Found malloc function, index: %u", - exports[i].index); + LOG_VERBOSE("Found malloc function, name: %s, index: %u", + exports[i].name, exports[i].index); } } - else if (!strcmp(exports[i].name, "free")) { + else if (!strcmp(exports[i].name, "__new")) { + func_index = exports[i].index - module->import_func_count; + func_type_index = module->func_type_indexes[func_index]; + func_type = module->func_types[func_type_index]; + if (func_type->param_count == 2 + && func_type->result_count == 1 + && func_type->types[0] == VALUE_TYPE_I32 + && func_type->types[1] == VALUE_TYPE_I32 + && func_type->types[2] == VALUE_TYPE_I32) { + uint32 j; + WASMExport *export_tmp; + + bh_assert(module->malloc_func_index == (uint32)-1); + module->malloc_func_index = func_index; + LOG_VERBOSE("Found malloc function, name: %s, index: %u", + exports[i].name, exports[i].index); + + /* resolve retain function. + If not find, reset malloc function index */ + export_tmp = module->exports; + for (j = 0; j < module->export_count; j++, export_tmp++) { + if ((export_tmp->kind == EXPORT_KIND_FUNC) + && (!strcmp(export_tmp->name, "__retain"))) { + func_index = export_tmp->index + - module->import_func_count; + func_type_index = + module->func_type_indexes[func_index]; + func_type = module->func_types[func_type_index]; + if (func_type->param_count == 1 + && func_type->result_count == 1 + && func_type->types[0] == VALUE_TYPE_I32 + && func_type->types[1] == VALUE_TYPE_I32) { + bh_assert( + module->retain_func_index == (uint32)-1); + module->retain_func_index = export_tmp->index; + LOG_VERBOSE( + "Found retain function, name: %s, index: %u", + export_tmp->name, export_tmp->index); + break; + } + } + } + if (j == module->export_count) { + module->malloc_func_index = (uint32)-1; + LOG_VERBOSE("Can't find retain function," + "reset malloc function index to -1"); + } + } + } + else if ((!strcmp(exports[i].name, "free")) + || (!strcmp(exports[i].name, "__release"))) { func_index = exports[i].index - module->import_func_count; func_type_index = module->func_type_indexes[func_index]; func_type = module->func_types[func_type_index]; if (func_type->param_count == 1 && func_type->result_count == 0 && func_type->types[0] == VALUE_TYPE_I32) { + bh_assert(module->free_func_index == (uint32)-1); module->free_func_index = func_index; - LOG_VERBOSE("Found free function, index: %u", - exports[i].index); + LOG_VERBOSE("Found free function, name: %s, index: %u", + exports[i].name, exports[i].index); } } } @@ -2057,6 +2110,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, module->malloc_func_index = comp_data->malloc_func_index; module->free_func_index = comp_data->free_func_index; + module->retain_func_index = comp_data->retain_func_index; module->aux_data_end_global_index = comp_data->aux_data_end_global_index; module->aux_data_end = comp_data->aux_data_end; diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index d6db2d51..32394518 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1263,23 +1263,39 @@ aot_clear_exception(AOTModuleInstance *module_inst) static bool execute_malloc_function(AOTModuleInstance *module_inst, AOTFunctionInstance *malloc_func, + AOTFunctionInstance *retain_func, uint32 size, uint32 *p_result) { - uint32 argv[2]; + uint32 argv[2], argc; bool ret; argv[0] = size; + argc = 1; + if (retain_func) { + argv[1] = 0; + argc = 2; + } + #ifdef OS_ENABLE_HW_BOUND_CHECK if (aot_exec_env != NULL) { bh_assert(aot_exec_env->module_inst == (WASMModuleInstanceCommon *)module_inst); - ret = aot_call_function(aot_exec_env, malloc_func, 1, argv); + ret = aot_call_function(aot_exec_env, malloc_func, argc, argv); + + if (retain_func && ret) { + ret = aot_call_function(aot_exec_env, retain_func, 1, argv); + } } else #endif { ret = aot_create_exec_env_and_call_function - (module_inst, malloc_func, 1, argv); + (module_inst, malloc_func, argc, argv); + + if (retain_func && ret) { + ret = aot_create_exec_env_and_call_function + (module_inst, retain_func, 1, argv); + } } if (ret) @@ -1328,11 +1344,27 @@ aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, } else if (module->malloc_func_index != (uint32)-1 && module->free_func_index != (uint32)-1) { - AOTFunctionInstance *malloc_func = - aot_lookup_function(module_inst, "malloc", "(i)i"); + AOTFunctionInstance *malloc_func, *retain_func = NULL; + char *malloc_func_name; + char *malloc_func_sig; + + if (module->retain_func_index != (uint32)-1) { + malloc_func_name = "__new"; + malloc_func_sig = "(ii)i"; + retain_func = + aot_lookup_function(module_inst, "__retain", "(i)i"); + bh_assert(retain_func); + } + else { + malloc_func_name = "malloc"; + malloc_func_sig = "(i)i"; + } + malloc_func = + aot_lookup_function(module_inst, + malloc_func_name, malloc_func_sig); bh_assert(malloc_func); - if (!execute_malloc_function(module_inst, malloc_func, + if (!execute_malloc_function(module_inst, malloc_func, retain_func, size, &offset)) { return 0; } @@ -1371,8 +1403,17 @@ aot_module_free(AOTModuleInstance *module_inst, uint32 ptr) && module->free_func_index != (uint32)-1 && (uint8 *)memory_inst->memory_data.ptr <= addr && addr < (uint8 *)memory_inst->memory_data_end.ptr) { - AOTFunctionInstance *free_func = - aot_lookup_function(module_inst, "free", "(i)i"); + AOTFunctionInstance *free_func; + char *free_func_name; + + if (module->retain_func_index != (uint32)-1) { + free_func_name = "__release"; + } + else { + free_func_name = "free"; + } + free_func = + aot_lookup_function(module_inst, free_func_name, "(i)i"); bh_assert(free_func); execute_free_function(module_inst, free_func, ptr); diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 2fa72158..87dc1166 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -149,6 +149,7 @@ typedef struct AOTModule { uint32 malloc_func_index; uint32 free_func_index; + uint32 retain_func_index; /* AOTed code, NULL for JIT mode */ void *code; diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 5e85cc1f..fd127c81 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -512,6 +512,7 @@ aot_create_comp_data(WASMModule *module) comp_data->start_func_index = module->start_function; comp_data->malloc_func_index = module->malloc_function; comp_data->free_func_index = module->free_function; + comp_data->retain_func_index = module->retain_function; comp_data->wasm_module = module; diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index a898ad04..63379236 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -206,6 +206,7 @@ typedef struct AOTCompData { uint32 start_func_index; uint32 malloc_func_index; uint32 free_func_index; + uint32 retain_func_index; uint32 aux_data_end_global_index; uint32 aux_data_end; diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 040b3312..feae8eff 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -371,6 +371,10 @@ struct WASMModule { uint32 malloc_function; uint32 free_function; + /* the index of __retain function, + -1 means unexported */ + uint32 retain_function; + /* Whether there is possible memory grow, e.g. memory.grow opcode */ bool possible_memory_grow; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f4b71805..5ba09257 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -2762,8 +2762,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, module->malloc_function = (uint32)-1; module->free_function = (uint32)-1; + module->retain_function = (uint32)-1; - /* Resolve auxiliary data/stack/heap info and reset memory info */ + /* Resolve malloc/free function exported by wasm module */ export = module->exports; for (i = 0; i < module->export_count; i++, export++) { if (export->kind == EXPORT_KIND_FUNC) { @@ -2775,21 +2776,75 @@ load_from_sections(WASMModule *module, WASMSection *sections, && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { + bh_assert(module->malloc_function == (uint32)-1); module->malloc_function = export->index; - LOG_VERBOSE("Found malloc function, index: %u", - export->index); + LOG_VERBOSE("Found malloc function, name: %s, index: %u", + export->name, export->index); } } - else if (!strcmp(export->name, "free") + else if (!strcmp(export->name, "__new") + && export->index >= module->import_function_count) { + /* __new && __retain for AssemblyScript */ + func_index = export->index - module->import_function_count; + func_type = module->functions[func_index]->func_type; + if (func_type->param_count == 2 + && func_type->result_count == 1 + && func_type->types[0] == VALUE_TYPE_I32 + && func_type->types[1] == VALUE_TYPE_I32 + && func_type->types[2] == VALUE_TYPE_I32) { + uint32 j; + WASMExport *export_tmp; + + bh_assert(module->malloc_function == (uint32)-1); + module->malloc_function = export->index; + LOG_VERBOSE("Found malloc function, name: %s, index: %u", + export->name, export->index); + + /* resolve retain function. + If not find, reset malloc function index */ + export_tmp = module->exports; + for (j = 0; j < module->export_count; j++, export_tmp++) { + if ((export_tmp->kind == EXPORT_KIND_FUNC) + && (!strcmp(export_tmp->name, "__retain")) + && (export_tmp->index + >= module->import_function_count)) { + func_index = export_tmp->index + - module->import_function_count; + func_type = + module->functions[func_index]->func_type; + if (func_type->param_count == 1 + && func_type->result_count == 1 + && func_type->types[0] == VALUE_TYPE_I32 + && func_type->types[1] == VALUE_TYPE_I32) { + bh_assert( + module->retain_function == (uint32)-1); + module->retain_function = export_tmp->index; + LOG_VERBOSE( + "Found retain function, name: %s, index: %u", + export_tmp->name, export_tmp->index); + break; + } + } + } + if (j == module->export_count) { + module->malloc_function = (uint32)-1; + LOG_VERBOSE("Can't find retain function," + "reset malloc function index to -1"); + } + } + } + else if (((!strcmp(export->name, "free")) + || (!strcmp(export->name, "__release"))) && export->index >= module->import_function_count) { func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; if (func_type->param_count == 1 && func_type->result_count == 0 && func_type->types[0] == VALUE_TYPE_I32) { + bh_assert(module->free_function == (uint32)-1); module->free_function = export->index; - LOG_VERBOSE("Found free function, index: %u", - export->index); + LOG_VERBOSE("Found free function, name: %s, index: %u", + export->name, export->index); } } } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index d25a310f..cb1222a4 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -1701,7 +1701,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, module->malloc_function = (uint32)-1; module->free_function = (uint32)-1; - /* Resolve auxiliary data/stack/heap info and reset memory info */ + /* Resolve malloc/free function exported by wasm module */ export = module->exports; for (i = 0; i < module->export_count; i++, export++) { if (export->kind == EXPORT_KIND_FUNC) { @@ -1713,21 +1713,75 @@ load_from_sections(WASMModule *module, WASMSection *sections, && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { + bh_assert(module->malloc_function == (uint32)-1); module->malloc_function = export->index; - LOG_VERBOSE("Found malloc function, index: %u", - export->index); + LOG_VERBOSE("Found malloc function, name: %s, index: %u", + export->name, export->index); } } - else if (!strcmp(export->name, "free") + else if (!strcmp(export->name, "__new") + && export->index >= module->import_function_count) { + /* __new && __retain for AssemblyScript */ + func_index = export->index - module->import_function_count; + func_type = module->functions[func_index]->func_type; + if (func_type->param_count == 2 + && func_type->result_count == 1 + && func_type->types[0] == VALUE_TYPE_I32 + && func_type->types[1] == VALUE_TYPE_I32 + && func_type->types[2] == VALUE_TYPE_I32) { + uint32 j; + WASMExport *export_tmp; + + bh_assert(module->malloc_function == (uint32)-1); + module->malloc_function = export->index; + LOG_VERBOSE("Found malloc function, name: %s, index: %u", + export->name, export->index); + + /* resolve retain function. + If not find, reset malloc function index */ + export_tmp = module->exports; + for (j = 0; j < module->export_count; j++, export_tmp++) { + if ((export_tmp->kind == EXPORT_KIND_FUNC) + && (!strcmp(export_tmp->name, "__retain")) + && (export_tmp->index + >= module->import_function_count)) { + func_index = export_tmp->index + - module->import_function_count; + func_type = + module->functions[func_index]->func_type; + if (func_type->param_count == 1 + && func_type->result_count == 1 + && func_type->types[0] == VALUE_TYPE_I32 + && func_type->types[1] == VALUE_TYPE_I32) { + bh_assert( + module->retain_function == (uint32)-1); + module->retain_function = export_tmp->index; + LOG_VERBOSE( + "Found retain function, name: %s, index: %u", + export_tmp->name, export_tmp->index); + break; + } + } + } + if (j == module->export_count) { + module->malloc_function = (uint32)-1; + LOG_VERBOSE("Can't find retain function," + "reset malloc function index to -1"); + } + } + } + else if (((!strcmp(export->name, "free")) + || (!strcmp(export->name, "__release"))) && export->index >= module->import_function_count) { func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; if (func_type->param_count == 1 && func_type->result_count == 0 && func_type->types[0] == VALUE_TYPE_I32) { + bh_assert(module->free_function == (uint32)-1); module->free_function = export->index; - LOG_VERBOSE("Found free function, index: %u", - export->index); + LOG_VERBOSE("Found free function, name: %s, index: %u", + export->name, export->index); } } } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 7f32b5ae..f6382f60 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -970,14 +970,35 @@ execute_start_function(WASMModuleInstance *module_inst) static bool execute_malloc_function(WASMModuleInstance *module_inst, WASMFunctionInstance *malloc_func, + WASMFunctionInstance *retain_func, uint32 size, uint32 *p_result) { - uint32 argv[2]; + uint32 argv[2], argc; bool ret; argv[0] = size; + argc = 1; + + /* if __retain is exported, then this module is compiled by + assemblyscript, the memory should be managed by as's runtime, + in this case we need to call the retain function after malloc + the memory */ + if (retain_func) { + /* the malloc functino from assemblyscript is: + function __new(size: usize, id: u32) + id = 0 means this is an ArrayBuffer object */ + argv[1] = 0; + argc = 2; + } + ret = wasm_create_exec_env_and_call_function - (module_inst, malloc_func, 1, argv); + (module_inst, malloc_func, argc, argv); + + if (retain_func && ret) { + ret = wasm_create_exec_env_and_call_function + (module_inst, retain_func, 1, argv); + } + if (ret) *p_result = argv[0]; return ret; @@ -1409,6 +1430,11 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, &module_inst->functions[module->free_function]; } + if (module->retain_function != (uint32)-1) { + module_inst->retain_function = + &module_inst->functions[module->retain_function]; + } + #if WASM_ENABLE_LIBC_WASI != 0 /* The sub-instance will get the wasi_ctx from main-instance */ if (!is_sub_inst) { @@ -1651,6 +1677,7 @@ wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, && module_inst->free_function) { if (!execute_malloc_function(module_inst, module_inst->malloc_function, + module_inst->retain_function, size, &offset)) { return 0; } diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 242d5f12..4f13b689 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -184,6 +184,7 @@ struct WASMModuleInstance { WASMFunctionInstance *start_function; WASMFunctionInstance *malloc_function; WASMFunctionInstance *free_function; + WASMFunctionInstance *retain_function; WASMModule *module;