Merge pull request #4 from bytecodealliance/master

sync up with upstream
This commit is contained in:
Wang Xin 2020-04-11 09:10:10 +08:00 committed by GitHub
commit d02d772def
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
284 changed files with 9519 additions and 9736 deletions

8
.gitignore vendored
View File

@ -1,2 +1,10 @@
.vscode
**/*build/
core/deps/lv_drivers
core/deps/llvm
core/deps/lvgl
core/shared/mem-alloc/tlsf
wamr-sdk/out/
wamr-sdk/runtime/build_runtime_sdk/
test-tools/host-tool/bin/

View File

@ -28,12 +28,16 @@ iwasm VM core
- [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)
### Performance and memory usage
The WAMR performance, footprint and memory usage data are available at the [performance](../../wiki/Performance) wiki page.
### Supported architectures and platforms
The iwasm supports the following architectures:
- X86-64, X86-32
- ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested)
- AArch64 (Cortex-A57 and Cortex-A53 are tested)
- MIPS
- XTENSA
@ -49,7 +53,7 @@ Execute following commands to build **wamrc** compiler:
```shell
cd wamr-compiler
./build_llvm.sh
./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target)
mkdir build && cd build
cmake ..
make
@ -96,7 +100,9 @@ The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly.
Samples
=================
The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components.
The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components.
- [**Basic**](./samples/basic): Demonstrating how host runtime calls WASM function as well as WASM function calls native function.
- **[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.

129
_clang-format Normal file
View File

@ -0,0 +1,129 @@
---
BasedOnStyle: Mozilla
IndentWidth: 4
---
Language: Cpp
AlignConsecutiveMacros: true
AllowShortBlocksOnASingleLine: true
BinPackArguments: true
BinPackParameters: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
AfterExternBlock: true
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: false
SplitEmptyNamespace: true
ColumnLimit: 79
DerivePointerAlignment: false
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 1
- Regex: ".*"
Priority: 3
PointerAlignment: Right
ReflowComments: false
Standard: Cpp03
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
# AccessModifierOffset: -2
# AlignAfterOpenBracket: Align
# AlignConsecutiveAssignments: false
# AlignConsecutiveDeclarations: false
# AlignEscapedNewlines: Right
# AlignOperands: true
# AlignTrailingComments: true
# AllowAllArgumentsOnNextLine: true
# AllowAllConstructorInitializersOnNextLine: true
# AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortCaseLabelsOnASingleLine: false
# AllowShortFunctionsOnASingleLine: Inline
# AllowShortLambdasOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: TopLevel
# AlwaysBreakAfterReturnType: TopLevel
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: Yes
# BreakBeforeBinaryOperators: None
# BreakBeforeInheritanceComma: false
# BreakInheritanceList: BeforeComma
# BreakBeforeTernaryOperators: true
# BreakConstructorInitializersBeforeComma: false
# BreakConstructorInitializers: BeforeComma
# BreakAfterJavaFieldAnnotations: false
# BreakStringLiterals: true
# CommentPragmas: '^ IWYU pragma:'
# CompactNamespaces: false
# ConstructorInitializerAllOnOneLineOrOnePerLine: false
# ConstructorInitializerIndentWidth: 2
# ContinuationIndentWidth: 2
# Cpp11BracedListStyle: false
# DisableFormat: false
# ExperimentalAutoDetectBinPacking: false
# FixNamespaceComments: false
# ForEachMacros:
# - foreach
# - Q_FOREACH
# - BOOST_FOREACH
# IncludeIsMainRegex: '(Test)?$'
# IndentCaseLabels: true
# IndentPPDirectives: None
# IndentWrappedFunctionNames: false
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
# KeepEmptyLinesAtTheStartOfBlocks: true
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
# NamespaceIndentation: None
# ObjCBinPackProtocolList: Auto
# ObjCBlockIndentWidth: 2
# ObjCSpaceAfterProperty: true
# ObjCSpaceBeforeProtocolList: false
# PenaltyBreakAssignment: 2
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 200
# SortIncludes: true
# SortUsingDeclarations: true
# SpaceAfterCStyleCast: false
# SpaceAfterLogicalNot: false
# SpaceAfterTemplateKeyword: false
# SpaceBeforeAssignmentOperators: true
# SpaceBeforeCpp11BracedList: false
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# SpaceBeforeParens: ControlStatements
# SpaceBeforeRangeBasedForLoopColon: true
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
# TabWidth: 4
# UseTab: Never
# ...

View File

@ -5,11 +5,11 @@
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize",
"build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize",
"build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize",
"build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize",
"build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize",
"build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize --use abort=",
"build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize --use abort=",
"build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize --use abort=",
"build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize --use abort=",
"build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize --use abort=",
"build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher"
},
"author": "",

View File

@ -3,13 +3,13 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
@external("env", "printf")
@external("env", "puts")
declare function printf(a: ArrayBuffer): i32;
export function log(a: string): void {
printf(String.UTF8.encode(a + '\n', true));
printf(String.UTF8.encode(a, true));
}
export function log_number(a: number): void {
printf(String.UTF8.encode(a.toString() + '\n'));
printf(String.UTF8.encode(a.toString()));
}

View File

@ -3,24 +3,6 @@
string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET)
# Add definitions for the build platform
if (WAMR_BUILD_PLATFORM STREQUAL "linux")
add_definitions(-DBH_PLATFORM_LINUX)
elseif (WAMR_BUILD_PLATFORM STREQUAL "linux-sgx")
add_definitions(-DBH_PLATFORM_LINUX_SGX)
elseif (WAMR_BUILD_PLATFORM STREQUAL "zephyr")
add_definitions(-DBH_PLATFORM_ZEPHYR)
elseif (WAMR_BUILD_PLATFORM STREQUAL "vxworks")
add_definitions(-DBH_PLATFORM_VXWORKS)
elseif (WAMR_BUILD_PLATFORM STREQUAL "darwin")
add_definitions(-DBH_PLATFORM_DARWIN)
elseif (WAMR_BUILD_PLATFORM STREQUAL "alios-things")
add_definitions(-DBH_PLATFORM_ALIOS_THINGS)
elseif (WAMR_BUILD_PLATFORM STREQUAL "android")
add_definitions(-DBH_PLATFORM_ANDROID)
else ()
message (WARNING "-- WAMR build platform isn't set")
endif ()
# Add definitions for the build target
if (WAMR_BUILD_TARGET STREQUAL "X86_64")
@ -45,6 +27,9 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
add_definitions(-DBUILD_TARGET_THUMB)
add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
endif ()
elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
add_definitions(-DBUILD_TARGET_AARCH64)
add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
add_definitions(-DBUILD_TARGET_MIPS)
elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
@ -53,8 +38,12 @@ else ()
message (FATAL_ERROR "-- WAMR build target isn't set")
endif ()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DBH_DEBUG=1)
endif ()
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
# Add -fPIC flag if build as 64-bit
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
@ -105,33 +94,33 @@ message (" CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE})
if (WAMR_BUILD_INTERP EQUAL 1)
message (" WAMR Interpreter enabled")
else ()
message (" WAMR Interpreter disbled")
message (" WAMR Interpreter disabled")
endif ()
if (WAMR_BUILD_AOT EQUAL 1)
message (" WAMR AOT enabled")
else ()
message (" WAMR AOT disbled")
message (" WAMR AOT disabled")
endif ()
if (WAMR_BUILD_JIT EQUAL 1)
message (" WAMR JIT enabled")
else ()
message (" WAMR JIT disbled")
message (" WAMR JIT disabled")
endif ()
if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
message (" Libc builtin enabled")
else ()
message (" Libc builtin disbled")
message (" Libc builtin disabled")
endif ()
if (WAMR_BUILD_LIBC_WASI EQUAL 1)
message (" Libc WASI enabled")
else ()
message (" Libc WASI disbled")
message (" Libc WASI disabled")
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")
message (" Fast interpreter disabled")
endif ()

View File

@ -31,7 +31,7 @@ endif ()
# Set default options
# Set WAMR_BUILD_TARGET, currently values supported:
# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
if (NOT DEFINED WAMR_BUILD_TARGET)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
# Build as X86_64 by default in 64-bit platform

View File

@ -16,14 +16,7 @@ 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)
{

View File

@ -9,30 +9,6 @@
/* Note: the bh_plaform.h is the only head file separately
implemented by both [app] and [native] worlds */
#include "bh_platform.h"
#include "wasm_export.h"
#define get_module_inst(exec_env) \
wasm_runtime_get_module_inst(exec_env)
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, size)
#define validate_app_str_addr(offset) \
wasm_runtime_validate_app_str_addr(module_inst, offset)
#define addr_app_to_native(offset) \
wasm_runtime_addr_app_to_native(module_inst, offset)
#define addr_native_to_app(ptr) \
wasm_runtime_addr_native_to_app(module_inst, ptr)
#define module_malloc(size, p_native_addr) \
wasm_runtime_module_malloc(module_inst, size, p_native_addr)
#define module_free(offset) \
wasm_runtime_module_free(module_inst, offset)
/*char *wa_strdup(const char *);*/
#endif /* end of _NATIVE_INTERFACE_H */

View File

@ -79,23 +79,3 @@ char *wa_strdup(const char *s)
memcpy(s1, s, strlen(s) + 1);
return s1;
}
#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;
}

View File

@ -35,14 +35,14 @@ typedef int int32;
#define WA_FREE free
#endif
char *wa_strdup(const char *s);
uint32 htonl(uint32 value);
uint32 ntohl(uint32 value);
uint16 htons(uint16 value);
uint16 ntohs(uint16 value);
int
b_memcpy_s(void * s1, unsigned int s1max, const void * s2, unsigned int n);
// We are not worried for the WASM world since the sandbox will catch it.
#define bh_memcpy_s(dst, dst_len, src, src_len) memcpy(dst, src, src_len)
#endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */

View File

@ -3,12 +3,9 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "runtime_timer.h"
#include "bh_platform.h"
#include "app_manager_export.h"
#include "module_wasm_app.h"
#include "bh_list.h"
#include "bh_thread.h"
#include "bh_time.h"
#include "timer_native_api.h"
static bool timer_thread_run = true;
@ -46,7 +43,7 @@ void * thread_modulers_timer_check(void * arg)
while (timer_thread_run) {
ms_to_expiry = -1;
vm_mutex_lock(&g_timer_ctx_list_mutex);
os_mutex_lock(&g_timer_ctx_list_mutex);
timer_ctx_node_t* elem = (timer_ctx_node_t*)
bh_list_first_elem(&g_timer_ctx_list);
while (elem) {
@ -58,14 +55,14 @@ void * thread_modulers_timer_check(void * arg)
elem = (timer_ctx_node_t*) bh_list_elem_next(elem);
}
vm_mutex_unlock(&g_timer_ctx_list_mutex);
os_mutex_unlock(&g_timer_ctx_list_mutex);
if (ms_to_expiry == -1)
ms_to_expiry = 60 * 1000;
vm_mutex_lock(&g_timer_ctx_list_mutex);
vm_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
ms_to_expiry);
vm_mutex_unlock(&g_timer_ctx_list_mutex);
os_mutex_lock(&g_timer_ctx_list_mutex);
os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
ms_to_expiry * 1000);
os_mutex_unlock(&g_timer_ctx_list_mutex);
}
return NULL;
@ -73,9 +70,9 @@ void * thread_modulers_timer_check(void * arg)
void wakeup_modules_timer_thread(timer_ctx_t ctx)
{
vm_mutex_lock(&g_timer_ctx_list_mutex);
vm_cond_signal(&g_timer_ctx_list_cond);
vm_mutex_unlock(&g_timer_ctx_list_mutex);
os_mutex_lock(&g_timer_ctx_list_mutex);
os_cond_signal(&g_timer_ctx_list_cond);
os_mutex_unlock(&g_timer_ctx_list_mutex);
}
void init_wasm_timer()
@ -83,11 +80,11 @@ void init_wasm_timer()
korp_tid tm_tid;
bh_list_init(&g_timer_ctx_list);
vm_cond_init(&g_timer_ctx_list_cond);
os_cond_init(&g_timer_ctx_list_cond);
/* temp solution for: thread_modulers_timer_check thread would recursive lock the mutex */
vm_recursive_mutex_init(&g_timer_ctx_list_mutex);
os_recursive_mutex_init(&g_timer_ctx_list_mutex);
vm_thread_create(&tm_tid, thread_modulers_timer_check,
os_thread_create(&tm_tid, thread_modulers_timer_check,
NULL, BH_APPLET_PRESERVED_STACK_SIZE);
}
@ -115,16 +112,16 @@ timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
memset(node, 0, sizeof(*node));
node->timer_ctx = ctx;
vm_mutex_lock(&g_timer_ctx_list_mutex);
os_mutex_lock(&g_timer_ctx_list_mutex);
bh_list_insert(&g_timer_ctx_list, node);
vm_mutex_unlock(&g_timer_ctx_list_mutex);
os_mutex_unlock(&g_timer_ctx_list_mutex);
return ctx;
}
void destroy_module_timer_ctx(unsigned int module_id)
{
vm_mutex_lock(&g_timer_ctx_list_mutex);
os_mutex_lock(&g_timer_ctx_list_mutex);
timer_ctx_node_t* elem = (timer_ctx_node_t*)
bh_list_first_elem(&g_timer_ctx_list);
while (elem) {
@ -137,7 +134,7 @@ void destroy_module_timer_ctx(unsigned int module_id)
elem = (timer_ctx_node_t*) bh_list_elem_next(elem);
}
vm_mutex_unlock(&g_timer_ctx_list_mutex);
os_mutex_unlock(&g_timer_ctx_list_mutex);
}
timer_ctx_t get_wasm_timer_ctx(wasm_module_inst_t module_inst)
@ -192,6 +189,6 @@ extern uint32 get_sys_tick_ms();
uint32
wasm_get_sys_tick_ms(wasm_exec_env_t exec_env)
{
return (uint32) bh_get_tick_ms();
return (uint32)bh_get_tick_ms();
}

View File

@ -11,14 +11,12 @@
*/
#include "connection_lib.h"
#include "bh_thread.h"
#include "bh_platform.h"
#include "app_manager_export.h"
#include "module_wasm_app.h"
#include "conn_tcp.h"
#include "conn_udp.h"
#include "conn_uart.h"
#include "bh_common.h"
#include "bh_assert.h"
#include <unistd.h>
#include <sys/epoll.h>
@ -96,7 +94,7 @@ connection_interface_t connection_impl = {
static void add_connection(sys_connection_t *conn)
{
vm_mutex_lock(&g_lock);
os_mutex_lock(&g_lock);
g_handle_max++;
if (g_handle_max == -1)
@ -110,7 +108,7 @@ static void add_connection(sys_connection_t *conn)
g_connections = conn;
}
vm_mutex_unlock(&g_lock);
os_mutex_unlock(&g_lock);
}
#define FREE_CONNECTION(conn) do { \
@ -124,7 +122,7 @@ static int get_app_conns_num(uint32 module_id)
sys_connection_t *conn;
int num = 0;
vm_mutex_lock(&g_lock);
os_mutex_lock(&g_lock);
conn = g_connections;
while (conn) {
@ -133,7 +131,7 @@ static int get_app_conns_num(uint32 module_id)
conn = conn->next;
}
vm_mutex_unlock(&g_lock);
os_mutex_unlock(&g_lock);
return num;
}
@ -142,7 +140,7 @@ static sys_connection_t *find_connection(uint32 handle, bool remove_found)
{
sys_connection_t *conn, *prev = NULL;
vm_mutex_lock(&g_lock);
os_mutex_lock(&g_lock);
conn = g_connections;
while (conn) {
@ -154,7 +152,7 @@ static sys_connection_t *find_connection(uint32 handle, bool remove_found)
g_connections = conn->next;
}
}
vm_mutex_unlock(&g_lock);
os_mutex_unlock(&g_lock);
return conn;
} else {
prev = conn;
@ -162,7 +160,7 @@ static sys_connection_t *find_connection(uint32 handle, bool remove_found)
}
}
vm_mutex_unlock(&g_lock);
os_mutex_unlock(&g_lock);
return NULL;
}
@ -171,7 +169,7 @@ static void cleanup_connections(uint32 module_id)
{
sys_connection_t *conn, *prev = NULL;
vm_mutex_lock(&g_lock);
os_mutex_lock(&g_lock);
conn = g_connections;
while (conn) {
@ -194,7 +192,7 @@ static void cleanup_connections(uint32 module_id)
}
}
vm_mutex_unlock(&g_lock);
os_mutex_unlock(&g_lock);
}
static conn_type_t get_conn_type(const char *name)
@ -546,13 +544,13 @@ void app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg)
bool init_connection_framework()
{
korp_thread tid;
korp_tid tid;
epollfd = epoll_create(MAX_EVENTS);
if (epollfd == -1)
return false;
if (vm_mutex_init(&g_lock) != 0) {
if (os_mutex_init(&g_lock) != 0) {
close(epollfd);
return false;
}
@ -566,7 +564,7 @@ bool init_connection_framework()
goto fail;
}
if (vm_thread_create(&tid,
if (os_thread_create(&tid,
polling_thread_routine,
NULL,
BH_APPLET_PRESERVED_STACK_SIZE) != 0) {
@ -576,7 +574,7 @@ bool init_connection_framework()
return true;
fail:
vm_mutex_destroy(&g_lock);
os_mutex_destroy(&g_lock);
close(epollfd);
return false;
}

View File

@ -6,10 +6,7 @@
#include "runtime_sensor.h"
#include "app_manager_export.h"
#include "module_wasm_app.h"
#include "bh_thread.h"
#include "bh_time.h"
#include "bh_common.h"
#include "bh_assert.h"
#include "bh_platform.h"
static sys_sensor_t * g_sys_sensors = NULL;
static int g_sensor_id_max = 0;
@ -103,11 +100,11 @@ wasm_sensor_config(wasm_exec_env_t exec_env,
module_inst);
bh_assert(mod_id != ID_NONE);
vm_mutex_lock(&s->lock);
os_mutex_lock(&s->lock);
c = find_sensor_client(s, mod_id, false);
if (c == NULL) {
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
return false;
}
@ -115,7 +112,7 @@ wasm_sensor_config(wasm_exec_env_t exec_env,
c->bit_cfg = bit_cfg;
c->delay = delay;
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
if (s->config != NULL) {
attr_cont = attr_container_create("config sensor");
@ -149,19 +146,19 @@ wasm_sensor_open(wasm_exec_env_t exec_env,
module_inst);
bh_assert(mod_id != ID_NONE);
vm_mutex_lock(&s->lock);
os_mutex_lock(&s->lock);
c = find_sensor_client(s, mod_id, false);
if (c) {
// the app already opened this sensor
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
return -1;
}
sensor_client_t * client = (sensor_client_t*) wasm_runtime_malloc(
sizeof(sensor_client_t));
if (client == NULL) {
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
return -1;
}
@ -172,7 +169,7 @@ wasm_sensor_open(wasm_exec_env_t exec_env,
client->next = s->clients;
s->clients = client;
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
refresh_read_interval(s);
@ -218,10 +215,10 @@ wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor)
if (s == NULL)
return false;
vm_mutex_lock(&s->lock);
os_mutex_lock(&s->lock);
if ((c = find_sensor_client(s, client_id, true)) != NULL)
wasm_runtime_free(c);
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
refresh_read_interval(s);
@ -251,7 +248,7 @@ void refresh_read_interval(sensor_obj_t sensor)
{
sensor_client_t *c;
uint32 interval = sensor->default_interval;
vm_mutex_lock(&sensor->lock);
os_mutex_lock(&sensor->lock);
c = sensor->clients;
if (c)
@ -263,7 +260,7 @@ void refresh_read_interval(sensor_obj_t sensor)
c = c->next;
}
vm_mutex_unlock(&sensor->lock);
os_mutex_unlock(&sensor->lock);
sensor->read_interval = interval;
}
@ -310,7 +307,7 @@ add_sys_sensor(char * name, char * description, int instance,
g_sys_sensors = s;
}
vm_mutex_init(&s->lock);
os_mutex_init(&s->lock);
return s;
}
@ -366,7 +363,7 @@ sensor_client_t *find_sensor_client(sys_sensor_t * sensor,
int check_sensor_timers()
{
int ms_to_next_check = -1;
uint32 now = (uint32) bh_get_tick_ms();
uint32 now = (uint32)bh_get_tick_ms();
sys_sensor_t * s = g_sys_sensors;
while (s) {
@ -412,11 +409,11 @@ void sensor_cleanup_callback(uint32 module_id)
while (s) {
sensor_client_t *c;
vm_mutex_lock(&s->lock);
os_mutex_lock(&s->lock);
if ((c = find_sensor_client(s, module_id, true)) != NULL) {
wasm_runtime_free(c);
}
vm_mutex_unlock(&s->lock);
os_mutex_unlock(&s->lock);
s = s->next;
}
}

View File

@ -3,9 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_common.h"
#include "bh_queue.h"
#include "bh_thread.h"
#include "bh_platform.h"
#include "runtime_sensor.h"
#include "bi-inc/attr_container.h"
#include "module_wasm_app.h"
@ -91,15 +89,15 @@ static void thread_sensor_check(void * arg)
int ms_to_expiry = check_sensor_timers();
if (ms_to_expiry == -1)
ms_to_expiry = 5000;
vm_mutex_lock(&mutex);
vm_cond_reltimedwait(&cond, &mutex, ms_to_expiry);
vm_mutex_unlock(&mutex);
os_mutex_lock(&mutex);
os_cond_reltimedwait(&cond, &mutex, ms_to_expiry * 1000);
os_mutex_unlock(&mutex);
}
}
static void cb_wakeup_thread()
{
vm_cond_signal(&cond);
os_cond_signal(&cond);
}
void set_sensor_reshceduler(void (*callback)());
@ -107,8 +105,8 @@ void set_sensor_reshceduler(void (*callback)());
void init_sensor_framework()
{
// init the mutext and conditions
vm_cond_init(&cond);
vm_mutex_init(&mutex);
os_cond_init(&cond);
os_mutex_init(&mutex);
set_sensor_reshceduler(cb_wakeup_thread);
@ -123,9 +121,9 @@ void init_sensor_framework()
void start_sensor_framework()
{
korp_thread tid;
korp_tid tid;
vm_thread_create(&tid,
os_thread_create(&tid,
(void *)thread_sensor_check,
NULL,
BH_APPLET_PRESERVED_STACK_SIZE);

View File

@ -11,115 +11,139 @@
/* -------------------------------------------------------------------------
* Button widget native function wrappers
* -------------------------------------------------------------------------*/
static int32
lv_btn_create_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *par, lv_obj_t *copy)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_create_wrapper)
{
return wgl_native_wigdet_create(WIDGET_TYPE_BTN, par, copy, module_inst);
int32 res;
wgl_native_return_type(int32);
wgl_native_get_arg(uint32, par_obj_id);
wgl_native_get_arg(uint32, copy_obj_id);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
res = wgl_native_wigdet_create(WIDGET_TYPE_BTN, par_obj_id, copy_obj_id, module_inst);
wgl_native_set_return(res);
}
static void
lv_btn_set_toggle_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn, bool tgl)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_toggle_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, btn);
wgl_native_get_arg(bool, tgl);
(void)exec_env;
lv_btn_set_toggle(btn, tgl);
}
static void
lv_btn_set_state_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn, lv_btn_state_t state)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_state_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, btn);
wgl_native_get_arg(lv_btn_state_t, state);
(void)exec_env;
lv_btn_set_state(btn, state);
}
static void
lv_btn_set_ink_in_time_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn, uint16_t time)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_ink_in_time_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, btn);
wgl_native_get_arg(uint16_t, time);
(void)exec_env;
lv_btn_set_ink_in_time(btn, time);
}
static void
lv_btn_set_ink_out_time_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn, uint16_t time)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_ink_out_time_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, btn);
wgl_native_get_arg(uint16_t, time);
(void)exec_env;
lv_btn_set_ink_out_time(btn, time);
}
static void
lv_btn_set_ink_wait_time_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn, uint16_t time)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_set_ink_wait_time_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, btn);
wgl_native_get_arg(uint16_t, time);
(void)exec_env;
lv_btn_set_ink_wait_time(btn, time);
}
static uint16_t
lv_btn_get_ink_in_time_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_ink_in_time_wrapper)
{
(void)module_inst;
return lv_btn_get_ink_in_time(btn);
uint16_t res;
wgl_native_return_type(uint16_t);
wgl_native_get_arg(lv_obj_t *, btn);
(void)exec_env;
res = lv_btn_get_ink_in_time(btn);
wgl_native_set_return(res);
}
static uint16_t
lv_btn_get_ink_out_time_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_ink_out_time_wrapper)
{
(void)module_inst;
return lv_btn_get_ink_out_time(btn);
uint16_t res;
wgl_native_return_type(uint16_t);
wgl_native_get_arg(lv_obj_t *, btn);
(void)exec_env;
res = lv_btn_get_ink_out_time(btn);
wgl_native_set_return(res);
}
static uint16_t
lv_btn_get_ink_wait_time_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_ink_wait_time_wrapper)
{
(void)module_inst;
return lv_btn_get_ink_wait_time(btn);
uint16_t res;
wgl_native_return_type(uint16_t);
wgl_native_get_arg(lv_obj_t *, btn);
(void)exec_env;
res = lv_btn_get_ink_wait_time(btn);
wgl_native_set_return(res);
}
static lv_btn_state_t
lv_btn_get_state_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_state_wrapper)
{
(void)module_inst;
return lv_btn_get_state(btn);
lv_btn_state_t res;
wgl_native_return_type(lv_btn_state_t);
wgl_native_get_arg(lv_obj_t *, btn);
(void)exec_env;
res = lv_btn_get_state(btn);
wgl_native_set_return(res);
}
static bool
lv_btn_get_toggle_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_get_toggle_wrapper)
{
(void)module_inst;
return lv_btn_get_toggle(btn);
bool res;
wgl_native_return_type(bool);
wgl_native_get_arg(lv_obj_t *, btn);
(void)exec_env;
res = lv_btn_get_toggle(btn);
wgl_native_set_return(res);
}
static void
lv_btn_toggle_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * btn)
DEFINE_WGL_NATIVE_WRAPPER(lv_btn_toggle_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, btn);
(void)exec_env;
lv_btn_toggle(btn);
}
static WGLNativeFuncDef btn_native_func_defs[] = {
{ BTN_FUNC_ID_CREATE, lv_btn_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} },
{ BTN_FUNC_ID_SET_TOGGLE, lv_btn_set_toggle_wrapper, NO_RET, 3, {1, -1}, {-1} },
{ BTN_FUNC_ID_SET_STATE, lv_btn_set_state_wrapper, NO_RET, 3, {1, -1}, {-1} },
// { BTN_FUNC_ID_SET_STYLE, _btn_set_style, NO_RET, 2, {0, -1}, {-1} },
{ BTN_FUNC_ID_SET_INK_IN_TIME, lv_btn_set_ink_in_time_wrapper, NO_RET, 3, {1, -1}, {-1} },
{ BTN_FUNC_ID_SET_INK_OUT_TIME, lv_btn_set_ink_out_time_wrapper, NO_RET, 3, {1, -1}, {-1} },
{ BTN_FUNC_ID_SET_INK_WAIT_TIME, lv_btn_set_ink_wait_time_wrapper, NO_RET, 3, {1, -1}, {-1} },
{ BTN_FUNC_ID_GET_INK_IN_TIME, lv_btn_get_ink_in_time_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ BTN_FUNC_ID_GET_INK_OUT_TIME, lv_btn_get_ink_out_time_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ BTN_FUNC_ID_GET_INK_WAIT_TIME, lv_btn_get_ink_wait_time_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ BTN_FUNC_ID_GET_STATE, lv_btn_get_state_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ BTN_FUNC_ID_GET_TOGGLE, lv_btn_get_toggle_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ BTN_FUNC_ID_TOGGLE, lv_btn_toggle_wrapper, NO_RET, 2, {1, -1}, {-1} },
{ BTN_FUNC_ID_CREATE, lv_btn_create_wrapper, 2, false },
{ BTN_FUNC_ID_SET_TOGGLE, lv_btn_set_toggle_wrapper, 2, true },
{ BTN_FUNC_ID_SET_STATE, lv_btn_set_state_wrapper, 2, true },
{ BTN_FUNC_ID_SET_INK_IN_TIME, lv_btn_set_ink_in_time_wrapper, 2, true },
{ BTN_FUNC_ID_SET_INK_OUT_TIME, lv_btn_set_ink_out_time_wrapper, 2, true },
{ BTN_FUNC_ID_SET_INK_WAIT_TIME, lv_btn_set_ink_wait_time_wrapper, 2, true },
{ BTN_FUNC_ID_GET_INK_IN_TIME, lv_btn_get_ink_in_time_wrapper, 1, true },
{ BTN_FUNC_ID_GET_INK_OUT_TIME, lv_btn_get_ink_out_time_wrapper, 1, true },
{ BTN_FUNC_ID_GET_INK_WAIT_TIME, lv_btn_get_ink_wait_time_wrapper, 1, true },
{ BTN_FUNC_ID_GET_STATE, lv_btn_get_state_wrapper, 1, true },
{ BTN_FUNC_ID_GET_TOGGLE, lv_btn_get_toggle_wrapper, 1, true },
{ BTN_FUNC_ID_TOGGLE, lv_btn_toggle_wrapper, 1, true },
};
@ -128,10 +152,9 @@ void
wasm_btn_native_call(wasm_exec_env_t exec_env,
int32 func_id, uint32 *argv, uint32 argc)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef);
wgl_native_func_call(module_inst,
wgl_native_func_call(exec_env,
btn_native_func_defs,
size,
func_id,

View File

@ -12,62 +12,88 @@
/* -------------------------------------------------------------------------
* Label widget native function wrappers
* -------------------------------------------------------------------------*/
static int32
lv_cb_create_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *par, lv_obj_t *copy)
DEFINE_WGL_NATIVE_WRAPPER(lv_cb_create_wrapper)
{
return wgl_native_wigdet_create(WIDGET_TYPE_CB, par, copy, module_inst);
int32 res;
wgl_native_return_type(int32);
wgl_native_get_arg(uint32, par_obj_id);
wgl_native_get_arg(uint32, copy_obj_id);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
res = wgl_native_wigdet_create(WIDGET_TYPE_CB, par_obj_id, copy_obj_id, module_inst);
wgl_native_set_return(res);
}
static void
lv_cb_set_text_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * cb, const char * txt)
DEFINE_WGL_NATIVE_WRAPPER(lv_cb_set_text_wrapper)
{
(void)module_inst;
lv_cb_set_text(cb, txt);
char *text;
wgl_native_get_arg(lv_obj_t *, cb);
wgl_native_get_arg(uint32, text_offset);
wgl_native_get_arg(uint32, text_len);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (!validate_app_addr(text_offset, text_len)
|| !(text = addr_app_to_native(text_offset)))
return;
lv_cb_set_text(cb, text);
}
static void
lv_cb_set_static_text_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * cb, const char * txt)
DEFINE_WGL_NATIVE_WRAPPER(lv_cb_set_static_text_wrapper)
{
(void)module_inst;
lv_cb_set_static_text(cb, txt);
char *text;
wgl_native_get_arg(lv_obj_t *, cb);
wgl_native_get_arg(uint32, text_offset);
wgl_native_get_arg(uint32, text_len);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (!validate_app_addr(text_offset, text_len)
|| !(text = addr_app_to_native(text_offset)))
return;
lv_cb_set_static_text(cb, text);
}
static int32
lv_cb_get_text_length_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *cb)
DEFINE_WGL_NATIVE_WRAPPER(lv_cb_get_text_length_wrapper)
{
const char *text = lv_cb_get_text(cb);
const char *text;
wgl_native_return_type(int32);
wgl_native_get_arg(lv_obj_t *, cb);
if (text == NULL)
return 0;
(void)exec_env;
return strlen(text);
text = lv_cb_get_text(cb);
wgl_native_set_return(text ? strlen(text): 0);
}
static char *
lv_cb_get_text_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *cb, char *buffer, int buffer_len)
DEFINE_WGL_NATIVE_WRAPPER(lv_cb_get_text_wrapper)
{
const char *text = lv_cb_get_text(cb);
const char *text;
char *buffer;
wgl_native_return_type(uint32);
wgl_native_get_arg(lv_obj_t *, cb);
wgl_native_get_arg(uint32, buffer_offset);
wgl_native_get_arg(int, buffer_len);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (text == NULL)
return 0;
if (!validate_app_addr(buffer_offset, buffer_len)
|| !(buffer = addr_app_to_native(buffer_offset)))
return;
strncpy(buffer, text, buffer_len - 1);
buffer[buffer_len - 1] = '\0';
if ((text = lv_cb_get_text(cb))) {
strncpy(buffer, text, buffer_len - 1);
buffer[buffer_len - 1] = '\0';
}
return buffer;
wgl_native_set_return(buffer_offset);
}
static WGLNativeFuncDef cb_native_func_defs[] = {
{ CB_FUNC_ID_CREATE, lv_cb_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} },
{ CB_FUNC_ID_SET_TEXT, lv_cb_set_text_wrapper, NO_RET, 3, {1, -1}, {2, -1} },
{ CB_FUNC_ID_SET_STATIC_TEXT, lv_cb_set_static_text_wrapper, NO_RET, 3, {1, -1}, {2, -1} },
{ CB_FUNC_ID_GET_TEXT_LENGTH, lv_cb_get_text_length_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ CB_FUNC_ID_GET_TEXT, lv_cb_get_text_wrapper, RET_PTR, 4, {1, -1}, {2, -1} },
{ CB_FUNC_ID_CREATE, lv_cb_create_wrapper, 2, false },
{ CB_FUNC_ID_SET_TEXT, lv_cb_set_text_wrapper, 3, true },
{ CB_FUNC_ID_SET_STATIC_TEXT, lv_cb_set_static_text_wrapper, 3, true },
{ CB_FUNC_ID_GET_TEXT_LENGTH, lv_cb_get_text_length_wrapper, 1, true },
{ CB_FUNC_ID_GET_TEXT, lv_cb_get_text_wrapper, 3, true },
};
/*************** Native Interface to Wasm App ***********/
@ -75,10 +101,9 @@ void
wasm_cb_native_call(wasm_exec_env_t exec_env,
int32 func_id, uint32 *argv, uint32 argc)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef);
wgl_native_func_call(module_inst,
wgl_native_func_call(exec_env,
cb_native_func_defs,
size,
func_id,

View File

@ -12,53 +12,72 @@
/* -------------------------------------------------------------------------
* Label widget native function wrappers
* -------------------------------------------------------------------------*/
static int32
lv_label_create_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *par, lv_obj_t *copy)
DEFINE_WGL_NATIVE_WRAPPER(lv_label_create_wrapper)
{
return wgl_native_wigdet_create(WIDGET_TYPE_LABEL, par, copy, module_inst);
int32 res;
wgl_native_return_type(int32);
wgl_native_get_arg(uint32, par_obj_id);
wgl_native_get_arg(uint32, copy_obj_id);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
res = wgl_native_wigdet_create(WIDGET_TYPE_LABEL, par_obj_id, copy_obj_id, module_inst);
wgl_native_set_return(res);
}
static void
lv_label_set_text_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * label, const char * text)
DEFINE_WGL_NATIVE_WRAPPER(lv_label_set_text_wrapper)
{
(void)module_inst;
char *text;
wgl_native_get_arg(lv_obj_t *, label);
wgl_native_get_arg(uint32, text_offset);
wgl_native_get_arg(uint32, text_len);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (!validate_app_addr(text_offset, text_len)
|| !(text = addr_app_to_native(text_offset)))
return;
lv_label_set_text(label, text);
}
static int32
lv_label_get_text_length_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *label)
DEFINE_WGL_NATIVE_WRAPPER(lv_label_get_text_length_wrapper)
{
char *text = lv_label_get_text(label);
wgl_native_return_type(int32);
wgl_native_get_arg(lv_obj_t *, label);
const char *text;
if (text == NULL)
return 0;
(void)exec_env;
return strlen(text);
text = lv_label_get_text(label);
wgl_native_set_return(text ? strlen(text) : 0);
}
static char *
lv_label_get_text_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *label, char *buffer, int buffer_len)
DEFINE_WGL_NATIVE_WRAPPER(lv_label_get_text_wrapper)
{
char *text = lv_label_get_text(label);
const char *text;
char *buffer;
wgl_native_return_type(uint32);
wgl_native_get_arg(lv_obj_t *, label);
wgl_native_get_arg(uint32, buffer_offset);
wgl_native_get_arg(int, buffer_len);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (text == NULL)
return 0;
if (!validate_app_addr(buffer_offset, buffer_len)
|| !(buffer = addr_app_to_native(buffer_offset)))
return;
strncpy(buffer, text, buffer_len - 1);
buffer[buffer_len - 1] = '\0';
if ((text = lv_label_get_text(label))) {
strncpy(buffer, text, buffer_len - 1);
buffer[buffer_len - 1] = '\0';
}
return buffer;
wgl_native_set_return(buffer_offset);
}
static WGLNativeFuncDef label_native_func_defs[] = {
{ LABEL_FUNC_ID_CREATE, lv_label_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} },
{ LABEL_FUNC_ID_SET_TEXT, lv_label_set_text_wrapper, NO_RET, 3, {1, -1}, {2, -1} },
{ LABEL_FUNC_ID_GET_TEXT_LENGTH, lv_label_get_text_length_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ LABEL_FUNC_ID_GET_TEXT, lv_label_get_text_wrapper, RET_PTR, 4, {1, -1}, {2, -1} },
{ LABEL_FUNC_ID_CREATE, lv_label_create_wrapper, 2, false },
{ LABEL_FUNC_ID_SET_TEXT, lv_label_set_text_wrapper, 3, true },
{ LABEL_FUNC_ID_GET_TEXT_LENGTH, lv_label_get_text_length_wrapper, 1, true },
{ LABEL_FUNC_ID_GET_TEXT, lv_label_get_text_wrapper, 3, true },
};
/*************** Native Interface to Wasm App ***********/
@ -66,10 +85,9 @@ void
wasm_label_native_call(wasm_exec_env_t exec_env,
int32 func_id, uint32 *argv, uint32 argc)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef);
wgl_native_func_call(module_inst,
wgl_native_func_call(exec_env,
label_native_func_defs,
size,
func_id,

View File

@ -12,38 +12,53 @@
/* -------------------------------------------------------------------------
* List widget native function wrappers
* -------------------------------------------------------------------------*/
static int32
lv_list_create_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *par, lv_obj_t *copy)
DEFINE_WGL_NATIVE_WRAPPER(lv_list_create_wrapper)
{
return wgl_native_wigdet_create(WIDGET_TYPE_LIST, par, copy, module_inst);
int32 res;
wgl_native_return_type(int32);
wgl_native_get_arg(uint32, par_obj_id);
wgl_native_get_arg(uint32, copy_obj_id);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
res = wgl_native_wigdet_create(WIDGET_TYPE_LIST, par_obj_id, copy_obj_id, module_inst);
wgl_native_set_return(res);
}
static int32
lv_list_add_btn_wrapper(wasm_module_inst_t module_inst,
lv_obj_t *list, const char *text)
DEFINE_WGL_NATIVE_WRAPPER(lv_list_add_btn_wrapper)
{
wgl_native_return_type(int32);
wgl_native_get_arg(lv_obj_t *, list);
wgl_native_get_arg(uint32, text_offset);
wgl_native_get_arg(uint32, text_len);
uint32 btn_obj_id;
lv_obj_t *btn;
uint32 mod_id;
char *text;
wasm_module_inst_t module_inst = get_module_inst(exec_env);
btn = lv_list_add_btn(list, NULL, text);
if (!validate_app_addr(text_offset, text_len)
|| !(text = addr_app_to_native(text_offset)))
return;
if (btn == NULL)
return 0;
if (!(btn = lv_list_add_btn(list, NULL, text))) {
wasm_runtime_set_exception(module_inst, "add button to list fail.");
return;
}
mod_id = app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(mod_id != ID_NONE);
if (wgl_native_add_object(btn, mod_id, &btn_obj_id))
return btn_obj_id; /* success return */
if (!wgl_native_add_object(btn, mod_id, &btn_obj_id)) {
wasm_runtime_set_exception(module_inst, "add button to object list fail.");
return;
}
return 0;
wgl_native_set_return(btn_obj_id);
}
static WGLNativeFuncDef list_native_func_defs[] = {
{ LIST_FUNC_ID_CREATE, lv_list_create_wrapper, HAS_RET, 3, {1 | NULL_OK, 2 | NULL_OK, -1}, {-1} },
{ LIST_FUNC_ID_ADD_BTN, lv_list_add_btn_wrapper, HAS_RET, 3, {1, -1}, {2, -1} },
{ LIST_FUNC_ID_CREATE, lv_list_create_wrapper, 2, false },
{ LIST_FUNC_ID_ADD_BTN, lv_list_add_btn_wrapper, 3, true },
};
/*************** Native Interface to Wasm App ***********/
@ -51,10 +66,9 @@ void
wasm_list_native_call(wasm_exec_env_t exec_env,
int32 func_id, uint32 *argv, uint32 argc)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef);
wgl_native_func_call(module_inst,
wgl_native_func_call(exec_env,
list_native_func_defs,
size,
func_id,

View File

@ -10,18 +10,28 @@
#define THROW_EXC(msg) wasm_runtime_set_exception(module_inst, msg);
void
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy,
uint32 wgl_native_wigdet_create(int8 widget_type,
uint32 par_obj_id,
uint32 copy_obj_id,
wasm_module_inst_t module_inst)
{
uint32 obj_id;
lv_obj_t *wigdet = NULL;
lv_obj_t *wigdet = NULL, *par = NULL, *copy = NULL;
uint32 mod_id;
//TODO: limit total widget number
/* validate the parent object id if not equal to 0 */
if (par_obj_id != 0 && !wgl_native_validate_object(par_obj_id, &par)) {
THROW_EXC("create widget with invalid parent object.");
return 0;
}
/* validate the copy object id if not equal to 0 */
if (copy_obj_id != 0 && !wgl_native_validate_object(copy_obj_id, &copy)) {
THROW_EXC("create widget with invalid copy object.");
return 0;
}
if (par == NULL)
par = lv_disp_get_scr_act(NULL);
@ -48,146 +58,58 @@ uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy,
return 0;
}
static void invokeNative(intptr_t argv[], uint32 argc, void (*native_code)())
{
bh_assert(argc >= 1);
switch(argc) {
case 1:
native_code(argv[0]);
break;
case 2:
native_code(argv[0], argv[1]);
break;
case 3:
native_code(argv[0], argv[1], argv[2]);
break;
case 4:
native_code(argv[0], argv[1], argv[2], argv[3]);
break;
case 5:
native_code(argv[0], argv[1], argv[2], argv[3], argv[4]);
break;
case 6:
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
break;
case 7:
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6]);
break;
case 8:
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], argv[7]);
break;
case 9:
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], argv[7], argv[8]);
break;
case 10:
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], argv[7], argv[8], argv[9]);
break;
default:
{
/* FIXME: If this happen, add more cases. */
wasm_module_inst_t module_inst = (wasm_module_inst_t)argv[0];
THROW_EXC("the argument number of native function exceeds maximum");
return;
}
}
}
typedef void (*GenericFunctionPointer)();
typedef int32 (*Int32FuncPtr)(intptr_t *, uint32, GenericFunctionPointer);
typedef void (*VoidFuncPtr)(intptr_t *, uint32, GenericFunctionPointer);
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
void wgl_native_func_call(wasm_module_inst_t module_inst,
void wgl_native_func_call(wasm_exec_env_t exec_env,
WGLNativeFuncDef *funcs,
uint32 size,
int32 func_id,
uint32 *argv,
uint32 argc)
{
typedef void (*WGLNativeFuncPtr)(wasm_exec_env_t, uint64*, uint32*);
WGLNativeFuncPtr wglNativeFuncPtr;
wasm_module_inst_t module_inst = get_module_inst(exec_env);
WGLNativeFuncDef *func_def = funcs;
WGLNativeFuncDef *func_def_end = func_def + size;
while (func_def < func_def_end) {
if (func_def->func_id == func_id) {
int i, obj_arg_num = 0, ptr_arg_num = 0, argc1 = 0;
intptr_t argv_copy_buf[16];
intptr_t *argv_copy = argv_copy_buf;
/* Note: argv is validated in wasm_runtime_invoke_native()
* with pointer length equals to 1. Here validate the argv
* buffer again but with its total length in bytes */
if (!wasm_runtime_validate_native_addr(module_inst, argv, argc * sizeof(uint32)))
return;
argc1++; /* module_inst */
argc1 += func_def->arg_num;
if (argc1 > 16) {
argv_copy = (intptr_t *)wasm_runtime_malloc(func_def->arg_num *
sizeof(intptr_t));
if (argv_copy == NULL)
while (func_def < func_def_end) {
if (func_def->func_id == func_id
&& (uint32)func_def->arg_num == argc) {
uint64 argv_copy_buf[16], size;
uint64 *argv_copy = argv_copy_buf;
int i;
if (argc > sizeof(argv_copy_buf) / sizeof(uint64)) {
size = sizeof(uint64) * (uint64)argc;
if (size >= UINT32_MAX
|| !(argv_copy = wasm_runtime_malloc((uint32)size))) {
THROW_EXC("allocate memory failed.");
return;
}
memset(argv_copy, 0, (uint32)size);
}
/* Init argv_copy */
argv_copy[0] = (intptr_t)module_inst;
for (i = 0; i < func_def->arg_num; i++)
argv_copy[i + 1] = (intptr_t)argv[i];
*(uint32*)&argv_copy[i] = argv[i];
/* Validate object arguments */
i = 0;
for (; i < OBJ_ARG_NUM_MAX && func_def->obj_arg_indexes[i] != 0xff;
i++, obj_arg_num++) {
uint8 index = func_def->obj_arg_indexes[i];
bool null_ok = index & NULL_OK;
index = index & (~NULL_OK);
/* Some API's allow to pass NULL obj, such as xxx_create() */
if (argv_copy[index] == 0) {
if (!null_ok) {
THROW_EXC("the object id is 0 and invalid");
goto fail;
}
/* Continue so that to pass null object validation */
continue;
}
if (!wgl_native_validate_object(argv_copy[index],
(lv_obj_t **)&argv_copy[index])) {
/* Validate the first argument which is a lvgl object if needed */
if (func_def->check_obj) {
lv_obj_t *obj = NULL;
if (!wgl_native_validate_object(argv[0], &obj)) {
THROW_EXC("the object is invalid");
goto fail;
}
*(lv_obj_t **)&argv_copy[0] = obj;
}
/* Validate address arguments */
i = 0;
for (; i < PTR_ARG_NUM_MAX && func_def->ptr_arg_indexes[i] != 0xff;
i++, ptr_arg_num++) {
uint8 index = func_def->ptr_arg_indexes[i];
/* The index+1 arg is the data size to be validated */
if (!validate_app_addr(argv_copy[index], argv_copy[index + 1]))
goto fail;
/* Convert to native address before call lvgl function */
argv_copy[index] = (intptr_t)addr_app_to_native(argv_copy[index]);
}
if (func_def->has_ret == NO_RET)
invokeNative_Void(argv_copy,
argc1,
func_def->func_ptr);
else {
argv[0] = invokeNative_Int32(argv_copy,
argc1,
func_def->func_ptr);
/* Convert to app memory offset if return value is a
* native address pointer */
if (func_def->has_ret == RET_PTR)
argv[0] = addr_native_to_app((char *)(intptr_t)argv[0]);
}
wglNativeFuncPtr = (WGLNativeFuncPtr)func_def->func_ptr;
wglNativeFuncPtr(exec_env, argv_copy, argv);
if (argv_copy != argv_copy_buf)
wasm_runtime_free(argv_copy);

View File

@ -15,19 +15,12 @@ extern "C" {
#include "wasm_export.h"
#include "bi-inc/wgl_shared_utils.h"
#define OBJ_ARG_NUM_MAX 4
#define PTR_ARG_NUM_MAX 4
#define wgl_native_return_type(type) type *wgl_ret = (type*)(args_ret)
#define wgl_native_get_arg(type, name) type name = *((type*)(args++))
#define wgl_native_set_return(val) *wgl_ret = (val)
#define NULL_OK 0x80
enum {
/* The function has a normal return value (not a pointer) */
HAS_RET,
/* The function doesn't have return value */
NO_RET,
/* The function's return value is a native address pointer */
RET_PTR
};
#define DEFINE_WGL_NATIVE_WRAPPER(func_name) \
static void func_name(wasm_exec_env_t exec_env, uint64 *args, uint32 *args_ret)
enum {
WIDGET_TYPE_BTN,
@ -46,19 +39,11 @@ typedef struct WGLNativeFuncDef {
/* Native function pointer */
void *func_ptr;
/* whether has return value */
uint8 has_ret;
/* argument number */
uint8 arg_num;
/* low 7 bit: obj argument index
* highest 1 bit: allow obj be null or not
* -1 means the end of this array */
uint8 obj_arg_indexes[OBJ_ARG_NUM_MAX];
/* pointer argument indexes, -1 means the end of this array */
uint8 ptr_arg_indexes[PTR_ARG_NUM_MAX];
/* whether the first argument is lvgl object and needs validate */
bool check_obj;
} WGLNativeFuncDef;
bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj);
@ -66,11 +51,11 @@ bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj);
bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id);
uint32 wgl_native_wigdet_create(int8 widget_type,
lv_obj_t *par,
lv_obj_t *copy,
uint32 par_obj_id,
uint32 copy_obj_id,
wasm_module_inst_t module_inst);
void wgl_native_func_call(wasm_module_inst_t module_inst,
void wgl_native_func_call(wasm_exec_env_t exec_env,
WGLNativeFuncDef *funcs,
uint32 size,
int32 func_id,

View File

@ -6,8 +6,7 @@
#include "lvgl.h"
#include "app_manager_export.h"
#include "module_wasm_app.h"
#include "bh_list.h"
#include "bh_thread.h"
#include "bh_platform.h"
#include "wgl_native_utils.h"
#include "wgl.h"
@ -39,6 +38,10 @@ static korp_mutex g_object_list_mutex;
static bool lv_task_handler_thread_run = true;
static korp_mutex task_handler_lock;
static korp_cond task_handler_cond;
static void app_mgr_object_event_callback(module_data *m_data, bh_message_t msg)
{
uint32 argv[2];
@ -79,7 +82,7 @@ static void cleanup_object_list(uint32 module_id)
{
object_node_t *elem;
vm_mutex_lock(&g_object_list_mutex);
os_mutex_lock(&g_object_list_mutex);
while (true) {
bool found = false;
@ -104,7 +107,7 @@ static void cleanup_object_list(uint32 module_id)
break;
}
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
}
static bool init_object_event_callback_framework()
@ -128,20 +131,20 @@ bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj)
{
object_node_t *elem;
vm_mutex_lock(&g_object_list_mutex);
os_mutex_lock(&g_object_list_mutex);
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
while (elem) {
if (obj_id == elem->obj_id) {
if (obj != NULL)
*obj = elem->obj;
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
return true;
}
elem = (object_node_t *) bh_list_elem_next(elem);
}
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
return false;
}
@ -165,9 +168,9 @@ bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id)
node->obj_id = g_obj_id_max;
node->module_id = module_id;
vm_mutex_lock(&g_object_list_mutex);
os_mutex_lock(&g_object_list_mutex);
bh_list_insert(&g_object_list, node);
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
if (obj_id != NULL)
*obj_id = node->obj_id;
@ -194,20 +197,20 @@ static void _obj_del_recursive(lv_obj_t *obj)
i = i_next;
}
vm_mutex_lock(&g_object_list_mutex);
os_mutex_lock(&g_object_list_mutex);
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
while (elem) {
if (obj == elem->obj) {
bh_list_remove(&g_object_list, elem);
wasm_runtime_free(elem);
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
return;
}
elem = (object_node_t *) bh_list_elem_next(elem);
}
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
}
static void _obj_clean_recursive(lv_obj_t *obj)
@ -255,52 +258,55 @@ static void internal_lv_obj_event_cb(lv_obj_t *obj, lv_event_t event)
{
object_node_t *elem;
vm_mutex_lock(&g_object_list_mutex);
os_mutex_lock(&g_object_list_mutex);
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
while (elem) {
if (obj == elem->obj) {
post_widget_msg_to_module(elem, event);
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
return;
}
elem = (object_node_t *) bh_list_elem_next(elem);
}
vm_mutex_unlock(&g_object_list_mutex);
os_mutex_unlock(&g_object_list_mutex);
}
static void* lv_task_handler_thread_routine (void *arg)
{
korp_sem sem;
if (vm_sem_init(&sem, 1) != 0) {
printf("Init semaphore for lvgl task handler thread fail!\n");
return NULL;
}
os_mutex_lock(&task_handler_lock);
while (lv_task_handler_thread_run) {
vm_sem_reltimedwait(&sem, 100);
os_cond_reltimedwait(&task_handler_cond, &task_handler_lock,
100 * 1000);
lv_task_handler();
}
vm_sem_destroy(&sem);
os_mutex_unlock(&task_handler_lock);
return NULL;
}
void wgl_init(void)
{
korp_thread tid;
korp_tid tid;
if (os_mutex_init(&task_handler_lock) != 0)
return;
if (os_cond_init(&task_handler_cond) != 0) {
os_mutex_destroy(&task_handler_lock);
return;
}
lv_init();
bh_list_init(&g_object_list);
vm_recursive_mutex_init(&g_object_list_mutex);
os_recursive_mutex_init(&g_object_list_mutex);
init_object_event_callback_framework();
/* new a thread, call lv_task_handler periodically */
vm_thread_create(&tid,
os_thread_create(&tid,
lv_task_handler_thread_routine,
NULL,
BH_APPLET_PRESERVED_STACK_SIZE);
@ -309,34 +315,41 @@ void wgl_init(void)
void wgl_exit(void)
{
lv_task_handler_thread_run = false;
os_cond_destroy(&task_handler_cond);
os_mutex_destroy(&task_handler_lock);
}
/* -------------------------------------------------------------------------
* Obj native function wrappers
* -------------------------------------------------------------------------*/
static lv_res_t
lv_obj_del_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj)
DEFINE_WGL_NATIVE_WRAPPER(lv_obj_del_wrapper)
{
(void)module_inst;
lv_res_t res;
wgl_native_return_type(lv_res_t);
wgl_native_get_arg(lv_obj_t *, obj);
(void)exec_env;
/* Recursively delete object node in the list belong to this
* parent object including itself */
_obj_del_recursive(obj);
return lv_obj_del(obj);
res = lv_obj_del(obj);
wgl_native_set_return(res);
}
static void
lv_obj_del_async_wrapper(wasm_module_inst_t module_inst, lv_obj_t * obj)
DEFINE_WGL_NATIVE_WRAPPER(lv_obj_del_async_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, obj);
(void)exec_env;
lv_obj_del_async(obj);
}
static void
lv_obj_clean_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj)
DEFINE_WGL_NATIVE_WRAPPER(lv_obj_clean_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, obj);
(void)exec_env;
/* Recursively delete child object node in the list belong to this
* parent object */
@ -346,33 +359,40 @@ lv_obj_clean_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj)
lv_obj_clean(obj);
}
static void
lv_obj_align_wrapper(wasm_module_inst_t module_inst,
lv_obj_t * obj,
const lv_obj_t * base,
lv_align_t align,
lv_coord_t x_mod,
lv_coord_t y_mod)
DEFINE_WGL_NATIVE_WRAPPER(lv_obj_align_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, obj);
wgl_native_get_arg(uint32, base_obj_id);
wgl_native_get_arg(lv_align_t, align);
wgl_native_get_arg(lv_coord_t, x_mod);
wgl_native_get_arg(lv_coord_t, y_mod);
lv_obj_t *base = NULL;
wasm_module_inst_t module_inst = get_module_inst(exec_env);
/* validate the base object id if not equal to 0 */
if (base_obj_id != 0 && !wgl_native_validate_object(base_obj_id, &base)) {
wasm_runtime_set_exception(module_inst, "align with invalid base object.");
return;
}
lv_obj_align(obj, base, align, x_mod, y_mod);
}
static void
lv_obj_set_event_cb_wrapper(wasm_module_inst_t module_inst, lv_obj_t *obj)
DEFINE_WGL_NATIVE_WRAPPER(lv_obj_set_event_cb_wrapper)
{
(void)module_inst;
wgl_native_get_arg(lv_obj_t *, obj);
(void)exec_env;
lv_obj_set_event_cb(obj, internal_lv_obj_event_cb);
}
/* ------------------------------------------------------------------------- */
static WGLNativeFuncDef obj_native_func_defs[] = {
{ OBJ_FUNC_ID_DEL, lv_obj_del_wrapper, HAS_RET, 2, {1, -1}, {-1} },
{ OBJ_FUNC_ID_DEL_ASYNC, lv_obj_del_async_wrapper, NO_RET, 2, {1, -1}, {-1} },
{ OBJ_FUNC_ID_CLEAN, lv_obj_clean_wrapper, NO_RET, 2, {1, -1}, {-1} },
{ OBJ_FUNC_ID_ALIGN, lv_obj_align_wrapper, NO_RET, 6, {1, 2 | NULL_OK, -1}, {-1} },
{ OBJ_FUNC_ID_SET_EVT_CB, lv_obj_set_event_cb_wrapper, NO_RET, 2, {1, -1}, {-1} },
{ OBJ_FUNC_ID_DEL, lv_obj_del_wrapper, 1, true },
{ OBJ_FUNC_ID_DEL_ASYNC, lv_obj_del_async_wrapper, 1, true },
{ OBJ_FUNC_ID_CLEAN, lv_obj_clean_wrapper, 1, true },
{ OBJ_FUNC_ID_ALIGN, lv_obj_align_wrapper, 5, true },
{ OBJ_FUNC_ID_SET_EVT_CB, lv_obj_set_event_cb_wrapper, 1, true },
};
/*************** Native Interface to Wasm App ***********/
@ -380,10 +400,9 @@ void
wasm_obj_native_call(wasm_exec_env_t exec_env,
int32 func_id, uint32 *argv, uint32 argc)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef);
wgl_native_func_call(module_inst,
wgl_native_func_call(exec_env,
obj_native_func_defs,
size,
func_id,

View File

@ -5,8 +5,7 @@
#include "app_manager.h"
#include "app_manager_host.h"
#include "bh_queue.h"
#include "bh_thread.h"
#include "bh_platform.h"
#include "bi-inc/attr_container.h"
#include "event.h"
#include "watchdog.h"
@ -38,7 +37,7 @@ void app_manager_post_applets_update_event()
return;
}
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
m_data = module_data_list;
while (m_data) {
@ -80,7 +79,8 @@ void app_manager_post_applets_update_event()
app_manager_printf("Post applets update event success!\n");
attr_container_dump(attr_cont);
fail: vm_mutex_unlock(&module_data_list_lock);
fail:
os_mutex_unlock(&module_data_list_lock);
attr_container_destroy(attr_cont);
}
@ -89,7 +89,7 @@ static int get_applets_count()
module_data *m_data;
int num = 0;
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
m_data = module_data_list;
while (m_data) {
@ -97,7 +97,7 @@ static int get_applets_count()
m_data = m_data->next;
}
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
return num;
}
@ -118,7 +118,7 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
return false;
}
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
m_data = module_data_list;
while (m_data) {
@ -186,7 +186,8 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
app_manager_printf("Query Applets success!\n");
attr_container_dump(attr_cont);
fail: vm_mutex_unlock(&module_data_list_lock);
fail:
os_mutex_unlock(&module_data_list_lock);
attr_container_destroy(attr_cont);
return ret;
}
@ -368,9 +369,11 @@ void app_manager_startup(host_interface *interface)
/* Enter loop run */
bh_queue_enter_loop_run(g_app_mgr_queue, app_manager_queue_callback, NULL);
fail2: module_data_list_destroy();
fail2:
module_data_list_destroy();
fail1: bh_queue_destroy(g_app_mgr_queue);
fail1:
bh_queue_destroy(g_app_mgr_queue);
}
#include "module_config.h"

