refactor(tvix/eval): Drop LightSpan entirely

This was made unnecessary in c92d06271 (feat(tvix/eval): drop
LightSpan::Delayed, 2023-12-08) because it didn't improve benchmarks as
much as expected and has been vestigial since; this continues the
cleanup by just removing it altogether

Change-Id: I21ec7ae9b52a5cccd2092696a5a87f658194d672
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11949
Autosubmit: aspen <root@gws.fyi>
Tested-by: BuildkiteCI
Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
Aspen Smith 2024-07-04 13:42:50 -04:00 committed by clbot
parent 8e31088a01
commit 6037888e18
8 changed files with 109 additions and 175 deletions

View file

@ -7,6 +7,7 @@ use std::path::PathBuf;
use std::rc::Rc;
use bstr::{BString, ByteVec};
use codemap::Span;
use lexical_core::format::CXX_LITERAL;
use serde::Deserialize;
@ -23,7 +24,6 @@ mod thunk;
use crate::errors::{CatchableErrorKind, ErrorKind};
use crate::opcode::StackIdx;
use crate::spans::LightSpan;
use crate::vm::generators::{self, GenCo};
use crate::AddContext;
pub use attrs::NixAttrs;
@ -224,7 +224,7 @@ impl Value {
/// their contents, too.
///
/// This is a generator function.
pub(super) async fn deep_force(self, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> {
pub(super) async fn deep_force(self, co: GenCo, span: Span) -> Result<Value, ErrorKind> {
if let Some(v) = Self::deep_force_(self.clone(), co, span).await? {
Ok(v)
} else {
@ -233,11 +233,7 @@ impl Value {
}
/// Returns Some(v) or None to indicate the returned value is myself
async fn deep_force_(
myself: Value,
co: GenCo,
span: LightSpan,
) -> Result<Option<Value>, ErrorKind> {
async fn deep_force_(myself: Value, co: GenCo, span: Span) -> Result<Option<Value>, ErrorKind> {
// This is a stack of values which still remain to be forced.
let mut vals = vec![myself];
@ -256,7 +252,7 @@ impl Value {
if !thunk_set.insert(t) {
continue;
}
Thunk::force_(t.clone(), &co, span.clone()).await?
Thunk::force_(t.clone(), &co, span).await?
} else {
v
};
@ -307,7 +303,7 @@ impl Value {
self,
co: GenCo,
kind: CoercionKind,
span: LightSpan,
span: Span,
) -> Result<Value, ErrorKind> {
self.coerce_to_string_(&co, kind, span).await
}
@ -318,7 +314,7 @@ impl Value {
self,
co: &GenCo,
kind: CoercionKind,
span: LightSpan,
span: Span,
) -> Result<Value, ErrorKind> {
let mut result = BString::default();
let mut vals = vec![self];
@ -331,7 +327,7 @@ impl Value {
loop {
let value = if let Some(v) = vals.pop() {
v.force(co, span.clone()).await?
v.force(co, span).await?
} else {
return Ok(Value::String(NixString::new_context_from(context, result)));
};
@ -377,7 +373,7 @@ impl Value {
// `__toString` is preferred.
(Value::Attrs(attrs), kind) => {
if let Some(to_string) = attrs.select("__toString") {
let callable = to_string.clone().force(co, span.clone()).await?;
let callable = to_string.clone().force(co, span).await?;
// Leave the attribute set on the stack as an argument
// to the function call.
@ -467,7 +463,7 @@ impl Value {
other: Value,
co: GenCo,
ptr_eq: PointerEquality,
span: LightSpan,
span: Span,
) -> Result<Value, ErrorKind> {
self.nix_eq(other, &co, ptr_eq, span).await
}
@ -487,7 +483,7 @@ impl Value {
other: Value,
co: &GenCo,
ptr_eq: PointerEquality,
span: LightSpan,
span: Span,
) -> Result<Value, ErrorKind> {
// this is a stack of ((v1,v2),peq) triples to be compared;
// after each triple is popped off of the stack, v1 is
@ -513,13 +509,13 @@ impl Value {
}
};
Thunk::force_(thunk, co, span.clone()).await?
Thunk::force_(thunk, co, span).await?
}
_ => a,
};
let b = b.force(co, span.clone()).await?;
let b = b.force(co, span).await?;
debug_assert!(!matches!(a, Value::Thunk(_)));
debug_assert!(!matches!(b, Value::Thunk(_)));
@ -568,11 +564,11 @@ impl Value {
#[allow(clippy::single_match)] // might need more match arms later
match (a1.select("type"), a2.select("type")) {
(Some(v1), Some(v2)) => {
let s1 = v1.clone().force(co, span.clone()).await?;
let s1 = v1.clone().force(co, span).await?;
if s1.is_catchable() {
return Ok(s1);
}
let s2 = v2.clone().force(co, span.clone()).await?;
let s2 = v2.clone().force(co, span).await?;
if s2.is_catchable() {
return Ok(s2);
}
@ -593,8 +589,8 @@ impl Value {
.context("comparing derivations")?
.clone();
let out1 = out1.clone().force(co, span.clone()).await?;
let out2 = out2.clone().force(co, span.clone()).await?;
let out1 = out1.clone().force(co, span).await?;
let out2 = out2.clone().force(co, span).await?;
if out1.is_catchable() {
return Ok(out1);
@ -745,7 +741,7 @@ impl Value {
self,
other: Self,
co: GenCo,
span: LightSpan,
span: Span,
) -> Result<Result<Ordering, CatchableErrorKind>, ErrorKind> {
Self::nix_cmp_ordering_(self, other, co, span).await
}
@ -754,7 +750,7 @@ impl Value {
myself: Self,
other: Self,
co: GenCo,
span: LightSpan,
span: Span,
) -> Result<Result<Ordering, CatchableErrorKind>, ErrorKind> {
// this is a stack of ((v1,v2),peq) triples to be compared;
// after each triple is popped off of the stack, v1 is
@ -770,14 +766,14 @@ impl Value {
};
if ptr_eq == PointerEquality::AllowAll {
if a.clone()
.nix_eq(b.clone(), &co, PointerEquality::AllowAll, span.clone())
.nix_eq(b.clone(), &co, PointerEquality::AllowAll, span)
.await?
.as_bool()?
{
continue;
}
a = a.force(&co, span.clone()).await?;
b = b.force(&co, span.clone()).await?;
a = a.force(&co, span).await?;
b = b.force(&co, span).await?;
}
let result = match (a, b) {
(Value::Catchable(c), _) => return Ok(Err(*c)),
@ -820,7 +816,7 @@ impl Value {
}
// TODO(amjoseph): de-asyncify this (when called directly by the VM)
pub async fn force(self, co: &GenCo, span: LightSpan) -> Result<Value, ErrorKind> {
pub async fn force(self, co: &GenCo, span: Span) -> Result<Value, ErrorKind> {
if let Value::Thunk(thunk) = self {
// TODO(amjoseph): use #[tailcall::mutual]
return Thunk::force_(thunk, co, span).await;
@ -829,7 +825,7 @@ impl Value {
}
// need two flavors, because async
pub async fn force_owned_genco(self, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> {
pub async fn force_owned_genco(self, co: GenCo, span: Span) -> Result<Value, ErrorKind> {
if let Value::Thunk(thunk) = self {
// TODO(amjoseph): use #[tailcall::mutual]
return Thunk::force_(thunk, &co, span).await;

View file

@ -28,7 +28,6 @@ use std::{
use crate::{
errors::ErrorKind,
opcode::OpCode,
spans::LightSpan,
upvalues::Upvalues,
value::Closure,
vm::generators::{self, GenCo},
@ -59,7 +58,7 @@ enum ThunkRepr {
Suspended {
lambda: Rc<Lambda>,
upvalues: Rc<Upvalues>,
light_span: LightSpan,
span: Span,
},
/// Thunk is a suspended native computation.
@ -69,10 +68,10 @@ enum ThunkRepr {
/// value means that infinite recursion has occured.
Blackhole {
/// Span at which the thunk was first forced.
forced_at: LightSpan,
forced_at: Span,
/// Span at which the thunk was originally suspended.
suspended_at: Option<LightSpan>,
suspended_at: Option<Span>,
/// Span of the first instruction of the actual code inside
/// the thunk.
@ -143,11 +142,11 @@ impl Thunk {
)))))
}
pub fn new_suspended(lambda: Rc<Lambda>, light_span: LightSpan) -> Self {
pub fn new_suspended(lambda: Rc<Lambda>, span: Span) -> Self {
Thunk(Rc::new(RefCell::new(ThunkRepr::Suspended {
upvalues: Rc::new(Upvalues::with_capacity(lambda.upvalue_count)),
lambda: lambda.clone(),
light_span,
span,
})))
}
@ -162,9 +161,8 @@ impl Thunk {
/// particularly useful in builtin implementations if the result of calling
/// a function does not need to be forced immediately, because e.g. it is
/// stored in an attribute set.
pub fn new_suspended_call(callee: Value, arg: Value, light_span: LightSpan) -> Self {
pub fn new_suspended_call(callee: Value, arg: Value, span: Span) -> Self {
let mut lambda = Lambda::default();
let span = light_span.span();
let arg_idx = lambda.chunk().push_constant(arg);
let f_idx = lambda.chunk().push_constant(callee);
@ -183,17 +181,15 @@ impl Thunk {
Thunk(Rc::new(RefCell::new(ThunkRepr::Suspended {
upvalues: Rc::new(Upvalues::with_capacity(0)),
lambda: Rc::new(lambda),
light_span,
span,
})))
}
fn prepare_blackhole(&self, forced_at: LightSpan) -> ThunkRepr {
fn prepare_blackhole(&self, forced_at: Span) -> ThunkRepr {
match &*self.0.borrow() {
ThunkRepr::Suspended {
light_span, lambda, ..
} => ThunkRepr::Blackhole {
ThunkRepr::Suspended { span, lambda, .. } => ThunkRepr::Blackhole {
forced_at,
suspended_at: Some(light_span.clone()),
suspended_at: Some(*span),
content_span: Some(lambda.chunk.first_span()),
},
@ -205,14 +201,10 @@ impl Thunk {
}
}
pub async fn force(myself: Thunk, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> {
pub async fn force(myself: Thunk, co: GenCo, span: Span) -> Result<Value, ErrorKind> {
Self::force_(myself, &co, span).await
}
pub async fn force_(
mut myself: Thunk,
co: &GenCo,
span: LightSpan,
) -> Result<Value, ErrorKind> {
pub async fn force_(mut myself: Thunk, co: &GenCo, span: Span) -> Result<Value, ErrorKind> {
// This vector of "thunks which point to the thunk-being-forced", to
// be updated along with it, is necessary in order to write this
// function in iterative (and later, mutual-tail-call) form.
@ -232,7 +224,7 @@ impl Thunk {
// Begin evaluation of this thunk by marking it as a blackhole, meaning
// that any other forcing frame encountering this thunk before its
// evaluation is completed detected an evaluation cycle.
let inner = myself.0.replace(myself.prepare_blackhole(span.clone()));
let inner = myself.0.replace(myself.prepare_blackhole(span));
match inner {
// If there was already a blackhole in the thunk, this is an
@ -243,8 +235,8 @@ impl Thunk {
content_span,
} => {
return Err(ErrorKind::InfiniteRecursion {
first_force: forced_at.span(),
suspended_at: suspended_at.map(|s| s.span()),
first_force: forced_at,
suspended_at,
content_span,
})
}
@ -262,13 +254,12 @@ impl Thunk {
ThunkRepr::Suspended {
lambda,
upvalues,
light_span,
span,
} => {
// TODO(amjoseph): use #[tailcall::mutual] here. This can
// be turned into a tailcall to vm::execute_bytecode() by
// passing `also_update` to it.
let value =
generators::request_enter_lambda(co, lambda, upvalues, light_span).await;
let value = generators::request_enter_lambda(co, lambda, upvalues, span).await;
myself.0.replace(ThunkRepr::Evaluated(value));
continue;
}