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:
Wenyong Huang
2021-07-06 17:05:59 +08:00
committed by GitHub
parent d91047cc37
commit b554a9d05d
16 changed files with 576 additions and 104 deletions

View File

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

View File

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