View File

@ -7,9 +7,6 @@
#define APP_MANAGER_H
#include "bh_platform.h"
#include "bh_common.h"
#include "bh_queue.h"
#include "bh_types.h"
#include "app_manager_export.h"
#include "native_interface.h"
#include "bi-inc/shared_utils.h"
@ -21,8 +18,8 @@ extern "C" {
#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
/* os_printf is defined in each platform */
#define app_manager_printf os_printf
#define SEND_ERR_RESPONSE(mid, err_msg) do { \
app_manager_printf("%s\n", err_msg); \

View File

@ -3,13 +3,11 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_common.h"
#include "bh_types.h"
#include "bh_platform.h"
#include "app_manager_host.h"
#include "app_manager.h"
#include "app_manager_export.h"
#include "coap_ext.h"
#include "bh_thread.h"
/* host communication interface */
static host_interface host_commu;
@ -235,7 +233,7 @@ int aee_host_msg_callback(void *msg, uint16_t msg_len)
bool app_manager_host_init(host_interface *interface)
{
vm_mutex_init(&host_lock);
os_mutex_init(&host_lock);
memset(&recv_ctx, 0, sizeof(recv_ctx));
host_commu.init = interface->init;
@ -255,7 +253,7 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
int size_s = size, n;
char header[16];
vm_mutex_lock(&host_lock);
os_mutex_lock(&host_lock);
/* leading bytes */
bh_memcpy_s(header, 2, leadings, 2);
@ -270,13 +268,13 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
bh_memcpy_s(header + 4, 4, &size_s, 4);
n = host_commu.send(NULL, header, 8);
if (n != 8) {
vm_mutex_unlock(&host_lock);
os_mutex_unlock(&host_lock);
return 0;
}
/* payload */
n = host_commu.send(NULL, buf, size);
vm_mutex_unlock(&host_lock);
os_mutex_unlock(&host_lock);
printf("sent %d bytes to host\n", n);
return n;

View File

@ -269,12 +269,12 @@ check_exception()
jeff_runtime_call_java(method, argc, argv, argt);
if (is_wd_started) {
vm_mutex_lock(&wd_timer->lock);
os_mutex_lock(&wd_timer->lock);
if (!wd_timer->is_interrupting) {
wd_timer->is_stopped = true;
watchdog_timer_stop(wd_timer);
}
vm_mutex_unlock(&wd_timer->lock);
os_mutex_unlock(&wd_timer->lock);
}
return !check_exception();
@ -1395,7 +1395,7 @@ check_exception()
if (applet_data->vm_instance->main_file) {
app_manager_printf("Watchdog cancel applet main thread.\n");
vm_thread_cancel(applet_data->vm_instance->main_tlr.handle);
os_thread_cancel(applet_data->vm_instance->main_tlr.handle);
/* k_thread_abort(applet_data->vm_instance->main_tlr.handle); */
}

View File

@ -5,8 +5,7 @@
#include "app_manager.h"
#include "app_manager_host.h"
#include "bh_queue.h"
#include "bh_thread.h"
#include "bh_platform.h"
#include "bi-inc/attr_container.h"
#include "event.h"
#include "watchdog.h"
@ -21,13 +20,13 @@ module_data *module_data_list;
bool module_data_list_init()
{
module_data_list = NULL;
return !vm_mutex_init(&module_data_list_lock) ? true : false;
return !os_mutex_init(&module_data_list_lock) ? true : false;
}
void module_data_list_destroy()
{
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
if (module_data_list) {
while (module_data_list) {
module_data *p = module_data_list->next;
@ -35,14 +34,14 @@ void module_data_list_destroy()
module_data_list = p;
}
}
vm_mutex_unlock(&module_data_list_lock);
vm_mutex_destroy(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
os_mutex_destroy(&module_data_list_lock);
}
static void module_data_list_add(module_data *m_data)
{
static uint32 module_id_max = 1;
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
// reserve some special ID
// TODO: check the new id is not already occupied!
if (module_id_max == 0xFFFFFFF0)
@ -55,12 +54,12 @@ static void module_data_list_add(module_data *m_data)
m_data->next = module_data_list;
module_data_list = m_data;
}
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
}
void module_data_list_remove(module_data *m_data)
{
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
if (module_data_list) {
if (module_data_list == m_data)
module_data_list = module_data_list->next;
@ -74,46 +73,46 @@ void module_data_list_remove(module_data *m_data)
p->next = p->next->next;
}
}
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
}
module_data*
module_data_list_lookup(const char *module_name)
{
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
if (module_data_list) {
module_data *p = module_data_list;
while (p) {
/* Search by module name */
if (!strcmp(module_name, p->module_name)) {
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
return p;
}
p = p->next;
}
}
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
return NULL;
}
module_data*
module_data_list_lookup_id(unsigned int module_id)
{
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
if (module_data_list) {
module_data *p = module_data_list;
while (p) {
/* Search by module name */
if (module_id == p->id) {
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
return p;
}
p = p->next;
}
}
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
return NULL;
}
@ -201,7 +200,7 @@ void release_module(module_data *m_data)
int check_modules_timer_expiry()
{
vm_mutex_lock(&module_data_list_lock);
os_mutex_lock(&module_data_list_lock);
module_data *p = module_data_list;
int ms_to_expiry = -1;
@ -215,7 +214,7 @@ int check_modules_timer_expiry()
p = p->next;
}
vm_mutex_unlock(&module_data_list_lock);
os_mutex_unlock(&module_data_list_lock);
return ms_to_expiry;
}

View File

