mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2026-01-12 20:36:42 +00:00
Merge 163b8ada56 into 2a2dd19f32
This commit is contained in:
commit
feb29f9b14
|
|
@ -778,6 +778,7 @@ message (
|
|||
" \"Sign-extension Operators\"\n"
|
||||
" \"WebAssembly C and C++ API\"\n"
|
||||
" \"Branch Hinting\"\n"
|
||||
" \"Compilation Hints\"\n"
|
||||
" Configurable. 0 is OFF. 1 is ON:\n"
|
||||
" \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n"
|
||||
" \"Bulk-memory-opt\" via WAMR_BUILD_BULK_MEMORY_OPT: ${WAMR_BUILD_BULK_MEMORY_OPT}\n"
|
||||
|
|
|
|||
|
|
@ -591,6 +591,10 @@ unless used elsewhere */
|
|||
#define WASM_ENABLE_BRANCH_HINTS 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_COMPILATION_HINTS
|
||||
#define WASM_ENABLE_COMPILATION_HINTS 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_GC
|
||||
#define WASM_ENABLE_GC 0
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ aot_create_funcs(const WASMModule *module, uint32 pointer_size)
|
|||
aot_func->local_types_wp = func->local_types;
|
||||
aot_func->code = func->code;
|
||||
aot_func->code_size = func->code_size;
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
aot_func->code_body_begin = func->code_body_begin;
|
||||
#endif
|
||||
|
||||
|
|
@ -875,7 +875,7 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
|
|||
comp_data->name_section_buf_end = module->name_section_buf_end;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
comp_data->function_hints = module->function_hints;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ typedef struct AOTFunc {
|
|||
/* offset of each local, including function parameters
|
||||
and local variables */
|
||||
uint16 *local_offsets;
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
uint8 *code_body_begin;
|
||||
#endif
|
||||
} AOTFunc;
|
||||
|
|
@ -300,7 +300,7 @@ typedef struct AOTCompData {
|
|||
dwarf_extractor_handle_t extractor;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
struct WASMCompilationHint **function_hints;
|
||||
#endif
|
||||
} AOTCompData;
|
||||
|
|
|
|||
|
|
@ -1233,6 +1233,12 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
|
||||
case WASM_OP_CALL_INDIRECT:
|
||||
{
|
||||
#if WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
const uint32 instr_offset =
|
||||
(frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
|
||||
#else
|
||||
const uint32 instr_offset = 0;
|
||||
#endif
|
||||
uint32 tbl_idx;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_idx);
|
||||
|
|
@ -1246,7 +1252,7 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
}
|
||||
|
||||
if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx,
|
||||
tbl_idx))
|
||||
tbl_idx, instr_offset))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1269,6 +1275,12 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
|
||||
case WASM_OP_RETURN_CALL_INDIRECT:
|
||||
{
|
||||
#if WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
const uint32 instr_offset =
|
||||
(frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
|
||||
#else
|
||||
const uint32 instr_offset = 0;
|
||||
#endif
|
||||
uint32 tbl_idx;
|
||||
|
||||
if (!comp_ctx->enable_tail_call) {
|
||||
|
|
@ -1286,7 +1298,7 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
}
|
||||
|
||||
if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx,
|
||||
tbl_idx))
|
||||
tbl_idx, instr_offset))
|
||||
return false;
|
||||
if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -272,14 +272,14 @@ aot_emit_branch_hint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
{
|
||||
struct WASMCompilationHint *hint = func_ctx->function_hints;
|
||||
while (hint != NULL) {
|
||||
if (hint->type == WASM_COMPILATION_BRANCH_HINT
|
||||
&& ((struct WASMCompilationHintBranchHint *)hint)->offset
|
||||
== offset) {
|
||||
if (hint->type == WASM_COMPILATION_HINT_BRANCH
|
||||
&& hint->offset == offset) {
|
||||
break;
|
||||
}
|
||||
hint = hint->next;
|
||||
}
|
||||
if (hint != NULL) {
|
||||
hint->used = true;
|
||||
// same weight llvm MDBuilder::createLikelyBranchWeights assigns
|
||||
const uint32_t likely_weight = (1U << 20) - 1;
|
||||
const uint32_t unlikely_weight = 1;
|
||||
|
|
@ -1096,11 +1096,11 @@ aot_compile_conditional_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
uint64 size;
|
||||
|
||||
// ip is advanced by one byte for the opcode
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
uint32 instr_offset =
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
const uint32 instr_offset =
|
||||
(*p_frame_ip - 0x1) - (func_ctx->aot_func->code_body_begin);
|
||||
#else
|
||||
uint32 instr_offset = 0;
|
||||
const uint32 instr_offset = 0;
|
||||
#endif
|
||||
uint64 br_depth;
|
||||
if (!read_leb(p_frame_ip, *p_frame_ip + 5, 32, false, &br_depth, NULL, 0))
|
||||
|
|
|
|||
|
|
@ -112,6 +112,64 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
static void
|
||||
aot_emit_call_target_hint(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 offset, LLVMValueRef call_instr)
|
||||
{
|
||||
struct WASMCompilationHint *hint = func_ctx->function_hints;
|
||||
while (hint != NULL) {
|
||||
if (hint->type == WASM_COMPILATION_HINT_CALL_TARGETS
|
||||
&& hint->offset == offset) {
|
||||
break;
|
||||
}
|
||||
hint = hint->next;
|
||||
}
|
||||
if (hint != NULL) {
|
||||
hint->used = true;
|
||||
struct WASMCompilationHintCallTargets *ct_hint =
|
||||
(struct WASMCompilationHintCallTargets *)hint;
|
||||
|
||||
const unsigned md_node_cnt = ct_hint->target_count * 2 + 3;
|
||||
LLVMMetadataRef *md_nodes =
|
||||
wasm_runtime_malloc(md_node_cnt * sizeof(LLVMMetadataRef));
|
||||
if (!md_nodes) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
md_nodes[0] =
|
||||
LLVMMDStringInContext2(comp_ctx->context, "VP", strlen("VP"));
|
||||
md_nodes[1] = LLVMValueAsMetadata(I32_CONST(0));
|
||||
// since wasm encodes a call frequency in full percent, we forward this
|
||||
// to llvm as 100 calls to match the percentages
|
||||
// (could be enhanced with the instruction frequency hints)
|
||||
md_nodes[2] = LLVMValueAsMetadata(I64_CONST(100));
|
||||
|
||||
for (size_t i = 0; i < ct_hint->target_count; ++i) {
|
||||
struct WASMCompilationHintCallTargetsHint *target =
|
||||
&ct_hint->hints[i];
|
||||
char target_func_name[48];
|
||||
snprintf(target_func_name, sizeof(target_func_name), "%s%d",
|
||||
AOT_FUNC_PREFIX,
|
||||
target->func_idx - comp_ctx->comp_data->import_func_count);
|
||||
const uint64_t func_name_hash =
|
||||
aot_func_name_hash(target_func_name);
|
||||
md_nodes[i * 2 + 3] =
|
||||
LLVMValueAsMetadata(I64_CONST(func_name_hash));
|
||||
md_nodes[i * 2 + 3 + 1] =
|
||||
LLVMValueAsMetadata(I64_CONST(target->call_frequency));
|
||||
}
|
||||
LLVMMetadataRef meta_data =
|
||||
LLVMMDNodeInContext2(comp_ctx->context, md_nodes, md_node_cnt);
|
||||
LLVMValueRef meta_data_as_value =
|
||||
LLVMMetadataAsValue(comp_ctx->context, meta_data);
|
||||
LLVMSetMetadata(call_instr, 2, meta_data_as_value);
|
||||
wasm_runtime_free(md_nodes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check whether there was exception thrown, if yes, return directly */
|
||||
static bool
|
||||
check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
|
@ -1929,7 +1987,7 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
LLVMValueRef *param_values, uint32 param_count,
|
||||
uint32 param_cell_num, uint32 result_count,
|
||||
uint8 *wasm_ret_types, LLVMValueRef *value_rets,
|
||||
LLVMValueRef *p_res)
|
||||
LLVMValueRef *p_res, uint32 instr_offset)
|
||||
{
|
||||
LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
|
||||
LLVMTypeRef ret_type, ret_ptr_type, elem_ptr_type;
|
||||
|
|
@ -2074,14 +2132,14 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
cell_num += wasm_value_type_cell_num_internal(wasm_ret_types[i],
|
||||
comp_ctx->pointer_size);
|
||||
}
|
||||
|
||||
*p_res = res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 type_idx, uint32 tbl_idx)
|
||||
uint32 type_idx, uint32 tbl_idx,
|
||||
uint32 instr_offset)
|
||||
{
|
||||
AOTFuncType *func_type;
|
||||
LLVMValueRef tbl_idx_value, elem_idx, func_idx;
|
||||
|
|
@ -2620,7 +2678,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
if (!call_aot_call_indirect_func(
|
||||
comp_ctx, func_ctx, func_type, ftype_idx, tbl_idx_value, elem_idx,
|
||||
param_types + 1, param_values + 1, func_param_count, param_cell_num,
|
||||
func_result_count, wasm_ret_types, value_rets, &res))
|
||||
func_result_count, wasm_ret_types, value_rets, &res, instr_offset))
|
||||
goto fail;
|
||||
|
||||
/* Check whether exception was thrown when executing the function */
|
||||
|
|
@ -2681,6 +2739,10 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
aot_emit_call_target_hint(comp_ctx, func_ctx, instr_offset, value_ret);
|
||||
#endif
|
||||
|
||||
/* Check whether exception was thrown when executing the function */
|
||||
if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
|
||||
&& !check_exception_thrown(comp_ctx, func_ctx))
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
bool
|
||||
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 type_idx, uint32 tbl_idx);
|
||||
uint32 type_idx, uint32 tbl_idx,
|
||||
uint32 instr_offset);
|
||||
|
||||
bool
|
||||
aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
|
|
|||
|
|
@ -1963,7 +1963,7 @@ aot_create_func_context(const AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
func_ctx->function_hints =
|
||||
comp_ctx->comp_data->function_hints
|
||||
? comp_ctx->comp_data->function_hints[func_index]
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ typedef struct AOTFuncContext {
|
|||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef debug_func;
|
||||
#endif
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
struct WASMCompilationHint *function_hints;
|
||||
#endif
|
||||
|
||||
|
|
@ -674,6 +674,9 @@ unsigned int
|
|||
aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncType *callee_func_type);
|
||||
|
||||
uint64_t
|
||||
aot_func_name_hash(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -433,3 +433,9 @@ aot_compress_aot_func_names(AOTCompContext *comp_ctx, uint32 *p_size)
|
|||
*p_size = compressed_str_len;
|
||||
return compressed_str;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
aot_func_name_hash(const char *name)
|
||||
{
|
||||
return MD5Hash(StringRef(name));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -752,7 +752,7 @@ struct WASMFunction {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
uint8 *code_body_begin;
|
||||
#endif
|
||||
};
|
||||
|
|
@ -765,21 +765,31 @@ struct WASMTag {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
enum WASMCompilationHintType {
|
||||
DUMMY = 0,
|
||||
WASM_COMPILATION_BRANCH_HINT = 0,
|
||||
WASM_COMPILATION_HINT_BRANCH = 1,
|
||||
WASM_COMPILATION_HINT_CALL_TARGETS = 2,
|
||||
};
|
||||
struct WASMCompilationHint {
|
||||
struct WASMCompilationHint *next;
|
||||
enum WASMCompilationHintType type;
|
||||
uint32 offset;
|
||||
bool used;
|
||||
};
|
||||
struct WASMCompilationHintBranchHint {
|
||||
struct WASMCompilationHint *next;
|
||||
enum WASMCompilationHintType type;
|
||||
uint32 offset;
|
||||
struct WASMCompilationHint common;
|
||||
bool is_likely;
|
||||
};
|
||||
struct WASMCompilationHintCallTargetsHint {
|
||||
uint32 func_idx;
|
||||
uint32 call_frequency;
|
||||
};
|
||||
struct WASMCompilationHintCallTargets {
|
||||
struct WASMCompilationHint common;
|
||||
size_t target_count;
|
||||
struct WASMCompilationHintCallTargetsHint *hints;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct WASMGlobal {
|
||||
|
|
@ -1071,7 +1081,7 @@ struct WASMModule {
|
|||
const uint8 *name_section_buf_end;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
struct WASMCompilationHint **function_hints;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -3908,7 +3908,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
/* Resolve local set count */
|
||||
p_code_end = p_code + code_size;
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
uint8 *p_body_start = (uint8 *)p_code;
|
||||
#endif
|
||||
local_count = 0;
|
||||
|
|
@ -3991,7 +3991,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
if (local_count > 0)
|
||||
func->local_types = (uint8 *)func + sizeof(WASMFunction);
|
||||
func->code_size = code_size;
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
func->code_body_begin = p_body_start;
|
||||
#endif
|
||||
/*
|
||||
|
|
@ -5566,11 +5566,14 @@ fail:
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
typedef bool (*CompileHintSig)(const uint8 *, const uint8 *, uint32, void *,
|
||||
char *, uint32, WASMModule *);
|
||||
static bool
|
||||
handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end,
|
||||
read_code_metadata_section(const uint8 *buf, const uint8 *buf_end,
|
||||
WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
uint32 error_buf_size, size_t hint_struct_size,
|
||||
const CompileHintSig hint_processor)
|
||||
{
|
||||
if (module->function_hints == NULL) {
|
||||
module->function_hints = loader_malloc(
|
||||
|
|
@ -5601,45 +5604,31 @@ handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
uint32 num_hints;
|
||||
read_leb_uint32(buf, buf_end, num_hints);
|
||||
struct WASMCompilationHintBranchHint *new_hints = loader_malloc(
|
||||
sizeof(struct WASMCompilationHintBranchHint) * num_hints, error_buf,
|
||||
error_buf_size);
|
||||
struct WASMCompilationHint *new_hints = loader_malloc(
|
||||
hint_struct_size * num_hints, error_buf, error_buf_size);
|
||||
for (uint32 j = 0; j < num_hints; ++j) {
|
||||
struct WASMCompilationHintBranchHint *new_hint = &new_hints[j];
|
||||
struct WASMCompilationHint *new_hint =
|
||||
new_hints + j * hint_struct_size;
|
||||
new_hint->next = NULL;
|
||||
new_hint->type = WASM_COMPILATION_BRANCH_HINT;
|
||||
new_hint->used = false;
|
||||
read_leb_uint32(buf, buf_end, new_hint->offset);
|
||||
|
||||
uint32 size;
|
||||
read_leb_uint32(buf, buf_end, size);
|
||||
if (size != 1) {
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"invalid branch hint size, expected 1, got %d.",
|
||||
size);
|
||||
wasm_runtime_free(new_hint);
|
||||
|
||||
if (!hint_processor(buf, buf_end, size, (void *)new_hint, error_buf,
|
||||
error_buf_size, module)) {
|
||||
wasm_runtime_free(new_hints);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8 data = *buf++;
|
||||
if (data == 0x00)
|
||||
new_hint->is_likely = false;
|
||||
else if (data == 0x01)
|
||||
new_hint->is_likely = true;
|
||||
else {
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"invalid branch hint, expected 0 or 1, got %d",
|
||||
data);
|
||||
wasm_runtime_free(new_hint);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
current_hint->next = (struct WASMCompilationHint *)new_hint;
|
||||
current_hint = (struct WASMCompilationHint *)new_hint;
|
||||
buf += size;
|
||||
current_hint->next = new_hint;
|
||||
current_hint = new_hint;
|
||||
}
|
||||
}
|
||||
if (buf != buf_end) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid branch hint section, not filled until end");
|
||||
"invalid compilation hint section, not filled until end");
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -5648,6 +5637,117 @@ fail:
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
bool
|
||||
handle_compilation_hint_branch_hint_processor(const uint8 *buf,
|
||||
const uint8 *buf_end,
|
||||
const uint32 hint_size,
|
||||
void *hint_store, char *error_buf,
|
||||
uint32 error_buf_size,
|
||||
WASMModule *module)
|
||||
{
|
||||
(void)module;
|
||||
struct WASMCompilationHintBranchHint *hint = hint_store;
|
||||
hint->common.type = WASM_COMPILATION_HINT_BRANCH;
|
||||
if (hint_size != 1) {
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"invalid branch hint size, expected 1, got %d.",
|
||||
hint_size);
|
||||
return false;
|
||||
}
|
||||
CHECK_BUF(buf, buf_end, 1);
|
||||
const uint8 data = read_uint8(buf);
|
||||
if (data == 0x00)
|
||||
hint->is_likely = false;
|
||||
else if (data == 0x01)
|
||||
hint->is_likely = true;
|
||||
else {
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"invalid branch hint value, expected 0 or 1, got %d",
|
||||
data);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_branch_hint_section(const uint8 *buf, const uint8 *buf_end,
|
||||
WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
return read_code_metadata_section(
|
||||
buf, buf_end, module, error_buf, error_buf_size,
|
||||
sizeof(struct WASMCompilationHintCallTargets),
|
||||
handle_compilation_hint_branch_hint_processor);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
bool
|
||||
handle_compilation_hint_call_targets_processor(
|
||||
const uint8 *buf, const uint8 *buf_end, const uint32 hint_size,
|
||||
void *hint_store, char *error_buf, uint32 error_buf_size,
|
||||
WASMModule *module)
|
||||
{
|
||||
struct WASMCompilationHintCallTargets *hint = hint_store;
|
||||
hint->common.type = WASM_COMPILATION_HINT_CALL_TARGETS;
|
||||
CHECK_BUF(buf, buf_end, hint_size);
|
||||
hint->target_count = 0;
|
||||
|
||||
const uint8 *orig_buf = buf;
|
||||
const uint8 *hint_end = buf + hint_size;
|
||||
// first pass: count hints
|
||||
while (buf < hint_end) {
|
||||
uint32 func_idx;
|
||||
read_leb_uint32(buf, buf_end, func_idx);
|
||||
check_function_index(module, func_idx, error_buf, error_buf_size);
|
||||
uint32 call_frequency;
|
||||
read_leb_uint32(buf, buf_end, call_frequency);
|
||||
(void)call_frequency;
|
||||
hint->target_count += 1;
|
||||
}
|
||||
if (buf != hint_end) {
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"incomplete call targets hint");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hint->hints = (struct WASMCompilationHintCallTargetsHint *)loader_malloc(
|
||||
sizeof(struct WASMCompilationHintCallTargetsHint) * hint->target_count,
|
||||
error_buf, error_buf_size);
|
||||
if (!hint->hints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// second pass: store hint information
|
||||
buf = orig_buf;
|
||||
for (size_t i = 0; i < hint->target_count; ++i) {
|
||||
struct WASMCompilationHintCallTargetsHint *target_hint =
|
||||
&hint->hints[i];
|
||||
read_leb_uint32(buf, buf_end, target_hint->func_idx);
|
||||
read_leb_uint32(buf, buf_end, target_hint->call_frequency);
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_compilation_hint_call_targets_section(const uint8 *buf,
|
||||
const uint8 *buf_end,
|
||||
WASMModule *module,
|
||||
char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
return read_code_metadata_section(
|
||||
buf, buf_end, module, error_buf, error_buf_size,
|
||||
sizeof(struct WASMCompilationHintCallTargets),
|
||||
handle_compilation_hint_call_targets_processor);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
bool is_load_from_file_buf, char *error_buf,
|
||||
|
|
@ -5706,12 +5806,34 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
return false;
|
||||
}
|
||||
LOG_VERBOSE("Load branch hint section success.");
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (name_len == 25
|
||||
&& memcmp((const char *)p, "metadata.code.branch_hint", 25) == 0) {
|
||||
LOG_VERBOSE("Found branch hint section, but branch hints are disabled "
|
||||
"in this build, skipping.");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
if (name_len == 26
|
||||
&& memcmp((const char *)p, "metadata.code.call_targets", 26) == 0) {
|
||||
p += name_len;
|
||||
if (!handle_compilation_hint_call_targets_section(
|
||||
p, p_end, module, error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
LOG_VERBOSE("Load call target compilation hint section success.");
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (name_len == 26
|
||||
&& memcmp((const char *)p, "metadata.code.call_targets", 26) == 0) {
|
||||
LOG_VERBOSE("Found compilation hints call targets section, but "
|
||||
"compilation hints are disabled in this build, skipping.");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -7500,13 +7622,35 @@ wasm_loader_unload(WASMModule *module)
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0
|
||||
#if WASM_ENABLE_BRANCH_HINTS != 0 || WASM_ENABLE_COMPILATION_HINTS != 0
|
||||
for (i = 0; i < module->function_count; i++) {
|
||||
// be carefull when adding more hints. This only works as long as
|
||||
// the hint structs have been allocated all at once as an array.
|
||||
// With only branch-hints at the moment, this is the case.
|
||||
if (module->function_hints != NULL && module->function_hints[i] != NULL)
|
||||
wasm_runtime_free(module->function_hints[i]);
|
||||
if (module->function_hints != NULL
|
||||
&& module->function_hints[i] != NULL) {
|
||||
// properly free all additionally allocated data:
|
||||
// each code metadata section parsed adds a chain of hints to the
|
||||
// function hints. That chain of WASMCompilationHint specializations
|
||||
// is allocated as an array. We need to find the starts of the
|
||||
// separate arrays to free them all properly.
|
||||
struct WASMCompilationHint *curr = module->function_hints[i];
|
||||
struct WASMCompilationHint *last_chain_start = curr;
|
||||
while (curr != NULL) {
|
||||
if (!curr->used) {
|
||||
LOG_WARNING("Unused hint for function %u, offset: %x\n",
|
||||
i + module->import_count, curr->offset);
|
||||
}
|
||||
if (curr->type != last_chain_start->type) {
|
||||
// we switched chains -> deallocate previous chain and reset
|
||||
wasm_runtime_free(last_chain_start);
|
||||
last_chain_start = curr;
|
||||
}
|
||||
if (curr->type == WASM_COMPILATION_HINT_CALL_TARGETS) {
|
||||
wasm_runtime_free(
|
||||
((struct WASMCompilationHintCallTargets *)curr)->hints);
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
wasm_runtime_free(last_chain_start);
|
||||
}
|
||||
}
|
||||
if (module->function_hints != NULL)
|
||||
wasm_runtime_free(module->function_hints);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Users can turn those features on or off by using compilation options. If a relev
|
|||
## Off-by-default Wasm Proposals
|
||||
|
||||
| Proposal | >= Phase 4 | Compilation Option |
|
||||
| ----------------------------- | ---------- | ---------------------------------|
|
||||
| ----------------------------- | ---------- |----------------------------------|
|
||||
| Extended Constant Expressions | Yes | `WAMR_BUILD_EXTENDED_CONST_EXPR` |
|
||||
| Garbage Collection | Yes | `WAMR_BUILD_GC` |
|
||||
| Legacy Exception Handling[^3] | No | `WAMR_BUILD_EXCE_HANDLING` |
|
||||
|
|
@ -41,6 +41,7 @@ Users can turn those features on or off by using compilation options. If a relev
|
|||
| Tail Call | Yes | `WAMR_BUILD_TAIL_CALL` |
|
||||
| Threads[^5] | Yes | `WAMR_BUILD_SHARED_MEMORY` |
|
||||
| Typed Function References | Yes | `WAMR_BUILD_GC` |
|
||||
| Compilation Hints | No | `WASM_ENABLE_COMPILATION_HINTS` |
|
||||
|
||||
[^3]:
|
||||
interpreter only. [a legacy version](https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md).
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ wasm_proposal_print_status(void)
|
|||
printf(" - Non-trapping float-to-int Conversions\n");
|
||||
printf(" - Sign-extension Operators\n");
|
||||
printf(" - WebAssembly C and C++ API\n");
|
||||
printf(" - Branch Hinting\n");
|
||||
printf(" - Compilation Hints\n");
|
||||
printf(" Compilation Configurable. 0 is OFF. 1 is ON:\n");
|
||||
printf(" - Bulk Memory Operation via WASM_ENABLE_BULK_MEMORY: %u\n",
|
||||
WASM_ENABLE_BULK_MEMORY);
|
||||
|
|
@ -41,7 +43,6 @@ wasm_proposal_print_status(void)
|
|||
printf(" - Typed Function References via WASM_ENABLE_GC: %u\n",
|
||||
WASM_ENABLE_GC);
|
||||
printf(" Unsupported (>= Phase4):\n");
|
||||
printf(" - Branch Hinting\n");
|
||||
printf(" - Custom Annotation Syntax in the Text Format\n");
|
||||
printf(" - Exception Handling\n");
|
||||
printf(" - JS String Builtins\n");
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ add_definitions(-DWASM_ENABLE_TAIL_CALL=1)
|
|||
add_definitions(-DWASM_ENABLE_REF_TYPES=1)
|
||||
add_definitions(-DWASM_ENABLE_CALL_INDIRECT_OVERLONG=1)
|
||||
add_definitions(-DWASM_ENABLE_BRANCH_HINTS=1)
|
||||
add_definitions(-DWASM_ENABLE_COMPILATION_HINTS=1)
|
||||
add_definitions(-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
|
||||
add_definitions(-DWASM_ENABLE_AOT_STACK_FRAME=1)
|
||||
add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user