refactor(tvix/eval): use CodeIdx wrapper for instruction pointer

As suggested by sterni in cl/6453.

Change-Id: I3cf80d97c11fd7d085ab510f6be4b5f937c791ec
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6562
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2022-09-13 15:58:55 +03:00 committed by tazjin
parent a9914a79a0
commit d5ee893fb1
3 changed files with 34 additions and 9 deletions

View file

@ -53,7 +53,7 @@ pub trait Observer {
/// Called when the runtime *begins* executing an instruction. The /// Called when the runtime *begins* executing an instruction. The
/// provided stack is the state at the beginning of the operation. /// provided stack is the state at the beginning of the operation.
fn observe_execute_op(&mut self, _ip: usize, _: &OpCode, _: &[Value]) {} fn observe_execute_op(&mut self, _ip: CodeIdx, _: &OpCode, _: &[Value]) {}
} }
#[derive(Default)] #[derive(Default)]
@ -162,8 +162,8 @@ impl<W: Write> Observer for TracingObserver<W> {
); );
} }
fn observe_execute_op(&mut self, ip: usize, op: &OpCode, stack: &[Value]) { fn observe_execute_op(&mut self, ip: CodeIdx, op: &OpCode, stack: &[Value]) {
let _ = write!(&mut self.writer, "{:04} {:?}\t[ ", ip, op); let _ = write!(&mut self.writer, "{:04} {:?}\t[ ", ip.0, op);
for val in stack { for val in stack {
let _ = write!(&mut self.writer, "{} ", val); let _ = write!(&mut self.writer, "{} ", val);

View file

@ -1,6 +1,8 @@
//! This module implements the instruction set running on the abstract //! This module implements the instruction set running on the abstract
//! machine implemented by tvix. //! machine implemented by tvix.
use std::ops::{AddAssign, Sub};
/// Index of a constant in the current code chunk. /// Index of a constant in the current code chunk.
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -11,6 +13,20 @@ pub struct ConstantIdx(pub usize);
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct CodeIdx(pub usize); pub struct CodeIdx(pub usize);
impl AddAssign<usize> for CodeIdx {
fn add_assign(&mut self, rhs: usize) {
*self = CodeIdx(self.0 + rhs)
}
}
impl Sub<usize> for CodeIdx {
type Output = Self;
fn sub(self, rhs: usize) -> Self::Output {
CodeIdx(self.0 - rhs)
}
}
/// Index of a value in the runtime stack. /// Index of a value in the runtime stack.
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]

View file

@ -13,9 +13,18 @@ use crate::{
}; };
struct CallFrame { struct CallFrame {
/// The lambda currently being executed.
lambda: Rc<Lambda>, lambda: Rc<Lambda>,
/// Optional captured upvalues of this frame (if a thunk or
/// closure if being evaluated).
upvalues: Upvalues, upvalues: Upvalues,
ip: usize,
/// Instruction pointer to the instruction currently being
/// executed.
ip: CodeIdx,
/// Stack offset, i.e. the frames "view" into the VM's full stack.
stack_offset: usize, stack_offset: usize,
} }
@ -134,7 +143,7 @@ impl<'o> VM<'o> {
} }
fn inc_ip(&mut self) -> OpCode { fn inc_ip(&mut self) -> OpCode {
let op = self.chunk().code[self.frame().ip]; let op = self.chunk()[self.frame().ip];
self.frame_mut().ip += 1; self.frame_mut().ip += 1;
op op
} }
@ -154,7 +163,7 @@ impl<'o> VM<'o> {
/// Returns the source span of the instruction currently being /// Returns the source span of the instruction currently being
/// executed. /// executed.
fn current_span(&self) -> codemap::Span { fn current_span(&self) -> codemap::Span {
self.chunk().get_span(CodeIdx(self.frame().ip - 1)) self.chunk().get_span(self.frame().ip - 1)
} }
/// Construct an error from the given ErrorKind and the source /// Construct an error from the given ErrorKind and the source
@ -181,7 +190,7 @@ impl<'o> VM<'o> {
let frame = CallFrame { let frame = CallFrame {
lambda, lambda,
upvalues, upvalues,
ip: 0, ip: CodeIdx(0),
stack_offset: self.stack.len() - arg_count, stack_offset: self.stack.len() - arg_count,
}; };
@ -200,7 +209,7 @@ impl<'o> VM<'o> {
// Break the loop if this call frame has already run to // Break the loop if this call frame has already run to
// completion, pop it off, and return the value to the // completion, pop it off, and return the value to the
// caller. // caller.
if self.frame().ip == self.chunk().code.len() { if self.frame().ip.0 == self.chunk().code.len() {
self.frames.pop(); self.frames.pop();
return Ok(self.pop()); return Ok(self.pop());
} }
@ -465,7 +474,7 @@ impl<'o> VM<'o> {
let mut frame = self.frame_mut(); let mut frame = self.frame_mut();
frame.lambda = lambda; frame.lambda = lambda;
frame.upvalues = closure.upvalues().clone(); frame.upvalues = closure.upvalues().clone();
frame.ip = 0; // reset instruction pointer to beginning frame.ip = CodeIdx(0); // reset instruction pointer to beginning
} }
_ => return Err(self.error(ErrorKind::NotCallable)), _ => return Err(self.error(ErrorKind::NotCallable)),