This commit is contained in:
Alix ANNERAUD 2025-05-08 01:52:59 +08:00 committed by GitHub
commit a77ead5bdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 104 additions and 3 deletions

View File

@ -669,6 +669,10 @@ if (WAMR_BUILD_AOT_VALIDATOR EQUAL 1)
message (" AOT validator enabled") message (" AOT validator enabled")
add_definitions (-DWASM_ENABLE_AOT_VALIDATOR=1) add_definitions (-DWASM_ENABLE_AOT_VALIDATOR=1)
endif () endif ()
if (WAMR_BUILD_INSTRUCTION_METERING EQUAL 1)
message (" Instruction metering enabled")
add_definitions (-DWASM_ENABLE_INSTRUCTION_METERING=1)
endif ()
######################################## ########################################
# Show Phase4 Wasm proposals status. # Show Phase4 Wasm proposals status.

View File

@ -716,4 +716,8 @@ unless used elsewhere */
#define WASM_ENABLE_AOT_VALIDATOR 0 #define WASM_ENABLE_AOT_VALIDATOR 0
#endif #endif
#ifndef WASM_ENABLE_INSTRUCTION_METERING
#define WASM_ENABLE_INSTRUCTION_METERING 0
#endif
#endif /* end of _CONFIG_H_ */ #endif /* end of _CONFIG_H_ */

View File

@ -85,6 +85,10 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
wasm_runtime_dump_exec_env_mem_consumption(exec_env); wasm_runtime_dump_exec_env_mem_consumption(exec_env);
#endif #endif
#if WASM_ENABLE_INSTRUCTION_METERING != 0
exec_env->instructions_to_execute = -1;
#endif
return exec_env; return exec_env;
#ifdef OS_ENABLE_HW_BOUND_CHECK #ifdef OS_ENABLE_HW_BOUND_CHECK

View File

