diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index 59239b72a..04b5fa25b 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -8,6 +8,8 @@ WAMR project reused some components from other open source project: - **freebsd libm**: used in core/shared/platform/alios/bh_math.c - **littlevgl**: for the gui samples and wrapped the wasm graphic layer. +The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated oprand stack location. + ## Licenses ### wasmtime diff --git a/README.md b/README.md index d16353ea8..faf50a57e 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,13 @@ iwasm VM core ### key features -- [Embeddable with the supporting C API's](./doc/embed_wamr.md) +- 100% compliant to the W3C WASM MVP - Small runtime binary size (85K for interpreter and 50K for AoT) and low memory usage -- Near to native speed by AoT -- Unique AoT support for embedded systems which have no system loaders +- Near to native speed by AoT +- Self-implemented module loader enables AoT working cross Linux, SGX and MCU systems - Choices of WASM application libc support: the built-in libc subset for the embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc -- [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md) +- [Embeddable with the supporting C API's](./doc/embed_wamr.md) +- [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md) ### Supported architectures and platforms @@ -36,11 +37,11 @@ The iwasm supports the following architectures: - MIPS - XTENSA -Following platforms are supported: +Following platforms are supported. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. - [Linux](./doc/build_wamr.md#linux), [Zephyr](./doc/build_wamr.md#zephyr), [MacOS](./doc/build_wamr.md#macos), [VxWorks](./doc/build_wamr.md#vxworks), [AliOS-Things](./doc/build_wamr.md#alios-things), [Intel Software Guard Extention (Linux)](./doc/build_wamr.md#linux-sgx-intel-software-guard-extention), [Android](./doc/build_wamr.md#android) -Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. + ### Build wamrc AoT compiler @@ -52,7 +53,7 @@ cd wamr-compiler mkdir build && cd build cmake .. make -ln -s ./wamrc /usr/bin/wamrc +ln -s {current path}/wamrc /usr/bin/wamrc ``` ### Build the mini product @@ -76,27 +77,26 @@ Browse the folder [core/app-framework](./core/app-framework) for how to extend # Remote application management -The WAMR application manager supports remote application management from the host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes. +The WAMR application manager supports [remote application management](./core/app-mgr) from the host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes. The tool [host_tool](./test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from the host system. And the [IoT App Store Demo](./test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from the cloud. -Browse the folder [core/app-mgr](./core/app-mgr) for the details. WAMR SDK ========== Usually there are two tasks for integrating the WAMR into a particular project: -- Select what WAMR components (vmcore, libc, app-mgr, app-framework components) to be integrated, and get the associated source files added into the project building configuration +- Select what WAMR components (vmcore, libc, app-mgr, app-framework components) to be integrated, and get the associated source files added into the project building configuration - Generate the APP SDK for developing the WASM apps on the selected libc and framework components -The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly. It supports menu configuration for selecting WAMR components and builds the WAMR to a SDK package that includes **runtime SDK** and **APP SDK**. The runtime SDK is used for building the native application and the APP SDK should be shipped to WASM application developers. +The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly. It supports menu configuration for selecting WAMR components and builds the WAMR to a SDK package that includes **runtime SDK** and **APP SDK**. The runtime SDK is used for building the native application and the APP SDK should be shipped to WASM application developers. Samples ================= -The WAMR samples integrate the iwasm VM core, application manager and selected application framework components. The samples are located in folder [samples](./samples): +The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components. - **[Simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default. - **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. It uses **WASI libc** and executes apps in **AoT mode** by default. - **[gui](./samples/gui/README.md)**: Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default. diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 6d4c02851..8cb6ed141 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -127,4 +127,11 @@ if (WAMR_BUILD_LIBC_WASI EQUAL 1) else () message (" Libc WASI disbled") endif () +if (WAMR_BUILD_FAST_INTERP EQUAL 1) + add_definitions (-DWASM_ENABLE_FAST_INTERP=1) + message (" Fast interpreter enabled") +else () + add_definitions (-DWASM_ENABLE_FAST_INTERP=0) + message (" Fast interpreter disbled") +endif () diff --git a/core/app-framework/README.md b/core/app-framework/README.md index 0deb4af86..34f0e27eb 100644 --- a/core/app-framework/README.md +++ b/core/app-framework/README.md @@ -7,7 +7,7 @@ Application framework This folder "app-native-shared" is for the source files shared by both WASM APP and native runtime -- The c files in this directory are compiled into both the WASM APP and runtime. +- The c files in this directory are compiled into both the WASM APP and runtime. - The header files for distributing to SDK are placed in the "bi-inc" folder. @@ -16,7 +16,7 @@ This folder "template" contains a pre-defined directory structure for a framewor -Every other subfolder is framework component. Each component contains two library parts: **app and native**. +Every other subfolder is framework component. Each component contains two library parts: **app and native**. - The "base" component provide timer API and inter-app communication support. It must be enabled if other components are selected. - Under the "app" folder of a component, the subfolder "wa_inc" holds all header files that should be included by the WASM applications @@ -85,13 +85,13 @@ Generally you should follow following steps to create a new component: ```c //use right signature for your functions - EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_1, "(i*~)i"), + EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_1, "(i*~)i"), EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_2, "(i)i"), ``` - Ensure "wasm_lib.cmake" is provided as it will be included by the WAMR SDK building script - - Add a definition in "wasm_lib.cmake" for your component, e.g. + - Add a definition in "wasm_lib.cmake" for your component, e.g. ```cmake add_definitions (-DAPP_FRAMEWORK_MY_COMPONENT) @@ -101,12 +101,12 @@ Generally you should follow following steps to create a new component: ``` #include "lib_export.h" - + ... #ifdef APP_FRAMEWORK_MY_COMPONENT // this definition is created in wasm_lib.cmake #include "my_component_native_api.h" #endif - + static NativeSymbol extended_native_symbol_defs[] = { ... #ifdef APP_FRAMEWORK_MY_COMPONENT @@ -115,7 +115,7 @@ Generally you should follow following steps to create a new component: }; ``` - + ## Sensor component working flow diff --git a/core/app-framework/app-native-shared/attr_container.c b/core/app-framework/app-native-shared/attr_container.c index 5145ac70b..478bef0e3 100644 --- a/core/app-framework/app-native-shared/attr_container.c +++ b/core/app-framework/app-native-shared/attr_container.c @@ -16,10 +16,14 @@ typedef union jvalue { double d; } jvalue; +#ifndef bh_memcpy_s +int b_memcpy_s(void * s1, unsigned int s1max, + const void * s2, unsigned int n); #define bh_memcpy_s(dest, dlen, src, slen) do { \ int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \ (void)_ret; \ } while (0) +#endif static inline int16_t get_int16(const char *buf) { diff --git a/core/app-framework/app-native-shared/bi-inc/attr_container.h b/core/app-framework/app-native-shared/bi-inc/attr_container.h index 52e0ebcc0..d8fc08e4b 100644 --- a/core/app-framework/app-native-shared/bi-inc/attr_container.h +++ b/core/app-framework/app-native-shared/bi-inc/attr_container.h @@ -406,11 +406,11 @@ void attr_container_dump(const attr_container_t *attr_cont); #ifndef attr_container_malloc -#define attr_container_malloc wa_malloc +#define attr_container_malloc WA_MALLOC #endif #ifndef attr_container_free -#define attr_container_free wa_free +#define attr_container_free WA_FREE #endif #ifndef attr_container_printf diff --git a/core/app-framework/app-native-shared/bi-inc/shared_utils.h b/core/app-framework/app-native-shared/bi-inc/shared_utils.h index 2ce84a1f0..3154b4b5c 100644 --- a/core/app-framework/app-native-shared/bi-inc/shared_utils.h +++ b/core/app-framework/app-native-shared/bi-inc/shared_utils.h @@ -145,6 +145,8 @@ unpack_response(char * packet, int size, response_t * response); void free_req_resp_packet(char * packet); +char * +wa_strdup(const char *str); #ifdef __cplusplus diff --git a/core/app-framework/app-native-shared/restful_utils.c b/core/app-framework/app-native-shared/restful_utils.c index 5edc47081..4907df017 100644 --- a/core/app-framework/app-native-shared/restful_utils.c +++ b/core/app-framework/app-native-shared/restful_utils.c @@ -43,7 +43,7 @@ char * pack_request(request_t *request, int * size) { int url_len = strlen(request->url) + 1; int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len; - char * packet = (char*) wa_malloc(len); + char * packet = (char*) WA_MALLOC(len); if (packet == NULL) return NULL; @@ -65,7 +65,7 @@ char * pack_request(request_t *request, int * size) void free_req_resp_packet(char * packet) { - wa_free(packet); + WA_FREE(packet); } request_t * unpack_request(char * packet, int size, request_t * request) @@ -108,7 +108,7 @@ request_t * unpack_request(char * packet, int size, request_t * request) char * pack_response(response_t *response, int * size) { int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len; - char * packet = (char*) wa_malloc(len); + char * packet = (char*) WA_MALLOC(len); if (packet == NULL) return NULL; @@ -152,7 +152,7 @@ response_t * unpack_response(char * packet, int size, response_t * response) request_t *clone_request(request_t *request) { /* deep clone */ - request_t *req = (request_t *) wa_malloc(sizeof(request_t)); + request_t *req = (request_t *) WA_MALLOC(sizeof(request_t)); if (req == NULL) return NULL; @@ -169,7 +169,7 @@ request_t *clone_request(request_t *request) req->payload_len = request->payload_len; if (request->payload_len) { - req->payload = (char *) wa_malloc(request->payload_len); + req->payload = (char *) WA_MALLOC(request->payload_len); if (!req->payload) goto fail; memcpy(req->payload, request->payload, request->payload_len); @@ -188,24 +188,24 @@ fail: void request_cleaner(request_t *request) { if (request->url != NULL) - wa_free(request->url); + WA_FREE(request->url); if (request->payload != NULL && request->payload_len > 0) - wa_free(request->payload); + WA_FREE(request->payload); - wa_free(request); + WA_FREE(request); } void response_cleaner(response_t * response) { if (response->payload != NULL && response->payload_len > 0) - wa_free(response->payload); + WA_FREE(response->payload); - wa_free(response); + WA_FREE(response); } response_t * clone_response(response_t * response) { - response_t *clone = (response_t *) wa_malloc(sizeof(response_t)); + response_t *clone = (response_t *) WA_MALLOC(sizeof(response_t)); if (clone == NULL) return NULL; @@ -216,7 +216,7 @@ response_t * clone_response(response_t * response) clone->reciever = response->reciever; clone->payload_len = response->payload_len; if (clone->payload_len) { - clone->payload = (char *) wa_malloc(response->payload_len); + clone->payload = (char *) WA_MALLOC(response->payload_len); if (!clone->payload) goto fail; memcpy(clone->payload, response->payload, response->payload_len); diff --git a/core/app-framework/base/app/bh_platform.c b/core/app-framework/base/app/bh_platform.c index 37b828e0e..e539e8b0b 100644 --- a/core/app-framework/base/app/bh_platform.c +++ b/core/app-framework/base/app/bh_platform.c @@ -75,7 +75,7 @@ uint16 ntohs(uint16 value) char *wa_strdup(const char *s) { char *s1 = NULL; - if (s && (s1 = wa_malloc(strlen(s) + 1))) + if (s && (s1 = WA_MALLOC(strlen(s) + 1))) memcpy(s1, s, strlen(s) + 1); return s1; } diff --git a/core/app-framework/base/app/bh_platform.h b/core/app-framework/base/app/bh_platform.h index d44522c02..91b43bb25 100755 --- a/core/app-framework/base/app/bh_platform.h +++ b/core/app-framework/base/app/bh_platform.h @@ -25,14 +25,14 @@ typedef int int32; #define inline __inline #endif -// all wasm-app<->native shared source files should use wa_malloc/wa_free. +// all wasm-app<->native shared source files should use WA_MALLOC/WA_FREE. // they will be mapped to different implementations in each side -#ifndef wa_malloc -#define wa_malloc malloc +#ifndef WA_MALLOC +#define WA_MALLOC malloc #endif -#ifndef wa_free -#define wa_free free +#ifndef WA_FREE +#define WA_FREE free #endif char *wa_strdup(const char *s); diff --git a/core/app-framework/base/native/base_lib_export.c b/core/app-framework/base/native/base_lib_export.c index ee90f1da9..0b716fc5e 100644 --- a/core/app-framework/base/native/base_lib_export.c +++ b/core/app-framework/base/native/base_lib_export.c @@ -17,7 +17,7 @@ static NativeSymbol extended_native_symbol_defs[] = { #include "base_lib.inl" }; -int get_base_lib_export_apis(NativeSymbol **p_base_lib_apis) +uint32 get_base_lib_export_apis(NativeSymbol **p_base_lib_apis) { *p_base_lib_apis = extended_native_symbol_defs; return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol); diff --git a/core/app-framework/base/native/timer_wrapper.c b/core/app-framework/base/native/timer_wrapper.c index ba5db9e81..44887df9e 100644 --- a/core/app-framework/base/native/timer_wrapper.c +++ b/core/app-framework/base/native/timer_wrapper.c @@ -107,7 +107,7 @@ timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num) return NULL; timer_ctx_node_t * node = (timer_ctx_node_t*) - bh_malloc(sizeof(timer_ctx_node_t)); + wasm_runtime_malloc(sizeof(timer_ctx_node_t)); if (node == NULL) { destroy_timer_ctx(ctx); return NULL; @@ -131,7 +131,7 @@ void destroy_module_timer_ctx(unsigned int module_id) if (timer_ctx_get_owner(elem->timer_ctx) == module_id) { bh_list_remove(&g_timer_ctx_list, elem); destroy_timer_ctx(elem->timer_ctx); - bh_free(elem); + wasm_runtime_free(elem); break; } diff --git a/core/app-framework/connection/native/linux/connection_mgr.c b/core/app-framework/connection/native/linux/connection_mgr.c index cd8431a35..fe4ef6168 100644 --- a/core/app-framework/connection/native/linux/connection_mgr.c +++ b/core/app-framework/connection/native/linux/connection_mgr.c @@ -115,8 +115,8 @@ static void add_connection(sys_connection_t *conn) #define FREE_CONNECTION(conn) do { \ if (conn->arg) \ - bh_free(conn->arg); \ - bh_free(conn); \ + wasm_runtime_free(conn->arg); \ + wasm_runtime_free(conn); \ } while (0) static int get_app_conns_num(uint32 module_id) @@ -223,7 +223,7 @@ static uint32 _conn_open(wasm_module_inst_t module_inst, if (get_app_conns_num(module_id) >= MAX_CONNECTION_PER_APP) return -1; - conn = (sys_connection_t *)bh_malloc(sizeof(*conn)); + conn = (sys_connection_t *)wasm_runtime_malloc(sizeof(*conn)); if (conn == NULL) return -1; @@ -296,7 +296,7 @@ static uint32 _conn_open(wasm_module_inst_t module_inst, fail: find_connection(conn->handle, true); - bh_free(conn); + wasm_runtime_free(conn); return -1; } @@ -356,7 +356,7 @@ static bool _conn_config(uint32 handle, attr_container_t *cfg) port = attr_container_get_as_uint16(cfg, "port"); if (conn->arg == NULL) { - addr = (struct sockaddr_in *)bh_malloc(sizeof(*addr)); + addr = (struct sockaddr_in *)wasm_runtime_malloc(sizeof(*addr)); if (addr == NULL) return false; @@ -390,8 +390,8 @@ typedef struct connection_event { static void connection_event_cleaner(connection_event_t *conn_event) { if (conn_event->data != NULL) - bh_free(conn_event->data); - bh_free(conn_event); + wasm_runtime_free(conn_event->data); + wasm_runtime_free(conn_event); } static void post_msg_to_module(sys_connection_t *conn, @@ -406,14 +406,14 @@ static void post_msg_to_module(sys_connection_t *conn, if (module == NULL) return; - conn_data_event = (connection_event_t *)bh_malloc(sizeof(*conn_data_event)); + conn_data_event = (connection_event_t *)wasm_runtime_malloc(sizeof(*conn_data_event)); if (conn_data_event == NULL) return; if (len > 0) { - data_copy = (char *)bh_malloc(len); + data_copy = (char *)wasm_runtime_malloc(len); if (data_copy == NULL) { - bh_free(conn_data_event); + wasm_runtime_free(conn_data_event); return; } bh_memcpy_s(data_copy, len, data, len); diff --git a/core/app-framework/sensor/native/runtime_sensor.c b/core/app-framework/sensor/native/runtime_sensor.c index 63a03983d..ac7eed9dd 100644 --- a/core/app-framework/sensor/native/runtime_sensor.c +++ b/core/app-framework/sensor/native/runtime_sensor.c @@ -32,10 +32,10 @@ sensor_event_cleaner(sensor_event_data_t *sensor_event) if (sensor_event->data_fmt == FMT_ATTR_CONTAINER) attr_container_destroy(sensor_event->data); else - bh_free(sensor_event->data); + wasm_runtime_free(sensor_event->data); } - bh_free(sensor_event); + wasm_runtime_free(sensor_event); } static void @@ -56,7 +56,7 @@ wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data) return; sensor_data_len = attr_container_get_serialize_length(sensor_data); - sensor_data_clone = (attr_container_t *)bh_malloc(sensor_data_len); + sensor_data_clone = (attr_container_t *)wasm_runtime_malloc(sensor_data_len); if (sensor_data_clone == NULL) return; @@ -64,9 +64,9 @@ wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data) bh_memcpy_s(sensor_data_clone, sensor_data_len, sensor_data, sensor_data_len); - sensor_event = (sensor_event_data_t *)bh_malloc(sizeof(*sensor_event)); + sensor_event = (sensor_event_data_t *)wasm_runtime_malloc(sizeof(*sensor_event)); if (sensor_event == NULL) { - bh_free(sensor_data_clone); + wasm_runtime_free(sensor_data_clone); return; } @@ -158,7 +158,7 @@ wasm_sensor_open(wasm_exec_env_t exec_env, return -1; } - sensor_client_t * client = (sensor_client_t*) bh_malloc( + sensor_client_t * client = (sensor_client_t*) wasm_runtime_malloc( sizeof(sensor_client_t)); if (client == NULL) { vm_mutex_unlock(&s->lock); @@ -220,7 +220,7 @@ wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor) vm_mutex_lock(&s->lock); if ((c = find_sensor_client(s, client_id, true)) != NULL) - bh_free(c); + wasm_runtime_free(c); vm_mutex_unlock(&s->lock); refresh_read_interval(s); @@ -272,7 +272,7 @@ sensor_obj_t add_sys_sensor(char * name, char * description, int instance, uint32 default_interval, void * read_func, void * config_func) { - sys_sensor_t * s = (sys_sensor_t *) bh_malloc(sizeof(sys_sensor_t)); + sys_sensor_t * s = (sys_sensor_t *) wasm_runtime_malloc(sizeof(sys_sensor_t)); if (s == NULL) return NULL; @@ -282,15 +282,15 @@ add_sys_sensor(char * name, char * description, int instance, s->default_interval = default_interval; if (!s->name) { - bh_free(s); + wasm_runtime_free(s); return NULL; } if (description) { s->description = bh_strdup(description); if (!s->description) { - bh_free(s->name); - bh_free(s); + wasm_runtime_free(s->name); + wasm_runtime_free(s); return NULL; } } @@ -414,7 +414,7 @@ void sensor_cleanup_callback(uint32 module_id) sensor_client_t *c; vm_mutex_lock(&s->lock); if ((c = find_sensor_client(s, module_id, true)) != NULL) { - bh_free(c); + wasm_runtime_free(c); } vm_mutex_unlock(&s->lock); s = s->next; diff --git a/core/app-framework/wgl/native/wgl_native_utils.c b/core/app-framework/wgl/native/wgl_native_utils.c index 353329802..005ab3fe7 100644 --- a/core/app-framework/wgl/native/wgl_native_utils.c +++ b/core/app-framework/wgl/native/wgl_native_utils.c @@ -124,7 +124,7 @@ void wgl_native_func_call(wasm_module_inst_t module_inst, argc1++; /* module_inst */ argc1 += func_def->arg_num; if (argc1 > 16) { - argv_copy = (intptr_t *)bh_malloc(func_def->arg_num * + argv_copy = (intptr_t *)wasm_runtime_malloc(func_def->arg_num * sizeof(intptr_t)); if (argv_copy == NULL) return; @@ -190,14 +190,14 @@ void wgl_native_func_call(wasm_module_inst_t module_inst, } if (argv_copy != argv_copy_buf) - bh_free(argv_copy); + wasm_runtime_free(argv_copy); /* success return */ return; fail: if (argv_copy != argv_copy_buf) - bh_free(argv_copy); + wasm_runtime_free(argv_copy); return; } diff --git a/core/app-framework/wgl/native/wgl_obj_wrapper.c b/core/app-framework/wgl/native/wgl_obj_wrapper.c index 9f2940ff9..31b648c0e 100644 --- a/core/app-framework/wgl/native/wgl_obj_wrapper.c +++ b/core/app-framework/wgl/native/wgl_obj_wrapper.c @@ -93,7 +93,7 @@ static void cleanup_object_list(uint32 module_id) found = true; lv_obj_del(elem->obj); bh_list_remove(&g_object_list, elem); - bh_free(elem); + wasm_runtime_free(elem); elem = next; } else { elem = (object_node_t *)bh_list_elem_next(elem); @@ -150,7 +150,7 @@ bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id) { object_node_t *node; - node = (object_node_t *) bh_malloc(sizeof(object_node_t)); + node = (object_node_t *) wasm_runtime_malloc(sizeof(object_node_t)); if (node == NULL) return false; @@ -200,7 +200,7 @@ static void _obj_del_recursive(lv_obj_t *obj) while (elem) { if (obj == elem->obj) { bh_list_remove(&g_object_list, elem); - bh_free(elem); + wasm_runtime_free(elem); vm_mutex_unlock(&g_object_list_mutex); return; } @@ -237,7 +237,7 @@ static void post_widget_msg_to_module(object_node_t *object_node, lv_event_t eve if (module == NULL) return; - object_event = (object_event_t *)bh_malloc(sizeof(*object_event)); + object_event = (object_event_t *)wasm_runtime_malloc(sizeof(*object_event)); if (object_event == NULL) return; diff --git a/core/app-mgr/app-manager/app_manager.c b/core/app-mgr/app-manager/app_manager.c index 7c8c8577a..ca41d6ffd 100644 --- a/core/app-mgr/app-manager/app_manager.c +++ b/core/app-mgr/app-manager/app_manager.c @@ -6,7 +6,6 @@ #include "app_manager.h" #include "app_manager_host.h" #include "bh_queue.h" -#include "bh_memory.h" #include "bh_thread.h" #include "bi-inc/attr_container.h" #include "event.h" diff --git a/core/app-mgr/app-manager/app_manager.h b/core/app-mgr/app-manager/app_manager.h index 188c685d1..c41002f13 100644 --- a/core/app-mgr/app-manager/app_manager.h +++ b/core/app-mgr/app-manager/app_manager.h @@ -18,6 +18,9 @@ extern "C" { #endif +#define APP_MGR_MALLOC wasm_runtime_malloc +#define APP_MGR_FREE wasm_runtime_free + /* bh_printf is defined in each platform */ #define app_manager_printf bh_printf diff --git a/core/app-mgr/app-manager/app_manager_host.c b/core/app-mgr/app-manager/app_manager_host.c index efd86e486..db50cb1b4 100644 --- a/core/app-mgr/app-manager/app_manager_host.c +++ b/core/app-mgr/app-manager/app_manager_host.c @@ -9,7 +9,6 @@ #include "app_manager.h" #include "app_manager_export.h" #include "coap_ext.h" -#include "bh_memory.h" #include "bh_thread.h" /* host communication interface */ @@ -66,7 +65,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) ctx->message.payload_size = 0; if (ctx->message.payload) { - bh_free(ctx->message.payload); + APP_MGR_FREE(ctx->message.payload); ctx->message.payload = NULL; } @@ -117,7 +116,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) app_manager_printf("##On byte arrive: payload_size: %d\n", ctx->message.payload_size); if (ctx->message.payload) { - bh_free(ctx->message.payload); + APP_MGR_FREE(ctx->message.payload); ctx->message.payload = NULL; } @@ -137,7 +136,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) if (ctx->message.message_type != INSTALL_WASM_APP) { ctx->message.payload = - (char *) bh_malloc(ctx->message.payload_size); + (char *) APP_MGR_MALLOC(ctx->message.payload_size); if (!ctx->message.payload) { ctx->phase = Phase_Non_Start; return 0; @@ -222,7 +221,7 @@ int aee_host_msg_callback(void *msg, uint16_t msg_len) printf("unexpected host msg type: %d\n", msg_type); } - bh_free(recv_ctx.message.payload); + APP_MGR_FREE(recv_ctx.message.payload); recv_ctx.message.payload = NULL; recv_ctx.message.payload_size = 0; } diff --git a/core/app-mgr/app-manager/ble_msg.c b/core/app-mgr/app-manager/ble_msg.c index 3794fa56b..179eb78ba 100644 --- a/core/app-mgr/app-manager/ble_msg.c +++ b/core/app-mgr/app-manager/ble_msg.c @@ -75,16 +75,16 @@ app_instance_free_ble_msg(char *msg) dev_info = (ble_device_info *) ble_msg->payload; if (dev_info->scan_response != NULL) - bh_free(dev_info->scan_response); + APP_MGR_FREE(dev_info->scan_response); if (dev_info->private_data != NULL) - bh_free(dev_info->private_data); + APP_MGR_FREE(dev_info->private_data); if (dev_info->adv_data != NULL) - bh_free(dev_info->adv_data); + APP_MGR_FREE(dev_info->adv_data); if (dev_info != NULL) - bh_free(dev_info); + APP_MGR_FREE(dev_info); } static void diff --git a/core/app-mgr/app-manager/event.c b/core/app-mgr/app-manager/event.c index 67def1c78..f2c49dfd0 100644 --- a/core/app-mgr/app-manager/event.c +++ b/core/app-mgr/app-manager/event.c @@ -8,7 +8,6 @@ #include "event.h" #include "app_manager.h" -#include "bh_memory.h" #include "coap_ext.h" typedef struct _subscribe { @@ -38,7 +37,7 @@ static bool find_subscriber(event_reg_t * reg, uint32 id, bool remove_found) else reg->subscribers = next; - bh_free(c); + APP_MGR_FREE(c); } return true; @@ -77,7 +76,7 @@ bool am_register_event(const char *url, uint32_t reg_client) if (current == NULL) { if (NULL - == (current = (event_reg_t *) bh_malloc( + == (current = (event_reg_t *) APP_MGR_MALLOC( offsetof(event_reg_t, url) + strlen(url) + 1))) { app_manager_printf("am_register_event: malloc fail\n"); return false; @@ -92,7 +91,7 @@ bool am_register_event(const char *url, uint32_t reg_client) if (find_subscriber(current, reg_client, false)) { return true; } else { - subscribe_t * s = (subscribe_t*) bh_malloc(sizeof(subscribe_t)); + subscribe_t * s = (subscribe_t*) APP_MGR_MALLOC(sizeof(subscribe_t)); if (s == NULL) return false; @@ -128,7 +127,7 @@ bool am_unregister_event(const char *url, uint32_t reg_client) pre->next = next; else g_events = next; - bh_free(current); + APP_MGR_FREE(current); current = next; continue; } diff --git a/core/app-mgr/app-manager/message.c b/core/app-mgr/app-manager/message.c index 13ee4c04f..2aed14757 100644 --- a/core/app-mgr/app-manager/message.c +++ b/core/app-mgr/app-manager/message.c @@ -7,7 +7,6 @@ #include "app_manager_host.h" #include "event.h" #include "bi-inc/attr_container.h" -#include "bh_memory.h" #include "coap_ext.h" #if 0 @@ -21,7 +20,7 @@ bool send_coap_packet_to_host(coap_packet_t * packet) return false; app_manager_host_send_msg(buf, size); - bh_free(buf); + APP_MGR_FREE(buf); return true; } diff --git a/core/app-mgr/app-manager/module_jeff.c b/core/app-mgr/app-manager/module_jeff.c index af2fbaef0..25ded4be0 100644 --- a/core/app-mgr/app-manager/module_jeff.c +++ b/core/app-mgr/app-manager/module_jeff.c @@ -125,7 +125,7 @@ get_class_qname(const JeffString *pname, const JeffString *cname) { unsigned int length = pname->length ? pname->length + 2 + cname->length : cname->length + 1; - char *buf = bh_malloc(length), *p; + char *buf = APP_MGR_MALLOC(length), *p; if (!buf) return NULL; @@ -166,7 +166,7 @@ send_exception_event_to_host(const char *applet_name, const char *exc_name) } url_len = strlen("/exception/") + strlen(applet_name); - url = bh_malloc(url_len + 1); + url = APP_MGR_MALLOC(url_len + 1); if (!url) { app_manager_printf("Send exception to host fail: allocate memory"); goto fail; @@ -182,7 +182,7 @@ send_exception_event_to_host(const char *applet_name, const char *exc_name) app_send_request_msg_to_host(&msg); - bh_free(url); + APP_MGR_FREE(url); fail: attr_container_destroy(payload); @@ -208,7 +208,7 @@ check_exception() /* Send exception event to host */ if (qname_buf) { send_exception_event_to_host(app_manager_get_module_name(Module_Jeff), qname_buf); - bh_free(qname_buf); + APP_MGR_FREE(qname_buf); } /* Uninstall the applet */ @@ -455,17 +455,17 @@ check_exception() fail: if (dev_info->scan_response != NULL) { - bh_free(dev_info->scan_response); + APP_MGR_FREE(dev_info->scan_response); } if (dev_info->private_data != NULL) { - bh_free(dev_info->private_data); + APP_MGR_FREE(dev_info->private_data); } if (dev_info->adv_data != NULL) { - bh_free(dev_info->adv_data); + APP_MGR_FREE(dev_info->adv_data); } if (dev_info != NULL) { - bh_free(dev_info); + APP_MGR_FREE(dev_info); } } @@ -479,16 +479,16 @@ check_exception() dev_info = (ble_device_info *) ble_msg->payload; if (dev_info->scan_response != NULL) - bh_free(dev_info->scan_response); + APP_MGR_FREE(dev_info->scan_response); if (dev_info->private_data != NULL) - bh_free(dev_info->private_data); + APP_MGR_FREE(dev_info->private_data); if (dev_info->adv_data != NULL) - bh_free(dev_info->adv_data); + APP_MGR_FREE(dev_info->adv_data); if (dev_info != NULL) - bh_free(dev_info); + APP_MGR_FREE(dev_info); } static void @@ -500,7 +500,7 @@ check_exception() case APPLET_REQUEST: { bh_request_msg_t *req_msg = (bh_request_msg_t *)msg->payload; - bh_free(req_msg); + APP_MGR_FREE(req_msg); break; } @@ -516,7 +516,7 @@ check_exception() attr_container_t *event = sensor_event->event; attr_container_destroy(event); - bh_free(sensor_event); + APP_MGR_FREE(sensor_event); } break; } @@ -525,7 +525,7 @@ check_exception() { if (msg->payload) { app_instance_free_ble_msg(msg->payload); - bh_free(msg->payload); + APP_MGR_FREE(msg->payload); } break; } @@ -541,7 +541,7 @@ check_exception() } } - bh_free(msg); + APP_MGR_FREE(msg); } static void @@ -609,7 +609,7 @@ check_exception() fail2: jeff_runtime_pop_local_object_ref(1); fail1: - bh_free(req_msg); + APP_MGR_FREE(req_msg); break; } @@ -633,7 +633,7 @@ check_exception() bool ret = attr_container_to_attr_obj(event, &sensor->event); attr_container_destroy(event); - bh_free(sensor_event); + APP_MGR_FREE(sensor_event); if (ret) { /* Call Sensor.callOnSensorEvent() method */ @@ -649,7 +649,7 @@ check_exception() { if (msg->payload) { app_instance_process_ble_msg(msg->payload); - bh_free(msg->payload); + APP_MGR_FREE(msg->payload); } break; } @@ -678,7 +678,7 @@ check_exception() } } - bh_free(msg); + APP_MGR_FREE(msg); } static JeffClassHeaderLinked* @@ -837,7 +837,7 @@ check_exception() /* TODO: convert bpk file to Jeff file */ main_file_len = bpk_file_len; - main_file = bh_malloc(main_file_len); + main_file = APP_MGR_MALLOC(main_file_len); if (!main_file) { SEND_ERR_RESPONSE(msg->mid, "Install Applet failed: allocate memory failed."); return false; @@ -866,7 +866,7 @@ check_exception() /* Create module data */ size = offsetof(module_data, module_name) + strlen(applet_name) + 1; size = align_uint(size, 4); - m_data = bh_malloc(size + sizeof(jeff_applet_data)); + m_data = APP_MGR_MALLOC(size + sizeof(jeff_applet_data)); if (!m_data) { SEND_ERR_RESPONSE(msg->mid, "Install Applet failed: allocate memory failed."); goto fail2; @@ -888,7 +888,7 @@ check_exception() /* Create applet permissions */ applet_perm = attr_container_get_as_string(attr_cont, "perm"); if (applet_perm != NULL) { - applet_data->perms = bh_malloc(strlen(applet_perm) + 1); + applet_data->perms = APP_MGR_MALLOC(strlen(applet_perm) + 1); if (!applet_data->perms) { SEND_ERR_RESPONSE(msg->mid, "Install Applet failed: allocate memory for applet permissions failed."); goto fail3; @@ -993,16 +993,16 @@ check_exception() bh_queue_destroy(m_data->queue, NULL); fail3_1: - bh_free(applet_data->perms); + APP_MGR_FREE(applet_data->perms); fail3: - bh_free(applet_data); + APP_MGR_FREE(applet_data); fail2: jeff_runtime_unload(main_file); fail1: - bh_free(main_file); + APP_MGR_FREE(main_file); return false; } @@ -1014,7 +1014,7 @@ check_exception() /* Unload Jeff main file and free it */ jeff_runtime_unload(applet_data->main_file); - bh_free(applet_data->main_file); + APP_MGR_FREE(applet_data->main_file); /* Destroy queue */ bh_queue_destroy(m_data->queue, app_instance_queue_free_callback); @@ -1027,8 +1027,8 @@ check_exception() /* Remove module data from module data list and free it */ app_manager_del_module_data(m_data); - bh_free(applet_data->perms); - bh_free(m_data); + APP_MGR_FREE(applet_data->perms); + APP_MGR_FREE(m_data); } /* Uninstall Java Applet */ @@ -1476,7 +1476,7 @@ check_exception() } /* Create queue message for tool agent */ - if (!(tool_agent_msg = bh_malloc(sizeof(bh_queue_msg_t)))) { + if (!(tool_agent_msg = APP_MGR_MALLOC(sizeof(bh_queue_msg_t)))) { SEND_ERR_RESPONSE(mid, "Send request to tool agent failed: allocate memory failed"); return false; } @@ -1487,9 +1487,9 @@ check_exception() req_msg_len = sizeof(bh_request_msg_t) + strlen(p) + 1 + attr_cont_len; /* Create request message */ - if (!(req_msg = bh_malloc(req_msg_len))) { + if (!(req_msg = APP_MGR_MALLOC(req_msg_len))) { SEND_ERR_RESPONSE(mid, "Send request to applet failed: allocate memory failed"); - bh_free(tool_agent_msg); + APP_MGR_FREE(tool_agent_msg); return false; } @@ -1511,8 +1511,8 @@ check_exception() tool_agent_msg->payload_size = req_msg_len; tool_agent_msg->payload = (char*)req_msg; if (!bh_queue_send_message(applet_data->tool_agent_queue, tool_agent_msg)) { - bh_free(req_msg); - bh_free(tool_agent_msg); + APP_MGR_FREE(req_msg); + APP_MGR_FREE(tool_agent_msg); SEND_ERR_RESPONSE (mid, "Send request to tool agent failed: send queue msg failed."); return false; @@ -1693,16 +1693,16 @@ check_exception() goto fail; } - bh_free(req_msg); - bh_free(msg); + APP_MGR_FREE(req_msg); + APP_MGR_FREE(msg); return; fail: bh_queue_exit_loop_run(queue); - bh_free(req_msg); + APP_MGR_FREE(req_msg); } - bh_free(msg); + APP_MGR_FREE(msg); } void @@ -1712,10 +1712,10 @@ check_exception() if (msg->message_type == JDWP_REQUEST) { bh_request_msg_t *req_msg = (bh_request_msg_t*)msg->payload; - bh_free(req_msg); + APP_MGR_FREE(req_msg); } - bh_free(msg); + APP_MGR_FREE(msg); } #endif /* BEIHAI_ENABLE_TOOL_AGENT != 0 */ diff --git a/core/app-mgr/app-manager/module_utils.c b/core/app-mgr/app-manager/module_utils.c index a4e52cb45..1f7219c8d 100644 --- a/core/app-mgr/app-manager/module_utils.c +++ b/core/app-mgr/app-manager/module_utils.c @@ -6,7 +6,6 @@ #include "app_manager.h" #include "app_manager_host.h" #include "bh_queue.h" -#include "bh_memory.h" #include "bh_thread.h" #include "bi-inc/attr_container.h" #include "event.h" @@ -32,7 +31,7 @@ void module_data_list_destroy() if (module_data_list) { while (module_data_list) { module_data *p = module_data_list->next; - bh_free(module_data_list); + APP_MGR_FREE(module_data_list); module_data_list = p; } } @@ -197,7 +196,7 @@ void release_module(module_data *m_data) destroy_module_timer_ctx(m_data->id); - bh_free(m_data); + APP_MGR_FREE(m_data); } int check_modules_timer_expiry() diff --git a/core/app-mgr/app-manager/module_wasm_app.c b/core/app-mgr/app-manager/module_wasm_app.c index ecc352ed0..1035a348c 100644 --- a/core/app-mgr/app-manager/module_wasm_app.c +++ b/core/app-mgr/app-manager/module_wasm_app.c @@ -10,7 +10,6 @@ #include "bh_queue.h" #include "bi-inc/attr_container.h" #include "bh_thread.h" -#include "bh_memory.h" #include "coap_ext.h" #include "event.h" #include "watchdog.h" @@ -551,12 +550,7 @@ cleanup_app_resource(module_data *m_data) static bool wasm_app_module_init(void) { - /* Initialize WASM VM*/ - if (!wasm_runtime_init()) { - app_manager_printf("WASM runtime environment initialization failed.\n"); - return false; - } - + /* wasm runtime is already initialized by main func */ return true; } @@ -776,7 +770,7 @@ wasm_app_module_install(request_t * msg) /* Create module data including the wasm_app_data as its internal_data*/ m_data_size = offsetof(module_data, module_name) + strlen(m_name) + 1; m_data_size = align_uint(m_data_size, 4); - m_data = bh_malloc(m_data_size + sizeof(wasm_data)); + m_data = APP_MGR_MALLOC(m_data_size + sizeof(wasm_data)); if (!m_data) { SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: allocate memory failed."); goto fail; @@ -1096,7 +1090,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, recv_ctx.message.request_url_len = ntohs(recv_ctx.message.request_url_len); recv_ctx.message.request_url = - bh_malloc(recv_ctx.message.request_url_len + 1); + APP_MGR_MALLOC(recv_ctx.message.request_url_len + 1); if (NULL == recv_ctx.message.request_url) { app_manager_printf("Allocate memory failed!\n"); goto fail; @@ -1177,7 +1171,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, uint8 section_type = ch; if (section_type <= SECTION_TYPE_DATA) { wasm_section_t *new_section; - if (!(new_section = (wasm_section_t *) bh_malloc(sizeof(wasm_section_t)))) { + if (!(new_section = (wasm_section_t *) APP_MGR_MALLOC(sizeof(wasm_section_t)))) { app_manager_printf("Allocate memory failed!\n"); goto fail; } @@ -1226,7 +1220,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, if ((byte & 0x80) == 0) { /* leb128 encoded section size parsed done */ - if (!(section->section_body = bh_malloc(section->section_body_size))) { + if (!(section->section_body = APP_MGR_MALLOC(section->section_body_size))) { app_manager_printf("Allocate memory failed!\n"); goto fail; } @@ -1248,7 +1242,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, if (recv_ctx.total_received_size == request_total_size) { /* whole wasm app received */ if (module_wasm_app_handle_install_msg(&recv_ctx.message)) { - bh_free(recv_ctx.message.request_url); + APP_MGR_FREE(recv_ctx.message.request_url); recv_ctx.message.request_url = NULL; memset(&recv_ctx, 0, sizeof(recv_ctx)); return true; @@ -1297,7 +1291,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, if (aot_file_cur_offset % 4) return true; - if (!(cur_section = (aot_section_t *) bh_malloc(sizeof(aot_section_t)))) { + if (!(cur_section = (aot_section_t *) APP_MGR_MALLOC(sizeof(aot_section_t)))) { app_manager_printf("Allocate memory failed!\n"); goto fail; } @@ -1377,7 +1371,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, } else { if (!(section->section_body = - bh_malloc(section->section_body_size))) { + APP_MGR_MALLOC(section->section_body_size))) { app_manager_printf("Allocate memory failed!\n"); goto fail; } @@ -1411,7 +1405,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, if (recv_ctx.total_received_size == request_total_size) { /* whole aot file received */ if (module_wasm_app_handle_install_msg(&recv_ctx.message)) { - bh_free(recv_ctx.message.request_url); + APP_MGR_FREE(recv_ctx.message.request_url); recv_ctx.message.request_url = NULL; memset(&recv_ctx, 0, sizeof(recv_ctx)); return true; @@ -1449,7 +1443,7 @@ fail: } if (recv_ctx.message.request_url != NULL) { - bh_free(recv_ctx.message.request_url); + APP_MGR_FREE(recv_ctx.message.request_url); recv_ctx.message.request_url = NULL; } @@ -1466,7 +1460,7 @@ module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) request_t *request = NULL; bh_message_t msg; - request = (request_t *) bh_malloc(sizeof(request_t)); + request = (request_t *) APP_MGR_MALLOC(sizeof(request_t)); if (request == NULL) return false; @@ -1477,7 +1471,7 @@ module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) request->sender = ID_HOST; request->mid = message->request_mid; request->payload_len = sizeof(message->app_file); - request->payload = bh_malloc(request->payload_len); + request->payload = APP_MGR_MALLOC(request->payload_len); if (request->url == NULL || request->payload == NULL) { request_cleaner(request); @@ -1512,8 +1506,8 @@ destroy_all_wasm_sections(wasm_section_list_t sections) while (cur) { wasm_section_t *next = cur->next; if (cur->section_body != NULL) - bh_free(cur->section_body); - bh_free(cur); + APP_MGR_FREE(cur->section_body); + APP_MGR_FREE(cur); cur = next; } } @@ -1537,8 +1531,8 @@ destroy_part_wasm_sections(wasm_section_list_t *p_sections, *p_sections = next; if (cur->section_body != NULL) - bh_free(cur->section_body); - bh_free(cur); + APP_MGR_FREE(cur->section_body); + APP_MGR_FREE(cur); break; } else { @@ -1561,9 +1555,9 @@ destroy_all_aot_sections(aot_section_list_t sections) if (cur->section_type == AOT_SECTION_TYPE_TEXT) bh_munmap(cur->section_body, cur->section_body_size); else - bh_free(cur->section_body); + APP_MGR_FREE(cur->section_body); } - bh_free(cur); + APP_MGR_FREE(cur); cur = next; } } @@ -1591,9 +1585,9 @@ destroy_part_aot_sections(aot_section_list_t *p_sections, if (cur->section_type == AOT_SECTION_TYPE_TEXT) bh_munmap(cur->section_body, cur->section_body_size); else - bh_free(cur->section_body); + APP_MGR_FREE(cur->section_body); } - bh_free(cur); + APP_MGR_FREE(cur); break; } else { diff --git a/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c b/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c index 67ae69b4f..59c471fe9 100644 --- a/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c +++ b/core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c @@ -5,7 +5,6 @@ #include "app_manager.h" #include "bh_platform.h" -#include "bh_memory.h" #include #include #include @@ -21,7 +20,7 @@ void* app_manager_timer_create(void (*timer_callback)(void*), watchdog_timer *wd_timer) { - struct k_timer_watchdog *timer = bh_malloc(sizeof(struct k_timer_watchdog)); + struct k_timer_watchdog *timer = APP_MGR_MALLOC(sizeof(struct k_timer_watchdog)); if (timer) { k_timer_init(&timer->timer, (void (*)(struct k_timer*)) timer_callback, @@ -34,7 +33,7 @@ app_manager_timer_create(void (*timer_callback)(void*), void app_manager_timer_destroy(void *timer) { - bh_free(timer); + APP_MGR_FREE(timer); } void app_manager_timer_start(void *timer, int timeout) diff --git a/core/app-mgr/app-manager/resource_reg.c b/core/app-mgr/app-manager/resource_reg.c index 854357e09..c6655ff65 100644 --- a/core/app-mgr/app-manager/resource_reg.c +++ b/core/app-mgr/app-manager/resource_reg.c @@ -158,14 +158,14 @@ bool am_register_resource(const char *url, if (register_num >= RESOURCE_REGISTRATION_NUM_MAX) return false; - r = (app_res_register_t *) bh_malloc(sizeof(app_res_register_t)); + r = (app_res_register_t *) APP_MGR_MALLOC(sizeof(app_res_register_t)); if (r == NULL) return false; memset(r, 0, sizeof(*r)); r->url = bh_strdup(url); if (r->url == NULL) { - bh_free(r); + APP_MGR_FREE(r); return false; } @@ -191,8 +191,8 @@ void am_cleanup_registeration(uint32 register_id) else g_resources = next; - bh_free(r->url); - bh_free(r); + APP_MGR_FREE(r->url); + APP_MGR_FREE(r); } else /* if r is freed, should not change prev. Only set prev to r when r isn't freed. */ diff --git a/core/app-mgr/app-manager/watchdog.c b/core/app-mgr/app-manager/watchdog.c index e23939452..2f3179962 100644 --- a/core/app-mgr/app-manager/watchdog.c +++ b/core/app-mgr/app-manager/watchdog.c @@ -6,8 +6,6 @@ #include "watchdog.h" #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" -#include "jeff_export.h" #define WATCHDOG_THREAD_PRIORITY 5 diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 211ba61f9..3b2baaaa9 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -5,7 +5,6 @@ #include "aot_runtime.h" #include "bh_common.h" -#include "bh_memory.h" #include "bh_log.h" #include "aot_reloc.h" #include "../common/wasm_runtime_common.h" @@ -155,7 +154,7 @@ const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, char* error_buf, uint32 error_buf_size) { HashMap *set = module->const_str_set; - char *c_str = wasm_malloc((uint32)len + 1), *value; + char *c_str = wasm_runtime_malloc((uint32)len + 1), *value; if (!c_str) { set_error_buf(error_buf, error_buf_size, @@ -168,7 +167,7 @@ const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, c_str[len] = '\0'; if ((value = bh_hash_map_find(set, c_str))) { - wasm_free(c_str); + wasm_runtime_free(c_str); return value; } @@ -176,7 +175,7 @@ const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "insert string to hash map failed."); - wasm_free(c_str); + wasm_runtime_free(c_str); return NULL; } @@ -330,8 +329,8 @@ destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count, uint32 i; for (i = 0; i < count; i++) if (data_list[i]) - wasm_free(data_list[i]); - wasm_free(data_list); + wasm_runtime_free(data_list[i]); + wasm_runtime_free(data_list); } } @@ -349,7 +348,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, size = sizeof(AOTMemInitData *) * (uint64)module->mem_init_data_count; if (size >= UINT32_MAX || !(module->mem_init_data_list = - data_list = wasm_malloc((uint32)size))) { + data_list = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -367,7 +366,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, read_uint32(buf, buf_end, byte_count); size = offsetof(AOTMemInitData, bytes) + (uint64)byte_count; if (size >= UINT32_MAX - || !(data_list[i] = wasm_malloc((uint32)size))) { + || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -419,8 +418,8 @@ destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count, uint32 i; for (i = 0; i < count; i++) if (data_list[i]) - wasm_free(data_list[i]); - wasm_free(data_list); + wasm_runtime_free(data_list[i]); + wasm_runtime_free(data_list); } } @@ -438,7 +437,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, size = sizeof(AOTTableInitData *) * (uint64)module->table_init_data_count; if (size >= UINT32_MAX || !(module->table_init_data_list = - data_list = wasm_malloc((uint32)size))) { + data_list = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -459,7 +458,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, size1 = sizeof(uint32) * (uint64)func_index_count; size = offsetof(AOTTableInitData, func_indexes) + size1; if (size >= UINT32_MAX - || !(data_list[i] = wasm_malloc((uint32)size))) { + || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -507,8 +506,8 @@ destroy_func_types(AOTFuncType **func_types, uint32 count, bool is_jit_mode) uint32 i; for (i = 0; i < count; i++) if (func_types[i]) - wasm_free(func_types[i]); - wasm_free(func_types); + wasm_runtime_free(func_types[i]); + wasm_runtime_free(func_types); } } @@ -525,7 +524,7 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTFuncType *) * (uint64)module->func_type_count; if (size >= UINT32_MAX - || !(module->func_types = func_types = wasm_malloc((uint32)size))) { + || !(module->func_types = func_types = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -545,7 +544,7 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, size1 = (uint64)param_count + (uint64)result_count; size = offsetof(AOTFuncType, types) + size1; if (size >= UINT32_MAX - || !(func_types[i] = wasm_malloc((uint32)size))) { + || !(func_types[i] = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -587,7 +586,7 @@ static void destroy_import_globals(AOTImportGlobal *import_globals, bool is_jit_mode) { if (!is_jit_mode) - wasm_free(import_globals); + wasm_runtime_free(import_globals); } static bool @@ -604,7 +603,7 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; if (size >= UINT32_MAX || !(module->import_globals = - import_globals = wasm_malloc((uint32)size))) { + import_globals = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -657,7 +656,7 @@ static void destroy_globals(AOTGlobal *globals, bool is_jit_mode) { if (!is_jit_mode) - wasm_free(globals); + wasm_runtime_free(globals); } static bool @@ -674,7 +673,7 @@ load_globals(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTGlobal) * (uint64)module->global_count; if (size >= UINT32_MAX - || !(module->globals = globals = wasm_malloc((uint32)size))) { + || !(module->globals = globals = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -739,7 +738,7 @@ destroy_import_funcs(AOTImportFunc *import_funcs, bool is_jit_mode) { if (!is_jit_mode) - wasm_free(import_funcs); + wasm_runtime_free(import_funcs); } static bool @@ -757,7 +756,7 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, size = sizeof(AOTImportFunc) * (uint64)module->import_func_count; if (size >= UINT32_MAX || !(module->import_funcs = - import_funcs = wasm_malloc((uint32)size))) { + import_funcs = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -831,7 +830,7 @@ destroy_object_data_sections(AOTObjectDataSection *data_sections, for (i = 0; i < data_section_count; i++, data_section++) if (data_section->data) bh_munmap(data_section->data, data_section->size); - wasm_free(data_sections); + wasm_runtime_free(data_sections); } static bool @@ -848,7 +847,7 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, size = sizeof(AOTObjectDataSection) * (uint64)module->data_section_count; if (size >= UINT32_MAX || !(module->data_sections = - data_sections = wasm_malloc((uint32)size))) { + data_sections = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -1002,7 +1001,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, size = sizeof(void*) * (uint64)module->func_count; if (size >= UINT32_MAX - || !(module->func_ptrs = wasm_malloc((uint32)size))) { + || !(module->func_ptrs = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: allocate memory failed."); return false; @@ -1042,7 +1041,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, size = sizeof(uint32) * (uint64)module->func_count; if (size >= UINT32_MAX - || !(module->func_type_indexes = wasm_malloc((uint32)size))) { + || !(module->func_type_indexes = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: allocate memory failed."); return false; @@ -1074,7 +1073,7 @@ static void destroy_export_funcs(AOTExportFunc *export_funcs, bool is_jit_mode) { if (!is_jit_mode) - wasm_free(export_funcs); + wasm_runtime_free(export_funcs); } static bool @@ -1091,7 +1090,7 @@ load_export_funcs(const uint8 **p_buf, const uint8 *buf_end, size = sizeof(AOTExportFunc) * (uint64)module->export_func_count; if (size >= UINT32_MAX || !(module->export_funcs = - export_funcs = wasm_malloc((uint32)size))) { + export_funcs = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -1204,7 +1203,7 @@ do_text_relocation(AOTModule *module, if (symbol_len + 1 <= sizeof(symbol_buf)) symbol = symbol_buf; else { - if (!(symbol = wasm_malloc(symbol_len + 1))) { + if (!(symbol = wasm_runtime_malloc(symbol_len + 1))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -1254,7 +1253,7 @@ do_text_relocation(AOTModule *module, } if (symbol != symbol_buf) - wasm_free(symbol); + wasm_runtime_free(symbol); if (!apply_relocation(module, aot_text, aot_text_size, @@ -1270,7 +1269,7 @@ do_text_relocation(AOTModule *module, check_symbol_fail: if (symbol != symbol_buf) - wasm_free(symbol); + wasm_runtime_free(symbol); return false; } @@ -1399,7 +1398,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, /* Allocate memory for relocation groups */ size = sizeof(AOTRelocationGroup) * (uint64)group_count; - if (size >= UINT32_MAX || !(groups = wasm_malloc((uint32)size))) { + if (size >= UINT32_MAX || !(groups = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -1442,7 +1441,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, size = sizeof(AOTRelocation) * (uint64)group->relocation_count; if (size >= UINT32_MAX || !(group->relocations = relocation = - wasm_malloc((uint32)size))) { + wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -1522,8 +1521,8 @@ fail: if (groups) { for (i = 0, group = groups; i < group_count; i++, group++) if (group->relocations) - wasm_free(group->relocations); - wasm_free(groups); + wasm_runtime_free(group->relocations); + wasm_runtime_free(groups); } return ret; @@ -1603,16 +1602,16 @@ load_from_sections(AOTModule *module, AOTSection *sections, #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 static void aot_free(void *ptr) { - wasm_free(ptr); + wasm_runtime_free(ptr); } #else -#define aot_free wasm_free +#define aot_free wasm_runtime_free #endif static AOTModule* create_module(char *error_buf, uint32 error_buf_size) { - AOTModule *module = wasm_malloc(sizeof(AOTModule)); + AOTModule *module = wasm_runtime_malloc(sizeof(AOTModule)); if (!module) { set_error_buf(error_buf, error_buf_size, @@ -1634,7 +1633,7 @@ create_module(char *error_buf, uint32 error_buf_size) set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "create const string set failed."); - wasm_free(module); + wasm_runtime_free(module); return NULL; } @@ -1670,7 +1669,7 @@ destroy_sections(AOTSection *section_list, bool destroy_aot_text) && section->section_type == AOT_SECTION_TYPE_TEXT && section->section_body) bh_munmap((uint8*)section->section_body, section->section_body_size); - wasm_free(section); + wasm_runtime_free(section); section = next; } } @@ -1694,7 +1693,7 @@ create_sections(const uint8 *buf, uint32 size, read_uint32(p, p_end, section_size); CHECK_BUF(p, p_end, section_size); - if (!(section = wasm_malloc(sizeof(AOTSection)))) { + if (!(section = wasm_runtime_malloc(sizeof(AOTSection)))) { set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "allocate memory failed."); @@ -1703,7 +1702,7 @@ create_sections(const uint8 *buf, uint32 size, memset(section, 0, sizeof(AOTSection)); section->section_type = (int32)section_type; - section->section_body = p; + section->section_body = (uint8*)p; section->section_body_size = section_size; if (section_type == AOT_SECTION_TYPE_TEXT) { @@ -1722,7 +1721,7 @@ create_sections(const uint8 *buf, uint32 size, if (total_size >= UINT32_MAX || !(aot_text = bh_mmap(NULL, (uint32)total_size, map_prot, map_flags))) { - wasm_free(section); + wasm_runtime_free(section); set_error_buf(error_buf, error_buf_size, "AOT module load failed: " "mmap memory failed."); @@ -1849,7 +1848,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, AOTModule *module; /* Allocate memory for module */ - if (!(module = wasm_malloc(sizeof(AOTModule)))) { + if (!(module = wasm_runtime_malloc(sizeof(AOTModule)))) { set_error_buf(error_buf, error_buf_size, "Allocate memory for AOT module failed."); return NULL; @@ -1891,7 +1890,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, /* Allocate memory for function pointers */ size = (uint64)module->func_count * sizeof(void *); if (size >= UINT32_MAX - || !(module->func_ptrs = wasm_malloc((uint32)size))) { + || !(module->func_ptrs = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "Create func ptrs fail."); goto fail1; } @@ -1913,7 +1912,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, /* Allocation memory for function type indexes */ size = (uint64)module->func_count * sizeof(uint32); if (size >= UINT32_MAX - || !(module->func_type_indexes = wasm_malloc((uint32)size))) { + || !(module->func_type_indexes = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "Create func type indexes fail."); goto fail2; } @@ -1965,9 +1964,9 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, return module; fail2: - wasm_free(module->func_ptrs); + wasm_runtime_free(module->func_ptrs); fail1: - wasm_free(module); + wasm_runtime_free(module); return NULL; } @@ -2067,10 +2066,10 @@ aot_unload(AOTModule *module) module->is_jit_mode); if (module->func_type_indexes) - wasm_free(module->func_type_indexes); + wasm_runtime_free(module->func_type_indexes); if (module->func_ptrs) - wasm_free(module->func_ptrs); + wasm_runtime_free(module->func_ptrs); if (module->const_str_set) bh_hash_map_destroy(module->const_str_set); @@ -2082,7 +2081,7 @@ aot_unload(AOTModule *module) destroy_object_data_sections(module->data_sections, module->data_section_count); - wasm_free(module); + wasm_runtime_free(module); } uint32 diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 44c7d48fd..2be359bf1 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -4,7 +4,6 @@ */ #include "aot_runtime.h" -#include "bh_memory.h" #include "bh_log.h" #include "mem_alloc.h" @@ -116,7 +115,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Allocate memory */ if (total_size >= UINT32_MAX - || !(module_inst->memory_data.ptr = wasm_malloc((uint32)total_size))) { + || !(module_inst->memory_data.ptr = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "AOT module instantiate failed: allocate memory failed."); return false; @@ -166,7 +165,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, if (length > 0 && (base_offset >= module_inst->memory_data_size || base_offset + length > module_inst->memory_data_size)) { - wasm_free(module_inst->memory_data.ptr); + wasm_runtime_free(module_inst->memory_data.ptr); module_inst->memory_data.ptr = NULL; set_error_buf(error_buf, error_buf_size, "AOT module instantiate failed: data segment out of range."); @@ -193,7 +192,7 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module, /* Allocate memory */ if (total_size >= UINT32_MAX - || !(module_inst->func_ptrs.ptr = wasm_malloc((uint32)total_size))) { + || !(module_inst->func_ptrs.ptr = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "AOT module instantiate failed: allocate memory failed."); return false; @@ -222,7 +221,8 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module, /* Allocate memory */ if (total_size >= UINT32_MAX - || !(module_inst->func_type_indexes.ptr = wasm_malloc((uint32)total_size))) { + || !(module_inst->func_type_indexes.ptr = + wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "AOT module instantiate failed: allocate memory failed."); return false; @@ -304,7 +304,7 @@ aot_instantiate(AOTModule *module, /* Allocate module instance, global data, table data and heap data */ if (total_size >= UINT32_MAX - || !(module_inst = wasm_malloc((uint32)total_size))) { + || !(module_inst = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "AOT module instantiate failed: allocate memory failed."); return NULL; @@ -407,18 +407,18 @@ aot_deinstantiate(AOTModuleInstance *module_inst) #endif if (module_inst->memory_data.ptr) - wasm_free(module_inst->memory_data.ptr); + wasm_runtime_free(module_inst->memory_data.ptr); if (module_inst->heap_handle.ptr) mem_allocator_destroy(module_inst->heap_handle.ptr); if (module_inst->func_ptrs.ptr) - wasm_free(module_inst->func_ptrs.ptr); + wasm_runtime_free(module_inst->func_ptrs.ptr); if (module_inst->func_type_indexes.ptr) - wasm_free(module_inst->func_type_indexes.ptr); + wasm_runtime_free(module_inst->func_type_indexes.ptr); - wasm_free(module_inst); + wasm_runtime_free(module_inst); } AOTFunctionInstance* @@ -750,8 +750,8 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) uint32 cur_page_count = module_inst->mem_cur_page_count; uint32 max_page_count = module_inst->mem_max_page_count; uint32 total_page_count = cur_page_count + inc_page_count; - uint32 old_size = num_bytes_per_page * cur_page_count; uint64 total_size = (uint64)num_bytes_per_page * total_page_count; + uint32 total_size_old; if (inc_page_count <= 0) /* No need to enlarge memory */ @@ -763,20 +763,29 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) return false; } - if (total_size >= UINT32_MAX - || !(mem_data_new = wasm_malloc((uint32)total_size))) { + if (total_size >= UINT32_MAX) { aot_set_exception(module_inst, "fail to enlarge memory."); return false; } - memcpy(mem_data_new, mem_data_old, old_size); - memset(mem_data_new + old_size, 0, (uint32)total_size - old_size); + if (!(mem_data_new = wasm_runtime_realloc(mem_data_old, (uint32)total_size))) { + if (!(mem_data_new = wasm_runtime_malloc((uint32)total_size))) { + aot_set_exception(module_inst, "fail to enlarge memory."); + return false; + } + total_size_old = module_inst->memory_data_size; + bh_memcpy_s(mem_data_new, (uint32)total_size, + mem_data_old, total_size_old); + memset(mem_data_new + total_size_old, + 0, (uint32)total_size - total_size_old); + wasm_runtime_free(mem_data_old); + } + module_inst->mem_cur_page_count = total_page_count; module_inst->memory_data_size = (uint32)total_size; module_inst->memory_data.ptr = mem_data_new; module_inst->memory_data_end.ptr = mem_data_new + (uint32)total_size; - wasm_free(mem_data_old); return true; } diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index 0dac4f663..16ea56b18 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -44,6 +44,20 @@ void __aeabi_idivmod(); void __aeabi_uidivmod(); void __aeabi_ldivmod(); void __aeabi_uldivmod(); +void __aeabi_i2d(); +void __aeabi_dadd(); +void __aeabi_ddiv(); +void __aeabi_dcmplt(); +void __aeabi_dcmpun(); +void __aeabi_dcmple(); +void __aeabi_dcmpge(); +void __aeabi_d2iz(); +void __aeabi_fcmplt(); +void __aeabi_fcmpun(); +void __aeabi_fcmple(); +void __aeabi_fcmpge(); +void __aeabi_f2iz(); +void __aeabi_f2d(); static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS, @@ -77,7 +91,21 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_idivmod), REG_SYM(__aeabi_uidivmod), REG_SYM(__aeabi_ldivmod), - REG_SYM(__aeabi_uldivmod) + REG_SYM(__aeabi_uldivmod), + REG_SYM(__aeabi_i2d), + REG_SYM(__aeabi_dadd), + REG_SYM(__aeabi_ddiv), + REG_SYM(__aeabi_dcmplt), + REG_SYM(__aeabi_dcmpun), + REG_SYM(__aeabi_dcmple), + REG_SYM(__aeabi_dcmpge), + REG_SYM(__aeabi_d2iz), + REG_SYM(__aeabi_fcmplt), + REG_SYM(__aeabi_fcmpun), + REG_SYM(__aeabi_fcmple), + REG_SYM(__aeabi_fcmpge), + REG_SYM(__aeabi_f2iz), + REG_SYM(__aeabi_f2d), }; static void diff --git a/core/iwasm/aot/arch/aot_reloc_thumb.c b/core/iwasm/aot/arch/aot_reloc_thumb.c index 86e2e3305..af0c99d95 100644 --- a/core/iwasm/aot/arch/aot_reloc_thumb.c +++ b/core/iwasm/aot/arch/aot_reloc_thumb.c @@ -43,6 +43,20 @@ void __aeabi_idivmod(); void __aeabi_uidivmod(); void __aeabi_ldivmod(); void __aeabi_uldivmod(); +void __aeabi_i2d(); +void __aeabi_dadd(); +void __aeabi_ddiv(); +void __aeabi_dcmplt(); +void __aeabi_dcmpun(); +void __aeabi_dcmple(); +void __aeabi_dcmpge(); +void __aeabi_d2iz(); +void __aeabi_fcmplt(); +void __aeabi_fcmpun(); +void __aeabi_fcmple(); +void __aeabi_fcmpge(); +void __aeabi_f2iz(); +void __aeabi_f2d(); static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS, @@ -76,7 +90,21 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_idivmod), REG_SYM(__aeabi_uidivmod), REG_SYM(__aeabi_ldivmod), - REG_SYM(__aeabi_uldivmod) + REG_SYM(__aeabi_uldivmod), + REG_SYM(__aeabi_i2d), + REG_SYM(__aeabi_dadd), + REG_SYM(__aeabi_ddiv), + REG_SYM(__aeabi_dcmplt), + REG_SYM(__aeabi_dcmpun), + REG_SYM(__aeabi_dcmple), + REG_SYM(__aeabi_dcmpge), + REG_SYM(__aeabi_d2iz), + REG_SYM(__aeabi_fcmplt), + REG_SYM(__aeabi_fcmpun), + REG_SYM(__aeabi_fcmple), + REG_SYM(__aeabi_fcmpge), + REG_SYM(__aeabi_f2iz), + REG_SYM(__aeabi_f2d), }; static void diff --git a/core/iwasm/common/iwasm_common.cmake b/core/iwasm/common/iwasm_common.cmake index 42ce00417..3e2acfd99 100644 --- a/core/iwasm/common/iwasm_common.cmake +++ b/core/iwasm/common/iwasm_common.cmake @@ -5,6 +5,9 @@ set (IWASM_COMMON_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories (${IWASM_COMMON_DIR}) +add_definitions(-DBH_MALLOC=wasm_runtime_malloc) +add_definitions(-DBH_FREE=wasm_runtime_free) + file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c) if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64") diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 92ec42c96..895cdaea1 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -4,7 +4,6 @@ */ #include "wasm_exec_env.h" -#include "bh_memory.h" #include "wasm_runtime_common.h" WASMExecEnv * @@ -16,14 +15,14 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, WASMExecEnv *exec_env; if (total_size >= UINT32_MAX - || !(exec_env = wasm_malloc((uint32)total_size))) + || !(exec_env = wasm_runtime_malloc((uint32)total_size))) return NULL; memset(exec_env, 0, (uint32)total_size); #if WASM_ENABLE_AOT != 0 - if (!(exec_env->argv_buf = wasm_malloc(sizeof(uint32) * 64))) { - wasm_free(exec_env); + if (!(exec_env->argv_buf = wasm_runtime_malloc(sizeof(uint32) * 64))) { + wasm_runtime_free(exec_env); return NULL; } #endif @@ -40,9 +39,9 @@ void wasm_exec_env_destroy(WASMExecEnv *exec_env) { #if WASM_ENABLE_AOT != 0 - wasm_free(exec_env->argv_buf); + wasm_runtime_free(exec_env->argv_buf); #endif - wasm_free(exec_env); + wasm_runtime_free(exec_env); } WASMModuleInstanceCommon * diff --git a/core/shared/mem-alloc/bh_memory.c b/core/iwasm/common/wasm_memory.c similarity index 58% rename from core/shared/mem-alloc/bh_memory.c rename to core/iwasm/common/wasm_memory.c index 236bf4faa..4f39df8de 100644 --- a/core/shared/mem-alloc/bh_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -3,28 +3,26 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_config.h" +#include "wasm_runtime_common.h" #include "bh_platform.h" -#include "bh_memory.h" #include "mem_alloc.h" -#include +#include "bh_thread.h" #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 -#include "bh_thread.h" /* Memory profile data of a function */ typedef struct memory_profile { - struct memory_profile *next; - const char *function_name; - const char *file_name; - int line_in_file; - int malloc_num; - int free_num; - int total_malloc; - int total_free; + struct memory_profile *next; + const char *function_name; + const char *file_name; + int line_in_file; + int malloc_num; + int free_num; + int total_malloc; + int total_free; } memory_profile_t; -/* Memory in use which grows when bh_malloc was called +/* Memory in use which grows when BH_MALLOC was called * and decreases when bh_free was called */ static unsigned int memory_in_use = 0; @@ -33,7 +31,7 @@ static memory_profile_t *memory_profiles_list = NULL; /* Lock of the memory profile list */ static korp_mutex profile_lock; -#endif +#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */ #ifndef MALLOC_MEMORY_FROM_SYSTEM @@ -48,11 +46,13 @@ static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN; static mem_allocator_t pool_allocator = NULL; static void *(*malloc_func)(unsigned int size) = NULL; +static void *(*realloc_func)(void *ptr, unsigned int size) = NULL; static void (*free_func)(void *ptr) = NULL; static unsigned int global_pool_size; -int bh_memory_init_with_pool(void *mem, unsigned int bytes) +static bool +wasm_memory_init_with_pool(void *mem, unsigned int bytes) { mem_allocator_t _allocator = mem_allocator_create(mem, bytes); @@ -63,29 +63,51 @@ int bh_memory_init_with_pool(void *mem, unsigned int bytes) vm_mutex_init(&profile_lock); #endif global_pool_size = bytes; - return 0; + return true; } bh_printf("Init memory with pool (%p, %u) failed.\n", mem, bytes); - return -1; + return false; } -int bh_memory_init_with_allocator(void *_malloc_func, void *_free_func) +static bool +wasm_memory_init_with_allocator(void *_malloc_func, + void *_realloc_func, + void *_free_func) { if (_malloc_func && _free_func && _malloc_func != _free_func) { memory_mode = MEMORY_MODE_ALLOCATOR; malloc_func = _malloc_func; + realloc_func = _realloc_func; free_func = _free_func; #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 vm_mutex_init(&profile_lock); #endif - return 0; + return true; } - bh_printf("Init memory with allocator (%p, %p) failed.\n", _malloc_func, - _free_func); - return -1; + bh_printf("Init memory with allocator (%p, %p, %p) failed.\n", + _malloc_func, _realloc_func, _free_func); + return false; } -void bh_memory_destroy() +bool +wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, + const MemAllocOption *alloc_option) +{ + if (mem_alloc_type == Alloc_With_Pool) + return wasm_memory_init_with_pool(alloc_option->pool.heap_buf, + alloc_option->pool.heap_size); + else if (mem_alloc_type == Alloc_With_Allocator) + return wasm_memory_init_with_allocator(alloc_option->allocator.malloc_func, + alloc_option->allocator.realloc_func, + alloc_option->allocator.free_func); + else if (mem_alloc_type == Alloc_With_System_Allocator) + return wasm_memory_init_with_allocator(os_malloc, os_realloc, os_free); + else + return false; +} + +void +wasm_runtime_memory_destroy() { #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 vm_mutex_destroy(&profile_lock); @@ -95,7 +117,8 @@ void bh_memory_destroy() memory_mode = MEMORY_MODE_UNKNOWN; } -unsigned bh_memory_pool_size() +unsigned +wasm_runtime_memory_pool_size() { if (memory_mode == MEMORY_MODE_POOL) return global_pool_size; @@ -103,10 +126,11 @@ unsigned bh_memory_pool_size() return 1 * BH_GB; } -void* bh_malloc_internal(unsigned int size) +void * +wasm_runtime_malloc(unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - bh_printf("bh_malloc failed: memory hasn't been initialize.\n"); + bh_printf("wasm_runtime_malloc failed: memory hasn't been initialize.\n"); return NULL; } else if (memory_mode == MEMORY_MODE_POOL) { return mem_allocator_malloc(pool_allocator, size); @@ -115,10 +139,27 @@ void* bh_malloc_internal(unsigned int size) } } -void bh_free_internal(void *ptr) +void * +wasm_runtime_realloc(void *ptr, unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - bh_printf("bh_free failed: memory hasn't been initialize.\n"); + bh_printf("wasm_runtime_realloc failed: memory hasn't been initialize.\n"); + return NULL; + } else if (memory_mode == MEMORY_MODE_POOL) { + return mem_allocator_realloc(pool_allocator, ptr, size); + } else { + if (realloc_func) + return realloc_func(ptr, size); + else + return NULL; + } +} + +void +wasm_runtime_free(void *ptr) +{ + if (memory_mode == MEMORY_MODE_UNKNOWN) { + bh_printf("wasm_runtime_free failed: memory hasn't been initialize.\n"); } else if (memory_mode == MEMORY_MODE_POOL) { mem_allocator_free(pool_allocator, ptr); } else { @@ -127,12 +168,11 @@ void bh_free_internal(void *ptr) } #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 -void* bh_malloc_profile(const char *file, - int line, - const char *func, - unsigned int size) +void * +wasm_runtime_malloc_profile(const char *file, int line, + const char *func, unsigned int size) { - void *p = bh_malloc_internal(size + 8); + void *p = wasm_rutime_malloc(size + 8); if (p) { memory_profile_t *profile; @@ -152,7 +192,7 @@ void* bh_malloc_profile(const char *file, profile->total_malloc += size;/* TODO: overflow check */ profile->malloc_num++; } else { - profile = bh_malloc_internal(sizeof(memory_profile_t)); + profile = wasm_runtime_malloc(sizeof(memory_profile_t)); if (!profile) { vm_mutex_unlock(&profile_lock); bh_memcpy_s(p, size + 8, &size, sizeof(size)); @@ -182,12 +222,14 @@ void* bh_malloc_profile(const char *file, return NULL; } -void bh_free_profile(const char *file, int line, const char *func, void *ptr) +void +wasm_runtime_free_profile(const char *file, int line, + const char *func, void *ptr) { unsigned int size = *(unsigned int *)((char *)ptr - 8); memory_profile_t *profile; - bh_free_internal((char *)ptr - 8); + wasm_runtime_free((char *)ptr - 8); if (memory_in_use >= size) memory_in_use -= size; @@ -207,7 +249,7 @@ void bh_free_profile(const char *file, int line, const char *func, void *ptr) profile->total_free += size;/* TODO: overflow check */ profile->free_num++; } else { - profile = bh_malloc_internal(sizeof(memory_profile_t)); + profile = wasm_runtime_malloc(sizeof(memory_profile_t)); if (!profile) { vm_mutex_unlock(&profile_lock); return; @@ -240,60 +282,53 @@ void memory_usage_summarize() profile = memory_profiles_list; while (profile) { bh_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n", - profile->total_malloc, - profile->malloc_num, - profile->total_free, - profile->free_num, - profile->function_name); + profile->total_malloc, + profile->malloc_num, + profile->total_free, + profile->free_num, + profile->function_name); profile = profile->next; } vm_mutex_unlock(&profile_lock); } -void memory_profile_print(const char *file, - int line, - const char *func, - int alloc) +void +memory_profile_print(const char *file, int line, + const char *func, int alloc) { bh_printf("location:%s@%d:used:%d:contribution:%d\n", - func, line, memory_in_use, alloc); + func, line, memory_in_use, alloc); } -#else - -void* bh_malloc(unsigned int size) -{ - return bh_malloc_internal(size); -} - -void bh_free(void *ptr) -{ - bh_free_internal(ptr); -} -#endif +#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */ #else /* else of MALLOC_MEMORY_FROM_SYSTEM */ -#if BEIHAI_ENABLE_MEMORY_PROFILING == 0 -void* bh_malloc(unsigned int size) +void * +wasm_runtime_malloc(unsigned int size) { return malloc(size); } -void bh_free(void *ptr) +void * +wasm_runtime_realloc(void *ptr, unsigned int size) +{ + return realloc(ptr, size); +} + +void +wasm_runtime_free(void *ptr) { if (ptr) free(ptr); } -#else /* else of BEIHAI_ENABLE_MEMORY_PROFILING */ - -void* bh_malloc_profile(const char *file, - int line, - const char *func, - unsigned int size) +#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +void * +wasm_runtime_malloc_profile(const char *file, int line, + const char *func, unsigned int size) { (void)file; (void)line; @@ -306,7 +341,24 @@ void* bh_malloc_profile(const char *file, return malloc(size); } -void bh_free_profile(const char *file, int line, const char *func, void *ptr) +void * +wasm_runtime_realloc_profile(const char *file, int line, + const char *func, void *ptr, unsigned int size) +{ + (void)file; + (void)line; + (void)func; + + (void)memory_profiles_list; + (void)profile_lock; + (void)memory_in_use; + + return realloc(ptr, size); +} + +void +wasm_runtime_free_profile(const char *file, int line, + const char *func, void *ptr) { (void)file; (void)line; @@ -317,3 +369,4 @@ void bh_free_profile(const char *file, int line, const char *func, void *ptr) } #endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */ #endif /* end of MALLOC_MEMORY_FROM_SYSTEM*/ + diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h new file mode 100644 index 000000000..08157acfb --- /dev/null +++ b/core/iwasm/common/wasm_memory.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_MEMORY_H +#define _WASM_MEMORY_H + +#include "bh_common.h" +#include "../include/wasm_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, + const MemAllocOption *alloc_option); + +void +wasm_runtime_memory_destroy(); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_MEMORY_H */ + diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 29b762da8..38d2f6bd6 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -184,7 +184,7 @@ wasm_native_register_natives(const char *module_name, { NativeSymbolsNode *node; - if (!(node = bh_malloc(sizeof(NativeSymbolsNode)))) + if (!(node = wasm_runtime_malloc(sizeof(NativeSymbolsNode)))) return false; node->module_name = module_name; @@ -256,7 +256,7 @@ wasm_native_destroy() node = g_native_symbols_list; while (node) { node_next = node->next; - bh_free(node); + wasm_runtime_free(node); node = node_next; } diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index dcacd5826..039987848 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -7,18 +7,13 @@ #define _WASM_NATIVE_H #include "bh_common.h" +#include "../include/wasm_export.h" #include "../interpreter/wasm.h" #ifdef __cplusplus extern "C" { #endif -typedef struct NativeSymbol { - const char *symbol; - void *func_ptr; - const char *signature; -} NativeSymbol; - typedef struct NativeSymbolsNode { struct NativeSymbolsNode *next; const char *module_name; diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8aaa97674..f8d7eea07 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -9,6 +9,7 @@ #include "bh_assert.h" #include "bh_log.h" #include "wasm_runtime_common.h" +#include "wasm_memory.h" #if WASM_ENABLE_INTERP != 0 #include "../interpreter/wasm_runtime.h" #endif @@ -23,8 +24,8 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) snprintf(error_buf, error_buf_size, "%s", string); } -bool -wasm_runtime_init() +static bool +wasm_runtime_env_init() { if (bh_platform_init() != 0) return false; @@ -35,8 +36,20 @@ wasm_runtime_init() if (vm_thread_sys_init() != 0) return false; - if (wasm_native_init() == false) { - wasm_runtime_destroy(); + if (wasm_native_init() == false) + return false; + + return true; +} + +bool +wasm_runtime_init() +{ + if (!wasm_runtime_memory_init(Alloc_With_System_Allocator, NULL)) + return false; + + if (!wasm_runtime_env_init()) { + wasm_runtime_memory_destroy(); return false; } @@ -48,6 +61,30 @@ wasm_runtime_destroy() { wasm_native_destroy(); vm_thread_sys_destroy(); + wasm_runtime_memory_destroy(); +} + +bool +wasm_runtime_full_init(RuntimeInitArgs *init_args) +{ + if (!wasm_runtime_memory_init(init_args->mem_alloc_type, + &init_args->mem_alloc_option)) + return false; + + if (!wasm_runtime_env_init()) { + wasm_runtime_memory_destroy(); + return false; + } + + if (init_args->n_native_symbols > 0 + && !wasm_runtime_register_natives(init_args->native_module_name, + init_args->native_symbols, + init_args->n_native_symbols)) { + wasm_runtime_destroy(); + return false; + } + + return true; } PackageType @@ -202,7 +239,7 @@ wasm_runtime_get_module_inst(WASMExecEnv *exec_env) } WASMFunctionInstanceCommon * -wasm_runtime_lookup_function(const WASMModuleInstanceCommon *module_inst, +wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst, const char *name, const char *signature) { @@ -339,7 +376,7 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst) #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) return ((WASMModuleInstance*)module_inst)->custom_data; -#endif +#endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) return ((AOTModuleInstance*)module_inst)->custom_data.ptr; @@ -619,7 +656,7 @@ wasm_runtime_set_wasi_args(WASMModuleCommon *module, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, const char *env_list[], uint32 env_count, - const char *argv[], uint32 argc) + char *argv[], int argc) { WASIArguments *wasi_args = NULL; @@ -649,7 +686,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, const char *env[], uint32 env_count, - const char *argv[], uint32 argc, + char *argv[], uint32 argc, char *error_buf, uint32 error_buf_size) { WASIContext *wasi_ctx; @@ -673,7 +710,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, uint64 total_size; uint32 i; - if (!(wasi_ctx = wasm_malloc(sizeof(WASIContext)))) { + if (!(wasi_ctx = wasm_runtime_malloc(sizeof(WASIContext)))) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: allocate memory failed."); return false; @@ -902,7 +939,7 @@ wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst) fd_table_destroy(wasi_ctx->curfds); if (wasi_ctx->prestats) fd_prestats_destroy(wasi_ctx->prestats); - bh_free(wasi_ctx); + wasm_runtime_free(wasi_ctx); } } @@ -1222,7 +1259,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, total_size = sizeof(uint32) * (uint64)(argc1 > 2 ? argc1 : 2); if (total_size >= UINT32_MAX - || (!(argv1 = wasm_malloc((uint32)total_size)))) { + || (!(argv1 = wasm_runtime_malloc((uint32)total_size)))) { wasm_runtime_set_exception(module_inst, "allocate memory failed."); goto fail; } @@ -1367,12 +1404,12 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, } bh_printf("\n"); - wasm_free(argv1); + wasm_runtime_free(argv1); return true; fail: if (argv1) - wasm_free(argv1); + wasm_runtime_free(argv1); exception = wasm_runtime_get_exception(module_inst); bh_assert(exception); @@ -1501,7 +1538,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { size = sizeof(uint32) * (uint32)argc1; if (size >= UINT32_MAX - || !(argv1 = wasm_malloc((uint32)size))) { + || !(argv1 = wasm_runtime_malloc((uint32)size))) { wasm_runtime_set_exception(exec_env->module_inst, "allocate memory failed."); return false; @@ -1629,7 +1666,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, fail: if (argv1 != argv_buf) - wasm_free(argv1); + wasm_runtime_free(argv1); return ret; } #endif /* end of defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) */ @@ -1676,7 +1713,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { size = sizeof(uint32) * (uint64)argc1; if (size >= UINT_MAX - || !(argv1 = wasm_malloc((uint32)size))) { + || !(argv1 = wasm_runtime_malloc((uint32)size))) { wasm_runtime_set_exception(exec_env->module_inst, "allocate memory failed."); return false; @@ -1769,7 +1806,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, fail: if (argv1 != argv_buf) - wasm_free(argv1); + wasm_runtime_free(argv1); return ret; } @@ -1824,7 +1861,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { size = sizeof(uint64) * (uint64)argc1; if (size >= UINT32_MAX - || !(argv1 = wasm_malloc((uint32)size))) { + || !(argv1 = wasm_runtime_malloc((uint32)size))) { wasm_runtime_set_exception(exec_env->module_inst, "allocate memory failed."); return false; @@ -1926,7 +1963,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, ret = true; fail: if (argv1 != argv_buf) - wasm_free(argv1); + wasm_runtime_free(argv1); return ret; } diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 11fc5c797..39c803c19 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -11,6 +11,7 @@ #include "bh_thread.h" #include "wasm_exec_env.h" #include "wasm_native.h" +#include "../include/wasm_export.h" #include "../interpreter/wasm.h" #if WASM_ENABLE_LIBC_WASI != 0 #include "wasmtime_ssp.h" @@ -21,15 +22,6 @@ extern "C" { #endif -#define wasm_malloc bh_malloc -#define wasm_free bh_free - -/* Package Type */ -typedef enum { - Wasm_Module_Bytecode = 0, - Wasm_Module_AoT, - Package_Type_Unknown = 0xFFFF -} PackageType; typedef struct WASMModuleCommon { /* Module type, for module loaded from WASM bytecode binary, @@ -53,19 +45,6 @@ typedef struct WASMModuleInstanceCommon { uint8 module_inst_data[1]; } WASMModuleInstanceCommon; -typedef void WASMFunctionInstanceCommon; - -/* WASM section */ -typedef struct WASMSection { - struct WASMSection *next; - /* section type */ - int section_type; - /* section body, not include type and size */ - const uint8 *section_body; - /* section body size */ - uint32 section_body_size; -} WASMSection, AOTSection; - #if WASM_ENABLE_LIBC_WASI != 0 typedef struct WASIContext { struct fd_table *curfds; @@ -74,10 +53,17 @@ typedef struct WASIContext { } WASIContext; #endif +typedef package_type_t PackageType; +typedef wasm_section_t WASMSection, AOTSection; + /* See wasm_export.h for description */ bool wasm_runtime_init(); +/* See wasm_export.h for description */ +bool +wasm_runtime_full_init(RuntimeInitArgs *init_args); + /* See wasm_export.h for description */ void wasm_runtime_destroy(); @@ -112,7 +98,7 @@ wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst); /* See wasm_export.h for description */ WASMFunctionInstanceCommon * -wasm_runtime_lookup_function(const WASMModuleInstanceCommon *module_inst, +wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst, const char *name, const char *signature); /* See wasm_export.h for description */ @@ -245,7 +231,7 @@ wasm_runtime_set_wasi_args(WASMModuleCommon *module, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, const char *env_list[], uint32 env_count, - const char *argv[], uint32 argc); + char *argv[], int argc); /* See wasm_export.h for description */ bool @@ -260,7 +246,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, const char *env[], uint32 env_count, - const char *argv[], uint32 argc, + char *argv[], uint32 argc, char *error_buf, uint32 error_buf_size); void diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 83b6bb981..8f8bfaa77 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -4,7 +4,6 @@ */ #include "aot.h" -#include "bh_memory.h" static char aot_error[128]; @@ -30,8 +29,8 @@ aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count) uint32 i; for (i = 0; i < count; i++) if (data_list[i]) - wasm_free(data_list[i]); - wasm_free(data_list); + wasm_runtime_free(data_list[i]); + wasm_runtime_free(data_list); } static AOTMemInitData ** @@ -44,7 +43,7 @@ aot_create_mem_init_data_list(const WASMModule *module) /* Allocate memory */ size = sizeof(AOTMemInitData *) * (uint64)module->data_seg_count; if (size >= UINT32_MAX - || !(data_list = wasm_malloc((uint32)size))) { + || !(data_list = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -56,7 +55,7 @@ aot_create_mem_init_data_list(const WASMModule *module) size = offsetof(AOTMemInitData, bytes) + (uint64)module->data_segments[i]->data_length; if (size >= UINT32_MAX - || !(data_list[i] = wasm_malloc((uint32)size))) { + || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); goto fail; } @@ -80,8 +79,8 @@ aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count) uint32 i; for (i = 0; i < count; i++) if (data_list[i]) - wasm_free(data_list[i]); - wasm_free(data_list); + wasm_runtime_free(data_list[i]); + wasm_runtime_free(data_list); } static AOTTableInitData ** @@ -94,7 +93,7 @@ aot_create_table_init_data_list(const WASMModule *module) /* Allocate memory */ size = sizeof(AOTTableInitData *) * (uint64)module->table_seg_count; if (size >= UINT32_MAX - || !(data_list = wasm_malloc((uint32)size))) { + || !(data_list = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -106,7 +105,7 @@ aot_create_table_init_data_list(const WASMModule *module) size = offsetof(AOTTableInitData, func_indexes) + sizeof(uint32) * (uint64)module->table_segments[i].function_count; if (size >= UINT32_MAX - || !(data_list[i] = wasm_malloc((uint32)size))) { + || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); goto fail; } @@ -135,7 +134,7 @@ aot_create_import_globals(const WASMModule *module, /* Allocate memory */ size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; if (size >= UINT32_MAX - || !(import_globals = wasm_malloc((uint32)size))) { + || !(import_globals = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -172,7 +171,7 @@ aot_create_globals(const WASMModule *module, /* Allocate memory */ size = sizeof(AOTGlobal) * (uint64)module->global_count; if (size >= UINT32_MAX - || !(globals = wasm_malloc((uint32)size))) { + || !(globals = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -202,8 +201,8 @@ aot_destroy_func_types(AOTFuncType **func_types, uint32 count) uint32 i; for (i = 0; i < count; i++) if (func_types[i]) - wasm_free(func_types[i]); - wasm_free(func_types); + wasm_runtime_free(func_types[i]); + wasm_runtime_free(func_types); } static AOTFuncType ** @@ -216,7 +215,7 @@ aot_create_func_types(const WASMModule *module) /* Allocate memory */ size = sizeof(AOTFuncType*) * (uint64)module->type_count; if (size >= UINT32_MAX - || !(func_types = wasm_malloc((uint32)size))) { + || !(func_types = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -229,7 +228,7 @@ aot_create_func_types(const WASMModule *module) (uint64)module->types[i]->param_count + (uint64)module->types[i]->result_count; if (size >= UINT32_MAX - || !(func_types[i] = wasm_malloc((uint32)size))) { + || !(func_types[i] = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); goto fail; } @@ -253,7 +252,7 @@ aot_create_import_funcs(const WASMModule *module) /* Allocate memory */ size = sizeof(AOTImportFunc) * (uint64)module->import_function_count; if (size >= UINT32_MAX - || !(import_funcs = wasm_malloc((uint32)size))) { + || !(import_funcs = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -284,8 +283,8 @@ aot_destroy_funcs(AOTFunc **funcs, uint32 count) for (i = 0; i < count; i++) if (funcs[i]) - wasm_free(funcs[i]); - wasm_free(funcs); + wasm_runtime_free(funcs[i]); + wasm_runtime_free(funcs); } static AOTFunc ** @@ -298,7 +297,7 @@ aot_create_funcs(const WASMModule *module) /* Allocate memory */ size = sizeof(AOTFunc*) * (uint64)module->function_count; if (size >= UINT32_MAX - || !(funcs = wasm_malloc((uint32)size))) { + || !(funcs = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -309,7 +308,7 @@ aot_create_funcs(const WASMModule *module) for (i = 0; i < module->function_count; i++) { WASMFunction *func = module->functions[i]; size = sizeof (AOTFunc); - if (!(funcs[i] = wasm_malloc((uint32)size))) { + if (!(funcs[i] = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); goto fail; } @@ -348,7 +347,7 @@ aot_create_export_funcs(const WASMModule *module, /* Allocate memory */ size = sizeof(AOTExportFunc) * (uint64)export_func_count; if (size >= UINT32_MAX - || !(export_funcs = wasm_malloc((uint32)size))) { + || !(export_funcs = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -376,7 +375,7 @@ aot_create_comp_data(WASMModule *module) uint32 import_global_data_size = 0, global_data_size = 0, i; /* Allocate memory */ - if (!(comp_data = wasm_malloc(sizeof(AOTCompData)))) { + if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) { aot_set_last_error("create compile data failed.\n"); return NULL; } @@ -492,24 +491,24 @@ aot_destroy_comp_data(AOTCompData *comp_data) comp_data->table_init_data_count); if (comp_data->import_globals) - wasm_free(comp_data->import_globals); + wasm_runtime_free(comp_data->import_globals); if (comp_data->globals) - wasm_free(comp_data->globals); + wasm_runtime_free(comp_data->globals); if (comp_data->func_types) aot_destroy_func_types(comp_data->func_types, comp_data->func_type_count); if (comp_data->import_funcs) - wasm_free(comp_data->import_funcs); + wasm_runtime_free(comp_data->import_funcs); if (comp_data->funcs) aot_destroy_funcs(comp_data->funcs, comp_data->func_count); if (comp_data->export_funcs) - wasm_free(comp_data->export_funcs); + wasm_runtime_free(comp_data->export_funcs); - wasm_free(comp_data); + wasm_runtime_free(comp_data); } diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 8d078344e..14e45f0ed 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -14,7 +14,6 @@ #include "aot_emit_control.h" #include "aot_emit_function.h" #include "aot_emit_parametric.h" -#include "bh_memory.h" #include "../aot/aot_runtime.h" #include "../interpreter/wasm_opcode.h" #include @@ -152,7 +151,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) case WASM_OP_BR_TABLE: read_leb_uint32(frame_ip, frame_ip_end, br_count); - if (!(br_depths = wasm_malloc((uint32)sizeof(uint32) * (br_count + 1)))) { + if (!(br_depths = + wasm_runtime_malloc((uint32)sizeof(uint32) * (br_count + 1)))) { aot_set_last_error("allocate memory failed."); goto fail; } @@ -161,11 +161,11 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) if (!aot_compile_op_br_table(comp_ctx, func_ctx, br_depths, br_count, &frame_ip)) { - wasm_free(br_depths); + wasm_runtime_free(br_depths); return false; } - wasm_free(br_depths); + wasm_runtime_free(br_depths); break; case WASM_OP_RETURN: diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index c9959e0ad..d13b43862 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -8,7 +8,6 @@ #include "aot.h" #include "aot_llvm.h" -#include "bh_memory.h" #ifdef __cplusplus extern "C" { @@ -103,7 +102,7 @@ typedef enum FloatArithmetic { && (aot_value->type != VALUE_TYPE_I32 \ && aot_value->type != VALUE_TYPE_I1))) { \ aot_set_last_error("invalid WASM stack data type."); \ - wasm_free(aot_value); \ + wasm_runtime_free(aot_value); \ goto fail; \ } \ if (aot_value->type == value_type) \ @@ -113,11 +112,11 @@ typedef enum FloatArithmetic { if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \ aot_value->value, I32_TYPE, "i1toi32"))) { \ aot_set_last_error("invalid WASM stack data type.");\ - wasm_free(aot_value); \ + wasm_runtime_free(aot_value); \ goto fail; \ } \ } \ - wasm_free(aot_value); \ + wasm_runtime_free(aot_value); \ } while (0) #define POP_I32(v) POP(v, VALUE_TYPE_I32) @@ -133,7 +132,7 @@ typedef enum FloatArithmetic { if (aot_value->type != VALUE_TYPE_I1 \ && aot_value->type != VALUE_TYPE_I32) { \ aot_set_last_error("invalid WASM stack data type."); \ - wasm_free(aot_value); \ + wasm_runtime_free(aot_value); \ goto fail; \ } \ if (aot_value->type == VALUE_TYPE_I1) \ @@ -143,11 +142,11 @@ typedef enum FloatArithmetic { LLVMIntNE, aot_value->value, I32_ZERO, \ "i1_cond"))){ \ aot_set_last_error("llvm build trunc failed."); \ - wasm_free(aot_value); \ + wasm_runtime_free(aot_value); \ goto fail; \ } \ } \ - wasm_free(aot_value); \ + wasm_runtime_free(aot_value); \ } while (0) #define PUSH(llvm_value, value_type) do { \ @@ -156,7 +155,7 @@ typedef enum FloatArithmetic { aot_set_last_error("WASM block stack underflow."); \ goto fail; \ } \ - aot_value = wasm_malloc(sizeof(AOTValue)); \ + aot_value = wasm_runtime_malloc(sizeof(AOTValue)); \ memset(aot_value, 0, sizeof(AOTValue)); \ if (!aot_value) { \ aot_set_last_error("allocate memory failed."); \ diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 29d706fd6..9f8c82d08 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -509,7 +509,7 @@ get_relocation_symbol_index(const char *symbol_name, } /* Not found in symbol_list, add it */ - sym = bh_malloc(sizeof(AOTSymbolNode)); + sym = wasm_runtime_malloc(sizeof(AOTSymbolNode)); if (!sym) { return (uint32)-1; } @@ -1492,7 +1492,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) if (sections_count > 0) { size = (uint32)sizeof(AOTObjectDataSection) * sections_count; - if (!(data_section = obj_data->data_sections = bh_malloc(size))) { + if (!(data_section = obj_data->data_sections = wasm_runtime_malloc(size))) { aot_set_last_error("allocate memory for data sections failed."); return false; } @@ -1531,7 +1531,7 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) /* allocate memory for aot function */ obj_data->func_count = comp_ctx->comp_data->func_count; if (!(obj_data->funcs - = bh_malloc((uint32)sizeof(AOTObjectFunc) * obj_data->func_count))) { + = wasm_runtime_malloc((uint32)sizeof(AOTObjectFunc) * obj_data->func_count))) { aot_set_last_error("allocate memory for functions failed."); return false; } @@ -1602,7 +1602,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, return false; } size = (uint32)sizeof(AOTRelocation) * group->relocation_count; - if (!(relocation = group->relocations = bh_malloc(size))) { + if (!(relocation = group->relocations = wasm_runtime_malloc(size))) { aot_set_last_error("allocate memory for relocations failed."); return false; } @@ -1754,7 +1754,7 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) return true; size = (uint32)sizeof(AOTRelocationGroup) * group_count; - if (!(relocation_group = obj_data->relocation_groups = bh_malloc(size))) { + if (!(relocation_group = obj_data->relocation_groups = wasm_runtime_malloc(size))) { aot_set_last_error("allocate memory for relocation groups failed."); return false; } @@ -1795,8 +1795,8 @@ destroy_relocation_groups(AOTRelocationGroup *relocation_groups, for (i = 0; i < relocation_group_count; i++, relocation_group++) if (relocation_group->relocations) - bh_free(relocation_group->relocations); - bh_free(relocation_groups); + wasm_runtime_free(relocation_group->relocations); + wasm_runtime_free(relocation_groups); } static void @@ -1807,7 +1807,7 @@ destroy_relocation_symbol_list(AOTSymbolList *symbol_list) elem = symbol_list->head; while (elem) { AOTSymbolNode *next = elem->next; - bh_free(elem); + wasm_runtime_free(elem); elem = next; } } @@ -1820,15 +1820,15 @@ aot_obj_data_destroy(AOTObjectData *obj_data) if (obj_data->mem_buf) LLVMDisposeMemoryBuffer(obj_data->mem_buf); if (obj_data->funcs) - bh_free(obj_data->funcs); + wasm_runtime_free(obj_data->funcs); if (obj_data->data_sections) - bh_free(obj_data->data_sections); + wasm_runtime_free(obj_data->data_sections); if (obj_data->relocation_groups) destroy_relocation_groups(obj_data->relocation_groups, obj_data->relocation_group_count); if (obj_data->symbol_list.len) destroy_relocation_symbol_list(&obj_data->symbol_list); - bh_free(obj_data); + wasm_runtime_free(obj_data); } static AOTObjectData * @@ -1837,7 +1837,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx) char *err = NULL; AOTObjectData *obj_data; - if (!(obj_data = bh_malloc(sizeof(AOTObjectData)))) { + if (!(obj_data = wasm_runtime_malloc(sizeof(AOTObjectData)))) { aot_set_last_error("allocate memory failed."); return false; } @@ -1896,7 +1896,7 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data, aot_file_size = get_aot_file_size(comp_data, obj_data); - if (!(buf = aot_file_buf = bh_malloc(aot_file_size))) { + if (!(buf = aot_file_buf = wasm_runtime_malloc(aot_file_size))) { aot_set_last_error("allocate memory failed."); goto fail1; } @@ -1938,7 +1938,7 @@ fail3: fclose(file); fail2: - bh_free(aot_file_buf); + wasm_runtime_free(aot_file_buf); fail1: aot_obj_data_destroy(obj_data); diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index c98a08661..d2a321fa1 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -7,7 +7,6 @@ #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" #include "../interpreter/wasm_loader.h" -#include "bh_memory.h" static char *block_name_prefix[] = { "block", "loop", "if" }; static char *block_name_suffix[] = { "begin", "else", "end" }; @@ -208,7 +207,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Allocate memory */ - if (!(block = wasm_malloc(sizeof(AOTBlock)))) { + if (!(block = wasm_runtime_malloc(sizeof(AOTBlock)))) { aot_set_last_error("allocate memory failed."); return false; } @@ -309,7 +308,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } /* skip the block */ - wasm_free(block); + wasm_runtime_free(block); *p_frame_ip = end_addr + 1; } } @@ -322,7 +321,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return true; fail: - wasm_free(block); + wasm_runtime_free(block); return false; } diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index 21c7324e0..0634435ba 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -247,7 +247,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_count = (int32)func_type->param_count; total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); if (total_size >= UINT32_MAX - || !(param_values = wasm_malloc((uint32)total_size))) { + || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); return false; } @@ -268,7 +268,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Initialize parameter types of the LLVM function */ total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); if (total_size >= UINT32_MAX - || !(param_types = wasm_malloc((uint32)total_size))) { + || !(param_types = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } @@ -321,9 +321,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ret = true; fail: if (param_types) - wasm_free(param_types); + wasm_runtime_free(param_types); if (param_values) - wasm_free(param_values); + wasm_runtime_free(param_values); return ret; } @@ -548,7 +548,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_count = (int32)func_type->param_count; total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); if (total_size >= UINT32_MAX - || !(param_types = wasm_malloc((uint32)total_size))) { + || !(param_types = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } @@ -571,7 +571,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Allocate memory for parameters */ total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); if (total_size >= UINT32_MAX - || !(param_values = wasm_malloc((uint32)total_size))) { + || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } @@ -601,9 +601,9 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, fail: if (param_values) - wasm_free(param_values); + wasm_runtime_free(param_values); if (param_types) - wasm_free(param_types); + wasm_runtime_free(param_types); return ret; } diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index 46ed1cc3d..62ea6cc8c 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -186,7 +186,7 @@ call_llvm_intrinsic(AOTCompContext *comp_ctx, /* Create param values */ total_size = sizeof(LLVMValueRef) * (uint64)param_count; if (total_size >= UINT32_MAX - || !(param_values = wasm_malloc((uint32)total_size))) { + || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("allocate memory for param values failed."); return false; } @@ -201,7 +201,7 @@ call_llvm_intrinsic(AOTCompContext *comp_ctx, param_types, param_count, param_values); - wasm_free(param_values); + wasm_runtime_free(param_values); return ret; } @@ -221,7 +221,7 @@ call_llvm_intrinsic_v(AOTCompContext *comp_ctx, /* Create param values */ total_size = sizeof(LLVMValueRef) * (uint64)param_count; if (total_size >= UINT32_MAX - || !(param_values = wasm_malloc((uint32)total_size))) { + || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("allocate memory for param values failed."); return false; } @@ -234,7 +234,7 @@ call_llvm_intrinsic_v(AOTCompContext *comp_ctx, param_types, param_count, param_values); - wasm_free(param_values); + wasm_runtime_free(param_values); return ret; } @@ -857,13 +857,34 @@ fail: return false; } +static bool +is_targeting_soft_float(LLVMTargetMachineRef target_machine) +{ + bool ret = false; + char *feature_string; + + if (!(feature_string = + LLVMGetTargetMachineFeatureString(target_machine))) { + aot_set_last_error("llvm get target machine feature string fail."); + return false; + } + + ret = strstr(feature_string, "+soft-float") ? true : false; + LLVMDisposeMessage(feature_string); + return ret; +} + static bool compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatArithmetic arith_op, bool is_f32) { switch (arith_op) { case FLOAT_ADD: - DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + if (is_targeting_soft_float(comp_ctx->target_machine)) + DEF_FP_BINARY_OP(LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"), + "llvm build fadd fail."); + else + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( comp_ctx, (is_f32 ? "llvm.experimental.constrained.fadd.f32" @@ -873,10 +894,14 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, right, comp_ctx->fp_rounding_mode, comp_ctx->fp_exception_behavior), - NULL); + NULL); return true; case FLOAT_SUB: - DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + if (is_targeting_soft_float(comp_ctx->target_machine)) + DEF_FP_BINARY_OP(LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"), + "llvm build fsub fail."); + else + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( comp_ctx, (is_f32 ? "llvm.experimental.constrained.fsub.f32" @@ -886,10 +911,14 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, right, comp_ctx->fp_rounding_mode, comp_ctx->fp_exception_behavior), - NULL); + NULL); return true; case FLOAT_MUL: - DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + if (is_targeting_soft_float(comp_ctx->target_machine)) + DEF_FP_BINARY_OP(LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"), + "llvm build fmul fail."); + else + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( comp_ctx, (is_f32 ? "llvm.experimental.constrained.fmul.f32" @@ -899,10 +928,14 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, right, comp_ctx->fp_rounding_mode, comp_ctx->fp_exception_behavior), - NULL); + NULL); return true; case FLOAT_DIV: - DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + if (is_targeting_soft_float(comp_ctx->target_machine)) + DEF_FP_BINARY_OP(LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"), + "llvm build fdiv fail."); + else + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( comp_ctx, (is_f32 ? "llvm.experimental.constrained.fdiv.f32" @@ -912,7 +945,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, right, comp_ctx->fp_rounding_mode, comp_ctx->fp_exception_behavior), - NULL); + NULL); return true; case FLOAT_MIN: DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, @@ -1017,7 +1050,15 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, NULL); return true; case FLOAT_SQRT: - DEF_FP_UNARY_OP(call_llvm_libm_expermental_constrained_intrinsic( + if (is_targeting_soft_float(comp_ctx->target_machine)) + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, + is_f32 ? "llvm.sqrt.f32" : + "llvm.sqrt.f64", + is_f32, + operand), + NULL); + else + DEF_FP_UNARY_OP(call_llvm_libm_expermental_constrained_intrinsic( comp_ctx, (is_f32 ? "llvm.experimental.constrained.sqrt.f32" @@ -1026,7 +1067,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, operand, comp_ctx->fp_rounding_mode, comp_ctx->fp_exception_behavior), - NULL); + NULL); return true; default: bh_assert(0); diff --git a/core/iwasm/compilation/aot_emit_parametric.c b/core/iwasm/compilation/aot_emit_parametric.c index 0660f9562..dc81ad53e 100644 --- a/core/iwasm/compilation/aot_emit_parametric.c +++ b/core/iwasm/compilation/aot_emit_parametric.c @@ -43,7 +43,7 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, *p_value = aot_value->value; } - wasm_free(aot_value); + wasm_runtime_free(aot_value); if ((is_32 && (type != VALUE_TYPE_I32 && type != VALUE_TYPE_F32)) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index f12ff7c28..a7a7e799f 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -4,7 +4,6 @@ */ #include "aot_llvm.h" -#include "bh_memory.h" #include "aot_compiler.h" #include "../aot/aot_runtime.h" @@ -47,7 +46,7 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, /* Initialize parameter types of the LLVM function */ size = sizeof(LLVMTypeRef) * ((uint64)param_count); if (size >= UINT32_MAX - || !(param_types = wasm_malloc((uint32)size))) { + || !(param_types = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -88,7 +87,7 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, } fail: - wasm_free(param_types); + wasm_runtime_free(param_types); return func; } @@ -102,7 +101,7 @@ aot_create_func_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, AOTBlock *aot_block; /* Allocate memory */ - if (!(aot_block = wasm_malloc(sizeof(AOTBlock)))) { + if (!(aot_block = wasm_runtime_malloc(sizeof(AOTBlock)))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -129,7 +128,7 @@ aot_create_func_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return aot_block; fail: - wasm_free(aot_block); + wasm_runtime_free(aot_block); return NULL; } @@ -137,7 +136,7 @@ static bool create_exception_blocks(AOTFuncContext *func_ctx) { if (!(func_ctx->exception_blocks = - wasm_malloc(sizeof(LLVMBasicBlockRef) * EXCE_NUM))) { + wasm_runtime_malloc(sizeof(LLVMBasicBlockRef) * EXCE_NUM))) { aot_set_last_error("allocate memory failed."); return false;; } @@ -451,7 +450,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, size = offsetof(AOTFuncContext, locals) + sizeof(LLVMValueRef) * ((uint64)aot_func_type->param_count + func->local_count); if (size >= UINT32_MAX - || !(func_ctx = wasm_malloc((uint32)size))) { + || !(func_ctx = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -605,9 +604,9 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, fail: if (func_ctx->exception_blocks) - wasm_free(func_ctx->exception_blocks); + wasm_runtime_free(func_ctx->exception_blocks); aot_block_stack_destroy(&func_ctx->block_stack); - wasm_free(func_ctx); + wasm_runtime_free(func_ctx); return NULL; } @@ -619,11 +618,11 @@ aot_destroy_func_contexts(AOTFuncContext **func_ctxes, uint32 count) for (i = 0; i < count; i++) if (func_ctxes[i]) { if (func_ctxes[i]->exception_blocks) - wasm_free(func_ctxes[i]->exception_blocks); + wasm_runtime_free(func_ctxes[i]->exception_blocks); aot_block_stack_destroy(&func_ctxes[i]->block_stack); - wasm_free(func_ctxes[i]); + wasm_runtime_free(func_ctxes[i]); } - wasm_free(func_ctxes); + wasm_runtime_free(func_ctxes); } /** @@ -639,7 +638,7 @@ aot_create_func_contexts(AOTCompData *comp_data, AOTCompContext *comp_ctx) /* Allocate memory */ size = sizeof(AOTFuncContext*) * (uint64)comp_data->func_count; if (size >= UINT32_MAX - || !(func_ctxes = wasm_malloc((uint32)size))) { + || !(func_ctxes = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -877,7 +876,7 @@ aot_create_comp_context(AOTCompData *comp_data, LLVMLinkInMCJIT(); /* Allocate memory */ - if (!(comp_ctx = wasm_malloc(sizeof(AOTCompContext)))) { + if (!(comp_ctx = wasm_runtime_malloc(sizeof(AOTCompContext)))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -1176,7 +1175,7 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (comp_ctx->func_ctxes) aot_destroy_func_contexts(comp_ctx->func_ctxes, comp_ctx->func_ctx_count); - wasm_free(comp_ctx); + wasm_runtime_free(comp_ctx); } void @@ -1216,7 +1215,7 @@ aot_value_stack_destroy(AOTValueStack *stack) while (value) { p = value->next; - wasm_free(value); + wasm_runtime_free(value); value = p; } } @@ -1259,7 +1258,7 @@ aot_block_stack_destroy(AOTBlockStack *stack) while (block) { p = block->next; aot_value_stack_destroy(&block->value_stack); - wasm_free(block); + wasm_runtime_free(block); block = p; } } @@ -1268,5 +1267,5 @@ void aot_block_destroy(AOTBlock *block) { aot_value_stack_destroy(&block->value_stack); - wasm_free(block); + wasm_runtime_free(block); } diff --git a/core/iwasm/include/bh_memory.h b/core/iwasm/include/bh_memory.h deleted file mode 100644 index 4b3aa86db..000000000 --- a/core/iwasm/include/bh_memory.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_MEMORY_H -#define _BH_MEMORY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define BH_KB (1024) -#define BH_MB ((BH_KB)*1024) -#define BH_GB ((BH_MB)*1024) - -/** - * Initialize memory allocator with a pool, the bh_malloc/bh_free function - * will malloc/free memory from the pool - * - * @param mem the pool buffer - * @param bytes the size bytes of the buffer - * - * @return 0 if success, -1 otherwise - */ -int bh_memory_init_with_pool(void *mem, unsigned int bytes); - -/** - * Initialize memory allocator with memory allocator, the bh_malloc/bh_free - * function will malloc/free memory with the allocator passed - * - * @param malloc_func the malloc function - * @param free_func the free function - * - * @return 0 if success, -1 otherwise - */ -int bh_memory_init_with_allocator(void *malloc_func, void *free_func); - -/** - * Destroy memory - */ -void bh_memory_destroy(); - -/** - * Get the pool size of memory, if memory is initialized with allocator, - * return 1GB by default. - */ -unsigned bh_memory_pool_size(); - -#if BEIHAI_ENABLE_MEMORY_PROFILING == 0 - -/** - * This function allocates a memory chunk from system - * - * @param size bytes need allocate - * - * @return the pointer to memory allocated - */ -void* bh_malloc(unsigned int size); - -/** - * This function frees memory chunk - * - * @param ptr the pointer to memory need free - */ -void bh_free(void *ptr); - -#else - -void* bh_malloc_profile(const char *file, int line, const char *func, unsigned int size); -void bh_free_profile(const char *file, int line, const char *func, void *ptr); - -#define bh_malloc(size) bh_malloc_profile(__FILE__, __LINE__, __func__, size) -#define bh_free(ptr) bh_free_profile(__FILE__, __LINE__, __func__, ptr) - -/** - * Print current memory profiling data - * - * @param file file name of the caller - * @param line line of the file of the caller - * @param func function name of the caller - */ -void memory_profile_print(const char *file, int line, const char *func, int alloc); - -/** - * Summarize memory usage and print it out - * Can use awk to analyze the output like below: - * awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1 - */ -void memory_usage_summarize(); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef _BH_MEMORY_H */ - diff --git a/core/iwasm/include/lib_export.h b/core/iwasm/include/lib_export.h index 97e043e11..8489afc49 100644 --- a/core/iwasm/include/lib_export.h +++ b/core/iwasm/include/lib_export.h @@ -6,6 +6,8 @@ #ifndef _LIB_EXPORT_H_ #define _LIB_EXPORT_H_ +#include + #ifdef __cplusplus extern "C" { #endif @@ -31,25 +33,9 @@ typedef struct NativeSymbol { * * @return the number of the exported API */ -int +uint32_t get_base_lib_export_apis(NativeSymbol **p_base_lib_apis); -/** - * Get the exported APIs of extended lib, this API isn't provided by WASM VM, - * it must be provided by developer to register the extended native APIs, - * for example, developer can register his native APIs to extended_native_symbol_defs, - * array, and include file ext_lib_export.h which implements this API. - * And if developer hasn't any native API to register, he can define an empty - * extended_native_symbol_defs array, and then include file ext_lib_export.h to - * implements this API. - * - * @param p_base_lib_apis return the exported API array of extend lib - * - * @return the number of the exported API - */ -int -get_extend_lib_export_apis(NativeSymbol **p_base_lib_apis); - #ifdef __cplusplus } #endif diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index a0654c496..57b2ec077 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -25,21 +25,19 @@ struct WASMModuleInstanceCommon; typedef struct WASMModuleInstanceCommon *wasm_module_inst_t; /* Function instance */ -struct WASMFunctionInstanceCommon; -typedef struct WASMFunctionInstanceCommon *wasm_function_inst_t; +typedef void WASMFunctionInstanceCommon; +typedef WASMFunctionInstanceCommon *wasm_function_inst_t; /* WASM section */ -typedef struct wasm_section { - struct wasm_section *next; +typedef struct wasm_section_t { + struct wasm_section_t *next; /* section type */ int section_type; /* section body, not include type and size */ uint8_t *section_body; /* section body size */ uint32_t section_body_size; -} wasm_section_t, *wasm_section_list_t; - -typedef wasm_section_t aot_section_t, *aot_section_list_t; +} wasm_section_t, aot_section_t, *wasm_section_list_t, *aot_section_list_t; /* Execution environment, e.g. stack info */ struct WASMExecEnv; @@ -52,20 +50,95 @@ typedef enum { Package_Type_Unknown = 0xFFFF } package_type_t; +/* Memory allocator type */ +typedef enum { + /* pool mode, allocate memory from user defined heap buffer */ + Alloc_With_Pool = 0, + /* user allocator mode, allocate memory from user defined + malloc function */ + Alloc_With_Allocator, + /* system allocator mode, allocate memory from system allocator, + or, platform's os_malloc function */ + Alloc_With_System_Allocator, +} mem_alloc_type_t; + +/* Memory allocator option */ +typedef union MemAllocOption { + struct { + void *heap_buf; + uint32_t heap_size; + } pool; + struct { + void *malloc_func; + void *realloc_func; + void *free_func; + } allocator; +} MemAllocOption; + +/* WASM runtime initialize arguments */ +typedef struct RuntimeInitArgs { + mem_alloc_type_t mem_alloc_type; + MemAllocOption mem_alloc_option; + + const char *native_module_name; + NativeSymbol *native_symbols; + uint32_t n_native_symbols; +} RuntimeInitArgs; + /** - * Initialize the WASM runtime environment. + * Initialize the WASM runtime environment, and also initialize + * the memory allocator with system allocator, which calls os_malloc + * to allocate memory * * @return true if success, false otherwise */ bool wasm_runtime_init(); +/** + * Initialize the WASM runtime environment, and also initialize + * the memory allocator and register native symbols, which are specified + * with init arguments + * + * @param init_args specifies the init arguments + * + * @return return true if success, false otherwise + */ +bool +wasm_runtime_full_init(RuntimeInitArgs *init_args); + /** * Destroy the WASM runtime environment. */ void wasm_runtime_destroy(); +/** + * Allocate memory from runtime memory environment. + * + * @param size bytes need to allocate + * + * @return the pointer to memory allocated + */ +void * +wasm_runtime_malloc(unsigned int size); + +/** + * Reallocate memory from runtime memory environment + * + * @param ptr the original memory + * @param size bytes need to reallocate + * + * @return the pointer to memory reallocated + */ +void * +wasm_runtime_realloc(void *ptr, unsigned int size); + +/* + * Free memory to runtime memory environment. + */ +void wasm_runtime_free(void *ptr); + /** * Get the package type of a buffer. * @@ -167,7 +240,7 @@ wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst); * @return the function instance found */ wasm_function_inst_t -wasm_runtime_lookup_function(const wasm_module_inst_t module_inst, +wasm_runtime_lookup_function(wasm_module_inst_t const module_inst, const char *name, const char *signature); /** diff --git a/core/iwasm/interpreter/iwasm_interp.cmake b/core/iwasm/interpreter/iwasm_interp.cmake index 9ac035b1c..bb4f23219 100644 --- a/core/iwasm/interpreter/iwasm_interp.cmake +++ b/core/iwasm/interpreter/iwasm_interp.cmake @@ -7,7 +7,17 @@ add_definitions (-DWASM_ENABLE_INTERP=1) include_directories(${IWASM_INTERP_DIR}) -file (GLOB_RECURSE source_all ${IWASM_INTERP_DIR}/*.c) +if (WAMR_BUILD_FAST_INTERP EQUAL 1) + set (INTERPRETER "wasm_interp_fast.c") +else () + set (INTERPRETER "wasm_interp_classic.c") +endif () + +file (GLOB_RECURSE source_all + ${IWASM_INTERP_DIR}/wasm_loader.c + ${IWASM_INTERP_DIR}/wasm_runtime.c + ${IWASM_INTERP_DIR}/${INTERPRETER} +) set (IWASM_INTERP_SOURCE ${source_all}) diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index f730d7a11..d1c6b661e 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -189,6 +189,12 @@ typedef struct WASMFunction { bool has_op_func_call; uint32 code_size; uint8 *code; +#if WASM_ENABLE_FAST_INTERP != 0 + uint32 code_compiled_size; + uint8 *code_compiled; + uint8 *consts; + uint32 const_cell_num; +#endif } WASMFunction; typedef struct WASMGlobal { @@ -231,7 +237,7 @@ typedef struct WASIArguments { uint32 map_dir_count; const char **env; uint32 env_count; - const char **argv; + char **argv; uint32 argc; } WASIArguments; #endif diff --git a/core/iwasm/interpreter/wasm_interp.h b/core/iwasm/interpreter/wasm_interp.h index 3d7844065..9883d2654 100644 --- a/core/iwasm/interpreter/wasm_interp.h +++ b/core/iwasm/interpreter/wasm_interp.h @@ -26,6 +26,13 @@ typedef struct WASMInterpFrame { /* Instruction pointer of the bytecode array. */ uint8 *ip; +#if WASM_ENABLE_FAST_INTERP != 0 + /* return offset of current frame. + the callee will put return value here */ + uint32 ret_offset; + uint32 *lp; + uint32 operand[1]; +#else /* Operand stack top pointer of the current frame. The bottom of the stack is the next cell after the last local variable. */ uint32 *sp_bottom; @@ -43,6 +50,7 @@ typedef struct WASMInterpFrame { ref to frame end: data types of local vairables and stack data */ uint32 lp[1]; +#endif } WASMInterpFrame; /** diff --git a/core/iwasm/interpreter/wasm_interp.c b/core/iwasm/interpreter/wasm_interp_classic.c similarity index 98% rename from core/iwasm/interpreter/wasm_interp.c rename to core/iwasm/interpreter/wasm_interp_classic.c index bcba0d516..c18151ee6 100644 --- a/core/iwasm/interpreter/wasm_interp.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4,7 +4,6 @@ */ #include "wasm_interp.h" -#include "bh_memory.h" #include "bh_log.h" #include "wasm_runtime.h" #include "wasm_opcode.h" @@ -225,27 +224,24 @@ LOAD_I16(void *addr) #endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ #define CHECK_MEMORY_OVERFLOW() do { \ - uint32 offset1 = offset + addr; \ + uint64 offset1 = offset + addr; \ /* if (flags != 2) \ LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\ /* The WASM spec doesn't require that the dynamic address operand must be \ unsigned, so we don't check whether integer overflow or not here. */ \ /* if (offset1 < offset) \ goto out_of_bounds; */ \ - if (offset1 < memory_data_size) { \ + if (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= memory_data_size) { \ /* If offset1 is in valid range, maddr must also be in valid range, \ no need to check it again. */ \ maddr = memory->memory_data + offset1; \ - if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > memory->end_addr) \ - goto out_of_bounds; \ } \ - else if (offset1 > heap_base_offset \ - && offset1 < heap_base_offset + heap_data_size) { \ + else if (offset1 > DEFAULT_APP_HEAP_BASE_OFFSET \ + && (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= \ + DEFAULT_APP_HEAP_BASE_OFFSET + heap_data_size)) { \ /* If offset1 is in valid range, maddr must also be in valid range, \ no need to check it again. */ \ maddr = memory->heap_data + offset1 - memory->heap_base_offset; \ - if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > memory->heap_data_end) \ - goto out_of_bounds; \ } \ else \ goto out_of_bounds; \ @@ -795,7 +791,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMMemoryInstance *memory = module->default_memory; uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; uint32 memory_data_size = memory ? num_bytes_per_page * memory->cur_page_count : 0; - uint32 heap_base_offset = memory ? (uint32)memory->heap_base_offset : 0; uint32 heap_data_size = memory ? (uint32)(memory->heap_data_end - memory->heap_data) : 0; uint8 *global_data = memory ? memory->global_data : NULL; WASMTableInstance *table = module->default_table; @@ -952,7 +947,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, else { uint64 total_size = sizeof(uint32) * (uint64)count; if (total_size >= UINT32_MAX - || !(depths = wasm_malloc((uint32)total_size))) { + || !(depths = wasm_runtime_malloc((uint32)total_size))) { wasm_set_exception(module, "WASM interp failed: allocate memory failed."); goto got_exception; @@ -967,7 +962,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, depth = depths[didx]; } if (depths != depth_buf) { - wasm_free(depths); + wasm_runtime_free(depths); depths = NULL; } POP_CSP_N(depth); @@ -1080,7 +1075,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP_END (); } - HANDLE_OP (WASM_OP_GET_LOCAL_FAST): + HANDLE_OP (EXT_OP_GET_LOCAL_FAST): { local_offset = *frame_ip++; if (local_offset & 0x80) @@ -1111,7 +1106,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP_END (); } - HANDLE_OP (WASM_OP_SET_LOCAL_FAST): + HANDLE_OP (EXT_OP_SET_LOCAL_FAST): { local_offset = *frame_ip++; if (local_offset & 0x80) @@ -1143,7 +1138,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP_END (); } - HANDLE_OP (WASM_OP_TEE_LOCAL_FAST): + HANDLE_OP (EXT_OP_TEE_LOCAL_FAST): { local_offset = *frame_ip++; if (local_offset & 0x80) @@ -2225,6 +2220,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP (WASM_OP_UNUSED_0x25): HANDLE_OP (WASM_OP_UNUSED_0x26): HANDLE_OP (WASM_OP_UNUSED_0x27): + /* Used by fast interpreter */ + HANDLE_OP (EXT_OP_SET_LOCAL_FAST_I64): + HANDLE_OP (EXT_OP_TEE_LOCAL_FAST_I64): + HANDLE_OP (EXT_OP_COPY_STACK_TOP): + HANDLE_OP (EXT_OP_COPY_STACK_TOP_I64): { wasm_set_exception(module, "WASM interp failed: unsupported opcode."); goto got_exception; diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c new file mode 100644 index 000000000..c372115e1 --- /dev/null +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -0,0 +1,2278 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_interp.h" +#include "bh_log.h" +#include "wasm_runtime.h" +#include "wasm_opcode.h" +#include "wasm_loader.h" +#include "../common/wasm_exec_env.h" + +typedef int32 CellType_I32; +typedef int64 CellType_I64; +typedef float32 CellType_F32; +typedef float64 CellType_F64; + +#define BR_TABLE_TMP_BUF_LEN 32 + +/* 64-bit Memory accessors. */ +#if WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 +#define PUT_I64_TO_ADDR(addr, value) do { \ + *(int64*)(addr) = (int64)(value); \ + } while (0) +#define PUT_F64_TO_ADDR(addr, value) do { \ + *(float64*)(addr) = (float64)(value); \ + } while (0) + +#define GET_I64_FROM_ADDR(addr) (*(int64*)(addr)) +#define GET_F64_FROM_ADDR(addr) (*(float64*)(addr)) + +/* For STORE opcodes */ +#define STORE_I64 PUT_I64_TO_ADDR +#define STORE_U32(addr, value) do { \ + *(uint32*)(addr) = (uint32)(value); \ + } while (0) +#define STORE_U16(addr, value) do { \ + *(uint16*)(addr) = (uint16)(value); \ + } while (0) + +/* For LOAD opcodes */ +#define LOAD_I64(addr) (*(int64*)(addr)) +#define LOAD_F64(addr) (*(float64*)(addr)) +#define LOAD_F32(addr) (*(float32*)(addr)) +#define LOAD_I32(addr) (*(int32*)(addr)) +#define LOAD_U32(addr) (*(uint32*)(addr)) +#define LOAD_I16(addr) (*(int16*)(addr)) +#define LOAD_U16(addr) (*(uint16*)(addr)) + +#else /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ +#define PUT_I64_TO_ADDR(addr, value) do { \ + union { int64 val; uint32 parts[2]; } u; \ + u.val = (int64)(value); \ + (addr)[0] = u.parts[0]; \ + (addr)[1] = u.parts[1]; \ + } while (0) +#define PUT_F64_TO_ADDR(addr, value) do { \ + union { float64 val; uint32 parts[2]; } u; \ + u.val = (value); \ + (addr)[0] = u.parts[0]; \ + (addr)[1] = u.parts[1]; \ + } while (0) + +static inline int64 +GET_I64_FROM_ADDR(uint32 *addr) +{ + union { int64 val; uint32 parts[2]; } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +static inline float64 +GET_F64_FROM_ADDR (uint32 *addr) +{ + union { float64 val; uint32 parts[2]; } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +/* For STORE opcodes */ +#define STORE_I64(addr, value) do { \ + uintptr_t addr1 = (uintptr_t)(addr); \ + union { int64 val; uint32 u32[2]; \ + uint16 u16[4]; uint8 u8[8]; } u; \ + if ((addr1 & (uintptr_t)7) == 0) \ + *(int64*)(addr) = (int64)(value); \ + else { \ + u.val = (int64)(value); \ + if ((addr1 & (uintptr_t)3) == 0) { \ + ((uint32*)(addr))[0] = u.u32[0]; \ + ((uint32*)(addr))[1] = u.u32[1]; \ + } \ + else if ((addr1 & (uintptr_t)1) == 0) { \ + ((uint16*)(addr))[0] = u.u16[0]; \ + ((uint16*)(addr))[1] = u.u16[1]; \ + ((uint16*)(addr))[2] = u.u16[2]; \ + ((uint16*)(addr))[3] = u.u16[3]; \ + } \ + else { \ + int32 t; \ + for (t = 0; t < 8; t++) \ + ((uint8*)(addr))[t] = u.u8[t]; \ + } \ + } \ + } while (0) + +#define STORE_U32(addr, value) do { \ + uintptr_t addr1 = (uintptr_t)(addr); \ + union { uint32 val; \ + uint16 u16[2]; uint8 u8[4]; } u; \ + if ((addr1 & (uintptr_t)3) == 0) \ + *(uint32*)(addr) = (uint32)(value); \ + else { \ + u.val = (uint32)(value); \ + if ((addr1 & (uintptr_t)1) == 0) { \ + ((uint16*)(addr))[0] = u.u16[0]; \ + ((uint16*)(addr))[1] = u.u16[1]; \ + } \ + else { \ + ((uint8*)(addr))[0] = u.u8[0]; \ + ((uint8*)(addr))[1] = u.u8[1]; \ + ((uint8*)(addr))[2] = u.u8[2]; \ + ((uint8*)(addr))[3] = u.u8[3]; \ + } \ + } \ + } while (0) + +#define STORE_U16(addr, value) do { \ + union { uint16 val; uint8 u8[2]; } u; \ + u.val = (uint16)(value); \ + ((uint8*)(addr))[0] = u.u8[0]; \ + ((uint8*)(addr))[1] = u.u8[1]; \ + } while (0) + +/* For LOAD opcodes */ +static inline int64 +LOAD_I64(void *addr) +{ + uintptr_t addr1 = (uintptr_t)addr; + union { int64 val; uint32 u32[2]; + uint16 u16[4]; uint8 u8[8]; } u; + if ((addr1 & (uintptr_t)7) == 0) + return *(int64*)addr; + + if ((addr1 & (uintptr_t)3) == 0) { + u.u32[0] = ((uint32*)addr)[0]; + u.u32[1] = ((uint32*)addr)[1]; + } + else if ((addr1 & (uintptr_t)1) == 0) { + u.u16[0] = ((uint16*)addr)[0]; + u.u16[1] = ((uint16*)addr)[1]; + u.u16[2] = ((uint16*)addr)[2]; + u.u16[3] = ((uint16*)addr)[3]; + } + else { + int32 t; + for (t = 0; t < 8; t++) + u.u8[t] = ((uint8*)addr)[t]; + } + return u.val; +} + +static inline float64 +LOAD_F64(void *addr) +{ + uintptr_t addr1 = (uintptr_t)addr; + union { float64 val; uint32 u32[2]; + uint16 u16[4]; uint8 u8[8]; } u; + if ((addr1 & (uintptr_t)7) == 0) + return *(float64*)addr; + + if ((addr1 & (uintptr_t)3) == 0) { + u.u32[0] = ((uint32*)addr)[0]; + u.u32[1] = ((uint32*)addr)[1]; + } + else if ((addr1 & (uintptr_t)1) == 0) { + u.u16[0] = ((uint16*)addr)[0]; + u.u16[1] = ((uint16*)addr)[1]; + u.u16[2] = ((uint16*)addr)[2]; + u.u16[3] = ((uint16*)addr)[3]; + } + else { + int32 t; + for (t = 0; t < 8; t++) + u.u8[t] = ((uint8*)addr)[t]; + } + return u.val; +} + +static inline int32 +LOAD_I32(void *addr) +{ + uintptr_t addr1 = (uintptr_t)addr; + union { int32 val; uint16 u16[2]; uint8 u8[4]; } u; + if ((addr1 & (uintptr_t)3) == 0) + return *(int32*)addr; + + if ((addr1 & (uintptr_t)1) == 0) { + u.u16[0] = ((uint16*)addr)[0]; + u.u16[1] = ((uint16*)addr)[1]; + } + else { + u.u8[0] = ((uint8*)addr)[0]; + u.u8[1] = ((uint8*)addr)[1]; + u.u8[2] = ((uint8*)addr)[2]; + u.u8[3] = ((uint8*)addr)[3]; + } + return u.val; +} + +static inline int16 +LOAD_I16(void *addr) +{ + union { int16 val; uint8 u8[2]; } u; + u.u8[0] = ((uint8*)addr)[0]; + u.u8[1] = ((uint8*)addr)[1]; + return u.val; +} + +#define LOAD_U32(addr) ((uint32)LOAD_I32(addr)) +#define LOAD_U16(addr) ((uint16)LOAD_I16(addr)) +#define LOAD_F32(addr) ((float32)LOAD_I32(addr)) + +#endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ + +#define CHECK_MEMORY_OVERFLOW() do { \ + uint64 offset1 = offset + addr; \ + /* if (flags != 2) \ + LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\ + /* The WASM spec doesn't require that the dynamic address operand must be \ + unsigned, so we don't check whether integer overflow or not here. */ \ + /* if (offset1 < offset) \ + goto out_of_bounds; */ \ + if (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= memory_data_size) { \ + /* If offset1 is in valid range, maddr must also be in valid range, \ + no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + } \ + else if (offset1 > DEFAULT_APP_HEAP_BASE_OFFSET \ + && (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= \ + DEFAULT_APP_HEAP_BASE_OFFSET + heap_data_size)) { \ + /* If offset1 is in valid range, maddr must also be in valid range, \ + no need to check it again. */ \ + maddr = memory->heap_data + offset1 - DEFAULT_APP_HEAP_BASE_OFFSET; \ + } \ + else \ + goto out_of_bounds; \ + } while (0) + +#define CHECK_MEMORY_OVERFLOW_FAST(bytes) do { \ + uint64 offset1 = offset + addr; \ + /* if (flags != 2) \ + LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\ + /* The WASM spec doesn't require that the dynamic address operand must be \ + unsigned, so we don't check whether integer overflow or not here. */ \ + /* if (offset1 < offset) \ + goto out_of_bounds; */ \ + if (offset1 + bytes <= memory_data_size) { \ + /* If offset1 is in valid range, maddr must also be in valid range, \ + no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + } \ + else if (offset1 > DEFAULT_APP_HEAP_BASE_OFFSET \ + && (offset1 + bytes <= \ + DEFAULT_APP_HEAP_BASE_OFFSET + heap_data_size)) { \ + /* If offset1 is in valid range, maddr must also be in valid range, \ + no need to check it again. */ \ + maddr = memory->heap_data + offset1 - DEFAULT_APP_HEAP_BASE_OFFSET; \ + } \ + else \ + goto out_of_bounds; \ + } while (0) + +static inline uint32 +rotl32(uint32 n, uint32 c) +{ + const uint32 mask = (31); + c = c % 32; + c &= mask; + return (n<>( (-c)&mask )); +} + +static inline uint32 +rotr32(uint32 n, uint32 c) +{ + const uint32 mask = (31); + c = c % 32; + c &= mask; + return (n>>c) | (n<<( (-c)&mask )); +} + +static inline uint64 +rotl64(uint64 n, uint64 c) +{ + const uint64 mask = (63); + c = c % 64; + c &= mask; + return (n<>( (-c)&mask )); +} + +static inline uint64 +rotr64(uint64 n, uint64 c) +{ + const uint64 mask = (63); + c = c % 64; + c &= mask; + return (n>>c) | (n<<( (-c)&mask )); +} + +static inline double +wa_fmax(double a, double b) +{ + double c = fmax(a, b); + if (c==0 && a==b) + return signbit(a) ? b : a; + return c; +} + +static inline double +wa_fmin(double a, double b) +{ + double c = fmin(a, b); + if (c==0 && a==b) + return signbit(a) ? a : b; + return c; +} + +static inline uint32 +clz32(uint32 type) +{ + uint32 num = 0; + if (type == 0) + return 32; + while (!(type & 0x80000000)) { + num++; + type <<= 1; + } + return num; +} + +static inline uint32 +clz64(uint64 type) +{ + uint32 num = 0; + if (type == 0) + return 64; + while (!(type & 0x8000000000000000LL)) { + num++; + type <<= 1; + } + return num; +} + +static inline uint32 +ctz32(uint32 type) +{ + uint32 num = 0; + if (type == 0) + return 32; + while (!(type & 1)) { + num++; + type >>= 1; + } + return num; +} + +static inline uint32 +ctz64(uint64 type) +{ + uint32 num = 0; + if (type == 0) + return 64; + while (!(type & 1)) { + num++; + type >>= 1; + } + return num; +} + +static inline uint32 +popcount32(uint32 u) +{ + uint32 ret = 0; + while (u) { + u = (u & (u - 1)); + ret++; + } + return ret; +} + +static inline uint32 +popcount64(uint64 u) +{ + uint32 ret = 0; + while (u) { + u = (u & (u - 1)); + ret++; + } + return ret; +} + +static uint64 +read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) +{ + uint64 result = 0; + uint32 shift = 0; + uint32 bcnt = 0; + uint64 byte; + + while (true) { + byte = buf[*p_offset]; + *p_offset += 1; + result |= ((byte & 0x7f) << shift); + shift += 7; + if ((byte & 0x80) == 0) { + break; + } + bcnt += 1; + } + if (sign && (shift < maxbits) && (byte & 0x40)) { + /* Sign extend */ + result |= - ((uint64)1 << shift); + } + return result; +} + +#define read_leb_uint32(p, p_end, res) do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = _val; \ + p++; \ + break; \ + } \ + uint32 _off = 0; \ + res = (uint32)read_leb(p, &_off, 32, false); \ + p += _off; \ +} while (0) + +#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ + uint32 param_count = cur_func->param_count; \ + read_leb_uint32(frame_ip, frame_ip_end, local_idx); \ + bh_assert(local_idx < param_count + cur_func->local_count); \ + local_offset = cur_func->local_offsets[local_idx]; \ + if (local_idx < param_count) \ + local_type = cur_func->param_types[local_idx]; \ + else \ + local_type = cur_func->local_types[local_idx - param_count]; \ + } while (0) + +#define GET_OFFSET() (frame_ip += 2, *(int16 *)(frame_ip - 2)) + +#define SET_OPERAND(type, off, value) \ + (*(type*)(frame_lp + *(int16*)(frame_ip + off))) = value + +#define GET_OPERAND(type, off) (*(type*)(frame_lp + *(int16*)(frame_ip + off))) + +#define PUSH_I32(value) do { \ + *(int32*)(frame_lp + GET_OFFSET()) = value; \ + } while (0) + +#define PUSH_F32(value) do { \ + *(float32*)(frame_lp + GET_OFFSET()) = value; \ + } while (0) + +#define PUSH_I64(value) do { \ + *(int64*)(frame_lp + GET_OFFSET()) = value; \ + } while (0) + +#define PUSH_F64(value) do { \ + *(float64*)(frame_lp + GET_OFFSET()) = value; \ + } while (0) + +#define POP_I32() (*(int32*)(frame_lp + GET_OFFSET())) + +#define POP_F32() (*(float32*)(frame_lp + GET_OFFSET())) + +#define POP_I64() (*(int64*)(frame_lp + GET_OFFSET())) + +#define POP_F64() (*(float64*)(frame_lp + GET_OFFSET())) + +#define SYNC_ALL_TO_FRAME() do { \ + frame->ip = frame_ip; \ + } while (0) + +#define UPDATE_ALL_FROM_FRAME() do { \ + frame_ip = frame->ip; \ + } while (0) + +#define RECOVER_CONTEXT(new_frame) do { \ + frame = (new_frame); \ + cur_func = frame->function; \ + prev_frame = frame->prev_frame; \ + frame_ip = frame->ip; \ + frame_lp = frame->lp; \ + } while (0) + +#if WASM_ENABLE_LABELS_AS_VALUES != 0 +#define GET_OPCODE() opcode = *(frame_ip++); +#else +#define GET_OPCODE() (void)0 +#endif + +#define DEF_OP_EQZ(ctype, src_op_type) do { \ + SET_OPERAND(int32, 2, (GET_OPERAND(ctype, 0) == 0)); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_CMP(src_type, src_op_type, cond) do { \ + SET_OPERAND(uint32, 4, GET_OPERAND(src_type, 2) cond \ + GET_OPERAND(src_type, 0)); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) do { \ + SET_OPERAND(src_type, 2, \ + (src_type)operation(GET_OPERAND(src_type, 0))); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_NUMERIC(src_type1, src_type2, src_op_type, operation) do { \ + SET_OPERAND(src_type1, 4, (GET_OPERAND(src_type1, 2) \ + operation GET_OPERAND(src_type1, 0))); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_REINTERPRET(src_type) do { \ + SET_OPERAND(src_type, 2, GET_OPERAND(src_type, 0)); \ + frame_ip += 4; \ + } while (0) + +#if WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 +#define DEF_OP_NUMERIC_64 DEF_OP_NUMERIC +#else +#define DEF_OP_NUMERIC_64(src_type1, src_type2, src_op_type, operation) do { \ + src_type1 val1; \ + src_type2 val2; \ + val1 = \ + (src_type1)GET_##src_op_type##_FROM_ADDR(frame_lp + (*(int16*)(frame_ip + 2))); \ + val2 = \ + (src_type2)GET_##src_op_type##_FROM_ADDR(frame_lp + (*(int16*)(frame_ip))); \ + val1 operation##= val2; \ + PUT_##src_op_type##_TO_ADDR(frame_lp + (*(int16*)(frame_ip + 4)), val1); \ + frame_ip += 6; \ + } while (0) +#endif + +#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) do { \ + SET_OPERAND(src_type1, 4, (GET_OPERAND(src_type1, 2) \ + operation (GET_OPERAND(src_type1, 0) % 32))); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) do { \ + SET_OPERAND(src_type1, 4, (GET_OPERAND(src_type1, 2) \ + operation (GET_OPERAND(src_type1, 0) % 64))); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_MATH(src_type, src_op_type, method) do { \ + SET_OPERAND(src_type, 2, method(GET_OPERAND(src_type, 0))); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type, \ + min_cond, max_cond) do { \ + src_type value = GET_OPERAND(src_type, 0); \ + if (isnan(value)) { \ + wasm_set_exception(module, "invalid conversion to integer"); \ + goto got_exception; \ + } \ + else if (value min_cond || value max_cond) { \ + wasm_set_exception(module, "integer overflow"); \ + goto got_exception; \ + } \ + SET_OPERAND(dst_type, 2, value); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_CONVERT(dst_type, dst_op_type, \ + src_type, src_op_type) do { \ + dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ + PUSH_##dst_op_type(value); \ + } while (0) + +#define RECOVER_BR_INFO() do { \ + uint16 stack_index, ret_cell_num; \ + stack_index = *(uint16*)frame_ip; \ + frame_ip += sizeof(uint16); \ + ret_cell_num = *(uint8*)frame_ip; \ + frame_ip += sizeof(uint8); \ + if (ret_cell_num == 1) \ + frame_lp[stack_index] = \ + frame_lp[*(int16*)frame_ip]; \ + else if (ret_cell_num == 2) { \ + *(int64*)(frame_lp + stack_index) = \ + *(int64*)(frame_lp + *(int16*)frame_ip);\ + } \ + frame_ip += sizeof(int16); \ + frame_ip = *(uint8**)frame_ip; \ + } while (0) + +static inline int32 +sign_ext_8_32(int8 val) +{ + if (val & 0x80) + return (int32)val | (int32)0xffffff00; + return val; +} + +static inline int32 +sign_ext_16_32(int16 val) +{ + if (val & 0x8000) + return (int32)val | (int32)0xffff0000; + return val; +} + +static inline int64 +sign_ext_8_64(int8 val) +{ + if (val & 0x80) + return (int64)val | (int64)0xffffffffffffff00; + return val; +} + +static inline int64 +sign_ext_16_64(int16 val) +{ + if (val & 0x8000) + return (int64)val | (int64)0xffffffffffff0000; + return val; +} + +static inline int64 +sign_ext_32_64(int32 val) +{ + if (val & (int32)0x80000000) + return (int64)val | (int64)0xffffffff00000000; + return val; +} + +static inline void +word_copy(uint32 *dest, uint32 *src, unsigned num) +{ + for (; num > 0; num--) + *dest++ = *src++; +} + +static inline WASMInterpFrame* +ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) +{ + WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size); + + if (frame) + frame->prev_frame = prev_frame; + else { + wasm_set_exception((WASMModuleInstance*)exec_env->module_inst, + "WASM interp failed: stack overflow."); + } + + return frame; +} + +static inline void +FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) +{ + wasm_exec_env_free_wasm_frame(exec_env, frame); +} + +static void +wasm_interp_call_func_native(WASMModuleInstance *module_inst, + WASMExecEnv *exec_env, + WASMFunctionInstance *cur_func, + WASMInterpFrame *prev_frame) +{ + unsigned local_cell_num = 2; + WASMInterpFrame *frame; + uint32 argv_ret[2]; + bool ret; + + if (!(frame = ALLOC_FRAME(exec_env, + wasm_interp_interp_frame_size(local_cell_num), + prev_frame))) + return; + + frame->function = cur_func; + frame->ip = NULL; + frame->lp = frame->operand; + + wasm_exec_env_set_cur_frame(exec_env, frame); + + if (!cur_func->u.func_import->func_ptr_linked) { + char buf[128]; + snprintf(buf, + sizeof(buf), "fail to call unlinked import function (%s, %s)", + cur_func->u.func_import->module_name, + cur_func->u.func_import->field_name); + wasm_set_exception((WASMModuleInstance*)module_inst, buf); + return; + } + + ret = wasm_runtime_invoke_native(exec_env, cur_func->u.func_import->func_ptr_linked, + cur_func->u.func_import->func_type, + cur_func->u.func_import->signature, + frame->lp, cur_func->param_cell_num, argv_ret); + + if (!ret) + return; + + if (cur_func->ret_cell_num == 1) { + prev_frame->lp[prev_frame->ret_offset] = argv_ret[0]; + } + else if (cur_func->ret_cell_num == 2) { + *(int64*)(prev_frame->lp + prev_frame->ret_offset) = *(int64*)argv_ret; + } + + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, prev_frame); +} + +#if WASM_ENABLE_LABELS_AS_VALUES != 0 + +//#define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n");h_##opcode +#define HANDLE_OP(opcode) HANDLE_##opcode +#if WASM_ENABLE_FAST_INTERP == 0 +#define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++] +#else +#if WASM_ENABLE_ABS_LABEL_ADDR != 0 +#define FETCH_OPCODE_AND_DISPATCH() do { \ + const void *p_label_addr = *(void**)frame_ip; \ + frame_ip += sizeof(void*); \ + goto *p_label_addr; \ + } while (0) +#else +#define FETCH_OPCODE_AND_DISPATCH() do { \ + const void *p_label_addr = label_base \ + + *(int16*)frame_ip; \ + frame_ip += sizeof(int16); \ + goto *p_label_addr; \ + } while (0) +#endif +#endif +#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() + +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ + +#define HANDLE_OP(opcode) case opcode +#define HANDLE_OP_END() continue + +#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ + +#if WASM_ENABLE_FAST_INTERP != 0 +static void *global_handle_table[WASM_INSTRUCTION_NUM] = { 0 }; +#endif + +static void +wasm_interp_call_func_bytecode(WASMModuleInstance *module, + WASMExecEnv *exec_env, + WASMFunctionInstance *cur_func, + WASMInterpFrame *prev_frame) +{ + WASMMemoryInstance *memory = module->default_memory; + uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; + uint32 memory_data_size = memory ? num_bytes_per_page * memory->cur_page_count : 0; + uint32 heap_data_size = memory ? (uint32)(memory->heap_data_end - memory->heap_data) : 0; + uint8 *global_data = memory ? memory->global_data : NULL; + WASMTableInstance *table = module->default_table; + WASMGlobalInstance *globals = module->globals; + uint8 opcode_IMPDEP = WASM_OP_IMPDEP; + WASMInterpFrame *frame = NULL; + /* Points to this special opcode so as to jump to the call_method_from_entry. */ + register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */ + register uint32 *frame_lp = NULL; /* cache of frame->lp */ +#if WASM_ENABLE_ABS_LABEL_ADDR == 0 + register uint8 *label_base = &&HANDLE_WASM_OP_UNREACHABLE; /* cache of label base addr */ +#endif + WASMGlobalInstance *global; + uint8 *frame_ip_end; + uint8 opcode; + uint32 cond, count, fidx, tidx, frame_size = 0; + uint64 all_cell_num = 0; + int16 addr1, addr2, addr_ret; + int32 didx, val; + uint8 *maddr = NULL; + uint32 local_idx, local_offset, global_idx; + uint8 local_type, *global_addr; + +#if WASM_ENABLE_LABELS_AS_VALUES != 0 + #define HANDLE_OPCODE(op) &&HANDLE_##op + DEFINE_GOTO_TABLE (handle_table); + #undef HANDLE_OPCODE +#if WASM_ENABLE_FAST_INTERP != 0 + if (exec_env == NULL) { + bh_memcpy_s(global_handle_table, sizeof(void*) * WASM_INSTRUCTION_NUM, + handle_table, sizeof(void*) * WASM_INSTRUCTION_NUM); + return; + } +#endif +#endif + + /* Size of memory load. + This starts with the first memory load operator at opcode 0x28 */ + uint32 LOAD_SIZE[] = { + 4, 8, 4, 8, 1, 1, 2, 2, 1, 1, 2, 2, 4, 4, /* loads */ + 4, 8, 4, 8, 1, 2, 1, 2, 4 }; /* stores */ + +#if WASM_ENABLE_LABELS_AS_VALUES == 0 + while (frame_ip < frame_ip_end) { + opcode = *frame_ip++; + switch (opcode) { +#else + goto *handle_table[WASM_OP_IMPDEP]; +#endif + /* control instructions */ + HANDLE_OP (WASM_OP_UNREACHABLE): + wasm_set_exception(module, "unreachable"); + goto got_exception; + + HANDLE_OP (WASM_OP_IF): + cond = (uint32)POP_I32(); + + if (cond == 0) { + if (*(uint8**)frame_ip == NULL) { + frame_ip = *(uint8**)(frame_ip + sizeof(uint8*)); + } + else { + frame_ip = *(uint8**)(frame_ip); + } + } + else { + frame_ip += sizeof(uint8*) * 2; + } + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_ELSE): + frame_ip = *(uint8**)(frame_ip); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_BR): + RECOVER_BR_INFO(); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_BR_IF): + cond = frame_lp[GET_OFFSET()]; + + if (cond) + RECOVER_BR_INFO(); + else { + frame_ip += (2 + 1 + 2 + sizeof(uint8*)); + } + + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_BR_TABLE): + count = GET_OPERAND(uint32, 0); + didx = GET_OPERAND(uint32, 2); + frame_ip += 4; + + if (!(didx >= 0 && (uint32)didx < count)) + didx = count; + + frame_ip += (didx * ((2 + 1 + 2 + sizeof(uint8*)))); + RECOVER_BR_INFO(); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_RETURN): + if (cur_func->ret_cell_num == 2) { + *((uint64 *)(prev_frame->lp + prev_frame->ret_offset)) = + GET_OPERAND(uint64, 0); + } else if (cur_func->ret_cell_num == 1) { + prev_frame->lp[prev_frame->ret_offset] = GET_OPERAND(int32, 0);; + } + goto return_func; + + HANDLE_OP (WASM_OP_CALL_INDIRECT): + { + WASMType *cur_type, *cur_func_type; + + tidx = GET_OPERAND(int32, 0); + val = GET_OPERAND(int32, 2); + frame_ip += 4; + + if (tidx >= module->module->type_count) { + wasm_set_exception(module, "type index is overflow"); + goto got_exception; + } + cur_type = module->module->types[tidx]; + + if (val < 0 || val >= (int32)table->cur_size) { + wasm_set_exception(module, "undefined element"); + goto got_exception; + } + + fidx = ((uint32*)table->base_addr)[val]; + if (fidx == (uint32)-1) { + wasm_set_exception(module, "uninitialized element"); + goto got_exception; + } + + cur_func = module->functions + fidx; + + if (cur_func->is_import_func) + cur_func_type = cur_func->u.func_import->func_type; + else + cur_func_type = cur_func->u.func->func_type; + if (!wasm_type_equal(cur_type, cur_func_type)) { + wasm_set_exception(module, "indirect call type mismatch"); + goto got_exception; + } + goto call_func_from_interp; + } + + /* parametric instructions */ + HANDLE_OP (WASM_OP_SELECT): + { + cond = frame_lp[GET_OFFSET()]; + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + if (!cond) + frame_lp[addr_ret] = frame_lp[addr1]; + else + frame_lp[addr_ret] = frame_lp[addr2]; + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_SELECT_64): + { + cond = frame_lp[GET_OFFSET()]; + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + if (!cond) + *(int64*)(frame_lp + addr_ret) = *(int64*)(frame_lp + addr1); + else + *(int64*)(frame_lp + addr_ret) = *(int64*)(frame_lp + addr2); + HANDLE_OP_END (); + } + + /* variable instructions */ + HANDLE_OP (EXT_OP_SET_LOCAL_FAST): + HANDLE_OP (EXT_OP_TEE_LOCAL_FAST): + { + local_offset = *frame_ip++; + *(int32*)(frame_lp + local_offset) = GET_OPERAND(uint32, 0); + frame_ip += 2; + HANDLE_OP_END (); + } + + HANDLE_OP (EXT_OP_SET_LOCAL_FAST_I64): + HANDLE_OP (EXT_OP_TEE_LOCAL_FAST_I64): + { + local_offset = *frame_ip++; + PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), GET_OPERAND(uint64, 0)); + frame_ip += 2; + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_GET_GLOBAL): + { + global_idx = frame_lp[GET_OFFSET()]; + addr_ret = GET_OFFSET(); + + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = global_data + global->data_offset; + + switch (global->type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: + frame_lp[addr_ret] = *(uint32*)global_addr; + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + *(uint64 *)(frame_lp + addr_ret) = GET_I64_FROM_ADDR((uint32*)global_addr); + break; + default: + wasm_set_exception(module, "invalid global type"); + goto got_exception; + } + + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_SET_GLOBAL): + { + global_idx = frame_lp[GET_OFFSET()]; + addr1 = GET_OFFSET(); + + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = global_data + global->data_offset; + + switch (global->type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: + *(int32*)global_addr = frame_lp[addr1]; + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + PUT_I64_TO_ADDR((uint32*)global_addr, *(int64 *)(frame_lp + addr1)); + break; + default: + wasm_set_exception(module, "invalid global type"); + goto got_exception; + } + + HANDLE_OP_END (); + } + + /* memory load instructions */ + HANDLE_OP (WASM_OP_I32_LOAD): + { + uint32 offset, addr; + offset = GET_OPERAND(uint32, 1); + addr = GET_OPERAND(uint32, 3); + frame_ip += 5; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW_FAST(4); + frame_lp[addr_ret] = LOAD_I32(maddr); + HANDLE_OP_END (); + } + HANDLE_OP (WASM_OP_I64_LOAD): + HANDLE_OP (WASM_OP_F32_LOAD): + HANDLE_OP (WASM_OP_F64_LOAD): + HANDLE_OP (WASM_OP_I32_LOAD8_S): + HANDLE_OP (WASM_OP_I32_LOAD8_U): + HANDLE_OP (WASM_OP_I32_LOAD16_S): + HANDLE_OP (WASM_OP_I32_LOAD16_U): + HANDLE_OP (WASM_OP_I64_LOAD8_S): + HANDLE_OP (WASM_OP_I64_LOAD8_U): + HANDLE_OP (WASM_OP_I64_LOAD16_S): + HANDLE_OP (WASM_OP_I64_LOAD16_U): + HANDLE_OP (WASM_OP_I64_LOAD32_S): + HANDLE_OP (WASM_OP_I64_LOAD32_U): + { + uint32 offset, flags, addr; + GET_OPCODE(); + offset = GET_OPERAND(uint32, 0); + addr = GET_OPERAND(int32, 2); + frame_ip += 4; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(); +#if WASM_ENABLE_LABELS_AS_VALUES != 0 + static const void *handle_load_table[] = { + &&HANDLE_LOAD_WASM_OP_I32_LOAD, + &&HANDLE_LOAD_WASM_OP_I64_LOAD, + &&HANDLE_LOAD_WASM_OP_F32_LOAD, + &&HANDLE_LOAD_WASM_OP_F64_LOAD, + &&HANDLE_LOAD_WASM_OP_I32_LOAD8_S, + &&HANDLE_LOAD_WASM_OP_I32_LOAD8_U, + &&HANDLE_LOAD_WASM_OP_I32_LOAD16_S, + &&HANDLE_LOAD_WASM_OP_I32_LOAD16_U, + &&HANDLE_LOAD_WASM_OP_I64_LOAD8_S, + &&HANDLE_LOAD_WASM_OP_I64_LOAD8_U, + &&HANDLE_LOAD_WASM_OP_I64_LOAD16_S, + &&HANDLE_LOAD_WASM_OP_I64_LOAD16_U, + &&HANDLE_LOAD_WASM_OP_I64_LOAD32_S, + &&HANDLE_LOAD_WASM_OP_I64_LOAD32_U + }; + #define HANDLE_OP_LOAD(opcode) HANDLE_LOAD_##opcode + goto *handle_load_table[opcode - WASM_OP_I32_LOAD]; +#else + #define HANDLE_OP_LOAD(opcode) case opcode + switch (opcode) +#endif + { + HANDLE_OP_LOAD(WASM_OP_I32_LOAD): + frame_lp[addr_ret] = LOAD_I32(maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD): + *(int64 *)(frame_lp + addr_ret) = (LOAD_I64(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_F32_LOAD): + *(float32 *)(frame_lp + addr_ret) = (LOAD_F32(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_F64_LOAD): + *(float64 *)(frame_lp + addr_ret) = (LOAD_F64(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_S): + frame_lp[addr_ret] = sign_ext_8_32(*(int8*)maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_U): + frame_lp[addr_ret] = (uint32)(*(uint8*)maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_S): + frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_U): + frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_S): + *(int64 *)(frame_lp + addr_ret) = sign_ext_8_64(*(int8*)maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_U): + *(int64 *)(frame_lp + addr_ret) = (uint64)(*(uint8*)maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_S): + *(int64 *)(frame_lp + addr_ret) = sign_ext_16_64(LOAD_I16(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_U): + *(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U16(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_S): + *(int64 *)(frame_lp + addr_ret) = sign_ext_32_64(LOAD_I32(maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_U): + *(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U32(maddr)); + HANDLE_OP_END(); + } + (void)flags; + HANDLE_OP_END (); + } + + /* memory store instructions */ + HANDLE_OP (WASM_OP_F32_STORE): + { + uint32 offset, addr; + GET_OPCODE(); + offset = GET_OPERAND(uint32, 0); + val = GET_OPERAND(int32, 2); + addr = GET_OPERAND(int32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW_FAST(4); + STORE_U32(maddr, val); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F64_STORE): + { + uint32 offset, addr; + int32 val_offset; + GET_OPCODE(); + offset = GET_OPERAND(uint32, 0); + frame_ip += 2; + val_offset = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr = (uint32)frame_lp[addr2]; + CHECK_MEMORY_OVERFLOW_FAST(8); + STORE_U32(maddr, frame_lp[val_offset]); + STORE_U32(maddr + 4, frame_lp[val_offset + 1]); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_STORE): + { + uint32 offset, addr; + uint32 sval; + offset = GET_OPERAND(uint32, 1); + sval = GET_OPERAND(uint32, 3); + addr = GET_OPERAND(uint32, 5); + frame_ip += 7; + CHECK_MEMORY_OVERFLOW_FAST(4); + STORE_U32(maddr, sval); + HANDLE_OP_END (); + } + HANDLE_OP (WASM_OP_I32_STORE8): + HANDLE_OP (WASM_OP_I32_STORE16): + { + uint32 offset, addr; + uint32 sval; + GET_OPCODE(); + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint32, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(); + switch (opcode) { + case WASM_OP_I32_STORE8: + *(uint8*)maddr = (uint8)sval; + break; + case WASM_OP_I32_STORE16: + STORE_U16(maddr, (uint16)sval); + break; + } + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_STORE): + HANDLE_OP (WASM_OP_I64_STORE8): + HANDLE_OP (WASM_OP_I64_STORE16): + HANDLE_OP (WASM_OP_I64_STORE32): + { + uint32 offset, addr; + uint64 sval; + GET_OPCODE(); + offset = GET_OPERAND(uint32, 0); + sval = GET_OPERAND(uint64, 2); + addr = GET_OPERAND(uint32, 4); + frame_ip += 6; + CHECK_MEMORY_OVERFLOW(); + switch (opcode) { + case WASM_OP_I64_STORE: + STORE_I64(maddr, sval); + break; + case WASM_OP_I64_STORE8: + *(uint8*)maddr = (uint8)sval; + break; + case WASM_OP_I64_STORE16: + STORE_U16(maddr, (uint16)sval); + break; + case WASM_OP_I64_STORE32: + STORE_U32(maddr, (uint32)sval); + break; + } + HANDLE_OP_END (); + } + + /* memory size and memory grow instructions */ + HANDLE_OP (WASM_OP_MEMORY_SIZE): + { + uint32 reserved; + addr_ret = GET_OFFSET(); + frame_lp[addr_ret] = memory->cur_page_count; + (void)reserved; + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_MEMORY_GROW): + { + uint32 reserved, delta, prev_page_count = memory->cur_page_count; + + addr1 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + delta = (uint32)frame_lp[addr1]; + + if (!wasm_enlarge_memory(module, delta)) { + /* fail to memory.grow, return -1 */ + frame_lp[addr_ret] = -1; + if (wasm_get_exception(module)) { + bh_printf("%s\n", wasm_get_exception(module)); + wasm_set_exception(module, NULL); + } + } + else { + /* success, return previous page count */ + frame_lp[addr_ret] = prev_page_count; + /* update the memory instance ptr */ + memory = module->default_memory; + memory_data_size = num_bytes_per_page * memory->cur_page_count; + global_data = memory->global_data; + } + + (void)reserved; + HANDLE_OP_END (); + } + + /* comparison instructions of i32 */ + HANDLE_OP (WASM_OP_I32_EQZ): + DEF_OP_EQZ(int32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_EQ): + DEF_OP_CMP(uint32, I32, ==); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_NE): + DEF_OP_CMP(uint32, I32, !=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_LT_S): + DEF_OP_CMP(int32, I32, <); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_LT_U): + DEF_OP_CMP(uint32, I32, <); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_GT_S): + DEF_OP_CMP(int32, I32, >); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_GT_U): + DEF_OP_CMP(uint32, I32, >); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_LE_S): + DEF_OP_CMP(int32, I32, <=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_LE_U): + DEF_OP_CMP(uint32, I32, <=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_GE_S): + DEF_OP_CMP(int32, I32, >=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_GE_U): + DEF_OP_CMP(uint32, I32, >=); + HANDLE_OP_END (); + + /* comparison instructions of i64 */ + HANDLE_OP (WASM_OP_I64_EQZ): + DEF_OP_EQZ(int64, I64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_EQ): + DEF_OP_CMP(uint64, I64, ==); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_NE): + DEF_OP_CMP(uint64, I64, !=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_LT_S): + DEF_OP_CMP(int64, I64, <); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_LT_U): + DEF_OP_CMP(uint64, I64, <); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_GT_S): + DEF_OP_CMP(int64, I64, >); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_GT_U): + DEF_OP_CMP(uint64, I64, >); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_LE_S): + DEF_OP_CMP(int64, I64, <=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_LE_U): + DEF_OP_CMP(uint64, I64, <=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_GE_S): + DEF_OP_CMP(int64, I64, >=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_GE_U): + DEF_OP_CMP(uint64, I64, >=); + HANDLE_OP_END (); + + /* comparison instructions of f32 */ + HANDLE_OP (WASM_OP_F32_EQ): + DEF_OP_CMP(float32, F32, ==); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_NE): + DEF_OP_CMP(float32, F32, !=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_LT): + DEF_OP_CMP(float32, F32, <); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_GT): + DEF_OP_CMP(float32, F32, >); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_LE): + DEF_OP_CMP(float32, F32, <=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_GE): + DEF_OP_CMP(float32, F32, >=); + HANDLE_OP_END (); + + /* comparison instructions of f64 */ + HANDLE_OP (WASM_OP_F64_EQ): + DEF_OP_CMP(float64, F64, ==); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_NE): + DEF_OP_CMP(float64, F64, !=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_LT): + DEF_OP_CMP(float64, F64, <); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_GT): + DEF_OP_CMP(float64, F64, >); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_LE): + DEF_OP_CMP(float64, F64, <=); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_GE): + DEF_OP_CMP(float64, F64, >=); + HANDLE_OP_END (); + + /* numberic instructions of i32 */ + HANDLE_OP (WASM_OP_I32_CLZ): + DEF_OP_BIT_COUNT(uint32, I32, clz32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_CTZ): + DEF_OP_BIT_COUNT(uint32, I32, ctz32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_POPCNT): + DEF_OP_BIT_COUNT(uint32, I32, popcount32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_ADD): + DEF_OP_NUMERIC(uint32, uint32, I32, +); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_SUB): + DEF_OP_NUMERIC(uint32, uint32, I32, -); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_MUL): + DEF_OP_NUMERIC(uint32, uint32, I32, *); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_DIV_S): + { + int32 a, b; + + b = frame_lp[GET_OFFSET()]; + a = frame_lp[GET_OFFSET()]; + addr_ret = GET_OFFSET(); + if (a == (int32)0x80000000 && b == -1) { + wasm_set_exception(module, "integer overflow"); + goto got_exception; + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a / b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_DIV_U): + { + uint32 a, b; + + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + b = (uint32)frame_lp[addr1]; + a = (uint32)frame_lp[addr2]; + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a / b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_REM_S): + { + int32 a, b; + + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + b = frame_lp[addr1]; + a = frame_lp[addr2]; + if (a == (int32)0x80000000 && b == -1) { + frame_lp[addr_ret] = 0; + HANDLE_OP_END (); + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a % b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_REM_U): + { + uint32 a, b; + + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + b = (uint32)frame_lp[addr1]; + a = (uint32)frame_lp[addr2]; + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a % b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_AND): + DEF_OP_NUMERIC(uint32, uint32, I32, &); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_OR): + DEF_OP_NUMERIC(uint32, uint32, I32, |); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_XOR): + DEF_OP_NUMERIC(uint32, uint32, I32, ^); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_SHL): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) + DEF_OP_NUMERIC(uint32, uint32, I32, <<); +#else + DEF_OP_NUMERIC2(uint32, uint32, I32, <<); +#endif + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_SHR_S): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) + DEF_OP_NUMERIC(int32, uint32, I32, >>); +#else + DEF_OP_NUMERIC2(int32, uint32, I32, >>); +#endif + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_SHR_U): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) + DEF_OP_NUMERIC(uint32, uint32, I32, >>); +#else + DEF_OP_NUMERIC2(uint32, uint32, I32, >>); +#endif + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_ROTL): + { + uint32 a, b; + + b = (uint32)frame_lp[GET_OFFSET()]; + a = (uint32)frame_lp[GET_OFFSET()]; + frame_lp[GET_OFFSET()] = rotl32(a, b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_ROTR): + { + uint32 a, b; + + b = (uint32)frame_lp[GET_OFFSET()]; + a = (uint32)frame_lp[GET_OFFSET()]; + frame_lp[GET_OFFSET()] = rotr32(a, b); + HANDLE_OP_END (); + } + + /* numberic instructions of i64 */ + HANDLE_OP (WASM_OP_I64_CLZ): + DEF_OP_BIT_COUNT(uint64, I64, clz64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_CTZ): + DEF_OP_BIT_COUNT(uint64, I64, ctz64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_POPCNT): + DEF_OP_BIT_COUNT(uint64, I64, popcount64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_ADD): + DEF_OP_NUMERIC_64(uint64, uint64, I64, +); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_SUB): + DEF_OP_NUMERIC_64(uint64, uint64, I64, -); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_MUL): + DEF_OP_NUMERIC_64(uint64, uint64, I64, *); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_DIV_S): + { + int64 a, b; + + b = *(int64*)(frame_lp + GET_OFFSET()); + a = *(int64*)(frame_lp + GET_OFFSET()); + if (a == (int64)0x8000000000000000LL && b == -1) { + wasm_set_exception(module, "integer overflow"); + goto got_exception; + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + *(int64*)(frame_lp + GET_OFFSET()) = (a / b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_DIV_U): + { + uint64 a, b; + + b = *(uint64*)(frame_lp + GET_OFFSET()); + a = *(uint64*)(frame_lp + GET_OFFSET()); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + *(uint64*)(frame_lp + GET_OFFSET()) = (a / b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_REM_S): + { + int64 a, b; + + b = *(int64*)(frame_lp + GET_OFFSET()); + a = *(int64*)(frame_lp + GET_OFFSET()); + if (a == (int64)0x8000000000000000LL && b == -1) { + *(int64*)(frame_lp + GET_OFFSET()) = 0; + HANDLE_OP_END (); + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + *(int64*)(frame_lp + GET_OFFSET()) = (a % b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_REM_U): + { + uint64 a, b; + + b = *(uint64*)(frame_lp + GET_OFFSET()); + a = *(uint64*)(frame_lp + GET_OFFSET()); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + *(uint64*)(frame_lp + GET_OFFSET()) = (a % b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_AND): + DEF_OP_NUMERIC_64(uint64, uint64, I64, &); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_OR): + DEF_OP_NUMERIC_64(uint64, uint64, I64, |); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_XOR): + DEF_OP_NUMERIC_64(uint64, uint64, I64, ^); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_SHL): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) + DEF_OP_NUMERIC_64(uint64, uint64, I64, <<); +#else + DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<); +#endif + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_SHR_S): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) + DEF_OP_NUMERIC_64(int64, uint64, I64, >>); +#else + DEF_OP_NUMERIC2_64(int64, uint64, I64, >>); +#endif + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_SHR_U): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) + DEF_OP_NUMERIC_64(uint64, uint64, I64, >>); +#else + DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>); +#endif + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_ROTL): + { + uint64 a, b; + + b = *(int64*)(frame_lp + GET_OFFSET()); + a = *(int64*)(frame_lp + GET_OFFSET()); + *(int64*)(frame_lp + GET_OFFSET()) = rotl64(a, b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I64_ROTR): + { + uint64 a, b; + + b = *(uint64*)(frame_lp + GET_OFFSET()); + a = *(uint64*)(frame_lp + GET_OFFSET()); + *(uint64*)(frame_lp + GET_OFFSET()) = rotr64(a, b); + HANDLE_OP_END (); + } + + /* numberic instructions of f32 */ + HANDLE_OP (WASM_OP_F32_ABS): + DEF_OP_MATH(float32, F32, fabs); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_NEG): + { + int32 i32 = (int32)frame_lp[GET_OFFSET()]; + addr_ret = GET_OFFSET(); + int32 sign_bit = i32 & (1 << 31); + if (sign_bit) + frame_lp[addr_ret] = i32 & ~(1 << 31); + else + frame_lp[addr_ret] = (uint32)(i32 | (1 << 31)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F32_CEIL): + DEF_OP_MATH(float32, F32, ceil); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_FLOOR): + DEF_OP_MATH(float32, F32, floor); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_TRUNC): + DEF_OP_MATH(float32, F32, trunc); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_NEAREST): + DEF_OP_MATH(float32, F32, rint); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_SQRT): + DEF_OP_MATH(float32, F32, sqrt); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_ADD): + DEF_OP_NUMERIC(float32, float32, F32, +); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_SUB): + DEF_OP_NUMERIC(float32, float32, F32, -); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_MUL): + DEF_OP_NUMERIC(float32, float32, F32, *); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_DIV): + DEF_OP_NUMERIC(float32, float32, F32, /); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_MIN): + { + float32 a, b; + + b = *(float32*)(frame_lp + GET_OFFSET()); + a = *(float32*)(frame_lp + GET_OFFSET()); + + if (isnan(a)) + *(float32*)(frame_lp + GET_OFFSET()) = a; + else if (isnan(b)) + *(float32*)(frame_lp + GET_OFFSET()) = b; + else + *(float32*)(frame_lp + GET_OFFSET()) = wa_fmin(a, b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F32_MAX): + { + float32 a, b; + + b = *(float32*)(frame_lp + GET_OFFSET()); + a = *(float32*)(frame_lp + GET_OFFSET()); + + if (isnan(a)) + *(float32*)(frame_lp + GET_OFFSET()) = a; + else if (isnan(b)) + *(float32*)(frame_lp + GET_OFFSET()) = b; + else + *(float32*)(frame_lp + GET_OFFSET()) = wa_fmax(a, b); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F32_COPYSIGN): + { + float32 a, b; + + b = *(float32*)(frame_lp + GET_OFFSET()); + a = *(float32*)(frame_lp + GET_OFFSET()); + *(float32*)(frame_lp + GET_OFFSET()) = (signbit(b) ? -fabs(a) : fabs(a)); + HANDLE_OP_END (); + } + + /* numberic instructions of f64 */ + HANDLE_OP (WASM_OP_F64_ABS): + DEF_OP_MATH(float64, F64, fabs); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_NEG): + { + int64 i64 = *(int64*)(frame_lp + GET_OFFSET()); + int64 sign_bit = i64 & (((int64)1) << 63); + if (sign_bit) + *(int64*)(frame_lp + GET_OFFSET()) = (uint64)i64 & ~(((uint64)1) << 63); + else + *(int64*)(frame_lp + GET_OFFSET()) = (uint64)i64 | (((uint64)1) << 63); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F64_CEIL): + DEF_OP_MATH(float64, F64, ceil); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_FLOOR): + DEF_OP_MATH(float64, F64, floor); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_TRUNC): + DEF_OP_MATH(float64, F64, trunc); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_NEAREST): + DEF_OP_MATH(float64, F64, rint); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_SQRT): + DEF_OP_MATH(float64, F64, sqrt); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_ADD): + DEF_OP_NUMERIC_64(float64, float64, F64, +); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_SUB): + DEF_OP_NUMERIC_64(float64, float64, F64, -); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_MUL): + DEF_OP_NUMERIC_64(float64, float64, F64, *); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_DIV): + DEF_OP_NUMERIC_64(float64, float64, F64, /); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_MIN): + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + + if (isnan(a)) + PUSH_F64(a); + else if (isnan(b)) + PUSH_F64(b); + else + PUSH_F64(wa_fmin(a, b)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F64_MAX): + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + + if (isnan(a)) + PUSH_F64(a); + else if (isnan(b)) + PUSH_F64(b); + else + PUSH_F64(wa_fmax(a, b)); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_F64_COPYSIGN): + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + PUSH_F64(signbit(b) ? -fabs(a) : fabs(a)); + HANDLE_OP_END (); + } + + /* conversions of i32 */ + HANDLE_OP (WASM_OP_I32_WRAP_I64): + { + int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL); + PUSH_I32(value); + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_I32_TRUNC_S_F32): + /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX, + since float/double values of ieee754 cannot precisely represent + all int32/uint32/int64/uint64 values, e.g.: + UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f, + but not 4294967295.0f. */ + DEF_OP_TRUNC(int32, I32, float32, F32, <= -2147483904.0f, + >= 2147483648.0f); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_TRUNC_U_F32): + DEF_OP_TRUNC(uint32, I32, float32, F32, <= -1.0f, + >= 4294967296.0f); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_TRUNC_S_F64): + DEF_OP_TRUNC(int32, I32, float64, F64, <= -2147483649.0, + >= 2147483648.0); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I32_TRUNC_U_F64): + DEF_OP_TRUNC(uint32, I32, float64, F64, <= -1.0 , + >= 4294967296.0); + HANDLE_OP_END (); + + /* conversions of i64 */ + HANDLE_OP (WASM_OP_I64_EXTEND_S_I32): + DEF_OP_CONVERT(int64, I64, int32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_EXTEND_U_I32): + DEF_OP_CONVERT(int64, I64, uint32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_TRUNC_S_F32): + DEF_OP_TRUNC(int64, I64, float32, F32, <= -9223373136366403584.0f, + >= 9223372036854775808.0f); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_TRUNC_U_F32): + DEF_OP_TRUNC(uint64, I64, float32, F32, <= -1.0f, + >= 18446744073709551616.0f); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_TRUNC_S_F64): + DEF_OP_TRUNC(int64, I64, float64, F64, <= -9223372036854777856.0, + >= 9223372036854775808.0); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_I64_TRUNC_U_F64): + DEF_OP_TRUNC(uint64, I64, float64, F64, <= -1.0, + >= 18446744073709551616.0); + HANDLE_OP_END (); + + /* conversions of f32 */ + HANDLE_OP (WASM_OP_F32_CONVERT_S_I32): + DEF_OP_CONVERT(float32, F32, int32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_CONVERT_U_I32): + DEF_OP_CONVERT(float32, F32, uint32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_CONVERT_S_I64): + DEF_OP_CONVERT(float32, F32, int64, I64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_CONVERT_U_I64): + DEF_OP_CONVERT(float32, F32, uint64, I64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F32_DEMOTE_F64): + DEF_OP_CONVERT(float32, F32, float64, F64); + HANDLE_OP_END (); + + /* conversions of f64 */ + HANDLE_OP (WASM_OP_F64_CONVERT_S_I32): + DEF_OP_CONVERT(float64, F64, int32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_CONVERT_U_I32): + DEF_OP_CONVERT(float64, F64, uint32, I32); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_CONVERT_S_I64): + DEF_OP_CONVERT(float64, F64, int64, I64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_CONVERT_U_I64): + DEF_OP_CONVERT(float64, F64, uint64, I64); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_F64_PROMOTE_F32): + DEF_OP_CONVERT(float64, F64, float32, F32); + HANDLE_OP_END (); + + /* reinterpretations */ + HANDLE_OP (WASM_OP_I32_REINTERPRET_F32): + DEF_OP_REINTERPRET(float32); + HANDLE_OP_END (); + HANDLE_OP (WASM_OP_I64_REINTERPRET_F64): + DEF_OP_REINTERPRET(float64); + HANDLE_OP_END (); + HANDLE_OP (WASM_OP_F32_REINTERPRET_I32): + DEF_OP_REINTERPRET(int32); + HANDLE_OP_END (); + HANDLE_OP (WASM_OP_F64_REINTERPRET_I64): + DEF_OP_REINTERPRET(int64); + HANDLE_OP_END (); + + HANDLE_OP (EXT_OP_COPY_STACK_TOP): + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + frame_lp[addr2] = frame_lp[addr1]; + HANDLE_OP_END (); + + HANDLE_OP (EXT_OP_COPY_STACK_TOP_I64): + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + *(float64*)(frame_lp + addr2) = *(float64*)(frame_lp + addr1); + HANDLE_OP_END (); + + HANDLE_OP (WASM_OP_SET_LOCAL): + HANDLE_OP (WASM_OP_TEE_LOCAL): + { + GET_LOCAL_INDEX_TYPE_AND_OFFSET(); + + switch (local_type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: + *(int32*)(frame_lp + local_offset) = GET_OPERAND(uint32, 0); + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), GET_OPERAND(uint64, 0)); + break; + default: + wasm_set_exception(module, "invalid local type"); + goto got_exception; + } + + HANDLE_OP_END (); + } + + HANDLE_OP (WASM_OP_IMPDEP): + frame = prev_frame; + frame_ip = frame->ip; + goto call_func_from_entry; + + HANDLE_OP (WASM_OP_CALL): + fidx = frame_lp[GET_OFFSET()]; + bh_assert(fidx < module->function_count); + cur_func = module->functions + fidx; + goto call_func_from_interp; + +#if WASM_ENABLE_LABELS_AS_VALUES == 0 + default: + wasm_set_exception(module, "WASM interp failed: unsupported opcode."); + goto got_exception; + } +#endif + +#if WASM_ENABLE_LABELS_AS_VALUES != 0 + HANDLE_OP (WASM_OP_UNUSED_0x06): + HANDLE_OP (WASM_OP_UNUSED_0x07): + HANDLE_OP (WASM_OP_UNUSED_0x08): + HANDLE_OP (WASM_OP_UNUSED_0x09): + HANDLE_OP (WASM_OP_UNUSED_0x0a): + HANDLE_OP (WASM_OP_UNUSED_0x12): + HANDLE_OP (WASM_OP_UNUSED_0x13): + HANDLE_OP (WASM_OP_UNUSED_0x14): + HANDLE_OP (WASM_OP_UNUSED_0x15): + HANDLE_OP (WASM_OP_UNUSED_0x16): + HANDLE_OP (WASM_OP_UNUSED_0x17): + HANDLE_OP (WASM_OP_UNUSED_0x18): + HANDLE_OP (WASM_OP_UNUSED_0x19): + HANDLE_OP (WASM_OP_UNUSED_0x1c): + HANDLE_OP (WASM_OP_UNUSED_0x1d): + HANDLE_OP (WASM_OP_UNUSED_0x1e): + HANDLE_OP (WASM_OP_UNUSED_0x1f): + HANDLE_OP (WASM_OP_UNUSED_0x25): + HANDLE_OP (WASM_OP_UNUSED_0x26): + HANDLE_OP (WASM_OP_UNUSED_0x27): + /* optimized op code */ + HANDLE_OP (EXT_OP_GET_LOCAL_FAST): + HANDLE_OP (WASM_OP_GET_LOCAL): + HANDLE_OP (WASM_OP_F64_CONST): + HANDLE_OP (WASM_OP_I64_CONST): + HANDLE_OP (WASM_OP_F32_CONST): + HANDLE_OP (WASM_OP_I32_CONST): + HANDLE_OP (WASM_OP_DROP): + HANDLE_OP (WASM_OP_DROP_64): + HANDLE_OP (WASM_OP_BLOCK): + HANDLE_OP (WASM_OP_LOOP): + HANDLE_OP (WASM_OP_END): + HANDLE_OP (WASM_OP_NOP): + { + wasm_set_exception(module, "WASM interp failed: unsupported opcode."); + goto got_exception; + } +#endif + +#if WASM_ENABLE_LABELS_AS_VALUES == 0 + continue; +#else + FETCH_OPCODE_AND_DISPATCH (); +#endif + + call_func_from_interp: + /* Only do the copy when it's called from interpreter. */ + { + WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env); + outs_area->lp = outs_area->operand + cur_func->const_cell_num; + for (int i = 0; i < cur_func->param_count; i++) { + if (cur_func->param_types[i] == VALUE_TYPE_I64 + || cur_func->param_types[i] == VALUE_TYPE_F64) { + *(int64*)(outs_area->lp) = + GET_OPERAND(int64, (2 * (cur_func->param_count - i - 1))); + outs_area->lp += 2; + } else { + *(outs_area->lp) = GET_OPERAND(int32, (2 * (cur_func->param_count - i - 1)));; + outs_area->lp ++; + } + } + frame_ip += cur_func->param_count * sizeof(int16); + if (cur_func->ret_cell_num != 0) + frame->ret_offset = GET_OFFSET(); + SYNC_ALL_TO_FRAME(); + prev_frame = frame; + } + + call_func_from_entry: + { + if (cur_func->is_import_func) { + wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame); + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + + memory = module->default_memory; + if (wasm_get_exception(module)) + goto got_exception; + } + else { + WASMFunction *cur_wasm_func = cur_func->u.func; + + all_cell_num = (uint64)cur_func->param_cell_num + + (uint64)cur_func->local_cell_num + + (uint64)cur_func->const_cell_num + + (uint64)cur_wasm_func->max_stack_cell_num; + if (all_cell_num >= UINT32_MAX) { + wasm_set_exception(module, "WASM interp failed: stack overflow."); + goto got_exception; + } + + frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); + if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) { + frame = prev_frame; + goto got_exception; + } + + /* Initialize the interpreter context. */ + frame->function = cur_func; + frame_ip = wasm_get_func_code(cur_func); + frame_ip_end = wasm_get_func_code_end(cur_func); + + frame_lp = frame->lp = frame->operand + cur_wasm_func->const_cell_num; + + /* Initialize the consts */ + bh_memcpy_s(frame->operand, all_cell_num * 4, + cur_wasm_func->consts, cur_wasm_func->const_cell_num * 4); + + /* Initialize the local varialbes */ + memset(frame_lp + cur_func->param_cell_num, 0, + (uint32)(cur_func->local_cell_num * 4)); + + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)frame); + } + HANDLE_OP_END (); + } + + return_func: + { + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)prev_frame); + + if (!prev_frame->ip) + /* Called from native. */ + return; + + RECOVER_CONTEXT(prev_frame); + HANDLE_OP_END (); + } + + (void)frame_ip_end; + + out_of_bounds: + wasm_set_exception(module, "out of bounds memory access"); + + got_exception: + return; + +#if WASM_ENABLE_LABELS_AS_VALUES == 0 + } +#else + FETCH_OPCODE_AND_DISPATCH (); +#endif +} + +#if WASM_ENABLE_FAST_INTERP != 0 +void ** +wasm_interp_get_handle_table() +{ + WASMModuleInstance module; + memset(&module, 0, sizeof(WASMModuleInstance)); + wasm_interp_call_func_bytecode(&module, NULL, NULL, NULL); + return global_handle_table; +} +#endif + +void +wasm_interp_call_wasm(WASMModuleInstance *module_inst, + WASMExecEnv *exec_env, + WASMFunctionInstance *function, + uint32 argc, uint32 argv[]) +{ + WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env); + WASMInterpFrame *frame, *outs_area; + + /* Allocate sufficient cells for all kinds of return values. */ + unsigned all_cell_num = 2, i; + /* This frame won't be used by JITed code, so only allocate interp + frame here. */ + unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); + + if (argc != function->param_cell_num) { + char buf[128]; + snprintf(buf, sizeof(buf), + "invalid argument count %d, expected %d", + argc, function->param_cell_num); + wasm_set_exception(module_inst, buf); + return; + } + + /* TODO: check stack overflow. */ + + if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame))) + return; + + outs_area = wasm_exec_env_wasm_stack_top(exec_env); + frame->function = NULL; + frame->ip = NULL; + /* There is no local variable. */ + frame->lp = frame->operand + 0; + frame->ret_offset = 0; + + if (argc > 0) + word_copy(outs_area->operand + function->const_cell_num, argv, argc); + + wasm_exec_env_set_cur_frame(exec_env, frame); + + if (function->is_import_func) + wasm_interp_call_func_native(module_inst, exec_env, function, frame); + else + wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); + + /* Output the return value to the caller */ + if (!wasm_get_exception(module_inst)) { + for (i = 0; i < function->ret_cell_num; i++) + argv[i] = *(frame->lp + i); + } + + wasm_exec_env_set_cur_frame(exec_env, prev_frame); + FREE_FRAME(exec_env, frame); +} diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f9968c92d..b718c47b3 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -5,7 +5,6 @@ #include "wasm_loader.h" #include "bh_common.h" -#include "bh_memory.h" #include "bh_log.h" #include "wasm.h" #include "wasm_opcode.h" @@ -295,7 +294,7 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, if (node) return node->str; - if (!(node = wasm_malloc(sizeof(StringNode) + len + 1))) { + if (!(node = wasm_runtime_malloc(sizeof(StringNode) + len + 1))) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: " "allocate memory failed."); @@ -394,7 +393,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->type_count = type_count; total_size = sizeof(WASMType*) * (uint64)type_count; if (total_size >= UINT32_MAX - || !(module->types = wasm_malloc((uint32)total_size))) { + || !(module->types = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load type section failed: allocate memory failed."); return false; @@ -429,7 +428,8 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, total_size = offsetof(WASMType, types) + sizeof(uint8) * (uint64)(param_count + result_count); if (total_size >= UINT32_MAX - || !(type = module->types[i] = wasm_malloc((uint32)total_size))) { + || !(type = module->types[i] = + wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load type section failed: allocate memory failed."); return false; @@ -482,13 +482,16 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, return true; } +unsigned +wasm_runtime_memory_pool_size(); + static bool load_memory_import(const uint8 **p_buf, const uint8 *buf_end, WASMMemoryImport *memory, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; - uint32 pool_size = bh_memory_pool_size(); + uint32 pool_size = wasm_runtime_memory_pool_size(); uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; @@ -535,7 +538,7 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; - uint32 pool_size = bh_memory_pool_size(); + uint32 pool_size = wasm_runtime_memory_pool_size(); uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT / DEFAULT_NUM_BYTES_PER_PAGE; @@ -575,7 +578,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->import_count = import_count; total_size = sizeof(WASMImport) * (uint64)import_count; if (total_size >= UINT32_MAX - || !(module->imports = wasm_malloc((uint32)total_size))) { + || !(module->imports = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load import section failed: allocate memory failed."); return false; @@ -817,7 +820,7 @@ init_function_local_offsets(WASMFunction *func, uint64 total_size = sizeof(uint16) * ((uint64)param_count + local_count); if (total_size >= UINT32_MAX - || !(func->local_offsets = wasm_malloc((uint32)total_size))) { + || !(func->local_offsets = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load function section failed: allocate memory failed."); return false; @@ -868,7 +871,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, module->function_count = func_count; total_size = sizeof(WASMFunction*) * (uint64)func_count; if (total_size >= UINT32_MAX - || !(module->functions = wasm_malloc((uint32)total_size))) { + || !(module->functions = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load function section failed: allocate memory failed."); return false; @@ -921,7 +924,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, total_size = sizeof(WASMFunction) + (uint64)local_count; if (total_size >= UINT32_MAX - || !(func = module->functions[i] = wasm_malloc((uint32)total_size))) { + || !(func = module->functions[i] = + wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load function section failed: " "allocate memory failed."); @@ -1006,7 +1010,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->table_count = table_count; total_size = sizeof(WASMTable) * (uint64)table_count; if (total_size >= UINT32_MAX - || !(module->tables = wasm_malloc((uint32)total_size))) { + || !(module->tables = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load table section failed: allocate memory failed."); return false; @@ -1052,7 +1056,7 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->memory_count = memory_count; total_size = sizeof(WASMMemory) * (uint64)memory_count; if (total_size >= UINT32_MAX - || !(module->memories = wasm_malloc((uint32)total_size))) { + || !(module->memories = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load memory section failed: allocate memory failed."); return false; @@ -1093,7 +1097,7 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->global_count = global_count; total_size = sizeof(WASMGlobal) * (uint64)global_count; if (total_size >= UINT32_MAX - || !(module->globals = wasm_malloc((uint32)total_size))) { + || !(module->globals = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load global section failed: " "allocate memory failed."); @@ -1148,7 +1152,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->export_count = export_count; total_size = sizeof(WASMExport) * (uint64)export_count; if (total_size >= UINT32_MAX - || !(module->exports = wasm_malloc((uint32)total_size))) { + || !(module->exports = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load export section failed: " "allocate memory failed."); @@ -1242,7 +1246,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m module->table_seg_count = table_segment_count; total_size = sizeof(WASMTableSeg) * (uint64)table_segment_count; if (total_size >= UINT32_MAX - || !(module->table_segments = wasm_malloc((uint32)total_size))) { + || !(module->table_segments = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load table segment section failed: " "allocate memory failed."); @@ -1272,7 +1276,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m total_size = sizeof(uint32) * (uint64)function_count; if (total_size >= UINT32_MAX || !(table_segment->func_indexes = (uint32 *) - wasm_malloc((uint32)total_size))) { + wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load table segment section failed: " "allocate memory failed."); @@ -1312,7 +1316,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, module->data_seg_count = data_seg_count; total_size = sizeof(WASMDataSeg*) * (uint64)data_seg_count; if (total_size >= UINT32_MAX - || !(module->data_segments = wasm_malloc((uint32)total_size))) { + || !(module->data_segments = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load data segment section failed: " "allocate memory failed."); @@ -1330,7 +1334,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, read_leb_uint32(p, p_end, data_seg_len); if (!(dataseg = module->data_segments[i] = - wasm_malloc((uint32)sizeof(WASMDataSeg)))) { + wasm_runtime_malloc((uint32)sizeof(WASMDataSeg)))) { set_error_buf(error_buf, error_buf_size, "Load data segment section failed: " "allocate memory failed."); @@ -1455,6 +1459,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, BlockAddr *block_addr_cache, char *error_buf, uint32 error_buf_size); +#if WASM_ENABLE_FAST_INTERP != 0 +void ** +wasm_interp_get_handle_table(); + +static void **handle_table; +#endif + static bool load_from_sections(WASMModule *module, WASMSection *sections, char *error_buf, uint32 error_buf_size) @@ -1551,9 +1562,13 @@ load_from_sections(WASMModule *module, WASMSection *sections, section = section->next; } +#if WASM_ENABLE_FAST_INTERP != 0 + handle_table = wasm_interp_get_handle_table(); +#endif + total_size = sizeof(BlockAddr) * (uint64)BLOCK_ADDR_CACHE_SIZE * BLOCK_ADDR_CONFLICT_SIZE; if (total_size >= UINT32_MAX - || !(block_addr_cache = wasm_malloc((uint32)total_size))) { + || !(block_addr_cache = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: allocate memory failed"); return false; @@ -1565,7 +1580,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (!wasm_loader_prepare_bytecode(module, func, block_addr_cache, error_buf, error_buf_size)) return false; } - wasm_free(block_addr_cache); + wasm_runtime_free(block_addr_cache); /* Resolve llvm auxiliary data/stack/heap info and reset memory info */ if (!module->possible_memory_grow) { @@ -1682,7 +1697,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 static void wasm_loader_free(void *ptr) { - wasm_free(ptr); + wasm_runtime_free(ptr); } #else #define wasm_loader_free wasm_free @@ -1691,7 +1706,7 @@ static void wasm_loader_free(void *ptr) static WASMModule* create_module(char *error_buf, uint32 error_buf_size) { - WASMModule *module = wasm_malloc(sizeof(WASMModule)); + WASMModule *module = wasm_runtime_malloc(sizeof(WASMModule)); if (!module) { set_error_buf(error_buf, error_buf_size, @@ -1733,7 +1748,7 @@ destroy_sections(WASMSection *section_list) WASMSection *section = section_list, *next; while (section) { next = section->next; - wasm_free(section); + wasm_runtime_free(section); section = next; } } @@ -1772,7 +1787,7 @@ create_sections(const uint8 *buf, uint32 size, read_leb_uint32(p, p_end, section_size); CHECK_BUF1(p, p_end, section_size); - if (!(section = wasm_malloc(sizeof(WASMSection)))) { + if (!(section = wasm_runtime_malloc(sizeof(WASMSection)))) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: " "allocate memory failed."); @@ -1781,7 +1796,7 @@ create_sections(const uint8 *buf, uint32 size, memset(section, 0, sizeof(WASMSection)); section->section_type = section_type; - section->section_body = p; + section->section_body = (uint8*)p; section->section_body_size = section_size; if (!*p_section_list) @@ -1863,12 +1878,10 @@ load(const uint8 *buf, uint32 size, WASMModule *module, return true; } -const uint8* wasm_file; WASMModule* wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size) { - wasm_file = buf; - WASMModule *module = wasm_malloc(sizeof(WASMModule)); + WASMModule *module = wasm_runtime_malloc(sizeof(WASMModule)); if (!module) { set_error_buf(error_buf, error_buf_size, @@ -1905,63 +1918,69 @@ wasm_loader_unload(WASMModule *module) if (module->types) { for (i = 0; i < module->type_count; i++) { if (module->types[i]) - wasm_free(module->types[i]); + wasm_runtime_free(module->types[i]); } - wasm_free(module->types); + wasm_runtime_free(module->types); } if (module->imports) - wasm_free(module->imports); + wasm_runtime_free(module->imports); if (module->functions) { for (i = 0; i < module->function_count; i++) { if (module->functions[i]) { if (module->functions[i]->local_offsets) - wasm_free(module->functions[i]->local_offsets); - wasm_free(module->functions[i]); + wasm_runtime_free(module->functions[i]->local_offsets); +#if WASM_ENABLE_FAST_INTERP != 0 + if (module->functions[i]->code_compiled) + wasm_runtime_free(module->functions[i]->code_compiled); + if (module->functions[i]->consts) + wasm_runtime_free(module->functions[i]->consts); +#endif + wasm_runtime_free(module->functions[i]); } } - wasm_free(module->functions); + wasm_runtime_free(module->functions); } if (module->tables) - wasm_free(module->tables); + wasm_runtime_free(module->tables); if (module->memories) - wasm_free(module->memories); + wasm_runtime_free(module->memories); if (module->globals) - wasm_free(module->globals); + wasm_runtime_free(module->globals); if (module->exports) - wasm_free(module->exports); + wasm_runtime_free(module->exports); if (module->table_segments) { for (i = 0; i < module->table_seg_count; i++) { if (module->table_segments[i].func_indexes) - wasm_free(module->table_segments[i].func_indexes); + wasm_runtime_free(module->table_segments[i].func_indexes); } - wasm_free(module->table_segments); + wasm_runtime_free(module->table_segments); } if (module->data_segments) { for (i = 0; i < module->data_seg_count; i++) { if (module->data_segments[i]) - wasm_free(module->data_segments[i]); + wasm_runtime_free(module->data_segments[i]); } - wasm_free(module->data_segments); + wasm_runtime_free(module->data_segments); } if (module->const_str_list) { StringNode *node = module->const_str_list, *node_next; while (node) { node_next = node->next; - wasm_free(node); + wasm_runtime_free(node); node = node_next; } } - wasm_free(module); + wasm_runtime_free(module); } bool @@ -2092,9 +2111,9 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, skip_leb_uint32(p, p_end); /* localidx */ break; - case WASM_OP_GET_LOCAL_FAST: - case WASM_OP_SET_LOCAL_FAST: - case WASM_OP_TEE_LOCAL_FAST: + case EXT_OP_GET_LOCAL_FAST: + case EXT_OP_SET_LOCAL_FAST: + case EXT_OP_TEE_LOCAL_FAST: CHECK_BUF(p, p_end, 1); p++; break; @@ -2289,6 +2308,23 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, #define REF_F64_1 VALUE_TYPE_F64 #define REF_F64_2 VALUE_TYPE_F64 +#if WASM_ENABLE_FAST_INTERP != 0 + +#if WASM_DEBUG_PREPROCESSOR != 0 +#define LOG_OP(...) bh_printf(__VA_ARGS__) +#else +#define LOG_OP(...) +#endif + +#define PATCH_ELSE 0 +#define PATCH_END 1 +typedef struct BranchBlockPatch { + struct BranchBlockPatch *next; + uint8 patch_type; + uint8 *code_compiled; +} BranchBlockPatch; +#endif + typedef struct BranchBlock { uint8 block_type; uint8 return_type; @@ -2297,79 +2333,188 @@ typedef struct BranchBlock { uint8 *else_addr; uint8 *end_addr; uint32 stack_cell_num; +#if WASM_ENABLE_FAST_INTERP != 0 + uint16 dynamic_offset; + uint8 *code_compiled; + BranchBlockPatch *patch_list; +#endif } BranchBlock; +typedef struct WASMLoaderContext { + /* frame ref stack */ + uint8 *frame_ref; + uint8 *frame_ref_bottom; + uint8 *frame_ref_boundary; + uint32 frame_ref_size; + uint32 stack_cell_num; + uint32 max_stack_cell_num; + + /* frame csp stack */ + BranchBlock *frame_csp; + BranchBlock *frame_csp_bottom; + BranchBlock *frame_csp_boundary; + uint32 frame_csp_size; + uint32 csp_num; + uint32 max_csp_num; + +#if WASM_ENABLE_FAST_INTERP != 0 + /* frame offset stack */ + int16 *frame_offset; + int16 *frame_offset_bottom; + int16 *frame_offset_boundary; + uint32 frame_offset_size; + int16 dynamic_offset; + int16 start_dynamic_offset; + int16 max_dynamic_offset; + + /* const buffer */ + uint8 *const_buf; + uint16 num_const; + uint16 const_buf_size; + uint16 const_cell_num; + + /* processed code */ + uint8 *p_code_compiled; + uint8 *p_code_compiled_end; + uint32 code_compiled_size; +#endif +} WASMLoaderContext; + +typedef struct Const { + WASMValue value; + uint16 slot_index; + uint8 value_type; +} Const; + static void* -memory_realloc(void *mem_old, uint32 size_old, uint32 size_new) +memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, + char *error_buf, uint32 error_buf_size) { uint8 *mem_new; bh_assert(size_new > size_old); - if ((mem_new = wasm_malloc(size_new))) { + if ((mem_new = wasm_runtime_malloc(size_new))) { bh_memcpy_s(mem_new, size_new, mem_old, size_old); memset(mem_new + size_old, 0, size_new - size_old); - wasm_free(mem_old); + wasm_runtime_free(mem_old); + } + else { + set_error_buf(error_buf, error_buf_size, + "WASM loader prepare bytecode failed: " + "allocate memory failed."); } return mem_new; } -#define MEM_REALLOC(mem, size_old, size_new) do { \ - void *mem_new = memory_realloc(mem, size_old, size_new);\ - if (!mem_new) { \ - set_error_buf(error_buf, error_buf_size, \ - "WASM loader prepare bytecode failed: " \ - "allocate memory failed."); \ - goto fail; \ - } \ - mem = mem_new; \ +#define MEM_REALLOC(mem, size_old, size_new) do { \ + void *mem_new = memory_realloc(mem, size_old, size_new, \ + error_buf, error_buf_size); \ + if (!mem_new) \ + goto fail; \ + mem = mem_new; \ } while (0) +#define CHECK_CSP_PUSH() do { \ + if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ + MEM_REALLOC(ctx->frame_csp_bottom, ctx->frame_csp_size, \ + (uint32)(ctx->frame_csp_size \ + + 8 * sizeof(BranchBlock))); \ + ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ + ctx->frame_csp_boundary = ctx->frame_csp_bottom + \ + ctx->frame_csp_size / sizeof(BranchBlock); \ + ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \ + } \ + } while (0) + +#define CHECK_CSP_POP() do { \ + if (ctx->csp_num < 1) { \ + set_error_buf(error_buf, error_buf_size, \ + "WASM module load failed: type mismatch: " \ + "expect data but block stack was empty"); \ + goto fail; \ + } \ + } while (0) + +#if WASM_ENABLE_FAST_INTERP != 0 static bool -check_stack_push(uint8 **p_frame_ref_bottom, uint8 **p_frame_ref_boundary, - uint8 **p_frame_ref, uint32 *p_frame_ref_size, - uint32 stack_cell_num, - char *error_buf, uint32 error_buf_size) +check_offset_push(WASMLoaderContext *ctx, + char *error_buf, uint32 error_buf_size) { - if (*p_frame_ref >= *p_frame_ref_boundary) { - MEM_REALLOC(*p_frame_ref_bottom, *p_frame_ref_size, - *p_frame_ref_size + 16); - *p_frame_ref_size += 16; - *p_frame_ref_boundary = *p_frame_ref_bottom + *p_frame_ref_size; - *p_frame_ref = *p_frame_ref_bottom + stack_cell_num; + if (ctx->frame_offset >= ctx->frame_offset_boundary) { + MEM_REALLOC(ctx->frame_offset_bottom, ctx->frame_offset_size, + ctx->frame_offset_size + 16); + ctx->frame_offset_size += 16; + ctx->frame_offset_boundary = ctx->frame_offset_bottom + + ctx->frame_offset_size / sizeof(int16); + ctx->frame_offset = ctx->frame_offset_bottom + ctx->stack_cell_num; } return true; fail: return false; } -#define CHECK_STACK_PUSH() do { \ - if (!check_stack_push(&frame_ref_bottom, &frame_ref_boundary,\ - &frame_ref, &frame_ref_size, \ - stack_cell_num, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) +static void free_label_patch_list(BranchBlock *frame_csp) +{ + BranchBlockPatch *label_patch = frame_csp->patch_list; + BranchBlockPatch *next; + while (label_patch != NULL) { + next = label_patch->next; + wasm_runtime_free(label_patch); + label_patch = next; + } + frame_csp->patch_list = NULL; +} + +static void free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) +{ + BranchBlock *tmp_csp = frame_csp; + + for (uint32 i = 0; i < csp_num; i++) { + free_label_patch_list(tmp_csp); + tmp_csp ++; + } +} + +#endif static bool -check_stack_pop(uint8 type, uint8 *frame_ref, uint32 stack_cell_num, +check_stack_push(WASMLoaderContext *ctx, + char *error_buf, uint32 error_buf_size) +{ + if (ctx->frame_ref >= ctx->frame_ref_boundary) { + MEM_REALLOC(ctx->frame_ref_bottom, ctx->frame_ref_size, + ctx->frame_ref_size + 16); + ctx->frame_ref_size += 16; + ctx->frame_ref_boundary = ctx->frame_ref_bottom + ctx->frame_ref_size; + ctx->frame_ref = ctx->frame_ref_bottom + ctx->stack_cell_num; + } + return true; +fail: + return false; +} + +static bool +check_stack_pop(WASMLoaderContext *ctx, uint8 type, char *error_buf, uint32 error_buf_size, const char *type_str) { if (((type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) - && stack_cell_num < 1) + && ctx->stack_cell_num < 1) || ((type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) - && stack_cell_num < 2)) { + && ctx->stack_cell_num < 2)) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: " "type mismatch: expect data but stack was empty"); return false; } - if ((type == VALUE_TYPE_I32 && *(frame_ref - 1) != REF_I32) - || (type == VALUE_TYPE_F32 && *(frame_ref - 1) != REF_F32) + if ((type == VALUE_TYPE_I32 && *(ctx->frame_ref - 1) != REF_I32) + || (type == VALUE_TYPE_F32 && *(ctx->frame_ref - 1) != REF_F32) || (type == VALUE_TYPE_I64 - && (*(frame_ref - 2) != REF_I64_1 || *(frame_ref - 1) != REF_I64_2)) + && (*(ctx->frame_ref - 2) != REF_I64_1 + || *(ctx->frame_ref - 1) != REF_I64_2)) || (type == VALUE_TYPE_F64 - && (*(frame_ref - 2) != REF_F64_1 || *(frame_ref - 1) != REF_F64_2))) { + && (*(ctx->frame_ref - 2) != REF_F64_1 + || *(ctx->frame_ref - 1) != REF_F64_2))) { if (error_buf != NULL) snprintf(error_buf, error_buf_size, "%s%s%s", "WASM module load failed: type mismatch: expect ", @@ -2379,215 +2524,716 @@ check_stack_pop(uint8 type, uint8 *frame_ref, uint32 stack_cell_num, return true; } -#define CHECK_STACK_POP(TYPE, type) do { \ - if (!check_stack_pop(VALUE_TYPE_##TYPE, \ - frame_ref, stack_cell_num, \ - error_buf, error_buf_size, #type)) \ - goto fail; \ - } while (0) +static void wasm_loader_ctx_destroy(WASMLoaderContext *ctx) +{ + if (ctx) { + if (ctx->frame_ref_bottom) + wasm_runtime_free(ctx->frame_ref_bottom); + if (ctx->frame_csp_bottom) { +#if WASM_ENABLE_FAST_INTERP != 0 + free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num); +#endif + wasm_runtime_free(ctx->frame_csp_bottom); + } +#if WASM_ENABLE_FAST_INTERP != 0 + if (ctx->frame_offset_bottom) + wasm_runtime_free(ctx->frame_offset_bottom); + if (ctx->const_buf) + wasm_runtime_free(ctx->const_buf); +#endif + wasm_runtime_free(ctx); + } +} -#define PUSH_I32() do { \ - CHECK_STACK_PUSH(); \ - *frame_ref++ = REF_I32; \ - stack_cell_num++; \ - if (stack_cell_num > max_stack_cell_num) \ - max_stack_cell_num = stack_cell_num; \ - } while (0) +static WASMLoaderContext* +wasm_loader_ctx_init(WASMFunction *func) +{ + WASMLoaderContext *loader_ctx = + wasm_runtime_malloc(sizeof(WASMLoaderContext)); + if (!loader_ctx) + return false; + memset(loader_ctx, 0, sizeof(WASMLoaderContext)); -#define PUSH_F32() do { \ - CHECK_STACK_PUSH(); \ - *frame_ref++ = REF_F32; \ - stack_cell_num++; \ - if (stack_cell_num > max_stack_cell_num) \ - max_stack_cell_num = stack_cell_num; \ - } while (0) + loader_ctx->frame_ref_size = 32; + if (!(loader_ctx->frame_ref_bottom = loader_ctx->frame_ref = + wasm_runtime_malloc(loader_ctx->frame_ref_size))) + goto fail; + memset(loader_ctx->frame_ref_bottom, 0, loader_ctx->frame_ref_size); + loader_ctx->frame_ref_boundary = loader_ctx->frame_ref_bottom + + loader_ctx->frame_ref_size; -#define PUSH_I64() do { \ - CHECK_STACK_PUSH(); \ - *frame_ref++ = REF_I64_1; \ - stack_cell_num++; \ - CHECK_STACK_PUSH(); \ - *frame_ref++ = REF_I64_2; \ - stack_cell_num++; \ - if (stack_cell_num > max_stack_cell_num) \ - max_stack_cell_num = stack_cell_num; \ - } while (0) + loader_ctx->frame_csp_size = sizeof(BranchBlock) * 8; + if (!(loader_ctx->frame_csp_bottom = loader_ctx->frame_csp = + wasm_runtime_malloc(loader_ctx->frame_csp_size))) + goto fail; + memset(loader_ctx->frame_csp_bottom, 0, loader_ctx->frame_csp_size); + loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8; -#define PUSH_F64() do { \ - CHECK_STACK_PUSH(); \ - *frame_ref++ = REF_F64_1; \ - stack_cell_num++; \ - CHECK_STACK_PUSH(); \ - *frame_ref++ = REF_F64_2; \ - stack_cell_num++; \ - if (stack_cell_num > max_stack_cell_num) \ - max_stack_cell_num = stack_cell_num; \ - } while (0) +#if WASM_ENABLE_FAST_INTERP != 0 + loader_ctx->frame_offset_size = sizeof(int16) * 32; + if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset = + wasm_runtime_malloc(loader_ctx->frame_offset_size))) + goto fail; + memset(loader_ctx->frame_offset_bottom, 0, + loader_ctx->frame_offset_size); + loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32; -#define POP_I32() do { \ - CHECK_STACK_POP(I32, i32); \ - stack_cell_num--; \ - frame_ref--; \ - } while (0) + loader_ctx->num_const = 0; + loader_ctx->const_buf_size = sizeof(Const) * 8; + if (!(loader_ctx->const_buf = wasm_runtime_malloc(loader_ctx->const_buf_size))) + goto fail; + memset(loader_ctx->const_buf, 0, loader_ctx->const_buf_size); -#define POP_I64() do { \ - CHECK_STACK_POP(I64, i64); \ - stack_cell_num -= 2; \ - frame_ref -= 2; \ - } while (0) + loader_ctx->start_dynamic_offset = loader_ctx->dynamic_offset = + loader_ctx->max_dynamic_offset = func->param_cell_num + + func->local_cell_num; +#endif + return loader_ctx; -#define POP_F32() do { \ - CHECK_STACK_POP(F32, f32); \ - stack_cell_num--; \ - frame_ref--; \ - } while (0) - -#define POP_F64() do { \ - CHECK_STACK_POP(F64, f64); \ - stack_cell_num -= 2; \ - frame_ref -= 2; \ - } while (0) +fail: + wasm_loader_ctx_destroy(loader_ctx); + return NULL; +} static bool -push_type(uint8 type, uint8 **p_frame_ref_bottom, - uint8 **p_frame_ref_boundary, - uint8 **p_frame_ref, uint32 *p_frame_ref_size, - uint32 *p_stack_cell_num, uint32 *p_max_stack_cell_num, - char *error_buf, uint32 error_buf_size) +wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, + char *error_buf, uint32 error_buf_size) { - uint8 *frame_ref = *p_frame_ref; - uint32 frame_ref_size = *p_frame_ref_size; - uint32 max_stack_cell_num = *p_max_stack_cell_num; - uint32 stack_cell_num = *p_stack_cell_num; + if (type == VALUE_TYPE_VOID) + return true; - switch (type) { - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - if (!check_stack_push(p_frame_ref_bottom, p_frame_ref_boundary, - &frame_ref, &frame_ref_size, - stack_cell_num, - error_buf, error_buf_size)) - goto fail; - *frame_ref++ = type; - stack_cell_num++; - if (stack_cell_num > max_stack_cell_num) - max_stack_cell_num = stack_cell_num; - goto handle_i32_f32; -handle_i32_f32: - case VALUE_TYPE_I32: - case VALUE_TYPE_F32: - if (!check_stack_push(p_frame_ref_bottom, p_frame_ref_boundary, - &frame_ref, &frame_ref_size, - stack_cell_num, - error_buf, error_buf_size)) - goto fail; - *frame_ref++ = type; - stack_cell_num++; - if (stack_cell_num > max_stack_cell_num) - max_stack_cell_num = stack_cell_num; - break; - } + if (!check_stack_push(ctx, error_buf, error_buf_size)) + return false; - *p_frame_ref = frame_ref; - *p_frame_ref_size = frame_ref_size; - *p_max_stack_cell_num = max_stack_cell_num; - *p_stack_cell_num = stack_cell_num; + *ctx->frame_ref++ = type; + ctx->stack_cell_num++; + if (ctx->stack_cell_num > ctx->max_stack_cell_num) + ctx->max_stack_cell_num = ctx->stack_cell_num; + + if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) + return true; + + if (!check_stack_push(ctx, error_buf, error_buf_size)) + return false; + *ctx->frame_ref++ = type; + ctx->stack_cell_num++; + if (ctx->stack_cell_num > ctx->max_stack_cell_num) + ctx->max_stack_cell_num = ctx->stack_cell_num; + return true; +} + +static bool +wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, + char *error_buf, uint32 error_buf_size) +{ + char *type_str[] = { "f64", "f32", "i64", "i32" }; + if (type == VALUE_TYPE_VOID) + return true; + + if (!check_stack_pop(ctx, type, error_buf, error_buf_size, + type_str[type - VALUE_TYPE_F64])) + return false; + + ctx->frame_ref--; + ctx->stack_cell_num--; + + if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) + return true; + + ctx->frame_ref--; + ctx->stack_cell_num--; + return true; +} + +static bool +wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 type, + uint8 ret_type, uint8* start_addr, + char *error_buf, uint32 error_buf_size) +{ + CHECK_CSP_PUSH(); + memset(ctx->frame_csp, 0, sizeof(BranchBlock)); + ctx->frame_csp->block_type = type; + ctx->frame_csp->return_type = ret_type; + ctx->frame_csp->start_addr = start_addr; + ctx->frame_csp->stack_cell_num = ctx->stack_cell_num; +#if WASM_ENABLE_FAST_INTERP != 0 + ctx->frame_csp->dynamic_offset = ctx->dynamic_offset; + ctx->frame_csp->patch_list = NULL; +#endif + ctx->frame_csp++; + ctx->csp_num++; + if (ctx->csp_num > ctx->max_csp_num) + ctx->max_csp_num = ctx->csp_num; return true; fail: return false; } -#define PUSH_TYPE(type) do { \ - if (!push_type(type, &frame_ref_bottom, \ - &frame_ref_boundary, \ - &frame_ref, &frame_ref_size, \ - &stack_cell_num, &max_stack_cell_num, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) +static bool +wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, + char *error_buf, uint32 error_buf_size) +{ + CHECK_CSP_POP(); + ctx->frame_csp--; + ctx->csp_num--; + return true; +fail: + return false; +} static bool -pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num, - char *error_buf, uint32 error_buf_size) +wasm_loader_check_br(WASMLoaderContext *ctx, uint32 depth, + char *error_buf, uint32 error_buf_size) { - char *type_str[] = { "f64", "f32", "i64", "i32" }; - switch (type) { - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - if (!check_stack_pop(type, *p_frame_ref, *p_stack_cell_num, - error_buf, error_buf_size, - type_str[type - VALUE_TYPE_F64])) - return false; - *p_frame_ref -= 2; - *p_stack_cell_num -= 2; - break; - case VALUE_TYPE_I32: - case VALUE_TYPE_F32: - if (!check_stack_pop(type, *p_frame_ref, *p_stack_cell_num, - error_buf, error_buf_size, - type_str[type - VALUE_TYPE_F64])) - return false; - *p_frame_ref -= 1; - *p_stack_cell_num -= 1; - break; + if (ctx->csp_num < depth + 1) { + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: type mismatch: " + "unexpected end of section or function"); + return false; + } + if ((ctx->frame_csp - (depth + 1))->block_type != BLOCK_TYPE_LOOP) { + uint8 tmp_ret_type = (ctx->frame_csp - (depth + 1))->return_type; + if ((tmp_ret_type == VALUE_TYPE_I32 + && (ctx->stack_cell_num < 1 || *(ctx->frame_ref - 1) != REF_I32)) + || (tmp_ret_type == VALUE_TYPE_F32 + && (ctx->stack_cell_num < 1 || *(ctx->frame_ref - 1) != REF_F32)) + || (tmp_ret_type == VALUE_TYPE_I64 + && (ctx->stack_cell_num < 2 + || *(ctx->frame_ref - 2) != REF_I64_1 + || *(ctx->frame_ref - 1) != REF_I64_2)) + || (tmp_ret_type == VALUE_TYPE_F64 + && (ctx->stack_cell_num < 2 + || *(ctx->frame_ref - 2) != REF_F64_1 + || *(ctx->frame_ref - 1) != REF_F64_2))) { + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: type mismatch: " + "expect data but stack was empty or other type"); + return false; + } + (ctx->frame_csp - (depth + 1))->is_block_reachable = true; } return true; } -#define POP_TYPE(type) do { \ - if (!pop_type(type, &frame_ref, &stack_cell_num,\ - error_buf, error_buf_size)) \ - goto fail; \ +#if WASM_ENABLE_FAST_INTERP != 0 +static bool +wasm_loader_ctx_reinit(WASMLoaderContext *ctx) +{ + if (!(ctx->p_code_compiled = wasm_runtime_malloc(ctx->code_compiled_size))) + return false; + memset(ctx->p_code_compiled, 0, ctx->code_compiled_size); + ctx->p_code_compiled_end = ctx->p_code_compiled + + ctx->code_compiled_size; + + /* clean up frame ref */ + memset(ctx->frame_ref_bottom, 0, ctx->frame_ref_size); + ctx->frame_ref = ctx->frame_ref_bottom; + ctx->stack_cell_num = 0; + + /* clean up frame csp */ + memset(ctx->frame_csp_bottom, 0, ctx->frame_csp_size); + ctx->frame_csp = ctx->frame_csp_bottom; + ctx->csp_num = 0; + ctx->max_csp_num = 0; + + /* clean up frame offset */ + memset(ctx->frame_offset_bottom, 0, ctx->frame_offset_size); + ctx->frame_offset = ctx->frame_offset_bottom; + ctx->dynamic_offset = ctx->start_dynamic_offset; + + /* const buf is reserved */ + return true; +} + +static void +wasm_loader_emit_int16(WASMLoaderContext *ctx, int16 value) +{ + if (ctx->p_code_compiled) { + *(int16*)(ctx->p_code_compiled) = value; + ctx->p_code_compiled += sizeof(int16); + } + else + ctx->code_compiled_size += sizeof(int16); +} + +static void +wasm_loader_emit_uint8(WASMLoaderContext *ctx, uint8 value) +{ + if (ctx->p_code_compiled) { + *(ctx->p_code_compiled) = value; + ctx->p_code_compiled += sizeof(uint8); + } + else + ctx->code_compiled_size += sizeof(uint8); +} + +static void +wasm_loader_emit_ptr(WASMLoaderContext *ctx, void *value) +{ + if (ctx->p_code_compiled) { + *(uint8**)(ctx->p_code_compiled) = value; + ctx->p_code_compiled += sizeof(void *); + } + else + ctx->code_compiled_size += sizeof(void *); +} + +static void +wasm_loader_emit_backspace(WASMLoaderContext *ctx, uint32 size) +{ + if (ctx->p_code_compiled) { + ctx->p_code_compiled -= size; + } + else + ctx->code_compiled_size -= size; +} + +static void +wasm_loader_emit_leb(WASMLoaderContext *ctx, uint8* start, uint8* end) +{ + if (ctx->p_code_compiled) { + bh_memcpy_s(ctx->p_code_compiled, + ctx->p_code_compiled_end - ctx->p_code_compiled, + start, end - start); + ctx->p_code_compiled += (end - start); + } + else { + ctx->code_compiled_size += (end - start); + } + +} + +static bool +add_label_patch_to_list(BranchBlock *frame_csp, + uint8 patch_type, uint8 *p_code_compiled, + char *error_buf, uint32 error_buf_size) +{ + BranchBlockPatch *patch = wasm_runtime_malloc(sizeof(BranchBlockPatch)); + if (!patch) { + set_error_buf(error_buf, error_buf_size, + "WASM loader prepare bytecode failed: " + "allocate memory failed"); + return false; + } + patch->patch_type = patch_type; + patch->code_compiled = p_code_compiled; + if (!frame_csp->patch_list) { + frame_csp->patch_list = patch; + patch->next = NULL; + } + else { + patch->next = frame_csp->patch_list; + frame_csp->patch_list = patch; + } + return true; +} + +static void +apply_label_patch(WASMLoaderContext *ctx, uint8 depth, + uint8 patch_type, uint8 *frame_ip) +{ + BranchBlock *frame_csp = ctx->frame_csp - depth; + BranchBlockPatch *node = frame_csp->patch_list; + BranchBlockPatch *node_prev = NULL, *node_next; + + if (!ctx->p_code_compiled) + return; + + while (node) { + node_next = node->next; + if (node->patch_type == patch_type) { + *((uint8**)node->code_compiled) = ctx->p_code_compiled; + if (node_prev == NULL) { + frame_csp->patch_list = node_next; + } + else { + node_prev->next = node_next; + } + wasm_runtime_free(node); + } + else { + node_prev = node; + } + node = node_next; + } +} + +#define emit_operand(ctx, offset) do { \ + wasm_loader_emit_int16(ctx, offset); \ + LOG_OP("%d\t", offset); \ } while (0) -#define CHECK_CSP_PUSH() do { \ - if (frame_csp >= frame_csp_boundary) { \ - MEM_REALLOC(frame_csp_bottom, frame_csp_size, \ - (uint32)(frame_csp_size \ - + 8 * sizeof(BranchBlock))); \ - frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ - frame_csp_boundary = frame_csp_bottom + \ - frame_csp_size / sizeof(BranchBlock); \ - frame_csp = frame_csp_bottom + csp_num; \ - } \ +#define emit_byte(ctx, byte) do { \ + wasm_loader_emit_uint8(ctx, byte); \ + LOG_OP("%d\t", byte); \ } while (0) -#define CHECK_CSP_POP() do { \ - if (csp_num < 1) { \ - set_error_buf(error_buf, error_buf_size, \ - "WASM module load failed: type mismatch: "\ - "expect data but block stack was empty"); \ - goto fail; \ - } \ +#define emit_leb() do { \ + wasm_loader_emit_leb(loader_ctx, p_org, p); \ } while (0) -#define PUSH_CSP(type, ret_type, _start_addr) do { \ - CHECK_CSP_PUSH(); \ - frame_csp->block_type = type; \ - frame_csp->is_block_reachable = false; \ - frame_csp->return_type = ret_type; \ - frame_csp->start_addr = _start_addr; \ - frame_csp->else_addr = NULL; \ - frame_csp->end_addr = NULL; \ - frame_csp->stack_cell_num = stack_cell_num; \ - frame_csp++; \ - csp_num++; \ - if (csp_num > max_csp_num) \ - max_csp_num = csp_num; \ +#define emit_const(value) do { \ + GET_CONST_OFFSET(VALUE_TYPE_I32, value); \ + emit_operand(loader_ctx, operand_offset); \ } while (0) -#define POP_CSP() do { \ - CHECK_CSP_POP(); \ - frame_csp--; \ - csp_num--; \ +static bool +wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, + char *error_buf, uint32 error_buf_size) +{ + emit_operand(ctx, frame_csp->dynamic_offset); + if (frame_csp->return_type == VALUE_TYPE_I32 + || frame_csp->return_type == VALUE_TYPE_F32) { + emit_byte(ctx, 1); + emit_operand(ctx, *(int16*)(ctx->frame_offset - 1)); + } + else if (frame_csp->return_type == VALUE_TYPE_I64 + || frame_csp->return_type == VALUE_TYPE_F64) { + emit_byte(ctx, 2); + emit_operand(ctx, *(int16*)(ctx->frame_offset - 2)); + } + else { + emit_byte(ctx, 0); + emit_operand(ctx, 0); + } + if (frame_csp->block_type == BLOCK_TYPE_LOOP) { + wasm_loader_emit_ptr(ctx, frame_csp->code_compiled); + } + else { + if (!add_label_patch_to_list(frame_csp, PATCH_END, + ctx->p_code_compiled, + error_buf, error_buf_size)) + return false; + /* label address, to be patched */ + wasm_loader_emit_ptr(ctx, NULL); + } + return true; +} + +static bool +wasm_loader_push_frame_offset(WASMLoaderContext *ctx, uint8 type, + bool disable_emit, int16 operand_offset, + char *error_buf, uint32 error_buf_size) +{ + if (type == VALUE_TYPE_VOID) + return true; + + // only check memory overflow in first traverse + if (ctx->p_code_compiled == NULL) { + if (!check_offset_push(ctx, error_buf, error_buf_size)) + return false; + } + + if (disable_emit) + *(ctx->frame_offset)++ = operand_offset; + else { + emit_operand(ctx, ctx->dynamic_offset); + *(ctx->frame_offset)++ = ctx->dynamic_offset; + ctx->dynamic_offset++; + if (ctx->dynamic_offset > ctx->max_dynamic_offset) + ctx->max_dynamic_offset = ctx->dynamic_offset; + } + + if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) + return true; + + if (ctx->p_code_compiled == NULL) { + if (!check_offset_push(ctx, error_buf, error_buf_size)) + return false; + } + + ctx->frame_offset++; + ctx->dynamic_offset++; + if (ctx->dynamic_offset > ctx->max_dynamic_offset) + ctx->max_dynamic_offset = ctx->dynamic_offset; + return true; +} + +/* The frame_offset stack should always keep the same depth with + frame_ref, so we don't check pop of frame_offset */ +static bool +wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, + char *error_buf, uint32 error_buf_size) +{ + if (type == VALUE_TYPE_VOID) + return true; + + if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) { + ctx->frame_offset -= 1; + if (*(ctx->frame_offset) > ctx->start_dynamic_offset) + ctx->dynamic_offset -= 1; + } + else { + ctx->frame_offset -= 2; + if (*(ctx->frame_offset) > ctx->start_dynamic_offset) + ctx->dynamic_offset -= 2; + } + emit_operand(ctx, *(ctx->frame_offset)); + return true; +} + +static bool +wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type, + bool disable_emit, int16 operand_offset, + char *error_buf, uint32 error_buf_size) +{ + if (!(wasm_loader_push_frame_ref(ctx, type, error_buf, error_buf_size))) + return false; + if (!(wasm_loader_push_frame_offset(ctx, type, disable_emit, operand_offset, + error_buf, error_buf_size))) + return false; + + return true; +} + +static bool +wasm_loader_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 type, + char *error_buf, uint32 error_buf_size) +{ + if (!wasm_loader_pop_frame_ref(ctx, type, error_buf, error_buf_size)) + return false; + if (!wasm_loader_pop_frame_offset(ctx, type, error_buf, error_buf_size)) + return false; + + return true; +} + + +static bool +wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, + int64 val_int, float32 val_f32, + float64 val_f64, int16 *offset, + char *error_buf, uint32 error_buf_size) +{ + int16 operand_offset = 0; + Const *c; + for (c = (Const *)ctx->const_buf; + (uint8*)c < ctx->const_buf + ctx->num_const * sizeof(Const); c ++) { + if ((type == c->value_type) + && ((type == VALUE_TYPE_I64 && (int64)val_int == c->value.i64) + || (type == VALUE_TYPE_I32 && (int32)val_int == c->value.i32) + || (type == VALUE_TYPE_F64 && (float64)val_f64 == c->value.f64) + || (type == VALUE_TYPE_F32 && (float32)val_f32 == c->value.f32))) { + operand_offset = c->slot_index; + break; + } + if (c->value_type == VALUE_TYPE_I64 + || c->value_type == VALUE_TYPE_F64) + operand_offset += 2; + else + operand_offset += 1; + } + if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) { + if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) { + MEM_REALLOC(ctx->const_buf, + ctx->const_buf_size, + ctx->const_buf_size + 4 * sizeof(Const)); + ctx->const_buf_size += 4 * sizeof(Const); + c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const)); + } + c->value_type = type; + switch (type) { + case VALUE_TYPE_F64: + c->value.f64 = (float64)val_f64; + ctx->const_cell_num += 2; + /* The const buf will be reversed, we use the second cell */ + /* of the i64/f64 const so the finnal offset is corrent */ + operand_offset ++; + break; + case VALUE_TYPE_I64: + c->value.i64 = (int64)val_int; + ctx->const_cell_num += 2; + operand_offset ++; + break; + case VALUE_TYPE_F32: + c->value.f32 = (float32)val_f32; + ctx->const_cell_num ++; + break; + case VALUE_TYPE_I32: + c->value.i32 = (int32)val_int; + ctx->const_cell_num ++; + break; + default: + break; + } + c->slot_index = operand_offset; + ctx->num_const ++; + LOG_OP("#### new const [%d]: %ld\n", + ctx->num_const, (int64)c->value.i64); + } + /* use negetive index for const */ + operand_offset = -(operand_offset + 1); + *offset = operand_offset; + return true; +fail: + return false; +} + +/* + PUSH(POP)_XXX = push(pop) frame_ref + push(pop) frame_offset + -- Mostly used for the binary / compare operation + PUSH(POP)_OFFSET_TYPE only push(pop) the frame_offset stack + -- Mostly used in block / control instructions + + The POP will always emit the offset on the top of the frame_offset stack + PUSH can be used in two ways: + 1. directly PUSH: + PUSH_XXX(); + will allocate a dynamic space and emit + 2. silent PUSH: + operand_offset = xxx; disable_emit = true; + PUSH_XXX(); + only push the frame_offset stack, no emit +*/ +#define PUSH_I32() do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \ + disable_emit, operand_offset,\ + error_buf, error_buf_size)) \ + goto fail; \ } while (0) +#define PUSH_F32() do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \ + disable_emit, operand_offset,\ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_I64() do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \ + disable_emit, operand_offset,\ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_F64() do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \ + disable_emit, operand_offset,\ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_I32() do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_F32() do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_I64() do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_F64() do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_OFFSET_TYPE(type) do { \ + if (!(wasm_loader_push_frame_offset(loader_ctx, type, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_OFFSET_TYPE(type) do { \ + if (!(wasm_loader_pop_frame_offset(loader_ctx, type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#else /* WASM_ENABLE_FAST_INTERP */ + +#define PUSH_I32() do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I32, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_F32() do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F32, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_I64() do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I64, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_F64() do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F64, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_I32() do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_F32() do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F32, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_I64() do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I64, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_F64() do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F64, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#endif /* WASM_ENABLE_FAST_INTERP */ + +#define PUSH_TYPE(type) do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_TYPE(type) do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_CSP(type, ret_type, _start_addr) do { \ + if (!wasm_loader_push_frame_csp(loader_ctx, type, ret_type, \ + _start_addr, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_CSP() do { \ + if (!wasm_loader_pop_frame_csp(loader_ctx, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + + #define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ read_leb_uint32(p, p_end, local_idx); \ if (local_idx >= param_count + local_count) { \ set_error_buf(error_buf, error_buf_size, \ "WASM module load failed: " \ - "local index out of range"); \ + "local index out of range"); \ goto fail; \ } \ local_type = local_idx < param_count \ @@ -2597,33 +3243,9 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num, } while (0) #define CHECK_BR(depth) do { \ - if (csp_num < depth + 1) { \ - set_error_buf(error_buf, error_buf_size, \ - "WASM module load failed: type mismatch: " \ - "unexpected end of section or function"); \ - goto fail; \ - } \ - if ((frame_csp - (depth + 1))->block_type != BLOCK_TYPE_LOOP) { \ - uint8 tmp_ret_type = (frame_csp - (depth + 1))->return_type; \ - if ((tmp_ret_type == VALUE_TYPE_I32 \ - && (stack_cell_num < 1 || *(frame_ref - 1) != REF_I32)) \ - || (tmp_ret_type == VALUE_TYPE_F32 \ - && (stack_cell_num < 1 || *(frame_ref - 1) != REF_F32))\ - || (tmp_ret_type == VALUE_TYPE_I64 \ - && (stack_cell_num < 2 \ - || *(frame_ref - 2) != REF_I64_1 \ - || *(frame_ref - 1) != REF_I64_2)) \ - || (tmp_ret_type == VALUE_TYPE_F64 \ - && (stack_cell_num < 2 \ - || *(frame_ref - 2) != REF_F64_1 \ - || *(frame_ref - 1) != REF_F64_2))) { \ - set_error_buf(error_buf, error_buf_size, \ - "WASM module load failed: type mismatch: " \ - "expect data but stack was empty or other type"); \ + if (!wasm_loader_check_br(loader_ctx, depth, \ + error_buf, error_buf_size)) \ goto fail; \ - } \ - (frame_csp - (depth + 1))->is_block_reachable = true; \ - } \ } while (0) static bool @@ -2640,32 +3262,146 @@ check_memory(WASMModule *module, return true; } -#define CHECK_MEMORY() do { \ - if (!check_memory(module, error_buf, error_buf_size)) \ - goto fail; \ +#define CHECK_MEMORY() do { \ + if (!check_memory(module, error_buf, error_buf_size)) \ + goto fail; \ } while (0) +#if WASM_ENABLE_FAST_INTERP != 0 +#if WASM_ENABLE_ABS_LABEL_ADDR != 0 + +#define emit_label(opcode) do { \ + wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) + +#define skip_label() do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) + +#else + +#define emit_label(opcode) do { \ + int32 offset = (int32)(handle_table[opcode] - handle_table[0]); \ + if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ + set_error_buf(error_buf, error_buf_size, \ + "WASM module load failed: " \ + "pre-compiled label offset out of range"); \ + goto fail; \ + } \ + wasm_loader_emit_int16(loader_ctx, offset); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) + +// drop local.get / const / block / loop / end +#define skip_label() do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) + +#endif /* WASM_ENABLE_ABS_LABEL_ADDR */ + +#define emit_empty_label_addr_and_frame_ip(type) do { \ + if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ + loader_ctx->p_code_compiled, \ + error_buf, error_buf_size)) \ + goto fail; \ + /* label address, to be patched */ \ + wasm_loader_emit_ptr(loader_ctx, NULL); \ + } while (0) + +#define emit_br_info(frame_csp) do { \ + if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define LAST_OP_OUTPUT_I32() (last_op >= WASM_OP_I32_EQZ \ + && last_op <= WASM_OP_I32_ROTR) \ + || (last_op == WASM_OP_I32_LOAD \ + || last_op == WASM_OP_F32_LOAD) \ + || (last_op >= WASM_OP_I32_LOAD8_S \ + && last_op <= WASM_OP_I32_LOAD16_U) \ + || (last_op >= WASM_OP_F32_ABS \ + && last_op <= WASM_OP_F32_COPYSIGN) \ + || (last_op >= WASM_OP_I32_WRAP_I64 \ + && last_op <= WASM_OP_I32_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ + && last_op <= WASM_OP_F32_DEMOTE_F64) \ + || (last_op == WASM_OP_I32_REINTERPRET_F32) \ + || (last_op == WASM_OP_F32_REINTERPRET_I32) \ + || (last_op == EXT_OP_COPY_STACK_TOP) + +#define LAST_OP_OUTPUT_I64() (last_op >= WASM_OP_I64_CLZ \ + && last_op <= WASM_OP_I64_ROTR) \ + || (last_op >= WASM_OP_F64_ABS \ + && last_op <= WASM_OP_F64_COPYSIGN) \ + || (last_op == WASM_OP_I64_LOAD \ + || last_op == WASM_OP_F64_LOAD) \ + || (last_op >= WASM_OP_I64_LOAD8_S \ + && last_op <= WASM_OP_I64_LOAD32_U) \ + || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ + && last_op <= WASM_OP_I64_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ + && last_op <= WASM_OP_F64_PROMOTE_F32) \ + || (last_op == WASM_OP_I64_REINTERPRET_F64) \ + || (last_op == WASM_OP_F64_REINTERPRET_I64) \ + || (last_op == EXT_OP_COPY_STACK_TOP_I64) + +#define GET_CONST_OFFSET(type, val) do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, \ + val, 0, 0, &operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F32_OFFSET(type, fval) do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, \ + 0, fval, 0, &operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F64_OFFSET(type, fval) do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, \ + 0, 0, fval, &operand_offset, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#endif /* WASM_ENABLE_FAST_INTERP */ + static bool wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, BlockAddr *block_addr_cache, char *error_buf, uint32 error_buf_size) { uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; - uint8 *frame_ref_bottom = NULL, *frame_ref_boundary, *frame_ref; - BranchBlock *frame_csp_bottom = NULL, *frame_csp_boundary, *frame_csp; uint32 param_count, local_count, global_count; - uint32 max_stack_cell_num = 0, max_csp_num = 0; - uint32 stack_cell_num = 0, csp_num = 0; - uint32 frame_ref_size, frame_csp_size; uint8 *param_types, ret_type, *local_types, local_type, global_type; uint16 *local_offsets, local_offset; - uint32 count, i, local_idx, global_idx, depth, u32; + uint32 count, i, local_idx, global_idx, depth, u32, align, mem_offset; uint32 cache_index, item_index; int32 i32, i32_const = 0; int64 i64; uint8 opcode, u8, block_return_type; bool return_value = false, is_i32_const = false; BlockAddr *cache_items; + WASMLoaderContext *loader_ctx; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *func_const_end, *func_const; + int16 operand_offset; + uint8 last_op = 0; + bool disable_emit; + float32 f32; + float64 f64; + + LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", + func->param_cell_num, + func->local_cell_num, + func->ret_cell_num); +#endif global_count = module->import_global_count + module->global_count; @@ -2678,50 +3414,66 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, local_types = func->local_types; local_offsets = func->local_offsets; - frame_ref_size = 32; - if (!(frame_ref_bottom = frame_ref = wasm_malloc(frame_ref_size))) { - set_error_buf(error_buf, error_buf_size, - "WASM loader prepare bytecode failed: " - "allocate memory failed"); - goto fail; - } - memset(frame_ref_bottom, 0, frame_ref_size); - frame_ref_boundary = frame_ref_bottom + frame_ref_size; - - frame_csp_size = sizeof(BranchBlock) * 8; - if (!(frame_csp_bottom = frame_csp = wasm_malloc(frame_csp_size))) { + if (!(loader_ctx = wasm_loader_ctx_init(func))) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " "allocate memory failed"); goto fail; } - memset(frame_csp_bottom, 0, frame_csp_size); - frame_csp_boundary = frame_csp_bottom + 8; +#if WASM_ENABLE_FAST_INTERP != 0 +re_scan: + if (loader_ctx->code_compiled_size > 0) { + if (!wasm_loader_ctx_reinit(loader_ctx)) { + set_error_buf(error_buf, error_buf_size, + "WASM loader prepare bytecode failed: " + "allocate memory failed"); + goto fail; + } + p = func->code; + func->code_compiled = loader_ctx->p_code_compiled; + } +#endif PUSH_CSP(BLOCK_TYPE_FUNCTION, ret_type, p); - (frame_csp - 1)->is_block_reachable = true; + (loader_ctx->frame_csp - 1)->is_block_reachable = true; while (p < p_end) { opcode = *p++; +#if WASM_ENABLE_FAST_INTERP != 0 + p_org = p; + disable_emit = false; + emit_label(opcode); +#endif switch (opcode) { case WASM_OP_UNREACHABLE: goto handle_next_reachable_block; case WASM_OP_NOP: +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); +#endif break; case WASM_OP_BLOCK: /* 0x40/0x7F/0x7E/0x7D/0x7C */ block_return_type = read_uint8(p); PUSH_CSP(BLOCK_TYPE_BLOCK, block_return_type, p); +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); +#endif break; case WASM_OP_LOOP: /* 0x40/0x7F/0x7E/0x7D/0x7C */ block_return_type = read_uint8(p); PUSH_CSP(BLOCK_TYPE_LOOP, block_return_type, p); +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + (loader_ctx->frame_csp - 1)->code_compiled = + loader_ctx->p_code_compiled; +#endif break; case WASM_OP_IF: @@ -2729,144 +3481,253 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* 0x40/0x7F/0x7E/0x7D/0x7C */ block_return_type = read_uint8(p); PUSH_CSP(BLOCK_TYPE_IF, block_return_type, p); +#if WASM_ENABLE_FAST_INTERP != 0 + emit_empty_label_addr_and_frame_ip(PATCH_ELSE); + emit_empty_label_addr_and_frame_ip(PATCH_END); +#endif if (!is_i32_const) - (frame_csp - 1)->is_block_reachable = true; + (loader_ctx->frame_csp - 1)->is_block_reachable = true; else { if (!i32_const) { - cache_index = ((uintptr_t)(frame_csp - 1)->start_addr) + cache_index = ((uintptr_t)(loader_ctx->frame_csp - 1)->start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); cache_items = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * cache_index; for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE; item_index++) { if (cache_items[item_index].start_addr == - (frame_csp - 1)->start_addr) { - (frame_csp - 1)->else_addr = cache_items[item_index].else_addr; - (frame_csp - 1)->end_addr = cache_items[item_index].end_addr; + (loader_ctx->frame_csp - 1)->start_addr) { + (loader_ctx->frame_csp - 1)->else_addr = + cache_items[item_index].else_addr; + (loader_ctx->frame_csp - 1)->end_addr = + cache_items[item_index].end_addr; break; } } - if(item_index == BLOCK_ADDR_CONFLICT_SIZE - && !wasm_loader_find_block_addr(block_addr_cache, - (frame_csp - 1)->start_addr, + if (item_index == BLOCK_ADDR_CONFLICT_SIZE + && !wasm_loader_find_block_addr(block_addr_cache, + (loader_ctx->frame_csp - 1)->start_addr, p_end, - (frame_csp - 1)->block_type, - &(frame_csp - 1)->else_addr, - &(frame_csp - 1)->end_addr, + (loader_ctx->frame_csp - 1)->block_type, + &(loader_ctx->frame_csp - 1)->else_addr, + &(loader_ctx->frame_csp - 1)->end_addr, error_buf, error_buf_size)) goto fail; - if ((frame_csp - 1)->else_addr) - p = (frame_csp - 1)->else_addr; + if ((loader_ctx->frame_csp - 1)->else_addr) + p = (loader_ctx->frame_csp - 1)->else_addr; else - p = (frame_csp - 1)->end_addr; + p = (loader_ctx->frame_csp - 1)->end_addr; + + is_i32_const = false; + continue; } } break; case WASM_OP_ELSE: - if (csp_num < 2 - || (frame_csp - 1)->block_type != BLOCK_TYPE_IF) { + if (loader_ctx->csp_num < 2 + || (loader_ctx->frame_csp - 1)->block_type != BLOCK_TYPE_IF) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " "opcode else found without matched opcode if"); goto fail; } - (frame_csp - 1)->else_addr = p - 1; - stack_cell_num = (frame_csp - 1)->stack_cell_num; - frame_ref = frame_ref_bottom + stack_cell_num; + (loader_ctx->frame_csp - 1)->else_addr = p - 1; + loader_ctx->stack_cell_num = (loader_ctx->frame_csp - 1)->stack_cell_num; + loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + + loader_ctx->stack_cell_num; +#if WASM_ENABLE_FAST_INTERP != 0 + // if the result of if branch is in local or const area, add a copy op + if ((loader_ctx->frame_csp - 1)->return_type != VALUE_TYPE_VOID) { + uint8 return_cells; + if ((loader_ctx->frame_csp - 1)->return_type == VALUE_TYPE_I32 + || (loader_ctx->frame_csp - 1)->return_type == VALUE_TYPE_F32) + return_cells = 1; + else + return_cells = 2; + if ((loader_ctx->frame_csp - 1)->dynamic_offset != + *(loader_ctx->frame_offset - return_cells)) { + skip_label(); + if (return_cells == 1) + emit_label(EXT_OP_COPY_STACK_TOP); + else + emit_label(EXT_OP_COPY_STACK_TOP_I64); + emit_operand(loader_ctx, *(loader_ctx->frame_offset - return_cells)); + emit_operand(loader_ctx, (loader_ctx->frame_csp - 1)->dynamic_offset); + *(loader_ctx->frame_offset - return_cells) = + loader_ctx->frame_csp->dynamic_offset; + emit_label(opcode); + } + } + loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + + loader_ctx->stack_cell_num; + emit_empty_label_addr_and_frame_ip(PATCH_END); + apply_label_patch(loader_ctx, 1, PATCH_ELSE, p); +#endif break; case WASM_OP_END: { POP_CSP(); - POP_TYPE(frame_csp->return_type); - PUSH_TYPE(frame_csp->return_type); + POP_TYPE(loader_ctx->frame_csp->return_type); + PUSH_TYPE(loader_ctx->frame_csp->return_type); - if (csp_num > 0) { - frame_csp->end_addr = p - 1; +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + // copy the result to the block return address + if (loader_ctx->frame_csp->return_type != VALUE_TYPE_VOID) { + uint8 return_cells; + if (loader_ctx->frame_csp->return_type == VALUE_TYPE_I32 + || loader_ctx->frame_csp->return_type == VALUE_TYPE_F32) + return_cells = 1; + else + return_cells = 2; + if (loader_ctx->frame_csp->dynamic_offset != + *(loader_ctx->frame_offset - return_cells)) { + if (return_cells == 1) + emit_label(EXT_OP_COPY_STACK_TOP); + else + emit_label(EXT_OP_COPY_STACK_TOP_I64); + emit_operand(loader_ctx, *(loader_ctx->frame_offset - return_cells)); + emit_operand(loader_ctx, loader_ctx->frame_csp->dynamic_offset); + } + // the frame_offset stack top should be the return address of the block + loader_ctx->frame_offset -= return_cells; + loader_ctx->dynamic_offset = loader_ctx->frame_csp->dynamic_offset; + PUSH_OFFSET_TYPE(loader_ctx->frame_csp->return_type); + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + } + + apply_label_patch(loader_ctx, 0, PATCH_END, p); + free_label_patch_list(loader_ctx->frame_csp); + if (loader_ctx->frame_csp->block_type == BLOCK_TYPE_FUNCTION) { + emit_label(WASM_OP_RETURN); + POP_OFFSET_TYPE(loader_ctx->frame_csp->return_type); + } +#endif + if (loader_ctx->csp_num > 0) { + loader_ctx->frame_csp->end_addr = p - 1; } else { /* end of function block, function will return, ignore the following bytecodes */ p = p_end; + + is_i32_const = false; + continue; } break; } case WASM_OP_BR: { +#if WASM_ENABLE_FAST_INTERP != 0 + BranchBlock *frame_csp_tmp; +#endif read_leb_uint32(p, p_end, depth); CHECK_BR(depth); +#if WASM_ENABLE_FAST_INTERP != 0 + frame_csp_tmp = loader_ctx->frame_csp - depth - 1; + emit_br_info(frame_csp_tmp); +#endif + handle_next_reachable_block: - for (i = 1; i <= csp_num; i++) - if ((frame_csp - i)->is_block_reachable) + for (i = 1; i <= loader_ctx->csp_num; i++) + if ((loader_ctx->frame_csp - i)->is_block_reachable) break; - block_return_type = (frame_csp - i)->return_type; + block_return_type = (loader_ctx->frame_csp - i)->return_type; - cache_index = ((uintptr_t)(frame_csp - i)->start_addr) + cache_index = ((uintptr_t)(loader_ctx->frame_csp - i)->start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); cache_items = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * cache_index; for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE; item_index++) { - if (cache_items[item_index].start_addr == (frame_csp - i)->start_addr) { - (frame_csp - i)->else_addr = cache_items[item_index].else_addr; - (frame_csp - i)->end_addr = cache_items[item_index].end_addr; + if (cache_items[item_index].start_addr == (loader_ctx->frame_csp - i)->start_addr) { + (loader_ctx->frame_csp - i)->else_addr = cache_items[item_index].else_addr; + (loader_ctx->frame_csp - i)->end_addr = cache_items[item_index].end_addr; break; } } if(item_index == BLOCK_ADDR_CONFLICT_SIZE && !wasm_loader_find_block_addr(block_addr_cache, - (frame_csp - i)->start_addr, + (loader_ctx->frame_csp - i)->start_addr, p_end, - (frame_csp - i)->block_type, - &(frame_csp - i)->else_addr, - &(frame_csp - i)->end_addr, + (loader_ctx->frame_csp - i)->block_type, + &(loader_ctx->frame_csp - i)->else_addr, + &(loader_ctx->frame_csp - i)->end_addr, error_buf, error_buf_size)) goto fail; - stack_cell_num = (frame_csp - i)->stack_cell_num; - frame_ref = frame_ref_bottom + stack_cell_num; - csp_num -= i - 1; - frame_csp -= i - 1; + loader_ctx->stack_cell_num = (loader_ctx->frame_csp - i)->stack_cell_num; + loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + + loader_ctx->stack_cell_num; + loader_ctx->csp_num -= i - 1; + loader_ctx->frame_csp -= i - 1; - if ((frame_csp - 1)->block_type == BLOCK_TYPE_IF - && (frame_csp - 1)->else_addr != NULL - && p <= (frame_csp - 1)->else_addr) - p = (frame_csp - 1)->else_addr; + if ((loader_ctx->frame_csp - 1)->block_type == BLOCK_TYPE_IF + && (loader_ctx->frame_csp - 1)->else_addr != NULL + && p <= (loader_ctx->frame_csp - 1)->else_addr) + p = (loader_ctx->frame_csp - 1)->else_addr; else { - p = (frame_csp - 1)->end_addr; + p = (loader_ctx->frame_csp - 1)->end_addr; PUSH_TYPE(block_return_type); +#if WASM_ENABLE_FAST_INTERP != 0 + loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + + loader_ctx->stack_cell_num; +#endif } - break; + is_i32_const = false; + continue; } case WASM_OP_BR_IF: + { +#if WASM_ENABLE_FAST_INTERP != 0 + BranchBlock *frame_csp_tmp; +#endif read_leb_uint32(p, p_end, depth); POP_I32(); CHECK_BR(depth); +#if WASM_ENABLE_FAST_INTERP != 0 + frame_csp_tmp = loader_ctx->frame_csp - depth - 1; + emit_br_info(frame_csp_tmp); +#endif if (!is_i32_const) - (frame_csp - (depth + 1))->is_block_reachable = true; + (loader_ctx->frame_csp - (depth + 1))->is_block_reachable = true; else { if (i32_const) goto handle_next_reachable_block; } break; + } case WASM_OP_BR_TABLE: { +#if WASM_ENABLE_FAST_INTERP != 0 + BranchBlock *frame_csp_tmp; +#endif + read_leb_uint32(p, p_end, count); +#if WASM_ENABLE_FAST_INTERP != 0 + emit_const(count); +#endif POP_I32(); /* TODO: check the const */ for (i = 0; i <= count; i++) { read_leb_uint32(p, p_end, depth); CHECK_BR(depth); +#if WASM_ENABLE_FAST_INTERP != 0 + frame_csp_tmp = loader_ctx->frame_csp - depth - 1; + emit_br_info(frame_csp_tmp); +#endif } + goto handle_next_reachable_block; } @@ -2875,39 +3736,49 @@ handle_next_reachable_block: POP_TYPE(ret_type); PUSH_TYPE(ret_type); - cache_index = ((uintptr_t)(frame_csp - 1)->start_addr) + cache_index = ((uintptr_t)(loader_ctx->frame_csp - 1)->start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); cache_items = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * cache_index; for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE; item_index++) { if (cache_items[item_index].start_addr == - (frame_csp - 1)->start_addr) { - (frame_csp - 1)->else_addr = cache_items[item_index].else_addr; - (frame_csp - 1)->end_addr = cache_items[item_index].end_addr; + (loader_ctx->frame_csp - 1)->start_addr) { + (loader_ctx->frame_csp - 1)->else_addr = cache_items[item_index].else_addr; + (loader_ctx->frame_csp - 1)->end_addr = cache_items[item_index].end_addr; break; } } if(item_index == BLOCK_ADDR_CONFLICT_SIZE && !wasm_loader_find_block_addr(block_addr_cache, - (frame_csp - 1)->start_addr, + (loader_ctx->frame_csp - 1)->start_addr, p_end, - (frame_csp - 1)->block_type, - &(frame_csp - 1)->else_addr, - &(frame_csp - 1)->end_addr, + (loader_ctx->frame_csp - 1)->block_type, + &(loader_ctx->frame_csp - 1)->else_addr, + &(loader_ctx->frame_csp - 1)->end_addr, error_buf, error_buf_size)) goto fail; - stack_cell_num = (frame_csp - 1)->stack_cell_num; - frame_ref = frame_ref_bottom + stack_cell_num; - if ((frame_csp - 1)->block_type == BLOCK_TYPE_IF - && p <= (frame_csp - 1)->else_addr) { - p = (frame_csp - 1)->else_addr; + loader_ctx->stack_cell_num = (loader_ctx->frame_csp - 1)->stack_cell_num; + loader_ctx->frame_ref = loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; + + if ((loader_ctx->frame_csp - 1)->block_type == BLOCK_TYPE_IF + && p <= (loader_ctx->frame_csp - 1)->else_addr) { + p = (loader_ctx->frame_csp - 1)->else_addr; } else { - p = (frame_csp - 1)->end_addr; - PUSH_TYPE((frame_csp - 1)->return_type); + p = (loader_ctx->frame_csp - 1)->end_addr; + PUSH_TYPE((loader_ctx->frame_csp - 1)->return_type); } - break; + +#if WASM_ENABLE_FAST_INTERP != 0 + // emit the offset after return opcode + POP_OFFSET_TYPE(ret_type); + loader_ctx->frame_offset = loader_ctx->frame_offset_bottom + + loader_ctx->stack_cell_num; +#endif + + is_i32_const = false; + continue; } case WASM_OP_CALL: @@ -2917,6 +3788,10 @@ handle_next_reachable_block: int32 idx; read_leb_uint32(p, p_end, func_idx); +#if WASM_ENABLE_FAST_INTERP != 0 + // we need to emit func_idx before arguments + emit_const(func_idx); +#endif if (func_idx >= module->import_function_count + module->function_count) { set_error_buf(error_buf, error_buf_size, @@ -2932,12 +3807,20 @@ handle_next_reachable_block: module->functions[func_idx - module->import_function_count]->func_type; if (func_type->param_count > 0) { - for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) + for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { POP_TYPE(func_type->types[idx]); +#if WASM_ENABLE_FAST_INTERP != 0 + POP_OFFSET_TYPE(func_type->types[idx]); +#endif + } } - if (func_type->result_count) + if (func_type->result_count) { PUSH_TYPE(func_type->types[func_type->param_count]); +#if WASM_ENABLE_FAST_INTERP != 0 + PUSH_OFFSET_TYPE(func_type->types[func_type->param_count]); +#endif + } func->has_op_func_call = true; break; @@ -2958,6 +3841,10 @@ handle_next_reachable_block: } read_leb_uint32(p, p_end, type_idx); +#if WASM_ENABLE_FAST_INTERP != 0 + // we need to emit func_idx before arguments + emit_const(type_idx); +#endif /* reserved byte 0x00 */ if (*p++ != 0x00) { @@ -2979,12 +3866,20 @@ handle_next_reachable_block: func_type = module->types[type_idx]; if (func_type->param_count > 0) { - for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) + for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { POP_TYPE(func_type->types[idx]); +#if WASM_ENABLE_FAST_INTERP != 0 + POP_OFFSET_TYPE(func_type->types[idx]); +#endif + } } - if (func_type->result_count > 0) + if (func_type->result_count > 0) { PUSH_TYPE(func_type->types[func_type->param_count]); +#if WASM_ENABLE_FAST_INTERP != 0 + PUSH_OFFSET_TYPE(func_type->types[func_type->param_count]); +#endif + } func->has_op_func_call = true; break; @@ -2992,28 +3887,44 @@ handle_next_reachable_block: case WASM_OP_DROP: { - if (stack_cell_num <= 0) { + if (loader_ctx->stack_cell_num <= 0) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " "opcode drop was found but stack was empty"); goto fail; } - if (*(frame_ref - 1) == REF_I32 - || *(frame_ref - 1) == REF_F32) { - frame_ref--; - stack_cell_num--; + if (*(loader_ctx->frame_ref - 1) == REF_I32 + || *(loader_ctx->frame_ref - 1) == REF_F32) { + loader_ctx->frame_ref--; + loader_ctx->stack_cell_num--; +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + loader_ctx->frame_offset--; + if (*(loader_ctx->frame_offset) > + loader_ctx->start_dynamic_offset) + loader_ctx->dynamic_offset --; +#endif } else { - if (stack_cell_num <= 1) { + if (loader_ctx->stack_cell_num <= 1) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " "opcode drop was found but stack was empty"); goto fail; } - frame_ref -= 2; - stack_cell_num -= 2; + loader_ctx->frame_ref -= 2; + loader_ctx->stack_cell_num -= 2; +#if WASM_ENABLE_FAST_INTERP == 0 *(p - 1) = WASM_OP_DROP_64; +#endif +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + loader_ctx->frame_offset -= 2; + if (*(loader_ctx->frame_offset) > + loader_ctx->start_dynamic_offset) + loader_ctx->dynamic_offset -= 2; +#endif } break; } @@ -3024,40 +3935,64 @@ handle_next_reachable_block: POP_I32(); - if (stack_cell_num <= 0) { + if (loader_ctx->stack_cell_num <= 0) { set_error_buf(error_buf, error_buf_size, "WASM loader prepare bytecode failed: " "opcode select was found but stack was empty"); goto fail; } - switch (*(frame_ref - 1)) { + switch (*(loader_ctx->frame_ref - 1)) { case REF_I32: case REF_F32: break; case REF_I64_2: case REF_F64_2: +#if WASM_ENABLE_FAST_INTERP == 0 *(p - 1) = WASM_OP_SELECT_64; +#endif +#if WASM_ENABLE_FAST_INTERP != 0 + if (loader_ctx->p_code_compiled) { +#if WASM_ENABLE_ABS_LABEL_ADDR != 0 + *(void**)(loader_ctx->p_code_compiled - 10) = + handle_table[WASM_OP_SELECT_64]; +#else + *((int16*)loader_ctx->p_code_compiled - 2) = (int16) + (handle_table[WASM_OP_SELECT_64] - handle_table[0]); +#endif + } +#endif break; } - ref_type = *(frame_ref - 1); + ref_type = *(loader_ctx->frame_ref - 1); POP_TYPE(ref_type); POP_TYPE(ref_type); PUSH_TYPE(ref_type); +#if WASM_ENABLE_FAST_INTERP != 0 + POP_OFFSET_TYPE(ref_type); + POP_OFFSET_TYPE(ref_type); + PUSH_OFFSET_TYPE(ref_type); +#endif break; } case WASM_OP_GET_LOCAL: { p_org = p - 1; - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); PUSH_TYPE(local_type); +#if WASM_ENABLE_FAST_INTERP != 0 + /* Get Local is optimized out */ + skip_label(); + disable_emit = true; + operand_offset = local_offset; + PUSH_OFFSET_TYPE(local_type); +#else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { - *p_org++ = WASM_OP_GET_LOCAL_FAST; + *p_org++ = EXT_OP_GET_LOCAL_FAST; if (local_type == VALUE_TYPE_I32 || local_type == VALUE_TYPE_F32) *p_org++ = (uint8)local_offset; @@ -3066,6 +4001,7 @@ handle_next_reachable_block: while (p_org < p) *p_org++ = WASM_OP_NOP; } +#endif #endif break; } @@ -3073,13 +4009,46 @@ handle_next_reachable_block: case WASM_OP_SET_LOCAL: { p_org = p - 1; - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); POP_TYPE(local_type); +#if WASM_ENABLE_FAST_INTERP != 0 + if (local_offset < 256) { + skip_label(); + if (LAST_OP_OUTPUT_I32()) { + if (loader_ctx->p_code_compiled) + *(int16*)(loader_ctx->p_code_compiled - 2) = local_offset; + loader_ctx->frame_offset --; + loader_ctx->dynamic_offset --; + } + else if (LAST_OP_OUTPUT_I64()) { + if (loader_ctx->p_code_compiled) + *(int16*)(loader_ctx->p_code_compiled - 2) = local_offset; + loader_ctx->frame_offset -= 2; + loader_ctx->dynamic_offset -= 2; + } + else { + if (local_type == VALUE_TYPE_I32 + || local_type == VALUE_TYPE_F32) { + emit_label(EXT_OP_SET_LOCAL_FAST); + emit_byte(loader_ctx, local_offset); + } + else { + emit_label(EXT_OP_SET_LOCAL_FAST_I64); + emit_byte(loader_ctx, local_offset); + } + POP_OFFSET_TYPE(local_type); + } + } + else { /* local index larger than 255, reserve leb */ + p_org ++; + emit_leb(); + POP_OFFSET_TYPE(local_type); + } +#else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { - *p_org++ = WASM_OP_SET_LOCAL_FAST; + *p_org++ = EXT_OP_SET_LOCAL_FAST; if (local_type == VALUE_TYPE_I32 || local_type == VALUE_TYPE_F32) *p_org++ = (uint8)local_offset; @@ -3089,21 +4058,40 @@ handle_next_reachable_block: *p_org++ = WASM_OP_NOP; } #endif - +#endif break; } case WASM_OP_TEE_LOCAL: { p_org = p - 1; - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); POP_TYPE(local_type); PUSH_TYPE(local_type); +#if WASM_ENABLE_FAST_INTERP != 0 + if (local_offset < 256) { + skip_label(); + if (local_type == VALUE_TYPE_I32 + || local_type == VALUE_TYPE_F32) { + emit_label(EXT_OP_TEE_LOCAL_FAST); + emit_byte(loader_ctx, local_offset); + } + else { + emit_label(EXT_OP_TEE_LOCAL_FAST_I64); + emit_byte(loader_ctx, local_offset); + } + } + else { /* local index larger than 255, reserve leb */ + p_org ++; + emit_leb(); + } + emit_operand(loader_ctx, *(loader_ctx->frame_offset - + wasm_value_type_cell_num(local_type))); +#else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { - *p_org++ = WASM_OP_TEE_LOCAL_FAST; + *p_org++ = EXT_OP_TEE_LOCAL_FAST; if (local_type == VALUE_TYPE_I32 || local_type == VALUE_TYPE_F32) *p_org++ = (uint8)local_offset; @@ -3113,7 +4101,7 @@ handle_next_reachable_block: *p_org++ = WASM_OP_NOP; } #endif - +#endif break; } @@ -3132,6 +4120,10 @@ handle_next_reachable_block: :module->globals[global_idx - module->import_global_count].type; PUSH_TYPE(global_type); +#if WASM_ENABLE_FAST_INTERP != 0 + emit_const(global_idx); + PUSH_OFFSET_TYPE(global_type); +#endif break; } @@ -3150,21 +4142,19 @@ handle_next_reachable_block: : module->globals[global_idx - module->import_global_count].type; POP_TYPE(global_type); +#if WASM_ENABLE_FAST_INTERP != 0 + emit_const(global_idx); + POP_OFFSET_TYPE(global_type); +#endif break; } + /* load */ case WASM_OP_I32_LOAD: case WASM_OP_I32_LOAD8_S: case WASM_OP_I32_LOAD8_U: case WASM_OP_I32_LOAD16_S: case WASM_OP_I32_LOAD16_U: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_I32(); - PUSH_I32(); - break; - case WASM_OP_I64_LOAD: case WASM_OP_I64_LOAD8_S: case WASM_OP_I64_LOAD8_U: @@ -3172,65 +4162,82 @@ handle_next_reachable_block: case WASM_OP_I64_LOAD16_U: case WASM_OP_I64_LOAD32_S: case WASM_OP_I64_LOAD32_U: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_I32(); - PUSH_I64(); - break; - case WASM_OP_F32_LOAD: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_I32(); - PUSH_F32(); - break; - case WASM_OP_F64_LOAD: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_I32(); - PUSH_F64(); - break; - + /* store */ case WASM_OP_I32_STORE: case WASM_OP_I32_STORE8: case WASM_OP_I32_STORE16: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_I32(); - POP_I32(); - break; - case WASM_OP_I64_STORE: case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_I64(); - POP_I32(); - break; - case WASM_OP_F32_STORE: - CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_F32(); - POP_I32(); - break; - case WASM_OP_F64_STORE: + { CHECK_MEMORY(); - read_leb_uint32(p, p_end, u32); /* align */ - read_leb_uint32(p, p_end, u32); /* offset */ - POP_F64(); - POP_I32(); + read_leb_uint32(p, p_end, align); /* align */ + read_leb_uint32(p, p_end, mem_offset); /* offset */ +#if WASM_ENABLE_FAST_INTERP != 0 + emit_byte(loader_ctx, opcode); + emit_const(mem_offset); +#endif + switch (opcode) + { + /* load */ + case WASM_OP_I32_LOAD: + case WASM_OP_I32_LOAD8_S: + case WASM_OP_I32_LOAD8_U: + case WASM_OP_I32_LOAD16_S: + case WASM_OP_I32_LOAD16_U: + POP_I32(); + PUSH_I32(); + break; + case WASM_OP_I64_LOAD: + case WASM_OP_I64_LOAD8_S: + case WASM_OP_I64_LOAD8_U: + case WASM_OP_I64_LOAD16_S: + case WASM_OP_I64_LOAD16_U: + case WASM_OP_I64_LOAD32_S: + case WASM_OP_I64_LOAD32_U: + POP_I32(); + PUSH_I64(); + break; + case WASM_OP_F32_LOAD: + POP_I32(); + PUSH_F32(); + break; + case WASM_OP_F64_LOAD: + POP_I32(); + PUSH_F64(); + break; + /* store */ + case WASM_OP_I32_STORE: + case WASM_OP_I32_STORE8: + case WASM_OP_I32_STORE16: + POP_I32(); + POP_I32(); + break; + case WASM_OP_I64_STORE: + case WASM_OP_I64_STORE8: + case WASM_OP_I64_STORE16: + case WASM_OP_I64_STORE32: + POP_I64(); + POP_I32(); + break; + case WASM_OP_F32_STORE: + POP_F32(); + POP_I32(); + break; + case WASM_OP_F64_STORE: + POP_F64(); + POP_I32(); + break; + default: + break; + } break; + } case WASM_OP_MEMORY_SIZE: CHECK_MEMORY(); @@ -3264,21 +4271,44 @@ handle_next_reachable_block: read_leb_int32(p, p_end, i32_const); /* Currently we only track simple I32_CONST opcode. */ is_i32_const = true; +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + disable_emit = true; + GET_CONST_OFFSET(VALUE_TYPE_I32, i32_const); +#endif PUSH_I32(); break; case WASM_OP_I64_CONST: read_leb_int64(p, p_end, i64); +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + disable_emit = true; + GET_CONST_OFFSET(VALUE_TYPE_I64, i64); +#endif PUSH_I64(); break; case WASM_OP_F32_CONST: p += sizeof(float32); +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + disable_emit = true; + f32 = *(float32 *)p_org; + GET_CONST_F32_OFFSET(VALUE_TYPE_F32, f32); +#endif PUSH_F32(); break; case WASM_OP_F64_CONST: p += sizeof(float64); +#if WASM_ENABLE_FAST_INTERP != 0 + skip_label(); + disable_emit = true; + /* Some MCU may require 8-byte align */ + memcpy((uint8*)&f64, p_org, sizeof(float64)); + GET_CONST_F64_OFFSET(VALUE_TYPE_F64, f64); +#endif PUSH_F64(); break; @@ -3545,24 +4575,57 @@ handle_next_reachable_block: if (opcode != WASM_OP_I32_CONST) is_i32_const = false; + +#if WASM_ENABLE_FAST_INTERP != 0 + last_op = opcode; +#endif } - if (csp_num > 0) { + if (loader_ctx->csp_num > 0) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: " "function body must end with END opcode."); goto fail; } - func->max_stack_cell_num = max_stack_cell_num; - func->max_block_num = max_csp_num; +#if WASM_ENABLE_FAST_INTERP != 0 + if (loader_ctx->p_code_compiled == NULL) + goto re_scan; + + func->const_cell_num = loader_ctx->const_cell_num; + if (!(func->consts = func_const = + wasm_runtime_malloc(func->const_cell_num * 4))) { + set_error_buf(error_buf, error_buf_size, + "WASM loader prepare bytecode failed: " + "allocate memory failed"); + goto fail; + } + memset(func->consts, 0, func->const_cell_num * 4); + func_const_end = func->consts + func->const_cell_num * 4; + // reverse the const buf + for (int i = loader_ctx->num_const - 1; i >= 0; i--) { + Const *c = (Const*)(loader_ctx->const_buf + i * sizeof(Const)); + if (c->value_type == VALUE_TYPE_F64 + || c->value_type == VALUE_TYPE_I64) { + bh_memcpy_s(func_const, func_const_end - func_const, + &c->value.f64, sizeof(int64)); + func_const += sizeof(int64); + } else { + *(uint32*)func_const = c->value.i32; + func_const += sizeof(int32); + } + } + + func->max_stack_cell_num = loader_ctx->max_dynamic_offset - + loader_ctx->start_dynamic_offset + 1; +#else + func->max_stack_cell_num = loader_ctx->max_stack_cell_num; +#endif + func->max_block_num = loader_ctx->max_csp_num; return_value = true; fail: - if (frame_ref_bottom) - wasm_free(frame_ref_bottom); - if (frame_csp_bottom) - wasm_free(frame_csp_bottom); + wasm_loader_ctx_destroy(loader_ctx); (void)u8; (void)u32; @@ -3570,5 +4633,7 @@ fail: (void)i64; (void)local_offset; (void)p_org; + (void)mem_offset; + (void)align; return return_value; } diff --git a/core/iwasm/interpreter/wasm_opcode.h b/core/iwasm/interpreter/wasm_opcode.h index e96dc7869..e99db696a 100644 --- a/core/iwasm/interpreter/wasm_opcode.h +++ b/core/iwasm/interpreter/wasm_opcode.h @@ -238,13 +238,19 @@ typedef enum WASMOpcode { WASM_OP_F64_REINTERPRET_I64 = 0xbf, /* f64.reinterpret/i64 */ /* drop/select specified types*/ - WASM_OP_DROP_64 = 0xc0, - WASM_OP_SELECT_64 = 0xc1, - WASM_OP_GET_LOCAL_FAST = 0xc2, - WASM_OP_SET_LOCAL_FAST = 0xc3, - WASM_OP_TEE_LOCAL_FAST = 0xc4, + WASM_OP_DROP_64 = 0xc0, + WASM_OP_SELECT_64 = 0xc1, - WASM_OP_IMPDEP = 0xc5 + /* extend op code */ + EXT_OP_GET_LOCAL_FAST = 0xc2, + EXT_OP_SET_LOCAL_FAST_I64 = 0xc3, + EXT_OP_SET_LOCAL_FAST = 0xc4, + EXT_OP_TEE_LOCAL_FAST = 0xc5, + EXT_OP_TEE_LOCAL_FAST_I64 = 0xc6, + EXT_OP_COPY_STACK_TOP = 0xc7, + EXT_OP_COPY_STACK_TOP_I64 = 0xc8, + + WASM_OP_IMPDEP = 0xc9 } WASMOpcode; #ifdef __cplusplus @@ -450,12 +456,16 @@ static const void *_name[WASM_INSTRUCTION_NUM] = { \ HANDLE_OPCODE (WASM_OP_I64_REINTERPRET_F64), /* 0xbd */ \ HANDLE_OPCODE (WASM_OP_F32_REINTERPRET_I32), /* 0xbe */ \ HANDLE_OPCODE (WASM_OP_F64_REINTERPRET_I64), /* 0xbf */ \ - HANDLE_OPCODE (WASM_OP_DROP_64), /* 0xc0 */ \ - HANDLE_OPCODE (WASM_OP_SELECT_64), /* 0xc1 */ \ - HANDLE_OPCODE (WASM_OP_GET_LOCAL_FAST),/* 0xc2 */ \ - HANDLE_OPCODE (WASM_OP_SET_LOCAL_FAST),/* 0xc3 */ \ - HANDLE_OPCODE (WASM_OP_TEE_LOCAL_FAST),/* 0xc4 */ \ - HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xc5 */ \ + HANDLE_OPCODE (WASM_OP_DROP_64), /* 0xc0 */ \ + HANDLE_OPCODE (WASM_OP_SELECT_64), /* 0xc1 */ \ + HANDLE_OPCODE (EXT_OP_GET_LOCAL_FAST), /* 0xc2 */ \ + HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST_I64), /* 0xc3 */ \ + HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST), /* 0xc4 */ \ + HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST), /* 0xc5 */ \ + HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST_I64), /* 0xc6 */ \ + HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP), /* 0xc7 */ \ + HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xc8 */ \ + HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xc9 */ \ } #endif /* end of _WASM_OPCODE_H */ diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 6f56cce69..cfd607f5b 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -51,10 +51,10 @@ memories_deinstantiate(WASMMemoryInstance **memories, uint32 count) if (memories[i]) { if (memories[i]->heap_handle) mem_allocator_destroy(memories[i]->heap_handle); - wasm_free(memories[i]->heap_data); - wasm_free(memories[i]); + wasm_runtime_free(memories[i]->heap_data); + wasm_runtime_free(memories[i]); } - wasm_free(memories); + wasm_runtime_free(memories); } } @@ -72,7 +72,7 @@ memory_instantiate(uint32 num_bytes_per_page, /* Allocate memory space, addr data and global data */ if (total_size >= UINT32_MAX - || !(memory = wasm_malloc((uint32)total_size))) { + || !(memory = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate memory failed: allocate memory failed."); return NULL; @@ -92,7 +92,7 @@ memory_instantiate(uint32 num_bytes_per_page, memory->end_addr = memory->global_data + global_data_size; /* Allocate heap space */ - if (!(memory->heap_data = wasm_malloc(heap_size))) { + if (!(memory->heap_data = wasm_runtime_malloc(heap_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate memory failed: allocate memory failed."); goto fail1; @@ -114,10 +114,10 @@ memory_instantiate(uint32 num_bytes_per_page, return memory; fail2: - wasm_free(memory->heap_data); + wasm_runtime_free(memory->heap_data); fail1: - wasm_free(memory); + wasm_runtime_free(memory); return NULL; } @@ -141,7 +141,7 @@ memories_instantiate(const WASMModule *module, total_size = sizeof(WASMMemoryInstance*) * (uint64)memory_count; if (total_size >= UINT32_MAX - || !(memories = wasm_malloc((uint32)total_size))) { + || !(memories = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate memory failed: " "allocate memory failed."); @@ -210,8 +210,8 @@ tables_deinstantiate(WASMTableInstance **tables, uint32 count) if (tables) { for (i = 0; i < count; i++) if (tables[i]) - wasm_free(tables[i]); - wasm_free(tables); + wasm_runtime_free(tables[i]); + wasm_runtime_free(tables); } } @@ -229,7 +229,7 @@ tables_instantiate(const WASMModule *module, WASMTableInstance **tables, *table; if (total_size >= UINT32_MAX - || !(tables = wasm_malloc((uint32)total_size))) { + || !(tables = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate table failed: " "allocate memory failed."); @@ -244,7 +244,8 @@ tables_instantiate(const WASMModule *module, total_size = offsetof(WASMTableInstance, base_addr) + sizeof(uint32) * (uint64)import->u.table.init_size; if (total_size >= UINT32_MAX - || !(table = tables[table_index++] = wasm_malloc((uint32)total_size))) { + || !(table = tables[table_index++] = + wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate table failed: " "allocate memory failed."); @@ -264,7 +265,8 @@ tables_instantiate(const WASMModule *module, total_size = offsetof(WASMTableInstance, base_addr) + sizeof(uint32) * (uint64)module->tables[i].init_size; if (total_size >= UINT32_MAX - || !(table = tables[table_index++] = wasm_malloc((uint32)total_size))) { + || !(table = tables[table_index++] = + wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate table failed: " "allocate memory failed."); @@ -290,7 +292,7 @@ static void functions_deinstantiate(WASMFunctionInstance *functions, uint32 count) { if (functions) { - wasm_free(functions); + wasm_runtime_free(functions); } } @@ -308,7 +310,7 @@ functions_instantiate(const WASMModule *module, WASMFunctionInstance *functions, *function; if (total_size >= UINT32_MAX - || !(functions = wasm_malloc((uint32)total_size))) { + || !(functions = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate function failed: " "allocate memory failed."); @@ -355,6 +357,10 @@ functions_instantiate(const WASMModule *module, function->local_offsets = function->u.func->local_offsets; +#if WASM_ENABLE_FAST_INTERP != 0 + function->const_cell_num = function->u.func->const_cell_num; +#endif + function++; } @@ -369,7 +375,7 @@ static void globals_deinstantiate(WASMGlobalInstance *globals) { if (globals) - wasm_free(globals); + wasm_runtime_free(globals); } /** @@ -388,7 +394,7 @@ globals_instantiate(const WASMModule *module, WASMGlobalInstance *globals, *global; if (total_size >= UINT32_MAX - || !(globals = wasm_malloc((uint32)total_size))) { + || !(globals = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate global failed: " "allocate memory failed."); @@ -501,7 +507,7 @@ static void export_functions_deinstantiate(WASMExportFuncInstance *functions) { if (functions) - wasm_free(functions); + wasm_runtime_free(functions); } /** @@ -519,7 +525,7 @@ export_functions_instantiate(const WASMModule *module, uint64 total_size = sizeof(WASMExportFuncInstance) * (uint64)export_func_count; if (total_size >= UINT32_MAX - || !(export_func = export_funcs = wasm_malloc((uint32)total_size))) { + || !(export_func = export_funcs = wasm_runtime_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate export function failed: " "allocate memory failed."); @@ -619,7 +625,7 @@ wasm_instantiate(WASMModule *module, return NULL; /* Allocate the memory */ - if (!(module_inst = wasm_malloc((uint32)sizeof(WASMModuleInstance)))) { + if (!(module_inst = wasm_runtime_malloc((uint32)sizeof(WASMModuleInstance)))) { set_error_buf(error_buf, error_buf_size, "Instantiate module failed: allocate memory failed."); globals_deinstantiate(globals); @@ -846,7 +852,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst) globals_deinstantiate(module_inst->globals); export_functions_deinstantiate(module_inst->export_functions); - wasm_free(module_inst); + wasm_runtime_free(module_inst); } WASMFunctionInstance* @@ -1101,12 +1107,13 @@ bool wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { #if WASM_ENABLE_MEMORY_GROW != 0 - WASMMemoryInstance *memory = module->default_memory; - WASMMemoryInstance *new_memory; + WASMMemoryInstance *memory = module->default_memory, *new_memory; + uint32 old_page_count = memory->cur_page_count, total_size_old; uint32 total_page_count = inc_page_count + memory->cur_page_count; uint64 total_size = offsetof(WASMMemoryInstance, base_addr) + memory->num_bytes_per_page * (uint64)total_page_count + memory->global_data_size; + uint8 *global_data_old; if (inc_page_count <= 0) /* No need to enlarge memory */ @@ -1118,43 +1125,39 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) return false; } - if (total_size >= UINT32_MAX - || !(new_memory = wasm_malloc((uint32)total_size))) { + if (total_size >= UINT32_MAX) { wasm_set_exception(module, "fail to enlarge memory."); return false; } - new_memory->num_bytes_per_page = memory->num_bytes_per_page; + if (!(new_memory = wasm_runtime_realloc(memory, (uint32)total_size))) { + if (!(new_memory = wasm_runtime_malloc((uint32)total_size))) { + wasm_set_exception(module, "fail to enlarge memory."); + return false; + } + total_size_old = memory->end_addr - (uint8*)memory; + bh_memcpy_s((uint8*)new_memory, (uint32)total_size, + (uint8*)memory, total_size_old); + memset((uint8*)new_memory + total_size_old, + 0, (uint32)total_size - total_size_old); + wasm_runtime_free(memory); + } + new_memory->cur_page_count = total_page_count; - new_memory->max_page_count = memory->max_page_count; - new_memory->memory_data = new_memory->base_addr; - new_memory->global_data = new_memory->memory_data + - memory->num_bytes_per_page * total_page_count; - new_memory->global_data_size = memory->global_data_size; + new_memory->num_bytes_per_page * total_page_count; + new_memory->end_addr = new_memory->global_data + new_memory->global_data_size; - new_memory->end_addr = new_memory->global_data + memory->global_data_size; + global_data_old = new_memory->memory_data + + new_memory->num_bytes_per_page * old_page_count; - /* Copy memory data */ - bh_memcpy_s(new_memory->memory_data, - (uint32)(memory->global_data - memory->memory_data), - memory->memory_data, - (uint32)(memory->global_data - memory->memory_data)); /* Copy global data */ bh_memcpy_s(new_memory->global_data, new_memory->global_data_size, - memory->global_data, memory->global_data_size); - /* Init free space of new memory */ - memset(new_memory->memory_data + memory->num_bytes_per_page * memory->cur_page_count, - 0, memory->num_bytes_per_page * (total_page_count - memory->cur_page_count)); - - new_memory->heap_data = memory->heap_data; - new_memory->heap_data_end = memory->heap_data_end; - new_memory->heap_handle = memory->heap_handle; - new_memory->heap_base_offset = memory->heap_base_offset; + global_data_old, new_memory->global_data_size); + memset(global_data_old, 0, new_memory->global_data_size); module->memories[0] = module->default_memory = new_memory; - wasm_free(memory); return true; #else /* else of WASM_ENABLE_MEMORY_GROW */ wasm_set_exception(module, "unsupported operation: enlarge memory."); diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index aa025fcc6..bf172b284 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -87,6 +87,10 @@ typedef struct WASMFunctionInstance { uint16 ret_cell_num; /* cell num of local variables, 0 for import function */ uint16 local_cell_num; +#if WASM_ENABLE_FAST_INTERP != 0 + /* cell num of consts */ + uint16 const_cell_num; +#endif uint16 *local_offsets; /* parameter types */ uint8 *param_types; @@ -165,7 +169,11 @@ typedef struct WASMInterpFrame WASMRuntimeFrame; static inline uint8* wasm_get_func_code(WASMFunctionInstance *func) { +#if WASM_ENABLE_FAST_INTERP == 0 return func->is_import_func ? NULL : func->u.func->code; +#else + return func->is_import_func ? NULL : func->u.func->code_compiled; +#endif } /** @@ -178,8 +186,13 @@ wasm_get_func_code(WASMFunctionInstance *func) static inline uint8* wasm_get_func_code_end(WASMFunctionInstance *func) { +#if WASM_ENABLE_FAST_INTERP == 0 return func->is_import_func ? NULL : func->u.func->code + func->u.func->code_size; +#else + return func->is_import_func + ? NULL : func->u.func->code_compiled + func->u.func->code_compiled_size; +#endif } WASMModule * diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 724fe61c9..915788e97 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -78,12 +78,12 @@ wasi_args_get(wasm_exec_env_t exec_env, int32 *argv_offsets, char *argv_buf) total_size = sizeof(char*) * ((uint64)argc + 1); if (total_size >= UINT32_MAX - || !(argv = bh_malloc((uint32)total_size))) + || !(argv = wasm_runtime_malloc((uint32)total_size))) return (wasi_errno_t)-1; err = wasmtime_ssp_args_get(wasi_ctx->argv_environ, argv, argv_buf); if (err) { - bh_free(argv); + wasm_runtime_free(argv); return err; } @@ -91,7 +91,7 @@ wasi_args_get(wasm_exec_env_t exec_env, int32 *argv_offsets, char *argv_buf) argv_offsets[i] = addr_native_to_app(argv[i]); argv_offsets[argc] = 0; - bh_free(argv); + wasm_runtime_free(argv); return 0; } @@ -171,12 +171,12 @@ wasi_environ_get(wasm_exec_env_t exec_env, total_size = sizeof(char*) * (((uint64)environ_count + 1)); if (total_size >= UINT32_MAX - || !(environs = bh_malloc((uint32)total_size))) + || !(environs = wasm_runtime_malloc((uint32)total_size))) return (wasi_errno_t)-1; err = wasmtime_ssp_environ_get(wasi_ctx->argv_environ, environs, environ_buf); if (err) { - bh_free(environs); + wasm_runtime_free(environs); return err; } @@ -184,7 +184,7 @@ wasi_environ_get(wasm_exec_env_t exec_env, environ_offsets[i] = addr_native_to_app(environs[i]); environ_offsets[environ_count] = 0; - bh_free(environs); + wasm_runtime_free(environs); return 0; } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index cf302f834..ca85b09e1 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -47,7 +47,6 @@ #include "str.h" #include "bh_common.h" -#include "bh_memory.h" #if 0 /* TODO: -std=gnu99 causes compile error, comment them first */ // struct iovec must have the same layout as __wasi_iovec_t. @@ -278,7 +277,7 @@ static bool fd_prestats_grow( size *= 2; // Grow the file descriptor table's allocation. - struct fd_prestat *prestats = bh_malloc((uint32)(sizeof(*prestats) * size)); + struct fd_prestat *prestats = wasm_runtime_malloc((uint32)(sizeof(*prestats) * size)); if (prestats == NULL) return false; @@ -288,7 +287,7 @@ static bool fd_prestats_grow( } if (pt->prestats) - bh_free(pt->prestats); + wasm_runtime_free(pt->prestats); // Mark all new file descriptors as unused. for (size_t i = pt->size; i < size; ++i) @@ -408,7 +407,7 @@ static bool fd_table_grow( size *= 2; // Grow the file descriptor table's allocation. - struct fd_entry *entries = bh_malloc((uint32)(sizeof(*entries) * size)); + struct fd_entry *entries = wasm_runtime_malloc((uint32)(sizeof(*entries) * size)); if (entries == NULL) return false; @@ -418,7 +417,7 @@ static bool fd_table_grow( } if (ft->entries) - bh_free(ft->entries); + wasm_runtime_free(ft->entries); // Mark all new file descriptors as unused. for (size_t i = ft->size; i < size; ++i) @@ -434,7 +433,7 @@ static __wasi_errno_t fd_object_new( __wasi_filetype_t type, struct fd_object **fo ) TRYLOCKS_SHARED(0, (*fo)->refcount) { - *fo = bh_malloc(sizeof(**fo)); + *fo = wasm_runtime_malloc(sizeof(**fo)); if (*fo == NULL) return __WASI_ENOMEM; refcount_init(&(*fo)->refcount, 1); @@ -585,7 +584,7 @@ static void fd_object_release( CLOSE_NON_STD_FD(fd_number(fo)); break; } - bh_free(fo); + wasm_runtime_free(fo); } } @@ -878,7 +877,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread( size_t totalsize = 0; for (size_t i = 0; i < iovcnt; ++i) totalsize += iov[i].buf_len; - char *buf = bh_malloc(totalsize); + char *buf = wasm_runtime_malloc(totalsize); if (buf == NULL) { fd_object_release(fo); return __WASI_ENOMEM; @@ -888,7 +887,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread( ssize_t len = pread(fd_number(fo), buf, totalsize, offset); fd_object_release(fo); if (len < 0) { - bh_free(buf); + wasm_runtime_free(buf); return convert_errno(errno); } @@ -903,7 +902,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread( break; } } - bh_free(buf); + wasm_runtime_free(buf); *nread = len; return 0; } @@ -940,7 +939,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite( size_t totalsize = 0; for (size_t i = 0; i < iovcnt; ++i) totalsize += iov[i].buf_len; - char *buf = bh_malloc(totalsize); + char *buf = wasm_runtime_malloc(totalsize); if (buf == NULL) { fd_object_release(fo); return __WASI_ENOMEM; @@ -954,7 +953,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite( // Perform a single write operation. len = pwrite(fd_number(fo), buf, totalsize, offset); - bh_free(buf); + wasm_runtime_free(buf); } #endif fd_object_release(fo); @@ -1377,23 +1376,23 @@ static char *readlinkat_dup( size_t len_org = len; for (;;) { - char *newbuf = bh_malloc((uint32)len); + char *newbuf = wasm_runtime_malloc((uint32)len); if (newbuf == NULL) { if (buf) - bh_free(buf); + wasm_runtime_free(buf); return NULL; } if (buf != NULL) { bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org); - bh_free(buf); + wasm_runtime_free(buf); } buf = newbuf; ssize_t ret = readlinkat(fd, path, buf, len); if (ret < 0) { - bh_free(buf); + wasm_runtime_free(buf); return NULL; } if ((size_t)ret + 1 < len) { @@ -1444,7 +1443,7 @@ static __wasi_errno_t path_get( __wasi_errno_t error = fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting); if (error != 0) { - bh_free(path); + wasm_runtime_free(path); return error; } @@ -1585,7 +1584,7 @@ static __wasi_errno_t path_get( // when called on paths like ".", "a/..", but also if the path // had trailing slashes and the caller is not interested in the // name of the pathname component. - bh_free(paths_start[0]); + wasm_runtime_free(paths_start[0]); pa->path = "."; pa->path_start = NULL; goto success; @@ -1593,7 +1592,7 @@ static __wasi_errno_t path_get( // Finished expanding symlink. Continue processing along the // original path. - bh_free(paths_start[curpath--]); + wasm_runtime_free(paths_start[curpath--]); } continue; @@ -1601,7 +1600,7 @@ static __wasi_errno_t path_get( // Prevent infinite loops by placing an upper limit on the number of // symlink expansions. if (++expansions == 128) { - bh_free(symlink); + wasm_runtime_free(symlink); error = __WASI_ELOOP; goto fail; } @@ -1609,10 +1608,10 @@ static __wasi_errno_t path_get( if (*paths[curpath] == '\0') { // The original path already finished processing. Replace it by // this symlink entirely. - bh_free(paths_start[curpath]); + wasm_runtime_free(paths_start[curpath]); } else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) { // Too many nested symlinks. Stop processing. - bh_free(symlink); + wasm_runtime_free(symlink); error = __WASI_ELOOP; goto fail; } else { @@ -1644,7 +1643,7 @@ fail: for (size_t i = 1; i <= curfd; ++i) close(fds[i]); for (size_t i = 0; i <= curpath; ++i) - bh_free(paths_start[i]); + wasm_runtime_free(paths_start[i]); fd_object_release(fo); return error; #endif @@ -1668,7 +1667,7 @@ static __wasi_errno_t path_get_nofollow( static void path_put( struct path_access *pa ) UNLOCKS(pa->fd_object->refcount) { - bh_free(pa->path_start); + wasm_runtime_free(pa->path_start); if (fd_number(pa->fd_object) != pa->fd) close(pa->fd); fd_object_release(pa->fd_object); @@ -1770,12 +1769,12 @@ __wasi_errno_t wasmtime_ssp_path_link( rwlock_rdlock(&prestats->lock); if (!validate_path(target, prestats)) { rwlock_unlock(&prestats->lock); - bh_free(target); + wasm_runtime_free(target); return __WASI_EBADF; } rwlock_unlock(&prestats->lock); ret = symlinkat(target, new_pa.fd, new_pa.path); - bh_free(target); + wasm_runtime_free(target); } } path_put(&old_pa); @@ -2312,21 +2311,21 @@ __wasi_errno_t wasmtime_ssp_path_symlink( __wasi_errno_t error = path_get_nofollow(curfds, &pa, fd, new_path, new_path_len, __WASI_RIGHT_PATH_SYMLINK, 0, true); if (error != 0) { - bh_free(target); + wasm_runtime_free(target); return error; } rwlock_rdlock(&prestats->lock); if (!validate_path(target, prestats)) { rwlock_unlock(&prestats->lock); - bh_free(target); + wasm_runtime_free(target); return __WASI_EBADF; } rwlock_unlock(&prestats->lock); int ret = symlinkat(target, pa.fd, pa.path); path_put(&pa); - bh_free(target); + wasm_runtime_free(target); if (ret < 0) return convert_errno(errno); return 0; @@ -2479,12 +2478,12 @@ __wasi_errno_t wasmtime_ssp_poll_oneoff( // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also // the subscriptions generate by cloudlibc's poll() and select(). - struct fd_object **fos = bh_malloc((uint32)(nsubscriptions * sizeof(*fos))); + struct fd_object **fos = wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos))); if (fos == NULL) return __WASI_ENOMEM; - struct pollfd *pfds = bh_malloc((uint32)(nsubscriptions * sizeof(*pfds))); + struct pollfd *pfds = wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds))); if (pfds == NULL) { - bh_free(fos); + wasm_runtime_free(fos); return __WASI_ENOMEM; } @@ -2623,8 +2622,8 @@ __wasi_errno_t wasmtime_ssp_poll_oneoff( for (size_t i = 0; i < nsubscriptions; ++i) if (fos[i] != NULL) fd_object_release(fos[i]); - bh_free(fos); - bh_free(pfds); + wasm_runtime_free(fos); + wasm_runtime_free(pfds); return error; } @@ -2866,12 +2865,12 @@ bool argv_environ_init(struct argv_environ_values *argv_environ, total_size = sizeof(char *) * (uint64)argv_offsets_len; if (total_size >= UINT32_MAX - || !(argv_environ->argv = bh_malloc((uint32)total_size))) + || !(argv_environ->argv = wasm_runtime_malloc((uint32)total_size))) return false; if (argv_buf_len >= UINT32_MAX - || !(argv_environ->argv_buf = bh_malloc((uint32)argv_buf_len))) + || !(argv_environ->argv_buf = wasm_runtime_malloc((uint32)argv_buf_len))) goto fail1; for (i = 0; i < argv_offsets_len; ++i) { @@ -2885,11 +2884,11 @@ bool argv_environ_init(struct argv_environ_values *argv_environ, total_size = sizeof(char *) * (uint64)environ_offsets_len; if (total_size >= UINT32_MAX - || !(argv_environ->environ = bh_malloc((uint32)total_size))) + || !(argv_environ->environ = wasm_runtime_malloc((uint32)total_size))) goto fail2; if (environ_buf_len >= UINT32_MAX - || !(argv_environ->environ_buf = bh_malloc((uint32)environ_buf_len))) + || !(argv_environ->environ_buf = wasm_runtime_malloc((uint32)environ_buf_len))) goto fail3; for (i = 0; i < environ_offsets_len; ++i) { @@ -2901,11 +2900,11 @@ bool argv_environ_init(struct argv_environ_values *argv_environ, return true; fail3: - bh_free(argv_environ->environ); + wasm_runtime_free(argv_environ->environ); fail2: - bh_free(argv_environ->argv_buf); + wasm_runtime_free(argv_environ->argv_buf); fail1: - bh_free(argv_environ->argv); + wasm_runtime_free(argv_environ->argv); memset(argv_environ, 0, sizeof(struct argv_environ_values)); return false; @@ -2914,13 +2913,13 @@ fail1: void argv_environ_destroy(struct argv_environ_values *argv_environ) { if (argv_environ->argv_buf) - bh_free(argv_environ->argv_buf); + wasm_runtime_free(argv_environ->argv_buf); if (argv_environ->argv) - bh_free(argv_environ->argv); + wasm_runtime_free(argv_environ->argv); if (argv_environ->environ_buf) - bh_free(argv_environ->environ_buf); + wasm_runtime_free(argv_environ->environ_buf); if (argv_environ->environ) - bh_free(argv_environ->environ); + wasm_runtime_free(argv_environ->environ); } void fd_table_destroy(struct fd_table *ft) @@ -2931,7 +2930,7 @@ void fd_table_destroy(struct fd_table *ft) fd_object_release(ft->entries[i].object); } } - bh_free(ft->entries); + wasm_runtime_free(ft->entries); } } @@ -2940,9 +2939,9 @@ void fd_prestats_destroy(struct fd_prestats *pt) if (pt->prestats) { for (uint32 i = 0; i < pt->size; i++) { if (pt->prestats[i].dir != NULL) { - bh_free((void*)pt->prestats[i].dir); + wasm_runtime_free((void*)pt->prestats[i].dir); } } - bh_free(pt->prestats); + wasm_runtime_free(pt->prestats); } } diff --git a/core/shared/include/bh_common.h b/core/shared/include/bh_common.h index 831ffe8a4..7e78e3e82 100644 --- a/core/shared/include/bh_common.h +++ b/core/shared/include/bh_common.h @@ -6,12 +6,7 @@ #ifndef _BH_COMMON_H #define _BH_COMMON_H -#include "bh_assert.h" #include "bh_platform.h" -#include "bh_list.h" - -typedef void (*bh_print_function_t)(const char* message); -void bh_set_print_function(bh_print_function_t pf); #define bh_memcpy_s(dest, dlen, src, slen) do { \ int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \ @@ -31,4 +26,14 @@ void bh_set_print_function(bh_print_function_t pf); bh_assert (_ret == 0); \ } while (0) +int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n); +int b_strcat_s(char * s1, size_t s1max, const char * s2); +int b_strcpy_s(char * s1, size_t s1max, const char * s2); + +/* strdup with string allocated by BH_MALLOC */ +char *bh_strdup(const char *s); + +/* strdup with string allocated by WA_MALLOC */ +char *wa_strdup(const char *s); + #endif diff --git a/core/shared/include/bh_memory.h b/core/shared/include/bh_memory.h deleted file mode 100644 index 4b3aa86db..000000000 --- a/core/shared/include/bh_memory.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BH_MEMORY_H -#define _BH_MEMORY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define BH_KB (1024) -#define BH_MB ((BH_KB)*1024) -#define BH_GB ((BH_MB)*1024) - -/** - * Initialize memory allocator with a pool, the bh_malloc/bh_free function - * will malloc/free memory from the pool - * - * @param mem the pool buffer - * @param bytes the size bytes of the buffer - * - * @return 0 if success, -1 otherwise - */ -int bh_memory_init_with_pool(void *mem, unsigned int bytes); - -/** - * Initialize memory allocator with memory allocator, the bh_malloc/bh_free - * function will malloc/free memory with the allocator passed - * - * @param malloc_func the malloc function - * @param free_func the free function - * - * @return 0 if success, -1 otherwise - */ -int bh_memory_init_with_allocator(void *malloc_func, void *free_func); - -/** - * Destroy memory - */ -void bh_memory_destroy(); - -/** - * Get the pool size of memory, if memory is initialized with allocator, - * return 1GB by default. - */ -unsigned bh_memory_pool_size(); - -#if BEIHAI_ENABLE_MEMORY_PROFILING == 0 - -/** - * This function allocates a memory chunk from system - * - * @param size bytes need allocate - * - * @return the pointer to memory allocated - */ -void* bh_malloc(unsigned int size); - -/** - * This function frees memory chunk - * - * @param ptr the pointer to memory need free - */ -void bh_free(void *ptr); - -#else - -void* bh_malloc_profile(const char *file, int line, const char *func, unsigned int size); -void bh_free_profile(const char *file, int line, const char *func, void *ptr); - -#define bh_malloc(size) bh_malloc_profile(__FILE__, __LINE__, __func__, size) -#define bh_free(ptr) bh_free_profile(__FILE__, __LINE__, __func__, ptr) - -/** - * Print current memory profiling data - * - * @param file file name of the caller - * @param line line of the file of the caller - * @param func function name of the caller - */ -void memory_profile_print(const char *file, int line, const char *func, int alloc); - -/** - * Summarize memory usage and print it out - * Can use awk to analyze the output like below: - * awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1 - */ -void memory_usage_summarize(); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef _BH_MEMORY_H */ - diff --git a/core/shared/include/bh_queue.h b/core/shared/include/bh_queue.h index 92e9b014e..41792012f 100644 --- a/core/shared/include/bh_queue.h +++ b/core/shared/include/bh_queue.h @@ -20,8 +20,8 @@ typedef struct bh_queue bh_queue; typedef void (*bh_queue_handle_msg_callback)(void *message, void *arg); -#define bh_queue_malloc bh_malloc -#define bh_queue_free bh_free +#define bh_queue_malloc BH_MALLOC +#define bh_queue_free BH_FREE #define bh_queue_mutex korp_mutex #define bh_queue_sem korp_sem diff --git a/core/shared/include/bni.h b/core/shared/include/bni.h deleted file mode 100644 index 437cf41d7..000000000 --- a/core/shared/include/bni.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ -/** - * @file bni.h - * @date Mon Jul 2 16:54:58 2012 - * - * @brief Beihai native interface. - */ - -#ifndef BNI_H -#define BNI_H - -#include "bh_types.h" - -/* Primitive types */ -typedef uint8 jboolean; -typedef int8 jbyte; -typedef uint16 jchar; -typedef int16 jshort; -typedef int32 jint; -typedef int64 jlong; -typedef float jfloat; -typedef double jdouble; -typedef jint jsize; - -/* Predefined Java class types. */ -struct _jobject; -typedef struct _jobject *jobject; -struct _jclass; -typedef struct _jclass *jclass; -struct _jstring; -typedef struct _jstring *jstring; - -/* Values of jboolean: */ -#define BNI_FALSE 0 -#define BNI_TRUE 1 - -/** - * Return the length of the array object. - * - * @param array Java array object - * - * @return the length of the Java array - */ -#define bni_array_length(array) ((jsize)((uint32)(array)->__length >> 2)) - -/** - * Return the address of the first element of array object. - * - * @param array Java array object - * - * @return the address of the first element of array object - */ -#define bni_array_elem(array) ((array)->__elem) - -/** - * Find the Java class with given class name. - * - * @param name Java class name - * - * @return class object of the Java class if found, NULL otherwise - * - * @throws OutOfMemoryError if VM runs out of memory. - */ -jclass -bni_find_class(const char *name); - -/** - * Throw an exception of given class with message. - * - * @param clazz class object of a subclass of java.lang.Throwable - * @param msg message for the exception or NULL if no message - * - * @return 0 if succeeds, nonzero otherwise - */ -jint -bni_throw_new(jclass clazz, const char *msg); - -/** - * Throw a NullPointerException. - * - * @throws NullPointerException - */ -void -bni_throw_npe(void); - -/** - * Throw an ArrayIndexOutOfBoundsException - * - * @param index the index used to access the array - * - * @throws ArrayIndexOutOfBoundsException - */ -void -bni_throw_aioobe(int index); - -/** - * Determine whether an exception is being thrown. - * - * @return exception object if exception is thrown, NULL otherwise - */ -jobject -bni_exception_occurred(void); - -/** - * Print the current exception to error-reporting channel. - */ -void -bni_exception_describe(void); - -/** - * Clear the currently thrown exception. - */ -void -bni_exception_clear(void); - -/** - * Return the Unicode character number of a string. - * - * @param str Java string object - * - * @return the Unicode character number of the string - */ -jsize -bni_string_length(jstring str); - -/** - * Return the length in bytes of the modified UTF-8 representation of - * a string. - * - * @param str Java string object - * @param start start offset in the string - * @param len number of Unicode characters - * - * @return the UTF-8 length of the string - * - * @throws StringIndexOutOfBoundsException on index overflow. - */ -jsize -bni_string_utf_length(jstring str, jsize start, jsize len); - -/** - * Copies len number of Unicode characters beginning at offset start - * to the given buffer buf. - * - * @param str Java string object - * @param start start offset in the string - * @param len number of Unicode characters to copy - * @param buf buffer for storing the result - */ -void -bni_string_region(jstring str, jsize start, jsize len, jchar *buf); - -/** - * Translates len number of Unicode characters beginning at offset - * start into modified UTF-8 encoding and place the result in the - * given buffer buf. - * - * @param str Java string object - * @param start start offset in the string - * @param len number of Unicode characters to copy - * @param buf buffer for storing the result - * - * @throws StringIndexOutOfBoundsException on index overflow. - */ -void -bni_string_utf_region(jstring str, jsize start, jsize len, char *buf); - -/** - * Translate Unicode characters into modified UTF-8 encoding and return - * the result. - * - * @param str Java string object - * - * @return the UTF-8 encoding string if succeeds, NULL otherwise - */ -char * -bni_string_get_utf_chars(jstring str); - -/** - * Get the given Java object's class index. - * - * @param obj Java object - * - * @return -1 if obj is an array, class index of the object otherwise - */ -jint -bni_object_class_index(jobject obj); - -/** - * Allocate memory from the current instance's private heap. - * - * @param size bytes to allocate - * - * @return pointer to the allocated memory - * - * @throws OutOfMemoryError if VM runs out of memory. - */ -void* -bni_malloc(unsigned size); - -/** - * Allocate memory from the current instance's private heap and clear - * to zero. - * - * @param size bytes to allocate - * - * @return pointer to the allocated memory - * - * @throws OutOfMemoryError if VM runs out of memory. - */ -void* -bni_calloc(unsigned size); - -/** - * Free the memory allocated from the current instance's private heap. - * - * @param ptr pointer to the memory in current instance's private heap - */ -void -bni_free(void *ptr); - -#endif diff --git a/core/shared/include/config.h b/core/shared/include/config.h index bb98980ee..66bb55f57 100644 --- a/core/shared/include/config.h +++ b/core/shared/include/config.h @@ -98,6 +98,13 @@ enum { /* WASM Interpreter labels-as-values feature */ #define WASM_ENABLE_LABELS_AS_VALUES 1 +#if WASM_ENABLE_FAST_INTERP != 0 +#define WASM_ENABLE_ABS_LABEL_ADDR 1 +#define WASM_DEBUG_PREPROCESSOR 0 +#else +#define WASM_ENABLE_ABS_LABEL_ADDR 0 +#endif + /* Heap and stack profiling */ #define BEIHAI_ENABLE_MEMORY_PROFILING 0 diff --git a/core/shared/include/jeff_export.h b/core/shared/include/jeff_export.h deleted file mode 100644 index e9f4128dc..000000000 --- a/core/shared/include/jeff_export.h +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ -/** - * @file jeff-export.h - * @date Wed Aug 3 18:17:30 2011 - * - * @brief Exported interface for operating or executing JEFF files. - * All interface names start with "jeff_", which is the namespace name - * of this module. - */ - -#ifndef JEFF_EXPORT_H -#define JEFF_EXPORT_H - -#include "bni.h" -#include "bh_types.h" - -/******************************************************************** - * Exported internal types - ********************************************************************/ - -/** - * JEFF file handle type - */ -struct JeffFileHeaderLinked; -typedef struct JeffFileHeaderLinked *jeff_file_t; - -/** - * JEFF class type - */ -struct JeffClassHeaderLinked; -typedef struct JeffClassHeaderLinked *jeff_class_t; - -/** - * VM instance handle type - */ -struct JeffInstanceLocalRoot; -typedef struct JeffInstanceLocalRoot *jeff_instance_t; - -/** - * Record of one native method's definition. - */ -struct JeffNativeMethodDef { - /* Mangled name of the native method. NULL for initialization - functions. */ - const char *mangled_name; - - /* Points to the native C function. */ - void (*func_ptr)(uint32 *); - - /* Return size type of the native function. */ - uint32 return_size_type; -}; - -/******************************************************************** - * Interface for operating global environment of the JEFF VM - ********************************************************************/ - -/** - * Load the core library from the given file buffer and initialize the - * runtime environment (global objects etc.) of the VM. The thread - * calls this function becomes the supervisor thread, which belongs to - * a unique supervisor instance. Currently, if this init failed, - * partially initialized states of the VM runtime environment won't be - * cleaned up, so the VM must be shutdown and restarted. method_defs - * points to an array of native method definition records. - * Initialization functions must be in the front of the array and - * following native method definitions must be sorted by their mangled - * names. - * - * @param file the JEFF file of the core library - * @param file_size the size of the JEFF file of the core library - * @param method_defs native method definition records - * @param method_defs_num number of native method records - * @param heap the heap for the current (supervisor) instance - * - * @return true if succeeds, otherwise the error cannot be recovered - */ -bool -jeff_runtime_init(jeff_file_t file, unsigned file_size, - struct JeffNativeMethodDef *method_defs, unsigned method_defs_num, - void *heap); - -/** - * Load a JEFF file into the VM from the given file buffer. It can be - * called from any VM thread. - * - * @param file the JEFF file to be loaded - * @param size the size of the JEFF file - * @param is_library whether the JEFF file is a library - * @param allow_to_load a function that returns true if classes in the - * given package is allowed to be loaded. The NULL function pointer - * allows all packages. - * @param allow_to_link a function that returns true if classes in the - * given package is allowed to be linked to. The NULL function - * pointer allows all packages. - * - * @return true if succeeds, otherwise detailed error information is - * passed to vmci_diagnostic_print. The caller can catch it by - * implementing that function. - */ -bool -jeff_runtime_load(jeff_file_t file, unsigned size, bool is_library, - bool (*allow_to_load)(const uint8 *pname, unsigned len), - bool (*allow_to_link)(const uint8 *pname, unsigned plen, - const uint8 *cname, unsigned clen)); - -/** - * Unload a JEFF file from the VM. All resources related to the JEFF - * file except the JEFF file itself are released. It can be called - * from any VM thread. - * - * @param file the JEFF file to be unloaded - * - * @return true if succeeds, otherwise detailed error information is - * passed to vmci_diagnostic_print. The caller can catch it by - * implementing that function. - */ -bool -jeff_runtime_unload(jeff_file_t file); - -/** - * Return the JEFF file with the given file uid. - * - * @param fuid the unique id of a loaded JEFF file - * - * @return the JEFF file is exists, otherwise NULL - */ -jeff_file_t -jeff_runtime_fuid_to_file(unsigned fuid); - -/** - * Return the file uid of the given JEFF file. - * - * @param file a loaded JEFF file - * - * @return the unique id of the given JEFF file - */ -unsigned -jeff_runtime_file_to_fuid(jeff_file_t file); - -/** - * Create a supervisor thread belonging to the supervisor instance. - * Threads that may interact with VM core must be either the main - * thread of supervisor instance (which calls jeff_runtime_init) or - * created by this function so that VM core required data structures - * can be set up correctly. - * - * @param start_routine the start routine of the new thread - * @param arg argument to the start routine - * - * @return true if succeeds, false otherwise - */ -bool -jeff_runtime_create_supervisor_thread(void* (*start_routine)(void *), - void *arg); - -/** - * Create a supervisor thread belonging to the supervisor instance. - * Threads that may interact with VM core must be either the main - * thread of supervisor instance (which calls jeff_runtime_init) or - * created by this function so that VM core required data structures - * can be set up correctly. - * - * @param start_routine the start routine of the new thread - * @param arg argument to the start routine - * @param prio thread priority - * - * @return true if succeeds, false otherwise - */ -bool -jeff_runtime_create_supervisor_thread_with_prio(void* (*start_routine)(void *), - void *arg, int prio); - -/******************************************************************** - * Interface for operating instance local environment - ********************************************************************/ - -/** - * Create a VM instance with the given JEFF file as its main file, - * (i.e. the file containing the main class of the VM instance). This - * function can be called from any VM thread, but it must be isolated - * from JEFF file's unloading operation so that the main file won't be - * unloaded before it's locked by the new instance. All instance - * local memory except stacks of threads are allocated from the given - * heap. If succeeds, it increases reference count of the main_file - * and returns the handle of the new VM instance. The new instance's - * main thread will run the start_routine with argument arg. If the - * cleanup_routine is not NULL, it will be called after start_routine - * returns and just before the main thread exits. It will also be - * called after the instance is destroied. It is guaranteed to be - * called exactly once no matter how the instance terminates. - * - * @param main_file the main JEFF file of the new instance - * @param heap the private heap of the new instance - * @param stack_depth the maximal nesting levels of Java methods of - * the new instance. It must be <= 16 * 1024. Otherwise the instance - * creation will fail. - * @param start_routine start routine of the main thread. Don't - * destroy the heap or inform other thread to do this at the end of - * this routine since after it returns, VM core will call destroy - * functions on objects allocated in this heap (e.g. locks and - * condition variables). Do the destroying or informing of destroying - * in the cleanup_routine. - * @param arg the instance argument that will be passed to the start - * routine. It can be get or set by jeff_runtime_get_instance_arg and - * jeff_runtime_set_instance arg from threads of the instance. The - * caller can use it to store instance local data. - * @param cleanup_routine the optional cleanup routine for the - * instance, which may be NULL. It may be executed in the end of the - * main thread of the created instance by this function if this - * instance exits normally, or it may be executed in a thread of other - * instance in case this instance is being killed by that instance. - * In both cases, this routine regards it is executed in a thread of - * this instance (the instance created by this function) because - * jeff_runtime_get_instance_arg will always return the argument of - * this instance. - * - * @return the VM instance handle if succeeds, NULL otherwise - */ -jeff_instance_t -jeff_runtime_create_instance(jeff_file_t main_file, void *heap, - unsigned stack_depth, void* (*start_routine)(void *), void *arg, - void (*cleanup_routine)(void)); - -/** - * Destroy the given VM instance and decrease the reference count of - * its main file and all explicitly used JEFF files. It can be called - * from any VM thread. If there are alive threads of the instance, - * they will be terminated mandatorily and then the cleanup routine is - * called if it's not NULL. - * - * @param handle the handle of the instance to be destroyed - */ -void -jeff_runtime_destroy_instance(jeff_instance_t handle); - -/** - * Retrieve the current instance's argument. - * - * @return the current instance's argument - */ -void* -jeff_runtime_get_instance_arg(void); - -/** - * Set the current instance's argument. - * - * @return the new argument for the current instance - */ -void -jeff_runtime_set_instance_arg(void *arg); - -/** - * Retrieve the current instance's heap. - * - * @return the current instance's heap - */ -void* -jeff_runtime_get_instance_heap(void); - -/** - * Suspend all threads of the given VM instance. This function can - * only be called from thread that is not of the given VM instance. - * - * @param handle the handle of the instance to be suspended - */ -void -jeff_runtime_suspend_instance(jeff_instance_t handle); - -/** - * Resume all threads of the given VM instance. This function can - * only be called from thread that is not of the given VM instance. - * - * @param handle the handle of the instance to be resumed - */ -void -jeff_runtime_resume_instance(jeff_instance_t handle); - -/** - * Interrupt all threads of the given VM instance. This function can - * only be called from thread that is not of the given VM instance. - * - * @param handle the handle of the instance to be interrupted - * @param by_force whether the interruption is by force - */ -void -jeff_runtime_interrupt_instance(jeff_instance_t handle, bool by_force); - -/** - * Wait for the given VM instance to terminate. - * - * @param ilr the VM instance to be waited for - * @param mills wait millseconds to return - */ -void -jeff_runtime_wait_for_instance(jeff_instance_t ilr, int mills); - -/******************************************************************** - * Interface for operating thread local environment - ********************************************************************/ - -/** - * Return true if there is an uncaught exception (thrown during - * running an application or applet command). - * - * @return true if there is an uncaught exception - */ -bool -jeff_runtime_check_uncaught_exception(void); - -/** - * Print qualified name of the uncaught exception (and stack trace if - * enabled) by calling vmci_diagnostic_print. - */ -void -jeff_runtime_print_uncaught_exception(void); - -/** - * Clear the uncaught exception. - */ -void -jeff_runtime_reset_uncaught_exception(void); - -/** - * Change current thread to a safe state (VMWAIT). After calling this - * and before calling jeff_runtime_exit_safe_state, all operations - * must be safe, i.e. no GC or system level resource operations are - * allowed because in a safe state, the VM instance is assumed to be - * able to perform GC, JDWP or termination at any time. Usually, this - * function is called just before the native code is going to wait for - * something and the exiting safe state function is called just after - * the waiting returns. - */ -void -jeff_runtime_enter_safe_state(void); - -/** - * Change current thread to an unsafe state (RUNNING) so that unsafe - * operations can also be done. - */ -void -jeff_runtime_exit_safe_state(void); - -/** - * Set thread local error code for the current thread. - * - * @param code the error code to be set - */ -void -jeff_runtime_set_error(unsigned code); - -/** - * Get the last error code of current thread. - * - * @return the last error code of current thread - */ -unsigned -jeff_runtime_get_error(void); - -/******************************************************************** - * Interface for GC support - ********************************************************************/ - -/** - * Traverse all objects of the given heap that are global or locate in - * threads' frames and return them by calling vmci_gc_rootset_elem. - * This function will suspend all threads except the current one of - * the VM instance owning the given heap before traversing. It - * traverses either all or none of the rootset objects, and returns - * true and false respectively. If it returns false, the GC process - * shouldn't proceed and is not necessary to unmark anything because - * no objects are marked. The function jeff_runtime_gc_finished must - * be called if and only if this function returns true so as to resume - * threads that are suspended during GC process. - * - * @param heap the heap for which rootset objects are looked up - * - * @return true if succeeds, false otherwise - */ -bool -jeff_runtime_traverse_gc_rootset(void *heap); - -/** - * Get the reference offset table of the given object. If the - * returned value R >= 0, *ret points to the reference offset table of - * the object and R is the number of offsets in the table. Otherwise, - * if the returned value R < 0, all reference fields of the object - * must be in a continuous region (usually the object is an array), - * then *ret is the offset to the first field in the region and R is - * the number of such fields in the region. - * - * @param obj pointer to the Java object - * @param ret points to a pointer for storing the reference offset - * table if return value >= 0, or for storing the offset to the first - * object reference in the Java object if return value < 0 - * - * @return number of offsets in the reference_offset table if >= 0, or - * number of object references in the object if < 0 - */ -int -jeff_object_get_reference_offsets(const jobject obj, uint16 **ret); - -/** - * Inform the containing VM instance that GC has finished and all - * suspended threads can be resumed. This function must be called if - * and only if jeff_runtime_traverse_gc_rootset returns true. - */ -void -jeff_runtime_gc_finished(void); - -/******************************************************************** - * Interface for tooling support - ********************************************************************/ - -/** - * This function is used to suspend the main thread of VM instance so - * that debugger can have chance to connect to the VM instance, set - * breakpoints and do any other debug settings. It must be called - * from the main thread of VM instance at the point just after VM - * instance initialization finishes and just before application code - * is to be executed. - */ -void -jeff_tool_suspend_self(void); - -/** - * Start up tool agent thread for the given VM instance. It can be - * called from any VM thread. - * - * @param handle the VM instance for which tool agent is started up - * @param queue queue of the tool agent - * @return true if succeeds, false otherwise - */ -bool -jeff_tool_start_agent(jeff_instance_t handle, void *queue); - -/******************************************************************** - * Interface for toolkit support - ********************************************************************/ - -/** - * Return the JEFF class pointer of the given class name. - * - * @param class_name the qualified class name - * - * @return the JEFF class pointer - */ -jeff_class_t -jeff_tool_get_jeff_class(const char *class_name); - -/** - * Get the mangled class name of the given class. - * - * @param clz the JEFF class - * @param buf buffer for returning the mangled name - * @param buf_size size of the buffer - * - * @return actual size of the mangled class name including the - * terminating null byte - */ -unsigned -jeff_tool_get_mangled_class_name(jeff_class_t clz, char *buf, - unsigned buf_size); - -/** - * Get class index of given class in its containing JEFF file. - * - * @param clz the JEFF class - * - * @return class index in the containing JEFF file - */ -int -jeff_tool_get_class_index(jeff_class_t clz); - -/** - * Callback handler prototype for traversing fields of class. - * - * @param arg argument passed to the handler from caller - * @param access_flag access flag of the method - * @param name the field name - * @param descriptor mangled field type descriptor - * @param offset the offset of the field in the class - * @param size size of the field - */ -typedef void -(*JeffToolFieldHandler)(void *arg, unsigned access_flag, const char *name, - const char *descriptor, unsigned offset, unsigned size); - -/** - * Traverse all fields of the given class, including those inherited - * from super classes. The fields are traversed in the same order as - * the field layout of the class. - * - * @param arg argument to be passed to the handler - * @param clz the JEFF class - * @param instance instance fields or static fielts - * @param handler the callback handler for each field - */ -void -jeff_tool_foreach_field(void *arg, jeff_class_t clz, bool instance, - JeffToolFieldHandler handler); - -/** - * Callback handler prototype for traversing methods of class. - * - * @param arg argument passed to the handler from caller - * @param access_flag access flag of the method - * @param name mangled name of the method - * @param descriptor mangled method arguments descriptor - * @param retune_type mangled descriptor of method's return type - */ -typedef void -(*JeffToolMethodHandler)(void *arg, unsigned access_flag, const char *name, - const char *descriptor, const char *return_type); - -/** - * Traverse all methods of the given class. - * - * @param arg argument to be passed to the handler - * @param clz the JEFF class - * @param handler the callback handler for each method - */ -void -jeff_tool_foreach_method(void *arg, jeff_class_t clz, - JeffToolMethodHandler handler); - -/** - * Callback handler prototype for traversing classes of main file. - * - * @param arg argument passed to the handler from caller - * @param clz pointer to one class in the main file - */ -typedef void -(*JeffToolClassHandler)(void *arg, jeff_class_t clz); - -/** - * Traverse all classes of the main file. - * - * @param arg argument to be passed to the handler - * @param handler the callback handler for each class - */ -void -jeff_tool_foreach_class(void *arg, JeffToolClassHandler handler); - -/******************************************************************** - * Interface for executing applications - ********************************************************************/ - -/** - * Initialize global environment for executing Java applications. - * - * @return true if succeeds, false otherwise - */ -bool -jeff_application_env_init(void); - -/** - * Find the unique class containing a public static "main - * ([Ljava.lang.String;)V" method from the main JEFF file of the - * current instance and execute that method. - * - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the main method is called, false otherwise (e.g. an - * exception occurs when preparing the arguments Java string array) - */ -bool -jeff_application_execute(int argc, char *argv[]); - -/******************************************************************** - * Interface for executing applets - ********************************************************************/ - -/** - * Initialize global environment for executing applets. - * - * @return true if succeeds, false otherwise - */ -bool -jeff_applet_env_init(void); - -/** - * Start to run from com.intel.runtime.core.RuntimeContext.main with a - * default message queue size and a default service class object. If - * the main JEFF file of the current VM instance contains exactly one - * class that is derived from com.intel.util.IntelApplet, then use it - * as the default service class. - * - * @param queue_size the default main message queue size - * @param default_service_class qualified class name of the default - * service class (entry point class), which must be in the main JEFF - * file. If NULL, find the default main class with rules described - * above. - * - * @return true if succeeds, false otherwise - */ -bool -jeff_applet_start(int queue_size, const char *default_service_class); - -#endif diff --git a/core/shared/include/mem_alloc.h b/core/shared/include/mem_alloc.h index 3e1cf9577..9553de1a0 100644 --- a/core/shared/include/mem_alloc.h +++ b/core/shared/include/mem_alloc.h @@ -23,6 +23,9 @@ mem_allocator_destroy(mem_allocator_t allocator); void * mem_allocator_malloc(mem_allocator_t allocator, uint32_t size); +void * +mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size); + void mem_allocator_free(mem_allocator_t allocator, void *ptr); diff --git a/core/shared/mem-alloc/ems/ems_alloc.c b/core/shared/mem-alloc/ems/ems_alloc.c index 19e76ade5..3bd2e9ae7 100644 --- a/core/shared/mem-alloc/ems/ems_alloc.c +++ b/core/shared/mem-alloc/ems/ems_alloc.c @@ -348,7 +348,7 @@ unsigned long g_total_malloc = 0; unsigned long g_total_free = 0; gc_object_t _gc_alloc_vo_i_heap(void *vheap, - gc_size_t size ALLOC_EXTRA_PARAMETERS) + gc_size_t size ALLOC_EXTRA_PARAMETERS) { gc_heap_t* heap = (gc_heap_t*) vheap; hmu_t *hmu = NULL; @@ -381,12 +381,70 @@ gc_object_t _gc_alloc_vo_i_heap(void *vheap, bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); #endif - FINISH: +FINISH: gct_vm_mutex_unlock(&heap->lock); return ret; } +gc_object_t _gc_realloc_vo_i_heap(void *vheap, void *ptr, + gc_size_t size ALLOC_EXTRA_PARAMETERS) +{ + gc_heap_t* heap = (gc_heap_t*) vheap; + hmu_t *hmu = NULL, *hmu_old = NULL; + gc_object_t ret = (gc_object_t) NULL, obj_old = (gc_object_t)ptr; + gc_size_t tot_size = 0, size_old = 0; + + if (obj_old) { + hmu_old = obj_to_hmu(obj_old); + size_old = hmu_get_size(hmu_old); + size_old -= HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE; + if (size < size_old) + return NULL; + if (size == size_old) + return obj_old; + } + + /* align size*/ + tot_size = GC_ALIGN_8(size + HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE); /* hmu header, prefix, suffix*/ + if (tot_size < size) + return NULL; + + gct_vm_mutex_lock(&heap->lock); + + hmu = alloc_hmu_ex(heap, tot_size); + if (!hmu) + goto FINISH; + + g_total_malloc += tot_size; + + hmu_set_ut(hmu, HMU_VO); + hmu_unfree_vo(hmu); + +#if defined(GC_VERIFY) + hmu_init_prefix_and_suffix(hmu, tot_size, file_name, line_number); +#endif + + ret = hmu_to_obj(hmu); + +#if BH_ENABLE_MEMORY_PROFILING != 0 + bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); +#endif + +FINISH: + gct_vm_mutex_unlock(&heap->lock); + + if (ret) { + memset(ret, 0, size); + if (obj_old) { + memcpy(ret, obj_old, size_old); + gc_free_h(vheap, obj_old); + } + } + + return ret; +} + /* see ems_gc.h for description*/ gc_object_t _gc_alloc_jo_i_heap(void *vheap, gc_size_t size ALLOC_EXTRA_PARAMETERS) diff --git a/core/shared/mem-alloc/ems/ems_gc.h b/core/shared/mem-alloc/ems/ems_gc.h index c24fb841e..cac4a784e 100644 --- a/core/shared/mem-alloc/ems/ems_gc.h +++ b/core/shared/mem-alloc/ems/ems_gc.h @@ -193,12 +193,14 @@ extern int gc_set_threshold_factor(void *heap, unsigned int factor); # define ALLOC_EXTRA_ARGUMENTS , __FILE__, __LINE__ # define ALLOC_PASSDOWN_EXTRA_ARGUMENTS , file_name, line_number # define gc_alloc_vo_h(heap, size) gc_alloc_vo_i_heap(heap, size, __FILE__, __LINE__) +# define gc_realloc_vo_h(heap, ptr, size) gc_realloc_vo_i_heap(heap, ptr, size, __FILE__, __LINE__) # define gc_free_h(heap, obj) gc_free_i_heap(heap, obj, __FILE__, __LINE__) #else # define ALLOC_EXTRA_PARAMETERS # define ALLOC_EXTRA_ARGUMENTS # define ALLOC_PASSDOWN_EXTRA_ARGUMENTS # define gc_alloc_vo_h gc_alloc_vo_i_heap +# define gc_realloc_vo_h gc_realloc_vo_i_heap # define gc_free_h gc_free_i_heap #endif @@ -221,16 +223,22 @@ extern int gci_gc_heap(void *heap); * NULL if failed. */ extern gc_object_t _gc_alloc_vo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); + gc_size_t size ALLOC_EXTRA_PARAMETERS); +extern gc_object_t _gc_realloc_vo_i_heap(void *heap, void *ptr, + gc_size_t size ALLOC_EXTRA_PARAMETERS); extern gc_object_t _gc_alloc_jo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); + gc_size_t size ALLOC_EXTRA_PARAMETERS); #ifdef INSTRUMENT_TEST_ENABLED extern gc_object_t gc_alloc_vo_i_heap_instr(void *heap, gc_size_t size, const char* func_name ); +extern gc_object_t gc_realloc_vo_i_heap_instr(void *heap, void *ptr, gc_size_t size, + const char* func_name ); extern gc_object_t gc_alloc_jo_i_heap_instr(void *heap, gc_size_t size, const char* func_name); # define gc_alloc_vo_i_heap(heap, size) gc_alloc_vo_i_heap_instr(heap, size, __FUNCTION__) +# define gc_realloc_vo_i_heap(heap, ptr, size) gc_realloc_vo_i_heap_instr(heap, ptr, size, __FUNCTION__) # define gc_alloc_jo_i_heap(heap, size) gc_alloc_jo_i_heap_instr(heap, size, __FUNCTION__) #else # define gc_alloc_vo_i_heap _gc_alloc_vo_i_heap +# define gc_realloc_vo_i_heap _gc_realloc_vo_i_heap # define gc_alloc_jo_i_heap _gc_alloc_jo_i_heap #endif diff --git a/core/shared/mem-alloc/ems/ems_gc_internal.h b/core/shared/mem-alloc/ems/ems_gc_internal.h index 94efb60cb..ac153fa10 100644 --- a/core/shared/mem-alloc/ems/ems_gc_internal.h +++ b/core/shared/mem-alloc/ems/ems_gc_internal.h @@ -12,7 +12,6 @@ extern "C" { #include "bh_platform.h" #include "bh_thread.h" -#include "bh_memory.h" #include "bh_assert.h" #include "ems_gc.h" diff --git a/core/shared/mem-alloc/mem_alloc.c b/core/shared/mem-alloc/mem_alloc.c index 72670ff5f..71ae701b2 100644 --- a/core/shared/mem-alloc/mem_alloc.c +++ b/core/shared/mem-alloc/mem_alloc.c @@ -26,6 +26,12 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) return gc_alloc_vo_h((gc_handle_t) allocator, size); } +void * +mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size) +{ + return gc_realloc_vo_h((gc_handle_t) allocator, ptr, size); +} + void mem_allocator_free(mem_allocator_t allocator, void *ptr) { if (ptr) @@ -101,8 +107,8 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator; if (size == 0) - /* tlsf doesn't allow to allocate 0 byte */ - size = 1; + /* tlsf doesn't allow to allocate 0 byte */ + size = 1; vm_mutex_lock(&allocator_tlsf->lock); ret = tlsf_malloc(allocator_tlsf->tlsf, size); @@ -110,6 +116,22 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) return ret; } +void * +mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size) +{ + void *ret; + mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator; + + if (size == 0) + /* tlsf doesn't allow to allocate 0 byte */ + size = 1; + + vm_mutex_lock(&allocator_tlsf->lock); + ret = tlsf_realloc(allocator_tlsf->tlsf, ptr, size); + vm_mutex_unlock(&allocator_tlsf->lock); + return ret; +} + void mem_allocator_free(mem_allocator_t allocator, void *ptr) { diff --git a/core/shared/mem-alloc/mem_alloc.cmake b/core/shared/mem-alloc/mem_alloc.cmake index 2a224bf52..be57f3794 100644 --- a/core/shared/mem-alloc/mem_alloc.cmake +++ b/core/shared/mem-alloc/mem_alloc.cmake @@ -9,8 +9,7 @@ include_directories(${MEM_ALLOC_DIR}) file (GLOB_RECURSE source_all ${MEM_ALLOC_DIR}/ems/*.c ${MEM_ALLOC_DIR}/tlsf/*.c - ${MEM_ALLOC_DIR}/mem_alloc.c - ${MEM_ALLOC_DIR}/bh_memory.c) + ${MEM_ALLOC_DIR}/mem_alloc.c) set (MEM_ALLOC_SHARED_SOURCE ${source_all}) diff --git a/core/shared/platform/CMakeLists.txt b/core/shared/platform/CMakeLists.txt deleted file mode 100755 index 7abefa2b3..000000000 --- a/core/shared/platform/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -include_directories (./include ../include ./${WAMR_BUILD_PLATFORM}) - -add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE) - -file (GLOB_RECURSE source_all ${WAMR_BUILD_PLATFORM}/*.c) -add_library (supportlib ${source_all}) - -target_link_libraries (supportlib -pthread -lrt) - -if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - add_library (supportlib_ut ${source_all}) - - set_target_properties (supportlib_ut PROPERTIES COMPILE_DEFINITIONS BH_TEST=1) - - target_link_libraries (supportlib_ut -pthread -lrt) -endif () - diff --git a/core/shared/platform/alios/bh_definition.c b/core/shared/platform/alios/bh_definition.c deleted file mode 100644 index 1bd85b125..000000000 --- a/core/shared/platform/alios/bh_definition.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, - const void * s2, unsigned int n) -{ - char *dest = (char*)s1; - char *src = (char*)s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcat(s1, s2); - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcpy(s1, s2); - return 0; -} - diff --git a/core/shared/platform/alios/bh_platform.c b/core/shared/platform/alios/bh_platform.c index 9d3a1f6bd..f209bac1b 100644 --- a/core/shared/platform/alios/bh_platform.c +++ b/core/shared/platform/alios/bh_platform.c @@ -4,39 +4,43 @@ */ #include "bh_platform.h" -#include "bh_memory.h" #include "bh_common.h" #include #include -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() +int +bh_platform_init() { return 0; } +void * +os_malloc(unsigned size) +{ + return NULL; +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return NULL; +} + +void +os_free(void *ptr) +{ +} + void * bh_mmap(void *hint, unsigned int size, int prot, int flags) { - return bh_malloc(size); + return BH_MALLOC(size); } void bh_munmap(void *addr, uint32 size) { - return bh_free(addr); + return BH_FREE(addr); } int diff --git a/core/shared/platform/alios/bh_platform.h b/core/shared/platform/alios/bh_platform.h index 9b39c00e2..a3620112a 100644 --- a/core/shared/platform/alios/bh_platform.h +++ b/core/shared/platform/alios/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -39,10 +38,6 @@ typedef uint64_t uint64; typedef int64_t int64; -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup - typedef aos_task_t korp_thread; typedef korp_thread *korp_tid; typedef aos_task_t *aos_tid_t; @@ -58,6 +53,10 @@ typedef struct korp_cond { typedef void* (*thread_start_routine_t)(void*); +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); + /* Unit test framework is based on C++, where the declaration of snprintf is different. */ #ifndef __cplusplus @@ -85,10 +84,6 @@ int snprintf(char *buffer, size_t count, const char *format, ...); extern void bh_assert_internal(int v, const char *file_name, int line_number, const char *expr_string); #define bh_assert(expr) bh_assert_internal((int)(expr), __FILE__, __LINE__, # expr) -extern int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n); -extern int b_strcat_s(char * s1, size_t s1max, const char * s2); -extern int b_strcpy_s(char * s1, size_t s1max, const char * s2); - /* math functions */ double sqrt(double x); double floor(double x); diff --git a/core/shared/platform/alios/bh_thread.c b/core/shared/platform/alios/bh_thread.c index a17751914..042e974a2 100644 --- a/core/shared/platform/alios/bh_thread.c +++ b/core/shared/platform/alios/bh_thread.c @@ -6,7 +6,6 @@ #include "bh_thread.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include #include @@ -102,7 +101,7 @@ vm_thread_cleanup(void) wait_node_sem = &thread_data->wait_node.sem; /* Free thread data firstly */ - bh_free(thread_data); + BH_FREE(thread_data); aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER); if (thread_wait_list) { @@ -152,7 +151,7 @@ _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, return BHT_ERROR; /* Create and initialize thread data */ - if (!(thread_data = bh_malloc(sizeof(bh_thread_data)))) + if (!(thread_data = BH_MALLOC(sizeof(bh_thread_data)))) return BHT_ERROR; memset(thread_data, 0, sizeof(bh_thread_data)); @@ -184,7 +183,7 @@ fail3: fail2: aos_sem_free(&thread_data->wait_node.sem); fail1: - bh_free(thread_data); + BH_FREE(thread_data); return BHT_ERROR; } diff --git a/core/shared/platform/android/bh_definition.c b/core/shared/platform/android/bh_definition.c deleted file mode 100644 index 8fb58d2f8..000000000 --- a/core/shared/platform/android/bh_definition.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcat(s1, s2); - - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcpy(s1, s2); - - return 0; -} - -int fopen_s(FILE ** pFile, const char *filename, const char *mode) -{ - if (NULL == pFile || NULL == filename || NULL == mode) { - return -1; - } - - *pFile = fopen(filename, mode); - - if (NULL == *pFile) - return -1; - - return 0; -} diff --git a/core/shared/platform/android/bh_platform.c b/core/shared/platform/android/bh_platform.c index 4eda405b0..1831e9502 100755 --- a/core/shared/platform/android/bh_platform.c +++ b/core/shared/platform/android/bh_platform.c @@ -12,24 +12,30 @@ #include #include -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() +int +bh_platform_init() { return 0; } +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + char* bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { @@ -58,7 +64,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) file_size = (uint32)stat_buf.st_size; - if (!(buffer = bh_malloc(file_size))) { + if (!(buffer = BH_MALLOC(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); close(file); return NULL; @@ -69,7 +75,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) if (read_size < file_size) { printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); + BH_FREE(buffer); return NULL; } diff --git a/core/shared/platform/android/bh_platform.h b/core/shared/platform/android/bh_platform.h index fa221aa2e..003850954 100644 --- a/core/shared/platform/android/bh_platform.h +++ b/core/shared/platform/android/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -36,16 +35,10 @@ extern "C" { typedef uint64_t uint64; typedef int64_t int64; -extern void DEBUGME(void); - -#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) - #ifndef BH_PLATFORM_ANDROID #define BH_PLATFORM_ANDROID #endif -/* NEED qsort */ - #define _STACK_SIZE_ADJUSTMENT (32 * 1024) /* Stack size of applet threads's native part. */ @@ -67,13 +60,12 @@ typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; typedef void* (*thread_start_routine_t)(void*); -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); #define bh_printf(...) (__android_log_print(ANDROID_LOG_INFO, "wasm_runtime::", __VA_ARGS__)) - int snprintf(char *buffer, size_t count, const char *format, ...); double fmod(double x, double y); float fmodf(float x, float y); @@ -99,17 +91,8 @@ double sqrt(double x); #define bh_assert assert -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, - unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); - -int fopen_s(FILE ** pFile, const char *filename, const char *mode); - char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); -char *bh_strdup(const char *s); - int bh_platform_init(); /* MMAP mode */ diff --git a/core/shared/platform/android/bh_thread.c b/core/shared/platform/android/bh_thread.c index cf41c4568..88c62a3ba 100755 --- a/core/shared/platform/android/bh_thread.c +++ b/core/shared/platform/android/bh_thread.c @@ -6,7 +6,6 @@ #include "bh_thread.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include #include #include @@ -67,7 +66,7 @@ static void *vm_thread_wrapper(void *arg) targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); - bh_free(targ); + BH_FREE(targ); _vm_tls_put(1, NULL); return NULL; } @@ -94,7 +93,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, return BHT_ERROR; } - targ = (thread_wrapper_arg*) bh_malloc(sizeof(*targ)); + targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); if (!targ) { pthread_attr_destroy(&tattr); return BHT_ERROR; @@ -106,7 +105,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { pthread_attr_destroy(&tattr); - bh_free(targ); + BH_FREE(targ); return BHT_ERROR; } @@ -128,7 +127,7 @@ korp_tid _vm_self_thread() void vm_thread_exit(void * code) { - bh_free(_vm_tls_get(1)); + BH_FREE(_vm_tls_get(1)); _vm_tls_put(1, NULL); pthread_exit(code); } diff --git a/core/shared/platform/darwin/bh_definition.c b/core/shared/platform/darwin/bh_definition.c deleted file mode 100644 index f093cc9c5..000000000 --- a/core/shared/platform/darwin/bh_definition.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#ifdef RSIZE_MAX -#undef RSIZE_MAX -#endif - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcat(s1, s2); - - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcpy(s1, s2); - - return 0; -} - -int fopen_s(FILE ** pFile, const char *filename, const char *mode) -{ - if (NULL == pFile || NULL == filename || NULL == mode) { - return -1; - } - - *pFile = fopen(filename, mode); - - if (NULL == *pFile) - return -1; - - return 0; -} diff --git a/core/shared/platform/darwin/bh_platform.c b/core/shared/platform/darwin/bh_platform.c index 8a660b6d3..ddfacf3ea 100755 --- a/core/shared/platform/darwin/bh_platform.c +++ b/core/shared/platform/darwin/bh_platform.c @@ -12,24 +12,30 @@ #include #include -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() +int +bh_platform_init() { return 0; } +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + char* bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { @@ -58,7 +64,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) file_size = (uint32)stat_buf.st_size; - if (!(buffer = bh_malloc(file_size))) { + if (!(buffer = BH_MALLOC(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); close(file); return NULL; @@ -69,7 +75,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) if (read_size < file_size) { printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); + BH_FREE(buffer); return NULL; } diff --git a/core/shared/platform/darwin/bh_platform.h b/core/shared/platform/darwin/bh_platform.h index 11a577bbc..e07dd4e55 100644 --- a/core/shared/platform/darwin/bh_platform.h +++ b/core/shared/platform/darwin/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -34,16 +33,10 @@ extern "C" { typedef uint64_t uint64; typedef int64_t int64; -extern void DEBUGME(void); - -#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) - #ifndef BH_PLATFORM_DARWIN #define BH_PLATFORM_DARWIN #endif -/* NEED qsort */ - #define _STACK_SIZE_ADJUSTMENT (32 * 1024) /* Stack size of applet threads's native part. */ @@ -65,9 +58,9 @@ typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; typedef void* (*thread_start_routine_t)(void*); -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); #define bh_printf printf @@ -96,17 +89,8 @@ double sqrt(double x); #define bh_assert assert -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, - unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); - -int fopen_s(FILE ** pFile, const char *filename, const char *mode); - char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); -char *bh_strdup(const char *s); - int bh_platform_init(); /* MMAP mode */ diff --git a/core/shared/platform/darwin/bh_thread.c b/core/shared/platform/darwin/bh_thread.c index abf736806..c81e9786d 100644 --- a/core/shared/platform/darwin/bh_thread.c +++ b/core/shared/platform/darwin/bh_thread.c @@ -6,7 +6,6 @@ #include "bh_thread.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include #include #include @@ -67,7 +66,7 @@ static void *vm_thread_wrapper(void *arg) targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); - bh_free(targ); + BH_FREE(targ); _vm_tls_put(1, NULL); return NULL; } @@ -93,7 +92,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, return BHT_ERROR; } - targ = (thread_wrapper_arg*) bh_malloc(sizeof(*targ)); + targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); if (!targ) { pthread_attr_destroy(&tattr); return BHT_ERROR; @@ -105,7 +104,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { pthread_attr_destroy(&tattr); - bh_free(targ); + BH_FREE(targ); return BHT_ERROR; } @@ -127,7 +126,7 @@ korp_tid _vm_self_thread() void vm_thread_exit(void * code) { - bh_free(_vm_tls_get(1)); + BH_FREE(_vm_tls_get(1)); _vm_tls_put(1, NULL); pthread_exit(code); } diff --git a/core/shared/platform/include/bh_config.h b/core/shared/platform/include/bh_config.h index 0069194d1..ec4984133 100644 --- a/core/shared/platform/include/bh_config.h +++ b/core/shared/platform/include/bh_config.h @@ -16,5 +16,38 @@ #include "config.h" +#define BH_KB (1024) +#define BH_MB ((BH_KB)*1024) +#define BH_GB ((BH_MB)*1024) + +#ifndef BH_MALLOC +#define BH_MALLOC os_malloc +#endif + +#ifndef BH_FREE +#define BH_FREE os_free +#endif + +#ifndef WA_MALLOC +#include +#define WA_MALLOC malloc +#endif + +#ifndef WA_FREE +#include +#define WA_FREE free +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void *wasm_runtime_malloc(unsigned int size); +void wasm_runtime_free(void *ptr); + +#ifdef __cplusplus +} +#endif + #endif /* end of BH_CONFIG */ diff --git a/core/shared/platform/linux-sgx/bh_definition.c b/core/shared/platform/linux-sgx/bh_definition.c deleted file mode 100644 index 2b69af0ca..000000000 --- a/core/shared/platform/linux-sgx/bh_definition.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strncat(s1, s2, strlen(s2)); - - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strncpy(s1, s2, s1max); - - return 0; -} - diff --git a/core/shared/platform/linux-sgx/bh_platform.c b/core/shared/platform/linux-sgx/bh_platform.c index 5b66a13d0..8b742c6d0 100644 --- a/core/shared/platform/linux-sgx/bh_platform.c +++ b/core/shared/platform/linux-sgx/bh_platform.c @@ -14,24 +14,29 @@ #define FIXED_BUFFER_SIZE (1<<9) static bh_print_function_t print_function = NULL; -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - int bh_platform_init() { return 0; } +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + int putchar(int c) { return 0; diff --git a/core/shared/platform/linux-sgx/bh_platform.h b/core/shared/platform/linux-sgx/bh_platform.h index dc4723283..ab479e3da 100644 --- a/core/shared/platform/linux-sgx/bh_platform.h +++ b/core/shared/platform/linux-sgx/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -27,14 +26,15 @@ extern "C" { #endif +typedef void (*bh_print_function_t)(const char* message); +void bh_set_print_function(bh_print_function_t pf); + extern int bh_printf_sgx(const char *message, ...); extern int bh_vprintf_sgx(const char * format, va_list arg); typedef uint64_t uint64; typedef int64_t int64; -#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) - #ifndef BH_PLATFORM_LINUX_SGX #define BH_PLATFORM_LINUX_SGX #endif @@ -62,9 +62,9 @@ typedef sgx_thread_t korp_tid; typedef sgx_thread_t korp_thread; typedef sgx_thread_cond_t korp_cond; -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); #define bh_printf bh_printf_sgx @@ -94,13 +94,6 @@ double sqrt(double x); #define bh_assert assert -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, - unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); - -char *bh_strdup(const char *s); - int bh_platform_init(); /* MMAP mode */ diff --git a/core/shared/platform/linux-sgx/bh_thread.c b/core/shared/platform/linux-sgx/bh_thread.c index 28667be20..a2a76c3ca 100644 --- a/core/shared/platform/linux-sgx/bh_thread.c +++ b/core/shared/platform/linux-sgx/bh_thread.c @@ -5,7 +5,6 @@ #include "bh_thread.h" #include "bh_assert.h" -#include "bh_memory.h" #include #include #include diff --git a/core/shared/platform/linux/bh_definition.c b/core/shared/platform/linux/bh_definition.c deleted file mode 100644 index 8fb58d2f8..000000000 --- a/core/shared/platform/linux/bh_definition.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcat(s1, s2); - - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcpy(s1, s2); - - return 0; -} - -int fopen_s(FILE ** pFile, const char *filename, const char *mode) -{ - if (NULL == pFile || NULL == filename || NULL == mode) { - return -1; - } - - *pFile = fopen(filename, mode); - - if (NULL == *pFile) - return -1; - - return 0; -} diff --git a/core/shared/platform/linux/bh_platform.c b/core/shared/platform/linux/bh_platform.c index 4eda405b0..1831e9502 100755 --- a/core/shared/platform/linux/bh_platform.c +++ b/core/shared/platform/linux/bh_platform.c @@ -12,24 +12,30 @@ #include #include -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() +int +bh_platform_init() { return 0; } +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + char* bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { @@ -58,7 +64,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) file_size = (uint32)stat_buf.st_size; - if (!(buffer = bh_malloc(file_size))) { + if (!(buffer = BH_MALLOC(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); close(file); return NULL; @@ -69,7 +75,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) if (read_size < file_size) { printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); + BH_FREE(buffer); return NULL; } diff --git a/core/shared/platform/linux/bh_platform.h b/core/shared/platform/linux/bh_platform.h index 2fc4e1a30..e73b3d965 100644 --- a/core/shared/platform/linux/bh_platform.h +++ b/core/shared/platform/linux/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -66,9 +65,9 @@ typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; typedef void* (*thread_start_routine_t)(void*); -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); #define bh_printf printf @@ -97,17 +96,8 @@ double sqrt(double x); #define bh_assert assert -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, - unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); - -int fopen_s(FILE ** pFile, const char *filename, const char *mode); - char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); -char *bh_strdup(const char *s); - int bh_platform_init(); /* MMAP mode */ diff --git a/core/shared/platform/linux/bh_thread.c b/core/shared/platform/linux/bh_thread.c index 8160fb044..199809900 100755 --- a/core/shared/platform/linux/bh_thread.c +++ b/core/shared/platform/linux/bh_thread.c @@ -6,7 +6,6 @@ #include "bh_thread.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include #include #include @@ -67,7 +66,7 @@ static void *vm_thread_wrapper(void *arg) targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); - bh_free(targ); + BH_FREE(targ); _vm_tls_put(1, NULL); return NULL; } @@ -93,7 +92,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, return BHT_ERROR; } - targ = (thread_wrapper_arg*) bh_malloc(sizeof(*targ)); + targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); if (!targ) { pthread_attr_destroy(&tattr); return BHT_ERROR; @@ -105,7 +104,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { pthread_attr_destroy(&tattr); - bh_free(targ); + BH_FREE(targ); return BHT_ERROR; } @@ -127,7 +126,7 @@ korp_tid _vm_self_thread() void vm_thread_exit(void * code) { - bh_free(_vm_tls_get(1)); + BH_FREE(_vm_tls_get(1)); _vm_tls_put(1, NULL); pthread_exit(code); } diff --git a/core/shared/platform/vxworks/bh_definition.c b/core/shared/platform/vxworks/bh_definition.c deleted file mode 100644 index 4cdf98259..000000000 --- a/core/shared/platform/vxworks/bh_definition.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcat(s1, s2); - - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcpy(s1, s2); - - return 0; -} diff --git a/core/shared/platform/vxworks/bh_platform.c b/core/shared/platform/vxworks/bh_platform.c index ea5666b30..e0eca6a65 100644 --- a/core/shared/platform/vxworks/bh_platform.c +++ b/core/shared/platform/vxworks/bh_platform.c @@ -16,25 +16,30 @@ #include #include - -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() +int +bh_platform_init() { return 0; } +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + char* bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { @@ -63,7 +68,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) file_size = (uint32)stat_buf.st_size; - if (!(buffer = bh_malloc(file_size))) { + if (!(buffer = BH_MALLOC(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); close(file); return NULL; @@ -74,7 +79,7 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) if (read_size < file_size) { printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); + BH_FREE(buffer); return NULL; } diff --git a/core/shared/platform/vxworks/bh_platform.h b/core/shared/platform/vxworks/bh_platform.h index 457933d84..70c030e74 100644 --- a/core/shared/platform/vxworks/bh_platform.h +++ b/core/shared/platform/vxworks/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -42,8 +41,6 @@ extern void DEBUGME(void); #define BH_PLATFORM_VXWORKS #endif -/* NEED qsort */ - #define _STACK_SIZE_ADJUSTMENT (32 * 1024) /* Stack size of applet threads's native part. */ @@ -65,9 +62,9 @@ typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; typedef void* (*thread_start_routine_t)(void*); -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); #define bh_printf printf @@ -96,15 +93,8 @@ double sqrt(double x); #define bh_assert assert -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, - unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); - char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); -char *bh_strdup(const char *s); - int bh_platform_init(); /* MMAP mode */ diff --git a/core/shared/platform/vxworks/bh_thread.c b/core/shared/platform/vxworks/bh_thread.c index 3b51596fd..4267154ec 100644 --- a/core/shared/platform/vxworks/bh_thread.c +++ b/core/shared/platform/vxworks/bh_thread.c @@ -6,7 +6,6 @@ #include "bh_thread.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include #include #include @@ -67,7 +66,7 @@ static void *vm_thread_wrapper(void *arg) targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); - bh_free(targ); + BH_FREE(targ); _vm_tls_put(1, NULL); return NULL; } @@ -93,7 +92,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, return BHT_ERROR; } - targ = (thread_wrapper_arg*) bh_malloc(sizeof(*targ)); + targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ)); if (!targ) { pthread_attr_destroy(&tattr); return BHT_ERROR; @@ -105,7 +104,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) { pthread_attr_destroy(&tattr); - bh_free(targ); + BH_FREE(targ); return BHT_ERROR; } @@ -127,7 +126,7 @@ korp_tid _vm_self_thread() void vm_thread_exit(void * code) { - bh_free(_vm_tls_get(1)); + BH_FREE(_vm_tls_get(1)); _vm_tls_put(1, NULL); pthread_exit(code); } diff --git a/core/shared/platform/zephyr/bh_definition.c b/core/shared/platform/zephyr/bh_definition.c deleted file mode 100644 index aae3ed823..000000000 --- a/core/shared/platform/zephyr/bh_definition.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" - -#define RSIZE_MAX 0x7FFFFFFF - -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n) -{ - char *dest = (char*) s1; - char *src = (char*) s2; - if (n == 0) { - return 0; - } - - if (s1 == NULL || s1max > RSIZE_MAX) { - return -1; - } - if (s2 == NULL || n > s1max) { - memset(dest, 0, s1max); - return -1; - } - memcpy(dest, src, n); - return 0; -} - -int b_strcat_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1 || NULL == s2 - || s1max < (strlen(s1) + strlen(s2) + 1) - || s1max > RSIZE_MAX) { - return -1; - } - - strcat(s1, s2); - - return 0; -} - -int b_strcpy_s(char * s1, size_t s1max, const char * s2) -{ - if (NULL == s1|| NULL == s2 - || s1max < (strlen(s2) + 1) || s1max > RSIZE_MAX) { - return -1; - } - - strcpy(s1, s2); - - return 0; -} - diff --git a/core/shared/platform/zephyr/bh_platform.c b/core/shared/platform/zephyr/bh_platform.c index f2bc2e380..ba528cd56 100755 --- a/core/shared/platform/zephyr/bh_platform.c +++ b/core/shared/platform/zephyr/bh_platform.c @@ -4,7 +4,6 @@ */ #include "bh_platform.h" -#include "bh_memory.h" #include "bh_common.h" #include #include @@ -12,19 +11,6 @@ #include #endif -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - #ifdef CONFIG_ARM_MPU /** * This function will allow execute from sram region. @@ -54,7 +40,8 @@ _stdout_hook_iwasm(int c) return 1; } -int bh_platform_init() +int +bh_platform_init() { extern void __stdout_hook_install(int (*hook)(int)); /* Enable printf() in Zephyr */ @@ -70,16 +57,33 @@ int bh_platform_init() return 0; } +void * +os_malloc(unsigned size) +{ + return NULL; +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return NULL; +} + +void +os_free(void *ptr) +{ +} + void * bh_mmap(void *hint, unsigned int size, int prot, int flags) { - return bh_malloc(size); + return BH_MALLOC(size); } void bh_munmap(void *addr, uint32 size) { - return bh_free(addr); + return BH_FREE(addr); } int diff --git a/core/shared/platform/zephyr/bh_platform.h b/core/shared/platform/zephyr/bh_platform.h index 77db8a358..34cd386fa 100644 --- a/core/shared/platform/zephyr/bh_platform.h +++ b/core/shared/platform/zephyr/bh_platform.h @@ -8,7 +8,6 @@ #include "bh_config.h" #include "bh_types.h" -#include "bh_memory.h" #include #include #include @@ -55,10 +54,6 @@ typedef korp_thread *korp_tid; typedef struct k_mutex korp_mutex; typedef struct k_sem korp_sem; -#define wa_malloc bh_malloc -#define wa_free bh_free -#define wa_strdup bh_strdup - struct bh_thread_wait_node; typedef struct bh_thread_wait_node *bh_thread_wait_list; typedef struct korp_cond { @@ -68,8 +63,9 @@ typedef struct korp_cond { typedef void* (*thread_start_routine_t)(void*); -#define wa_malloc bh_malloc -#define wa_free bh_free +void *os_malloc(unsigned size); +void *os_realloc(void *ptr, unsigned size); +void os_free(void *ptr); #define bh_printf printf @@ -102,11 +98,6 @@ int snprintf(char *buffer, size_t count, const char *format, ...); } \ } while (0) -int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, - unsigned int n); -int b_strcat_s(char * s1, size_t s1max, const char * s2); -int b_strcpy_s(char * s1, size_t s1max, const char * s2); - /* math functions */ double sqrt(double x); double floor(double x); diff --git a/core/shared/platform/zephyr/bh_thread.c b/core/shared/platform/zephyr/bh_thread.c index fd9e6e0c0..9493076e6 100755 --- a/core/shared/platform/zephyr/bh_thread.c +++ b/core/shared/platform/zephyr/bh_thread.c @@ -6,9 +6,6 @@ #include "bh_thread.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" -#include -#include typedef struct bh_thread_wait_node { struct k_sem sem; @@ -140,11 +137,11 @@ static void thread_obj_list_reclaim() if (p->to_be_freed) { if (p_prev == NULL) { /* p is the head of list */ thread_obj_list = p->next; - bh_free(p); + BH_FREE(p); p = thread_obj_list; } else { /* p is not the head of list */ p_prev->next = p->next; - bh_free(p); + BH_FREE(p); p = p_prev->next; } } else { @@ -210,7 +207,7 @@ static void vm_thread_cleanup(void) /* Set flag to true for the next thread creating to free the thread object */ ((bh_thread_obj*) thread_data->tid)->to_be_freed = true; - bh_free(thread_data); + BH_FREE(thread_data); } static void vm_thread_wrapper(void *start, void *arg, void *thread_data) @@ -244,15 +241,15 @@ int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, thread_obj_list_reclaim(); /* Create and initialize thread object */ - if (!(tid = bh_malloc(sizeof(bh_thread_obj)))) + if (!(tid = BH_MALLOC(sizeof(bh_thread_obj)))) return BHT_ERROR; memset(tid, 0, sizeof(bh_thread_obj)); /* Create and initialize thread data */ thread_data_size = offsetof(bh_thread_data, stack) + stack_size; - if (!(thread_data = bh_malloc(thread_data_size))) { - bh_free(tid); + if (!(thread_data = BH_MALLOC(thread_data_size))) { + BH_FREE(tid); return BHT_ERROR; } @@ -265,8 +262,8 @@ int _vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, if (!((tid = k_thread_create(tid, (k_thread_stack_t *) thread_data->stack, stack_size, vm_thread_wrapper, start, arg, thread_data, prio, 0, K_NO_WAIT)))) { - bh_free(tid); - bh_free(thread_data); + BH_FREE(tid); + BH_FREE(thread_data); return BHT_ERROR; } @@ -305,7 +302,7 @@ int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) bh_thread_wait_node *node; /* Create wait node and append it to wait list */ - if (!(node = bh_malloc(sizeof(bh_thread_wait_node)))) + if (!(node = BH_MALLOC(sizeof(bh_thread_wait_node)))) return BHT_ERROR; k_sem_init(&node->sem, 0, 1); @@ -334,7 +331,7 @@ int _vm_thread_join(korp_tid thread, void **value_ptr, int mills) k_sleep(100); /* Destroy resource */ - bh_free(node); + BH_FREE(node); return BHT_OK; } @@ -449,7 +446,7 @@ static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bh_thread_wait_node *node; /* Create wait node and append it to wait list */ - if (!(node = bh_malloc(sizeof(bh_thread_wait_node)))) + if (!(node = BH_MALLOC(sizeof(bh_thread_wait_node)))) return BHT_ERROR; k_sem_init(&node->sem, 0, 1); @@ -483,7 +480,7 @@ static int _vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, p = p->next; p->next = node->next; } - bh_free(node); + BH_FREE(node); k_mutex_unlock(&cond->wait_list_lock); return BHT_OK; diff --git a/core/shared/utils/bh_definition.c b/core/shared/utils/bh_definition.c new file mode 100644 index 000000000..3d2a1e0df --- /dev/null +++ b/core/shared/utils/bh_definition.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "bh_common.h" + +#ifdef RSIZE_MAX +#undef RSIZE_MAX +#endif + +#define RSIZE_MAX 0x7FFFFFFF + +int +b_memcpy_s(void * s1, unsigned int s1max, + const void * s2, unsigned int n) +{ + char *dest = (char*)s1; + char *src = (char*)s2; + if (n == 0) { + return 0; + } + + if (s1 == NULL || s1max > RSIZE_MAX) { + return -1; + } + if (s2 == NULL || n > s1max) { + memset(dest, 0, s1max); + return -1; + } + memcpy(dest, src, n); + return 0; +} + +int +b_strcat_s(char * s1, size_t s1max, const char * s2) +{ + if (NULL == s1 || NULL == s2 + || s1max < (strlen(s1) + strlen(s2) + 1) + || s1max > RSIZE_MAX) { + return -1; + } + + memcpy(s1 + strlen(s1), s2, strlen(s2) + 1); + return 0; +} + +int +b_strcpy_s(char * s1, size_t s1max, const char * s2) +{ + if (NULL == s1 || NULL == s2 + || s1max < (strlen(s2) + 1) + || s1max > RSIZE_MAX) { + return -1; + } + + memcpy(s1, s2, strlen(s2) + 1); + return 0; +} + +char * +bh_strdup(const char *s) +{ + uint32 size; + char *s1 = NULL; + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = BH_MALLOC(size))) + bh_memcpy_s(s1, size, s, size); + } + return s1; +} + +char * +wa_strdup(const char *s) +{ + uint32 size; + char *s1 = NULL; + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = WA_MALLOC(size))) + bh_memcpy_s(s1, size, s, size); + } + return s1; +} + diff --git a/core/shared/utils/bh_hashmap.c b/core/shared/utils/bh_hashmap.c index 33891a8a0..0bebdfc64 100644 --- a/core/shared/utils/bh_hashmap.c +++ b/core/shared/utils/bh_hashmap.c @@ -6,7 +6,6 @@ #include "bh_hashmap.h" #include "bh_log.h" #include "bh_thread.h" -#include "bh_memory.h" typedef struct HashMapElem { @@ -55,7 +54,7 @@ bh_hash_map_create(uint32 size, bool use_lock, (use_lock ? sizeof(korp_mutex) : 0); if (total_size >= UINT32_MAX - || !(map = bh_malloc((uint32)total_size))) { + || !(map = BH_MALLOC((uint32)total_size))) { LOG_ERROR("HashMap create failed: alloc memory failed.\n"); return NULL; } @@ -68,7 +67,7 @@ bh_hash_map_create(uint32 size, bool use_lock, + sizeof(HashMapElem) * size); if (vm_mutex_init(map->lock)) { LOG_ERROR("HashMap create failed: init map lock failed.\n"); - bh_free(map); + BH_FREE(map); return NULL; } } @@ -106,7 +105,7 @@ bh_hash_map_insert(HashMap *map, void *key, void *value) elem = elem->next; } - if (!(elem = bh_malloc(sizeof(HashMapElem)))) { + if (!(elem = BH_MALLOC(sizeof(HashMapElem)))) { LOG_ERROR("HashMap insert elem failed: alloc memory failed.\n"); goto fail; } @@ -233,7 +232,7 @@ bh_hash_map_remove(HashMap *map, void *key, else prev->next = elem->next; - bh_free(elem); + BH_FREE(elem); if (map->lock) { vm_mutex_unlock(map->lock); @@ -277,7 +276,7 @@ bh_hash_map_destroy(HashMap *map) if (map->value_destroy_func) { map->value_destroy_func(elem->value); } - bh_free(elem); + BH_FREE(elem); elem = next; } @@ -287,6 +286,6 @@ bh_hash_map_destroy(HashMap *map) vm_mutex_unlock(map->lock); vm_mutex_destroy(map->lock); } - bh_free(map); + BH_FREE(map); return true; } diff --git a/core/shared/utils/bh_queue.c b/core/shared/utils/bh_queue.c index cd6a58166..4f74cee7e 100644 --- a/core/shared/utils/bh_queue.c +++ b/core/shared/utils/bh_queue.c @@ -5,7 +5,6 @@ #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" #include "bh_time.h" #include "bh_common.h" @@ -131,7 +130,7 @@ bool bh_post_msg(bh_queue *queue, unsigned short tag, void *body, if (msg == NULL) { queue->drops++; if (len != 0 && body) - bh_free(body); + BH_FREE(body); return false; } diff --git a/core/shared/utils/bh_vector.c b/core/shared/utils/bh_vector.c index bb7900f44..9b7c9db9e 100644 --- a/core/shared/utils/bh_vector.c +++ b/core/shared/utils/bh_vector.c @@ -5,7 +5,6 @@ #include "bh_log.h" #include "bh_vector.h" -#include "bh_memory.h" static uint8* @@ -18,7 +17,7 @@ alloc_vector_data(uint32 length, uint32 size_elem) return NULL; } - if ((data = bh_malloc((uint32)total_size))) { + if ((data = BH_MALLOC((uint32)total_size))) { memset(data, 0, (uint32)total_size); } @@ -41,7 +40,7 @@ extend_vector(Vector *vector, uint32 length) } memcpy(data, vector->data, vector->size_elem * vector->max_elements); - bh_free(vector->data); + BH_FREE(vector->data); vector->data = data; vector->max_elements = length; return true; @@ -200,7 +199,7 @@ bh_vector_destroy(Vector *vector) } if (vector->data) - bh_free(vector->data); + BH_FREE(vector->data); memset(vector, 0, sizeof(Vector)); return true; } diff --git a/core/shared/utils/runtime_timer.c b/core/shared/utils/runtime_timer.c index 09e3f1411..c2894e4eb 100644 --- a/core/shared/utils/runtime_timer.c +++ b/core/shared/utils/runtime_timer.c @@ -172,7 +172,7 @@ static void release_timer(timer_ctx_t ctx, app_timer_t * t) vm_mutex_unlock(&ctx->mutex); } else { PRINT("destroy timer :%d\n", t->id); - bh_free(t); + BH_FREE(t); } } @@ -182,7 +182,7 @@ void release_timer_list(app_timer_t ** p_list) while (t) { app_timer_t *next = t->next; PRINT("destroy timer list:%d\n", t->id); - bh_free(t); + BH_FREE(t); t = next; } @@ -199,7 +199,7 @@ timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, check_timer_expiry_f expiery_checker, int prealloc_num, unsigned int owner) { - timer_ctx_t ctx = (timer_ctx_t) bh_malloc(sizeof(struct _timer_ctx)); + timer_ctx_t ctx = (timer_ctx_t) BH_MALLOC(sizeof(struct _timer_ctx)); if (ctx == NULL) return NULL; memset(ctx, 0, sizeof(struct _timer_ctx)); @@ -210,7 +210,7 @@ timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, ctx->owner = owner; while (prealloc_num > 0) { - app_timer_t *timer = (app_timer_t*) bh_malloc(sizeof(app_timer_t)); + app_timer_t *timer = (app_timer_t*) BH_MALLOC(sizeof(app_timer_t)); if (timer == NULL) goto cleanup; @@ -231,7 +231,7 @@ timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, if (ctx) { release_timer_list(&ctx->free_timers); - bh_free(ctx); + BH_FREE(ctx); } PRINT("timer ctx create failed\n"); return NULL; @@ -242,14 +242,14 @@ void destroy_timer_ctx(timer_ctx_t ctx) while (ctx->free_timers) { void * tmp = ctx->free_timers; ctx->free_timers = ctx->free_timers->next; - bh_free(tmp); + BH_FREE(tmp); } cleanup_app_timers(ctx); vm_cond_destroy(&ctx->cond); vm_mutex_destroy(&ctx->mutex); - bh_free(ctx); + BH_FREE(ctx); } unsigned int timer_ctx_get_owner(timer_ctx_t ctx) @@ -279,7 +279,7 @@ uint32 sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, ctx->free_timers = timer->next; } } else { - timer = (app_timer_t*) bh_malloc(sizeof(app_timer_t)); + timer = (app_timer_t*) BH_MALLOC(sizeof(app_timer_t)); if (timer == NULL) return (uint32)-1; } diff --git a/doc/build_wamr.md b/doc/build_wamr.md index eeac611f1..2f845fa50 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -1,12 +1,72 @@ Build WAMR core (iwasm) ========================= -Please follow the instructions below to build the WAMR VM core on different platforms. +It is recommended to use the [WAMR SDK](../wamr-sdk) tools to build a project that embedes the WAMR. This document introduces how to build the WAMR minimal product which is vmcore only (no app-framework and app-mgr) for multiple platforms. + + + +## iwasm VM core CMake building configurations + +By including the cmake scripts under folder [build-scripts](../build-scripts), it is easy to build minimal product with CMake. WAMR provides a number of features which can be easily configured through cmake variables: + +``` Bash +cmake -DWAMR_BUILD_INTERP=1/0 to enable or disable WASM intepreter +cmake -DWAMR_BUILD_FAST_INTERP=1/0 to build fast (default) or classic WASM intepreter. +cmake -DWAMR_BUILD_AOT=1/0 to enable or disable WASM AOT +cmake -DWAMR_BUILD_JIT=1/0 to enable or disable WASM JIT. (Disabled by default) +cmake -DWAMR_BUILD_LIBC_BUILTIN=1/0 enable or disable Libc builtin API's. (Enabled by default) +cmake -DWAMR_BUILD_LIBC_WASI=1/0 enable or disable Libc WASI API's +cmake -DWAMR_BUILD_TARGET= to set the building target, including: + X86_64, X86_32, ARM, THUMB, XTENSA and MIPS + For ARM and THUMB, the format is [][_VFP] where is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both and [_VFP] are optional. e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. +``` + +For example, if we want to enable classic interpreter, we can: + +``` Bash +cmake .. -DWAMR_BUILD_FAST_INTERP=0 +``` + +**Note** the fast interpreter will run ~2X faster than classic interpreter, but it consumes about 2X memory to hold the WASM bytecode code. + +If we want to disable interpreter, enable AOT and WASI, we can: + +``` Bash +cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=0 +``` + +Or if we want to enable inerpreter, disable AOT and WASI, and build as X86_32, we can: + +``` Bash +cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32 +``` + +By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is +set to X86_64 or X86_32 depending on the platform's bitwidth. + +To enable WASM JIT, firstly we should build LLVM: + +``` Bash +cd product-mini/platforms/linux/ +./build_llvm.sh (The llvm source code is cloned under /core/deps/llvm and auto built) +``` + +Then pass option -DWAMR_BUILD_JIT=1 to cmake to enable WASM JIT: + +``` Bash +mkdir build +cd build +cmake .. -DWAMR_BUILD_JIT=1 +make +``` + + Linux ------------------------- First of all please install the dependent packages. Run command below in Ubuntu-18.04: + ``` Bash sudo apt install build-essential cmake g++-multilib libgcc-8-dev lib32gcc-8-dev ``` @@ -29,46 +89,13 @@ make ``` The binary file iwasm will be generated under build folder. -Note: -WAMR provides some features which can be easily configured by passing options to cmake: -``` Bash -cmake -DWAMR_BUILD_INTERP=1/0 to enable or disable WASM intepreter -cmake -DWAMR_BUILD_AOT=1/0 to enable or disable WASM AOT -cmake -DWAMR_BUILD_JIT=1/0 to enable or disable WASM JIT -cmake -DWAMR_BUILD_LIBC_BUILTIN=1/0 enable or disable Libc builtin API's -cmake -DWAMR_BUILD_LIBC_WASI=1/0 enable or disable Libc WASI API's -cmake -DWAMR_BUILD_TARGET= to set the building target, including: - X86_64, X86_32, ARM, THUMB, XTENSA and MIPS - For ARM and THUMB, the format is [][_VFP] where is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both and [_VFP] are optional. e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. -``` -For example, if we want to disable interpreter, enable AOT and WASI, we can: -``` Bash -cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=0 -``` -Or if we want to enable inerpreter, disable AOT and WASI, and build as X86_32, we can: -``` Bash -cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32 -``` -By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is -set to X86_64 or X86_32 depending on the platform's bitwidth. -To enable WASM JIT, firstly we should build LLVM: -``` Bash -cd product-mini/platforms/linux/ -./build_llvm.sh (The llvm source code is cloned under /core/deps/llvm and auto built) -``` -Then pass option -DWAMR_BUILD_JIT=1 to cmake to enable WASM JIT: -``` Bash -mkdir build -cd build -cmake .. -DWAMR_BUILD_JIT=1 -make -``` Linux SGX (Intel Software Guard Extention) ------------------------- + First of all please install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk). After installing dependencies, build the source code: @@ -122,11 +149,11 @@ VxWorks 7 SR0620 release is validated. First you need to build a VSB. Make sure *UTILS_UNIX* layer is added in the VSB. After the VSB is built, export the VxWorks toolchain path by: -``` +```bash export /host/vx-compiler/bin:$PATH ``` Now switch to iwasm source tree to build the source code: -``` +```bash cd product-mini/platforms/vxworks/ mkdir build cd build @@ -155,18 +182,19 @@ cd zephyr/samples/ cp -a /product-mini/platforms/zephyr/simple . cd simple ln -s wamr -mkdir build && cd build -source ../../../zephyr-env.sh - -1. build for x86 -cmake -GNinja -DBOARD=qemu_x86_nommu .. -ninja -2. build for ARM -modify ../prj.conf, modify the commented line "# CONFIG_ARM_MPU is not set" to "CONFIG_ARM_MPU=y" -cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 .. -ninja +source ../../zephyr-env.sh ``` + +1. build for x86 (qemu_x86_nommu) +``` Bash +./build.sh x86 +``` +2. build for ARM (nucleo_f767zi) +``` Bash +./build.sh stm32 +``` + Note: WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default. diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index 3a2c530aa..390dd7ebd 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -4,13 +4,11 @@ Embedding WAMR guideline **Note**: All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files. -## The initialization procedure +## The runtime initialization ``` C - static char global_heap_buf[512 * 1024]; - char *buffer, error_buf[128]; wasm_module_t module; wasm_module_inst_t module_inst; @@ -18,28 +16,63 @@ Embedding WAMR guideline wasm_exec_env_t exec_env; uint32 size, stack_size = 8092, heap_size = 8092; - // all the WAMR heap and WASM applications are limited in this buffer - bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)); - + // initialize the wasm runtime by default configurations wasm_runtime_init(); // read WASM file into a memory buffer buffer = read_wasm_binary_to_buffer(…, &size); - + + // Add it below if runtime needs to export native functions to WASM APP + // wasm_runtime_register_natives(...) + // parse the WASM file from buffer and create a WASM module module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); // create an instance of the WASM module (WASM linear memory is ready) - module_inst = wasm_runtime_instantiate(module, - stack_size, + module_inst = wasm_runtime_instantiate(module, + stack_size, heap_size, - error_buf, + error_buf, sizeof(error_buf)); ``` +The `wasm_runtime_init()` will use the default memory allocator from the [`core/shared/platform`](../core/shared/platform) for the runtime memory management. +The WAMR supports to restrict its all memory allocations in a raw buffer. It ensures the dynamics by the WASM applications won't harm the system availability, which is extremely important for embedded systems. This can be done by using `wasm_runtime_full_init()`. This function also allows you to configure the native APIs for exporting to WASM app. + +Refer to the following sample: + +```c +// the native functions that will be exported to WASM app +static NativeSymbol native_symbols[] = { + EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), + EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)") +}; + +// all the runtime memory allocations are retricted in the global_heap_buf array +static char global_heap_buf[512 * 1024]; +RuntimeInitArgs init_args; +memset(&init_args, 0, sizeof(RuntimeInitArgs)); + +// configure the memory allocator for the runtime +init_args.mem_alloc_type = Alloc_With_Pool; +init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; +init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + +// configure the native functions being exported to WASM app +init_args.native_module_name = "env"; +init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); +init_args.native_symbols = native_symbols; + +/* initialize runtime environment with user configurations*/ +if (!wasm_runtime_full_init(&init_args)) { + return -1; +} +``` + + ## Native calls WASM functions and passes parameters @@ -48,7 +81,8 @@ After a module is instantiated, the runtime native can lookup WASM functions by ```c unit32 argv[2]; - // lookup a WASM function by its name + // lookup a WASM function by its name. + // The function signature can NULL here func = wasm_runtime_lookup_function(module_inst, "fib", NULL); // creat a excution environment which can be used by executing WASM functions @@ -59,7 +93,6 @@ After a module is instantiated, the runtime native can lookup WASM functions by // call the WASM function if (wasm_runtime_call_wasm(exec_env, func, 1, argv) ) { - /* the return value is stored in argv[0] */ printf("fib function return: %d\n", argv[0]); } @@ -79,25 +112,24 @@ The parameters are transferred in an array of 32 bits elements. For parameters t double arg3 = 1.0; int 64 arg4 = 100; double ret; - + argv[0] = arg1; argv[1] = arg2; - - // use memory copy for 8 bytes parameters rather than - // *(double*)(&argv[2]) = arg3 here because some archs + + // use memory copy for 8 bytes parameters rather than + // *(double*)(&argv[2]) = arg3 here because some archs // like ARM, MIPS requires address is 8 aligned. // Or use the aligned malloc or compiler align attribute // to ensure the array address is 8 bytes aligned memcpy(&argv[2], &arg3, sizeof(arg3)); memcpy(&argv[4], &arg4, sizeof(arg4)); - - // + // // attention: the arg number is 6 here since both // arg3 and arg4 each takes 2 elements // wasm_runtime_call_wasm(exec_env, func, 6, argv); - - // if the return value is type of 8 bytes, it takes + + // if the return value is type of 8 bytes, it takes // the first two array elements memcpy(&ret, &argv[0], sizeof(ret)); @@ -109,7 +141,7 @@ The parameters are transferred in an array of 32 bits elements. For parameters t -If we need to transfer a buffer to WASM function, we can pass the buffer address through a parameter. **Attention**: The sandbox will forbid the WASM code to access outside memory, we must **allocate the buffer from WASM instance's own memory space and pass the buffer address in instance's space (not the runtime native address)**. +If we need to transfer a buffer to WASM function, we can pass the buffer address through a parameter. **Attention**: The sandbox will forbid the WASM code to access outside memory, we must **allocate the buffer from WASM instance's own memory space and pass the buffer address in instance's space (not the runtime native address)**. @@ -124,10 +156,10 @@ There are two runtime APIs available for this purpose. * size: the buffer size to allocate */ int32_t -wasm_runtime_module_malloc(wasm_module_inst_t module_inst, +wasm_runtime_module_malloc(wasm_module_inst_t module_inst, uint32_t size, - void **p_native_addr); - + void **p_native_addr); + /* * description: malloc a buffer from instance's private memory space, * and copy the data from another native buffer to it. @@ -137,8 +169,12 @@ wasm_runtime_module_malloc(wasm_module_inst_t module_inst, */ int32 wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, - const char *src, - uint32 size); + const char *src, + uint32 size); + +// free the memory allocated from module memory space +void +wasm_runtime_module_free(wasm_module_inst_t module_inst, int32_t ptr); ``` @@ -154,9 +190,13 @@ if(buffer_for_wasm != 0) { unit32 argv[2]; strncpy(buffer, "hello", 100); // use native address for accessing in runtime - argv[0] = buffer_for_wasm; // pass the buffer address for WASM space. + argv[0] = buffer_for_wasm; // pass the buffer address for WASM space. argv[1] = 100; // the size of buffer wasm_runtime_call_wasm(exec_env, func, 2, argv); + + // it is runtime responsibility to release the memory, + // unless the WASM app will free the passed pointer in its code + wasm_runtime_module_free(module_inst, buffer); } ``` @@ -176,7 +216,7 @@ We can't pass structure data or class objects through the pointer since the memo wasm_runtime_deinstantiate(module_inst); wasm_runtime_unload(module); wasm_runtime_destroy(); - bh_memory_destroy(); + ``` diff --git a/doc/export_native_api.md b/doc/export_native_api.md index 04c914e2d..8b21d4a12 100644 --- a/doc/export_native_api.md +++ b/doc/export_native_api.md @@ -9,7 +9,7 @@ Exporting native API steps #### Step 1: Declare the function interface in WASM app -Create a header file in a WASM app and declare the functions that are exported from native. In this example, we declare foo and foo2 as below in the header file "example.h" +Create a header file in a WASM app and declare the functions that are exported from native. In this example, we declare foo and foo2 as below in the header file `example.h` ```c /*** file name: example.h ***/ @@ -22,7 +22,7 @@ void foo2(char * msg, char * buffer, int buf_len); #### Step 2: Define the native API -Define the native functions which are executed from the WASM app in the runtime source file. The native function can be any name, for example **foo_native** and **foo2** here: +Then we should define the native functions in runtime source tree for handling the calls from the WASM app. The native function can be any name, for example **foo_native** and **foo2** here: ``` C int foo_native(wasm_exec_env_t exec_env , int a, int b) @@ -36,7 +36,7 @@ void foo2(wasm_exec_env_t exec_env, char * msg, uint8 * buffer, int buf_len) } ``` -The first parameter exec_env must be defined using type **wasm_exec_env_t** which is the calling convention for exporting native API by WAMR. +The first parameter exec_env must be defined using type **wasm_exec_env_t** which is the calling convention by WAMR. The rest parameters should be in the same types as the parameters of WASM function foo(), but there are a few special cases that are explained in section "Buffer address conversion and boundary check". Regarding the parameter names, they don't have to be the same, but we would suggest using the same names for easy maintenance. @@ -64,9 +64,7 @@ static NativeSymbol native_symbols[] = } }; -// ensure the memory and runtime initialization is finsihed -// before registering the native functions -bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)); +// initialize the runtime before registering the native functions wasm_runtime_init(); int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); @@ -87,28 +85,30 @@ The function signature field in **NativeSymbol** structure is a string for descr Each letter in the "()" represents a parameter type, and the one following after ")" represents the return value type. The meaning of each letter: -- 'i': i32 -- 'I': i64 -- 'f': f32 -- 'F': f64 -- '*': the parameter is a buffer address in WASM application -- '~': the parameter is the byte length of WASM buffer as referred by preceding argument "\*". It must follow after '*', otherwise, registration will fail -- '$': the parameter is a string in WASM application +- '**i**': i32 +- '**I**': i64 +- '**f**': f32 +- '**F**': f64 +- '**\***': the parameter is a buffer address in WASM application +- '**~**': the parameter is the byte length of WASM buffer as referred by preceding argument "\*". It must follow after '*', otherwise, registration will fail +- '**$**': the parameter is a string in WASM application + +The signature can defined as NULL, then all function parameters are assumed as i32 data type. **Use EXPORT_WASM_API_WITH_SIG** -The above foo2 NativeSymbol element can be also defined with macro EXPORT_WASM_API_WITH_SIG. This macro can be used when the native function name is the same as the WASM symbol name. +The `NativeSymbol` element for `foo2 ` above can be also defined with macro EXPORT_WASM_API_WITH_SIG. This macro can be used when the native function name is the same as the WASM symbol name. ```c static NativeSymbol native_symbols[] = { - EXPORT_WASM_API_WITH_SIG(foo2, "($*~)") + EXPORT_WASM_API_WITH_SIG(foo2, "($*~)") // wasm symbol name will be "foo2" }; ``` ​ -## Call exported API in wasm application +## Call exported API in WASM application Now we can call the exported native API in wasm application like this: ``` C @@ -121,7 +121,7 @@ int main(int argc, char **argv) char * msg = "hello"; char buffer[100]; - int c = foo(a, b); // call into native foo_native() + int c = foo(a, b); // call into native foo_native() foo2(msg, buffer, sizeof(buffer)); // call into native foo2() return 0; @@ -143,6 +143,11 @@ The signature letter '$', '\*' and '\~' help the runtime do automatic address co As function parameters are always passed in 32 bits numbers, you can also use 'i' for the pointer type argument, then you must do all the address conversion and boundary checking in your native function. For example, if you change the foo2 signature to "(iii)", then you will implement the native part as the following sample: ```c +// +// If the function signature used i32 data type ("i") +// for buffer address or string parameters, here +// is how to do address conversation and boundary check manually +// void foo2(wasm_exec_env_t exec_env, uint32 msg_offset, uint32 buffer_offset, diff --git a/doc/port_wamr.md b/doc/port_wamr.md index ed7d4af00..50a6e619f 100644 --- a/doc/port_wamr.md +++ b/doc/port_wamr.md @@ -20,8 +20,6 @@ Create folders: Implement folder core/shared/platform/super-os. Normally in this folder you should implement the following files: - bh_platform.h and bh_platform.c: define the platform related macros, data types and APIs. - bh_assert.c: implement function bh_assert_internal() and bh_debug_internal(). -- bh_definition.c: implement function b_memcpy_s, b_strcat_s and b_strcpy_s. And implement fopen_s - if we need to read wasm file from file system. - bh_platform_log.c: implement function bh_log_emit, bh_fprintf and bh_fflush. - bh_time.c: implement several time related functions. - bh_thread.c: implement thread, mutex, condition related functions. diff --git a/product-mini/platforms/alios-things/aos.mk b/product-mini/platforms/alios-things/aos.mk index 461cb5102..2d82a459b 100644 --- a/product-mini/platforms/alios-things/aos.mk +++ b/product-mini/platforms/alios-things/aos.mk @@ -5,6 +5,9 @@ NAME := iwasm IWASM_ROOT := wamr/core/iwasm SHARED_ROOT := wamr/core/shared +GLOBAL_DEFINES += BH_MALLOC=wasm_runtime_malloc +GLOBAL_DEFINES += BH_FREE=wasm_runtime_free + # Change it to THUMBV7M if you want to build for developerkit WAMR_BUILD_TARGET := X86_32 @@ -71,17 +74,16 @@ GLOBAL_INCLUDES += ${IWASM_ROOT}/aot endif $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/bh_assert.c \ - ${SHARED_ROOT}/platform/alios/bh_definition.c \ ${SHARED_ROOT}/platform/alios/bh_math.c \ ${SHARED_ROOT}/platform/alios/bh_platform.c \ ${SHARED_ROOT}/platform/alios/bh_platform_log.c \ ${SHARED_ROOT}/platform/alios/bh_thread.c \ ${SHARED_ROOT}/platform/alios/bh_time.c \ - ${SHARED_ROOT}/mem-alloc/bh_memory.c \ ${SHARED_ROOT}/mem-alloc/mem_alloc.c \ ${SHARED_ROOT}/mem-alloc/ems/ems_kfc.c \ ${SHARED_ROOT}/mem-alloc/ems/ems_alloc.c \ ${SHARED_ROOT}/mem-alloc/ems/ems_hmu.c \ + ${SHARED_ROOT}/utils/bh_definition.c \ ${SHARED_ROOT}/utils/bh_hashmap.c \ ${SHARED_ROOT}/utils/bh_list.c \ ${SHARED_ROOT}/utils/bh_log.c \ @@ -91,11 +93,12 @@ $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/bh_assert.c \ ${IWASM_ROOT}/common/wasm_runtime_common.c \ ${IWASM_ROOT}/common/wasm_native.c \ ${IWASM_ROOT}/common/wasm_exec_env.c \ + ${IWASM_ROOT}/common/wasm_memory.c \ ${IWASM_ROOT}/common/arch/${INVOKE_NATIVE} \ src/main.c ifeq (${WAMR_BUILD_INTERP}, 1) -$(NAME)_SOURCES += ${IWASM_ROOT}/interpreter/wasm_interp.c \ +$(NAME)_SOURCES += ${IWASM_ROOT}/interpreter/wasm_interp_classic.c \ ${IWASM_ROOT}/interpreter/wasm_loader.c \ ${IWASM_ROOT}/interpreter/wasm_runtime.c endif diff --git a/product-mini/platforms/alios-things/src/main.c b/product-mini/platforms/alios-things/src/main.c index 29bf5f9ba..6c5d322b7 100644 --- a/product-mini/platforms/alios-things/src/main.c +++ b/product-mini/platforms/alios-things/src/main.c @@ -9,7 +9,6 @@ #include "bh_log.h" #include "bh_platform_log.h" #include "wasm_export.h" -#include "bh_memory.h" #include "test_wasm.h" static int app_argc; @@ -48,6 +47,7 @@ void iwasm_main(void *arg1) uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; char error_buf[128]; #if WASM_ENABLE_LOG != 0 int log_verbose_level = 2; @@ -55,15 +55,17 @@ void iwasm_main(void *arg1) (void) arg1; - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - bh_printf("Init global heap failed.\n"); - return; - } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return; + } #if WASM_ENABLE_LOG != 0 bh_log_set_verbose_level(log_verbose_level); @@ -77,14 +79,17 @@ void iwasm_main(void *arg1) if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail2; + goto fail1; } /* instantiate the module */ - if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024, - 8 * 1024, error_buf, sizeof(error_buf)))) { + if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, + 8 * 1024, + 8 * 1024, + error_buf, + sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail3; + goto fail2; } app_instance_main(wasm_module_inst); @@ -92,15 +97,13 @@ void iwasm_main(void *arg1) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); - fail3: +fail2: /* unload the module */ wasm_runtime_unload(wasm_module); - fail2: +fail1: /* destroy runtime environment */ wasm_runtime_destroy(); - - fail1: bh_memory_destroy(); } #define DEFAULT_THREAD_STACKSIZE (6 * 1024) diff --git a/product-mini/platforms/android/wasm-jni.cpp b/product-mini/platforms/android/wasm-jni.cpp index be57aba8a..648f7e54c 100644 --- a/product-mini/platforms/android/wasm-jni.cpp +++ b/product-mini/platforms/android/wasm-jni.cpp @@ -75,27 +75,25 @@ static unsigned char wasm_test_file[] = { 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x extern "C" JNIEXPORT void JNICALL Java_com_intel_wasm_api_Runtime_run(JNIEnv *env, jclass thiz) { - char error_buf[128] = {0}; - - void *(*malloc_func)(size_t) = &malloc; - void (*free_func)(void *) = &free; - LOGI("bh_memory_init_with_allocator"); - if (bh_memory_init_with_allocator((void *) malloc_func, (void *) free_func)) { - LOGI("Init memory with memory allocator failed.\n"); - return; - } - wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; - + RuntimeInitArgs init_args; uint wasm_file_size = 0; uint8_t *wasm_file_buf = NULL; + char error_buf[128] = {0}; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void*)malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void*)realloc; + init_args.mem_alloc_option.allocator.free_func = (void*)free; + + LOGI("wasm_runtime_full_init"); /* initialize runtime environment */ - LOGI("wasm_runtime_init"); - if (!wasm_runtime_init()) { - LOGI("goto fail1\n"); - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + LOGI("Init runtime failed.\n"); + return; } // set log level to INFO @@ -112,8 +110,8 @@ Java_com_intel_wasm_api_Runtime_run(JNIEnv *env, jclass thiz) { if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { LOGI("in wasm_runtime_load %s\n", error_buf); - LOGI("goto fail3\n"); - goto fail3; + LOGI("goto fail1\n"); + goto fail1; } /* instantiate the module */ @@ -124,8 +122,8 @@ Java_com_intel_wasm_api_Runtime_run(JNIEnv *env, jclass thiz) { error_buf, sizeof(error_buf)))) { LOGI("%s\n", error_buf); - LOGI("goto fail4\n"); - goto fail4; + LOGI("goto fail2\n"); + goto fail2; } LOGI("run main() of the application"); @@ -135,23 +133,18 @@ Java_com_intel_wasm_api_Runtime_run(JNIEnv *env, jclass thiz) { LOGI("wasm_runtime_deinstantiate"); wasm_runtime_deinstantiate(wasm_module_inst); - fail4: +fail2: /* unload the module */ LOGI("wasm_runtime_unload"); wasm_runtime_unload(wasm_module); - fail3: +fail1: // in our case, we don't need a free, but it is not a typical one /* free the file buffer */ //bh_free((void *) wasm_file_buf); - fail2: /* destroy runtime environment */ LOGI("wasm_runtime_destroy"); wasm_runtime_destroy(); - - fail1: - LOGI("bh_memory_destroy"); - bh_memory_destroy(); return; } diff --git a/product-mini/platforms/darwin/main.c b/product-mini/platforms/darwin/main.c index 5f0ba1525..24c728862 100644 --- a/product-mini/platforms/darwin/main.c +++ b/product-mini/platforms/darwin/main.c @@ -11,7 +11,6 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include "wasm_export.h" static int app_argc; @@ -24,9 +23,11 @@ static int print_help() bh_printf(" -f|--function name Specify function name to run in module\n" " rather than main\n"); #if WASM_ENABLE_LOG != 0 - bh_printf(" -v=X Set log verbose level (0 to 5, default is 2),\n" + bh_printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" " larger level with more log\n"); #endif + bh_printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + bh_printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); #if WASM_ENABLE_LIBC_WASI != 0 @@ -153,8 +154,10 @@ int main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; + uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 int log_verbose_level = 2; @@ -186,6 +189,16 @@ int main(int argc, char *argv[]) #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; + else if (!strncmp(argv[0], "--stack-size=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + stack_size = atoi(argv[0] + 13); + } + else if (!strncmp(argv[0], "--heap-size=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + heap_size = atoi(argv[0] + 12); + } #if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') @@ -228,35 +241,37 @@ int main(int argc, char *argv[]) app_argc = argc; app_argv = argv; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + #if USE_GLOBAL_HEAP_BUF != 0 - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - bh_printf("Init memory with global heap buffer failed.\n"); - return -1; - } + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); #else - if (bh_memory_init_with_allocator(malloc, free)) { - bh_printf("Init memory with memory allocator failed.\n"); - return -1; - } + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; #endif /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return -1; + } bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, &wasm_file_size))) - goto fail2; + goto fail1; /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail3; + goto fail2; } #if WASM_ENABLE_LIBC_WASI != 0 @@ -269,12 +284,12 @@ int main(int argc, char *argv[]) /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - 64 * 1024, /* stack size */ - 64 * 1024, /* heap size */ + stack_size, + heap_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail4; + goto fail3; } if (is_repl_mode) @@ -287,20 +302,17 @@ int main(int argc, char *argv[]) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); -fail4: +fail3: /* unload the module */ wasm_runtime_unload(wasm_module); -fail3: - /* free the file buffer */ - bh_free(wasm_file_buf); - fail2: - /* destroy runtime environment */ - wasm_runtime_destroy(); + /* free the file buffer */ + wasm_runtime_free(wasm_file_buf); fail1: - bh_memory_destroy(); + /* destroy runtime environment */ + wasm_runtime_destroy(); return 0; } diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 714360ae7..bfa0252e7 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -7,7 +7,6 @@ #include #include "Enclave_t.h" #include "test_wasm.h" -#include "bh_memory.h" #include "wasm_export.h" static char global_heap_buf[2* 1024 * 1024] = { 0 }; @@ -50,17 +49,21 @@ void ecall_iwasm_main() int wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; char error_buf[128]; - if (bh_memory_init_with_pool(global_heap_buf, - sizeof(global_heap_buf)) != 0) { - ocall_print("Init global heap failed.\n"); - return; - } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + ocall_print("Init runtime environment failed."); + ocall_print("\n"); + return; + } /* load WASM byte buffer from byte buffer of include file */ wasm_file_buf = (uint8_t*) wasm_test_file; @@ -71,7 +74,7 @@ void ecall_iwasm_main() error_buf, sizeof(error_buf)))) { ocall_print(error_buf); ocall_print("\n"); - goto fail2; + goto fail1; } /* instantiate the module */ @@ -82,7 +85,7 @@ void ecall_iwasm_main() sizeof(error_buf)))) { ocall_print(error_buf); ocall_print("\n"); - goto fail3; + goto fail2; } /* execute the main function of wasm app */ @@ -91,15 +94,12 @@ void ecall_iwasm_main() /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); -fail3: +fail2: /* unload the module */ wasm_runtime_unload(wasm_module); -fail2: +fail1: /* destroy runtime environment */ wasm_runtime_destroy(); - -fail1: - bh_memory_destroy(); } diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 193d9ec0e..2b5a3e1dd 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -52,6 +52,11 @@ if (NOT DEFINED WAMR_BUILD_LIBC_WASI) set (WAMR_BUILD_LIBC_WASI 1) endif () +if (NOT DEFINED WAMR_BUILD_FAST_INTERP) + # Enable fast interpreter + set (WAMR_BUILD_FAST_INTERP 1) +endif () + set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) diff --git a/product-mini/platforms/linux/build_llvm.sh b/product-mini/platforms/linux/build_llvm.sh index d58579264..29c5e5058 100755 --- a/product-mini/platforms/linux/build_llvm.sh +++ b/product-mini/platforms/linux/build_llvm.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2020 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception DEPS_DIR=${PWD}/../../../core/deps @@ -8,7 +8,7 @@ DEPS_DIR=${PWD}/../../../core/deps cd ${DEPS_DIR} if [ ! -d "llvm" ]; then echo "Clone llvm to core/deps/ .." - git clone https://github.com/llvm-mirror/llvm.git + git clone --depth 1 https://github.com/llvm-mirror/llvm.git fi cd llvm diff --git a/product-mini/platforms/linux/main.c b/product-mini/platforms/linux/main.c index 5f0ba1525..24c728862 100644 --- a/product-mini/platforms/linux/main.c +++ b/product-mini/platforms/linux/main.c @@ -11,7 +11,6 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include "wasm_export.h" static int app_argc; @@ -24,9 +23,11 @@ static int print_help() bh_printf(" -f|--function name Specify function name to run in module\n" " rather than main\n"); #if WASM_ENABLE_LOG != 0 - bh_printf(" -v=X Set log verbose level (0 to 5, default is 2),\n" + bh_printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" " larger level with more log\n"); #endif + bh_printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + bh_printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); #if WASM_ENABLE_LIBC_WASI != 0 @@ -153,8 +154,10 @@ int main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; + uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 int log_verbose_level = 2; @@ -186,6 +189,16 @@ int main(int argc, char *argv[]) #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; + else if (!strncmp(argv[0], "--stack-size=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + stack_size = atoi(argv[0] + 13); + } + else if (!strncmp(argv[0], "--heap-size=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + heap_size = atoi(argv[0] + 12); + } #if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') @@ -228,35 +241,37 @@ int main(int argc, char *argv[]) app_argc = argc; app_argv = argv; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + #if USE_GLOBAL_HEAP_BUF != 0 - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - bh_printf("Init memory with global heap buffer failed.\n"); - return -1; - } + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); #else - if (bh_memory_init_with_allocator(malloc, free)) { - bh_printf("Init memory with memory allocator failed.\n"); - return -1; - } + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; #endif /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return -1; + } bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, &wasm_file_size))) - goto fail2; + goto fail1; /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail3; + goto fail2; } #if WASM_ENABLE_LIBC_WASI != 0 @@ -269,12 +284,12 @@ int main(int argc, char *argv[]) /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - 64 * 1024, /* stack size */ - 64 * 1024, /* heap size */ + stack_size, + heap_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail4; + goto fail3; } if (is_repl_mode) @@ -287,20 +302,17 @@ int main(int argc, char *argv[]) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); -fail4: +fail3: /* unload the module */ wasm_runtime_unload(wasm_module); -fail3: - /* free the file buffer */ - bh_free(wasm_file_buf); - fail2: - /* destroy runtime environment */ - wasm_runtime_destroy(); + /* free the file buffer */ + wasm_runtime_free(wasm_file_buf); fail1: - bh_memory_destroy(); + /* destroy runtime environment */ + wasm_runtime_destroy(); return 0; } diff --git a/product-mini/platforms/vxworks/main.c b/product-mini/platforms/vxworks/main.c index 5f0ba1525..24c728862 100644 --- a/product-mini/platforms/vxworks/main.c +++ b/product-mini/platforms/vxworks/main.c @@ -11,7 +11,6 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include "wasm_export.h" static int app_argc; @@ -24,9 +23,11 @@ static int print_help() bh_printf(" -f|--function name Specify function name to run in module\n" " rather than main\n"); #if WASM_ENABLE_LOG != 0 - bh_printf(" -v=X Set log verbose level (0 to 5, default is 2),\n" + bh_printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" " larger level with more log\n"); #endif + bh_printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + bh_printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); #if WASM_ENABLE_LIBC_WASI != 0 @@ -153,8 +154,10 @@ int main(int argc, char *argv[]) const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; + uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 int log_verbose_level = 2; @@ -186,6 +189,16 @@ int main(int argc, char *argv[]) #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; + else if (!strncmp(argv[0], "--stack-size=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + stack_size = atoi(argv[0] + 13); + } + else if (!strncmp(argv[0], "--heap-size=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + heap_size = atoi(argv[0] + 12); + } #if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') @@ -228,35 +241,37 @@ int main(int argc, char *argv[]) app_argc = argc; app_argv = argv; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + #if USE_GLOBAL_HEAP_BUF != 0 - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - bh_printf("Init memory with global heap buffer failed.\n"); - return -1; - } + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); #else - if (bh_memory_init_with_allocator(malloc, free)) { - bh_printf("Init memory with memory allocator failed.\n"); - return -1; - } + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; #endif /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return -1; + } bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, &wasm_file_size))) - goto fail2; + goto fail1; /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail3; + goto fail2; } #if WASM_ENABLE_LIBC_WASI != 0 @@ -269,12 +284,12 @@ int main(int argc, char *argv[]) /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - 64 * 1024, /* stack size */ - 64 * 1024, /* heap size */ + stack_size, + heap_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail4; + goto fail3; } if (is_repl_mode) @@ -287,20 +302,17 @@ int main(int argc, char *argv[]) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); -fail4: +fail3: /* unload the module */ wasm_runtime_unload(wasm_module); -fail3: - /* free the file buffer */ - bh_free(wasm_file_buf); - fail2: - /* destroy runtime environment */ - wasm_runtime_destroy(); + /* free the file buffer */ + wasm_runtime_free(wasm_file_buf); fail1: - bh_memory_destroy(); + /* destroy runtime environment */ + wasm_runtime_destroy(); return 0; } diff --git a/product-mini/platforms/zephyr/simple/build.sh b/product-mini/platforms/zephyr/simple/build.sh new file mode 100755 index 000000000..32a2c4000 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/build.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +X86_TARGET="x86" +STM32_TARGET="stm32" + +if [ $# != 1 ] ; then + echo "USAGE:" + echo "$0 $X86_TARGET|$STM32_TARGET" + echo "Example:" + echo " $0 $X86_TARGET" + echo " $0 $STM32_TARGET" + exit 1 +fi + +TARGET=$1 + +if [ "$TARGET" = "$X86_TARGET" ] ; then + cp prj_qemu_x86_nommu.conf prj.conf + rm -fr build && mkdir build && cd build + cmake -GNinja -DBOARD=qemu_x86_nommu -DWAMR_BUILD_TARGET=X86_32 .. + ninja + ninja run +elif [ "$TARGET" = "$STM32_TARGET" ] ; then + cp prj_nucleo767zi.conf prj.conf + rm -fr build && mkdir build && cd build + cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 .. + ninja + ninja flash +else + echo "unsupported target: $TARGET" + exit 1 +fi diff --git a/product-mini/platforms/zephyr/simple/prj.conf b/product-mini/platforms/zephyr/simple/prj.conf deleted file mode 100644 index 96db21f20..000000000 --- a/product-mini/platforms/zephyr/simple/prj.conf +++ /dev/null @@ -1,5 +0,0 @@ -# set CONFIG_ARM_MPU=y if run in ARM's board -# CONFIG_ARM_MPU is not set -CONFIG_STACK_SENTINEL=y -CONFIG_PRINTK=y -CONFIG_LOG=y diff --git a/core/shared/platform/zephyr/Makefile b/product-mini/platforms/zephyr/simple/prj_nucleo767zi.conf similarity index 57% rename from core/shared/platform/zephyr/Makefile rename to product-mini/platforms/zephyr/simple/prj_nucleo767zi.conf index c1520f363..c495644b7 100644 --- a/core/shared/platform/zephyr/Makefile +++ b/product-mini/platforms/zephyr/simple/prj_nucleo767zi.conf @@ -1,4 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -obj-y += bh_assert.o bh_definition.o bh_memory.o bh_platform_log.o bh_thread.o bh_time.o +CONFIG_ARM_MPU=y +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y diff --git a/core/shared/platform/Makefile b/product-mini/platforms/zephyr/simple/prj_qemu_x86_nommu.conf similarity index 69% rename from core/shared/platform/Makefile rename to product-mini/platforms/zephyr/simple/prj_qemu_x86_nommu.conf index cd10597a1..7f4a32832 100644 --- a/core/shared/platform/Makefile +++ b/product-mini/platforms/zephyr/simple/prj_qemu_x86_nommu.conf @@ -1,4 +1,6 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -obj-y += zephyr/ +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y diff --git a/product-mini/platforms/zephyr/simple/src/main.c b/product-mini/platforms/zephyr/simple/src/main.c index add1c24b5..078b3d811 100644 --- a/product-mini/platforms/zephyr/simple/src/main.c +++ b/product-mini/platforms/zephyr/simple/src/main.c @@ -8,7 +8,6 @@ #include "bh_platform.h" #include "bh_assert.h" #include "bh_log.h" -#include "bh_memory.h" #include "wasm_export.h" #include "test_wasm.h" @@ -63,6 +62,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; char error_buf[128]; #if WASM_ENABLE_LOG != 0 int log_verbose_level = 2; @@ -72,15 +72,17 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) (void) arg2; (void) arg3; - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - bh_printf("Init global heap failed.\n"); - return; - } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return; + } #if WASM_ENABLE_LOG != 0 bh_log_set_verbose_level(log_verbose_level); @@ -94,7 +96,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail2; + goto fail1; } /* instantiate the module */ @@ -104,7 +106,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail3; + goto fail2; } /* invoke the main function */ @@ -113,16 +115,14 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); - fail3: +fail2: /* unload the module */ wasm_runtime_unload(wasm_module); - fail2: +fail1: /* destroy runtime environment */ wasm_runtime_destroy(); - fail1: bh_memory_destroy(); - end = k_uptime_get_32(); printf("elpase: %d\n", (end - start)); diff --git a/samples/gui/README.md b/samples/gui/README.md index 09cdc18fb..b9e589ba1 100644 --- a/samples/gui/README.md +++ b/samples/gui/README.md @@ -117,4 +117,4 @@ First, connect PC and STM32 with UART. Then install to use host_tool.
The graphic user interface demo photo: -![WAMR samples diagram](../../doc/pics/vgl_demo.png "WAMR samples diagram") \ No newline at end of file +![WAMR samples diagram](../../doc/pics/vgl_demo.png "WAMR samples diagram") diff --git a/samples/gui/lv_config/lv_conf.h b/samples/gui/lv_config/lv_conf.h index e0caf37ab..5c46d7e83 100644 --- a/samples/gui/lv_config/lv_conf.h +++ b/samples/gui/lv_config/lv_conf.h @@ -84,9 +84,9 @@ typedef int16_t lv_coord_t; /* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ # define LV_MEM_AUTO_DEFRAG 1 #else /*LV_MEM_CUSTOM*/ -# define LV_MEM_CUSTOM_INCLUDE "bh_memory.h" /*Header for the dynamic memory function*/ -# define LV_MEM_CUSTOM_ALLOC bh_malloc /*Wrapper to malloc*/ -# define LV_MEM_CUSTOM_FREE bh_free /*Wrapper to free*/ +# define LV_MEM_CUSTOM_INCLUDE "bh_config.h" /*Header for the dynamic memory function*/ +# define LV_MEM_CUSTOM_ALLOC BH_MALLOC /*Wrapper to malloc*/ +# define LV_MEM_CUSTOM_FREE BH_FREE /*Wrapper to free*/ #endif /*LV_MEM_CUSTOM*/ /* Garbage Collector settings diff --git a/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c b/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c index b3b324d5d..38e121248 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c @@ -27,7 +27,6 @@ #include "bh_common.h" #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -466,19 +465,22 @@ static void hal_init(void) // Driver function int iwasm_main(int argc, char *argv[]) { + RuntimeInitArgs init_args; korp_thread tid; if (!parse_args(argc, argv)) return -1; - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - printf("Init global heap failed.\n"); - return -1; - } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); - if (vm_thread_sys_init() != 0) { - goto fail1; + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return -1; } if (!init_connection_framework()) { @@ -513,7 +515,6 @@ int iwasm_main(int argc, char *argv[]) exit_connection_framework(); fail1: - bh_memory_destroy(); - + wasm_runtime_destroy(); return -1; } diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c index af8d4d7ba..41edfe0aa 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c @@ -10,7 +10,6 @@ #include "bh_common.h" #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -146,16 +145,19 @@ static void hal_init(void) int iwasm_main() { + RuntimeInitArgs init_args; host_init(); - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - printf("Init global heap failed.\n"); - return -1; - } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); - if (vm_thread_sys_init() != 0) { - goto fail1; + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return -1; } wgl_init(); @@ -167,7 +169,6 @@ int iwasm_main() // TODO: app_manager_startup(&interface); -fail1: - bh_memory_destroy(); + wasm_runtime_destroy(); return -1; } diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c index 74e007e97..612259044 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c @@ -10,7 +10,6 @@ #include "bh_log.h" #include "bh_platform_log.h" #include "wasm_export.h" -#include "bh_memory.h" extern int iwasm_main(); diff --git a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt index 2ff88b002..005358c72 100644 --- a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt @@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr") enable_language (ASM) +add_definitions(-DWA_MALLOC=wasm_runtime_malloc) +add_definitions(-DWA_FREE=wasm_runtime_free) + # Build as THUMB by default # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS" or "XTENSA" # if we want to support arm_32, x86, mips or xtensa @@ -17,7 +20,6 @@ if (NOT DEFINED WAMR_BUILD_TARGET) set (WAMR_BUILD_TARGET "THUMBV7") endif () - if (NOT DEFINED WAMR_BUILD_INTERP) # Enable Interpreter by default set (WAMR_BUILD_INTERP 1) diff --git a/samples/littlevgl/README.md b/samples/littlevgl/README.md index bb41a27fb..6d5b62595 100644 --- a/samples/littlevgl/README.md +++ b/samples/littlevgl/README.md @@ -68,28 +68,46 @@ Build and Run Test on Zephyr ================================ We can use a STM32 NUCLEO_F767ZI board with ILI9341 display and XPT2046 touch screen to run the test. Then use host_tool to remotely install wasm app into STM32. -- Build WASM VM into Zephyr system
- a. clone zephyr source code
-Refer to Zephyr getting started.
-https://docs.zephyrproject.org/latest/getting_started/index.html
-`west init zephyrproject`
-`cd zephyrproject`
-`west update`
- b. copy samples
- `cd zephyr/samples/`
- `cp -a samples/littlevgl/vgl-wasm-runtime vgl-wasm-runtime`
- `cd vgl-wasm-runtime/zephyr_build`
- c. create a link to wamr root dir
- ` ln -s wamr`
- d. build source code
- Since ui_app incorporated LittlevGL source code, so it needs more RAM on the device to install the application. - It is recommended that RAM SIZE not less than 380KB. - In our test use nucleo_f767zi, which is supported by Zephyr. +- Build WASM VM into Zephyr system + a. clone zephyr source code + Refer to Zephyr getting started. + https://docs.zephyrproject.org/latest/getting_started/index.html - `mkdir build && cd build`
- `source ../../../../zephyr-env.sh`
- `cmake -GNinja -DBOARD=nucleo_f767zi ..`
- ` ninja flash`
+ ```bash + west init zephyrproject + cd zephyrproject + west update + ``` + + b. copy samples + ```bash + cd zephyr/samples/ + cp -a samples/littlevgl/vgl-wasm-runtime vgl-wasm-runtime + cd vgl-wasm-runtime/zephyr_build + ``` + c. create a link to wamr root dir + ```bash + ln -s wamr + ``` + + d. build source code + Since ui_app incorporated LittlevGL source code, so it needs more RAM on the device to install the application. It is recommended that RAM SIZE not less than 380KB. In our test use nucleo_f767zi, which is supported by Zephyr. Since the littlevgl wasm app is quite big (~100KB in wasm format and ~200KB in AOT format ), there isn't enough SRAM to build interpreter and AOT together. You can only choose one of them: + + - Interpreter + ``` Bash + mkdir build && cd build + source ../../../../zephyr-env.sh + cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 .. + ninja flash + ``` + + - AOT + ``` Bash + mkdir build && cd build + source ../../../../zephyr-env.sh + cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 .. + ninja flash + ``` - Hardware Connections diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c index 18ad0331a..83f72c5c4 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c @@ -27,7 +27,6 @@ #include "bh_common.h" #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -448,8 +447,6 @@ static bool parse_args(int argc, char *argv[]) } static NativeSymbol native_symbols[] = { - #include "runtime_sensor.inl" - #include "connection.inl" EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)"), EXPORT_WASM_API_WITH_SIG(display_fill, "(iiii*)"), @@ -461,29 +458,29 @@ static NativeSymbol native_symbols[] = { // Driver function int iwasm_main(int argc, char *argv[]) { + RuntimeInitArgs init_args; korp_thread tid; uint32 n_native_symbols; if (!parse_args(argc, argv)) return -1; - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - printf("Init global heap failed.\n"); + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + init_args.native_module_name = "env"; + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_symbols = native_symbols; + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); return -1; } - if (vm_thread_sys_init() != 0) { - goto fail1; - } - - /* Register native functions */ - n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); - if (!wasm_runtime_register_natives("env", - native_symbols, n_native_symbols)) { - goto fail1; - } - if (!init_connection_framework()) { vm_thread_sys_destroy(); goto fail1; @@ -514,7 +511,7 @@ int iwasm_main(int argc, char *argv[]) exit_connection_framework(); fail1: - bh_memory_destroy(); + wasm_runtime_destroy(); return -1; } diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c index a9639dc20..cb140306a 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c @@ -10,7 +10,6 @@ #include "bh_common.h" #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -80,8 +79,6 @@ timer_ctx_t timer_ctx; static char global_heap_buf[370 * 1024] = { 0 }; static NativeSymbol native_symbols[] = { - #include "runtime_sensor.inl" - #include "connection.inl" EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)"), EXPORT_WASM_API_WITH_SIG(display_fill, "(iiii*)"), @@ -92,28 +89,28 @@ static NativeSymbol native_symbols[] = { int iwasm_main() { + RuntimeInitArgs init_args; korp_thread tid, tm_tid; uint32 n_native_symbols; host_init(); - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { - printf("Init global heap failed.\n"); + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + init_args.native_module_name = "env"; + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_symbols = native_symbols; + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); return -1; } - if (vm_thread_sys_init() != 0) { - goto fail1; - } - - /* Register native functions */ - n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); - if (!wasm_runtime_register_natives("env", - native_symbols, n_native_symbols)) { - goto fail1; - } - display_init(); // timer manager @@ -122,7 +119,6 @@ int iwasm_main() // TODO: app_manager_startup(&interface); -fail1: - bh_memory_destroy(); + wasm_runtime_destroy(); return -1; } diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c index 231073fa5..c12fbe632 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c @@ -10,9 +10,10 @@ #include "bh_log.h" #include "bh_platform_log.h" #include "wasm_export.h" -#include "bh_memory.h" + extern void display_init(void); extern int iwasm_main(); + void main(void) { display_init(); diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt index 7458080d2..723ff8fa9 100644 --- a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt @@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr") enable_language (ASM) +add_definitions(-DWA_MALLOC=wasm_runtime_malloc) +add_definitions(-DWA_FREE=wasm_runtime_free) + # Build as THUMB by default # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS_32" or "XTENSA_32" # if we want to support arm_32, x86, mips or xtensa diff --git a/samples/simple/src/iwasm_main.c b/samples/simple/src/iwasm_main.c index e9b389d21..98caa655f 100644 --- a/samples/simple/src/iwasm_main.c +++ b/samples/simple/src/iwasm_main.c @@ -27,7 +27,6 @@ #include "bh_common.h" #include "bh_queue.h" #include "bh_thread.h" -#include "bh_memory.h" #include "runtime_sensor.h" #include "bi-inc/attr_container.h" #include "module_wasm_app.h" @@ -462,54 +461,50 @@ static bool parse_args(int argc, char *argv[]) // Driver function int iwasm_main(int argc, char *argv[]) { + RuntimeInitArgs init_args; korp_thread tid; if (!parse_args(argc, argv)) return -1; -#if 1 - if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + +#if USE_GLOBAL_HEAP_BUF != 0 + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); #else - if (bh_memory_init_with_allocator(malloc, free) + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; #endif - != 0) { - printf("Init global heap failed.\n"); + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); return -1; } - if (vm_thread_sys_init() != 0) { - goto fail1; - } - - // - // timer manager - // + /* timer manager */ init_wasm_timer(); - - // - // connection framework - // + /* connection framework */ if (!init_connection_framework()) { - vm_thread_sys_destroy(); goto fail1; } - // - // sensor framework - // + /* sensor framework */ init_sensor_framework(); // add the sys sensor objects add_sys_sensor("sensor_test", - "This is a sensor for test", - 0, - 1000, - read_test_sensor, + "This is a sensor for test", + 0, + 1000, + read_test_sensor, config_test_sensor); start_sensor_framework(); - - #ifndef CONNECTION_UART if (server_mode) vm_thread_create(&tid, func_server_mode, NULL, @@ -527,7 +522,7 @@ int iwasm_main(int argc, char *argv[]) exit_connection_framework(); fail1: - bh_memory_destroy(); + wasm_runtime_destroy(); return -1; } diff --git a/test-tools/host-tool/CMakeLists.txt b/test-tools/host-tool/CMakeLists.txt index e5d3ce0f8..e45b4de50 100644 --- a/test-tools/host-tool/CMakeLists.txt +++ b/test-tools/host-tool/CMakeLists.txt @@ -50,7 +50,6 @@ SET(SOURCES ${HOST_TOOL_SRC} ${PLATFORM_SHARED_SOURCE} ${UTILS_SHARED_SOURCE} - ${MEM_ALLOC_DIR}/bh_memory.c ${NATIVE_INTERFACE_SOURCE} ${CJSON_SOURCE} ${LIB_HOST_AGENT_SOURCE} diff --git a/test-tools/host-tool/src/host_tool_utils.c b/test-tools/host-tool/src/host_tool_utils.c index 17084da99..1444715b0 100644 --- a/test-tools/host-tool/src/host_tool_utils.c +++ b/test-tools/host-tool/src/host_tool_utils.c @@ -23,10 +23,14 @@ typedef union jvalue { double d; } jvalue; +#ifndef bh_memcpy_s +int b_memcpy_s(void * s1, unsigned int s1max, + const void * s2, unsigned int n); #define bh_memcpy_s(dest, dlen, src, slen) do { \ int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \ (void)_ret; \ } while (0) +#endif static inline int16_t get_int16(const char *buf) { diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 8143f38ba..39f82abda 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -5,7 +5,6 @@ #include #include "bh_platform.h" -#include "bh_memory.h" #include "bh_assert.h" #include "bh_log.h" #include "wasm_export.h" @@ -52,6 +51,7 @@ main(int argc, char *argv[]) wasm_module_t wasm_module = NULL; aot_comp_data_t comp_data = NULL; aot_comp_context_t comp_ctx = NULL; + RuntimeInitArgs init_args; AOTCompOption option = { 0 }; char error_buf[128]; int log_verbose_level = 2; @@ -134,43 +134,47 @@ main(int argc, char *argv[]) wasm_file_name = argv[0]; - if (bh_memory_init_with_allocator(malloc, free)) { - bh_printf("Init memory with memory allocator failed.\n"); - return -1; - } + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; /* initialize runtime environment */ - if (!wasm_runtime_init()) - goto fail1; + if (!wasm_runtime_full_init(&init_args)) { + bh_printf("Init runtime environment failed.\n"); + return -1; + } bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file = (uint8*) bh_read_file_to_buffer(wasm_file_name, &wasm_file_size))) - goto fail2; + goto fail1; /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file, wasm_file_size, error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf); - goto fail3; + goto fail2; } if (!(comp_data = aot_create_comp_data(wasm_module))) { bh_printf("%s\n", aot_get_last_error()); - goto fail4; + goto fail3; } if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) { bh_printf("%s\n", aot_get_last_error()); - goto fail5; + goto fail4; } if (!aot_compile_wasm(comp_ctx)) { bh_printf("%s\n", aot_get_last_error()); - goto fail6; + goto fail5; } switch (option.output_format) { @@ -178,19 +182,19 @@ main(int argc, char *argv[]) case AOT_LLVMIR_OPT_FILE: if (!aot_emit_llvm_file(comp_ctx, out_file_name)) { bh_printf("%s\n", aot_get_last_error()); - goto fail6; + goto fail5; } break; case AOT_OBJECT_FILE: if (!aot_emit_object_file(comp_ctx, out_file_name)) { bh_printf("%s\n", aot_get_last_error()); - goto fail6; + goto fail5; } break; case AOT_FORMAT_FILE: if (!aot_emit_aot_file(comp_ctx, comp_data, out_file_name)) { bh_printf("%s\n", aot_get_last_error()); - goto fail6; + goto fail5; } break; default: @@ -199,29 +203,25 @@ main(int argc, char *argv[]) bh_printf("Compile success, file %s was generated.\n", out_file_name); -fail6: +fail5: /* Destroy compiler context */ aot_destroy_comp_context(comp_ctx); -fail5: +fail4: /* Destroy compile data */ aot_destroy_comp_data(comp_data); -fail4: +fail3: /* Unload WASM module */ wasm_runtime_unload(wasm_module); -fail3: - /* free the file buffer */ - bh_free(wasm_file); - fail2: - /* Destroy runtime environment */ - wasm_runtime_destroy(); + /* free the file buffer */ + wasm_runtime_free(wasm_file); fail1: - bh_memory_destroy(); - + /* Destroy runtime environment */ + wasm_runtime_destroy(); return 0; } diff --git a/wamr-sdk/runtime/CMakeLists.txt b/wamr-sdk/runtime/CMakeLists.txt index 676daf56a..a6d47db83 100644 --- a/wamr-sdk/runtime/CMakeLists.txt +++ b/wamr-sdk/runtime/CMakeLists.txt @@ -7,6 +7,10 @@ project(runtime-sdk) SET (CMAKE_C_FLAGS "-O3") set (CMAKE_BUILD_TYPE Release) +add_definitions(-DBH_MALLOC=wasm_runtime_malloc) +add_definitions(-DBH_FREE=wasm_runtime_free) +add_definitions(-DWA_MALLOC=wasm_runtime_malloc) +add_definitions(-DWA_FREE=wasm_runtime_free) if (NOT DEFINED WAMR_BUILD_SDK_PROFILE) set (WAMR_BUILD_SDK_PROFILE "default")