pub trait ThreadedExecutableInstruction<Regs, Env, Memory, PC>where
Self: ExecutableInstruction<Regs, Env, Memory, PC>,
PC: InstructionFetcher<Self, Memory>,{
// Required method
fn execute_threaded(
instruction_fetcher: PC,
regs: &mut Regs,
env: Env,
memory: &mut Memory,
) -> ThreadedExecutionResult<Self>;
}Expand description
Tail-call-threaded counterpart of ExecutableInstruction.
ExecutableInstruction::execute() describes what a single instruction does and leaves both
fetching and control flow to a driver loop. This trait instead runs the whole program: it is
generated as one handler function per instruction variant, each of which executes its own
instruction and then tail-calls (become) the handler of the next one, so there is no loop and
no return until execution stops. Each handler touches only the operands its own instruction
names, which is what the shared loop cannot do.
Instruction implementations are unaffected: the handlers are assembled from the very same
match arms that ExecutableInstruction::execute() are assembled from, so both paths execute
identical logic and a caller picks between them purely on the trade between code size
(execute) and throughput (execute_threaded).
This trait is deliberately not const, unlike ExecutableInstruction: dispatch goes through
a table of function pointers, and calls through a function pointer are not allowed in
const fn.
Required Methods§
Sourcefn execute_threaded(
instruction_fetcher: PC,
regs: &mut Regs,
env: Env,
memory: &mut Memory,
) -> ThreadedExecutionResult<Self>
fn execute_threaded( instruction_fetcher: PC, regs: &mut Regs, env: Env, memory: &mut Memory, ) -> ThreadedExecutionResult<Self>
Execute instructions starting at the instruction fetcher’s current position and continue until execution stops or fails.
The instruction fetcher is taken by value rather than behind a reference so that it stays in registers across the whole handler chain.
env is taken by value for the same reason and one more: an owned value can be a zero-sized
type, which occupies no argument register at all, whereas a &mut occupies one whether
there is anything behind it or not. Most configurations have a stateless environment, which
thus vanishes, allowing more registers for other arguments. A configuration that does have a
state passes a &mut to it (which is an owned value too and for which there are blanket
implementations for convenience).
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".