@ -7,9 +7,8 @@
#include "native_interface.h" /* for request_t type */
#include "app_manager_host.h"
#include "bh_queue.h"
#include "bh_platform.h"
#include "bi-inc/attr_container.h"
#include "bh_thread.h"
#include "coap_ext.h"
#include "event.h"
#include "watchdog.h"
@ -429,7 +428,6 @@ wasm_app_routine(void *arg)
module_data *m_data = (module_data *) arg;
wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data;
wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
korp_tid thread = wasm_app_data->thread_id;
/* Set m_data to the VM managed instance's custom data */
wasm_runtime_set_custom_data(inst, m_data);
@ -489,8 +487,6 @@ fail2:
wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onDestroy, 0, NULL);
fail1:
vm_thread_detach(thread);
vm_thread_exit(NULL);
return NULL;
}
@ -847,7 +843,7 @@ wasm_app_module_install(request_t * msg)
}
/* Create WASM app thread. */
if (vm_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
if (os_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
(void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) {
module_data_list_remove(m_data);
SEND_ERR_RESPONSE(msg->mid,
@ -941,7 +937,7 @@ wasm_app_module_uninstall(request_t *msg)
/* Wait for wasm app thread to exit */
wasm_app_data = (wasm_data*) m_data->internal_data;
vm_thread_join(wasm_app_data->thread_id, NULL, -1);
os_thread_join(wasm_app_data->thread_id, NULL);
cleanup_app_resource(m_data);
@ -1358,7 +1354,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
total_size = (total_size + 3) & ~((uint64)3);
if (total_size >= UINT32_MAX
|| !(section->section_body =
bh_mmap(NULL, (uint32)total_size,
os_mmap(NULL, (uint32)total_size,
map_prot, map_flags))) {
app_manager_printf("Allocate executable memory failed!\n");
goto fail;
@ -1553,7 +1549,7 @@ destroy_all_aot_sections(aot_section_list_t sections)
aot_section_t *next = cur->next;
if (cur->section_body != NULL) {
if (cur->section_type == AOT_SECTION_TYPE_TEXT)
bh_munmap(cur->section_body, cur->section_body_size);
os_munmap(cur->section_body, cur->section_body_size);
else
APP_MGR_FREE(cur->section_body);
}
@ -1583,7 +1579,7 @@ destroy_part_aot_sections(aot_section_list_t *p_sections,
if (cur->section_body != NULL) {
if (cur->section_type == AOT_SECTION_TYPE_TEXT)
bh_munmap(cur->section_body, cur->section_body_size);
os_munmap(cur->section_body, cur->section_body_size);
else
APP_MGR_FREE(cur->section_body);
}

View File

@ -4,8 +4,7 @@
*/
#include "watchdog.h"
#include "bh_queue.h"
#include "bh_thread.h"
#include "bh_platform.h"
#define WATCHDOG_THREAD_PRIORITY 5
@ -20,7 +19,7 @@ static void watchdog_timer_callback(void *timer)
watchdog_timer_stop(wd_timer);
vm_mutex_lock(&wd_timer->lock);
os_mutex_lock(&wd_timer->lock);
if (!wd_timer->is_stopped) {
@ -30,7 +29,7 @@ static void watchdog_timer_callback(void *timer)
sizeof(module_data));
}
vm_mutex_unlock(&wd_timer->lock);
os_mutex_unlock(&wd_timer->lock);
}
#endif
@ -39,12 +38,12 @@ bool watchdog_timer_init(module_data *m_data)
#ifdef WATCHDOG_ENABLED /* TODO */
watchdog_timer *wd_timer = &m_data->wd_timer;
if (0 != vm_mutex_init(&wd_timer->lock))
if (0 != os_mutex_init(&wd_timer->lock))
return false;
if (!(wd_timer->timer_handle =
app_manager_timer_create(watchdog_timer_callback, wd_timer))) {
vm_mutex_destroy(&wd_timer->lock);
os_mutex_destroy(&wd_timer->lock);
return false;
}
@ -59,20 +58,20 @@ void watchdog_timer_destroy(watchdog_timer *wd_timer)
{
#ifdef WATCHDOG_ENABLED /* TODO */
app_manager_timer_destroy(wd_timer->timer_handle);
vm_mutex_destroy(&wd_timer->lock);
os_mutex_destroy(&wd_timer->lock);
#endif
}
void watchdog_timer_start(watchdog_timer *wd_timer)
{
vm_mutex_lock(&wd_timer->lock);
os_mutex_lock(&wd_timer->lock);
wd_timer->is_interrupting = false;
wd_timer->is_stopped = false;
app_manager_timer_start(wd_timer->timer_handle,
wd_timer->module_data->timeout);
vm_mutex_unlock(&wd_timer->lock);
os_mutex_unlock(&wd_timer->lock);
}
void watchdog_timer_stop(watchdog_timer *wd_timer)

View File

@ -8,6 +8,7 @@
#if !defined(BUILD_TARGET_X86_64) \
&& !defined(BUILD_TARGET_AMD_64) \
&& !defined(BUILD_TARGET_AARCH64) \
&& !defined(BUILD_TARGET_X86_32) \
&& !defined(BUILD_TARGET_ARM) \
&& !defined(BUILD_TARGET_ARM_VFP) \
@ -19,6 +20,8 @@
#define BUILD_TARGET_X86_64
#elif defined(__amd64__) || defined(__amd64)
#define BUILD_TARGET_AMD_64
#elif defined(__aarch64__)
#define BUILD_TARGET_AARCH64
#elif defined(__i386__) || defined(__i386) || defined(i386)
#define BUILD_TARGET_X86_32
#elif defined(__thumb__)
@ -36,6 +39,10 @@
#endif
#endif
#ifndef BH_DEBUG
#define BH_DEBUG 0
#endif
enum {
/* Memory allocator ems */
MEM_ALLOCATOR_EMS = 0,
@ -105,8 +112,16 @@ enum {
#define WASM_ENABLE_ABS_LABEL_ADDR 0
#endif
/* Enable opcode counter or not */
#ifndef WASM_ENABLE_OPCODE_COUNTER
#define WASM_ENABLE_OPCODE_COUNTER 0
#endif
/* Heap and stack profiling */
#define BEIHAI_ENABLE_MEMORY_PROFILING 0
#define BH_ENABLE_MEMORY_PROFILING 0
/* Heap verification */
#define BH_ENABLE_GC_VERIFY 0
/* Max app number of all modules */
#define MAX_APP_INSTALLATIONS 3
@ -144,7 +159,7 @@ enum {
/* Default min/max heap size of each app */
#define APP_HEAP_SIZE_DEFAULT (8 * 1024)
#define APP_HEAP_SIZE_MIN (2 * 1024)
#define APP_HEAP_SIZE_MAX (1024 * 1024)
#define APP_HEAP_SIZE_MAX (512 * 1024 * 1024)
/* Default wasm stack size of each app */
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)

View File

@ -140,6 +140,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
#define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */
#define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
#define E_MACHINE_ARM 40 /* ARM/Thumb */
#define E_MACHINE_AARCH64 183 /* AArch64 */
#define E_MACHINE_ARC 45 /* Argonaut RISC Core */
#define E_MACHINE_IA_64 50 /* Intel Merced */
#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */
@ -196,6 +197,7 @@ get_aot_file_target(AOTTargetInfo *target_info,
machine_type = "i386";
break;
case E_MACHINE_ARM:
case E_MACHINE_AARCH64:
machine_type = target_info->arch;
break;
case E_MACHINE_MIPS:
@ -614,6 +616,7 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
/* Create each import global */
for (i = 0; i < module->import_global_count; i++) {
buf = (uint8*)align_ptr(buf, 2);
read_uint8(buf, buf_end, import_globals[i].type);
read_uint8(buf, buf_end, import_globals[i].is_mutable);
read_string(buf, buf_end, import_globals[i].module_name);
@ -783,13 +786,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end,
if (!(import_funcs[i].func_ptr_linked =
wasm_native_resolve_symbol(module_name, field_name,
import_funcs[i].func_type,
&import_funcs[i].signature))) {
&import_funcs[i].signature,
&import_funcs[i].attachment,
&import_funcs[i].call_conv_raw))) {
LOG_WARNING("warning: fail to link import function (%s, %s)\n",
module_name, field_name);
}
#if WASM_ENABLE_LIBC_WASI != 0
if (!strcmp(import_funcs[i].module_name, "wasi_unstable"))
if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
|| !strcmp(import_funcs[i].module_name, "wasi_snapshot_preview1"))
module->is_wasi_module = true;
#endif
}
@ -829,7 +835,7 @@ destroy_object_data_sections(AOTObjectDataSection *data_sections,
AOTObjectDataSection *data_section = data_sections;
for (i = 0; i < data_section_count; i++, data_section++)
if (data_section->data)
bh_munmap(data_section->data, data_section->size);
os_munmap(data_section->data, data_section->size);
wasm_runtime_free(data_sections);
}
@ -872,7 +878,7 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end,
/* Allocate memory for data */
if (!(data_sections[i].data =
bh_mmap(NULL, data_sections[i].size, map_prot, map_flags))) {
os_mmap(NULL, data_sections[i].size, map_prot, map_flags))) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"allocate memory failed.");
@ -980,14 +986,21 @@ load_text_section(const uint8 *buf, const uint8 *buf_end,
return false;
}
module->code = (void*)buf;
module->code_size = (uint32)(buf_end - buf);
read_uint32(buf, buf_end, module->literal_size);
/* literal data is at begining of the text section */
module->literal = (uint8*)buf;
module->code = (void*)(buf + module->literal_size);
module->code_size = (uint32)(buf_end - (uint8*)module->code);
if (module->code_size > 0) {
plt_base = (uint8*)buf_end - get_plt_table_size();
init_plt_table(plt_base);
}
return true;
fail:
return false;
}
static bool
@ -1179,13 +1192,20 @@ resolve_target_sym(const char *symbol, int32 *p_index)
return NULL;
}
static bool
is_literal_relocation(const char *reloc_sec_name)
{
return !strcmp(reloc_sec_name, ".rela.literal");
}
static bool
do_text_relocation(AOTModule *module,
AOTRelocationGroup *group,
char *error_buf, uint32 error_buf_size)
{
uint8 *aot_text = module->code;
uint32 aot_text_size = module->code_size;
bool is_literal = is_literal_relocation(group->section_name);
uint8 *aot_text = is_literal ? module->literal : module->code;
uint32 aot_text_size = is_literal ? module->literal_size : module->code_size;
uint32 i, func_index, symbol_len;
char symbol_buf[128] = { 0 }, *symbol, *p;
void *symbol_addr;
@ -1243,6 +1263,9 @@ do_text_relocation(AOTModule *module,
goto check_symbol_fail;
}
}
else if (!strcmp(symbol, ".literal")) {
symbol_addr = module->literal;
}
else if (!(symbol_addr = resolve_target_sym(symbol, &symbol_index))) {
if (error_buf != NULL)
snprintf(error_buf, error_buf_size,
@ -1490,7 +1513,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
}
if (!strcmp(group->section_name, ".rel.text")
|| !strcmp(group->section_name, ".rela.text")) {
|| !strcmp(group->section_name, ".rela.text")
|| !strcmp(group->section_name, ".rela.literal")) {
if (!do_text_relocation(module, group, error_buf, error_buf_size))
return false;
}
@ -1594,12 +1618,12 @@ load_from_sections(AOTModule *module, AOTSection *sections,
/* Flush data cache before executing AOT code,
* otherwise unpredictable behavior can occur. */
bh_dcache_flush();
os_dcache_flush();
return true;
}
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
#if BH_ENABLE_MEMORY_PROFILING != 0
static void aot_free(void *ptr)
{
wasm_runtime_free(ptr);
@ -1668,7 +1692,7 @@ destroy_sections(AOTSection *section_list, bool destroy_aot_text)
if (destroy_aot_text
&& section->section_type == AOT_SECTION_TYPE_TEXT
&& section->section_body)
bh_munmap((uint8*)section->section_body, section->section_body_size);
os_munmap((uint8*)section->section_body, section->section_body_size);
wasm_runtime_free(section);
section = next;
}
@ -1719,7 +1743,7 @@ create_sections(const uint8 *buf, uint32 size,
total_size = (uint64)section_size + aot_get_plt_table_size();
total_size = (total_size + 3) & ~((uint64)3);
if (total_size >= UINT32_MAX
|| !(aot_text = bh_mmap(NULL, (uint32)total_size,
|| !(aot_text = os_mmap(NULL, (uint32)total_size,
map_prot, map_flags))) {
wasm_runtime_free(section);
set_error_buf(error_buf, error_buf_size,
@ -2074,8 +2098,11 @@ aot_unload(AOTModule *module)
if (module->const_str_set)
bh_hash_map_destroy(module->const_str_set);
if (module->code)
bh_munmap(module->code, module->code_size);
if (module->code) {
uint8 *mmap_addr = module->literal - sizeof(module->literal_size);
uint32 total_size = sizeof(module->literal_size) + module->literal_size + module->code_size;
os_munmap(mmap_addr, total_size);
}
if (module->data_sections)
destroy_object_data_sections(module->data_sections,

View File

@ -14,9 +14,8 @@ typedef struct {
#define REG_COMMON_SYMBOLS \
REG_SYM(aot_set_exception_with_id), \
REG_SYM(aot_get_exception), \
REG_SYM(aot_is_wasm_type_equal), \
REG_SYM(aot_invoke_native), \
REG_SYM(aot_call_indirect), \
REG_SYM(wasm_runtime_enlarge_memory), \
REG_SYM(wasm_runtime_set_exception), \
REG_SYM(fmin), \

View File

@ -457,7 +457,7 @@ aot_call_function(WASMExecEnv *exec_env,
AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst;
AOTFuncType *func_type = function->func_type;
bool ret = wasm_runtime_invoke_native(exec_env, function->func_ptr,
func_type, NULL, argv, argc, argv);
func_type, NULL, NULL, argv, argc, argv);
return ret && !aot_get_exception(module_inst) ? true : false;
}
@ -751,7 +751,7 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
uint32 max_page_count = module_inst->mem_max_page_count;
uint32 total_page_count = cur_page_count + inc_page_count;
uint64 total_size = (uint64)num_bytes_per_page * total_page_count;
uint32 total_size_old;
uint32 total_size_old = module_inst->memory_data_size;
if (inc_page_count <= 0)
/* No need to enlarge memory */
@ -773,14 +773,14 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
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);
}
memset(mem_data_new + total_size_old,
0, (uint32)total_size - total_size_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;
@ -811,7 +811,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
return wasm_type_equal(type1, type2);
}
void
bool
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
{
@ -824,21 +824,100 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
void **func_ptrs = (void**)module_inst->func_ptrs.ptr;
void *func_ptr = func_ptrs[func_idx];
AOTImportFunc *import_func;
const char *signature = NULL;
const char *signature;
void *attachment;
char buf[128];
if (func_idx < aot_module->import_func_count) {
import_func = aot_module->import_funcs + func_idx;
if (!func_ptr) {
snprintf(buf, sizeof(buf),
"fail to call unlinked import function (%s, %s)",
import_func->module_name, import_func->func_name);
aot_set_exception(module_inst, buf);
return;
}
signature = import_func->signature;
bh_assert(func_idx < aot_module->import_func_count);
import_func = aot_module->import_funcs + func_idx;
if (!func_ptr) {
snprintf(buf, sizeof(buf),
"fail to call unlinked import function (%s, %s)",
import_func->module_name, import_func->func_name);
aot_set_exception(module_inst, buf);
return false;
}
signature = import_func->signature;
attachment = import_func->attachment;
if (!import_func->call_conv_raw) {
return wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature, attachment,
frame_lp, argc, argv_ret);
}
else {
return wasm_runtime_invoke_native_raw(exec_env, func_ptr,
func_type, signature, attachment,
frame_lp, argc, argv_ret);
}
wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature, frame_lp, argc, argv_ret);
}
bool
aot_call_indirect(WASMExecEnv *exec_env,
bool check_func_type, uint32 func_type_idx,
uint32 table_elem_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
{
AOTModuleInstance *module_inst = (AOTModuleInstance*)
wasm_runtime_get_module_inst(exec_env);
AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr;
uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr;
uint32 *table_data = (uint32*)module_inst->table_data.ptr;
AOTFuncType *func_type;
void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr;
uint32 table_size = module_inst->table_size;
uint32 func_idx, func_type_idx1;
AOTImportFunc *import_func;
const char *signature = NULL;
void *attachment = NULL;
char buf[128];
if (table_elem_idx >= table_size) {
aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT);
return false;
}
func_idx = table_data[table_elem_idx];
if (func_idx == (uint32)-1) {
aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
return false;
}
func_type_idx1 = func_type_indexes[func_idx];
if (check_func_type
&& !aot_is_wasm_type_equal(module_inst, func_type_idx,
func_type_idx1)) {
aot_set_exception_with_id(module_inst,
EXCE_INVALID_FUNCTION_TYPE_INDEX);
return false;
}
func_type = aot_module->func_types[func_type_idx1];
if (!(func_ptr = func_ptrs[func_idx])) {
bh_assert(func_idx < aot_module->import_func_count);
import_func = aot_module->import_funcs + func_idx;
snprintf(buf, sizeof(buf),
"fail to call unlinked import function (%s, %s)",
import_func->module_name, import_func->func_name);
aot_set_exception(module_inst, buf);
return false;
}
if (func_idx < aot_module->import_func_count) {
/* Call native function */
import_func = aot_module->import_funcs + func_idx;
signature = import_func->signature;
if (import_func->call_conv_raw) {
attachment = import_func->attachment;
return wasm_runtime_invoke_native_raw(exec_env, func_ptr,
func_type, signature,
attachment,
frame_lp, argc, argv_ret);
}
}
return wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature, attachment,
frame_lp, argc, argv_ret);
}

View File

@ -125,6 +125,10 @@ typedef struct AOTModule {
void *code;
uint32 code_size;
/* literal for AOTed code, NULL for JIT mode */
uint8 *literal;
uint32 literal_size;
/* data sections in AOT object file, including .data, .rodata
* and .rodata.cstN. NULL for JIT mode. */
AOTObjectDataSection *data_sections;
@ -435,10 +439,16 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
/**
* Invoke native function from aot code
*/
void
bool
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
bool
aot_call_indirect(WASMExecEnv *exec_env,
bool check_func_type, uint32 func_type_idx,
uint32 table_elem_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
uint32
aot_get_plt_table_size();

View File

@ -0,0 +1,238 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "aot_reloc.h"
#define R_AARCH64_ADR_PREL_PG_HI21 275
#define R_AARCH64_ADD_ABS_LO12_NC 277
#define R_AARCH64_CALL26 283
static SymbolMap target_sym_map[] = {
REG_COMMON_SYMBOLS
};
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
{
if (error_buf != NULL)
snprintf(error_buf, error_buf_size, "%s", string);
}
SymbolMap *
get_target_symbol_map(uint32 *sym_num)
{
*sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
return target_sym_map;
}
void
get_current_target(char *target_buf, uint32 target_buf_size)
{
char *build_target = BUILD_TARGET;
char *p = target_buf, *p_end;
snprintf(target_buf, target_buf_size, "%s", build_target);
p_end = p + strlen(target_buf);
while (p < p_end) {
if (*p >= 'A' && *p <= 'Z')
*p++ += 'a' - 'A';
else
p++;
}
if (!strcmp(target_buf, "aarch64"))
snprintf(target_buf, target_buf_size, "aarch64v8");
}
static uint32
get_plt_item_size()
{
/* 8*4 bytes instructions and 8 bytes symbol address */
return 40;
}
void
init_plt_table(uint8 *plt)
{
uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
for (i = 0; i < num; i++) {
uint32 *p = (uint32*)plt;
*p++ = 0xd10023ff; /* sub sp, sp, #0x8 */
*p++ = 0xf90003fe; /* str x30, [sp] */
*p++ = 0x100000de; /* adr x30, #24 */
*p++ = 0xf94003de; /* ldr x30, [x30] */
*p++ = 0xd63f03c0; /* blr x30 */
*p++ = 0xf94003fe; /* ldr x30, [sp] */
*p++ = 0x910023ff; /* add sp, sp, #0x8 */
*p++ = 0xd61f03c0; /* br x30 */
/* symbol addr */
*(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
p += 2;
plt += get_plt_item_size();
}
}
uint32
get_plt_table_size()
{
return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
}
#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \
int64 m = ((int64)1 << (bits - 1)); \
val_ext = ((int64)val ^ m) - m; \
} while (0)
#define Page(expr) ((expr) & ~0xFFF)
static bool
check_reloc_offset(uint32 target_section_size,
uint64 reloc_offset, uint32 reloc_data_size,
char *error_buf, uint32 error_buf_size)
{
if (!(reloc_offset < (uint64)target_section_size
&& reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: invalid relocation offset.");
return false;
}
return true;
}
bool
apply_relocation(AOTModule *module,
uint8 *target_section_addr, uint32 target_section_size,
uint64 reloc_offset, uint64 reloc_addend,
uint32 reloc_type, void *symbol_addr, int32 symbol_index,
char *error_buf, uint32 error_buf_size)
{
switch (reloc_type) {
case R_AARCH64_CALL26:
{
void *S, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, imm26;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
imm26 = insn & 0x3FFFFFF;
SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
if (symbol_index < 0) {
/* Symbol address itself is an AOT function.
* Apply relocation with the symbol directly.
* Suppose the symbol address is in +-128MB relative
* to the relocation address.
*/
S = symbol_addr;
}
else {
uint8 *plt;
if (reloc_addend > 0) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: relocate to plt table "
"with reloc addend larger than 0 is unsupported.");
return false;
}
/* Symbol address is not an AOT function,
* but a function of runtime or native. Its address is
* beyond of the +-128MB space. Apply relocation with
* the PLT which branch to the target symbol address.
*/
S = plt = (uint8*)module->code + module->code_size
- get_plt_table_size()
+ get_plt_item_size() * symbol_index;
}
/* S + A - P */
X = (int64)S + A - (int64)P;
/* Check overflow: +-128MB */
if (X > (128 * BH_MB) || X < (-128 * BH_MB)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}
/* write the imm26 back to instruction */
*(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF));
break;
}
case R_AARCH64_ADR_PREL_PG_HI21:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, immhi19, immlo2, imm21;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
immhi19 = (insn >> 5) & 0x7FFFF;
immlo2 = (insn >> 29) & 0x3;
imm21 = (immhi19 << 2) | immlo2;
SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
/* Page(S+A) - Page(P) */
X = Page((int64)S + A) - Page((int64)P);
/* Check overflow: +-4GB */
if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}
/* write the imm21 back to instruction */
immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
immlo2 = (int32)((X >> 12) & 0x3);
*(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5);
break;
}
case R_AARCH64_ADD_ABS_LO12_NC:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, imm12;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
imm12 = (insn >> 10) & 0xFFF;
SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
/* S + A */
X = (int64)S + A;
/* No need to check overflow for this reloction type */
/* write the imm12 back to instruction */
*(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
break;
}
default:
if (error_buf != NULL)
snprintf(error_buf, error_buf_size,
"Load relocation section failed: "
"invalid relocation type %d.",
reloc_type);
return false;
}
return true;
}

View File

@ -9,10 +9,6 @@
#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL<cond>). */
#define R_ARM_ABS32 2 /* Direct 32 bit */
#ifndef BH_MB
#define BH_MB 1024 * 1024
#endif
void __divdi3();
void __udivdi3();
void __moddi3();
@ -163,7 +159,7 @@ init_plt_table(uint8 *plt)
/* nop */
*p++ = 0xe1a00000;
/* symbol addr */
*p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;;
*p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
plt += get_plt_item_size();
}
}

View File

@ -8,10 +8,6 @@
#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
#define R_ARM_THM_JMP24 30 /* B.W */
#ifndef BH_MB
#define BH_MB 1024 * 1024
#endif
void __divdi3();
void __udivdi3();
void __moddi3();

View File

@ -149,19 +149,22 @@ apply_relocation(AOTModule *module,
}
case R_X86_64_PLT32:
{
uint8 *plt = (uint8*)module->code + module->code_size - get_plt_table_size()
+ get_plt_item_size() * symbol_index;
intptr_t target_addr = (intptr_t) /* L + A - P */
(plt + reloc_addend
- (target_section_addr + reloc_offset));
uint8 *plt;
intptr_t target_addr = 0;
CHECK_RELOC_OFFSET(sizeof(int32));
if (symbol_index < 0) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"invalid symbol index for relocation");
return false;
if (symbol_index >= 0) {
plt = (uint8*)module->code + module->code_size - get_plt_table_size()
+ get_plt_item_size() * symbol_index;
target_addr = (intptr_t) /* L + A - P */
(plt + reloc_addend
- (target_section_addr + reloc_offset));
}
else {
target_addr = (intptr_t) /* L + A - P */
((uint8*)symbol_addr + reloc_addend
- (target_section_addr + reloc_offset));
}
if ((int32)target_addr != target_addr) {

View File

@ -5,10 +5,50 @@
#include "aot_reloc.h"
#define R_XTENSA_32 1 /* Direct 32 bit */
#define R_XTENSA_SLOT0_OP 20 /* PC relative */
/* for soft-float */
void __floatsidf();
void __divdf3();
void __ltdf2();
/* for mul32 */
void __mulsi3();
void __muldi3();
void __modsi3();
void __divdi3();
static SymbolMap target_sym_map[] = {
REG_COMMON_SYMBOLS
REG_COMMON_SYMBOLS,
/* API's for soft-float */
/* TODO: only register these symbols when Floating-Point Coprocessor
* Option is not enabled */
REG_SYM(__floatsidf),
REG_SYM(__divdf3),
REG_SYM(__ltdf2),
/* API's for 32-bit integer multiply */
/* TODO: only register these symbols when 32-bit Integer Multiply Option
* is not enabled */
REG_SYM(__mulsi3),
REG_SYM(__muldi3),
REG_SYM(__modsi3),
REG_SYM(__divdi3),
};
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
{
if (error_buf != NULL)
snprintf(error_buf, error_buf_size, "%s", string);
}
SymbolMap *
get_target_symbol_map(uint32 *sym_num)
{
@ -40,6 +80,67 @@ get_plt_table_size()
return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
}
static bool
check_reloc_offset(uint32 target_section_size,
uint64 reloc_offset, uint32 reloc_data_size,
char *error_buf, uint32 error_buf_size)
{
if (!(reloc_offset < (uint64)target_section_size
&& reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: invalid relocation offset.");
return false;
}
return true;
}
/*
* CPU like esp32 can read and write data through the instruction bus, but only
* in a word aligned manner; non-word-aligned access will cause a CPU exception.
* This function uses a world aligned manner to write 16bit value to instruction
* addreess.
*/
static void
put_imm16_to_addr(int16 imm16, int16 *addr)
{
int8 bytes[8];
int32 *addr_aligned1, *addr_aligned2;
addr_aligned1 = (int32*)((intptr_t)addr & ~3);
if ((intptr_t)addr % 4 != 3) {
*(int32*)bytes = *addr_aligned1;
*(int16*)(bytes + ((intptr_t)addr % 4)) = imm16;
memcpy(addr_aligned1, bytes, 4);
}
else {
addr_aligned2 = (int32*)(((intptr_t)addr + 3) & ~3);
*(int32*)bytes = *addr_aligned1;
*(int32*)(bytes + 4) = *addr_aligned2;
*(int16*)(bytes + 3) = imm16;
memcpy(addr_aligned1, bytes, 8);
}
}
static union {
int a;
char b;
} __ue = { .a = 1 };
#define is_little_endian() (__ue.b == 1)
typedef union {
struct l32r_le {
int8 other;
int16 imm16;
} __packed l;
struct l32r_be {
int16 imm16;
int8 other;
} __packed b;
} l32r_insn_t;
bool
apply_relocation(AOTModule *module,
uint8 *target_section_addr, uint32 target_section_size,
@ -48,7 +149,73 @@ apply_relocation(AOTModule *module,
char *error_buf, uint32 error_buf_size)
{
switch (reloc_type) {
/* TODO: implement relocation for xtensa */
case R_XTENSA_32:
{
uint8 *insn_addr = target_section_addr + reloc_offset;
int32 initial_addend;
/* (S + A) */
if ((intptr_t)insn_addr & 3) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"instruction address unaligned.");
return false;
}
CHECK_RELOC_OFFSET(4);
initial_addend = *(int32*)insn_addr;
*(uint8**)insn_addr
= (uint8*)symbol_addr + initial_addend + reloc_addend;
break;
}
case R_XTENSA_SLOT0_OP:
{
uint8 *insn_addr = target_section_addr + reloc_offset;
/* Currently only l32r instruction generates R_XTENSA_SLOT0_OP relocation */
l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr;
uint8 *reloc_addr;
int32 relative_offset/*, initial_addend */;
int16 imm16;
CHECK_RELOC_OFFSET(3); /* size of l32r instruction */
/*
imm16 = is_little_endian() ?
l32r_insn->l.imm16 : l32r_insn->b.imm16;
initial_addend = (int32)imm16 << 2;
*/
reloc_addr = (uint8*)symbol_addr + reloc_addend;
if ((intptr_t)reloc_addr & 3) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"relocation address unaligned.");
return false;
}
relative_offset = (int32)
((intptr_t)reloc_addr -
(((intptr_t)insn_addr + 3) & ~(intptr_t)3));
/* relative_offset += initial_addend; */
/* check relative offset boundary */
if (relative_offset < -256 * BH_KB || relative_offset > -4) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}
imm16 = (int16)(relative_offset >> 2);
/* write back the imm16 to the l32r instruction */
if (is_little_endian())
put_imm16_to_addr(imm16, &l32r_insn->l.imm16);
else
put_imm16_to_addr(imm16, &l32r_insn->b.imm16);
break;
}
default:
if (error_buf != NULL)

View File

@ -9,17 +9,19 @@ include_directories (${IWASM_AOT_DIR})
file (GLOB c_source_all ${IWASM_AOT_DIR}/*.c)
if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64")
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c)
elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c)
elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c)
elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c)
elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_thumb.c)
elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_mips.c)
elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")
elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_xtensa.c)
else ()
message (FATAL_ERROR "Build target isn't set")

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
.text
.align 2
.global invokeNative
.type invokeNative,function
/*
* Arguments passed in:
*
* x0 function ptr
* x1 argv
* x2 nstacks
*/
invokeNative:
sub sp, sp, #0x30
stp x19, x20, [sp, #0x20] /* save the registers */
stp x21, x22, [sp, #0x10]
stp x23, x24, [sp, #0x0]
mov x19, x0 /* x19 = function ptr */
mov x20, x1 /* x20 = argv */
mov x21, x2 /* x21 = nstacks */
mov x22, sp /* save the sp before call function */
/* Fill in float-point registers */
ldp d0, d1, [x20], #16 /* d0 = argv[0], d1 = argv[1] */
ldp d2, d3, [x20], #16 /* d2 = argv[2], d3 = argv[3] */
ldp d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */
ldp d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */
/* Fill inteter registers */
ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
/* Now x20 points to stack args */
/* Directly call the fucntion if no args in stack */
cmp x21, #0
beq call_func
/* Fill all stack args: reserve stack space and fill ony by one */
mov x23, sp
bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */
lsl x23, x21, #3 /* x23 = nstacks * 8 */
add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */
bic x23, x23, #15
sub sp, sp, x23 /* reserved stack space for stack arguments */
mov x23, sp
loop_stack_args: /* copy stack arguments to stack */
cmp x21, #0
beq call_func
ldr x24, [x20], #8
str x24, [x23], #8
sub x21, x21, #1
b loop_stack_args
call_func:
mov x20, x30 /* save x30(lr) */
blr x19
mov sp, x22 /* restore sp which is saved before calling fuction*/
return:
mov x30, x20 /* restore x30(lr) */
ldp x19, x20, [sp, #0x20] /* restore the registers in stack */
ldp x21, x22, [sp, #0x10]
ldp x23, x24, [sp, #0x0]
add sp, sp, #0x30 /* restore sp */
ret

View File

@ -10,27 +10,29 @@ 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")
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
if (${WAMR_BUILD_TARGET} MATCHES "ARM.*_VFP")
elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
if (WAMR_BUILD_TARGET MATCHES "ARM.*_VFP")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s)
else ()
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm.s)
endif ()
elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
if (${WAMR_BUILD_TARGET} MATCHES "THUMB.*_VFP")
elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
if (WAMR_BUILD_TARGET MATCHES "THUMB.*_VFP")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb_vfp.s)
else ()
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
endif ()
elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")
elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s)
elseif (${WAMR_BUILD_TARGET} STREQUAL "GENERAL")
elseif (WAMR_BUILD_TARGET STREQUAL "GENERAL")
# Use invokeNative_general.c instead of assembly code,
# but the maximum number of native arguments is limited to 20,
# and there are possible issues when passing arguments to

View File

@ -6,7 +6,6 @@
#ifndef _WASM_EXEC_ENV_H
#define _WASM_EXEC_ENV_H
#include "bh_thread.h"
#include "bh_assert.h"
#if WASM_ENABLE_INTERP != 0
#include "../interpreter/wasm.h"
@ -34,6 +33,11 @@ typedef struct WASMExecEnv {
uint32 *argv_buf;
#endif
/* attachment for native function */
void *attachment;
void *user_data;
/* Current interpreter frame of current thread */
struct WASMInterpFrame *cur_frame;

View File

@ -6,9 +6,8 @@
#include "wasm_runtime_common.h"
#include "bh_platform.h"
#include "mem_alloc.h"
#include "bh_thread.h"
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
#if BH_ENABLE_MEMORY_PROFILING != 0
/* Memory profile data of a function */
typedef struct memory_profile {
@ -31,7 +30,7 @@ static memory_profile_t *memory_profiles_list = NULL;
/* Lock of the memory profile list */
static korp_mutex profile_lock;
#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
#ifndef MALLOC_MEMORY_FROM_SYSTEM
@ -59,13 +58,13 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes)
if (_allocator) {
memory_mode = MEMORY_MODE_POOL;
pool_allocator = _allocator;
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
vm_mutex_init(&profile_lock);
#if BH_ENABLE_MEMORY_PROFILING != 0
os_mutex_init(&profile_lock);
#endif
global_pool_size = bytes;
return true;
}
bh_printf("Init memory with pool (%p, %u) failed.\n", mem, bytes);
LOG_ERROR("Init memory with pool (%p, %u) failed.\n", mem, bytes);
return false;
}
@ -79,12 +78,12 @@ wasm_memory_init_with_allocator(void *_malloc_func,
malloc_func = _malloc_func;
realloc_func = _realloc_func;
free_func = _free_func;
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
vm_mutex_init(&profile_lock);
#if BH_ENABLE_MEMORY_PROFILING != 0
os_mutex_init(&profile_lock);
#endif
return true;
}
bh_printf("Init memory with allocator (%p, %p, %p) failed.\n",
LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n",
_malloc_func, _realloc_func, _free_func);
return false;
}
@ -109,8 +108,8 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
void
wasm_runtime_memory_destroy()
{
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
vm_mutex_destroy(&profile_lock);
#if BH_ENABLE_MEMORY_PROFILING != 0
os_mutex_destroy(&profile_lock);
#endif
if (memory_mode == MEMORY_MODE_POOL)
mem_allocator_destroy(pool_allocator);
@ -130,7 +129,7 @@ void *
wasm_runtime_malloc(unsigned int size)
{
if (memory_mode == MEMORY_MODE_UNKNOWN) {
bh_printf("wasm_runtime_malloc failed: memory hasn't been initialize.\n");
LOG_WARNING("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);
@ -143,7 +142,7 @@ void *
wasm_runtime_realloc(void *ptr, unsigned int size)
{
if (memory_mode == MEMORY_MODE_UNKNOWN) {
bh_printf("wasm_runtime_realloc failed: memory hasn't been initialize.\n");
LOG_WARNING("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);
@ -159,7 +158,7 @@ void
wasm_runtime_free(void *ptr)
{
if (memory_mode == MEMORY_MODE_UNKNOWN) {
bh_printf("wasm_runtime_free failed: memory hasn't been initialize.\n");
LOG_WARNING("wasm_runtime_free failed: memory hasn't been initialize.\n");
} else if (memory_mode == MEMORY_MODE_POOL) {
mem_allocator_free(pool_allocator, ptr);
} else {
@ -167,17 +166,26 @@ wasm_runtime_free(void *ptr)
}
}
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
#if BH_ENABLE_MEMORY_PROFILING != 0
void
memory_profile_print(const char *file, int line,
const char *func, int alloc)
{
os_printf("location:%s@%d:used:%d:contribution:%d\n",
func, line, memory_in_use, alloc);
}
void *
wasm_runtime_malloc_profile(const char *file, int line,
const char *func, unsigned int size)
{
void *p = wasm_rutime_malloc(size + 8);
void *p = wasm_runtime_malloc(size + 8);
if (p) {
memory_profile_t *profile;
vm_mutex_lock(&profile_lock);
os_mutex_lock(&profile_lock);
profile = memory_profiles_list;
while (profile) {
@ -194,7 +202,7 @@ wasm_runtime_malloc_profile(const char *file, int line,
} else {
profile = wasm_runtime_malloc(sizeof(memory_profile_t));
if (!profile) {
vm_mutex_unlock(&profile_lock);
os_mutex_unlock(&profile_lock);
bh_memcpy_s(p, size + 8, &size, sizeof(size));
return (char *)p + 8;
}
@ -209,7 +217,7 @@ wasm_runtime_malloc_profile(const char *file, int line,
memory_profiles_list = profile;
}
vm_mutex_unlock(&profile_lock);
os_mutex_unlock(&profile_lock);
bh_memcpy_s(p, size + 8, &size, sizeof(size));
memory_in_use += size;
@ -234,7 +242,7 @@ wasm_runtime_free_profile(const char *file, int line,
if (memory_in_use >= size)
memory_in_use -= size;
vm_mutex_lock(&profile_lock);
os_mutex_lock(&profile_lock);
profile = memory_profiles_list;
while (profile) {
@ -251,7 +259,7 @@ wasm_runtime_free_profile(const char *file, int line,
} else {
profile = wasm_runtime_malloc(sizeof(memory_profile_t));
if (!profile) {
vm_mutex_unlock(&profile_lock);
os_mutex_unlock(&profile_lock);
return;
}
@ -265,7 +273,7 @@ wasm_runtime_free_profile(const char *file, int line,
memory_profiles_list = profile;
}
vm_mutex_unlock(&profile_lock);
os_mutex_unlock(&profile_lock);
}
/**
@ -277,11 +285,11 @@ void memory_usage_summarize()
{
memory_profile_t *profile;
vm_mutex_lock(&profile_lock);
os_mutex_lock(&profile_lock);
profile = memory_profiles_list;
while (profile) {
bh_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
os_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
profile->total_malloc,
profile->malloc_num,
profile->total_free,
@ -290,18 +298,10 @@ void memory_usage_summarize()
profile = profile->next;
}
vm_mutex_unlock(&profile_lock);
os_mutex_unlock(&profile_lock);
}
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);
}
#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
#else /* else of MALLOC_MEMORY_FROM_SYSTEM */
@ -325,7 +325,7 @@ wasm_runtime_free(void *ptr)
free(ptr);
}
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
#if BH_ENABLE_MEMORY_PROFILING != 0
void *
wasm_runtime_malloc_profile(const char *file, int line,
const char *func, unsigned int size)
@ -367,6 +367,6 @@ wasm_runtime_free_profile(const char *file, int line,
if (ptr)
free(ptr);
}
#endif /* end of BEIHAI_ENABLE_MEMORY_PROFILING */
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
#endif /* end of MALLOC_MEMORY_FROM_SYSTEM*/

View File

@ -110,7 +110,7 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
static void *
lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
const char *symbol, const char **p_signature)
const char *symbol, const char **p_signature, void **p_attachment)
{
int low = 0, mid, ret;
int high = n_native_symbols - 1;
@ -120,6 +120,7 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
ret = strcmp(symbol, native_symbols[mid].symbol);
if (ret == 0) {
*p_signature = native_symbols[mid].signature;
*p_attachment = native_symbols[mid].attachment;
return native_symbols[mid].func_ptr;
}
else if (ret < 0)
@ -133,11 +134,12 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
void*
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
const WASMType *func_type, const char **p_signature)
const WASMType *func_type, const char **p_signature,
void **p_attachment, bool *p_call_conv_raw)
{
NativeSymbolsNode *node, *node_next;
const char *signature = NULL;
void *func_ptr = NULL;
void *func_ptr = NULL, *attachment;
node = g_native_symbols_list;
while (node) {
@ -145,11 +147,12 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
if (!strcmp(node->module_name, module_name)) {
if ((func_ptr = lookup_symbol(node->native_symbols,
node->n_native_symbols,
field_name, &signature))
field_name, &signature, &attachment))
|| (field_name[0] == '_'
&& (func_ptr = lookup_symbol(node->native_symbols,
node->n_native_symbols,
field_name + 1, &signature))))
field_name + 1,
&signature, &attachment))))
break;
}
node = node_next;
@ -172,15 +175,19 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
else
/* signature is empty */
*p_signature = NULL;
*p_attachment = attachment;
*p_call_conv_raw = node->call_conv_raw;
}
return func_ptr;
}
bool
wasm_native_register_natives(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols)
static bool
register_natives(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols,
bool call_conv_raw)
{
NativeSymbolsNode *node;
@ -190,6 +197,7 @@ wasm_native_register_natives(const char *module_name,
node->module_name = module_name;
node->native_symbols = native_symbols;
node->n_native_symbols = n_native_symbols;
node->call_conv_raw = call_conv_raw;
node->next = NULL;
if (g_native_symbols_list_end) {
@ -204,6 +212,22 @@ wasm_native_register_natives(const char *module_name,
return true;
}
bool
wasm_native_register_natives(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols)
{
return register_natives(module_name, native_symbols, n_native_symbols, false);
}
bool
wasm_native_register_natives_raw(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols)
{
return register_natives(module_name, native_symbols, n_native_symbols, true);
}
bool
wasm_native_init()
{
@ -227,6 +251,9 @@ wasm_native_init()
if (!wasm_native_register_natives("wasi_unstable",
native_symbols, n_native_symbols))
return false;
if (!wasm_native_register_natives("wasi_snapshot_preview1",
native_symbols, n_native_symbols))
return false;
#endif
#if WASM_ENABLE_BASE_LIB != 0

View File

@ -19,6 +19,7 @@ typedef struct NativeSymbolsNode {
const char *module_name;
NativeSymbol *native_symbols;
uint32 n_native_symbols;
bool call_conv_raw;
} NativeSymbolsNode, *NativeSymbolsList;
/**
@ -50,13 +51,19 @@ wasm_native_lookup_libc_builtin_global(const char *module_name,
*/
void*
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
const WASMType *func_type, const char **p_signature);
const WASMType *func_type, const char **p_signature,
void **p_attachment, bool *p_call_conv_raw);
bool
wasm_native_register_natives(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols);
bool
wasm_native_register_natives_raw(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols);
bool
wasm_native_init();

View File

@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "config.h"
#include "bh_platform.h"
#include "bh_common.h"
#include "bh_assert.h"
@ -30,18 +29,25 @@ wasm_runtime_env_init()
if (bh_platform_init() != 0)
return false;
if (bh_log_init() != 0)
return false;
if (vm_thread_sys_init() != 0)
return false;
if (wasm_native_init() == false)
if (wasm_native_init() == false) {
bh_platform_destroy();
return false;
}
return true;
}
static bool
wasm_runtime_env_check(WASMExecEnv *exec_env)
{
return !(!exec_env
|| !exec_env->module_inst
|| exec_env->wasm_stack_size == 0
|| exec_env->wasm_stack.s.top_boundary !=
exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size
|| exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary);
}
bool
wasm_runtime_init()
{
@ -60,7 +66,7 @@ void
wasm_runtime_destroy()
{
wasm_native_destroy();
vm_thread_sys_destroy();
bh_platform_destroy();
wasm_runtime_memory_destroy();
}
@ -238,6 +244,24 @@ wasm_runtime_get_module_inst(WASMExecEnv *exec_env)
return wasm_exec_env_get_module_inst(exec_env);
}
void *
wasm_runtime_get_function_attachment(WASMExecEnv *exec_env)
{
return exec_env->attachment;
}
void
wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data)
{
exec_env->user_data = user_data;
}
void *
wasm_runtime_get_user_data(WASMExecEnv *exec_env)
{
return exec_env->user_data;
}
WASMFunctionInstanceCommon *
wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst,
const char *name,
@ -263,17 +287,12 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
unsigned argc, uint32 argv[])
{
if (!exec_env
|| !exec_env->module_inst
|| exec_env->wasm_stack_size == 0
|| exec_env->wasm_stack.s.top_boundary !=
exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size
|| exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary) {
if (!wasm_runtime_env_check(exec_env)) {
LOG_ERROR("Invalid exec env stack info.");
return false;
}
exec_env->handle = vm_self_thread();
exec_env->handle = os_self_thread();
#if WASM_ENABLE_INTERP != 0
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
@ -1375,34 +1394,38 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
/* print return value */
switch (type->types[type->param_count]) {
case VALUE_TYPE_I32:
bh_printf("0x%x:i32", argv1[0]);
os_printf("0x%x:i32", argv1[0]);
break;
case VALUE_TYPE_I64:
{
char buf[16];
union { uint64 val; uint32 parts[2]; } u;
u.parts[0] = argv1[0];
u.parts[1] = argv1[1];
#ifdef PRIx64
os_printf("0x%"PRIx64":i64", u.val);
#else
char buf[16];
if (sizeof(long) == 4)
snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
else
snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
bh_printf(buf, u.val);
os_printf(buf, u.val);
#endif
break;
}
case VALUE_TYPE_F32:
bh_printf("%.7g:f32", *(float32*)argv1);
os_printf("%.7g:f32", *(float32*)argv1);
break;
case VALUE_TYPE_F64:
{
union { float64 val; uint32 parts[2]; } u;
u.parts[0] = argv1[0];
u.parts[1] = argv1[1];
bh_printf("%.7g:f64", u.val);
os_printf("%.7g:f64", u.val);
break;
}
}
bh_printf("\n");
os_printf("\n");
wasm_runtime_free(argv1);
return true;
@ -1413,7 +1436,7 @@ fail:
exception = wasm_runtime_get_exception(module_inst);
bh_assert(exception);
bh_printf("%s\n", exception);
os_printf("%s\n", exception);
return false;
}
@ -1426,6 +1449,120 @@ wasm_runtime_register_natives(const char *module_name,
native_symbols, n_native_symbols);
}
bool
wasm_runtime_register_natives_raw(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols)
{
return wasm_native_register_natives_raw(module_name,
native_symbols, n_native_symbols);
}
bool
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *argv_ret)
{
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
typedef void (*NativeRawFuncPtr)(WASMExecEnv*, uint64*);
NativeRawFuncPtr invokeNativeRaw = (NativeRawFuncPtr)func_ptr;
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size;
uint32 *argv_src = argv, i, argc1, ptr_len;
int32 arg_i32;
bool ret = false;
argc1 = func_type->param_count;
if (argc1 > sizeof(argv_buf) / sizeof(uint64)) {
size = sizeof(uint64) * (uint64)argc1;
if (size >= UINT32_MAX
|| !(argv1 = wasm_runtime_malloc((uint32)size))) {
wasm_runtime_set_exception(exec_env->module_inst,
"allocate memory failed.");
return false;
}
memset(argv1, 0, (uint32)size);
}
argv_dst = argv1;
/* Traverse secondly to fill in each argument */
for (i = 0; i < func_type->param_count; i++, argv_dst++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
{
*(int32*)argv_dst = arg_i32 = (int32)*argv_src++;
if (signature) {
if (signature[i + 1] == '*') {
/* param is a pointer */
if (signature[i + 2] == '~')
/* pointer with length followed */
ptr_len = *argv_src;
else
/* pointer without length followed */
ptr_len = 1;
if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len))
goto fail;
*(uintptr_t*)argv_dst = (uintptr_t)
wasm_runtime_addr_app_to_native(module, arg_i32);
}
else if (signature[i + 1] == '$') {
/* param is a string */
if (!wasm_runtime_validate_app_str_addr(module, arg_i32))
goto fail;
*(uintptr_t*)argv_dst = (uintptr_t)
wasm_runtime_addr_app_to_native(module, arg_i32);
}
}
break;
}
case VALUE_TYPE_I64:
case VALUE_TYPE_F64:
bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, sizeof(uint32) * 2);
argv_src += 2;
break;
case VALUE_TYPE_F32:
*(float32*)argv_dst = *(float32*)argv_src++;
break;
default:
bh_assert(0);
break;
}
}
exec_env->attachment = attachment;
invokeNativeRaw(exec_env, argv1);
exec_env->attachment = NULL;
if (func_type->result_count > 0) {
switch (func_type->types[func_type->param_count]) {
case VALUE_TYPE_I32:
argv_ret[0] = *(uint32*)argv1;
break;
case VALUE_TYPE_F32:
*(float32*)argv_ret = *(float32*)argv1;
break;
case VALUE_TYPE_I64:
case VALUE_TYPE_F64:
bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1, sizeof(uint64));
break;
default:
bh_assert(0);
break;
}
}
ret = true;
fail:
if (argv1 != argv_buf)
wasm_runtime_free(argv1);
return ret;
}
/**
* Implementation of wasm_runtime_invoke_native()
*/
@ -1474,6 +1611,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *argv_ret)
{
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
@ -1639,6 +1777,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
}
}
exec_env->attachment = attachment;
if (func_type->result_count == 0) {
invokeNative_Void(func_ptr, argv1, n_stacks);
}
@ -1661,6 +1800,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
}
exec_env->attachment = NULL;
ret = true;
@ -1694,6 +1834,7 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *argv_ret)
{
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
@ -1779,6 +1920,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
}
argc1 = j;
exec_env->attachment = attachment;
if (func_type->result_count == 0) {
invokeNative_Void(func_ptr, argv1, argc1);
}
@ -1801,6 +1943,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
}
exec_env->attachment = NULL;
ret = true;
@ -1816,7 +1959,9 @@ fail:
|| defined(BUILD_TARGET_MIPS) \
|| defined(BUILD_TARGET_XTENSA) */
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
#if defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64)
typedef void (*GenericFunctionPointer)();
int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks);
@ -1826,23 +1971,28 @@ typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64*,uint64);
typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64*, uint64);
typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64*, uint64);
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative;
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)(uintptr_t)invokeNative;
static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)(uintptr_t)invokeNative;
static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)(uintptr_t)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)(uintptr_t)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative;
#if defined(_WIN32) || defined(_WIN32_)
#define MAX_REG_FLOATS 4
#define MAX_REG_INTS 4
#else
#define MAX_REG_FLOATS 8
#if defined(BUILD_TARGET_AARCH64)
#define MAX_REG_INTS 8
#else
#define MAX_REG_INTS 6
#endif
#endif /* end of defined(BUILD_TARGET_AARCH64 */
#endif /* end of defined(_WIN32) || defined(_WIN32_) */
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *argv_ret)
{
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
@ -1937,6 +2087,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
}
}
exec_env->attachment = attachment;
if (func_type->result_count == 0) {
invokeNative_Void(func_ptr, argv1, n_stacks);
}
@ -1959,6 +2110,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
}
exec_env->attachment = NULL;
ret = true;
fail:
@ -1968,4 +2120,33 @@ fail:
return ret;
}
#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env,
uint32_t element_indices,
uint32_t argc, uint32_t argv[])
{
if (!wasm_runtime_env_check(exec_env)) {
LOG_ERROR("Invalid exec env stack info.");
return false;
}
exec_env->handle = os_self_thread();
#if WASM_ENABLE_INTERP != 0
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
return wasm_call_indirect(exec_env,
element_indices,
argc, argv);
#endif
#if WASM_ENABLE_AOT != 0
if (exec_env->module_inst->module_type == Wasm_Module_AoT)
return aot_call_indirect(exec_env, false, 0,
element_indices,
argv, argc, argv);
#endif
return false;
}
#endif /* end of defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) */

