about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-23T20·09+0300
committertazjin <tazjin@tvl.su>2022-09-01T21·56+0000
commita060c8f4674a1ace310a3c0b48f22d461bbc5c30 (patch)
treebd6daad0d45f5e9e39cf8eb6722c0decd214cd2a
parent0b37b3f2a9b3cd59f609b41f7c72f1a4d7dce39c (diff)
refactor(tvix/eval): use call frame for top-level lambda r/4578
This wires up most of the machinery for executing different call
frames inside of the VM and stuffs the top-level lambda which the
compiler outputs in there, as well.

Change-Id: Ib6201b3e3be1af96a4d195f6eb147f452860ffc3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6242
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
-rw-r--r--tvix/eval/src/vm.rs43
1 files changed, 29 insertions, 14 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 99e2ba91327c..63e5e4ad7387 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -21,8 +21,6 @@ struct CallFrame {
 
 pub struct VM {
     frames: Vec<CallFrame>,
-    ip: usize,
-    chunk: Chunk,
     stack: Vec<Value>,
 
     // Stack indices of attribute sets from which variables should be
@@ -83,9 +81,22 @@ macro_rules! cmp_op {
 }
 
 impl VM {
+    fn frame(&self) -> &CallFrame {
+        &self.frames[self.frames.len() - 1]
+    }
+
+    fn chunk(&self) -> &Chunk {
+        &self.frame().lambda.chunk
+    }
+
+    fn frame_mut(&mut self) -> &mut CallFrame {
+        let idx = self.frames.len() - 1;
+        &mut self.frames[idx]
+    }
+
     fn inc_ip(&mut self) -> OpCode {
-        let op = self.chunk.code[self.ip];
-        self.ip += 1;
+        let op = self.chunk().code[self.frame().ip];
+        self.frame_mut().ip += 1;
         op
     }
 
@@ -109,7 +120,7 @@ impl VM {
             let op = self.inc_ip();
             match op {
                 OpCode::OpConstant(idx) => {
-                    let c = self.chunk.constant(idx).clone();
+                    let c = self.chunk().constant(idx).clone();
                     self.push(c);
                 }
 
@@ -235,25 +246,25 @@ impl VM {
                 OpCode::OpInterpolate(count) => self.run_interpolate(count)?,
 
                 OpCode::OpJump(offset) => {
-                    self.ip += offset;
+                    self.frame_mut().ip += offset;
                 }
 
                 OpCode::OpJumpIfTrue(offset) => {
                     if self.peek(0).as_bool()? {
-                        self.ip += offset;
+                        self.frame_mut().ip += offset;
                     }
                 }
 
                 OpCode::OpJumpIfFalse(offset) => {
                     if !self.peek(0).as_bool()? {
-                        self.ip += offset;
+                        self.frame_mut().ip += offset;
                     }
                 }
 
                 OpCode::OpJumpIfNotFound(offset) => {
                     if matches!(self.peek(0), Value::NotFound) {
                         self.pop();
-                        self.ip += offset;
+                        self.frame_mut().ip += offset;
                     }
                 }
 
@@ -324,10 +335,10 @@ impl VM {
 
             #[cfg(feature = "disassembler")]
             {
-                tracer.trace(&op, self.ip, &self.stack);
+                tracer.trace(&op, self.frame().ip, &self.stack);
             }
 
-            if self.ip == self.chunk.code.len() {
+            if self.frame().ip == self.chunk().code.len() {
                 return Ok(self.pop());
             }
         }
@@ -373,10 +384,14 @@ impl VM {
 }
 
 pub fn run_lambda(lambda: Lambda) -> EvalResult<Value> {
-    let mut vm = VM {
-        frames: vec![],
-        chunk: Rc::<Chunk>::try_unwrap(lambda.chunk).unwrap(),
+    let frame = CallFrame {
+        lambda,
         ip: 0,
+        stack_offset: 0,
+    };
+
+    let mut vm = VM {
+        frames: vec![frame],
         stack: vec![],
         with_stack: vec![],
     };