///|
/// Interpreter budgets per invocation. Values count operand and local slots,
/// not bytes; control frames include function and structured-control entries.
/// Host calls and guest-continuation callbacks share a native nesting budget
/// across interpreter contexts in the same Store.
/// These limits do not configure JIT stacks or guest linear-memory stacks.
pub struct InterpreterLimits {
max_frames : Int32
max_values : Int32
max_controls : Int32
max_reentry_depth : Int32
} derive(Debug)
///|
pub fn InterpreterLimits::new(
max_frames~ : Int32 = 16384,
max_values~ : Int32 = 1048576,
max_controls~ : Int32 = 65536,
max_reentry_depth~ : Int32 = 64,
) -> InterpreterLimits raise RuntimeError {
if max_frames <= 0 ||
max_values <= 0 ||
max_controls <= 0 ||
max_reentry_depth <= 0 {
raise TypeMismatch
}
{ max_frames, max_values, max_controls, max_reentry_depth, }
}
///|
pub fn InterpreterLimits::default() -> InterpreterLimits {
{
max_frames: 16384,
max_values: 1048576,
max_controls: 65536,
max_reentry_depth: 64,
}
}
///|
/// Reserve a native callback boundary before entering host or continuation code.
pub fn Store::enter_interpreter_boundary(
self : Store,
) -> Unit raise RuntimeError {
if self.interpreter_reentry_depth >= self.interpreter_limits.max_reentry_depth {
raise CallStackExhausted
}
self.interpreter_reentry_depth += 1
}
///|
pub fn Store::leave_interpreter_boundary(self : Store) -> Unit {
self.interpreter_reentry_depth -= 1
}
///|
pub extend InterpreterLimits with @debug.Debug::{to_repr}