View File

@ -8,7 +8,6 @@
#include "bh_platform.h"
#include "bh_common.h"
#include "bh_thread.h"
#include "wasm_exec_env.h"
#include "wasm_native.h"
#include "../include/wasm_export.h"
@ -114,12 +113,46 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
WASMModuleInstanceCommon *
wasm_runtime_get_module_inst(WASMExecEnv *exec_env);
/* See wasm_export.h for description */
void *
wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
/* See wasm_export.h for description */
void
wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
/* See wasm_export.h for description */
void *
wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
/* See wasm_export.h for description */
bool
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
unsigned argc, uint32 argv[]);
/**
* Call a function reference of a given WASM runtime instance with
* arguments.
*
* @param exec_env the execution environment to call the function
* which must be created from wasm_create_exec_env()
* @param element_indices the function ference indicies, usually
* prvovided by the caller of a registed native function
* @param argc the number of arguments
* @param argv the arguments. If the function method has return value,
* the first (or first two in case 64-bit return value) element of
* argv stores the return value of the called WASM function after this
* function returns.
*
* @return true if success, false otherwise and exception will be thrown,
* the caller can call wasm_runtime_get_exception to get exception info.
*/
bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env,
uint32_t element_indices,
uint32_t argc, uint32_t argv[]);
bool
wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst,
WASMFunctionInstanceCommon *function,
@ -258,6 +291,7 @@ wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst,
WASIContext *
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
#endif /* end of WASM_ENABLE_LIBC_WASI */
/**
@ -276,11 +310,23 @@ wasm_runtime_register_natives(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols);
/* See wasm_export.h for description */
bool
wasm_runtime_register_natives_raw(const char *module_name,
NativeSymbol *native_symbols,
uint32 n_native_symbols);
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *ret);
bool
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,
void *attachment,
uint32 *argv, uint32 argc, uint32 *ret);
#ifdef __cplusplus
}

View File

@ -265,6 +265,8 @@ aot_create_import_funcs(const WASMModule *module)
import_funcs[i].func_ptr_linked = import_func->func_ptr_linked;
import_funcs[i].func_type = import_func->func_type;
import_funcs[i].signature = import_func->signature;
import_funcs[i].attachment = import_func->attachment;
import_funcs[i].call_conv_raw = import_func->call_conv_raw;
/* Resolve function type index */
for (j = 0; j < module->type_count; j++)
if (import_func->func_type == module->types[j]) {

View File

@ -85,6 +85,9 @@ typedef struct AOTImportFunc {
void *func_ptr_linked;
/* signature from registered native symbols */
const char *signature;
/* attachment */
void *attachment;
bool call_conv_raw;
} AOTImportFunc;
/**

View File

@ -727,6 +727,8 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
bool ret;
uint32 i;
bh_print_time("Begin to compile WASM bytecode to LLVM IR");
for (i = 0; i < comp_ctx->func_ctx_count; i++)
if (!aot_compile_func(comp_ctx, i)) {
#if 0
@ -744,6 +746,8 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
errno = 0;
#endif
bh_print_time("Begin to verify LLVM module");
ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
if (!ret && msg) {
if (msg[0] != '\0') {
@ -754,6 +758,8 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
LLVMDisposeMessage(msg);
}
bh_print_time("Begin to run function optimization passes");
if (comp_ctx->optimize) {
LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr);
for (i = 0; i < comp_ctx->func_ctx_count; i++)
@ -769,6 +775,8 @@ aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
{
char *err = NULL;
bh_print_time("Begin to emit LLVM IR file");
if (LLVMPrintModuleToFile(comp_ctx->module, file_name, &err) != 0) {
if (err) {
LLVMDisposeMessage(err);
@ -786,6 +794,8 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
{
char *err = NULL;
bh_print_time("Begin to emit object file");
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
comp_ctx->module,
file_name,

View File

@ -49,6 +49,10 @@ typedef struct AOTObjectData {
void *text;
uint32 text_size;
/* literal data and size */
void *literal;
uint32 literal_size;
AOTObjectDataSection *data_sections;
uint32 data_sections_count;
@ -379,7 +383,7 @@ get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
static uint32
get_text_section_size(AOTObjectData *obj_data)
{
return obj_data->text_size;
return (sizeof(uint32) + obj_data->literal_size + obj_data->text_size + 3) & ~3;
}
static uint32
@ -1118,13 +1122,20 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
{
uint32 section_size = get_text_section_size(obj_data);
uint32 offset = *p_offset;
uint8 placeholder = 0;
*p_offset = offset = align_uint(offset, 4);
EMIT_U32(AOT_SECTION_TYPE_TEXT);
EMIT_U32(section_size);
EMIT_U32(obj_data->literal_size);
if (obj_data->literal_size > 0)
EMIT_BUF(obj_data->literal, obj_data->literal_size);
EMIT_BUF(obj_data->text, obj_data->text_size);
while (offset & 3)
EMIT_BUF(&placeholder, 1);
if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
aot_set_last_error("emit text section failed.");
return false;
@ -1449,6 +1460,29 @@ aot_resolve_text(AOTObjectData *obj_data)
return true;
}
static bool
aot_resolve_literal(AOTObjectData *obj_data)
{
LLVMSectionIteratorRef sec_itr;
char *name;
if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
aot_set_last_error("llvm get section iterator failed.");
return false;
}
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".literal")) {
obj_data->literal = (char *)LLVMGetSectionContents(sec_itr);
obj_data->literal_size = (uint32)LLVMGetSectionSize(sec_itr);
break;
}
LLVMMoveToNextSection(sec_itr);
}
LLVMDisposeSectionIterator(sec_itr);
return true;
}
static bool
is_data_section(char *section_name)
{
@ -1701,6 +1735,7 @@ is_relocation_section(char *section_name)
{
return (!strcmp(section_name, ".rela.text")
|| !strcmp(section_name, ".rel.text")
|| !strcmp(section_name, ".rela.literal")
|| !strcmp(section_name, ".rela.data")
|| !strcmp(section_name, ".rel.data")
|| !strcmp(section_name, ".rela.rodata")
@ -1837,6 +1872,8 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
char *err = NULL;
AOTObjectData *obj_data;
bh_print_time("Begin to emit object file to buffer");
if (!(obj_data = wasm_runtime_malloc(sizeof(AOTObjectData)))) {
aot_set_last_error("allocate memory failed.");
return false;
@ -1866,9 +1903,12 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
goto fail;
}
bh_print_time("Begin to resolve object file info");
/* resolve target info/text/relocations/functions */
if (!aot_resolve_target_info(comp_ctx, obj_data)
|| !aot_resolve_text(obj_data)
|| !aot_resolve_literal(obj_data)
|| !aot_resolve_object_data_sections(obj_data)
|| !aot_resolve_object_relocation_groups(obj_data)
|| !aot_resolve_functions(comp_ctx, obj_data))
@ -1894,6 +1934,8 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
if (!obj_data)
return false;
bh_print_time("Begin to emit AOT file");
aot_file_size = get_aot_file_size(comp_data, obj_data);
if (!(buf = aot_file_buf = wasm_runtime_malloc(aot_file_size))) {

View File

@ -8,41 +8,17 @@
#include "aot_emit_control.h"
#include "../aot/aot_runtime.h"
/* Check whether there was exception thrown, if yes, return directly */
static bool
check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
LLVMBasicBlockRef block_curr, check_exce_succ;
LLVMValueRef value, cmp;
/* Load the first byte of aot_module_inst->cur_exception, and check
whether it is '\0'. If yes, no exception was thrown. */
if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
"exce_value"))
|| !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
value, I8_ZERO, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
/* Add check exection success block */
if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_exce_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
/* Create function return block if it isn't created */
if (!func_ctx->func_return_block) {
if (!(func_ctx->func_return_block =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"func_ret"))) {
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func, "func_ret"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
@ -70,6 +46,42 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
}
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
return true;
}
/* Check whether there was exception thrown, if yes, return directly */
static bool
check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
LLVMBasicBlockRef block_curr, check_exce_succ;
LLVMValueRef value, cmp;
/* Create function return block if it isn't created */
if (!create_func_return_block(comp_ctx, func_ctx))
return false;
/* Load the first byte of aot_module_inst->cur_exception, and check
whether it is '\0'. If yes, no exception was thrown. */
if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
"exce_value"))
|| !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
value, I8_ZERO, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
/* Add check exection success block */
if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_exce_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
/* Create condition br */
if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
@ -82,18 +94,59 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
return true;
}
/* Check whether there was exception thrown, if yes, return directly */
static bool
check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef res)
{
LLVMBasicBlockRef block_curr, check_call_succ;
LLVMValueRef cmp;
/* Create function return block if it isn't created */
if (!create_func_return_block(comp_ctx, func_ctx))
return false;
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE,
res, I8_ZERO, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
/* Add check exection success block */
if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_exce_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMMoveBasicBlockAfter(check_call_succ, block_curr);
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
/* Create condition br */
if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
check_call_succ, func_ctx->func_return_block)) {
aot_set_last_error("llvm build cond br failed.");
return false;
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ);
return true;
}
static bool
call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef func_idx, AOTFuncType *aot_func_type,
LLVMTypeRef *param_types, LLVMValueRef *param_values,
uint32 param_count, uint32 param_cell_num,
LLVMTypeRef ret_type, uint8 wasm_ret_type,
LLVMValueRef *p_value_ret)
LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
{
LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
LLVMTypeRef ret_ptr_type, elem_ptr_type;
LLVMValueRef func, elem_idx, elem_ptr;
LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res;
LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res;
char buf[32], *func_name = "aot_invoke_native";
uint32 i, cell_num = 0;
@ -103,7 +156,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */
func_param_types[3] = I32_TYPE; /* argc */
func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */
if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) {
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
aot_set_last_error("llvm add function type failed.");
return false;
}
@ -198,7 +251,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* call aot_invoke_native() function */
if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) {
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
func_param_values, 5, "res"))) {
aot_set_last_error("llvm build call failed.");
return false;
}
@ -207,6 +261,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* get function return value */
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
*p_res = res;
return true;
}
@ -221,7 +276,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *func_type;
LLVMTypeRef *param_types = NULL, ret_type;
LLVMValueRef *param_values = NULL, value_ret = NULL, func;
LLVMValueRef import_func_idx;
LLVMValueRef import_func_idx, res;
int32 i, j = 0, param_count;
uint64 total_size;
uint8 wasm_ret_type;
@ -292,13 +347,17 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type,
param_types + 1, param_values + 1,
param_count, param_cell_num,
ret_type, wasm_ret_type, &value_ret))
ret_type, wasm_ret_type, &value_ret, &res))
goto fail;
/* Check whether there was exception thrown when executing the function */
if (!check_call_return(comp_ctx, func_ctx, res))
goto fail;
}
else {
func = func_ctxes[func_idx - import_func_count]->func;
/* Call the function */
/* Call the function */
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
param_values, (uint32)param_count + 1,
(func_type->result_count > 0
@ -309,15 +368,15 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Set calling convention for the call with the func's calling convention */
LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func));
/* Check whether there was exception thrown when executing the function */
if (!check_exception_thrown(comp_ctx, func_ctx))
goto fail;
}
if (func_type->result_count > 0)
PUSH(value_ret, func_type->types[func_type->param_count]);
/* Check whether there was exception thrown when executing the function */
if (!check_exception_thrown(comp_ctx, func_ctx))
goto fail;
ret = true;
fail:
if (param_types)
@ -327,21 +386,150 @@ fail:
return ret;
}
static bool
call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *aot_func_type,
LLVMValueRef func_type_idx, LLVMValueRef table_elem_idx,
LLVMTypeRef *param_types, LLVMValueRef *param_values,
uint32 param_count, uint32 param_cell_num,
LLVMTypeRef ret_type, uint8 wasm_ret_type,
LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
{
LLVMTypeRef func_type, func_ptr_type, func_param_types[7];
LLVMTypeRef ret_ptr_type, elem_ptr_type;
LLVMValueRef func, elem_idx, elem_ptr;
LLVMValueRef func_param_values[7], value_ret = NULL, value_ret_ptr, res = NULL;
char buf[32], *func_name = "aot_call_indirect";
uint32 i, cell_num = 0;
/* prepare function type of aot_call_indirect */
func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
func_param_types[1] = INT8_TYPE; /* check_func_type */
func_param_types[2] = I32_TYPE; /* func_type_idx */
func_param_types[3] = I32_TYPE; /* table_elem_idx */
func_param_types[4] = INT32_PTR_TYPE; /* frame_lp */
func_param_types[5] = I32_TYPE; /* argc */
func_param_types[6] = INT32_PTR_TYPE; /* argv_ret */
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 7, false))) {
aot_set_last_error("llvm add function type failed.");
return false;
}
/* prepare function pointer */
if (comp_ctx->is_jit_mode) {
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
return false;
}
/* JIT mode, call the function directly */
if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect))
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
aot_set_last_error("create LLVM value failed.");
return false;
}
}
else {
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
&& !(func = LLVMAddFunction(comp_ctx->module,
func_name, func_type))) {
aot_set_last_error("add LLVM function failed.");
return false;
}
}
if (param_count > 64) {
aot_set_last_error("prepare native arguments failed: "
"maximum 64 parameter cell number supported.");
return false;
}
/* prepare frame_lp */
for (i = 0; i < param_count; i++) {
if (!(elem_idx = I32_CONST(cell_num))
|| !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
aot_set_last_error("llvm add const or pointer type failed.");
return false;
}
snprintf(buf, sizeof(buf), "%s%d", "elem", i);
if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->argv_buf, &elem_idx, 1, buf))
|| !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
elem_ptr_type, buf))) {
aot_set_last_error("llvm build bit cast failed.");
return false;
}
if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) {
aot_set_last_error("llvm build store failed.");
return false;
}
LLVMSetAlignment(res, 1);
cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
}
if (wasm_ret_type != VALUE_TYPE_VOID) {
if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
aot_set_last_error("llvm add pointer type failed.");
return false;
}
if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
ret_ptr_type, "argv_ret"))) {
aot_set_last_error("llvm build bit cast failed.");
return false;
}
/* convert to int32 pointer */
if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
INT32_PTR_TYPE, "argv_ret_ptr"))) {
aot_set_last_error("llvm build store failed.");
return false;
}
}
else {
value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
}
func_param_values[0] = func_ctx->exec_env;
func_param_values[1] = I8_CONST(true);
func_param_values[2] = func_type_idx;
func_param_values[3] = table_elem_idx;
func_param_values[4] = func_ctx->argv_buf;
func_param_values[5] = I32_CONST(param_cell_num);
func_param_values[6] = value_ret_ptr;
if (!func_param_values[1] || !func_param_values[4]) {
aot_set_last_error("llvm create const failed.");
return false;
}
/* call aot_call_indirect() function */
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
func_param_values, 7, "res"))) {
aot_set_last_error("llvm build call failed.");
return false;
}
if (wasm_ret_type != VALUE_TYPE_VOID)
/* get function return value */
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
*p_res = res;
return true;
}
bool
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 type_idx)
{
AOTFuncType *func_type;
LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx;
LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch;
LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr;
LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret;
LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type,
f_type, f_ptr_type;
LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ;
LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ;
char *func_name = "aot_is_wasm_type_equal";
int32 i, j = 0, param_count;
LLVMValueRef elem_idx, ftype_idx;
LLVMValueRef *param_values = NULL, value_ret = NULL, res = NULL;
LLVMTypeRef *param_types = NULL, ret_type;
int32 i, param_count;
uint32 param_cell_num;
uint64 total_size;
uint8 wasm_ret_type;
@ -353,210 +541,26 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false;
}
ftype_idx = I32_CONST(type_idx);
CHECK_LLVM_CONST(ftype_idx);
func_type = comp_ctx->comp_data->func_types[type_idx];
param_cell_num = wasm_type_param_cell_num(func_type);
POP_I32(elem_idx);
table_size_const = I32_CONST(comp_ctx->comp_data->table_size);
CHECK_LLVM_CONST(table_size_const);
/* Check if (uint32)elem index >= table size */
if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE,
elem_idx, table_size_const,
"cmp_elem_idx"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
/* Throw exception if elem index >= table size */
if (!(check_elem_idx_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_elem_idx_succ"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_elem_idx_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT,
true, cmp_elem_idx, check_elem_idx_succ)))
goto fail;
/* Load function index */
if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->table_base,
&elem_idx, 1, "table_elem"))) {
aot_set_last_error("llvm build add failed.");
goto fail;
}
if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
/* Check if func_idx == -1 */
if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
func_idx, I32_NEG_ONE,
"cmp_func_idx"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
/* Throw exception if func_idx == -1 */
if (!(check_func_idx_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_func_idx_succ"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_func_idx_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT,
true, cmp_func_idx, check_func_idx_succ)))
goto fail;
/* Load function type index */
if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->func_type_indexes,
&func_idx, 1,
"ftype_idx_ptr"))) {
aot_set_last_error("llvm build inbounds gep failed.");
goto fail;
}
if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr,
"ftype_idx"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
/* Call aot_is_type_equal() to check whether function type match */
param_types_tmp[0] = INT8_PTR_TYPE;
param_types_tmp[1] = I32_TYPE;
param_types_tmp[2] = I32_TYPE;
ret_type = INT8_TYPE;
/* Create function type */
if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp,
3, false))) {
aot_set_last_error("create LLVM function type failed.");
goto fail;
}
if (comp_ctx->is_jit_mode) {
/* Create function type */
if (!(f_ptr_type = LLVMPointerType(f_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
goto fail;
}
/* Create LLVM function with const function pointer */
if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal))
|| !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) {
aot_set_last_error("create LLVM value failed.");
goto fail;
}
}
else {
/* Create LLVM function with external function pointer */
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
&& !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) {
aot_set_last_error("add LLVM function failed.");
goto fail;
}
}
/* Call the aot_is_type_equal() function */
param_values_tmp[0] = func_ctx->aot_inst;
param_values_tmp[1] = I32_CONST(type_idx);
param_values_tmp[2] = ftype_idx;
CHECK_LLVM_CONST(param_values_tmp[1]);
if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func,
param_values_tmp, 3,
"is_ftype_match"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
is_ftype_match, I8_ZERO,
"is_ftype_mismatch"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
if (!(check_ftype_idx_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_ftype_idx_success"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_ftype_idx_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX,
true, is_ftype_mismatch, check_ftype_idx_succ)))
goto fail;
/* Load function pointer */
if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs,
&func_idx, 1, "func_ptr"))) {
aot_set_last_error("llvm build inbounds gep failed.");
goto fail;
}
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
/* Check whether import function is NULL */
if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) {
aot_set_last_error("llvm build is null failed.");
goto fail;
}
/* Throw exception if import function is NULL */
if (!(check_func_ptr_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_func_ptr_succ"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_func_ptr_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx,
EXCE_CALL_UNLINKED_IMPORT_FUNC,
true, cmp_func_ptr, check_func_ptr_succ)))
goto fail;
/* Initialize parameter types of the LLVM function */
param_count = (int32)func_type->param_count;
total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
total_size = sizeof(LLVMTypeRef) * (uint64)param_count;
if (total_size >= UINT32_MAX
|| !(param_types = wasm_runtime_malloc((uint32)total_size))) {
aot_set_last_error("Allocate memory failed.");
goto fail;
}
j = 0;
param_types[j++] = comp_ctx->exec_env_type;
for (i = 0; i < param_count; i++)
param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
param_types[i] = TO_LLVM_TYPE(func_type->types[i]);
/* Resolve return type of the LLVM function */
if (func_type->result_count) {
@ -569,32 +573,30 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* Allocate memory for parameters */
total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1);
total_size = sizeof(LLVMValueRef) * (uint64)param_count;
if (total_size >= UINT32_MAX
|| !(param_values = wasm_runtime_malloc((uint32)total_size))) {
aot_set_last_error("Allocate memory failed.");
goto fail;
}
/* First parameter is exec env */
j = 0;
param_values[j++] = func_ctx->exec_env;
/* Pop parameters from stack */
for (i = param_count - 1; i >= 0; i--)
POP(param_values[i + j], func_type->types[i]);
POP(param_values[i], func_type->types[i]);
if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type,
param_types + 1, param_values + 1,
if (!call_aot_call_indirect_func(comp_ctx, func_ctx,
func_type, ftype_idx, elem_idx,
param_types, param_values,
param_count, param_cell_num,
ret_type, wasm_ret_type, &value_ret))
ret_type, wasm_ret_type,
&value_ret, &res))
goto fail;
if (func_type->result_count > 0)
PUSH(value_ret, func_type->types[func_type->param_count]);
/* Check whether there was exception thrown when executing the function */
if (!check_exception_thrown(comp_ctx, func_ctx))
if (!check_call_return(comp_ctx, func_ctx, res))
goto fail;
ret = true;

View File

@ -858,18 +858,63 @@ fail:
}
static bool
is_targeting_soft_float(LLVMTargetMachineRef target_machine)
is_target_arm(AOTCompContext *comp_ctx)
{
return !strncmp(comp_ctx->target_arch, "arm", 3) ||
!strncmp(comp_ctx->target_arch, "thumb", 5);
}
static bool
is_target_x86(AOTCompContext *comp_ctx)
{
return !strncmp(comp_ctx->target_arch, "x86_64", 6) ||
!strncmp(comp_ctx->target_arch, "i386", 4);
}
static bool
is_target_xtensa(AOTCompContext *comp_ctx)
{
return !strncmp(comp_ctx->target_arch, "xtensa", 6);
}
static bool
is_target_mips(AOTCompContext *comp_ctx)
{
return !strncmp(comp_ctx->target_arch, "mips", 4);
}
static bool
is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32)
{
bool ret = false;
char *feature_string;
if (!(feature_string =
LLVMGetTargetMachineFeatureString(target_machine))) {
LLVMGetTargetMachineFeatureString(comp_ctx->target_machine))) {
aot_set_last_error("llvm get target machine feature string fail.");
return false;
}
ret = strstr(feature_string, "+soft-float") ? true : false;
/* Note:
* LLVM CodeGen uses FPU Coprocessor registers by default,
* so user must specify '--cpu-features=+soft-float' to wamrc if the target
* doesn't have or enable FPU on arm, x86 or mips. */
if (is_target_arm(comp_ctx) ||
is_target_x86(comp_ctx) ||
is_target_mips(comp_ctx))
ret = strstr(feature_string, "+soft-float") ? true : false;
else if (is_target_xtensa(comp_ctx))
/* Note:
* 1. The Floating-Point Coprocessor Option of xtensa only support
* single-precision floating-point operations, so must use soft-float
* for f64(i.e. double).
* 2. LLVM CodeGen uses Floating-Point Coprocessor registers by default,
* so user must specify '--cpu-features=-fp' to wamrc if the target
* doesn't have or enable Floating-Point Coprocessor Option on xtensa. */
ret = (!is_f32 || strstr(feature_string, "-fp")) ? true : false;
else
ret = true;
LLVMDisposeMessage(feature_string);
return ret;
}
@ -880,7 +925,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
{
switch (arith_op) {
case FLOAT_ADD:
if (is_targeting_soft_float(comp_ctx->target_machine))
if (is_targeting_soft_float(comp_ctx, is_f32))
DEF_FP_BINARY_OP(LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"),
"llvm build fadd fail.");
else
@ -897,7 +942,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
NULL);
return true;
case FLOAT_SUB:
if (is_targeting_soft_float(comp_ctx->target_machine))
if (is_targeting_soft_float(comp_ctx, is_f32))
DEF_FP_BINARY_OP(LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"),
"llvm build fsub fail.");
else
@ -914,7 +959,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
NULL);
return true;
case FLOAT_MUL:
if (is_targeting_soft_float(comp_ctx->target_machine))
if (is_targeting_soft_float(comp_ctx, is_f32))
DEF_FP_BINARY_OP(LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"),
"llvm build fmul fail.");
else
@ -931,7 +976,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
NULL);
return true;
case FLOAT_DIV:
if (is_targeting_soft_float(comp_ctx->target_machine))
if (is_targeting_soft_float(comp_ctx, is_f32))
DEF_FP_BINARY_OP(LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"),
"llvm build fdiv fail.");
else
@ -1050,7 +1095,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
NULL);
return true;
case FLOAT_SQRT:
if (is_targeting_soft_float(comp_ctx->target_machine))
if (is_targeting_soft_float(comp_ctx, is_f32))
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
is_f32 ? "llvm.sqrt.f32" :
"llvm.sqrt.f64",

View File

