Make memory profiling show native stack usage (#1917)
This commit is contained in:
@ -259,6 +259,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
|
||||
#define I32_SIX LLVM_CONST(i32_six)
|
||||
#define I32_SEVEN LLVM_CONST(i32_seven)
|
||||
#define I32_EIGHT LLVM_CONST(i32_eight)
|
||||
#define I32_NINE LLVM_CONST(i32_nine)
|
||||
#define I32_NEG_ONE LLVM_CONST(i32_neg_one)
|
||||
#define I64_NEG_ONE LLVM_CONST(i64_neg_one)
|
||||
#define I32_MIN LLVM_CONST(i32_min)
|
||||
|
||||
@ -366,6 +366,87 @@ fail:
|
||||
#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
|
||||
|| (WASM_ENABLE_PERF_PROFILING != 0) */
|
||||
|
||||
static bool
|
||||
record_stack_usage(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 callee_cell_num)
|
||||
{
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMBasicBlockRef block_update;
|
||||
LLVMBasicBlockRef block_after_update;
|
||||
LLVMValueRef callee_local_size, new_sp, cmp;
|
||||
LLVMValueRef native_stack_top_min;
|
||||
LLVMTypeRef ptrdiff_type;
|
||||
if (comp_ctx->pointer_size == sizeof(uint64_t)) {
|
||||
ptrdiff_type = I64_TYPE;
|
||||
}
|
||||
else {
|
||||
ptrdiff_type = I32_TYPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* new_sp = last_alloca - callee_local_size;
|
||||
* if (*native_stack_top_min_addr > new_sp) {
|
||||
* *native_stack_top_min_addr = new_sp;
|
||||
* }
|
||||
*/
|
||||
|
||||
if (!(callee_local_size = LLVMConstInt(
|
||||
ptrdiff_type, -(int64_t)callee_cell_num * 4, true))) {
|
||||
aot_set_last_error("llvm build const failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(new_sp = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
func_ctx->last_alloca,
|
||||
&callee_local_size, 1, "new_sp"))) {
|
||||
aot_set_last_error("llvm build gep failed");
|
||||
return false;
|
||||
}
|
||||
if (!(native_stack_top_min = LLVMBuildLoad2(
|
||||
comp_ctx->builder, OPQ_PTR_TYPE,
|
||||
func_ctx->native_stack_top_min_addr, "native_stack_top_min"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
}
|
||||
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, new_sp,
|
||||
native_stack_top_min, "cmp"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(block_update = LLVMAppendBasicBlockInContext(
|
||||
comp_ctx->context, func_ctx->func, "block_update"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(block_after_update = LLVMAppendBasicBlockInContext(
|
||||
comp_ctx->context, func_ctx->func, "block_after_update"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMMoveBasicBlockAfter(block_update, block_curr);
|
||||
LLVMMoveBasicBlockAfter(block_after_update, block_update);
|
||||
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_update,
|
||||
block_after_update)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_update);
|
||||
if (!LLVMBuildStore(comp_ctx->builder, new_sp,
|
||||
func_ctx->native_stack_top_min_addr)) {
|
||||
aot_set_last_error("llvm build store failed");
|
||||
return false;
|
||||
}
|
||||
if (!LLVMBuildBr(comp_ctx->builder, block_after_update)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_after_update);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 callee_cell_num)
|
||||
@ -409,6 +490,19 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 callee_cell_num)
|
||||
{
|
||||
if (comp_ctx->enable_stack_estimation
|
||||
&& !record_stack_usage(comp_ctx, func_ctx, callee_cell_num))
|
||||
return false;
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the app address and its buffer are inside the linear memory,
|
||||
* if no, throw exception
|
||||
@ -852,8 +946,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
callee_cell_num =
|
||||
aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
||||
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
|
||||
if (!check_stack(comp_ctx, func_ctx, callee_cell_num))
|
||||
goto fail;
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 14
|
||||
@ -1467,12 +1560,11 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
/* Translate call non-import block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
|
||||
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx,
|
||||
param_cell_num + ext_cell_num
|
||||
+ 1
|
||||
/* Reserve some local variables */
|
||||
+ 16))
|
||||
if (!check_stack(comp_ctx, func_ctx,
|
||||
param_cell_num + ext_cell_num
|
||||
+ 1
|
||||
/* Reserve some local variables */
|
||||
+ 16))
|
||||
goto fail;
|
||||
|
||||
/* Load function pointer */
|
||||
|
||||
@ -286,6 +286,21 @@ create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
create_native_stack_top_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef offset = I32_NINE;
|
||||
|
||||
if (!(func_ctx->native_stack_top_min_addr = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
|
||||
"native_stack_top_min_addr"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
@ -434,7 +449,8 @@ create_local_variables(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_stack_bound_check) {
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
|| comp_ctx->enable_stack_estimation) {
|
||||
if (aot_func_type->param_count + func->local_count > 0) {
|
||||
func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
|
||||
+ func->local_count - 1];
|
||||
@ -963,6 +979,10 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
&& !create_native_stack_bound(comp_ctx, func_ctx)) {
|
||||
goto fail;
|
||||
}
|
||||
if (comp_ctx->enable_stack_estimation
|
||||
&& !create_native_stack_top_min(comp_ctx, func_ctx)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Get auxiliary stack info */
|
||||
if (wasm_func->has_op_set_global_aux_stack
|
||||
@ -1622,6 +1642,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
||||
if (option->disable_llvm_lto)
|
||||
comp_ctx->disable_llvm_lto = true;
|
||||
|
||||
if (option->enable_stack_estimation)
|
||||
comp_ctx->enable_stack_estimation = true;
|
||||
|
||||
comp_ctx->opt_level = option->opt_level;
|
||||
comp_ctx->size_level = option->size_level;
|
||||
|
||||
|
||||
@ -163,6 +163,7 @@ typedef struct AOTFuncContext {
|
||||
LLVMValueRef aot_inst;
|
||||
LLVMValueRef argv_buf;
|
||||
LLVMValueRef native_stack_bound;
|
||||
LLVMValueRef native_stack_top_min_addr;
|
||||
LLVMValueRef aux_stack_bound;
|
||||
LLVMValueRef aux_stack_bottom;
|
||||
LLVMValueRef native_symbol;
|
||||
@ -313,6 +314,9 @@ typedef struct AOTCompContext {
|
||||
/* Native stack bounday Check */
|
||||
bool enable_stack_bound_check;
|
||||
|
||||
/* Native stack usage estimation */
|
||||
bool enable_stack_estimation;
|
||||
|
||||
/* 128-bit SIMD */
|
||||
bool enable_simd;
|
||||
|
||||
@ -403,6 +407,7 @@ typedef struct AOTCompOption {
|
||||
bool enable_aux_stack_frame;
|
||||
bool disable_llvm_intrinsics;
|
||||
bool disable_llvm_lto;
|
||||
bool enable_stack_estimation;
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
|
||||
Reference in New Issue
Block a user