Add a bytecode VM as a third execution path - #3
Open
erichanwang wants to merge 1 commit into
Open
Conversation
The interpreter and the x86-64 codegen already diff against each other on every corpus program, but that only catches a bug if it shows up as a disagreement between exactly two implementations. A third, structurally different one raises the bar: the VM compiles the AST once into a flat instruction stream and resolves if/while to jump targets and break/continue to plain JMPs at compile time, instead of threading a Flow value through recursive C++ calls the way the interpreter does. Arithmetic, comparison, truthiness, and array indexing are each re-derived independently rather than shared with Interpreter or runtime.c, so the same bug has to exist in all three to slip through. run_tests.sh now diffs interpreter/VM/x86-64 output pairwise on the whole corpus; all fifteen programs agree. benchmark.sh times the VM alongside the existing two paths on bench/workload.lang: interpreter 89ms, VM 88ms, x86-64 30ms (best of 9). The VM lands close to the interpreter rather than clearly ahead of it, because both resolve every variable through a map<string, Value> frame lookup, and that is what a fib(21)-heavy workload spends most of its time on -- trading AST recursion for instruction dispatch does not help until variables are slots instead of names.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a stack-based bytecode VM alongside the tree-walking interpreter and the
x86-64 codegen, so the differential suite compares three independent
implementations instead of two.
The VM compiles the AST once into a flat instruction stream per function.
if/while lower to jump targets and break/continue to plain JMPs resolved at
compile time, rather than the Flow value the interpreter threads through
recursive calls. Arithmetic, comparison, truthiness, and array indexing are
each re-derived independently instead of shared with Interpreter or
runtime.c, so a bug has to survive three unrelated implementations to pass.
run_tests.sh now diffs interpreter/VM/x86-64 pairwise on every .lang program;
all fifteen agree. benchmark.sh times the VM alongside the other two paths.
Measured on bench/workload.lang, best of 9 runs:
The VM lands close to the interpreter rather than clearly ahead of it: both
resolve every variable through a map<string, Value> frame lookup, and that
is what this fib(21)-heavy workload spends most of its time on. Trading AST
recursion for instruction dispatch doesn't help until variables are slots
instead of names -- noted in the README as the next step, not implemented
here.