@ -740,7 +740,20 @@ typedef struct ArchItem {
static ArchItem valid_archs[] = {
{ "x86_64", false },
{ "i386", false },
{ "xtensa", false},
{ "mips", true },
{ "aarch64v8", false },
{ "aarch64v8.1", false },
{ "aarch64v8.2", false },
{ "aarch64v8.3", false },
{ "aarch64v8.4", false },
{ "aarch64v8.5", false },
{ "aarch64_bev8", false }, /* big endian */
{ "aarch64_bev8.1", false },
{ "aarch64_bev8.2", false },
{ "aarch64_bev8.3", false },
{ "aarch64_bev8.4", false },
{ "aarch64_bev8.5", false },
{ "armv4", true },
{ "armv4t", true },
{ "armv5t", true },
@ -789,23 +802,23 @@ static void
print_supported_targets()
{
uint32 i;
bh_printf("Supported targets:\n");
os_printf("Supported targets:\n");
for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) {
bh_printf("%s ", valid_archs[i].arch);
os_printf("%s ", valid_archs[i].arch);
if (valid_archs[i].support_eb)
bh_printf("%seb ", valid_archs[i].arch);
os_printf("%seb ", valid_archs[i].arch);
}
bh_printf("\n");
os_printf("\n");
}
static void
print_supported_abis()
{
uint32 i;
bh_printf("Supported ABI: ");
os_printf("Supported ABI: ");
for (i = 0; i < sizeof(valid_abis) / sizeof(const char *); i++)
bh_printf("%s ", valid_abis[i]);
bh_printf("\n");
os_printf("%s ", valid_abis[i]);
os_printf("\n");
}
static bool
@ -917,6 +930,8 @@ aot_create_comp_context(AOTCompData *comp_data,
goto fail;
}
comp_ctx->is_jit_mode = true;
comp_ctx->target_machine =
LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine);
}
else {
/* Create LLVM target machine */
@ -937,6 +952,10 @@ aot_create_comp_context(AOTCompData *comp_data,
arch = "thumbv4t";
else if (!strcmp(arch, "thumbeb"))
arch = "thumbv4teb";
else if (!strcmp(arch, "aarch64"))
arch = "aarch64v8";
else if (!strcmp(arch, "aarch64_be"))
arch = "aarch64_bev8";
}
/* Check target arch */
@ -1026,24 +1045,24 @@ aot_create_comp_context(AOTCompData *comp_data,
get_target_arch_from_triple(triple_norm, comp_ctx->target_arch,
sizeof(comp_ctx->target_arch));
bh_printf("Create AoT compiler with:\n");
bh_printf(" target: %s\n", comp_ctx->target_arch);
bh_printf(" target cpu: %s\n", cpu);
bh_printf(" cpu features: %s\n", features);
bh_printf(" opt level: %d\n", opt_level);
bh_printf(" size level: %d\n", size_level);
os_printf("Create AoT compiler with:\n");
os_printf(" target: %s\n", comp_ctx->target_arch);
os_printf(" target cpu: %s\n", cpu);
os_printf(" cpu features: %s\n", features);
os_printf(" opt level: %d\n", opt_level);
os_printf(" size level: %d\n", size_level);
switch (option->output_format) {
case AOT_LLVMIR_UNOPT_FILE:
bh_printf(" output format: unoptimized LLVM IR\n");
os_printf(" output format: unoptimized LLVM IR\n");
break;
case AOT_LLVMIR_OPT_FILE:
bh_printf(" output format: optimized LLVM IR\n");
os_printf(" output format: optimized LLVM IR\n");
break;
case AOT_FORMAT_FILE:
bh_printf(" output format: AoT file\n");
os_printf(" output format: AoT file\n");
break;
case AOT_OBJECT_FILE:
bh_printf(" output format: native object file\n");
os_printf(" output format: native object file\n");
break;
}
@ -1155,7 +1174,7 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
if (comp_ctx->pass_mgr)
LLVMDisposePassManager(comp_ctx->pass_mgr);
if (comp_ctx->target_machine)
if (comp_ctx->target_machine && !comp_ctx->is_jit_mode)
LLVMDisposeTargetMachine(comp_ctx->target_machine);
if (comp_ctx->builder)

View File

@ -16,15 +16,23 @@ typedef struct NativeSymbol {
const char *symbol;
void *func_ptr;
const char *signature;
/* attachment which can be retrieved in native API by
calling wasm_runtime_get_function_attachment(exec_env) */
void *attachment;
} NativeSymbol;
#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL}
#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL}
#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL, NULL}
#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL, NULL}
#define EXPORT_WASM_API_WITH_SIG(symbol, signature) \
{#symbol, (void*)symbol, signature}
{#symbol, (void*)symbol, signature, NULL}
#define EXPORT_WASM_API_WITH_SIG2(symbol, signature) \
{#symbol, (void*)symbol##_wrapper, signature}
{#symbol, (void*)symbol##_wrapper, signature, NULL}
#define EXPORT_WASM_API_WITH_ATT(symbol, signature, attachment) \
{#symbol, (void*)symbol, signature, attachment}
#define EXPORT_WASM_API_WITH_ATT2(symbol, signature, attachment) \
{#symbol, (void*)symbol##_wrapper, signature, attachment}
/**
* Get the exported APIs of base lib

View File

@ -15,6 +15,34 @@
extern "C" {
#endif
#define get_module_inst(exec_env) \
wasm_runtime_get_module_inst(exec_env)
#define validate_app_addr(offset, size) \
wasm_runtime_validate_app_addr(module_inst, offset, size)
#define validate_app_str_addr(offset) \
wasm_runtime_validate_app_str_addr(module_inst, offset)
#define addr_app_to_native(offset) \
wasm_runtime_addr_app_to_native(module_inst, offset)
#define addr_native_to_app(ptr) \
wasm_runtime_addr_native_to_app(module_inst, ptr)
#define module_malloc(size, p_native_addr) \
wasm_runtime_module_malloc(module_inst, size, p_native_addr)
#define module_free(offset) \
wasm_runtime_module_free(module_inst, offset)
#define native_raw_return_type(type, args) type *raw_ret = (type*)(args)
#define native_raw_get_arg(type, name, args) type name = *((type*)(args++))
#define native_raw_set_return(val) *raw_ret = (val)
/* Uninstantiated WASM module loaded from WASM binary file
or AoT binary file*/
struct WASMModuleCommon;
@ -334,6 +362,17 @@ wasm_application_execute_func(wasm_module_inst_t module_inst,
const char *
wasm_runtime_get_exception(wasm_module_inst_t module_inst);
/**
* Set exception info of the WASM module instance.
*
* @param module_inst the WASM module instance
*
* @param exception the exception string
*/
void
wasm_runtime_set_exception(wasm_module_inst_t module_inst,
const char *exception);
/**
* Clear exception info of the WASM module instance.
*
@ -538,6 +577,49 @@ bool wasm_runtime_register_natives(const char *module_name,
NativeSymbol *native_symbols,
uint32_t n_native_symbols);
/**
* Register native functions with same module name, similar to
* wasm_runtime_register_natives, the difference is that runtime passes raw
* arguments to native API, which means that the native API should be defined as:
* void foo(wasm_exec_env_t exec_env, uint64 *args);
* and native API should extract arguments one by one from args array with macro
* native_raw_get_arg
* and write the return value back to args[0] with macro
* native_raw_return_type and native_raw_set_return
*/
bool wasm_runtime_register_natives_raw(const char *module_name,
NativeSymbol *native_symbols,
uint32_t n_native_symbols);
/**
* Get attachment of native function from execution environment
*
* @param exec_env the execution environment to retrieve
*
* @return the attachment of native function
*/
void *
wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
/**
* Set user data to execution environment.
*
* @param exec_env the execution environment
* @param user_data the user data to be set
*/
void
wasm_runtime_set_user_data(wasm_exec_env_t exec_env,
void *user_data);
/**
* Get the user data within execution environment.
*
* @param exec_env the execution environment
*
* @return the user data (NULL if not set yet)
*/
void *
wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
#ifdef __cplusplus
}
#endif

View File

@ -137,8 +137,11 @@ typedef struct WASMFunctionImport {
WASMType *func_type;
/* function pointer after linked */
void *func_ptr_linked;
/* signature from registered native symbols */
/* signature from registered native symbols */
const char *signature;
/* attachment */
void *attachment;
bool call_conv_raw;
} WASMFunctionImport;
typedef struct WASMGlobalImport {

View File

@ -748,9 +748,18 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
return;
}
ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked,
func_import->func_type, func_import->signature,
frame->lp, cur_func->param_cell_num, argv_ret);
if (!func_import->call_conv_raw) {
ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked,
func_import->func_type, func_import->signature,
func_import->attachment,
frame->lp, cur_func->param_cell_num, argv_ret);
}
else {
ret = wasm_runtime_invoke_native_raw(exec_env, func_import->func_ptr_linked,
func_import->func_type, func_import->signature,
func_import->attachment,
frame->lp, cur_func->param_cell_num, argv_ret);
}
if (!ret)
return;
@ -818,7 +827,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
DEFINE_GOTO_TABLE (handle_table);
DEFINE_GOTO_TABLE (const void *, handle_table);
#undef HANDLE_OPCODE
#endif
@ -1401,7 +1410,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* fail to memory.grow, return -1 */
PUSH_I32(-1);
if (wasm_get_exception(module)) {
bh_printf("%s\n", wasm_get_exception(module));
os_printf("%s\n", wasm_get_exception(module));
wasm_set_exception(module, NULL);
}
}

View File

@ -225,31 +225,7 @@ LOAD_I16(void *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 { \
#define CHECK_MEMORY_OVERFLOW(bytes) do { \
uint64 offset1 = offset + addr; \
/* if (flags != 2) \
LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\
@ -675,6 +651,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
WASMFunctionInstance *cur_func,
WASMInterpFrame *prev_frame)
{
WASMFunctionImport *func_import = cur_func->u.func_import;
unsigned local_cell_num = 2;
WASMInterpFrame *frame;
uint32 argv_ret[2];
@ -691,20 +668,27 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
wasm_exec_env_set_cur_frame(exec_env, frame);
if (!cur_func->u.func_import->func_ptr_linked) {
if (!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);
func_import->module_name, 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 (!func_import->call_conv_raw) {
ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked,
func_import->func_type, func_import->signature,
func_import->attachment,
frame->lp, cur_func->param_cell_num, argv_ret);
}
else {
ret = wasm_runtime_invoke_native_raw(exec_env, func_import->func_ptr_linked,
func_import->func_type, func_import->signature,
func_import->attachment,
frame->lp, cur_func->param_cell_num, argv_ret);
}
if (!ret)
return;
@ -713,17 +697,50 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
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;
prev_frame->lp[prev_frame->ret_offset] = argv_ret[0];
prev_frame->lp[prev_frame->ret_offset + 1] = argv_ret[1];
}
FREE_FRAME(exec_env, frame);
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
}
#if WASM_ENABLE_OPCODE_COUNTER != 0
typedef struct OpcodeInfo {
char *name;
uint64 count;
} OpcodeInfo;
#define HANDLE_OPCODE(op) { #op, 0 }
DEFINE_GOTO_TABLE (OpcodeInfo, opcode_table);
#undef HANDLE_OPCODE
static void
wasm_interp_dump_op_count()
{
uint32 i;
uint64 total_count = 0;
for (i = 0; i < WASM_OP_IMPDEP; i++)
total_count += opcode_table[i].count;
printf("total opcode count: %ld\n", total_count);
for (i = 0; i < WASM_OP_IMPDEP; i++)
if (opcode_table[i].count > 0)
printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n",
opcode_table[i].name, opcode_table[i].count,
opcode_table[i].count * 100.0f / total_count);
}
#endif
#if WASM_ENABLE_LABELS_AS_VALUES != 0
//#define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n");h_##opcode
#if WASM_ENABLE_OPCODE_COUNTER != 0
#define HANDLE_OP(opcode) HANDLE_##opcode:opcode_table[opcode].count++;h_##opcode
#else
#define HANDLE_OP(opcode) HANDLE_##opcode
#endif
#if WASM_ENABLE_FAST_INTERP == 0
#define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++]
#else
@ -752,7 +769,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
#if WASM_ENABLE_FAST_INTERP != 0
static void *global_handle_table[WASM_INSTRUCTION_NUM] = { 0 };
static void **global_handle_table;
#endif
static void
@ -778,10 +795,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#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;
int16 addr1, addr2, addr_ret = 0;
int32 didx, val;
uint8 *maddr = NULL;
uint32 local_idx, local_offset, global_idx;
@ -789,23 +805,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
DEFINE_GOTO_TABLE (handle_table);
DEFINE_GOTO_TABLE (const void*, 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);
global_handle_table = (void **)handle_table;
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++;
@ -1016,133 +1025,144 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP (WASM_OP_I32_LOAD):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 1);
addr = GET_OPERAND(uint32, 3);
frame_ip += 5;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW_FAST(4);
CHECK_MEMORY_OVERFLOW(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();
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(int32, 2);
addr = GET_OPERAND(uint32, 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;
CHECK_MEMORY_OVERFLOW(8);
PUT_I64_TO_ADDR(frame_lp + addr_ret, LOAD_I64(maddr));
HANDLE_OP_END ();
}
/* memory store instructions */
HANDLE_OP (WASM_OP_F32_STORE):
HANDLE_OP (WASM_OP_I32_LOAD8_S):
{
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);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
frame_lp[addr_ret] = sign_ext_8_32(*(int8*)maddr);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_F64_STORE):
HANDLE_OP (WASM_OP_I32_LOAD8_U):
{
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]);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
frame_lp[addr_ret] = (uint32)(*(uint8*)maddr);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I32_LOAD16_S):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr));
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I32_LOAD16_U):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr));
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_LOAD8_S):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
*(int64 *)(frame_lp + addr_ret) = sign_ext_8_64(*(int8*)maddr);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_LOAD8_U):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
*(int64 *)(frame_lp + addr_ret) = (uint64)(*(uint8*)maddr);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_LOAD16_S):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
*(int64 *)(frame_lp + addr_ret) = sign_ext_16_64(LOAD_I16(maddr));
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_LOAD16_U):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
*(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U16(maddr));
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_LOAD32_S):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
*(int64 *)(frame_lp + addr_ret) = sign_ext_32_64(LOAD_I32(maddr));
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_LOAD32_U):
{
uint32 offset, addr;
offset = GET_OPERAND(uint32, 0);
addr = GET_OPERAND(uint32, 2);
frame_ip += 4;
addr_ret = GET_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
*(int64 *)(frame_lp + addr_ret) = (uint64)(LOAD_U32(maddr));
HANDLE_OP_END ();
}
@ -1150,63 +1170,90 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
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;
}
CHECK_MEMORY_OVERFLOW(4);
STORE_U32(maddr, sval);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I32_STORE8):
{
uint32 offset, addr;
uint32 sval;
offset = GET_OPERAND(uint32, 0);
sval = GET_OPERAND(uint32, 2);
addr = GET_OPERAND(uint32, 4);
frame_ip += 6;
CHECK_MEMORY_OVERFLOW(1);
*(uint8*)maddr = (uint8)sval;
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I32_STORE16):
{
uint32 offset, addr;
uint32 sval;
offset = GET_OPERAND(uint32, 0);
sval = GET_OPERAND(uint32, 2);
addr = GET_OPERAND(uint32, 4);
frame_ip += 6;
CHECK_MEMORY_OVERFLOW(2);
STORE_U16(maddr, (uint16)sval);
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;
}
CHECK_MEMORY_OVERFLOW(8);
STORE_I64(maddr, sval);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_STORE8):
{
uint32 offset, addr;
uint64 sval;
offset = GET_OPERAND(uint32, 0);
sval = GET_OPERAND(uint64, 2);
addr = GET_OPERAND(uint32, 4);
frame_ip += 6;
CHECK_MEMORY_OVERFLOW(1);
*(uint8*)maddr = (uint8)sval;
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_STORE16):
{
uint32 offset, addr;
uint64 sval;
offset = GET_OPERAND(uint32, 0);
sval = GET_OPERAND(uint64, 2);
addr = GET_OPERAND(uint32, 4);
frame_ip += 6;
CHECK_MEMORY_OVERFLOW(2);
STORE_U16(maddr, (uint16)sval);
HANDLE_OP_END ();
}
HANDLE_OP (WASM_OP_I64_STORE32):
{
uint32 offset, addr;
uint64 sval;
offset = GET_OPERAND(uint32, 0);
sval = GET_OPERAND(uint64, 2);
addr = GET_OPERAND(uint32, 4);
frame_ip += 6;
CHECK_MEMORY_OVERFLOW(4);
STORE_U32(maddr, (uint32)sval);
HANDLE_OP_END ();
}
@ -1232,7 +1279,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* fail to memory.grow, return -1 */
frame_lp[addr_ret] = -1;
if (wasm_get_exception(module)) {
bh_printf("%s\n", wasm_get_exception(module));
os_printf("%s\n", wasm_get_exception(module));
wasm_set_exception(module, NULL);
}
}
@ -2027,19 +2074,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP (WASM_OP_TEE_LOCAL):
{
GET_LOCAL_INDEX_TYPE_AND_OFFSET();
addr1 = GET_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;
if (local_type == VALUE_TYPE_I32
|| local_type == VALUE_TYPE_F32) {
*(int32*)(frame_lp + local_offset) = frame_lp[addr1];
}
else if (local_type == VALUE_TYPE_I64
|| local_type == VALUE_TYPE_F64) {
PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset),
GET_I64_FROM_ADDR(frame_lp + addr1));
}
else {
wasm_set_exception(module, "invalid local type");
goto got_exception;
}
HANDLE_OP_END ();
@ -2085,6 +2133,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP (WASM_OP_UNUSED_0x26):
HANDLE_OP (WASM_OP_UNUSED_0x27):
/* optimized op code */
HANDLE_OP (WASM_OP_F32_STORE):
HANDLE_OP (WASM_OP_F64_STORE):
HANDLE_OP (WASM_OP_F32_LOAD):
HANDLE_OP (WASM_OP_F64_LOAD):
HANDLE_OP (EXT_OP_GET_LOCAL_FAST):
HANDLE_OP (WASM_OP_GET_LOCAL):
HANDLE_OP (WASM_OP_F64_CONST):
@ -2275,4 +2327,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
FREE_FRAME(exec_env, frame);
#if WASM_ENABLE_OPCODE_COUNTER != 0
wasm_interp_dump_op_count();
#endif
}

View File

