From bdbc1568bac50371d4b552e179ecfc338f12fd43 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 22 Feb 2023 23:30:28 -0700 Subject: [PATCH] [wasm] Port from c_api to wasm-micro-runtime wasm_runtime API --- src/hb-debug.hh | 4 + src/hb-wasm-shape.cc | 196 ++++++++++++++++++++++++++----------------- 2 files changed, 122 insertions(+), 78 deletions(-) diff --git a/src/hb-debug.hh b/src/hb-debug.hh index 0ac4515fa..6055fce96 100644 --- a/src/hb-debug.hh +++ b/src/hb-debug.hh @@ -389,6 +389,10 @@ struct hb_no_trace_t { #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) #endif +#ifndef HB_DEBUG_WASM +#define HB_DEBUG_WASM (HB_DEBUG+0) +#endif + /* * With tracing. */ diff --git a/src/hb-wasm-shape.cc b/src/hb-wasm-shape.cc index e3cc7aa24..3ae2cbfec 100644 --- a/src/hb-wasm-shape.cc +++ b/src/hb-wasm-shape.cc @@ -24,27 +24,13 @@ * Google Author(s): Behdad Esfahbod */ +#define HB_DEBUG_WASM 1 + #include "hb-shaper-impl.hh" #ifdef HAVE_WASM -#include - -#define own // wasm-micro-runtime wasm-c-api/hello.c example has this; no idea why :)) - -static wasm_store_t * -get_wasm_store () -{ - - static wasm_store_t *store; - if (!store) - { - static wasm_engine_t *engine = wasm_engine_new(); - store = wasm_store_new (engine); - } - - return store; -} +#include /* @@ -54,63 +40,103 @@ get_wasm_store () #define HB_WASM_TAG_WASM HB_TAG('W','a','s','m') struct hb_wasm_face_data_t { - hb_blob_t *blob; - wasm_module_t *mod; - unsigned shape_func_idx; + hb_blob_t *wasm_blob; + wasm_module_t wasm_module; }; +static bool +init_wasm () +{ + static bool initialized; + if (initialized) + return true; + + RuntimeInitArgs init_args; + memset (&init_args, 0, sizeof (RuntimeInitArgs)); + + // Define an array of NativeSymbol for the APIs to be exported. + // Note: the array must be static defined since runtime + // will keep it after registration + // For the function signature specifications, goto the link: + // https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md + + static NativeSymbol native_symbols[] = { +#if 0 + { + "intToStr", // the name of WASM function name + intToStr, // the native function pointer + "(i*~i)i", // the function prototype signature, avoid to use i32 + NULL // attachment is NULL + }, + { + "get_pow", // the name of WASM function name + get_pow, // the native function pointer + "(ii)i", // the function prototype signature, avoid to use i32 + NULL // attachment is NULL + }, + { "calculate_native", calculate_native, "(iii)i", NULL } +#endif + }; + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *) hb_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *) hb_realloc; + init_args.mem_alloc_option.allocator.free_func = (void *) hb_free; + + init_args.mem_alloc_type = Alloc_With_System_Allocator; + + // Native symbols need below registration phase + init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + init_args.native_module_name = "env"; + init_args.native_symbols = native_symbols; + + if (!wasm_runtime_full_init (&init_args)) + { + DEBUG_MSG (WASM, nullptr, "Init runtime environment failed."); + return false; + } + + + initialized = true; + return true; +} + hb_wasm_face_data_t * _hb_wasm_shaper_face_data_create (hb_face_t *face) { - wasm_store_t *wasm_store = nullptr; - hb_blob_t *wasm_blob = nullptr; - own wasm_module_t *wasm_module = nullptr; hb_wasm_face_data_t *data = nullptr; - wasm_exporttype_vec_t exports = {}; - unsigned shape_func_idx = (unsigned) -1; + hb_blob_t *wasm_blob = nullptr; + wasm_module_t wasm_module = nullptr; wasm_blob = hb_face_reference_table (face, HB_WASM_TAG_WASM); unsigned length = hb_blob_get_length (wasm_blob); if (!length) goto fail; - wasm_store = get_wasm_store (); // Do before others to initialize + if (!init_wasm ()) + goto fail; - wasm_byte_vec_t binary; - wasm_byte_vec_new_uninitialized (&binary, length); - memcpy (binary.data, hb_blob_get_data (wasm_blob, nullptr), length); - wasm_module = wasm_module_new (wasm_store, &binary); + wasm_module = wasm_runtime_load ((uint8_t *) hb_blob_get_data_writable (wasm_blob, nullptr), + length, nullptr, 0); if (!wasm_module) - goto fail; - wasm_byte_vec_delete(&binary); - - wasm_module_exports (wasm_module, &exports); - for (unsigned i = 0; i < exports.size; i++) { - auto *name = wasm_exporttype_name(exports.data[i]); - if (0 == memcmp ("shape", name->data, name->size)) - { - shape_func_idx = i; - break; - } - } - if (shape_func_idx == (unsigned) -1) + DEBUG_MSG (WASM, nullptr, "Load wasm module failed."); goto fail; + } + data = (hb_wasm_face_data_t *) hb_calloc (1, sizeof (hb_wasm_face_data_t)); if (unlikely (!data)) goto fail; - data->blob = wasm_blob; - data->mod = wasm_module; - data->shape_func_idx = shape_func_idx; + data->wasm_blob = wasm_blob; + data->wasm_module = wasm_module; return data; fail: - wasm_exporttype_vec_delete (&exports); if (wasm_module) - wasm_module_delete (wasm_module); + wasm_runtime_unload (wasm_module); hb_blob_destroy (wasm_blob); hb_free (data); return nullptr; @@ -119,8 +145,8 @@ fail: void _hb_wasm_shaper_face_data_destroy (hb_wasm_face_data_t *data) { - wasm_module_delete (data->mod); - hb_blob_destroy (data->blob); + wasm_runtime_unload (data->wasm_module); + hb_blob_destroy (data->wasm_blob); hb_free (data); } @@ -156,35 +182,50 @@ _hb_wasm_shape (hb_shape_plan_t *shape_plan, { bool ret = true; const hb_wasm_face_data_t *face_data = font->face->data.wasm; - own wasm_instance_t *instance = nullptr; - const wasm_func_t *run_func = nullptr; - wasm_trap_t *trap = nullptr; - own wasm_extern_vec_t exports = {}; + constexpr uint32_t stack_size = 8092, heap_size = 8092; - wasm_val_t as[1] = { WASM_I32_VAL(6) }; - wasm_val_t rs[1] = { WASM_INIT_VAL }; - wasm_val_vec_t args = WASM_ARRAY_VEC (as); - wasm_val_vec_t results = WASM_ARRAY_VEC (rs); + wasm_module_inst_t module_inst = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_function_inst_t shape_func = nullptr; - instance = wasm_instance_new (get_wasm_store (), face_data->mod, nullptr/*imports*/, nullptr); - if (!instance) - goto fail; - - wasm_instance_exports (instance, &exports); - if (exports.size == 0) - goto fail; - - run_func = wasm_extern_as_func (exports.data[face_data->shape_func_idx]); - if (!run_func) - goto fail; - - trap = wasm_func_call (run_func, &args, &results); - if (trap) + module_inst = wasm_runtime_instantiate(face_data->wasm_module, + stack_size, heap_size, + nullptr, 0); + if (!module_inst) { + DEBUG_MSG (WASM, face_data->wasm_module, "Instantiate wasm module failed."); goto fail; } - ret = bool (rs[0].of.i32); + exec_env = wasm_runtime_create_exec_env (module_inst, stack_size); + if (!exec_env) { + DEBUG_MSG (WASM, module_inst, "Create wasm execution environment failed."); + goto fail; + } + + if (!(shape_func = wasm_runtime_lookup_function (module_inst, "shape", nullptr))) { + DEBUG_MSG (WASM, module_inst, "Shape function not found."); + } + + wasm_val_t results[1]; + wasm_val_t arguments[1]; + + results[0].kind = WASM_I32; + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 41; + + if (!wasm_runtime_call_wasm_a (exec_env, shape_func, 1, results, 1, arguments)) + { + DEBUG_MSG (WASM, module_inst, "Calling shape function failed: %s", + wasm_runtime_get_exception(module_inst)); + goto fail; + } + + printf ("%i\n", results[0].of.i32); + + + if (!face_data) + goto fail; if (0) { @@ -192,11 +233,10 @@ fail: ret = false; } - wasm_extern_vec_delete (&exports); - if (instance) - wasm_instance_delete(instance); - if (trap) - wasm_trap_delete (trap); + if (exec_env) + wasm_runtime_destroy_exec_env (exec_env); + if (module_inst) + wasm_runtime_deinstantiate (module_inst); return ret; }