refactor(tvix/eval): introduce Upvalues struct in closures & thunks

This struct will be responsible for tracking upvalues (and is a
convenient place to introduce optimisations for reducing value clones)
instead of a plain value vector.

The main motivation for this is that the upvalues will have to capture
the `with`-stack fully and I want to avoid duplicating the logic for
this between the two capturing types.

Change-Id: I6654f8739fc2e04ca046e6667d4a015f51724e99
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6485
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2022-09-06 22:08:25 +03:00 committed by tazjin
parent 6c9abc1f68
commit d75b207a63
4 changed files with 65 additions and 30 deletions

View file

@ -8,13 +8,13 @@ use crate::{
errors::{Error, ErrorKind, EvalResult},
observer::Observer,
opcode::{CodeIdx, ConstantIdx, Count, JumpOffset, OpCode, StackIdx, UpvalueIdx},
upvalues::UpvalueCarrier,
upvalues::{UpvalueCarrier, Upvalues},
value::{Builtin, Closure, Lambda, NixAttrs, NixList, Thunk, Value},
};
struct CallFrame {
lambda: Rc<Lambda>,
upvalues: Vec<Value>,
upvalues: Upvalues,
ip: usize,
stack_offset: usize,
}
@ -22,7 +22,7 @@ struct CallFrame {
impl CallFrame {
/// Retrieve an upvalue from this frame at the given index.
fn upvalue(&self, idx: UpvalueIdx) -> &Value {
&self.upvalues[idx.0]
&self.upvalues[idx]
}
}
@ -176,7 +176,7 @@ impl<'o> VM<'o> {
pub fn call(
&mut self,
lambda: Rc<Lambda>,
upvalues: Vec<Value>,
upvalues: Upvalues,
arg_count: usize,
) -> EvalResult<Value> {
self.observer
@ -443,7 +443,7 @@ impl<'o> VM<'o> {
match callable {
Value::Closure(closure) => {
let result =
self.call(closure.lambda(), closure.upvalues().to_vec(), 1)?;
self.call(closure.lambda(), closure.upvalues().clone(), 1)?;
self.push(result)
}
@ -468,7 +468,7 @@ impl<'o> VM<'o> {
// closure.
let mut frame = self.frame_mut();
frame.lambda = lambda;
frame.upvalues = closure.upvalues().to_vec();
frame.upvalues = closure.upvalues().clone();
frame.ip = 0; // reset instruction pointer to beginning
}
@ -658,7 +658,7 @@ impl<'o> VM<'o> {
fn populate_upvalues(
&mut self,
count: usize,
mut upvalues: RefMut<'_, Vec<Value>>,
mut upvalues: RefMut<'_, Upvalues>,
) -> EvalResult<()> {
for _ in 0..count {
match self.inc_ip() {
@ -744,7 +744,7 @@ fn unwrap_or_clone_rc<T: Clone>(rc: Rc<T>) -> T {
pub fn run_lambda(observer: &mut dyn Observer, lambda: Rc<Lambda>) -> EvalResult<Value> {
let mut vm = VM::new(observer);
let value = vm.call(lambda, vec![], 0)?;
let value = vm.call(lambda, Upvalues::with_capacity(0), 0)?;
vm.force_for_output(&value)?;
Ok(value)
}