CONCEPT Cited by 1 source
Quickening (runtime bytecode rewrite)¶
Quickening is an interpreter optimisation in which the VM rewrites its own bytecode at runtime to replace generic opcodes with type-specialized variants once operand types have been observed to stabilise. The technique is canonicalised in Stefan Brunthaler's Efficient Interpretation using Quickening (2010).
Mechanism¶
An original bytecode stream contains a generic ADD opcode.
The first time the VM executes it on operands of types INT64
and INT64, the quickening machinery overwrites the opcode in
place with a specialized ADD_INT64_INT64. Subsequent executions
dispatch directly to the specialized handler without the
type-switch overhead.
If the assumption is violated later (e.g. the operand is now
STRING), the specialized opcode bails out back to the
generic opcode or to the AST interpreter — the same
deoptimization pattern used by
JIT compilers.
Where quickening appears in practice¶
- CPython 3.11+'s "adaptive interpreter" uses quickening-style inline specialization (PEP 659) as a fast tier below JIT.
- Pyston and some Python JIT projects have used quickening as a first-tier optimisation.
- JavaScript engines use observationally-similar techniques (inline caches, hidden classes) though the exact mechanism differs.
Comparison with [static¶
specialization](<./static-type-specialization.md>)
Both techniques produce type-specialized instructions. They differ on when:
| Axis | Quickening | Static specialization |
|---|---|---|
| When specialization happens | Runtime, via observation | Compile time, via analysis |
| Prerequisite | None — works on any program | Compiler must know types ahead of time |
| Overhead | Warm-up cost; rewrite machinery | None at runtime |
| Deoptimization needed | Yes (types can drift) | Yes (value-dependent promotions) |
| Fits | General-purpose dynamic languages | DSLs with strong static type info |
Why Vitess chose static over quickening¶
Vitess's evalengine author Vicent Martí explicitly considered quickening first and moved on:
"The initial approach I had in mind for our SQL virtual machine was based on Efficient Interpretation using Quickening by Stefan Brunthaler. … To do that, a quickening VM needs to figure out at runtime the types of the expressions being evaluated and incrementally rewrite the bytecode into instructions that operate on them. This is very hard to do in practice! But after implementing a good chunk of specialized instructions for the different types of operators in SQL and attempting to runtime rewrite them, I noticed an opportunity to take the idea even further by making it more efficient and, crucially, simpler. It turns out that the semantic analysis we perform in Vitess is advanced enough that, through careful integration with the upstream MySQL server and its information schema, it can be used to statically type the AST of the SQL expressions we were executing." (Source: sources/2025-04-05-planetscale-faster-interpreters-in-go-catching-up-with-cpp)
Key insight: SQL's type system is strong enough at compile time that runtime observation buys nothing — the compiler already knows what quickening would eventually discover. Taking the static path eliminates the rewrite machinery, the warm-up period, and the class of bugs where quickening races with concurrent execution.
When quickening is the right choice¶
Quickening is the right tool when:
- The source language is dynamically typed and types can only be known by running the program.
- The code has hot paths (hits the same opcode millions of times) so runtime observation pays off.
- You can afford the rewrite machinery and deoptimization support.
For constrained VMs with strong compile-time type information — SQL expression engines, typed DSLs, rule engines — static specialization wins on simplicity with the same performance.
Seen in¶
- sources/2025-04-05-planetscale-faster-interpreters-in-go-catching-up-with-cpp — canonical mention: Martí considers quickening as the starting point for Vitess's VM and rejects it in favour of static specialization once he realises the Vitess planner already has enough type information at compile time.