@ -492,8 +492,12 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
{
const uint8 *p = *p_buf, *p_end = buf_end;
uint32 pool_size = wasm_runtime_memory_pool_size();
#if WASM_ENABLE_APP_FRAMEWORK != 0
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE;
#else
uint32 max_page_count = pool_size / DEFAULT_NUM_BYTES_PER_PAGE;
#endif
read_leb_uint32(p, p_end, memory->flags);
read_leb_uint32(p, p_end, memory->init_page_count);
@ -539,8 +543,12 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
{
const uint8 *p = *p_buf, *p_end = buf_end;
uint32 pool_size = wasm_runtime_memory_pool_size();
#if WASM_ENABLE_APP_FRAMEWORK != 0
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE;
#else
uint32 max_page_count = pool_size / DEFAULT_NUM_BYTES_PER_PAGE;
#endif
read_leb_uint32(p, p_end, memory->flags);
read_leb_uint32(p, p_end, memory->init_page_count);
@ -667,9 +675,11 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
p = p_old;
/* insert "env" and "wasi_unstable" to const str list */
/* insert "env", "wasi_unstable" and "wasi_snapshot_preview1" to const str list */
if (!const_str_list_insert((uint8*)"env", 3, module, error_buf, error_buf_size)
|| !const_str_list_insert((uint8*)"wasi_unstable", 13, module,
error_buf, error_buf_size)
|| !const_str_list_insert((uint8*)"wasi_snapshot_preview1", 22, module,
error_buf, error_buf_size)) {
return false;
}
@ -713,7 +723,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
if (!(import->u.function.func_ptr_linked =
wasm_native_resolve_symbol(module_name, field_name,
import->u.function.func_type,
&import->u.function.signature))) {
&import->u.function.signature,
&import->u.function.attachment,
&import->u.function.call_conv_raw))) {
#if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */
LOG_WARNING("warning: fail to link import function (%s, %s)\n",
module_name, field_name);
@ -787,7 +799,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
#if WASM_ENABLE_LIBC_WASI != 0
import = module->import_functions;
for (i = 0; i < module->import_function_count; i++, import++) {
if (!strcmp(import->u.names.module_name, "wasi_unstable")) {
if (!strcmp(import->u.names.module_name, "wasi_unstable")
|| !strcmp(import->u.names.module_name, "wasi_snapshot_preview1")) {
module->is_wasi_module = true;
break;
}
@ -1620,9 +1633,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
if (llvm_data_end_global && llvm_heap_base_global) {
if ((data_end_global_index == heap_base_global_index + 1
&& data_end_global_index > 0)
&& (int32)data_end_global_index > 1)
|| (heap_base_global_index == data_end_global_index + 1
&& heap_base_global_index > 0)) {
&& (int32)heap_base_global_index > 1)) {
global_index =
data_end_global_index < heap_base_global_index
? data_end_global_index - 1 : heap_base_global_index - 1;
@ -1694,7 +1707,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
return true;
}
#if BEIHAI_ENABLE_MEMORY_PROFILING != 0
#if BH_ENABLE_MEMORY_PROFILING != 0
static void wasm_loader_free(void *ptr)
{
wasm_runtime_free(ptr);
@ -2311,7 +2324,7 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
#if WASM_ENABLE_FAST_INTERP != 0
#if WASM_DEBUG_PREPROCESSOR != 0
#define LOG_OP(...) bh_printf(__VA_ARGS__)
#define LOG_OP(...) os_printf(__VA_ARGS__)
#else
#define LOG_OP(...)
#endif
@ -2367,6 +2380,9 @@ typedef struct WASMLoaderContext {
int16 start_dynamic_offset;
int16 max_dynamic_offset;
/* preserved local offset */
int16 preserved_local_offset;
/* const buffer */
uint8 *const_buf;
uint16 num_const;
@ -2716,6 +2732,128 @@ wasm_loader_check_br(WASMLoaderContext *ctx, uint32 depth,
}
#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)
#define emit_operand(ctx, offset) do { \
wasm_loader_emit_int16(ctx, offset); \
LOG_OP("%d\t", offset); \
} while (0)
#define emit_byte(ctx, byte) do { \
wasm_loader_emit_uint8(ctx, byte); \
LOG_OP("%d\t", byte); \
} while (0)
#define emit_leb() do { \
wasm_loader_emit_leb(loader_ctx, p_org, p); \
} while (0)
#define emit_const(value) do { \
GET_CONST_OFFSET(VALUE_TYPE_I32, value); \
emit_operand(loader_ctx, operand_offset); \
} while (0)
static bool
wasm_loader_ctx_reinit(WASMLoaderContext *ctx)
{
@ -2741,6 +2879,9 @@ wasm_loader_ctx_reinit(WASMLoaderContext *ctx)
ctx->frame_offset = ctx->frame_offset_bottom;
ctx->dynamic_offset = ctx->start_dynamic_offset;
/* init preserved local offsets */
ctx->preserved_local_offset = ctx->max_dynamic_offset;
/* const buf is reserved */
return true;
}
@ -2803,6 +2944,49 @@ wasm_loader_emit_leb(WASMLoaderContext *ctx, uint8* start, uint8* end)
}
static bool
preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
uint32 local_index, uint32 local_type, bool *preserved,
char *error_buf, uint32 error_buf_size)
{
int16 preserved_offset = (int16)local_index;
*preserved = false;
for (uint32 i = 0; i < loader_ctx->stack_cell_num; i++) {
/* move previous local into dynamic space before a set/tee_local opcode */
if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) {
if (preserved_offset == (int16)local_index) {
*preserved = true;
skip_label();
if (local_type == VALUE_TYPE_I32
|| local_type == VALUE_TYPE_F32) {
preserved_offset = loader_ctx->preserved_local_offset;
/* Only increase preserve offset in the second traversal */
if (loader_ctx->p_code_compiled)
loader_ctx->preserved_local_offset++;
emit_label(EXT_OP_COPY_STACK_TOP);
}
else {
preserved_offset = loader_ctx->preserved_local_offset;
if (loader_ctx->p_code_compiled)
loader_ctx->preserved_local_offset += 2;
emit_label(EXT_OP_COPY_STACK_TOP_I64);
}
emit_operand(loader_ctx, local_index);
emit_operand(loader_ctx, preserved_offset);
emit_label(opcode);
}
loader_ctx->frame_offset_bottom[i] = preserved_offset;
}
}
return true;
#if WASM_ENABLE_ABS_LABEL_ADDR == 0
fail:
return false;
#endif
}
static bool
add_label_patch_to_list(BranchBlock *frame_csp,
uint8 patch_type, uint8 *p_code_compiled,
@ -2830,7 +3014,7 @@ add_label_patch_to_list(BranchBlock *frame_csp,
static void
apply_label_patch(WASMLoaderContext *ctx, uint8 depth,
uint8 patch_type, uint8 *frame_ip)
uint8 patch_type)
{
BranchBlock *frame_csp = ctx->frame_csp - depth;
BranchBlockPatch *node = frame_csp->patch_list;
@ -2858,31 +3042,17 @@ apply_label_patch(WASMLoaderContext *ctx, uint8 depth,
}
}
#define emit_operand(ctx, offset) do { \
wasm_loader_emit_int16(ctx, offset); \
LOG_OP("%d\t", offset); \
} while (0)
#define emit_byte(ctx, byte) do { \
wasm_loader_emit_uint8(ctx, byte); \
LOG_OP("%d\t", byte); \
} while (0)
#define emit_leb() do { \
wasm_loader_emit_leb(loader_ctx, p_org, p); \
} while (0)
#define emit_const(value) do { \
GET_CONST_OFFSET(VALUE_TYPE_I32, value); \
emit_operand(loader_ctx, operand_offset); \
} while (0)
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
if (frame_csp->block_type == BLOCK_TYPE_LOOP ||
frame_csp->return_type == VALUE_TYPE_VOID) {
emit_byte(ctx, 0);
emit_operand(ctx, 0);
}
else 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));
@ -2892,10 +3062,7 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
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);
}
@ -2960,12 +3127,14 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) {
ctx->frame_offset -= 1;
if (*(ctx->frame_offset) > ctx->start_dynamic_offset)
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
ctx->dynamic_offset -= 1;
}
else {
ctx->frame_offset -= 2;
if (*(ctx->frame_offset) > ctx->start_dynamic_offset)
if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
&& (*(ctx->frame_offset) < ctx->max_dynamic_offset))
ctx->dynamic_offset -= 2;
}
emit_operand(ctx, *(ctx->frame_offset));
@ -3268,107 +3437,7 @@ check_memory(WASMModule *module,
} 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 */
@ -3393,7 +3462,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
uint8 *func_const_end, *func_const;
int16 operand_offset;
uint8 last_op = 0;
bool disable_emit;
bool disable_emit, preserve_local = false;
float32 f32;
float64 f64;
@ -3514,10 +3583,17 @@ re_scan:
error_buf, error_buf_size))
goto fail;
if ((loader_ctx->frame_csp - 1)->else_addr)
p = (loader_ctx->frame_csp - 1)->else_addr;
else
if ((loader_ctx->frame_csp - 1)->else_addr) {
#if WASM_ENABLE_FAST_INTERP != 0
loader_ctx->frame_offset = loader_ctx->frame_offset_bottom +
(loader_ctx->frame_csp - 1)->stack_cell_num;
apply_label_patch(loader_ctx, 1, PATCH_ELSE);
#endif
p = (loader_ctx->frame_csp - 1)->else_addr + 1;
}
else {
p = (loader_ctx->frame_csp - 1)->end_addr;
}
is_i32_const = false;
continue;
@ -3539,7 +3615,7 @@ re_scan:
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 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
@ -3557,14 +3633,14 @@ re_scan:
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;
(loader_ctx->frame_csp - 1)->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);
apply_label_patch(loader_ctx, 1, PATCH_ELSE);
#endif
break;
@ -3601,7 +3677,7 @@ re_scan:
wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
}
apply_label_patch(loader_ctx, 0, PATCH_END, p);
apply_label_patch(loader_ctx, 0, PATCH_END);
free_label_patch_list(loader_ctx->frame_csp);
if (loader_ctx->frame_csp->block_type == BLOCK_TYPE_FUNCTION) {
emit_label(WASM_OP_RETURN);
@ -3670,8 +3746,15 @@ handle_next_reachable_block:
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;
&& p <= (loader_ctx->frame_csp - 1)->else_addr) {
#if WASM_ENABLE_FAST_INTERP != 0
loader_ctx->frame_offset = loader_ctx->frame_offset_bottom +
(loader_ctx->frame_csp - 1)->stack_cell_num;
apply_label_patch(loader_ctx, 1, PATCH_ELSE);
#endif
p = (loader_ctx->frame_csp - 1)->else_addr + 1;
}
else {
p = (loader_ctx->frame_csp - 1)->end_addr;
PUSH_TYPE(block_return_type);
@ -3736,40 +3819,6 @@ handle_next_reachable_block:
POP_TYPE(ret_type);
PUSH_TYPE(ret_type);
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 ==
(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,
(loader_ctx->frame_csp - 1)->start_addr,
p_end,
(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;
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 = (loader_ctx->frame_csp - 1)->end_addr;
PUSH_TYPE((loader_ctx->frame_csp - 1)->return_type);
}
#if WASM_ENABLE_FAST_INTERP != 0
// emit the offset after return opcode
POP_OFFSET_TYPE(ret_type);
@ -3778,7 +3827,7 @@ handle_next_reachable_block:
#endif
is_i32_const = false;
continue;
goto handle_next_reachable_block;
}
case WASM_OP_CALL:
@ -3886,6 +3935,7 @@ handle_next_reachable_block:
}
case WASM_OP_DROP:
case WASM_OP_DROP_64:
{
if (loader_ctx->stack_cell_num <= 0) {
set_error_buf(error_buf, error_buf_size,
@ -3915,7 +3965,7 @@ handle_next_reachable_block:
}
loader_ctx->frame_ref -= 2;
loader_ctx->stack_cell_num -= 2;
#if WASM_ENABLE_FAST_INTERP == 0
#if (WASM_ENABLE_FAST_INTERP == 0) || (WASM_ENABLE_JIT != 0)
*(p - 1) = WASM_OP_DROP_64;
#endif
#if WASM_ENABLE_FAST_INTERP != 0
@ -3930,6 +3980,7 @@ handle_next_reachable_block:
}
case WASM_OP_SELECT:
case WASM_OP_SELECT_64:
{
uint8 ref_type;
@ -3948,7 +3999,7 @@ handle_next_reachable_block:
break;
case REF_I64_2:
case REF_F64_2:
#if WASM_ENABLE_FAST_INTERP == 0
#if (WASM_ENABLE_FAST_INTERP == 0) || (WASM_ENABLE_JIT != 0)
*(p - 1) = WASM_OP_SELECT_64;
#endif
#if WASM_ENABLE_FAST_INTERP != 0
@ -4013,15 +4064,20 @@ handle_next_reachable_block:
POP_TYPE(local_type);
#if WASM_ENABLE_FAST_INTERP != 0
if (!(preserve_referenced_local(loader_ctx, opcode, local_offset,
local_type, &preserve_local,
error_buf, error_buf_size)))
goto fail;
if (local_offset < 256) {
skip_label();
if (LAST_OP_OUTPUT_I32()) {
if ((!preserve_local) && (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()) {
else if ((!preserve_local) && (LAST_OP_OUTPUT_I64())) {
if (loader_ctx->p_code_compiled)
*(int16*)(loader_ctx->p_code_compiled - 2) = local_offset;
loader_ctx->frame_offset -= 2;
@ -4070,6 +4126,11 @@ handle_next_reachable_block:
PUSH_TYPE(local_type);
#if WASM_ENABLE_FAST_INTERP != 0
if (!(preserve_referenced_local(loader_ctx, opcode, local_offset,
local_type, &preserve_local,
error_buf, error_buf_size)))
goto fail;
if (local_offset < 256) {
skip_label();
if (local_type == VALUE_TYPE_I32
@ -4175,11 +4236,29 @@ handle_next_reachable_block:
case WASM_OP_F32_STORE:
case WASM_OP_F64_STORE:
{
#if WASM_ENABLE_FAST_INTERP != 0
/* change F32/F64 into I32/I64 */
if (opcode == WASM_OP_F32_LOAD) {
skip_label();
emit_label(WASM_OP_I32_LOAD);
}
else if (opcode == WASM_OP_F64_LOAD) {
skip_label();
emit_label(WASM_OP_I64_LOAD);
}
else if (opcode == WASM_OP_F32_STORE) {
skip_label();
emit_label(WASM_OP_I32_STORE);
}
else if (opcode == WASM_OP_F64_STORE) {
skip_label();
emit_label(WASM_OP_I64_STORE);
}
#endif
CHECK_MEMORY();
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)
@ -4616,7 +4695,7 @@ handle_next_reachable_block:
}
}
func->max_stack_cell_num = loader_ctx->max_dynamic_offset -
func->max_stack_cell_num = loader_ctx->preserved_local_offset -
loader_ctx->start_dynamic_offset + 1;
#else
func->max_stack_cell_num = loader_ctx->max_stack_cell_num;

View File

@ -262,8 +262,8 @@ typedef enum WASMOpcode {
*/
#define WASM_INSTRUCTION_NUM 256
#define DEFINE_GOTO_TABLE(_name) \
static const void *_name[WASM_INSTRUCTION_NUM] = { \
#define DEFINE_GOTO_TABLE(type, _name) \
static type _name[WASM_INSTRUCTION_NUM] = { \
HANDLE_OPCODE (WASM_OP_UNREACHABLE), /* 0x00 */ \
HANDLE_OPCODE (WASM_OP_NOP), /* 0x01 */ \
HANDLE_OPCODE (WASM_OP_BLOCK), /* 0x02 */ \

View File

@ -1108,7 +1108,8 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
{
#if WASM_ENABLE_MEMORY_GROW != 0
WASMMemoryInstance *memory = module->default_memory, *new_memory;
uint32 old_page_count = memory->cur_page_count, total_size_old;
uint32 old_page_count = memory->cur_page_count;
uint32 total_size_old = memory->end_addr - (uint8*)memory;
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 +
@ -1135,14 +1136,14 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
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);
}
memset((uint8*)new_memory + total_size_old,
0, (uint32)total_size - total_size_old);
new_memory->cur_page_count = total_page_count;
new_memory->memory_data = new_memory->base_addr;
new_memory->global_data = new_memory->memory_data +
@ -1165,3 +1166,42 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
#endif /* end of WASM_ENABLE_MEMORY_GROW */
}
bool
wasm_call_indirect(WASMExecEnv *exec_env,
uint32_t element_indices,
uint32_t argc, uint32_t argv[])
{
WASMModuleInstance *module_inst = NULL;
WASMTableInstance *table_inst = NULL;
uint32_t function_indices = 0;
WASMFunctionInstance *function_inst = NULL;
module_inst =
(WASMModuleInstance*)exec_env->module_inst;
bh_assert(module_inst);
table_inst = module_inst->default_table;
if (!table_inst) {
wasm_set_exception(module_inst, "there is no table");
goto got_exception;
}
if (element_indices >= table_inst->cur_size) {
wasm_set_exception(module_inst, "undefined element");
goto got_exception;
}
function_indices = ((uint32_t*)table_inst->base_addr)[element_indices];
if (function_indices == 0xFFFFFFFF) {
wasm_set_exception(module_inst, "uninitialized element");
goto got_exception;
}
function_inst = module_inst->functions + function_indices;
wasm_interp_call_wasm(module_inst, exec_env, function_inst, argc, argv);
return !wasm_get_exception(module_inst) ? true : false;
got_exception:
return false;
}

View File

@ -280,6 +280,11 @@ wasm_get_native_addr_range(WASMModuleInstance *module_inst,
bool
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count);
bool
wasm_call_indirect(WASMExecEnv *exec_env,
uint32_t element_indices,
uint32_t argc, uint32_t argv[]);
#ifdef __cplusplus
}
#endif

View File

@ -388,7 +388,7 @@ sprintf_out(int c, struct str_context *ctx)
static int
printf_out(int c, struct str_context *ctx)
{
bh_printf("%c", c);
os_printf("%c", c);
ctx->count++;
return c;
}
@ -470,13 +470,13 @@ snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size,
static int
puts_wrapper(wasm_exec_env_t exec_env, const char *str)
{
return bh_printf("%s\n", str);
return os_printf("%s\n", str);
}
static int
putchar_wrapper(wasm_exec_env_t exec_env, int c)
{
bh_printf("%c", c);
os_printf("%c", c);
return 1;
}
@ -908,7 +908,7 @@ static void
llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
bh_printf("_llvm_stackrestore called!\n");
os_printf("_llvm_stackrestore called!\n");
wasm_runtime_set_llvm_stack(module_inst, llvm_stack);
}
@ -916,7 +916,7 @@ static uint32
llvm_stacksave_wrapper(wasm_exec_env_t exec_env)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
bh_printf("_llvm_stacksave called!\n");
os_printf("_llvm_stacksave called!\n");
return wasm_runtime_get_llvm_stack(module_inst);
}
@ -996,11 +996,11 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env,
static void
print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
{
bh_printf("%d\n", i32);
os_printf("%d\n", i32);
}
#define REG_NATIVE_FUNC(func_name, signature) \
{ #func_name, func_name##_wrapper, signature }
{ #func_name, func_name##_wrapper, signature, NULL }
static NativeSymbol native_symbols_libc_builtin[] = {
REG_NATIVE_FUNC(printf, "($*)i"),
@ -1028,7 +1028,7 @@ static NativeSymbol native_symbols_libc_builtin[] = {
REG_NATIVE_FUNC(exit, "(i)"),
REG_NATIVE_FUNC(strtol, "($*i)i"),
REG_NATIVE_FUNC(strtoul, "($*i)i"),
REG_NATIVE_FUNC(memchr, "(*ii)"),
REG_NATIVE_FUNC(memchr, "(*ii)i"),
REG_NATIVE_FUNC(strncasecmp, "($$i)"),
REG_NATIVE_FUNC(strspn, "($$)i"),
REG_NATIVE_FUNC(strcspn, "($$)i"),

View File

@ -982,7 +982,7 @@ wasi_sched_yield(wasm_exec_env_t exec_env)
}
#define REG_NATIVE_FUNC(func_name, signature) \
{ #func_name, wasi_##func_name, signature }
{ #func_name, wasi_##func_name, signature, NULL }
static NativeSymbol native_symbols_libc_wasi[] = {
REG_NATIVE_FUNC(args_get, "(**)i"),

View File

@ -47,6 +47,7 @@
#include "str.h"
#include "bh_common.h"
#include "bh_assert.h"
#if 0 /* TODO: -std=gnu99 causes compile error, comment them first */
// struct iovec must have the same layout as __wasi_iovec_t.
@ -1907,6 +1908,21 @@ __wasi_errno_t wasmtime_ssp_path_open(
close(nfd);
return error;
}
{
struct stat sb;
if (fstat(nfd, &sb) < 0) {
close(nfd);
return convert_errno(errno);
}
if (S_ISDIR(sb.st_mode))
rights_base |= RIGHTS_DIRECTORY_BASE;
else if (S_ISREG(sb.st_mode))
rights_base |= RIGHTS_REGULAR_FILE_BASE;
}
return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base,
rights_inheriting & max_inheriting, fd);
}
@ -2272,8 +2288,14 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times(
__wasi_timestamp_t st_mtim,
__wasi_fstflags_t fstflags
) {
if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW |
__WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0)
if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW |
__WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0)
/* ATIM & ATIM_NOW can't be set at the same time */
|| ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0
&& (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0)
/* MTIM & MTIM_NOW can't be set at the same time */
|| ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0
&& (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0))
return __WASI_EINVAL;
struct path_access pa;

View File

@ -1,144 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/**
* @file bh_log.h
* @date Tue Nov 8 18:19:10 2011
*
* @brief This log system supports wrapping multiple outputs into one
* log message. This is useful for outputting variable-length logs
* without additional memory overhead (the buffer for concatenating
* the message), e.g. exception stack trace, which cannot be printed
* by a single log calling without the help of an additional buffer.
* Avoiding additional memory buffer is useful for resource-constraint
* systems. It can minimize the impact of log system on applications
* and logs can be printed even when no enough memory is available.
* Functions with prefix "_" are private functions. Only macros that
* are not start with "_" are exposed and can be used.
*/
#ifndef _BH_LOG_H
#define _BH_LOG_H
#include <stdarg.h>
#include "bh_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* The following functions are the primitive operations of this log
* system. A normal usage of the log system is to call bh_log_printf
* or bh_log_vprintf one or multiple times and then call bh_log_commit
* to wrap (mark) the previous outputs into one log message. The
* bh_log and macros LOG_ERROR etc. can be used to output log messages
* that can be wrapped into one log calling.
*/
int _bh_log_init(void);
void _bh_log_set_verbose_level(int level);
void _bh_log_printf(const char *fmt, ...);
void _bh_log_vprintf(const char *fmt, va_list ap);
void _bh_log_commit(void);
#if WASM_ENABLE_LOG != 0
# define bh_log_init() _bh_log_init ()
# define bh_log_set_verbose_level(l) _bh_log_set_verbose_level (l)
# define bh_log_printf(...) _bh_log_printf (__VA_ARGS__)
# define bh_log_vprintf(...) _bh_log_vprintf (__VA_ARGS__)
# define bh_log_commit() _bh_log_commit ()
#else /* WASM_ENABLE_LOG != 0 */
# define bh_log_init() 0
# define bh_log_set_verbose_level(l) (void)0
# define bh_log_printf(...) (void)0
# define bh_log_vprintf(...) (void)0
# define bh_log_commit() (void)0
#endif /* WASM_ENABLE_LOG != 0 */
void _bh_log(const char *tag, const char *file, int line, const char *fmt, ...);
/* Always print fatal message */
# define LOG_FATAL(...) _bh_log ("V0.", NULL, 0, __VA_ARGS__)
#if WASM_ENABLE_LOG != 0
# define LOG_ERROR(...) _bh_log ("V1.", NULL, 0, __VA_ARGS__)
# define LOG_WARNING(...) _bh_log ("V2.", NULL, 0, __VA_ARGS__)
# define LOG_INFO_RELEASE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__)
# define LOG_INFO_APP_DEV(...) _bh_log ("V4.", NULL, 0, __VA_ARGS__)
# define LOG_VERBOSE(...) _bh_log ("V5.", NULL, 0, __VA_ARGS__)
# if BEIHAI_ENABLE_MEMORY_PROFILING != 0
# define LOG_PROFILE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__)
# else
# define LOG_PROFILE(...) (void)0
#endif
# if BEIHAI_ENABLE_QUEUE_PROFILING != 0
# define LOG_QUEUE_PROFILE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__)
# else
# define LOG_QUEUE_PROFILE(...) (void)0
#endif
# if BEIHAI_ENABLE_GC_STAT_PROFILING != 0
# define LOG_GC_STAT_PROFILE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__)
# else
# define LOG_GC_STAT_PROFILE(...) (void)0
#endif
#else /* WASM_ENABLE_LOG != 0 */
# define LOG_ERROR(...) (void)0
# define LOG_WARNING(...) (void)0
# define LOG_INFO_APP_DEV(...) (void)0
# define LOG_INFO_RELEASE(...) (void)0
# define LOG_VERBOSE(...) (void)0
# define LOG_PROFILE(...) (void)0
# define LOG_QUEUE_PROFILE(...) (void)0
# define LOG_GC_STAT_PROFILE(...) (void)0
#endif /* WASM_ENABLE_LOG != 0 */
#define LOG_PROFILE_INSTANCE_HEAP_CREATED(heap) \
LOG_PROFILE ("PROF.INSTANCE.HEAP_CREATED: HEAP=%08X", heap)
#define LOG_PROFILE_INSTANCE_THREAD_STARTED(heap) \
LOG_PROFILE ("PROF.INSTANCE.THREAD_STARTED: HEAP=%08X", heap)
#define LOG_PROFILE_HEAP_ALLOC(heap, size) \
LOG_PROFILE ("PROF.HEAP.ALLOC: HEAP=%08X SIZE=%d", heap, size)
#define LOG_PROFILE_HEAP_FREE(heap, size) \
LOG_PROFILE ("PROF.HEAP.FREE: HEAP=%08X SIZE=%d", heap, size)
#define LOG_PROFILE_HEAP_NEW(heap, size) \
LOG_PROFILE ("PROF.HEAP.NEW: HEAP=%08X SIZE=%d", heap, size)
#define LOG_PROFILE_HEAP_GC(heap, size) \
LOG_PROFILE ("PROF.HEAP.GC: HEAP=%08X SIZE=%d", heap, size)
#define LOG_PROFILE_STACK_PUSH(used) \
LOG_PROFILE ("PROF.STACK.PUSH: USED=%d", used)
#define LOG_PROFILE_STACK_POP() \
LOG_PROFILE ("PROF.STACK.POP")
/* Please add your component ahead of LOG_COM_MAX */
enum {
LOG_COM_APP_MANAGER = 0,
LOG_COM_GC,
LOG_COM_HMC,
LOG_COM_UTILS,
LOG_COM_VERIFIER_JEFF,
LOG_COM_VMCORE_JEFF,
LOG_COM_MAX
};
#if defined(BH_DEBUG)
void log_parse_coms(const char *coms);
int bh_log_dcom_is_enabled(int component);
#define LOG_DEBUG(component, ...) do { \
if (bh_log_dcom_is_enabled (component)) \
_bh_log ("V6: ", __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
#else /* defined(BH_DEBUG) */
#define LOG_DEBUG(component, ...) (void)0
#endif /* defined(BH_DEBUG) */
#ifdef __cplusplus
}
#endif
#endif /* _BH_LOG_H */

View File

@ -6,21 +6,25 @@
#include "ems_gc_internal.h"
static int hmu_is_in_heap(gc_heap_t* heap, hmu_t* hmu)
static int
hmu_is_in_heap(gc_heap_t* heap, hmu_t* hmu)
{
return heap && hmu && (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size;
return heap && hmu
&& (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size;
}
/* Remove a node from the tree it belongs to*/
/* @p can not be NULL*/
/* @p can not be the ROOT node*/
/* Node @p will be removed from the tree and left,right,parent pointers of node @p will be*/
/* set to be NULL. Other fields will not be touched.*/
/* The tree will be re-organized so that the order conditions are still satisified.*/
BH_STATIC void remove_tree_node(hmu_tree_node_t *p)
/**
* Remove a node from the tree it belongs to
*
* @param p the node to remove, can not be NULL, can not be the ROOT node
* the node will be removed from the tree, and the left, right and
* parent pointers of the node @p will be set to be NULL. Other fields
* won't be touched. The tree will be re-organized so that the order
* conditions are still satisified.
*/
static void
remove_tree_node(hmu_tree_node_t *p)
{
hmu_tree_node_t *q = NULL, **slot = NULL;
@ -35,11 +39,14 @@ BH_STATIC void remove_tree_node(hmu_tree_node_t *p)
slot = &p->parent->left;
}
/* algorithms used to remove node p*/
/* case 1: if p has no left child, replace p with its right child*/
/* case 2: if p has no right child, replace p with its left child*/
/* case 3: otherwise, find p's predecessor, remove it from the tree and replace p with it.*/
/* use predecessor can keep the left <= root < right condition.*/
/**
* algorithms used to remove node p
* case 1: if p has no left child, replace p with its right child
* case 2: if p has no right child, replace p with its left child
* case 3: otherwise, find p's predecessor, remove it from the tree
* and replace p with it.
* use predecessor can keep the left <= root < right condition.
*/
if (!p->left) {
/* move right child up*/
@ -64,7 +71,8 @@ BH_STATIC void remove_tree_node(hmu_tree_node_t *p)
q = p->left;
while (q->right)
q = q->right;
remove_tree_node(q); /* remove from the tree*/
/* remove from the tree*/
remove_tree_node(q);
*slot = q;
q->parent = p->parent;
@ -78,71 +86,73 @@ BH_STATIC void remove_tree_node(hmu_tree_node_t *p)
p->left = p->right = p->parent = NULL;
}
static void unlink_hmu(gc_heap_t *heap, hmu_t *hmu)
static void
unlink_hmu(gc_heap_t *heap, hmu_t *hmu)
{
gc_size_t size;
bh_assert(gci_is_heap_valid(heap));
bh_assert(
hmu && (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size);
bh_assert(hmu && (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size);
bh_assert(hmu_get_ut(hmu) == HMU_FC);
size = hmu_get_size(hmu);
if (HMU_IS_FC_NORMAL(size)) {
uint32 node_idx = size >> 3;
hmu_normal_node_t* node = heap->kfc_normal_list[node_idx].next;
hmu_normal_node_t** p = &(heap->kfc_normal_list[node_idx].next);
hmu_normal_node_t *node_prev = &heap->kfc_normal_list[node_idx];
hmu_normal_node_t *node =
get_hmu_normal_node_next(&heap->kfc_normal_list[node_idx]);
while (node) {
if ((hmu_t*) node == hmu) {
*p = node->next;
set_hmu_normal_node_next(node_prev, get_hmu_normal_node_next(node));
break;
}
p = &(node->next);
node = node->next;
node_prev = node;
node = get_hmu_normal_node_next(node);
}
if (!node) {
bh_printf("[GC_ERROR]couldn't find the node in the normal list");
os_printf("[GC_ERROR]couldn't find the node in the normal list\n");
}
} else {
}
else {
remove_tree_node((hmu_tree_node_t *) hmu);
}
}
static void hmu_set_free_size(hmu_t *hmu)
static void
hmu_set_free_size(hmu_t *hmu)
{
gc_size_t size;
bh_assert(hmu && hmu_get_ut(hmu) == HMU_FC);
size = hmu_get_size(hmu);
*((uint32*) ((char*) hmu + size) - 1) = size;
*((uint32*)((char*) hmu + size) - 1) = size;
}
/* Add free chunk back to KFC*/
/* @heap should not be NULL and it should be a valid heap*/
/* @hmu should not be NULL and it should be a HMU of length @size inside @heap*/
/* @hmu should be aligned to 8*/
/* @size should be positive and multiple of 8*/
/* @hmu with size @size will be added into KFC as a new FC.*/
void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
/**
* Add free chunk back to KFC
*
* @param heap should not be NULL and it should be a valid heap
* @param hmu should not be NULL and it should be a HMU of length @size inside @heap
* hmu should be 8-bytes aligned
* @param size should be positive and multiple of 8
* hmu with size @size will be added into KFC as a new FC.
*/
void
gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
{
hmu_normal_node_t *np = NULL;
hmu_tree_node_t *root = NULL, *tp = NULL, *node = NULL;
uint32 node_idx;
bh_assert(gci_is_heap_valid(heap));
bh_assert(
hmu && (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size);
bh_assert(hmu && (gc_uint8*) hmu >= heap->base_addr
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size);
bh_assert(((gc_uint32)(uintptr_t)hmu_to_obj(hmu) & 7) == 0);
bh_assert(
size > 0
&& ((gc_uint8*) hmu) + size
<= heap->base_addr + heap->current_size);
bh_assert(size > 0
&& ((gc_uint8*) hmu) + size <= heap->base_addr + heap->current_size);
bh_assert(!(size & 7));
hmu_set_ut(hmu, HMU_FC);
@ -153,8 +163,9 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
np = (hmu_normal_node_t*) hmu;
node_idx = size >> 3;
np->next = heap->kfc_normal_list[node_idx].next;
heap->kfc_normal_list[node_idx].next = np;
set_hmu_normal_node_next(np, get_hmu_normal_node_next
(&heap->kfc_normal_list[node_idx]));
set_hmu_normal_node_next(&heap->kfc_normal_list[node_idx], np);
return;
}
@ -175,8 +186,8 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
break;
}
tp = tp->right;
} else /* tp->size >= size*/
{
}
else { /* tp->size >= size*/
if (!tp->left) {
tp->left = node;
node->parent = tp;
@ -187,17 +198,19 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
}
}
/* Find a proper hmu for required memory size*/
/* @heap should not be NULL and it should be a valid heap*/
/* @size should cover the header and it should be 8 bytes aligned*/
/* GC will not be performed here.*/
/* Heap extension will not be performed here.*/
/* A proper HMU will be returned. This HMU can include the header and given size. The returned HMU will be aligned to 8 bytes.*/
/* NULL will be returned if there are no proper HMU.*/
BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
/**
* Find a proper hmu for required memory size
*
* @param heap should not be NULL and should be a valid heap
* @param size should cover the header and should be 8 bytes aligned
* GC will not be performed here.
* Heap extension will not be performed here.
*
* @return hmu allocated if success, which will be aligned to 8 bytes,
* NULL otherwise
*/
static hmu_t *
alloc_hmu(gc_heap_t *heap, gc_size_t size)
{
hmu_normal_node_t *node = NULL, *p = NULL;
uint32 node_idx = 0, init_node_idx = 0;
@ -217,7 +230,7 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
for (node_idx = init_node_idx; node_idx < HMU_NORMAL_NODE_CNT;
node_idx++) {
node = heap->kfc_normal_list + node_idx;
if (node->next)
if (get_hmu_normal_node_next(node))
break;
node = NULL;
}
@ -226,32 +239,32 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
if (node) {
bh_assert(node_idx >= init_node_idx);
p = node->next;
node->next = p->next;
p = get_hmu_normal_node_next(node);
set_hmu_normal_node_next(node, get_hmu_normal_node_next(p));
bh_assert(((gc_int32)(uintptr_t)hmu_to_obj(p) & 7) == 0);
if ((gc_size_t)node_idx != (uint32)init_node_idx
&& ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { /* with bigger size*/
/* with bigger size*/
&& ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) {
rest = (hmu_t*) (((char *) p) + size);
gci_add_fc(heap, rest, (node_idx << 3) - size);
hmu_mark_pinuse(rest);
} else {
}
else {
size = node_idx << 3;
next = (hmu_t*) ((char*) p + size);
if (hmu_is_in_heap(heap, next))
hmu_mark_pinuse(next);
}
#if GC_STAT_DATA != 0
heap->total_free_size -= size;
if ((heap->current_size - heap->total_free_size)
> heap->highmark_size)
> heap->highmark_size)
heap->highmark_size = heap->current_size
- heap->total_free_size;
#endif
- heap->total_free_size;
hmu_set_size((hmu_t* ) p, size);
return (hmu_t*) p;
hmu_set_size((hmu_t* )p, size);
return (hmu_t*)p;
}
}
@ -284,18 +297,18 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
rest = (hmu_t*) ((char*) last_tp + size);
gci_add_fc(heap, rest, last_tp->size - size);
hmu_mark_pinuse(rest);
} else {
}
else {
size = last_tp->size;
next = (hmu_t*) ((char*) last_tp + size);
if (hmu_is_in_heap(heap, next))
hmu_mark_pinuse(next);
}
#if GC_STAT_DATA != 0
heap->total_free_size -= size;
if ((heap->current_size - heap->total_free_size) > heap->highmark_size)
heap->highmark_size = heap->current_size - heap->total_free_size;
#endif
hmu_set_size((hmu_t* ) last_tp, size);
return (hmu_t*) last_tp;
}
@ -303,194 +316,159 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
return NULL;
}
/* Find a proper HMU for given size*/
/* @heap should not be NULL and it should be a valid heap*/
/* @size should cover the header and it should be 8 bytes aligned*/
/* This function will try several ways to satisfy the allocation request.*/
/* 1. Find a proper on available HMUs.*/
/* 2. GC will be triggered if 1 failed.*/
/* 3. Find a proper on available HMUS.*/
/* 4. Return NULL if 3 failed*/
/* A proper HMU will be returned. This HMU can include the header and given size. The returned HMU will be aligned to 8 bytes.*/
/* NULL will be returned if there are no proper HMU.*/
BH_STATIC hmu_t* alloc_hmu_ex(gc_heap_t *heap, gc_size_t size)
/**
* Find a proper HMU with given size
*
* @param heap should not be NULL and should be a valid heap
* @param size should cover the header and should be 8 bytes aligned
*
* Note: This function will try several ways to satisfy the allocation request:
* 1. Find a proper on available HMUs.
* 2. GC will be triggered if 1 failed.
* 3. Find a proper on available HMUS.
* 4. Return NULL if 3 failed
*
* @return hmu allocated if success, which will be aligned to 8 bytes,
* NULL otherwise
*/
static hmu_t *
alloc_hmu_ex(gc_heap_t *heap, gc_size_t size)
{
hmu_t *ret = NULL;
bh_assert(gci_is_heap_valid(heap));
bh_assert(size > 0 && !(size & 7));
#ifdef GC_IN_EVERY_ALLOCATION
gci_gc_heap(heap);
ret = alloc_hmu(heap, size);
#else
# if GC_STAT_DATA != 0
if (heap->gc_threshold < heap->total_free_size)
ret = alloc_hmu(heap, size);
# else
ret = alloc_hmu(heap, size);
# endif
if (ret)
return ret;
/*gci_gc_heap(heap);*//* disable gc claim currently */
ret = alloc_hmu(heap, size);
#endif
return ret;
return alloc_hmu(heap, size);
}
unsigned long g_total_malloc = 0;
unsigned long g_total_free = 0;
static unsigned long g_total_malloc = 0;
static unsigned long g_total_free = 0;
gc_object_t _gc_alloc_vo_i_heap(void *vheap,
gc_size_t size ALLOC_EXTRA_PARAMETERS)
#if BH_ENABLE_GC_VERIFY == 0
gc_object_t
gc_alloc_vo(void *vheap, gc_size_t size)
#else
gc_object_t
gc_alloc_vo_internal(void *vheap, gc_size_t size,
const char *file, int line)
#endif
{
gc_heap_t* heap = (gc_heap_t*) vheap;
hmu_t *hmu = NULL;
gc_object_t ret = (gc_object_t) NULL;
gc_size_t tot_size = 0;
gc_size_t tot_size = 0, tot_size_unaligned;
/* align size*/
tot_size = GC_ALIGN_8(size + HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE); /* hmu header, prefix, suffix*/
/* hmu header + prefix + obj + suffix */
tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
/* aligned size*/
tot_size = GC_ALIGN_8(tot_size_unaligned);
if (tot_size < size)
/* integer overflow */
return NULL;
gct_vm_mutex_lock(&heap->lock);
os_mutex_lock(&heap->lock);
hmu = alloc_hmu_ex(heap, tot_size);
if (!hmu)
goto FINISH;
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);
#if BH_ENABLE_GC_VERIFY != 0
hmu_init_prefix_and_suffix(hmu, tot_size, file, line);
#endif
ret = hmu_to_obj(hmu);
if (tot_size > tot_size_unaligned)
/* clear buffer appended by GC_ALIGN_8() */
memset((uint8*)ret + size, 0, tot_size - tot_size_unaligned);
#if BH_ENABLE_MEMORY_PROFILING != 0
bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size);
os_printf("HEAP.ALLOC: heap: %p, size: %u\n", heap, size);
#endif
FINISH:
gct_vm_mutex_unlock(&heap->lock);
finish:
os_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)
#if BH_ENABLE_GC_VERIFY == 0
gc_object_t
gc_realloc_vo(void *vheap, void *ptr, gc_size_t size)
#else
gc_object_t
gc_realloc_vo_internal(void *vheap, void *ptr, gc_size_t size,
const char *file, int line)
#endif
{
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;
gc_size_t tot_size, tot_size_unaligned, tot_size_old = 0;
gc_size_t obj_size, obj_size_old;
/* hmu header + prefix + obj + suffix */
tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
/* aligned size*/
tot_size = GC_ALIGN_8(tot_size_unaligned);
if (tot_size < size)
/* integer overflow */
return NULL;
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)
tot_size_old = hmu_get_size(hmu_old);
if (tot_size <= tot_size_old)
/* current node alreay meets requirement */
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);
os_mutex_lock(&heap->lock);
hmu = alloc_hmu_ex(heap, tot_size);
if (!hmu)
goto FINISH;
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);
#if BH_ENABLE_GC_VERIFY != 0
hmu_init_prefix_and_suffix(hmu, tot_size, file, line);
#endif
ret = hmu_to_obj(hmu);
#if BH_ENABLE_MEMORY_PROFILING != 0
bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size);
os_printf("HEAP.ALLOC: heap: %p, size: %u\n", heap, size);
#endif
FINISH:
gct_vm_mutex_unlock(&heap->lock);
finish:
os_mutex_unlock(&heap->lock);
if (ret) {
memset(ret, 0, size);
obj_size = tot_size - HMU_SIZE - OBJ_PREFIX_SIZE - OBJ_SUFFIX_SIZE;
memset(ret, 0, obj_size);
if (obj_old) {
memcpy(ret, obj_old, size_old);
gc_free_h(vheap, obj_old);
obj_size_old = tot_size_old - HMU_SIZE
- OBJ_PREFIX_SIZE - OBJ_SUFFIX_SIZE;
bh_memcpy_s(ret, obj_size, obj_old, obj_size_old);
gc_free_vo(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)
{
gc_heap_t* heap = (gc_heap_t*) vheap;
gc_object_t ret = (gc_object_t) NULL;
hmu_t *hmu = NULL;
gc_size_t tot_size = 0;
bh_assert(gci_is_heap_valid(heap));
/* 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;
hmu = alloc_hmu_ex(heap, tot_size);
if (!hmu)
goto FINISH;
/* reset all fields*/
memset((char*) hmu + sizeof(*hmu), 0, tot_size - sizeof(*hmu));
/* hmu->header = 0; */
hmu_set_ut(hmu, HMU_JO);
hmu_unmark_jo(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:
return ret;
}
/* Do some checking to see if given pointer is a possible valid heap*/
/* Return GC_TRUE if all checking passed*/
/* Return GC_FALSE otherwise*/
int gci_is_heap_valid(gc_heap_t *heap)
/**
* Do some checking to see if given pointer is a possible valid heap
* @return GC_TRUE if all checking passed, GC_FALSE otherwise
*/
int
gci_is_heap_valid(gc_heap_t *heap)
{
if (!heap)
return GC_FALSE;
@ -500,7 +478,14 @@ int gci_is_heap_valid(gc_heap_t *heap)
return GC_TRUE;
}
int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS)
#if BH_ENABLE_GC_VERIFY == 0
int
gc_free_vo(void *vheap, gc_object_t obj)
#else
int
gc_free_vo_internal(void *vheap, gc_object_t obj,
const char *file, int line)
#endif
{
gc_heap_t* heap = (gc_heap_t*) vheap;
hmu_t *hmu = NULL;
@ -516,11 +501,11 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS)
hmu = obj_to_hmu(obj);
gct_vm_mutex_lock(&heap->lock);
os_mutex_lock(&heap->lock);
if ((gc_uint8 *) hmu >= heap->base_addr
&& (gc_uint8 *) hmu < heap->base_addr + heap->current_size) {
#ifdef GC_VERIFY
if ((gc_uint8 *)hmu >= heap->base_addr
&& (gc_uint8 *)hmu < heap->base_addr + heap->current_size) {
#if BH_ENABLE_GC_VERIFY != 0
hmu_verify(hmu);
#endif
ut = hmu_get_ut(hmu);
@ -535,11 +520,9 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS)
g_total_free += size;
#if GC_STAT_DATA != 0
heap->total_free_size += size;
#endif
#if BH_ENABLE_MEMORY_PROFILING != 0
bh_printf("HEAP.FREE, heap: %p, size: %u\n",heap, size);
os_printf("HEAP.FREE, heap: %p, size: %u\n", heap, size);
#endif
if (!hmu_get_pinuse(hmu)) {
@ -575,54 +558,51 @@ int gc_free_i_heap(void *vheap, gc_object_t obj ALLOC_EXTRA_PARAMETERS)
goto out;
}
out:
gct_vm_mutex_unlock(&heap->lock);
out:
os_mutex_unlock(&heap->lock);
return ret;
}
void gc_dump_heap_stats(gc_heap_t *heap)
void
gc_dump_heap_stats(gc_heap_t *heap)
{
bh_printf("heap: %p, heap start: %p\n", heap, heap->base_addr);
bh_printf(
"total malloc: totalfree: %u, current: %u, highmark: %u, gc cnt: %u\n",
heap->total_free_size, heap->current_size, heap->highmark_size,
heap->total_gc_count);
bh_printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n",
g_total_malloc, g_total_free, g_total_malloc - g_total_free);
os_printf("heap: %p, heap start: %p\n", heap, heap->base_addr);
os_printf("total free: %u, current: %u, highmark: %u\n",
heap->total_free_size, heap->current_size, heap->highmark_size);
os_printf("g_total_malloc=%lu, g_total_free=%lu, occupied=%lu\n",
g_total_malloc, g_total_free, g_total_malloc - g_total_free);
}
#ifdef GC_TEST
void gci_dump(char* buf, gc_heap_t *heap)
void
gci_dump(gc_heap_t *heap)
{
hmu_t *cur = NULL, *end = NULL;
hmu_type_t ut;
gc_size_t size;
int i = 0;
int p;
char inuse;
int mark;
int i = 0, p, mark;
char inuse = 'U';
cur = (hmu_t*)heap->base_addr;
end = (hmu_t*)((char*)heap->base_addr + heap->current_size);
while(cur < end)
{
while(cur < end) {
ut = hmu_get_ut(cur);
size = hmu_get_size(cur);
p = hmu_get_pinuse(cur);
mark = hmu_is_jo_marked (cur);
if(ut == HMU_VO)
inuse = 'V';
else if(ut == HMU_JO)
inuse = hmu_is_jo_marked(cur) ? 'J' : 'j';
else if(ut == HMU_FC)
inuse = 'F';
if (ut == HMU_VO)
inuse = 'V';
else if (ut == HMU_JO)
inuse = hmu_is_jo_marked(cur) ? 'J' : 'j';
else if (ut == HMU_FC)
inuse = 'F';
bh_assert(size > 0);
buf += sprintf(buf, "#%d %08x %x %x %d %c %d\n", i, (char*) cur - (char*) heap->base_addr, ut, p, mark, inuse, hmu_obj_size(size));
os_printf("#%d %08x %x %x %d %c %d\n",
i, (int32)((char*) cur - (char*) heap->base_addr),
ut, p, mark, inuse, (int32)hmu_obj_size(size));
cur = (hmu_t*)((char *)cur + size);
i++;
@ -631,4 +611,3 @@ void gci_dump(char* buf, gc_heap_t *heap)
bh_assert(cur == end);
}
#endif

View File

@ -21,49 +21,8 @@
extern "C" {
#endif
/*Pre-compile configuration can be done here or on Makefiles*/
/*#define GC_EMBEDDED or GC_STANDALONE*/
/*#define GC_DEBUG*/
/*#define GC_TEST // TEST mode is a sub-mode of STANDALONE*/
/* #define GC_ALLOC_TRACE */
/* #define GC_STAT */
#ifndef GC_STAT_DATA
#define GC_STAT_DATA 1
#endif
#define GC_HEAD_PADDING 4
/* Standalone GC is used for testing.*/
#ifndef GC_EMBEDDED
# ifndef GC_STANDALONE
# define GC_STANDALONE
# endif
#endif
#if defined(GC_EMBEDDED) && defined(GC_STANDALONE)
# error "Can not define GC_EMBEDDED and GC_STANDALONE at the same time"
#endif
#ifdef BH_TEST
# ifndef GC_TEST
# define GC_TEST
# endif
#endif
#ifdef BH_DEBUG
/*instrument mode ignore GC_DEBUG feature, for instrument testing gc_alloc_vo_i_heap only has func_name parameter*/
#if !defined INSTRUMENT_TEST_ENABLED && !defined GC_DEBUG
# define GC_DEBUG
#endif
#endif
#if defined(GC_EMBEDDED) && defined(GC_TEST)
# error "Can not defined GC_EMBEDDED and GC_TEST at the same time"
#endif
typedef void *gc_handle_t;
typedef void *gc_object_t;
#define NULL_REF ((gc_object_t)NULL)
#define GC_SUCCESS (0)
@ -74,72 +33,23 @@ typedef void *gc_object_t;
#define GC_MAX_HEAP_SIZE (256 * BH_KB)
typedef int64 gc_int64;
typedef unsigned int gc_uint32;
typedef signed int gc_int32;
typedef unsigned short gc_uint16;
typedef signed short gc_int16;
typedef unsigned char gc_uint8;
typedef signed char gc_int8;
typedef gc_uint32 gc_size_t;
typedef enum {
MMT_SHARED = 0,
MMT_INSTANCE = 1,
MMT_APPMANAGER = MMT_SHARED,
MMT_VERIFIER = MMT_SHARED,
MMT_JHI = MMT_SHARED,
MMT_LOADER = MMT_SHARED,
MMT_APPLET = MMT_INSTANCE,
MMT_INTERPRETER = MMT_INSTANCE
} gc_mm_t;
#ifdef GC_STAT
#define GC_HEAP_STAT_SIZE (128 / 4)
typedef struct {
int usage;
int usage_block;
int vo_usage;
int jo_usage;
int free;
int free_block;
int vo_free;
int jo_free;
int usage_sizes[GC_HEAP_STAT_SIZE];
int free_sizes[GC_HEAP_STAT_SIZE];
}gc_stat_t;
extern void gc_heap_stat(void* heap, gc_stat_t* gc_stat);
extern void __gc_print_stat(void *heap, int verbose);
#define gc_print_stat __gc_print_stat
#else
#define gc_print_stat(heap, verbose)
#endif
#if GC_STAT_DATA != 0
typedef void * gc_handle_t;
typedef void * gc_object_t;
typedef int64 gc_int64;
typedef uint32 gc_uint32;
typedef int32 gc_int32;
typedef uint16 gc_uint16;
typedef int16 gc_int16;
typedef uint8 gc_uint8;
typedef int8 gc_int8;
typedef uint32 gc_size_t;
typedef enum {
GC_STAT_TOTAL = 0,
GC_STAT_FREE,
GC_STAT_HIGHMARK,
GC_STAT_COUNT,
GC_STAT_TIME,
GC_STAT_MAX_1,
GC_STAT_MAX_2,
GC_STAT_MAX_3,
GC_STAT_MAX
} GC_STAT_INDEX;
#endif
/*////////////// Exported APIs*/
/**
* GC initialization from a buffer
*
@ -148,7 +58,8 @@ typedef enum {
*
* @return gc handle if success, NULL otherwise
*/
extern gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size);
gc_handle_t
gc_init_with_pool(char *buf, gc_size_t buf_size);
/**
* Destroy heap which is initilized from a buffer
@ -158,9 +69,8 @@ extern gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size);
* @return GC_SUCCESS if success
* GC_ERROR for bad parameters or failed system resource freeing.
*/
extern int gc_destroy_with_pool(gc_handle_t handle);
#if GC_STAT_DATA != 0
int
gc_destroy_with_pool(gc_handle_t handle);
/**
* Get Heap Stats
@ -169,166 +79,44 @@ extern int gc_destroy_with_pool(gc_handle_t handle);
* @param size [in] the size of stats
* @param mmt [in] type of heap, MMT_SHARED or MMT_INSTANCE
*/
extern void* gc_heap_stats(void *heap, uint32* stats, int size, gc_mm_t mmt);
void *
gc_heap_stats(void *heap, uint32* stats, int size);
/**
* Set GC threshold factor
*
* @param heap [in] the heap to set
* @param factor [in] the threshold size is free_size * factor / 1000
*
* @return GC_SUCCESS if success.
*/
extern int gc_set_threshold_factor(void *heap, unsigned int factor);
#if BH_ENABLE_GC_VERIFY == 0
#endif
gc_object_t
gc_alloc_vo(void *heap, gc_size_t size);
/*////// Allocate heap object*/
gc_object_t
gc_realloc_vo(void *heap, void *ptr, gc_size_t size);
/* There are two versions of allocate functions. The functions with _i suffix should be only used*/
/* internally. Functions without _i suffix are just wrappers with the corresponded functions with*/
/* _i suffix. Allocation operation code position are record under DEBUG model for debugging.*/
#ifdef GC_DEBUG
# define ALLOC_EXTRA_PARAMETERS ,const char*file_name,int line_number
# 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
int
gc_free_vo(void *heap, gc_object_t obj);
/**
* Invoke a GC
*
* @param heap
*
* @return GC_SUCCESS if success
*/
extern int gci_gc_heap(void *heap);
#else /* else of BH_ENABLE_GC_VERIFY */
/**
* Allocate VM Object in specific heap.
*
* @param heap heap to allocate.
* @param size bytes to allocate.
*
* @return pointer to VM object allocated
* NULL if failed.
*/
extern gc_object_t _gc_alloc_vo_i_heap(void *heap,
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);
#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
gc_object_t
gc_alloc_vo_internal(void *heap, gc_size_t size,
const char *file, int line);
/**
* Allocate Java object in specific heap.
*
* @param heap heap to allocate.
* @param size bytes to allocate.
*
* @return pointer to Java object allocated
* NULL if failed.
*/
extern gc_object_t _gc_alloc_jo_i_heap(void *heap,
gc_size_t size ALLOC_EXTRA_PARAMETERS);
gc_object_t
gc_realloc_vo_internal(void *heap, void *ptr, gc_size_t size,
const char *file, int line);
/**
* Free VM object
*
* @param heap heap to free.
* @param obj pointer to object need free.
*
* @return GC_SUCCESS if success
*/
extern int gc_free_i_heap(void *heap, gc_object_t obj ALLOC_EXTRA_PARAMETERS);
int
gc_free_vo_internal(void *heap, gc_object_t obj,
const char *file, int line);
/**
* Add ref to rootset of gc for current instance.
*
* @param obj pointer to real load of a valid Java object managed by gc for current instance.
*
* @return GC_SUCCESS if success.
* GC_ERROR for invalid parameters.
*/
extern int gc_add_root(void* heap, gc_object_t obj);
#define gc_alloc_vo(heap, size) \
gc_alloc_vo_internal(heap, size, __FILE__, __LINE__)
/*////////////// Imported APIs which should be implemented in other components*/
#define gc_realloc_vo(heap, ptr, size) \
gc_realloc_vo_internal(heap, ptr, size, __FILE__, __LINE__)
/*////// Java object layout related APIs*/
#define gc_free_vo(heap, obj) \
gc_free_vo_internal(heap, obj, __FILE__, __LINE__)
/**
* Get Java object size from corresponding VM module
*
* @param obj pointer to the real load of a Java object.
*
* @return size of java object.
*/
extern gc_size_t vm_get_java_object_size(gc_object_t obj);
/**
* Get reference list of this object
*
* @param obj [in] pointer to java object.
* @param is_compact_mode [in] indicate the java object mode. GC_TRUE or GC_FALSE.
* @param ref_num [out] the size of ref_list.
* @param ref_list [out] if is_compact_mode is GC_FALSE, this parameter will be set to a list of offset.
* @param ref_start_offset [out] If is_compact_mode is GC_TRUE, this parameter will be set to the start offset of the references in this object.
*
* @return GC_SUCCESS if success.
* GC_ERROR when error occurs.
*/
extern int vm_get_java_object_ref_list(gc_object_t obj, int *is_compact_mode,
gc_size_t *ref_num, gc_uint16 **ref_list, gc_uint32 *ref_start_offset);
/**
* Get gc handle for current instance
*
*
* @return instance heap handle.
*/
extern gc_handle_t app_manager_get_cur_applet_heap(void);
/**
* Begin current instance heap rootset enumeration
*
*
* @return GC_SUCCESS if success.
* GC_ERROR when error occurs.
*/
extern int vm_begin_rootset_enumeration(void *heap);
#ifdef _INSTRUMENT_TEST_ENABLED
extern int vm_begin_rootset_enumeration_instr(void *heap, const char*func_name);
#define vm_begin_rootset_enumeration(heap) vm_begin_rootset_enumeration_instr(heap, __FUNCTION__)
#else
#define vm_begin_rootset_enumeration _vm_begin_rootset_enumeration
#endif /* INSTUMENT_TEST_ENABLED*/
#ifndef offsetof
#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
#endif
#endif /* end of BH_ENABLE_GC_VERIFY */
#ifdef __cplusplus
}

View File

@ -11,58 +11,55 @@ extern "C" {
#endif
#include "bh_platform.h"
#include "bh_thread.h"
#include "bh_assert.h"
#include "ems_gc.h"
/* basic block managed by EMS gc is the so-called HMU (heap memory unit)*/
typedef enum _hmu_type_enum
{
/* HMU (heap memory unit) basic block type */
typedef enum hmu_type_enum {
HMU_TYPE_MIN = 0,
HMU_TYPE_MAX = 3,
HMU_JO = 3,
HMU_VO = 2,
HMU_FC = 1,
HMU_FM = 0
}hmu_type_t;
} hmu_type_t;
typedef struct _hmu_struct
{
typedef struct hmu_struct {
gc_uint32 header;
}hmu_t;
} hmu_t;
#if defined(GC_VERIFY)
#if BH_ENABLE_GC_VERIFY != 0
#define GC_OBJECT_PREFIX_PADDING_CNT 3
#define GC_OBJECT_SUFFIX_PADDING_CNT 4
#define GC_OBJECT_PADDING_VALUE (0x12345678)
typedef struct _gc_object_prefix
{
typedef struct gc_object_prefix {
const char *file_name;
gc_int32 line_no;
gc_int32 size;
gc_uint32 padding[GC_OBJECT_PREFIX_PADDING_CNT];
}gc_object_prefix_t;
} gc_object_prefix_t;
typedef struct gc_object_suffix {
gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT];
} gc_object_suffix_t;
#define OBJ_PREFIX_SIZE (sizeof(gc_object_prefix_t))
typedef struct _gc_object_suffix
{
gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT];
}gc_object_suffix_t;
#define OBJ_SUFFIX_SIZE (sizeof(gc_object_suffix_t))
extern void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file_name, int line_no);
extern void hmu_verify(hmu_t *hmu);
void
hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size,
const char *file_name, int line_no);
void
hmu_verify(hmu_t *hmu);
#define SKIP_OBJ_PREFIX(p) ((void*)((gc_uint8*)(p) + OBJ_PREFIX_SIZE))
#define SKIP_OBJ_SUFFIX(p) ((void*)((gc_uint8*)(p) + OBJ_SUFFIX_SIZE))
#define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
#else
#else /* else of BH_ENABLE_GC_VERIFY */
#define OBJ_PREFIX_SIZE 0
#define OBJ_SUFFIX_SIZE 0
@ -72,7 +69,7 @@ extern void hmu_verify(hmu_t *hmu);
#define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
#endif /* GC_DEBUG*/
#endif /* end of BH_ENABLE_GC_VERIFY */
#define hmu_obj_size(s) ((s)-OBJ_EXTRA_SIZE)
@ -81,7 +78,9 @@ extern void hmu_verify(hmu_t *hmu);
#define GC_SMALLEST_SIZE GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8)
#define GC_GET_REAL_SIZE(x) GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + (((x) > 8) ? (x): 8))
/*////// functions for bit operation*/
/**
* hmu bit operation
*/
#define SETBIT(v, offset) (v) |= (1 << (offset))
#define GETBIT(v, offset) ((v) & (1 << (offset)) ? 1 : 0)
@ -94,7 +93,9 @@ extern void hmu_verify(hmu_t *hmu);
#define CLRBITS(v, offset, size) (v) &= ~(((1 << size) - 1) << offset)
#define GETBITS(v, offset, size) (((v) & ((uint32)(((1 << size) - 1) << offset))) >> offset)
/*////// gc object layout definition*/
/**
* gc object layout definition
*/
#define HMU_SIZE (sizeof(hmu_t))
@ -123,6 +124,12 @@ extern void hmu_verify(hmu_t *hmu);
#define hmu_unmark_jo(hmu) CLRBIT ((hmu)->header, HMU_JO_MB_OFFSET)
#define hmu_is_jo_marked(hmu) GETBIT ((hmu)->header, HMU_JO_MB_OFFSET)
/**
* The hmu size is divisible by 8, its lowest 3 bits are 0, so we only
* store its higher bits of bit [29..3], and bit [2..0] are not stored.
* After that, the maximal heap size can be enlarged from (1<<27) = 128MB
* to (1<<27) * 8 = 1GB.
*/
#define HMU_SIZE_SIZE 27
#define HMU_SIZE_OFFSET 0
@ -131,10 +138,12 @@ extern void hmu_verify(hmu_t *hmu);
#define hmu_is_vo_freed(hmu) GETBIT ((hmu)->header, HMU_VO_FB_OFFSET)
#define hmu_unfree_vo(hmu) CLRBIT ((hmu)->header, HMU_VO_FB_OFFSET)
#define hmu_get_size(hmu) GETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE)
#define hmu_set_size(hmu, size) SETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, size)
#define hmu_get_size(hmu) (GETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE) << 3)
#define hmu_set_size(hmu, size) SETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, ((size) >> 3))
/*////// HMU free chunk management*/
/**
* HMU free chunk management
*/
#define HMU_NORMAL_NODE_CNT 32
#define HMU_FC_NORMAL_MAX_SIZE ((HMU_NORMAL_NODE_CNT - 1) << 3)
@ -143,24 +152,43 @@ extern void hmu_verify(hmu_t *hmu);
#error "Too small GC_MAX_HEAP_SIZE"
#endif
typedef struct _hmu_normal_node
{
typedef struct hmu_normal_node {
hmu_t hmu_header;
struct _hmu_normal_node *next;
}hmu_normal_node_t;
gc_int32 next_offset;
} hmu_normal_node_t;
typedef struct _hmu_tree_node
static inline hmu_normal_node_t *
get_hmu_normal_node_next(hmu_normal_node_t *node)
{
return node->next_offset
? (hmu_normal_node_t *)((uint8*)node + node->next_offset)
: NULL;
}
static inline void
set_hmu_normal_node_next(hmu_normal_node_t *node, hmu_normal_node_t *next)
{
if (next) {
bh_assert((uint8*)next - (uint8*)node < INT32_MAX);
node->next_offset = (gc_int32)(intptr_t)
((uint8*)next - (uint8*)node);
}
else {
node->next_offset = 0;
}
}
typedef struct hmu_tree_node {
hmu_t hmu_header;
gc_size_t size;
struct _hmu_tree_node *left;
struct _hmu_tree_node *right;
struct _hmu_tree_node *parent;
}hmu_tree_node_t;
struct hmu_tree_node *left;
struct hmu_tree_node *right;
struct hmu_tree_node *parent;
} hmu_tree_node_t;
typedef struct _gc_heap_struct
{
gc_handle_t heap_id; /* for double checking*/
typedef struct gc_heap_struct {
/* for double checking*/
gc_handle_t heap_id;
gc_uint8 *base_addr;
gc_size_t current_size;
@ -173,95 +201,32 @@ typedef struct _gc_heap_struct
/* order in kfc_tree is: size[left] <= size[cur] < size[right]*/
hmu_tree_node_t kfc_tree_root;
/* for rootset enumeration of private heap*/
void *root_set;
/* whether the fast mode of marking process that requires
additional memory fails. When the fast mode fails, the
marking process can still be done in the slow mode, which
doesn't need additional memory (by walking through all
blocks and marking sucessors of marked nodes until no new
node is marked). TODO: slow mode is not implemented. */
unsigned is_fast_marking_failed : 1;
#if GC_STAT_DATA != 0
gc_size_t highmark_size;
gc_size_t init_size;
gc_size_t total_gc_count;
gc_size_t highmark_size;
gc_size_t total_free_size;
gc_size_t gc_threshold;
gc_size_t gc_threshold_factor;
gc_int64 total_gc_time;
#endif
}gc_heap_t;
} gc_heap_t;
/*////// MISC internal used APIs*/
/**
* MISC internal used APIs
*/
extern void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size);
extern int gci_is_heap_valid(gc_heap_t *heap);
void
gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size);
#ifdef GC_DEBUG
extern void gci_verify_heap(gc_heap_t *heap);
extern void gci_dump(char* buf, gc_heap_t *heap);
#endif
int
gci_is_heap_valid(gc_heap_t *heap);
#if GC_STAT_DATA != 0
/**
* Verify heap integrity
*/
void
gci_verify_heap(gc_heap_t *heap);
/* the default GC threshold size is free_size * GC_DEFAULT_THRESHOLD_FACTOR / 1000 */
#define GC_DEFAULT_THRESHOLD_FACTOR 400
static inline void gc_update_threshold(gc_heap_t *heap)
{
heap->gc_threshold = heap->total_free_size * heap->gc_threshold_factor / 1000;
}
#endif
/*////// MISC data structures*/
#define MARK_NODE_OBJ_CNT 256
/* mark node is used for gc marker*/
typedef struct _mark_node_struct
{
/* number of to-expand objects can be saved in this node*/
gc_size_t cnt;
/* the first unused index*/
int idx;
/* next node on the node list*/
struct _mark_node_struct *next;
/* the actual to-expand objects list*/
gc_object_t set[MARK_NODE_OBJ_CNT];
}mark_node_t;
/*////// Imported APIs wrappers under TEST mode*/
#ifdef GC_TEST
extern int (*gct_vm_get_java_object_ref_list)(
gc_object_t obj,
int *is_compact_mode, /* can be set to GC_TRUE, or GC_FALSE */
gc_size_t *ref_num,
gc_uint16 **ref_list,
gc_uint32 *ref_start_offset);
extern int (*gct_vm_mutex_init)(korp_mutex *mutex);
extern int (*gct_vm_mutex_destroy)(korp_mutex *mutex);
extern int (*gct_vm_mutex_lock)(korp_mutex *mutex);
extern int (*gct_vm_mutex_unlock)(korp_mutex *mutex);
extern gc_handle_t (*gct_vm_get_gc_handle_for_current_instance)(void);
extern int (*gct_vm_begin_rootset_enumeration)(void* heap);
extern int (*gct_vm_gc_finished)(void);
#else
#define gct_vm_get_java_object_ref_list bh_get_java_object_ref_list
#define gct_vm_mutex_init vm_mutex_init
#define gct_vm_mutex_destroy vm_mutex_destroy
#define gct_vm_mutex_lock vm_mutex_lock
#define gct_vm_mutex_unlock vm_mutex_unlock
#define gct_vm_get_gc_handle_for_current_instance app_manager_get_cur_applet_heap
#define gct_vm_begin_rootset_enumeration vm_begin_rootset_enumeration
#define gct_vm_gc_finished jeff_runtime_gc_finished
#endif
/**
* Dump heap nodes
*/
void
gci_dump(gc_heap_t *heap);
#ifdef __cplusplus
}

