per-host function override of native stack requirement #3325
Description
consider that you have a few host functions which require huge native stack to run.
right now, you need to bump WASM_STACK_GUARD_SIZE enough for the largest possible consumer
even when you precisely know which instances/threads would use such functions.
it would be nicer to provide a way to keep WASM_STACK_GUARD_SIZE small while allowing a few host functions to consume more stack so that you can use large native stack only for instances/threads which actually need it.
even within our tree, some native functions require more native stack than others.
eg.
wasm-micro-runtime/core/config.h
Line 451 in d39d2ba
eg. #2332
possible implementation approaches:
a. extend NativeSymbol with necessary info. (eg. size_t native_stack_size)
make aot_call_function/aot_call_indirect etc detect overflows using the value.
pros:
- declarative
cons:
- NativeSymbol is not always handy when calling native function.
maybe we need to copy it to eg. AOTImportFunc. - a straightforward implementation would break the abi.
(it should be ok for 2.0 though) - direct call (what aot_compile_op_call does when signature is available)
needs something different. maybe the aot compiler can emit the check.
however, it would effectively make the stack requirement of the native
function a part of the AOT ABI. i'm not sure if it's acceptable.
a'. wasm_runtime_set_native_api_stacks
use similar detection logic as (a), but a different api to tell stack size.
wasm_runtime_set_native_api_stacks(const char *module_name, NativeSymbolStack *native_stacks, uint32 n_symbol_stack)
cons:
wamrc --native-lib
needs extra care
b. add an extra overflow detection logic to each possible stack-hogging functions
like this:
if (!wasm_runtime_check_native_stack(exec_env, 1000000)) {
return; /* fail */
}
pros:
- easy to implement
- flexible (eg. you can make the estimation depend on function parameters)
- consistent with aot-compiled modules. (check in callee)
cons:
- a lot of boring code changes if you have a lot of functions
(eg. libc-uvwasi) - unless we sprinkle noinline attributes, a compiler can inline functions
and possibly break the check.