Implement wasm-c-api frame/trap APIs for interpreter mode (#660)
And enable to cache compiled AOT file buffer for wasm-c-api JIT mode Avoid checks that rely on undefined C behavior Fix issues of wasm-c-api sample trap and callback_chain Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
@ -189,7 +189,7 @@ failed: \
|
||||
size_t i = 0; \
|
||||
memset(out, 0, sizeof(Vector)); \
|
||||
\
|
||||
if (!src->size) { \
|
||||
if (!src || !src->size) { \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
@ -232,6 +232,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
||||
WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal)
|
||||
WASM_DEFINE_VEC_OWN(instance, wasm_instance_delete_internal)
|
||||
WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete)
|
||||
WASM_DEFINE_VEC_OWN(frame, wasm_frame_delete)
|
||||
|
||||
static inline bool
|
||||
valid_module_type(uint32 module_type)
|
||||
@ -255,6 +256,21 @@ valid_module_type(uint32 module_type)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* conflicting declaration between aot_export.h and aot.h */
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
bool
|
||||
aot_compile_wasm_file_init();
|
||||
|
||||
void
|
||||
aot_compile_wasm_file_destroy();
|
||||
|
||||
uint8*
|
||||
aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
|
||||
uint32 opt_level, uint32 size_level,
|
||||
char *error_buf, uint32 error_buf_size,
|
||||
uint32 *p_aot_file_size);
|
||||
#endif
|
||||
|
||||
/* Runtime Environment */
|
||||
static void
|
||||
wasm_engine_delete_internal(wasm_engine_t *engine)
|
||||
@ -264,6 +280,10 @@ wasm_engine_delete_internal(wasm_engine_t *engine)
|
||||
wasm_runtime_free(engine);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
aot_compile_wasm_file_destroy();
|
||||
#endif
|
||||
|
||||
wasm_runtime_destroy();
|
||||
}
|
||||
|
||||
@ -311,6 +331,12 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
||||
bh_log_set_verbose_level(3);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
if (!aot_compile_wasm_file_init()) {
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create wasm_engine_t */
|
||||
if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
|
||||
goto failed;
|
||||
@ -1289,10 +1315,106 @@ wasm_val_same(const wasm_val_t *v1, const wasm_val_t *v2)
|
||||
return false;
|
||||
}
|
||||
|
||||
static wasm_frame_t *
|
||||
wasm_frame_new(wasm_instance_t *instance,
|
||||
size_t module_offset,
|
||||
uint32 func_index,
|
||||
size_t func_offset)
|
||||
{
|
||||
wasm_frame_t *frame;
|
||||
|
||||
if (!(frame = malloc_internal(sizeof(wasm_frame_t)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame->instance = instance;
|
||||
frame->module_offset = module_offset;
|
||||
frame->func_index = func_index;
|
||||
frame->func_offset = func_offset;
|
||||
return frame;
|
||||
}
|
||||
|
||||
own wasm_frame_t *
|
||||
wasm_frame_copy(const wasm_frame_t *src)
|
||||
{
|
||||
if (!src) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wasm_frame_new(src->instance, src->module_offset, src->func_index,
|
||||
src->func_offset);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_frame_delete(own wasm_frame_t *frame)
|
||||
{
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
wasm_runtime_free(frame);
|
||||
}
|
||||
|
||||
struct wasm_instance_t *
|
||||
wasm_frame_instance(const wasm_frame_t *frame)
|
||||
{
|
||||
return frame ? frame->instance : NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
wasm_frame_module_offset(const wasm_frame_t *frame)
|
||||
{
|
||||
return frame ? frame->module_offset : 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
wasm_frame_func_index(const wasm_frame_t *frame)
|
||||
{
|
||||
return frame ? frame->func_index : 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
wasm_frame_func_offset(const wasm_frame_t *frame)
|
||||
{
|
||||
return frame ? frame->func_offset : 0;
|
||||
}
|
||||
|
||||
static wasm_trap_t *
|
||||
wasm_trap_new_internal(const char *string)
|
||||
wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
|
||||
const char *default_error_info)
|
||||
{
|
||||
wasm_trap_t *trap;
|
||||
const char *error_info = NULL;
|
||||
wasm_instance_vec_t *instances;
|
||||
wasm_instance_t *frame_instance = NULL;
|
||||
uint32 i;
|
||||
|
||||
if (!singleton_engine || !singleton_engine->stores
|
||||
|| !singleton_engine->stores->num_elems) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
if (!(error_info =
|
||||
wasm_get_exception((WASMModuleInstance *)inst_comm_rt))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
if (!(error_info =
|
||||
aot_get_exception((AOTModuleInstance *)inst_comm_rt))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!error_info && !(error_info = default_error_info)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
|
||||
return NULL;
|
||||
@ -1302,11 +1424,39 @@ wasm_trap_new_internal(const char *string)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
wasm_name_new_from_string(trap->message, string);
|
||||
if (strlen(string) && !trap->message->data) {
|
||||
wasm_name_new_from_string_nt(trap->message, error_info);
|
||||
if (strlen(error_info) && !trap->message->data) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
trap->frames = ((WASMModuleInstance *)inst_comm_rt)->frames;
|
||||
}
|
||||
#endif
|
||||
#endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */
|
||||
|
||||
/* allow a NULL frames list */
|
||||
if (!trap->frames) {
|
||||
return trap;
|
||||
}
|
||||
|
||||
if (!(instances = singleton_engine->stores->data[0]->instances)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < instances->num_elems; i++) {
|
||||
if (instances->data[i]->inst_comm_rt == inst_comm_rt) {
|
||||
frame_instance = instances->data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < trap->frames->num_elems; i++) {
|
||||
(((wasm_frame_t *)trap->frames->data) + i)->instance = frame_instance;
|
||||
}
|
||||
|
||||
return trap;
|
||||
failed:
|
||||
wasm_trap_delete(trap);
|
||||
@ -1342,6 +1492,7 @@ wasm_trap_delete(wasm_trap_t *trap)
|
||||
}
|
||||
|
||||
DEINIT_VEC(trap->message, wasm_byte_vec_delete);
|
||||
/* reuse frames of WASMModuleInstance, do not free it here */
|
||||
|
||||
wasm_runtime_free(trap);
|
||||
}
|
||||
@ -1356,6 +1507,65 @@ wasm_trap_message(const wasm_trap_t *trap, own wasm_message_t *out)
|
||||
wasm_byte_vec_copy(out, trap->message);
|
||||
}
|
||||
|
||||
own wasm_frame_t *
|
||||
wasm_trap_origin(const wasm_trap_t *trap)
|
||||
{
|
||||
wasm_frame_t *latest_frame;
|
||||
|
||||
if (!trap || !trap->frames || !trap->frames->num_elems) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first frame is the latest frame */
|
||||
latest_frame = (wasm_frame_t *)trap->frames->data;
|
||||
return wasm_frame_copy(latest_frame);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_trap_trace(const wasm_trap_t *trap, own wasm_frame_vec_t *out)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
if (!trap || !out) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trap->frames || !trap->frames->num_elems) {
|
||||
wasm_frame_vec_new_empty(out);
|
||||
return;
|
||||
}
|
||||
|
||||
wasm_frame_vec_new_uninitialized(out, trap->frames->num_elems);
|
||||
if (out->size && !out->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < trap->frames->num_elems; i++) {
|
||||
wasm_frame_t *frame;
|
||||
|
||||
frame = ((wasm_frame_t *)trap->frames->data) + i;
|
||||
|
||||
if (!(out->data[i] =
|
||||
wasm_frame_new(frame->instance, frame->module_offset,
|
||||
frame->func_index, frame->func_offset))) {
|
||||
goto failed;
|
||||
}
|
||||
out->num_elems++;
|
||||
}
|
||||
|
||||
return;
|
||||
failed:
|
||||
for (i = 0; i < out->num_elems; i++) {
|
||||
if (out->data[i]) {
|
||||
wasm_runtime_free(out->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (out->data) {
|
||||
wasm_runtime_free(out->data);
|
||||
}
|
||||
}
|
||||
|
||||
struct wasm_module_ex_t {
|
||||
struct WASMModuleCommon *module_comm_rt;
|
||||
wasm_byte_vec_t *binary;
|
||||
@ -1386,6 +1596,10 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
||||
{
|
||||
char error_buf[128] = { 0 };
|
||||
wasm_module_ex_t *module_ex = NULL;
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
uint8 *aot_file_buf = NULL;
|
||||
uint32 aot_file_size;
|
||||
#endif
|
||||
|
||||
bh_assert(singleton_engine);
|
||||
|
||||
@ -1401,12 +1615,35 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
||||
|
||||
INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
|
||||
|
||||
module_ex->module_comm_rt = wasm_runtime_load(
|
||||
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
|
||||
error_buf, (uint32)sizeof(error_buf));
|
||||
if (!(module_ex->module_comm_rt)) {
|
||||
LOG_ERROR(error_buf);
|
||||
goto failed;
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
if (get_package_type((uint8 *)module_ex->binary->data,
|
||||
(uint32)module_ex->binary->size)
|
||||
== Wasm_Module_Bytecode) {
|
||||
if (!(aot_file_buf = aot_compile_wasm_file(
|
||||
(uint8 *)module_ex->binary->data,
|
||||
(uint32)module_ex->binary->size, 3, 3, error_buf,
|
||||
(uint32)sizeof(error_buf), &aot_file_size))) {
|
||||
LOG_ERROR(error_buf);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!(module_ex->module_comm_rt =
|
||||
wasm_runtime_load(aot_file_buf, aot_file_size, error_buf,
|
||||
(uint32)sizeof(error_buf)))) {
|
||||
LOG_ERROR(error_buf);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
module_ex->module_comm_rt = wasm_runtime_load(
|
||||
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
|
||||
error_buf, (uint32)sizeof(error_buf));
|
||||
if (!(module_ex->module_comm_rt)) {
|
||||
LOG_ERROR(error_buf);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* add it to a watching list in store */
|
||||
@ -2255,12 +2492,13 @@ failed:
|
||||
if (argv != argv_buf)
|
||||
wasm_runtime_free(argv);
|
||||
|
||||
/* trap -> exception -> trap */
|
||||
if (wasm_runtime_get_exception(func->inst_comm_rt)) {
|
||||
return wasm_trap_new_internal(
|
||||
wasm_runtime_get_exception(func->inst_comm_rt));
|
||||
return wasm_trap_new_internal(func->inst_comm_rt, NULL);
|
||||
}
|
||||
else {
|
||||
return wasm_trap_new_internal("wasm_func_call failed");
|
||||
return wasm_trap_new_internal(func->inst_comm_rt,
|
||||
"wasm_func_call failed");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3446,8 +3684,8 @@ wasm_instance_new(wasm_store_t *store,
|
||||
own wasm_trap_t **traps)
|
||||
{
|
||||
char error_buf[128] = { 0 };
|
||||
const uint32 stack_size = 16 * 1024;
|
||||
const uint32 heap_size = 16 * 1024;
|
||||
const uint32 stack_size = 32 * 1024;
|
||||
const uint32 heap_size = 32 * 1024;
|
||||
uint32 import_count = 0;
|
||||
wasm_instance_t *instance = NULL;
|
||||
uint32 i = 0;
|
||||
|
||||
@ -86,8 +86,16 @@ struct wasm_ref_t {
|
||||
uint32 obj;
|
||||
};
|
||||
|
||||
struct wasm_frame_t {
|
||||
wasm_instance_t *instance;
|
||||
uint32 module_offset;
|
||||
uint32 func_index;
|
||||
uint32 func_offset;
|
||||
};
|
||||
|
||||
struct wasm_trap_t {
|
||||
wasm_byte_vec_t *message;
|
||||
Vector *frames;
|
||||
};
|
||||
|
||||
struct wasm_func_t {
|
||||
|
||||
Reference in New Issue
Block a user