Support AssemblyScript's new/retain/release APIs (#460)

This commit is contained in:
Xu Jun 2020-12-07 16:37:49 +08:00 committed by GitHub
parent 5176fe2595
commit a84d51271c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 282 additions and 42 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -184,6 +184,7 @@ struct WASMModuleInstance {
WASMFunctionInstance *start_function;
WASMFunctionInstance *malloc_function;
WASMFunctionInstance *free_function;
WASMFunctionInstance *retain_function;
WASMModule *module;