about summary refs log tree commit diff
path: root/tvix/eval/src/vm.rs
AgeCommit message (Collapse)AuthorFilesLines
2022-09-10 r/4786 fix(tvix/eval): fix doc comment syntax where applicableVincent Ambo1-11/+11
As pointed out by grfn on cl/6091 Change-Id: I28308577b7cf99dffb4a4fd3cc8783eb9ab4d0d6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6460 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-10 r/4783 feat(tvix/eval): implement OpTailCallVincent Ambo1-9/+37
If the last operation within a chunk is a function call, the call can be executed in the same call frame without increasing the depth of the call stack. To enable this, a new OpTailCall instruction (similar to OpCall) is introduced, but not yet emitted by the compiler. Change-Id: I9ffbd7da6d2d6a8ec7a724646435dc6ee89712f2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6457 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-09 r/4782 fix(tvix/eval): force value passed to builtins.toStringVincent Ambo1-1/+1
This introduces a macro to do the forcing, but this solution isn't very nice and also does not work in all cases yet. Change-Id: Icd18862ec47edb82c0efc3af5835a6cb6126f629 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6456 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-09 r/4778 feat(tvix/eval): implement runtime tracing methods for ObserverVincent Ambo1-27/+23
These methods make it possible to trace the runtime execution of the VM through an observer. Change-Id: I90e26853ba2fe44748613e7f761ed5c1c5fc9ff7 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6452 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-09 r/4773 refactor(tvix/eval): index into Chunk with ConstantIdx/CodeIdxVincent Ambo1-4/+4
This is a step towards hiding the internal fields of thunk, and making the interface of the type more predictable. Part of the preparation for implementing observers. Change-Id: I1a88a96419c72eb9e2332b56a2dd94afa47e6f88 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6447 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-09 r/4771 chore(tvix/eval): debug_assert that all jumps are patchedVincent Ambo1-0/+4
Suggestion from sterni in cl/6282 Change-Id: I1adbdda9ff74f55a2f72892ffa524808b305f403 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6445 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-08 r/4768 feat(tvix/eval): print lambda memory adresses in disassemblerVincent Ambo1-3/+4
This makes it easier to track exactly which lambda is which when inspecting e.g. the concrete representation of a thunk. At runtime all lambdas live in an Rc. To make this print the right address, the construction of these Rcs had to be moved up right to the point where the lambda is first emitted (and disassembled). Change-Id: I6070e6c8ac55f0bd697966c4e7c5565c20d19106 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6435 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4763 fix(tvix/eval): address current clippy & grfn lintsVincent Ambo1-13/+4
Change-Id: I65c6feb9f817b5b367d37204a1f57acfe4100d97 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6430 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4752 refactor(tvix/eval): implement much clearer disassembler outputVincent Ambo1-23/+45
With this change the runtime trace contains much more exact information about the context of the computation (entering/exiting calls etc.) This is in large part due to moving the tracer to be a field on the VM itself, which enables consistent ordering of traces across the execution, and tracing an execution with its *input* instead of *output* stack. Change-Id: Ibe525e6e7d869756501e52bef1a441619ce7332c Reviewed-on: https://cl.tvl.fyi/c/depot/+/6419 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4751 chore(tvix/eval): print value when panicking on internalsVincent Ambo1-1/+3
This makes it much easier to figure out what happened while debugging this sort of thing. Change-Id: I2e0e8096709adc647d63c04f213c547c415e5f44 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6418 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4748 refactor(tvix/eval): return call frame result from VM::callVincent Ambo1-12/+20
Previously, "calling" (setting up the VM run loop for executing a call frame) and "running" (running this loop to completion) were separate operations. This was basically an attempt to avoid nesting `VM::run` invocations. However, doing things this way introduced some tricky bugs for exiting out of the call frames of thunks vs. builtins & closures. For now, we unify the two operations and always return the value to the caller directly. For now this makes calls a little less effective, but it gives us a chance to nail down some other strange behaviours and then re-optimise this afterwards. To make sure we tackle this again further down I've added it to the list of known possible optimisations. Change-Id: I96828ab6a628136e0bac1bf03555faa4e6b74ece Reviewed-on: https://cl.tvl.fyi/c/depot/+/6415 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4745 refactor(tvix/eval): add macros for generating Value castersVincent Ambo1-10/+10
The casting methods of `Value` are pretty verbose, and actually incorrect before this commit as they did not account for inner thunk values. To address this, we first attempt to make them correct by introducing a standard macro to generate them and traverse the inner thunk(s) if necessary. This is likely to be a performance hit as it will now involve more cloning of values. We can do multiple things to alleviate this, but should do some measurements first. Change-Id: If315d6e2afe7b69db727df535bc6cbfb89a691aa Reviewed-on: https://cl.tvl.fyi/c/depot/+/6412 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4744 refactor(tvix/eval): pass a VM reference to builtinsVincent Ambo1-1/+1
This makes it possible for builtins to force values on their own, without the VM having to apply a strictness mask to the arguments first. Change-Id: Ib49a94e56ca2a8d515c39647381ab55a727766e3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6411 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-08 r/4741 feat(tvix/eval): ensure all errors always carry a spanVincent Ambo1-48/+83
Previously error spans were optional because the information about code spans was not available at runtime. Now that this information has been added, the error type will always carry a span. This change is very invasive all throughout the codebase. This is due to the fact that many functions that are called *by* the VM expected to return `EvalResult`, but this no longer works as the span information is not available to those functions - only to the VM itself. To work around this the majority of these functions have been changed to return `Result<T, ErrorKind>` instead and an accompanying macro in the VM constructs the "real" error. Note that this implementatino currently has a bug where errors occuring within thunks will yield the location at which the thunk was forced, not the location at which the error occured within the code. This will be fixed soon, but the commit is large enough as is. Change-Id: Ib1ecb81a4d09d464a95ea7ea9e589f3bd08d5202 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6408 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-07 r/4738 feat(tvix/eval): Support builtins.{add,sub}William Carroll1-0/+1
First pass at supporting `builtins` for tvix. The following tests appear to be WAI: ```shell $ cd tvix/eval $ cargo build $ cargo test ``` Change-Id: I27cce23d503b17a886d1109e285e8b4be4264977 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6405 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-07 r/4706 fix(tvix/eval): address current clippy lintsVincent Ambo1-1/+0
Note that I've allowed `needless_lifetimes` for the attribute set iterator, as I find the type easier to understand with these annotations present. Change-Id: I33abb17837ee4813076cdb9a87f54bac4a37044e Reviewed-on: https://cl.tvl.fyi/c/depot/+/6373 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-07 r/4705 feat(tvix/eval): semi-strictly evaluate output values of the VMVincent Ambo1-1/+35
This essentially makes the VM behave like `nix-instantiate --eval --strict`, i.e. data structures are traversed strictly and thunks are forced. Thunks embedded in closures are not forced. This allows us to re-enable tests that were disabled because they needed to output nested thunk contents, but is overall a behaviour that must be configurable later on, as it is not cmopatible with e.g. an evaluation of nixpkgs. Change-Id: I5303a5c8e4322feab1384fdb7712fecb950afca5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6372 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-07 r/4700 refactor(tvix/eval): encapsulate all thunk-forcing logic in moduleVincent Ambo1-2/+3
The VM previously took care of repeatedly forcing a thunk until it reached an evaluated state. This logic is now encapsulated inside of the `Thunk::force` implementation. In addition, force no longer returns a reference to the value by default, leaving it up to callers to decide whether they want to borrow the value or not (a helper is provided for this). Change-Id: I2aa7da922058ad1c57fbf8bfc7785aab7971c02b Reviewed-on: https://cl.tvl.fyi/c/depot/+/6365 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-07 r/4688 feat(tvix/eval): implement OpForce in VMVincent Ambo1-1/+11
This operation forces the evaluation of a thunk. There is some potential here for making an implementation that avoids some copies, but the thunk machinery is tricky to get right so the first priority is to make sure it is correct by keeping the implementation simple. Change-Id: Ib381455b02f42ded717faff63f55afed4c8fb7e3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6352 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4681 feat(tvix/eval): implement OpThunk for runtime thunk constructionVincent Ambo1-2/+17
Implements an operation very similar to `OpClosure` which populates a thunk's upvalues and leaves it on the stack. Change-Id: I753b4dfeeaae6919316c7028ec361aaa13d87646 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6350 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4679 refactor(tvix/eval): extract VM::populate_upvalues functionVincent Ambo1-30/+42
This function is reusable between thunks & closures. Change-Id: I44d5f9897b087a385c8e75027d2ff39c48a096f0 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6349 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4678 refactor(tvix/eval): Carry lambda & upvalues directly in CallFrameVincent Ambo1-13/+25
CallFrame has to work for both thunks & closures (as a thunk is basically a "weird 0-argument closure"). We opt to store the common, relevant fields directly in the frame to avoid having to dereference through the nested structures constantly (which would be especially annoying in the case of thunks). Change-Id: I47781597b84ec5cd55502dba1713e92cf2592af3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6348 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4677 refactor(tvix/eval): introduce UpvalueCarrier traitVincent Ambo1-0/+1
This trait abstracts over the commonalities of upvalue handling between closures and thunks. It allows the VM to simplify the code used for setting up upvalues, without duplicating between the two different types. Note that this does not yet refactor the VM code to optimally make use of this. Change-Id: If8de5181f26ae1fa00d554f1ae6ea473ee4b6070 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6347 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4674 feat(tvix/eval): Add Compiler::thunk method for emitting thunksVincent Ambo1-0/+2
The logic in this method is *very* similar to `compile_lambda`. It is intended to be called around any expression that should be thunked (such as function applications, attribute set values, etc.). Change-Id: Idfbb2daa9f4b735095378fb9c39a2fd07c8cff91 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6344 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4667 feat(tvix/eval): implement OpFinalise instructionVincent Ambo1-0/+13
This instruction finalises the initialisation of deferred upvalues in closures (and soon, thunks). The compiler does not yet emit this instruction, some more accounting is needed for that. Change-Id: Ic4181b26e19779e206f51e17388559400da5f93a Reviewed-on: https://cl.tvl.fyi/c/depot/+/6337 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4666 feat(tvix/eval): set up deferred upvalues at runtimeVincent Ambo1-2/+2
This will leave a sentinel value in the upvalue slot in which the actual value is to be captured after resolution once a scope is fully set up. Change-Id: I12b37b0dc8d32603b03e675c3bd039468e70b354 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6336 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4665 feat(tvix/eval): detect deferred upvalue capturingVincent Ambo1-0/+5
Uses the threaded through slot offset to determine whether initialisation of a captured local upvalue must be defered to a later point where all values of a scope are available. This adds a new data representation to the opcode for this situation, but the equivalent runtime handling is not yet implemented. This is in part because there is more compiler machinery needed to find the resolution point. Change-Id: Ifd0c393f76abfe6e2d91483faf0f58947ab1dedc Reviewed-on: https://cl.tvl.fyi/c/depot/+/6329 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
2022-09-06 r/4660 fix(tvix/eval): correct runtime error for missing dynamic upvalueVincent Ambo1-0/+6
Change-Id: I75c351619780fdc5186a54f3df9b244ada984069 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6324 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4659 fix(tvix/eval): instantiate *new* closures from blueprints each timeVincent Ambo1-9/+13
The previous closure refactoring introduced a bug in which the same closure object would get mutated constantly for each instance of a closure, which is incorrect behaviour. This commit instead introduces an explicit new Value variant for the internal "blueprint" that the compiler generates (essentially just the lambda) and uses this variant to construct the closure at runtime. If the blueprint ever leaks out to a user somehow that is a critical bug and tvix-eval will panic. As a ~treat~ test for this, the fibonacci function is being used as it is a self-recursive closure (i.e. different instantiations of the same "blueprint") getting called with different values and it's good to have it around. Change-Id: I485de675e9bb0c599ed7d5dc0f001eb34ab4c15f Reviewed-on: https://cl.tvl.fyi/c/depot/+/6323 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4658 fix(tvix/eval): correctly thread through dynamic upvaluesVincent Ambo1-7/+64
This puts together the puzzle pieces for threading dynamic upvalues (that is, upvalues resolved from the `with`-stack) all the way through. Reading the test case enclosed in this commit and walking through it is recommended to understand what problem is being tackled here. In short, because the compiler can not statically know *which* with-scope a dynamic argument is resolved from it needs to lay the groundwork for resolving from *all* possible scopes. There are multiple different approaches to doing this. The approach chosen in this commit is that if a dynamic upvalue is detected, the compiler will emit instructions to close over this dynamic value in *all* enclosing lambda contexts. It uses a new instruction for this that will leave around a sentinel value in case an identifier could not be resolved, and wire the location of this found value (or sentinel) up through the upvalues to the next level of nesting. In this tradeoff, tvix potentially closes over more upvalues than are needed (but in practice, how often do people create *really* deep `with`-stacks? and in *this* kind of code situation? maybe we should even warn for this!) but avoids keeping the entire attribute sets themselves around. Looking at the test case, each surrounding closure will close over *all* dynamic identifiers that are referenced later on visible to it, but only the last one for each identifier will actually end up being used. This also covers our bases for an additional edge-case this creates, in which an identifier potentially resolves to a dynamic upvalue *and* to a dynamic value within the function's own scope (again, would anyone really do this?) by introducing a resolution instruction for that particular case. There is likely some potential for cleaning up this code which is quite ugly in some parts, but as this implementation is now carefully calibrated to work I decided it is time to commit it and clean it up in subsequent commits. Change-Id: Ib701e3e6da39bd2c95938d1384036ff4f9fb3749 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6322 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4654 fix(tvix/eval): account for stack offset when pushing a `with` scopeVincent Ambo1-1/+4
Change-Id: I4b98eaea3ed5059c29938a117a9d59499a0bb95d Reviewed-on: https://cl.tvl.fyi/c/depot/+/6318 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4653 feat(tvix/eval): implement capture of self-recursive upvaluesVincent Ambo1-3/+9
With this change, it becomes possible for functions to call themselves as they are being defined in local bindings. Change-Id: Ib46a39ba17b1452b5673d96fa729d633d237241a Reviewed-on: https://cl.tvl.fyi/c/depot/+/6314 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-06 r/4651 refactor(tvix/eval): encapsulate internal mutability within ClosureVincent Ambo1-16/+16
This is required to efficiently construct the upvalue array at runtime, as there are situations where during Closure construction multiple things already have a reference to the closure (e.g. a self-reference). Change-Id: I35263b845fdc695dc873de489f5168d39b370f6a Reviewed-on: https://cl.tvl.fyi/c/depot/+/6312 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-04 r/4635 feat(tvix/eval): implement upvalue resolution in `with` scopesVincent Ambo1-1/+6
These need to be handled specially by the runtime if the compiler determines that a given local must be resolved via `with`. Note that this implementation has a bug: It currently allows `with` inside of nested lambdas to shadow statically known identifiers. This will be cleaned up in the next commit. Change-Id: If196b99cbd1a0f2dbb4a40a0e88cdb09a009c6b9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6299 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-04 r/4634 fix(tvix/eval): ensure OpResolveWith can be tracedVincent Ambo1-16/+16
The previous implementation of OpResolveWith manually controlled the loop iteration, which skipped over the disassembler's tracing instruction. Instead, the resolution of dynamic variables has been delegated to a new helper function. This has the additional benefit that the loop labels are no longer required, making things a bit cleaner. Change-Id: If22b74c3d49c74bf3a1ec4497cb761a9ee6cf2a4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6298 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-03 r/4629 feat(tvix/eval): implement runtime closure construction (OpClosure)Vincent Ambo1-1/+28
Implements the final bit of logic remaining for wiring up closures, which is the runtime construction of closure objects. When encountering an OpClosure, the VM walks through the bytecode collecting all the upvalue location operands (see commit introducing the OpCode::Data* variants for details) and stores the runtime values in the new closures upvalue vector. After that, the handling of the closure itself becomes functionally identical to that of lambdas. With this initial implementation of closures there are several large optimisation potentials available, the two most notable ones are: - Distinguish the runtime representation of lambdas and closures explicitly. - Detect and handle multiple-arity functions directly in the compiler. However, for both of these we should wait until we have appropriate benchmarking infrastructure in place. This is because our test implementations have shown that the complexity of either of these changes is quite significant, and we do not yet know if they really pay off. Change-Id: I077e977810fd5cb2b1ecd7f1a119e728025dd786 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6295 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
2022-09-03 r/4628 feat(tvix/eval): implement OpGetUpvalue in the VMVincent Ambo1-4/+6
This resolves an upvalue at runtime by pushing it on the stack from the closure's upvalue vector. Change-Id: Ic3e7a7ecd9f7032f679114a1995e5bbf83062fcf Reviewed-on: https://cl.tvl.fyi/c/depot/+/6294 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
2022-09-03 r/4627 refactor(tvix/eval): store Closure inside of the VM's call framesVincent Ambo1-6/+6
In preparation for implementing calling of closures, store a closure directly in the VMs call frame. Change-Id: Iad24cd8c49fee4ebd4d0c84ffaa4c2505ee3dfd6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6293 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
2022-09-03 r/4625 feat(tvix/eval): compile creation of closure objectsVincent Ambo1-1/+8
Fully implements the instructions for compiling closure objects (without runtime handling yet). Closure (and thunk) objects are created at runtime by capturing all known upvalues. To represent this, the instructions for creating them need to have a variable number of arguments. Due to that, this commit introduces new variants in OpCode that are not actually operations, but data. If the VM is implemented correctly, the instruction pointer should never point at these. Due to this, the VM will panic if it sees a data operand during an execution run. Change-Id: Ic56b49b3a42736dc437751e76df0e89c8d0619c6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6291 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
2022-09-03 r/4623 feat(tvix/eval): implement compilation of upvalue accessVincent Ambo1-0/+2
This adds a new upvalue tracking structure in the compiler to resolve upvalues and track their positions within a function when compiling a closure. The compiler will emit runtime upvalue access instructions after this commit, but the creation of the runtime closure object etc. is not yet wired up. Change-Id: Ib0c2c25f686bfd45f797c528753068858e3a770d Reviewed-on: https://cl.tvl.fyi/c/depot/+/6289 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
2022-09-03 r/4622 refactor(tvix/eval): add opcode::Count type for less ambiguityVincent Ambo1-6/+6
Change-Id: Ibde0b2baa1128a74c1364ee9a6330b62db3da699 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6288 Autosubmit: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-03 r/4621 refactor(tvix/eval): add opcode::StackIdx type for less ambiguityVincent Ambo1-3/+3
Change-Id: I9b9de1f681972c205d4d20bc5731d2ce79858edb Reviewed-on: https://cl.tvl.fyi/c/depot/+/6287 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-03 r/4619 refactor(tvix/eval): add opcode::JumpOffset type for less ambiguityVincent Ambo1-5/+5
This adds a transparent wrapper around `usize` used for jump offsets in the opcodes. This is a step towards getting rid of ambiguous plain `usize` usage in the opcode. Change-Id: I21e35e67d94b32d68251908b96c7f62b6f56a8bb Reviewed-on: https://cl.tvl.fyi/c/depot/+/6282 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-03 r/4616 refactor(tvix/eval): avoid cloning in NixAttrs::update if possibleVincent Ambo1-3/+9
Refactors the update function to take the attribute sets by value instead. To facilitate this, we use an equivalent of the currently unstable `Rc::clone_or_unwrap` in the VM when encountering attribute sets, so that in cases where the only references to the attrs being updated are the ones on the stack those clones are avoided completely. This does make update() a little bit more tricky internally, as some optimised branches can directly return the moved value, and others need to destructure with ownership. For this reason there are now two different match statements handling the different ownership cases. Change-Id: Ia77d3ba5c86afb75b9f1f51758bda61729ba5aab Reviewed-on: https://cl.tvl.fyi/c/depot/+/6279 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-03 r/4613 refactor(tvix/eval): rename Value::NotFound & OpAttrOrNotFoundVincent Ambo1-4/+4
grfn suggested clearer naming for these in cl/6166. Change-Id: I83164bf1d1902ebd42272e9d5d63819a0f6a72c5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6277 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
2022-09-03 r/4605 refactor(tvix/eval): introduce Closure struct in Value typeVincent Ambo1-2/+2
This struct will carry the upvalue machinery in addition to the lambda itself. For now, all lambdas are wrapped in closures (though technically analysis of the environment can later remove innermost Closure wrapper, but this optimisation may not be worth it). Change-Id: If2b68549ec1ea4ab838fdc47a2181c694ac937f2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6269 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
2022-09-02 r/4597 refactor(tvix/eval): add NixAttrs::contains functionVincent Ambo1-1/+1
This avoids copying around the value more than needed. Change-Id: I35949d16dad7fb8f76e0f641eaccf48322144777 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6263 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
2022-09-02 r/4585 feat(tvix/eval): add initial representation of builtinsVincent Ambo1-0/+5
Builtins are represented as a Rust function pointer that accepts a vector of arguments, which represents variable arity builtins. Change-Id: Ibab7e662a646caf1172695d876d2f55e187c03dd Reviewed-on: https://cl.tvl.fyi/c/depot/+/6251 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
2022-09-02 r/4583 feat(tvix/eval): implement opcode for function calls in VMVincent Ambo1-8/+24
Nix functions always have a single argument and we do not yet make efforts to optimise this in Tvix for known multi-argument functions being directly applied. For this reason, the call instruction is fairly simple and just calls out to construct a new call frame. Note that the logic for terminating the run loop has moved to the top of the dispatch; this is because the loop run needs to be skipped if the call frame for the current lambda has just been dropped. Change-Id: I259bc07e19c1e55cd0a65207fa8105b23052b967 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6249 Reviewed-by: sterni <sternenseemann@systemli.org> Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
2022-09-02 r/4582 refactor(tvix/eval): add VM::call helper to set up call framesVincent Ambo1-7/+12
Change-Id: Ia7ff572af90ae379b23bbd0f5215cd13a4dc0ab5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6248 Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI