AOT/JIT native stack bound check improvement (#2244)

Move the native stack overflow check from the caller to the callee because the
former doesn't work for call_indirect and imported functions.

Make the stack usage estimation more accurate. Instead of making a guess from
the number of wasm locals in the function, use the LLVM's idea of the stack size
of each MachineFunction. The former is inaccurate because a) it doesn't reflect
optimization passes, and b) wasm locals are not the only reason to use stack.

To use the post-compilation stack usage information without requiring 2-pass
compilation or machine-code imm rewriting, introduce a global array to store
stack consumption of each functions:
For JIT, use a custom IRCompiler with an extra pass to fill the array.
For AOT, use `clang -fstack-usage` equivalent because we support external llc.

Re-implement function call stack usage estimation to reflect the real calling
conventions better. (aot_estimate_stack_usage_for_function_call)

Re-implement stack estimation logic (--enable-memory-profiling) based on the new
machinery.

Discussions: #2105.
This commit is contained in:
YAMAMOTO Takashi
2023-06-22 08:27:07 +09:00
committed by GitHub
parent 8797c751a5
commit cd7941cc39
12 changed files with 1348 additions and 252 deletions

View File

@ -153,6 +153,7 @@ typedef struct AOTMemInfo {
typedef struct AOTFuncContext {
AOTFunc *aot_func;
LLVMValueRef func;
LLVMValueRef precheck_func;
LLVMTypeRef func_type;
LLVMModuleRef module;
AOTBlockStack block_stack;
@ -165,7 +166,6 @@ typedef struct AOTFuncContext {
LLVMValueRef aux_stack_bound;
LLVMValueRef aux_stack_bottom;
LLVMValueRef native_symbol;
LLVMValueRef last_alloca;
LLVMValueRef func_ptrs;
AOTMemInfo *mem_info;
@ -182,6 +182,9 @@ typedef struct AOTFuncContext {
#if WASM_ENABLE_DEBUG_AOT != 0
LLVMMetadataRef debug_func;
#endif
unsigned int stack_consumption_for_func_call;
LLVMValueRef locals[1];
} AOTFuncContext;
@ -378,6 +381,11 @@ typedef struct AOTCompContext {
/* LLVM floating-point exception behavior metadata */
LLVMValueRef fp_exception_behavior;
/* a global array to store stack sizes */
LLVMTypeRef stack_sizes_type;
LLVMValueRef stack_sizes;
uint32 *jit_stack_sizes; /* for JIT */
/* LLVM data types */
AOTLLVMTypes basic_types;
LLVMTypeRef exec_env_type;
@ -406,6 +414,9 @@ typedef struct AOTCompContext {
* file for some architecture (such as arc) */
const char *external_asm_compiler;
const char *asm_compiler_flags;
const char *stack_usage_file;
char stack_usage_temp_file[64];
} AOTCompContext;
enum {
@ -509,8 +520,8 @@ void
aot_checked_addr_list_destroy(AOTFuncContext *func_ctx);
bool
aot_build_zero_function_ret(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *func_type);
aot_build_zero_function_ret(const AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, AOTFuncType *func_type);
LLVMValueRef
aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
@ -554,6 +565,13 @@ bool
aot_set_cond_br_weights(AOTCompContext *comp_ctx, LLVMValueRef cond_br,
int32 weights_true, int32 weights_false);
bool
aot_target_precheck_can_use_musttail(const AOTCompContext *comp_ctx);
unsigned int
aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx,
const AOTFuncType *callee_func_type);
#ifdef __cplusplus
} /* end of extern "C" */
#endif