Description
The tree-walking interpreter re-traverses AST nodes on every execution, paying match-dispatch, Completion enum wrapping, and recursive eval_expr call overhead on every single expression. A bytecode compiler that lowers the AST to a flat instruction sequence would eliminate this overhead and enable further optimizations (register allocation, peephole opts, superinstructions).
Motivation
Profiling the mandreel benchmark (#54) shows that even after adding fast paths for Number arithmetic, typed array access, and identifier resolution, the per-operation cost is dominated by:
eval_expr match dispatch (~30 variants)
Completion enum construction/destruction on every operation
- Recursive function call overhead for nested expressions
- Branch prediction misses from polymorphic dispatch
An empty for loop of 1M iterations takes ~1,250ms (1.25μs/iter), which is almost entirely dispatch overhead since the loop body is empty.
Scope
- Design a bytecode instruction set (stack-based or register-based)
- Implement a compiler pass: AST → bytecode
- Implement a bytecode interpreter (dispatch loop)
- Maintain spec compliance (test262 100%)
References
Description
The tree-walking interpreter re-traverses AST nodes on every execution, paying match-dispatch,
Completionenum wrapping, and recursiveeval_exprcall overhead on every single expression. A bytecode compiler that lowers the AST to a flat instruction sequence would eliminate this overhead and enable further optimizations (register allocation, peephole opts, superinstructions).Motivation
Profiling the mandreel benchmark (#54) shows that even after adding fast paths for Number arithmetic, typed array access, and identifier resolution, the per-operation cost is dominated by:
eval_exprmatch dispatch (~30 variants)Completionenum construction/destruction on every operationAn empty
forloop of 1M iterations takes ~1,250ms (1.25μs/iter), which is almost entirely dispatch overhead since the loop body is empty.Scope
References