1. 49
  1.  

  2. 4

    Great article! At first I didn’t see the significance of the new attribute, but now I see that forcing the compiler to emit a tail-call even in unoptimized builds (and breaking the build if it can’t) is important.

    The referenced article about the design of wasm3 is killer — I came across it a few months ago and wished I’d seen it a year ago when I was implementing a simple byte code interpreter. It spells out the advantages of the threaded call style hot use the old FORTH term) very clearly.

    FYI @haberman, I believe there’s a typo (thinko?) in the following sentence; “caller” should be “callee”:

    The preserve_most attribute makes the caller responsible for preserving nearly all registers, which moves the cost of the register spills to the fallback functions where we want it.

    1. 2

      You are correct, thanks for the heads up!

    2. 1

      This is awesome. I maintain a programming language interpreter, and now I want to rewrite it using this technique. Plus, it’s cool that the tail-threaded interpreter technique is applicable to a wider domain, like protobuf parsing. What else could I parse this way?

      If I use this technique, then does it block my ability to compile to WASM, or can LLVM generate WASM code that doesn’t explode the stack when I use ‘musttail’? Tail calls are a WASM proposal, in “implementation phase”, but Firefox has been stalled on this for two years, last I checked. I’m just not sure if LLVM ‘musttail’ depends on WASM tail calls.

      1. 1

        That is a great question. I don’t know the answer to it. LLVM has had a “musttail” attribute at the IR level for a while, the Clang change just piggybacked on this existing work. I assumed this means that tail calls are supported on all targets. But I’m not sure if there are complications that would prevent this on some targets, like wasm.

      2. 1

        i had heard that luaJIT was so complex that basically nobody besides mike pall could maintain it, but i didn’t realize it was written in assembly!

        enjoyed learning more about careful optimization in this article and the interesting connections between programming style & relationship with compiled output.

        1. 6

          Hi there, article author here. I’m glad you enjoyed the article. LuaJIT’s interpreter is written in assembly, but the rest (parser, optimizer, code generator, etc) are written in C.

          1. 1

            i had heard that luaJIT was so complex that basically nobody besides mike pall could maintain it, but i didn’t realize it was written in assembly!

            FWIW, PHP’s JIT is actually basically LuaJIT’s with a lot ripped out of it.