Просмотр исходного кода

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

Xu Jun 5 лет назад
Родитель
Сommit
a84d51271c

+ 2 - 1
.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

+ 8 - 8
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
     }

+ 6 - 6
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"
   }
 }

+ 59 - 5
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;

+ 49 - 8
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);

+ 1 - 0
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;

+ 1 - 0
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;
 

+ 1 - 0
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;

+ 4 - 0
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;
 

+ 61 - 6
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, name: %s, index: %u",
+                                export->name, export->index);
+                }
+            }
+            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, index: %u",
-                                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")
+            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);
                 }
             }
         }

+ 60 - 6
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, name: %s, index: %u",
+                                export->name, export->index);
+                }
+            }
+            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, index: %u",
-                                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")
+            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);
                 }
             }
         }

+ 29 - 2
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;
         }

+ 1 - 0
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;