View File

@ -5,13 +5,19 @@
#include "ems_gc_internal.h"
#if defined(GC_VERIFY)
/* Set default value to prefix and suffix*/
#if BH_ENABLE_GC_VERIFY != 0
/* @hmu should not be NULL and it should have been correctly initilized (except for prefix and suffix part)*/
/* @tot_size is offered here because hmu_get_size can not be used till now. @tot_size should not be smaller than OBJ_EXTRA_SIZE.*/
/* For VO, @tot_size should be equal to object total size.*/
void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file_name, int line_no)
/**
* Set default value to prefix and suffix
* @param hmu should not be NULL and should have been correctly initilized
* (except prefix and suffix part)
* @param tot_size is offered here because hmu_get_size can not be used till now.
* tot_size should not be smaller than OBJ_EXTRA_SIZE.
* For VO, tot_size should be equal to object total size.
*/
void
hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size,
const char *file_name, int line_no)
{
gc_object_prefix_t *prefix = NULL;
gc_object_suffix_t *suffix = NULL;
@ -28,17 +34,18 @@ void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file
prefix->file_name = file_name;
prefix->line_no = line_no;
prefix->size = tot_size;
for(i = 0;i < GC_OBJECT_PREFIX_PADDING_CNT;i++)
{
for(i = 0;i < GC_OBJECT_PREFIX_PADDING_CNT;i++) {
prefix->padding[i] = GC_OBJECT_PADDING_VALUE;
}
for(i = 0;i < GC_OBJECT_SUFFIX_PADDING_CNT;i++)
{
for(i = 0;i < GC_OBJECT_SUFFIX_PADDING_CNT;i++) {
suffix->padding[i] = GC_OBJECT_PADDING_VALUE;
}
}
void hmu_verify(hmu_t *hmu)
void
hmu_verify(hmu_t *hmu)
{
gc_object_prefix_t *prefix = NULL;
gc_object_suffix_t *suffix = NULL;
@ -83,5 +90,6 @@ void hmu_verify(hmu_t *hmu)
bh_assert(is_padding_ok);
}
}
#endif
#endif /* end of BH_ENABLE_GC_VERIFY */

View File

@ -5,37 +5,8 @@
#include "ems_gc_internal.h"
#define HEAP_INC_FACTOR 1
/* Check if current platform is compatible with current GC design*/
/* Return GC_ERROR if not;*/
/* Return GC_SUCCESS otherwise.*/
int gci_check_platform()
{
#define CHECK(x, y) do { \
if((x) != (y)) { \
bh_printf("Platform checking failed on LINE %d at FILE %s.",\
__LINE__, __FILE__); \
return GC_ERROR; \
} \
} while(0)
CHECK(8, sizeof(gc_int64));
CHECK(4, sizeof(gc_uint32));
CHECK(4, sizeof(gc_int32));
CHECK(2, sizeof(gc_uint16));
CHECK(2, sizeof(gc_int16));
CHECK(1, sizeof(gc_int8));
CHECK(1, sizeof(gc_uint8));
CHECK(4, sizeof(gc_size_t));
/*CHECK(4, sizeof(void *));*/
return GC_SUCCESS;
}
gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
gc_handle_t
gc_init_with_pool(char *buf, gc_size_t buf_size)
{
char *buf_end = buf + buf_size;
char *buf_aligned = (char*) (((uintptr_t) buf + 7) & (uintptr_t)~7);
@ -46,14 +17,8 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
hmu_tree_node_t *root = NULL, *q = NULL;
int i = 0, ret;
/* check system compatibility*/
if (gci_check_platform() == GC_ERROR) {
bh_printf("Check platform compatibility failed");
return NULL;
}
if (buf_size < 1024) {
bh_printf("[GC_ERROR]heap_init_size(%d) < 1024", buf_size);
os_printf("[GC_ERROR]heap_init_size(%d) < 1024\n", buf_size);
return NULL;
}
@ -63,30 +28,20 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
memset(heap, 0, sizeof *heap);
memset(base_addr, 0, heap_max_size);
ret = gct_vm_mutex_init(&heap->lock);
ret = os_mutex_init(&heap->lock);
if (ret != BHT_OK) {
bh_printf("[GC_ERROR]failed to init lock ");
os_printf("[GC_ERROR]failed to init lock\n");
return NULL;
}
#ifdef BH_FOOTPRINT
bh_printf("\nINIT HEAP 0x%08x %d\n", base_addr, heap_max_size);
#endif
/* init all data structures*/
heap->max_size = heap_max_size;
heap->current_size = heap_max_size;
heap->base_addr = (gc_uint8*) base_addr;
heap->heap_id = (gc_handle_t) heap;
heap->base_addr = (gc_uint8*)base_addr;
heap->heap_id = (gc_handle_t)heap;
#if GC_STAT_DATA != 0
heap->total_free_size = heap->current_size;
heap->highmark_size = 0;
heap->total_gc_count = 0;
heap->total_gc_time = 0;
heap->gc_threshold_factor = GC_DEFAULT_THRESHOLD_FACTOR;
gc_update_threshold(heap);
#endif
for (i = 0; i < HMU_NORMAL_NODE_CNT; i++) {
/* make normal node look like a FC*/
@ -112,30 +67,29 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size)
q->parent = root;
q->size = heap->current_size;
bh_assert(
root->size <= HMU_FC_NORMAL_MAX_SIZE
&& HMU_FC_NORMAL_MAX_SIZE < q->size); /*@NOTIFY*/
bh_assert(root->size <= HMU_FC_NORMAL_MAX_SIZE
&& HMU_FC_NORMAL_MAX_SIZE < q->size);
#if BH_ENABLE_MEMORY_PROFILING != 0
bh_printf("heap is successfully initialized with max_size=%u.",
heap_max_size);
os_printf("heap is successfully initialized with max_size=%u.\n",
heap_max_size);
#endif
return heap;
}
int gc_destroy_with_pool(gc_handle_t handle)
int
gc_destroy_with_pool(gc_handle_t handle)
{
gc_heap_t *heap = (gc_heap_t *) handle;
gct_vm_mutex_destroy(&heap->lock);
os_mutex_destroy(&heap->lock);
memset(heap->base_addr, 0, heap->max_size);
memset(heap, 0, sizeof(gc_heap_t));
return GC_SUCCESS;
}
#if defined(GC_VERIFY)
/* Verify heap integrity*/
/* @heap should not be NULL and it should be a valid heap*/
void gci_verify_heap(gc_heap_t *heap)
#if BH_ENABLE_GC_VERIFY != 0
void
gci_verify_heap(gc_heap_t *heap)
{
hmu_t *cur = NULL, *end = NULL;
@ -151,9 +105,9 @@ void gci_verify_heap(gc_heap_t *heap)
}
#endif
void* gc_heap_stats(void *heap_arg, uint32* stats, int size, gc_mm_t mmt)
void *
gc_heap_stats(void *heap_arg, uint32* stats, int size)
{
(void) mmt;
int i;
gc_heap_t *heap = (gc_heap_t *) heap_arg;
@ -168,15 +122,10 @@ void* gc_heap_stats(void *heap_arg, uint32* stats, int size, gc_mm_t mmt)
case GC_STAT_HIGHMARK:
stats[i] = heap->highmark_size;
break;
case GC_STAT_COUNT:
stats[i] = heap->total_gc_count;
break;
case GC_STAT_TIME:
stats[i] = (uint32)heap->total_gc_time;
break;
default:
break;
}
}
return heap;
}

View File

@ -4,7 +4,6 @@
*/
#include "mem_alloc.h"
#include "config.h"
#if DEFAULT_MEM_ALLOCATOR == MEM_ALLOCATOR_EMS
@ -23,25 +22,24 @@ void mem_allocator_destroy(mem_allocator_t allocator)
void *
mem_allocator_malloc(mem_allocator_t allocator, uint32_t size)
{
return gc_alloc_vo_h((gc_handle_t) allocator, size);
return gc_alloc_vo((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);
return gc_realloc_vo((gc_handle_t) allocator, ptr, size);
}
void mem_allocator_free(mem_allocator_t allocator, void *ptr)
{
if (ptr)
gc_free_h((gc_handle_t) allocator, ptr);
gc_free_vo((gc_handle_t) allocator, ptr);
}
#else /* else of DEFAULT_MEM_ALLOCATOR */
#include "tlsf/tlsf.h"
#include "bh_thread.h"
typedef struct mem_allocator_tlsf {
tlsf_t tlsf;
@ -79,7 +77,7 @@ mem_allocator_create(void *mem, uint32_t size)
allocator_tlsf->tlsf = tlsf;
if (vm_mutex_init(&allocator_tlsf->lock)) {
if (os_mutex_init(&allocator_tlsf->lock)) {
printf("Create mem allocator failed: tlsf_malloc failed.\n");
tlsf_free(tlsf, allocator_tlsf);
tlsf_destroy(tlsf);
@ -95,7 +93,7 @@ mem_allocator_destroy(mem_allocator_t allocator)
mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
tlsf_t tlsf = allocator_tlsf->tlsf;
vm_mutex_destroy(&allocator_tlsf->lock);
os_mutex_destroy(&allocator_tlsf->lock);
tlsf_free(tlsf, allocator_tlsf);
tlsf_destroy(tlsf);
}
@ -110,9 +108,9 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size)
/* tlsf doesn't allow to allocate 0 byte */
size = 1;
vm_mutex_lock(&allocator_tlsf->lock);
os_mutex_lock(&allocator_tlsf->lock);
ret = tlsf_malloc(allocator_tlsf->tlsf, size);
vm_mutex_unlock(&allocator_tlsf->lock);
os_mutex_unlock(&allocator_tlsf->lock);
return ret;
}
@ -126,9 +124,9 @@ mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size)
/* tlsf doesn't allow to allocate 0 byte */
size = 1;
vm_mutex_lock(&allocator_tlsf->lock);
os_mutex_lock(&allocator_tlsf->lock);
ret = tlsf_realloc(allocator_tlsf->tlsf, ptr, size);
vm_mutex_unlock(&allocator_tlsf->lock);
os_mutex_unlock(&allocator_tlsf->lock);
return ret;
}
@ -137,9 +135,9 @@ mem_allocator_free(mem_allocator_t allocator, void *ptr)
{
if (ptr) {
mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
vm_mutex_lock(&allocator_tlsf->lock);
os_mutex_lock(&allocator_tlsf->lock);
tlsf_free(allocator_tlsf->tlsf, ptr);
vm_mutex_unlock(&allocator_tlsf->lock);
os_mutex_unlock(&allocator_tlsf->lock);
}
}

View File

@ -6,7 +6,7 @@
#ifndef __MEM_ALLOC_H
#define __MEM_ALLOC_H
#include <inttypes.h>
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {

View File

@ -0,0 +1,10 @@
This folder contains the platform abstract layer for multiple platforms. To support a new platform, you can simply create a new folder here and implement all the APIs defined in [`include`](./include) folder.
Refer to [port_wamr.md](../../../doc/port_wamr.md) for how to port WAMR to a target platform.

View File

@ -3,15 +3,25 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "bh_common.h"
#include <stdlib.h>
#include <string.h>
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
int
os_thread_sys_init();
void
os_thread_sys_destroy();
int
bh_platform_init()
{
return 0;
return os_thread_sys_init();
}
void
bh_platform_destroy()
{
os_thread_sys_destroy();
}
void *
@ -32,24 +42,24 @@ os_free(void *ptr)
}
void *
bh_mmap(void *hint, unsigned int size, int prot, int flags)
os_mmap(void *hint, unsigned int size, int prot, int flags)
{
return BH_MALLOC(size);
}
void
bh_munmap(void *addr, uint32 size)
os_munmap(void *addr, uint32 size)
{
return BH_FREE(addr);
}
int
bh_mprotect(void *addr, uint32 size, int prot)
os_mprotect(void *addr, uint32 size, int prot)
{
return 0;
}
void
bh_dcache_flush()
os_dcache_flush()
{
}

View File

@ -0,0 +1,341 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
#define bh_assert(v) do { \
if (!(v)) { \
printf("\nASSERTION FAILED: %s, at %s, line %d\n", \
#v, __FILE__, __LINE__); \
aos_reboot(); \
while (1); \
} \
} while (0)
struct os_thread_data;
typedef struct os_thread_wait_node {
aos_sem_t sem;
os_thread_wait_list next;
} os_thread_wait_node;
typedef struct os_thread_data {
/* Thread body */
aos_task_t thread;
/* Thread start routine */
thread_start_routine_t start_routine;
/* Thread start routine argument */
void *arg;
/* Thread local root */
void *tlr;
/* Wait node of current thread */
os_thread_wait_node wait_node;
/* Lock for waiting list */
aos_mutex_t wait_list_lock;
/* Waiting list of other threads who are joining this thread */
os_thread_wait_list thread_wait_list;
} os_thread_data;
static bool is_thread_sys_inited = false;
/* Thread data of supervisor thread */
static os_thread_data supervisor_thread_data;
/* Thread data key */
static aos_task_key_t thread_data_key;
/* Thread name index */
static int thread_name_index;
int
os_thread_sys_init()
{
if (is_thread_sys_inited)
return BHT_OK;
if (aos_task_key_create(&thread_data_key) != 0)
return BHT_ERROR;
/* Initialize supervisor thread data */
memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
if (aos_sem_new(&supervisor_thread_data.wait_node.sem, 1) != 0) {
aos_task_key_delete(thread_data_key);
return BHT_ERROR;
}
if (aos_task_setspecific(thread_data_key, &supervisor_thread_data)) {
aos_sem_free(&supervisor_thread_data.wait_node.sem);
aos_task_key_delete(thread_data_key);
return BHT_ERROR;
}
is_thread_sys_inited = true;
return BHT_OK;
}
void
os_thread_sys_destroy()
{
if (is_thread_sys_inited) {
aos_task_key_delete(thread_data_key);
aos_sem_free(&supervisor_thread_data.wait_node.sem);
is_thread_sys_inited = false;
}
}
static os_thread_data *
thread_data_current()
{
return aos_task_getspecific(thread_data_key);
}
static void
os_thread_cleanup(void)
{
os_thread_data *thread_data = thread_data_current();
os_thread_wait_list thread_wait_list;
aos_mutex_t *wait_list_lock;
aos_sem_t *wait_node_sem;
bh_assert(thread_data != NULL);
wait_list_lock = &thread_data->wait_list_lock;
thread_wait_list = thread_data->thread_wait_list;
wait_node_sem = &thread_data->wait_node.sem;
/* Free thread data firstly */
BH_FREE(thread_data);
aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER);
if (thread_wait_list) {
/* Signal each joining thread */
os_thread_wait_list head = thread_wait_list;
while (head) {
os_thread_wait_list next = head->next;
aos_sem_signal(&head->sem);
head = next;
}
}
aos_mutex_unlock(wait_list_lock);
/* Free sem and lock */
aos_sem_free(wait_node_sem);
aos_mutex_free(wait_list_lock);
}
static void
os_thread_wrapper(void *arg)
{
os_thread_data *thread_data = arg;
/* Set thread custom data */
if (!aos_task_setspecific(thread_data_key, thread_data))
thread_data->start_routine(thread_data->arg);
os_thread_cleanup();
}
int
os_thread_create(korp_tid *p_tid, thread_start_routine_t start,
void *arg, unsigned int stack_size)
{
return os_thread_create_with_prio(p_tid, start, arg, stack_size,
BH_THREAD_DEFAULT_PRIORITY);
}
int
os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
void *arg, unsigned int stack_size, int prio)
{
os_thread_data *thread_data;
char thread_name[32];
if (!p_tid || !stack_size)
return BHT_ERROR;
/* Create and initialize thread data */
if (!(thread_data = BH_MALLOC(sizeof(os_thread_data))))
return BHT_ERROR;
memset(thread_data, 0, sizeof(os_thread_data));
thread_data->start_routine = start;
thread_data->arg = arg;
if (aos_sem_new(&thread_data->wait_node.sem, 1) != 0)
goto fail1;
if (aos_mutex_new(&thread_data->wait_list_lock))
goto fail2;
snprintf(thread_name, sizeof(thread_name), "%s%d",
"wasm-thread-", ++thread_name_index);
/* Create the thread */
if (aos_task_new_ext((aos_task_t*)thread_data, thread_name,
os_thread_wrapper, thread_data,
stack_size, prio))
goto fail3;
aos_msleep(10);
*p_tid = (korp_tid)thread_data;
return BHT_OK;
fail3:
aos_mutex_free(&thread_data->wait_list_lock);
fail2:
aos_sem_free(&thread_data->wait_node.sem);
fail1:
BH_FREE(thread_data);
return BHT_ERROR;
}
korp_tid
os_self_thread()
{
return (korp_tid)aos_task_getspecific(thread_data_key);
}
int
os_thread_join (korp_tid thread, void **value_ptr)
{
(void)value_ptr;
os_thread_data *thread_data, *curr_thread_data;
/* Get thread data of current thread */
curr_thread_data = thread_data_current();
curr_thread_data->wait_node.next = NULL;
/* Get thread data */
thread_data = (os_thread_data*)thread;
aos_mutex_lock(&thread_data->wait_list_lock, AOS_WAIT_FOREVER);
if (!thread_data->thread_wait_list)
thread_data->thread_wait_list = &curr_thread_data->wait_node;
else {
/* Add to end of waiting list */
os_thread_wait_node *p = thread_data->thread_wait_list;
while (p->next)
p = p->next;
p->next = &curr_thread_data->wait_node;
}
aos_mutex_unlock(&thread_data->wait_list_lock);
/* Wait the sem */
aos_sem_wait(&curr_thread_data->wait_node.sem, AOS_WAIT_FOREVER);
return BHT_OK;
}
int
os_mutex_init(korp_mutex *mutex)
{
return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR;
}
int
os_mutex_destroy(korp_mutex *mutex)
{
aos_mutex_free(mutex);
return BHT_OK;
}
void
os_mutex_lock(korp_mutex *mutex)
{
aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
}
void
os_mutex_unlock(korp_mutex *mutex)
{
aos_mutex_unlock(mutex);
}
int
os_cond_init(korp_cond *cond)
{
if (aos_mutex_new(&cond->wait_list_lock) != 0)
return BHT_ERROR;
cond->thread_wait_list = NULL;
return BHT_OK;
}
int
os_cond_destroy(korp_cond *cond)
{
aos_mutex_free(&cond->wait_list_lock);
return BHT_OK;
}
static int
os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex,
bool timed, int mills)
{
os_thread_wait_node *node = &thread_data_current()->wait_node;
node->next = NULL;
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (!cond->thread_wait_list)
cond->thread_wait_list = node;
else {
/* Add to end of wait list */
os_thread_wait_node *p = cond->thread_wait_list;
while (p->next)
p = p->next;
p->next = node;
}
aos_mutex_unlock(&cond->wait_list_lock);
/* Unlock mutex, wait sem and lock mutex again */
aos_mutex_unlock(mutex);
aos_sem_wait(&node->sem, timed ? mills : AOS_WAIT_FOREVER);
aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
/* Remove wait node from wait list */
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (cond->thread_wait_list == node)
cond->thread_wait_list = node->next;
else {
/* Remove from the wait list */
os_thread_wait_node *p = cond->thread_wait_list;
while (p->next != node)
p = p->next;
p->next = node->next;
}
aos_mutex_unlock(&cond->wait_list_lock);
return BHT_OK;
}
int
os_cond_wait(korp_cond *cond, korp_mutex *mutex)
{
return os_cond_wait_internal(cond, mutex, false, 0);
}
int
os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds)
{
if (useconds == BHT_WAIT_FOREVER)
return os_cond_wait_internal(cond, mutex, false, 0);
else
return os_cond_wait_internal(cond, mutex, true, useconds / 1000);
}
int
os_cond_signal(korp_cond *cond)
{
/* Signal the head wait node of wait list */
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (cond->thread_wait_list)
aos_sem_signal(&cond->thread_wait_list->sem);
aos_mutex_unlock(&cond->wait_list_lock);
return BHT_OK;
}

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "platform_api_vmcore.h"
uint64
os_time_get_boot_microsecond()
{
return (uint64)aos_now_ms() * 1000;
}

View File

@ -1,52 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "bh_assert.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef BH_TEST
#include <setjmp.h>
#endif
#ifdef BH_TEST
/* for exception throwing */
jmp_buf bh_test_jb;
#endif
void bh_assert_internal(int v, const char *file_name, int line_number, const char *expr_string)
{
if(v) return;
if(!file_name) file_name = "NULL FILENAME";
if(!expr_string) expr_string = "NULL EXPR_STRING";
printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string, file_name, line_number);
#ifdef BH_TEST
longjmp(bh_test_jb, 1);
#endif
aos_reboot();
}
void bh_debug_internal(const char *file_name, int line_number, const char *fmt, ...)
{
#ifndef JEFF_TEST_VERIFIER
va_list args;
va_start(args, fmt);
bh_assert(file_name);
printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number);
vprintf(fmt, args);
va_end(args);
printf("\n");
#endif
}

View File

@ -1,861 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "bh_platform.h"
#define __FDLIBM_STDC__
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
typedef union u32double_tag {
int *pint;
double *pdouble;
} U32DOUBLE;
static inline int *
pdouble2pint(double *pdouble)
{
U32DOUBLE u;
u.pdouble = pdouble;
return u.pint;
}
typedef union
{
double value;
struct
{
u_int32_t lsw;
u_int32_t msw;
} parts;
struct
{
u_int64_t w;
} xparts;
} ieee_double_shape_type_little;
typedef union
{
double value;
struct
{
u_int32_t msw;
u_int32_t lsw;
} parts;
struct
{
u_int64_t w;
} xparts;
} ieee_double_shape_type_big;
typedef union {
double d;
struct {
unsigned int manl :32;
unsigned int manh :20;
unsigned int exp :11;
unsigned int sign :1;
} bits;
} IEEEd2bits_L;
typedef union {
double d;
struct {
unsigned int sign :1;
unsigned int exp :11;
unsigned int manh :20;
unsigned int manl :32;
} bits;
} IEEEd2bits_B;
typedef union {
float f;
struct {
unsigned int man :23;
unsigned int exp :8;
unsigned int sign :1;
} bits;
} IEEEf2bits_L;
typedef union {
float f;
struct {
unsigned int sign :1;
unsigned int exp :8;
unsigned int man :23;
} bits;
} IEEEf2bits_B;
static union {
int a;
char b;
} __ue = { .a = 1 };
#define is_little_endian() (__ue.b == 1)
#define __HIL(x) *(1+pdouble2pint(&x))
#define __LOL(x) *(pdouble2pint(&x))
#define __HIB(x) *(int*)&x
#define __LOB(x) *(1+(int*)&x)
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS_L(ix0,ix1,d) \
do { \
ieee_double_shape_type_little ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
/* Set a double from two 32 bit ints. */
#define INSERT_WORDS_L(d,ix0,ix1) \
do { \
ieee_double_shape_type_little iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS_B(ix0,ix1,d) \
do { \
ieee_double_shape_type_big ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
/* Set a double from two 32 bit ints. */
#define INSERT_WORDS_B(d,ix0,ix1) \
do { \
ieee_double_shape_type_big iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
/* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD_L(i,d) \
do { \
ieee_double_shape_type_little gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
/* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD_B(i,d) \
do { \
ieee_double_shape_type_big gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
/* Set the more significant 32 bits of a double from an int. */
#define SET_HIGH_WORD_L(d,v) \
do { \
ieee_double_shape_type_little sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
} while (0)
/* Set the more significant 32 bits of a double from an int. */
#define SET_HIGH_WORD_B(d,v) \
do { \
ieee_double_shape_type_big sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
} while (0)
/*
* A union which permits us to convert between a float and a 32 bit
* int.
*/
typedef union
{
float value;
/* FIXME: Assumes 32 bit int. */
unsigned int word;
} ieee_float_shape_type;
/* Get a 32 bit int from a float. */
#define GET_FLOAT_WORD(i,d) \
do { \
ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
} while (0)
/* Set a float from a 32 bit int. */
#define SET_FLOAT_WORD(d,i) \
do { \
ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
} while (0)
/* Macro wrappers. */
#define EXTRACT_WORDS(ix0,ix1,d) do { \
if (is_little_endian()) \
EXTRACT_WORDS_L(ix0,ix1,d); \
else \
EXTRACT_WORDS_B(ix0,ix1,d); \
} while (0)
#define INSERT_WORDS(d,ix0,ix1) do { \
if (is_little_endian()) \
INSERT_WORDS_L(d,ix0,ix1); \
else \
INSERT_WORDS_B(d,ix0,ix1); \
} while (0)
#define GET_HIGH_WORD(i,d) \
do { \
if (is_little_endian()) \
GET_HIGH_WORD_L(i,d); \
else \
GET_HIGH_WORD_B(i,d); \
} while (0)
#define SET_HIGH_WORD(d,v) \
do { \
if (is_little_endian()) \
SET_HIGH_WORD_L(d,v); \
else \
SET_HIGH_WORD_B(d,v); \
} while (0)
#define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x))
#define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x))
/*
* Attempt to get strict C99 semantics for assignment with non-C99 compilers.
*/
#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
#else
#define STRICT_ASSIGN(type, lval, rval) do { \
volatile type __lval; \
\
if (sizeof(type) >= sizeof(long double)) \
(lval) = (rval); \
else { \
__lval = (rval); \
(lval) = __lval; \
} \
} while (0)
#endif
#ifdef __FDLIBM_STDC__
static const double huge = 1.0e300;
#else
static double huge = 1.0e300;
#endif
#ifdef __STDC__
static const double
#else
static double
#endif
tiny = 1.0e-300;
#ifdef __STDC__
static const double
#else
static double
#endif
one= 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
#ifdef __STDC__
static const double
#else
static double
#endif
TWO52[2]={
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
};
static double freebsd_sqrt(double x);
static double freebsd_floor(double x);
static double freebsd_ceil(double x);
static double freebsd_fabs(double x);
static double freebsd_rint(double x);
static int freebsd_isnan(double x);
static double freebsd_sqrt(double x) /* wrapper sqrt */
{
double z;
int32_t sign = (int)0x80000000;
int32_t ix0,s0,q,m,t,i;
u_int32_t r,t1,s1,ix1,q1;
EXTRACT_WORDS(ix0,ix1,x);
/* take care of Inf and NaN */
if((ix0&0x7ff00000)==0x7ff00000) {
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
sqrt(-inf)=sNaN */
}
/* take care of zero */
if(ix0<=0) {
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
else if(ix0<0)
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = (ix0>>20);
if(m==0) { /* subnormal x */
while(ix0==0) {
m -= 21;
ix0 |= (ix1>>11); ix1 <<= 21;
}
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
m -= i-1;
ix0 |= (ix1>>(32-i));
ix1 <<= i;
}
m -= 1023; /* unbias exponent */
ix0 = (ix0&0x000fffff)|0x00100000;
if(m&1){ /* odd m, double x to make it even */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
}
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
r = 0x00200000; /* r = moving bit from right to left */
while(r!=0) {
t = s0+r;
if(t<=ix0) {
s0 = t+r;
ix0 -= t;
q += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
r = sign;
while(r!=0) {
t1 = s1+r;
t = s0;
if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
s1 = t1+r;
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
ix0 -= t;
if (ix1 < t1) ix0 -= 1;
ix1 -= t1;
q1 += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
/* use floating add to find out rounding direction */
if((ix0|ix1)!=0) {
z = one-tiny; /* trigger inexact flag */
if (z>=one) {
z = one+tiny;
if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
else if (z>one) {
if (q1==(u_int32_t)0xfffffffe) q+=1;
q1+=2;
} else
q1 += (q1&1);
}
}
ix0 = (q>>1)+0x3fe00000;
ix1 = q1>>1;
if ((q&1)==1) ix1 |= sign;
ix0 += (m <<20);
INSERT_WORDS(z,ix0,ix1);
return z;
}
static double freebsd_floor(double x)
{
int32_t i0,i1,j0;
u_int32_t i,j;
EXTRACT_WORDS(i0,i1,x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
if(i0>=0) {i0=i1=0;}
else if(((i0&0x7fffffff)|i1)!=0)
{ i0=0xbff00000;i1=0;}
}
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0<0) i0 += (0x00100000)>>j0;
i0 &= (~i); i1=0;
}
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((u_int32_t)(0xffffffff))>>(j0-20);
if((i1&i)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0<0) {
if(j0==20) i0+=1;
else {
j = i1+(1<<(52-j0));
if(j<i1) i0 +=1 ; /* got a carry */
i1=j;
}
}
i1 &= (~i);
}
}
INSERT_WORDS(x,i0,i1);
return x;
}
static double freebsd_ceil(double x)
{
int32_t i0,i1,j0;
u_int32_t i,j;
EXTRACT_WORDS(i0,i1,x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
if(i0<0) {i0=0x80000000;i1=0;}
else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
}
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0>0) i0 += (0x00100000)>>j0;
i0 &= (~i); i1=0;
}
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((u_int32_t)(0xffffffff))>>(j0-20);
if((i1&i)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0>0) {
if(j0==20) i0+=1;
else {
j = i1 + (1<<(52-j0));
if(j<i1) i0+=1; /* got a carry */
i1 = j;
}
}
i1 &= (~i);
}
}
INSERT_WORDS(x,i0,i1);
return x;
}
static double freebsd_rint(double x)
{
int32_t i0,j0,sx;
u_int32_t i,i1;
double w,t;
EXTRACT_WORDS(i0,i1,x);
sx = (i0>>31)&1;
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) {
if(((i0&0x7fffffff)|i1)==0) return x;
i1 |= (i0&0x0fffff);
i0 &= 0xfffe0000;
i0 |= ((i1|-i1)>>12)&0x80000;
SET_HIGH_WORD(x,i0);
STRICT_ASSIGN(double,w,TWO52[sx]+x);
t = w-TWO52[sx];
GET_HIGH_WORD(i0,t);
SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
return t;
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
i>>=1;
if(((i0&i)|i1)!=0) {
/*
* Some bit is set after the 0.5 bit. To avoid the
* possibility of errors from double rounding in
* w = TWO52[sx]+x, adjust the 0.25 bit to a lower
* guard bit. We do this for all j0<=51. The
* adjustment is trickiest for j0==18 and j0==19
* since then it spans the word boundary.
*/
if(j0==19) i1 = 0x40000000; else
if(j0==18) i1 = 0x80000000; else
i0 = (i0&(~i))|((0x20000)>>j0);
}
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((u_int32_t)(0xffffffff))>>(j0-20);
if((i1&i)==0) return x; /* x is integral */
i>>=1;
if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
}
INSERT_WORDS(x,i0,i1);
STRICT_ASSIGN(double,w,TWO52[sx]+x);
return w-TWO52[sx];
}
static int freebsd_isnan(double d)
{
if (is_little_endian()) {
IEEEd2bits_L u;
u.d = d;
return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
}
else {
IEEEd2bits_B u;
u.d = d;
return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
}
}
static double freebsd_fabs(double x)
{
u_int32_t high;
GET_HIGH_WORD(high,x);
SET_HIGH_WORD(x,high&0x7fffffff);
return x;
}
static const float huge_f = 1.0e30F;
static const float
TWO23[2]={
8.3886080000e+06, /* 0x4b000000 */
-8.3886080000e+06, /* 0xcb000000 */
};
static float
freebsd_truncf(float x)
{
int32_t i0,j0;
u_int32_t i;
GET_FLOAT_WORD(i0,x);
j0 = ((i0>>23)&0xff)-0x7f;
if(j0<23) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge_f+x>0.0F) /* |x|<1, so return 0*sign(x) */
i0 &= 0x80000000;
} else {
i = (0x007fffff)>>j0;
if((i0&i)==0) return x; /* x is integral */
if(huge_f+x>0.0F) /* raise inexact flag */
i0 &= (~i);
}
} else {
if(j0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}
static float
freebsd_rintf(float x)
{
int32_t i0,j0,sx;
float w,t;
GET_FLOAT_WORD(i0,x);
sx = (i0>>31)&1;
j0 = ((i0>>23)&0xff)-0x7f;
if(j0<23) {
if(j0<0) {
if((i0&0x7fffffff)==0) return x;
STRICT_ASSIGN(float,w,TWO23[sx]+x);
t = w-TWO23[sx];
GET_FLOAT_WORD(i0,t);
SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
return t;
}
STRICT_ASSIGN(float,w,TWO23[sx]+x);
return w-TWO23[sx];
}
if(j0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
static float
freebsd_ceilf(float x)
{
int32_t i0,j0;
u_int32_t i;
GET_FLOAT_WORD(i0,x);
j0 = ((i0>>23)&0xff)-0x7f;
if(j0<23) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
if(i0<0) {i0=0x80000000;}
else if(i0!=0) { i0=0x3f800000;}
}
} else {
i = (0x007fffff)>>j0;
if((i0&i)==0) return x; /* x is integral */
if(huge_f+x>(float)0.0) { /* raise inexact flag */
if(i0>0) i0 += (0x00800000)>>j0;
i0 &= (~i);
}
}
} else {
if(j0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}
static float
freebsd_floorf(float x)
{
int32_t i0,j0;
u_int32_t i;
GET_FLOAT_WORD(i0,x);
j0 = ((i0>>23)&0xff)-0x7f;
if(j0<23) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
if(i0>=0) {i0=0;}
else if((i0&0x7fffffff)!=0)
{ i0=0xbf800000;}
}
} else {
i = (0x007fffff)>>j0;
if((i0&i)==0) return x; /* x is integral */
if(huge_f+x>(float)0.0) { /* raise inexact flag */
if(i0<0) i0 += (0x00800000)>>j0;
i0 &= (~i);
}
}
} else {
if(j0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}
static float
freebsd_fminf(float x, float y)
{
if (is_little_endian()) {
IEEEf2bits_L u[2];
u[0].f = x;
u[1].f = y;
/* Check for NaNs to avoid raising spurious exceptions. */
if (u[0].bits.exp == 255 && u[0].bits.man != 0)
return (y);
if (u[1].bits.exp == 255 && u[1].bits.man != 0)
return (x);
/* Handle comparisons of signed zeroes. */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[1].bits.sign].f);
}
else {
IEEEf2bits_B u[2];
u[0].f = x;
u[1].f = y;
/* Check for NaNs to avoid raising spurious exceptions. */
if (u[0].bits.exp == 255 && u[0].bits.man != 0)
return (y);
if (u[1].bits.exp == 255 && u[1].bits.man != 0)
return (x);
/* Handle comparisons of signed zeroes. */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[1].bits.sign].f);
}
return (x < y ? x : y);
}
static float
freebsd_fmaxf(float x, float y)
{
if (is_little_endian()) {
IEEEf2bits_L u[2];
u[0].f = x;
u[1].f = y;
/* Check for NaNs to avoid raising spurious exceptions. */
if (u[0].bits.exp == 255 && u[0].bits.man != 0)
return (y);
if (u[1].bits.exp == 255 && u[1].bits.man != 0)
return (x);
/* Handle comparisons of signed zeroes. */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[0].bits.sign].f);
}
else {
IEEEf2bits_B u[2];
u[0].f = x;
u[1].f = y;
/* Check for NaNs to avoid raising spurious exceptions. */
if (u[0].bits.exp == 255 && u[0].bits.man != 0)
return (y);
if (u[1].bits.exp == 255 && u[1].bits.man != 0)
return (x);
/* Handle comparisons of signed zeroes. */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[0].bits.sign].f);
}
return (x > y ? x : y);
}
double sqrt(double x)
{
return freebsd_sqrt(x);
}
double floor(double x)
{
return freebsd_floor(x);
}
double ceil(double x)
{
return freebsd_ceil(x);
}
double fmin(double x, double y)
{
return x < y ? x : y;
}
double fmax(double x, double y)
{
return x > y ? x : y;
}
double rint(double x)
{
return freebsd_rint(x);
}
double fabs(double x)
{
return freebsd_fabs(x);
}
int isnan(double x)
{
return freebsd_isnan(x);
}
double trunc(double x)
{
return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x);
}
int signbit(double x)
{
return ((__HI(x) & 0x80000000) >> 31);
}
float
truncf(float x)
{
return freebsd_truncf(x);
}
float
rintf(float x)
{
return freebsd_rintf(x);
}
float
ceilf(float x)
{
return freebsd_ceilf(x);
}
float
floorf(float x)
{
return freebsd_floorf(x);
}
float
fminf(float x, float y)
{
return freebsd_fminf(x, y);
}
float
fmaxf(float x, float y)
{
return freebsd_fmaxf(x, y);
}

