feat(tvix/eval): track whether locals needs to be finalised

When encountering a deferred local upvalue, the compiler will now mark
the corresponding local as needing a finaliser which makes it possible
to emit the OpFinalise instruction for this stack slot a little bit
down the line.

Change-Id: I3962066f10fc6c6e1472722b8bdb415a811e0740
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6338
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2022-08-28 17:50:16 +03:00 committed by tazjin
parent 025a9a4a0a
commit 5c4e102ac8
2 changed files with 12 additions and 0 deletions

View file

@ -844,6 +844,7 @@ impl Compiler {
// and can be finalised.
if slot.unwrap() < idx.0 {
self.chunk().push_op(OpCode::DataDeferredLocal(idx));
self.mark_needs_finaliser(slot.unwrap());
} else {
self.chunk().push_op(OpCode::DataLocalIdx(idx));
}
@ -987,6 +988,7 @@ impl Compiler {
name,
depth,
initialised: false,
needs_finaliser: false,
node: Some(node),
phantom: false,
used: false,
@ -1002,6 +1004,7 @@ impl Compiler {
self.scope_mut().locals.push(Local {
depth,
initialised: true,
needs_finaliser: false,
name: "".into(),
node: None,
phantom: true,
@ -1014,6 +1017,11 @@ impl Compiler {
self.scope_mut().locals[local_idx].initialised = true;
}
/// Mark local as needing a finaliser.
fn mark_needs_finaliser(&mut self, local_idx: usize) {
self.scope_mut().locals[local_idx].needs_finaliser = true;
}
fn resolve_upvalue(&mut self, ctx_idx: usize, name: &str) -> Option<UpvalueIdx> {
if ctx_idx == 0 {
// There can not be any upvalue at the outermost context.

View file

@ -38,6 +38,10 @@ pub struct Local {
// Is this local known to have been used at all?
pub used: bool,
// Does this local need to be finalised after the enclosing scope
// is completely constructed?
pub needs_finaliser: bool,
}
impl Local {