4 ms·
You can probably get a pretty efficient AST-style interpreter if you spit out a pile of very specialized closures calling each other. I saw that somewhere befo
by sirwhinesalot 3y ago
You can probably get a pretty efficient AST-style interpreter if you spit out a pile of very specialized closures calling each other.
I saw that somewhere before, let me see if I can find it.
EDIT: https://blog.cloudflare.com/building-fast-interpreters-in-rust/ https://blog.cloudflare.com/building-fast-interpreters-in-ru...
- mikewarot 3y agoSo...FORTH?
- mschaef 3y agoThis is not unheard of. IIRC, Microsoft did something similar with QuickBASIC 4. The surface language was QuickBASIC, but the underlying implementation was some threaded representation.
- z500 3y agoThat's really interesting. I found a StackExchange answer on this https://retrocomputing.stackexchange.com/a/24427 https://retrocomputing.stackexchange.com/a/24427
- UncleEntity 3y agoI found this[0] around the same time I found the paper from TFA during a recent rabbit hole journey, very similar methinks. Combined with a meta-compilation system I believe it would be a fairly efficient way to implement a tree-walking interpreter. [0] https://blog.reverberate.org/2021/04/21/musttail-efficient-interpreters.html https://blog.reverberate.org/2021/04/21/musttail-efficient-i...
- olliej 3y agoThe JavaScriptCore interpreter retained the original KJS AST interpreter model for many years, during which it was faster than the Firefox bytecode of the era, which indicates quite clearly that performance is not an automatic outcome of a bytecode interpreter. Functionally your "very specialized closures" are simply virtual calls (a closure is just a function pointer and a context object which is a single indirection less than a vcall). There are a bunch of reasons we did eventually give up on the AST interpreter, but one of the biggest was that by the end we were seeing more than of 15% of runtime being just the call+return overhead. But there are a bunch of other things that make bytecode better: the AST interpreter is inherently recursive so it wasn't uncommon to have code that would fail in JSC due to stack overflows because an expression like `function f() {a(b(c(df()))}` would fundamentally 5x the recursive calls per js call (this is just to give you an idea of how recursive things were, the example above strictly always overflows). The bytecode also made it much easier to perform some inter-expression optimision under the latency requirements of a js interpreter, as well as reducing the GC costs with JSC (JSC uses a conservative collector that does stack scanning).