View File

@ -1,131 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _BH_PLATFORM_H
#define _BH_PLATFORM_H
#include "bh_config.h"
#include "bh_types.h"
#include <aos/kernel.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef BH_PLATFORM_ALIOS_THINGS
#define BH_PLATFORM_ALIOS_THINGS
#endif
#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 30
#define BH_ROUTINE_MODIFIER
/* Invalid thread tid */
#define INVALID_THREAD_ID NULL
#define BH_WAIT_FOREVER AOS_WAIT_FOREVER
typedef uint64_t uint64;
typedef int64_t int64;
typedef aos_task_t korp_thread;
typedef korp_thread *korp_tid;
typedef aos_task_t *aos_tid_t;
typedef aos_mutex_t korp_mutex;
typedef aos_sem_t korp_sem;
struct bh_thread_wait_node;
typedef struct bh_thread_wait_node *bh_thread_wait_list;
typedef struct korp_cond {
aos_mutex_t wait_list_lock;
bh_thread_wait_list thread_wait_list;
} 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
int snprintf(char *buffer, size_t count, const char *format, ...);
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
/**
* Return the offset of the given field in the given type.
*
* @param Type the type containing the filed
* @param field the field in the type
*
* @return the offset of field in Type
*/
#ifndef offsetof
#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
#endif
#define bh_printf printf
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)
/* math functions */
double sqrt(double x);
double floor(double x);
double ceil(double x);
double fmin(double x, double y);
double fmax(double x, double y);
double rint(double x);
double fabs(double x);
double trunc(double x);
float floorf(float x);
float ceilf(float x);
float fminf(float x, float y);
float fmaxf(float x, float y);
float rintf(float x);
float truncf(float x);
int signbit(double x);
int isnan(double x);
int bh_platform_init();
/* MMAP mode */
enum {
MMAP_PROT_NONE = 0,
MMAP_PROT_READ = 1,
MMAP_PROT_WRITE = 2,
MMAP_PROT_EXEC = 4
};
/* MMAP flags */
enum {
MMAP_MAP_NONE = 0,
/* Put the mapping into 0 to 2 G, supported only on x86_64 */
MMAP_MAP_32BIT = 1,
/* Don't interpret addr as a hint: place the mapping at exactly
that address. */
MMAP_MAP_FIXED = 2
};
void *bh_mmap(void *hint, unsigned int size, int prot, int flags);
void bh_munmap(void *addr, uint32 size);
int bh_mprotect(void *addr, uint32 size, int prot);
void bh_dcache_flush();
#endif /* end of _BH_PLATFORM_H */

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include <stdio.h>
void bh_log_emit(const char *fmt, va_list ap)
{
vprintf(fmt, ap);
}
int bh_fprintf(FILE *stream, const char *fmt, ...)
{
(void)stream;
va_list ap;
int ret;
va_start(ap, fmt);
ret = vprintf(fmt, ap);
va_end(ap);
return ret;
}
int bh_fflush(void *stream)
{
(void)stream;
return 0;
}

View File

@ -1,435 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_thread.h"
#include "bh_assert.h"
#include "bh_log.h"
#include <stdio.h>
#include <stdlib.h>
struct bh_thread_data;
typedef struct bh_thread_wait_node {
aos_sem_t sem;
bh_thread_wait_list next;
} bh_thread_wait_node;
typedef struct bh_thread_data {
/* Thread body */
aos_task_t thread;
/* Thread start routine */
thread_start_routine_t start_routine;
/* Thread start routine argument */
void *arg;
/* Thread local root */
void *tlr;
/* Wait node of current thread */
bh_thread_wait_node wait_node;
/* Lock for waiting list */
aos_mutex_t wait_list_lock;
/* Waiting list of other threads who are joining this thread */
bh_thread_wait_list thread_wait_list;
} bh_thread_data;
static bool is_thread_sys_inited = false;
/* Thread data of supervisor thread */
static bh_thread_data supervisor_thread_data;
/* Thread data key */
static aos_task_key_t thread_data_key;
/* Thread name index */
static int thread_name_index;
int
_vm_thread_sys_init()
{
if (is_thread_sys_inited)
return BHT_OK;
if (aos_task_key_create(&thread_data_key) != 0)
return BHT_ERROR;
/* Initialize supervisor thread data */
memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
if (aos_sem_new(&supervisor_thread_data.wait_node.sem, 1) != 0) {
aos_task_key_delete(thread_data_key);
return BHT_ERROR;
}
if (aos_task_setspecific(thread_data_key, &supervisor_thread_data)) {
aos_sem_free(&supervisor_thread_data.wait_node.sem);
aos_task_key_delete(thread_data_key);
return BHT_ERROR;
}
is_thread_sys_inited = true;
return BHT_OK;
}
void
vm_thread_sys_destroy()
{
if (is_thread_sys_inited) {
aos_task_key_delete(thread_data_key);
aos_sem_free(&supervisor_thread_data.wait_node.sem);
is_thread_sys_inited = false;
}
}
static bh_thread_data *
thread_data_current()
{
return aos_task_getspecific(thread_data_key);
}
static void
vm_thread_cleanup(void)
{
bh_thread_data *thread_data = thread_data_current();
bh_thread_wait_list thread_wait_list;
aos_mutex_t *wait_list_lock;
aos_sem_t *wait_node_sem;
bh_assert(thread_data != NULL);
wait_list_lock = &thread_data->wait_list_lock;
thread_wait_list = thread_data->thread_wait_list;
wait_node_sem = &thread_data->wait_node.sem;
/* Free thread data firstly */
BH_FREE(thread_data);
aos_mutex_lock(wait_list_lock, AOS_WAIT_FOREVER);
if (thread_wait_list) {
/* Signal each joining thread */
bh_thread_wait_list head = thread_wait_list;
while (head) {
bh_thread_wait_list next = head->next;
aos_sem_signal(&head->sem);
head = next;
}
}
aos_mutex_unlock(wait_list_lock);
/* Free sem and lock */
aos_sem_free(wait_node_sem);
aos_mutex_free(wait_list_lock);
}
static void
vm_thread_wrapper(void *arg)
{
bh_thread_data *thread_data = arg;
/* Set thread custom data */
if (!aos_task_setspecific(thread_data_key, thread_data))
thread_data->start_routine(thread_data->arg);
vm_thread_cleanup();
}
int
_vm_thread_create(korp_tid *p_tid, thread_start_routine_t start,
void *arg, unsigned int stack_size)
{
return _vm_thread_create_with_prio(p_tid, start, arg, stack_size,
BH_THREAD_DEFAULT_PRIORITY);
}
int
_vm_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
void *arg, unsigned int stack_size, int prio)
{
bh_thread_data *thread_data;
char thread_name[32];
if (!p_tid || !stack_size)
return BHT_ERROR;
/* Create and initialize thread data */
if (!(thread_data = BH_MALLOC(sizeof(bh_thread_data))))
return BHT_ERROR;
memset(thread_data, 0, sizeof(bh_thread_data));
thread_data->start_routine = start;
thread_data->arg = arg;
if (aos_sem_new(&thread_data->wait_node.sem, 1) != 0)
goto fail1;
if (aos_mutex_new(&thread_data->wait_list_lock))
goto fail2;
snprintf(thread_name, sizeof(thread_name), "%s%d",
"wasm-thread-", ++thread_name_index);
/* Create the thread */
if (aos_task_new_ext((aos_task_t*)thread_data, thread_name,
vm_thread_wrapper, thread_data,
stack_size, prio))
goto fail3;
aos_msleep(10);
*p_tid = (korp_tid)thread_data;
return BHT_OK;
fail3:
aos_mutex_free(&thread_data->wait_list_lock);
fail2:
aos_sem_free(&thread_data->wait_node.sem);
fail1:
BH_FREE(thread_data);
return BHT_ERROR;
}
korp_tid
_vm_self_thread()
{
return (korp_tid)aos_task_getspecific(thread_data_key);
}
void
vm_thread_exit(void * code)
{
vm_thread_cleanup();
aos_task_exit((int)(intptr_t)code);
}
int
_vm_thread_cancel (korp_tid thread)
{
/* TODO */
return 0;
}
int
_vm_thread_join (korp_tid thread, void **value_ptr, int mills)
{
(void)value_ptr;
bh_thread_data *thread_data, *curr_thread_data;
/* Get thread data of current thread */
curr_thread_data = thread_data_current();
curr_thread_data->wait_node.next = NULL;
/* Get thread data */
thread_data = (bh_thread_data*)thread;
aos_mutex_lock(&thread_data->wait_list_lock, AOS_WAIT_FOREVER);
if (!thread_data->thread_wait_list)
thread_data->thread_wait_list = &curr_thread_data->wait_node;
else {
/* Add to end of waiting list */
bh_thread_wait_node *p = thread_data->thread_wait_list;
while (p->next)
p = p->next;
p->next = &curr_thread_data->wait_node;
}
aos_mutex_unlock(&thread_data->wait_list_lock);
/* Wait the sem */
aos_sem_wait(&curr_thread_data->wait_node.sem, mills);
return BHT_OK;
}
int
_vm_thread_detach (korp_tid thread)
{
(void)thread;
return BHT_OK;
}
void *
_vm_tls_get(unsigned idx)
{
(void)idx;
bh_thread_data *thread_data;
bh_assert (idx == 0);
thread_data = thread_data_current();
return thread_data ? thread_data->tlr : NULL;
}
int
_vm_tls_put(unsigned idx, void * tls)
{
bh_thread_data *thread_data;
(void)idx;
bh_assert (idx == 0);
thread_data = thread_data_current();
bh_assert (thread_data != NULL);
thread_data->tlr = tls;
return BHT_OK;
}
int
_vm_mutex_init(korp_mutex *mutex)
{
return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR;
}
int
_vm_recursive_mutex_init(korp_mutex *mutex)
{
return aos_mutex_new(mutex) == 0 ? BHT_OK : BHT_ERROR;
}
int
_vm_mutex_destroy(korp_mutex *mutex)
{
aos_mutex_free(mutex);
return BHT_OK;
}
void
vm_mutex_lock(korp_mutex *mutex)
{
aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
}
int
vm_mutex_trylock(korp_mutex *mutex)
{
return aos_mutex_lock(mutex, AOS_NO_WAIT);
}
void vm_mutex_unlock(korp_mutex *mutex)
{
aos_mutex_unlock(mutex);
}
int _vm_sem_init(korp_sem* sem, unsigned int c)
{
return aos_sem_new(sem, c) == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_sem_destroy(korp_sem *sem)
{
aos_sem_free(sem);
return BHT_OK;
}
int _vm_sem_wait(korp_sem *sem)
{
return aos_sem_wait(sem, AOS_WAIT_FOREVER);
}
int _vm_sem_reltimedwait(korp_sem *sem, int mills)
{
return aos_sem_wait(sem, mills);
}
int _vm_sem_post(korp_sem *sem)
{
aos_sem_signal(sem);
return BHT_OK;
}
int
_vm_cond_init(korp_cond *cond)
{
if (aos_mutex_new(&cond->wait_list_lock) != 0)
return BHT_ERROR;
cond->thread_wait_list = NULL;
return BHT_OK;
}
int
_vm_cond_destroy(korp_cond *cond)
{
aos_mutex_free(&cond->wait_list_lock);
return BHT_OK;
}
static int
vm_cond_wait_internal(korp_cond *cond, korp_mutex *mutex,
bool timed, int mills)
{
bh_thread_wait_node *node = &thread_data_current()->wait_node;
node->next = NULL;
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (!cond->thread_wait_list)
cond->thread_wait_list = node;
else {
/* Add to end of wait list */
bh_thread_wait_node *p = cond->thread_wait_list;
while (p->next)
p = p->next;
p->next = node;
}
aos_mutex_unlock(&cond->wait_list_lock);
/* Unlock mutex, wait sem and lock mutex again */
aos_mutex_unlock(mutex);
aos_sem_wait(&node->sem, timed ? mills : AOS_WAIT_FOREVER);
aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
/* Remove wait node from wait list */
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (cond->thread_wait_list == node)
cond->thread_wait_list = node->next;
else {
/* Remove from the wait list */
bh_thread_wait_node *p = cond->thread_wait_list;
while (p->next != node)
p = p->next;
p->next = node->next;
}
aos_mutex_unlock(&cond->wait_list_lock);
return BHT_OK;
}
int
_vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
{
return vm_cond_wait_internal(cond, mutex, false, 0);
}
int
_vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
{
return vm_cond_wait_internal(cond, mutex, true, mills);
}
int
_vm_cond_signal(korp_cond *cond)
{
/* Signal the head wait node of wait list */
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (cond->thread_wait_list)
aos_sem_signal(&cond->thread_wait_list->sem);
aos_mutex_unlock(&cond->wait_list_lock);
return BHT_OK;
}
int
_vm_cond_broadcast (korp_cond *cond)
{
/* Signal each wait node of wait list */
aos_mutex_lock(&cond->wait_list_lock, AOS_WAIT_FOREVER);
if (cond->thread_wait_list) {
bh_thread_wait_node *p = cond->thread_wait_list;
while (p) {
aos_sem_signal(&p->sem);
p = p->next;
}
}
aos_mutex_unlock(&cond->wait_list_lock);
return BHT_OK;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_time.h"
/*
* This function returns milliseconds per tick.
* @return milliseconds per tick.
*/
uint64 _bh_time_get_tick_millisecond()
{
return aos_get_hz() / 1000;
}
/*
* This function returns milliseconds after boot.
* @return milliseconds after boot.
*/
uint64 _bh_time_get_boot_millisecond()
{
return (uint64)aos_now_ms();
}
uint64 _bh_time_get_millisecond_from_1970()
{
return (uint64)aos_now_ms();
}
size_t
_bh_time_strftime (char *str, size_t max, const char *format, int64 time)
{
str = aos_now_time_str(str, max);
return str ? strlen(str) + 1 : 0;
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _PLATFORM_INTERNAL_H
#define _PLATFORM_INTERNAL_H
#include <aos/kernel.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef BH_PLATFORM_ALIOS_THINGS
#define BH_PLATFORM_ALIOS_THINGS
#endif
#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 30
typedef aos_task_t korp_thread;
typedef korp_thread *korp_tid;
typedef aos_task_t *aos_tid_t;
typedef aos_mutex_t korp_mutex;
struct os_thread_wait_node;
typedef struct os_thread_wait_node *os_thread_wait_list;
typedef struct korp_cond {
aos_mutex_t wait_list_lock;
os_thread_wait_list thread_wait_list;
} korp_cond;
#define os_printf printf
#define os_vprintf vprintf
/* math functions which are not provided by os*/
double sqrt(double x);
double floor(double x);
double ceil(double x);
double fmin(double x, double y);
double fmax(double x, double y);
double rint(double x);
double fabs(double x);
double trunc(double x);
float floorf(float x);
float ceilf(float x);
float fminf(float x, float y);
float fmaxf(float x, float y);
float rintf(float x);
float truncf(float x);
int signbit(double x);
int isnan(double x);
#endif /* end of _BH_PLATFORM_H */

View File

@ -1,13 +1,16 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
set (PLATFORM_SHARED_SOURCE ${source_all})
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions(-DBH_PLATFORM_ALIOS_THINGS)
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
include (${CMAKE_CURRENT_LIST_DIR}/../common/math/platform_api_math.cmake)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE})

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "bh_assert.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef BH_TEST
#include <setjmp.h>
#endif
#ifdef BH_TEST
/* for exception throwing */
jmp_buf bh_test_jb;
#endif
void bh_assert_internal(int v, const char *file_name, int line_number,
const char *expr_string)
{
if (v)
return;
if (!file_name)
file_name = "NULL FILENAME";
if (!expr_string)
expr_string = "NULL EXPR_STRING";
printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string,
file_name, line_number);
#ifdef BH_TEST
longjmp(bh_test_jb, 1);
#endif
abort();
}
void bh_debug_internal(const char *file_name, int line_number, const char *fmt,
...)
{
#ifndef JEFF_TEST_VERIFIER
va_list args;
va_start(args, fmt);
bh_assert(file_name);
printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number);
vprintf(fmt, args);
va_end(args);
printf("\n");
#endif
}

View File

@ -1,182 +0,0 @@
/*
* 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"
#include "bh_assert.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
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)
{
char *buffer;
int file;
uint32 file_size, read_size;
struct stat stat_buf;
if (!filename || !ret_size) {
printf("Read file to buffer failed: invalid filename or ret size.\n");
return NULL;
}
if ((file = open(filename, O_RDONLY, 0)) == -1) {
printf("Read file to buffer failed: open file %s failed.\n",
filename);
return NULL;
}
if (fstat(file, &stat_buf) != 0) {
printf("Read file to buffer failed: fstat file %s failed.\n",
filename);
close(file);
return NULL;
}
file_size = (uint32)stat_buf.st_size;
if (!(buffer = BH_MALLOC(file_size))) {
printf("Read file to buffer failed: alloc memory failed.\n");
close(file);
return NULL;
}
read_size = (uint32)read(file, buffer, file_size);
close(file);
if (read_size < file_size) {
printf("Read file to buffer failed: read file content failed.\n");
BH_FREE(buffer);
return NULL;
}
*ret_size = file_size;
return buffer;
}
void *
bh_mmap(void *hint, uint32 size, int prot, int flags)
{
int map_prot = PROT_NONE;
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
uint64 request_size, page_size;
uint8 *addr, *addr_aligned;
uint32 i;
/* align to 2M if no less than 2M, else align to 4K */
page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024;
request_size = (size + page_size - 1) & ~(page_size - 1);
request_size += page_size;
if (request_size >= UINT32_MAX)
return NULL;
if (prot & MMAP_PROT_READ)
map_prot |= PROT_READ;
if (prot & MMAP_PROT_WRITE)
map_prot |= PROT_WRITE;
if (prot & MMAP_PROT_EXEC)
map_prot |= PROT_EXEC;
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
if (flags & MMAP_MAP_32BIT)
map_flags |= MAP_32BIT;
#endif
if (flags & MMAP_MAP_FIXED)
map_flags |= MAP_FIXED;
/* try 5 times */
for (i = 0; i < 5; i ++) {
addr = mmap(hint, size, map_prot, map_flags, -1, 0);
if (addr != MAP_FAILED)
break;
}
if (addr == MAP_FAILED)
return NULL;
addr_aligned = (uint8*)(uintptr_t)
(((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1));
/* Unmap memory allocated before the aligned base address */
if (addr != addr_aligned) {
uint32 prefix_size = (uint32)(addr_aligned - addr);
munmap(addr, prefix_size);
request_size -= prefix_size;
}
/* Unmap memory allocated after the potentially unaligned end */
if (size != request_size) {
uint32 suffix_size = (uint32)(request_size - size);
munmap(addr_aligned + size, suffix_size);
request_size -= size;
}
if (size >= 2 * 1024 * 1024) {
/* Try to use huge page to improve performance */
if (!madvise(addr, size, MADV_HUGEPAGE))
/* make huge page become effective */
memset(addr, 0, size);
}
return addr_aligned;
}
void
bh_munmap(void *addr, uint32 size)
{
if (addr)
munmap(addr, size);
}
int
bh_mprotect(void *addr, uint32 size, int prot)
{
int map_prot = PROT_NONE;
if (!addr)
return 0;
if (prot & MMAP_PROT_READ)
map_prot |= PROT_READ;
if (prot & MMAP_PROT_WRITE)
map_prot |= PROT_WRITE;
if (prot & MMAP_PROT_EXEC)
map_prot |= PROT_EXEC;
return mprotect(addr, size, map_prot);
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _BH_PLATFORM_H
#define _BH_PLATFORM_H
#include "bh_config.h"
#include "bh_types.h"
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include <semaphore.h>
#include <limits.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <android/log.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint64_t uint64;
typedef int64_t int64;
#ifndef BH_PLATFORM_ANDROID
#define BH_PLATFORM_ANDROID
#endif
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0
#define BH_ROUTINE_MODIFIER
#define BHT_TIMEDOUT ETIMEDOUT
#define INVALID_THREAD_ID 0xFFffFFff
typedef pthread_t korp_tid;
typedef pthread_mutex_t korp_mutex;
typedef sem_t korp_sem;
typedef pthread_cond_t korp_cond;
typedef pthread_t korp_thread;
typedef void* (*thread_start_routine_t)(void*);
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);
double sqrt(double x);
#define BH_WAIT_FOREVER 0xFFFFFFFF
#ifndef NULL
# define NULL ((void*) 0)
#endif
/**
* Return the offset of the given field in the given type.
*
* @param Type the type containing the filed
* @param field the field in the type
*
* @return the offset of field in Type
*/
#ifndef offsetof
#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
#endif
#define bh_assert assert
char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size);
int bh_platform_init();
/* MMAP mode */
enum {
MMAP_PROT_NONE = 0,
MMAP_PROT_READ = 1,
MMAP_PROT_WRITE = 2,
MMAP_PROT_EXEC = 4
};
/* MMAP flags */
enum {
MMAP_MAP_NONE = 0,
/* Put the mapping into 0 to 2 G, supported only on x86_64 */
MMAP_MAP_32BIT = 1,
/* Don't interpret addr as a hint: place the mapping at exactly
that address. */
MMAP_MAP_FIXED = 2
};
void *bh_mmap(void *hint, unsigned int size, int prot, int flags);
void bh_munmap(void *addr, uint32 size);
int bh_mprotect(void *addr, uint32 size, int prot);
#define bh_dcache_flush() (void)0
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include <stdio.h>
#include <android/log.h>
void bh_log_emit(const char *fmt, va_list ap)
{
(void)__android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap);
}
int bh_fprintf(FILE *stream, const char *fmt, ...)
{
(void)stream;
va_list ap;
int ret = 0;
va_start(ap, fmt);
ret = __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap);
va_end(ap);
return ret;
}
int bh_fflush(void *stream)
{
(void)stream;
return __android_log_print(ANDROID_LOG_INFO, "wasm_runtime::", "%s", "NOT IMPLEMENT");
}

View File

@ -1,394 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_thread.h"
#include "bh_assert.h"
#include "bh_log.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
static bool is_thread_sys_inited = false;
static korp_mutex thread_list_lock;
static pthread_key_t thread_local_storage_key[BH_MAX_TLS_NUM];
int _vm_thread_sys_init()
{
unsigned i, j;
int ret;
if (is_thread_sys_inited)
return 0;
for (i = 0; i < BH_MAX_TLS_NUM; i++) {
ret = pthread_key_create(&thread_local_storage_key[i], NULL);
if (ret)
goto fail;
}
ret = vm_mutex_init(&thread_list_lock);
if (ret)
goto fail;
is_thread_sys_inited = true;
return 0;
fail: for (j = 0; j < i; j++)
pthread_key_delete(thread_local_storage_key[j]);
return -1;
}
void vm_thread_sys_destroy(void)
{
if (is_thread_sys_inited) {
unsigned i;
for (i = 0; i < BH_MAX_TLS_NUM; i++)
pthread_key_delete(thread_local_storage_key[i]);
vm_mutex_destroy(&thread_list_lock);
is_thread_sys_inited = false;
}
}
typedef struct {
thread_start_routine_t start;
void* stack;
uint32 stack_size;
void* arg;
} thread_wrapper_arg;
static void *vm_thread_wrapper(void *arg)
{
thread_wrapper_arg * targ = arg;
LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ);
targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff);
_vm_tls_put(1, targ);
targ->start(targ->arg);
BH_FREE(targ);
_vm_tls_put(1, NULL);
return NULL;
}
int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
void *arg, unsigned int stack_size, int prio)
{
(void)prio;
pthread_attr_t tattr;
thread_wrapper_arg *targ;
bh_assert(stack_size > 0);
bh_assert(tid);
bh_assert(start);
*tid = INVALID_THREAD_ID;
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
if (pthread_attr_setstacksize(&tattr, stack_size) != 0) {
bh_debug("Invalid thread stack size %u. Min stack size on Linux = %u",
stack_size, PTHREAD_STACK_MIN);
pthread_attr_destroy(&tattr);
return BHT_ERROR;
}
targ = (thread_wrapper_arg*) BH_MALLOC(sizeof(*targ));
if (!targ) {
pthread_attr_destroy(&tattr);
return BHT_ERROR;
}
targ->start = start;
targ->arg = arg;
targ->stack_size = stack_size;
if (pthread_create(tid, &tattr, vm_thread_wrapper, targ) != 0) {
pthread_attr_destroy(&tattr);
BH_FREE(targ);
return BHT_ERROR;
}
pthread_attr_destroy(&tattr);
return BHT_OK;
}
int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
unsigned int stack_size)
{
return _vm_thread_create_with_prio(tid, start, arg, stack_size,
BH_THREAD_DEFAULT_PRIORITY);
}
korp_tid _vm_self_thread()
{
return (korp_tid) pthread_self();
}
void vm_thread_exit(void * code)
{
BH_FREE(_vm_tls_get(1));
_vm_tls_put(1, NULL);
pthread_exit(code);
}
void *_vm_tls_get(unsigned idx)
{
bh_assert(idx < BH_MAX_TLS_NUM);
return pthread_getspecific(thread_local_storage_key[idx]);
}
int _vm_tls_put(unsigned idx, void * tls)
{
bh_assert(idx < BH_MAX_TLS_NUM);
pthread_setspecific(thread_local_storage_key[idx], tls);
return BHT_OK;
}
int _vm_mutex_init(korp_mutex *mutex)
{
return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_recursive_mutex_init(korp_mutex *mutex)
{
int ret;
pthread_mutexattr_t mattr;
bh_assert(mutex);
ret = pthread_mutexattr_init(&mattr);
if (ret)
return BHT_ERROR;
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP);
ret = pthread_mutex_init(mutex, &mattr);
pthread_mutexattr_destroy(&mattr);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_mutex_destroy(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_destroy(mutex);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
/* Returned error (EINVAL, EAGAIN and EDEADLK) from
locking the mutex indicates some logic error present in
the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_lock(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_lock(mutex);
if (0 != ret) {
printf("vm mutex lock failed (ret=%d)!\n", ret);
exit(-1);
}
}
int vm_mutex_trylock(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_trylock(mutex);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
/* Returned error (EINVAL, EAGAIN and EPERM) from
unlocking the mutex indicates some logic error present
in the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_unlock(korp_mutex *mutex)
{
int ret;
bh_assert(mutex);
ret = pthread_mutex_unlock(mutex);
if (0 != ret) {
printf("vm mutex unlock failed (ret=%d)!\n", ret);
exit(-1);
}
}
int _vm_sem_init(korp_sem* sem, unsigned int c)
{
int ret;
bh_assert(sem);
ret = sem_init(sem, 0, c);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_sem_destroy(korp_sem *sem)
{
int ret;
bh_assert(sem);
ret = sem_destroy(sem);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_sem_wait(korp_sem *sem)
{
int ret;
bh_assert(sem);
ret = sem_wait(sem);
return ret == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_sem_reltimedwait(korp_sem *sem, int mills)
{
int ret = BHT_OK;
struct timespec timeout;
const int mills_per_sec = 1000;
const int mills_to_nsec = 1E6;
bh_assert(sem);
if (mills == (int)BHT_WAIT_FOREVER) {
ret = sem_wait(sem);
} else {
timeout.tv_sec = mills / mills_per_sec;
timeout.tv_nsec = (mills % mills_per_sec) * mills_to_nsec;
timeout.tv_sec += time(NULL);
ret = sem_timedwait(sem, &timeout);
}
if (ret != BHT_OK) {
if (errno == BHT_TIMEDOUT) {
ret = BHT_TIMEDOUT;
errno = 0;
} else {
bh_debug("Faliure happens when timed wait is called");
bh_assert(0);
}
}
return ret;
}
int _vm_sem_post(korp_sem *sem)
{
bh_assert(sem);
return sem_post(sem) == 0 ? BHT_OK : BHT_ERROR;
}
int _vm_cond_init(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_init(cond, NULL) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_destroy(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_destroy(cond) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
{
bh_assert(cond);
bh_assert(mutex);
if (pthread_cond_wait(cond, mutex) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec)
{
struct timeval tv;
gettimeofday(&tv, NULL);
ts->tv_sec = (long int)(tv.tv_sec + msec / 1000);
ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec);
if (ts->tv_nsec >= 1000000000L) {
ts->tv_sec++;
ts->tv_nsec -= 1000000000L;
}
}
int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
{
int ret;
struct timespec abstime;
if (mills == (int)BHT_WAIT_FOREVER)
ret = pthread_cond_wait(cond, mutex);
else {
msec_nsec_to_abstime(&abstime, mills, 0);
ret = pthread_cond_timedwait(cond, mutex, &abstime);
}
if (ret != BHT_OK && ret != BHT_TIMEDOUT)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_signal(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_signal(cond) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_broadcast(korp_cond *cond)
{
bh_assert(cond);
if (pthread_cond_broadcast(cond) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_thread_cancel(korp_tid thread)
{
return pthread_kill(thread, SIGABRT);
}
int _vm_thread_join(korp_tid thread, void **value_ptr, int mills)
{
(void)mills;
return pthread_join(thread, value_ptr);
}
int _vm_thread_detach(korp_tid thread)
{
return pthread_detach(thread);
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_time.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
/*
* This function returns milliseconds per tick.
* @return milliseconds per tick.
*/
uint64 _bh_time_get_tick_millisecond()
{
return (uint64)sysconf(_SC_CLK_TCK);
}
/*
* This function returns milliseconds after boot.
* @return milliseconds after boot.
*/
uint64 _bh_time_get_boot_millisecond()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
return 0;
}
return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000);
}
uint32 bh_get_tick_sec()
{
return (uint32)(_bh_time_get_boot_millisecond() / 1000);
}
/*
* This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time.
* @return milliseconds since from 1970.1.1.
*/
uint64 _bh_time_get_millisecond_from_1970()
{
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return tv.tv_sec * 1000 + tv.tv_usec
- (tz.tz_dsttime == 0 ? 0 : 60 * 60 * 1000)
+ tz.tz_minuteswest * 60 * 1000;
}
size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time)
{
time_t time_sec = (time_t)(time / 1000);
struct timeval tv;
struct timezone tz;
struct tm *ltp;
gettimeofday(&tv, &tz);
time_sec -= tz.tz_minuteswest * 60;
ltp = localtime(&time_sec);
if (ltp == NULL) {
return 0;
}
return strftime(s, max, format, ltp);
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
int
bh_platform_init()
{
return 0;
}
void
bh_platform_destroy()
{
}
int os_printf(const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap);
va_end(ap);
return ret;
}
int os_vprintf(const char *fmt, va_list ap)
{
return __android_log_vprint(ANDROID_LOG_INFO, "wasm_runtime::", fmt, ap);
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _PLATFORM_INTERNAL_H
#define _PLATFORM_INTERNAL_H
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include <semaphore.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <netinet/in.h>
#include <android/log.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef BH_PLATFORM_ANDROID
#define BH_PLATFORM_ANDROID
#endif
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0
typedef pthread_t korp_tid;
typedef pthread_mutex_t korp_mutex;
typedef pthread_cond_t korp_cond;
typedef pthread_t korp_thread;
#ifdef __cplusplus
}
#endif
#endif /* end of _PLATFORM_INTERNAL_H */

View File

@ -3,15 +3,16 @@
set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions(-DBH_PLATFORM_ANDROID)
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
set (PLATFORM_SHARED_SOURCE ${source_all})
LIST (APPEND RUNTIME_LIB_HEADER_LIST "${PLATFORM_SHARED_DIR}/bh_platform.h")
set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})

View File

@ -28,7 +28,7 @@
* $FreeBSD$
*/
#include "bh_platform.h"
#include "platform_common.h"
#define __FDLIBM_STDC__
@ -123,8 +123,8 @@ static union {
#define __HIL(x) *(1+pdouble2pint(&x))
#define __LOL(x) *(pdouble2pint(&x))
#define __HIB(x) *(int*)&x
#define __LOB(x) *(1+(int*)&x)
#define __HIB(x) *(pdouble2pint(&x))
#define __LOB(x) *(1+pdouble2pint(&x))
/* Get two 32 bit ints from a double. */

View File

@ -0,0 +1,8 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (PLATFORM_COMMON_MATH_DIR ${CMAKE_CURRENT_LIST_DIR})
file (GLOB_RECURSE source_all ${PLATFORM_COMMON_MATH_DIR}/*.c)
set (PLATFORM_COMMON_MATH_SOURCE ${source_all} )

View File

@ -0,0 +1,8 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (PLATFORM_COMMON_POSIX_DIR ${CMAKE_CURRENT_LIST_DIR})
file (GLOB_RECURSE source_all ${PLATFORM_COMMON_POSIX_DIR}/*.c)
set (PLATFORM_COMMON_POSIX_SOURCE ${source_all} )

Some files were not shown because too many files have changed in this diff Show More