@ -87,6 +87,11 @@ typedef struct WASMExecEnv {
uint8 *bottom; uint8 *bottom;
} wasm_stack; } wasm_stack;
#if WASM_ENABLE_INSTRUCTION_METERING != 0
/* instructions to execute */
int instructions_to_execute;
#endif
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
/** /**
* Cache for * Cache for

View File

@ -2285,6 +2285,15 @@ wasm_runtime_access_exce_check_guard_page()
} }
#endif #endif
#if WASM_ENABLE_INSTRUCTION_METERING != 0
void
wasm_runtime_set_instruction_count_limit(WASMExecEnv *exec_env,
int instructions_to_execute)
{
exec_env->instructions_to_execute = instructions_to_execute;
}
#endif
WASMFuncType * WASMFuncType *
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function, wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
uint32 module_type) uint32 module_type)

View File

@ -791,9 +791,17 @@ WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_native_stack_boundary(WASMExecEnv *exec_env, wasm_runtime_set_native_stack_boundary(WASMExecEnv *exec_env,
uint8 *native_stack_boundary); uint8 *native_stack_boundary);
#if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0 #if WASM_ENABLE_INSTRUCTION_METERING != 0
/* See wasm_export.h for description */ /* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_instruction_count_limit(WASMExecEnv *exec_env,
int instructions_to_execute);
#endif
#if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN
void
wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst, wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst,
bool enable); bool enable);

View File

@ -1821,6 +1821,20 @@ WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_native_stack_boundary(wasm_exec_env_t exec_env, wasm_runtime_set_native_stack_boundary(wasm_exec_env_t exec_env,
uint8_t *native_stack_boundary); uint8_t *native_stack_boundary);
/**
* Set the instruction count limit to the execution environment.
* By default the instruction count limit is -1, which means no limit.
* However, if the instruction count limit is set to a positive value,
* the execution will be terminated when the instruction count reaches
* the limit.
*
* @param exec_env the execution environment
* @param instruction_count the instruction count limit
*/
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_instruction_count_limit(wasm_exec_env_t exec_env,
int instruction_count);
/** /**
* Dump runtime memory consumption, including: * Dump runtime memory consumption, including:
* Exec env memory consumption * Exec env memory consumption

View File

@ -1516,10 +1516,13 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
} \ } \
os_mutex_unlock(&exec_env->wait_lock); \ os_mutex_unlock(&exec_env->wait_lock); \
} \ } \
CHECK_INSTRUCTION_LIMIT(); \
goto *handle_table[*frame_ip++]; \ goto *handle_table[*frame_ip++]; \
} while (0) } while (0)
#else #else
#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() #define HANDLE_OP_END() \
CHECK_INSTRUCTION_LIMIT(); \
FETCH_OPCODE_AND_DISPATCH()
#endif #endif
#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #else /* else of WASM_ENABLE_LABELS_AS_VALUES */
@ -1542,9 +1545,12 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
} \ } \
os_mutex_unlock(&exec_env->wait_lock); \ os_mutex_unlock(&exec_env->wait_lock); \
} \ } \
CHECK_INSTRUCTION_LIMIT(); \
continue; continue;
#else #else
#define HANDLE_OP_END() continue #define HANDLE_OP_END() \
CHECK_INSTRUCTION_LIMIT(); \
continue;
#endif #endif
#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
@ -1562,6 +1568,18 @@ get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
#endif #endif
} }
#if WASM_ENABLE_INSTRUCTION_METERING != 0
#define CHECK_INSTRUCTION_LIMIT() \
if (instructions_left == 0) { \
wasm_set_exception(module, "instruction limit exceeded"); \
goto got_exception; \
} \
else if (instructions_left > 0) \
instructions_left--;
#else
#define CHECK_INSTRUCTION_LIMIT() (void)0
#endif
static void static void
wasm_interp_call_func_bytecode(WASMModuleInstance *module, wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMExecEnv *exec_env, WASMExecEnv *exec_env,
@ -1605,6 +1623,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 local_idx, local_offset, global_idx; uint32 local_idx, local_offset, global_idx;
uint8 local_type, *global_addr; uint8 local_type, *global_addr;
uint32 cache_index, type_index, param_cell_num, cell_num; uint32 cache_index, type_index, param_cell_num, cell_num;
#if WASM_ENABLE_INSTRUCTION_METERING != 0
int instructions_left = -1;
if (exec_env) {
instructions_left = exec_env->instructions_to_execute;
}
#endif
#if WASM_ENABLE_EXCE_HANDLING != 0 #if WASM_ENABLE_EXCE_HANDLING != 0
int32_t exception_tag_index; int32_t exception_tag_index;
#endif #endif

View File

@ -105,6 +105,19 @@ typedef float64 CellType_F64;
goto unaligned_atomic; \ goto unaligned_atomic; \
} while (0) } while (0)
#if WASM_ENABLE_INSTRUCTION_METERING != 0
#define CHECK_INSTRUCTION_LIMIT() \
if (instructions_left == 0) { \
wasm_set_exception(module, "instruction limit exceeded"); \
goto got_exception; \
} \
else if (instructions_left > 0) \
instructions_left--;
#else
#define CHECK_INSTRUCTION_LIMIT() (void)0
#endif
static inline uint32 static inline uint32
rotl32(uint32 n, uint32 c) rotl32(uint32 n, uint32 c)
{ {
@ -1441,6 +1454,7 @@ wasm_interp_dump_op_count()
do { \ do { \
const void *p_label_addr = *(void **)frame_ip; \ const void *p_label_addr = *(void **)frame_ip; \
frame_ip += sizeof(void *); \ frame_ip += sizeof(void *); \
CHECK_INSTRUCTION_LIMIT(); \
goto *p_label_addr; \ goto *p_label_addr; \
} while (0) } while (0)
#else #else
@ -1452,6 +1466,7 @@ wasm_interp_dump_op_count()
/* int32 relative offset was emitted in 64-bit target */ \ /* int32 relative offset was emitted in 64-bit target */ \
p_label_addr = label_base + (int32)LOAD_U32_WITH_2U16S(frame_ip); \ p_label_addr = label_base + (int32)LOAD_U32_WITH_2U16S(frame_ip); \
frame_ip += sizeof(int32); \ frame_ip += sizeof(int32); \
CHECK_INSTRUCTION_LIMIT(); \
goto *p_label_addr; \ goto *p_label_addr; \
} while (0) } while (0)
#else #else
@ -1462,6 +1477,7 @@ wasm_interp_dump_op_count()
/* uint32 label address was emitted in 32-bit target */ \ /* uint32 label address was emitted in 32-bit target */ \
p_label_addr = (void *)(uintptr_t)LOAD_U32_WITH_2U16S(frame_ip); \ p_label_addr = (void *)(uintptr_t)LOAD_U32_WITH_2U16S(frame_ip); \
frame_ip += sizeof(int32); \ frame_ip += sizeof(int32); \
CHECK_INSTRUCTION_LIMIT(); \
goto *p_label_addr; \ goto *p_label_addr; \
} while (0) } while (0)
#endif #endif
@ -1538,6 +1554,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint8 *maddr = NULL; uint8 *maddr = NULL;
uint32 local_idx, local_offset, global_idx; uint32 local_idx, local_offset, global_idx;
uint8 opcode = 0, local_type, *global_addr; uint8 opcode = 0, local_type, *global_addr;
#if WASM_ENABLE_INSTRUCTION_METERING != 0
int instructions_left = -1;
if (exec_env) {
instructions_left = exec_env->instructions_to_execute;
}
#endif
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ #if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
#if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0 #if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0

View File

@ -327,6 +327,10 @@ And the wasm app can calls below APIs to allocate/free memory from/to the shared
- **WAMR_BUILD_SHRUNK_MEMORY**=1/0, default to enable if not set - **WAMR_BUILD_SHRUNK_MEMORY**=1/0, default to enable if not set
> Note: When enabled, this feature will reduce memory usage by decreasing the size of the linear memory, particularly when the `memory.grow` opcode is not used and memory usage is somewhat predictable. > Note: When enabled, this feature will reduce memory usage by decreasing the size of the linear memory, particularly when the `memory.grow` opcode is not used and memory usage is somewhat predictable.
## **Instruction metering**
- **WAMR_BUILD_INSTRUCTION_METERING**=1/0, default to disable if not set
> Note: Enabling this feature allows limiting the number of instructions a wasm module instance can execute. Use the `wasm_runtime_set_instruction_count_limit(...)` API before calling `wasm_runtime_call_*(...)` APIs to enforce this limit.
## **Combination of configurations:** ## **Combination of configurations:**
We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: