diff --git a/src/isa.rs b/src/isa.rs index 39aaa9e..01cadb7 100644 --- a/src/isa.rs +++ b/src/isa.rs @@ -299,5 +299,46 @@ pub enum Instruction { #[derive(Debug, Clone)] pub struct Instructions { - pub code: Vec, + vec: Vec, +} + +impl Instructions { + pub fn new(instructions: I) -> Self + where I: IntoIterator + { + Instructions { + vec: instructions.into_iter().collect() + } + } + + pub fn iterate_from(&self, position: usize) -> InstructionIter { + InstructionIter{ + instructions: &self.vec, + position, + } + } +} + +pub struct InstructionIter<'a> { + instructions: &'a [Instruction], + position: usize, +} + +impl<'a> InstructionIter<'a> { + #[inline] + pub fn position(&self) -> usize { + self.position + } +} + +impl<'a> Iterator for InstructionIter<'a> { + type Item = &'a Instruction; + + #[inline] + fn next(&mut self) -> Option<::Item> { + self.instructions.get(self.position).map(|instruction| { + self.position += 1; + instruction + }) + } } diff --git a/src/runner.rs b/src/runner.rs index 5a9ec84..c0a3497 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -175,7 +175,7 @@ impl Interpreter { let function_return = self.do_run_function( &mut function_context, - &function_body.code.code, + &function_body.code, ).map_err(Trap::new)?; match function_return { @@ -229,18 +229,24 @@ impl Interpreter { } } - fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &[isa::Instruction]) -> Result { + fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &isa::Instructions) + -> Result + { + let mut iter = instructions.iterate_from(function_context.position); loop { - let instruction = &instructions[function_context.position]; + let instruction = iter.next().expect("instruction"); match self.run_instruction(function_context, instruction)? { - InstructionOutcome::RunNextInstruction => function_context.position += 1, + InstructionOutcome::RunNextInstruction => { + function_context.position = iter.position(); + }, InstructionOutcome::Branch(target) => { function_context.position = target.dst_pc as usize; + iter = instructions.iterate_from(function_context.position); self.value_stack.drop_keep(target.drop_keep); }, InstructionOutcome::ExecuteCall(func_ref) => { - function_context.position += 1; + function_context.position = iter.position(); return Ok(RunResult::NestedCall(func_ref)); }, InstructionOutcome::Return(drop_keep) => { diff --git a/src/validation/func.rs b/src/validation/func.rs index 7107e05..0481e21 100644 --- a/src/validation/func.rs +++ b/src/validation/func.rs @@ -1406,9 +1406,7 @@ impl<'a> FunctionValidationContext<'a> { } fn into_code(self) -> isa::Instructions { - isa::Instructions { - code: self.sink.into_inner(), - } + isa::Instructions::new(self.sink.into_inner()) } } diff --git a/src/validation/tests.rs b/src/validation/tests.rs index 7feb726..9f90437 100644 --- a/src/validation/tests.rs +++ b/src/validation/tests.rs @@ -313,7 +313,7 @@ fn validate(wat: &str) -> ValidatedModule { fn compile(wat: &str) -> Vec { let validated_module = validate(wat); let code = &validated_module.code_map[0]; - code.code.clone() + code.iterate_from(0).map(|i| i.clone()).collect() } #[test]