Skip to content

per-host function override of native stack requirement #3325

Open
@yamt

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.

/* UVWASI requires larger native stack */

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.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions