Live data from Hacker News

Wasm3 – A high performance WebAssembly interpreter in C

github.com

31–40 of 79 posts

Re: Wasm3 – A high performance WebAssembly interpreter in C

#31

This is pretty exciting if real: > Bytecode/opcodes are translated into more efficient "operations" during a compilation pass, generating pages of meta-machine code WASM compiled to a novel bytecode format aimed at efficient interpretation. > Commonly occurring sequences of operations can can also be optimized into a "fused" operation. Peephole optimizations producing fused opcodes, makes sense. > In M3/Wasm, the sta…

IR getting converted into an interpreter-oriented bytecode is pretty common. Mono does it for its interpreter and IIRC, Spidermonkey has historically done that as well. I'm not sure if V8 has ever interpreted from an IR (maybe now?) but you could view their original 'baseline JIT' model as converting into an interpreter-focused IR, where the IR just happened to be extremely unoptimized x86 assembly.

Translating the stack machine into registers was always a core part of the model but it's interesting to me that even interpreters are doing it. The necessity of doing coloring to assign registers efficiently is kind of unfortunate, I feel like the WASM compiler would have been the right place to do this offline.

Re: Wasm3 – A high performance WebAssembly interpreter in C

#32
post #6
post #5

Earlier quoted context omitted.

On the embedded side, I'd rather see a hardware interpreter.

I'm hardware ignorant... would that be a system on a chip?

No, a "system on a chip" means the chip includes things that are not typically part of the CPU but were always parts of computer systems: busses, I/O, sometimes memory, auxillary HW functions like audio, image/video processing or codecs.

Nowadays CPU's often have a bunch of these things anyways and you'll hear that all CPU's sort of resemble SoCs. They also tend to have auxillary, lower-power processors that manage power and other things for the main processor.

Re: Wasm3 – A high performance WebAssembly interpreter in C

#33

This is pretty exciting if real: > Bytecode/opcodes are translated into more efficient "operations" during a compilation pass, generating pages of meta-machine code WASM compiled to a novel bytecode format aimed at efficient interpretation. > Commonly occurring sequences of operations can can also be optimized into a "fused" operation. Peephole optimizations producing fused opcodes, makes sense. > In M3/Wasm, the sta…

Sure this is neat stuff, but I don't think any of it is novel. Bochs is a good source for some bytecode vm performance wizardry [1], even if the bytecode in question is the x86 ISA.

Regardless, kudos to the authors and nice to see a fast wasm interpreter done well.

1: http://www.emulators.com/docs/nx25_nostradamus.htm

Re: Wasm3 – A high performance WebAssembly interpreter in C

#34
post #2

The neater article seems to be about M3 interpreter https://github.com/soundandform/m3#m3-massey-meta-machine Tbh, I couldn't get the eureka moment though. Might try to read in the AM ;)

Yeah, this is a good way to design a fast interpreter! It's traditionally called a "threaded interpreter", or (somewhat confusingly) "threaded code":

https://en.wikipedia.org/wiki/Threaded_code

http://www.complang.tuwien.ac.at/forth/threaded-code.html

You can see an example of this particular implementation style (where each operation is a tail call to a C function, passing the registers as arguments) at the second link above, under "continuation-passing style".

One of the big advantages of a threaded interpreter is relatively good branch prediction. A simple switch-based dispatch loop has a single indirect jump at its core, which is almost entirely unpredictable -- whereas threaded dispatch puts a copy of that indirect jump at the end of each opcode's implementation, giving the branch predictor way more data to work with. Effectively, you're letting it use the current opcode to help predict the next opcode!

Re: Wasm3 – A high performance WebAssembly interpreter in C

#35
These are impressive performance numbers.

> Because operations end with a call to the next function, the C compiler will tail-call optimize most operations.

It appears that this relies on tail-call optimization to avoid overflowing the stack. Unfortunately this means you probably can't run it in debug mode.

Re: Wasm3 – A high performance WebAssembly interpreter in C

#36

This is pretty exciting if real: > Bytecode/opcodes are translated into more efficient "operations" during a compilation pass, generating pages of meta-machine code WASM compiled to a novel bytecode format aimed at efficient interpretation. > Commonly occurring sequences of operations can can also be optimized into a "fused" operation. Peephole optimizations producing fused opcodes, makes sense. > In M3/Wasm, the sta…

IR getting converted into an interpreter-oriented bytecode is pretty common. Mono does it for its interpreter and IIRC, Spidermonkey has historically done that as well. I'm not sure if V8 has ever interpreted from an IR (maybe now?) but you could view their original 'baseline JIT' model as converting into an interpreter-focused IR, where the IR just happened to be extremely unoptimized x86 assembly. Translating the s…

> The necessity of doing coloring to assign registers efficiently is kind of unfortunate

Register based VMs like Lua don't do this. The register allocation is incredibly simple https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lj_parse.c#L3...

Re: Wasm3 – A high performance WebAssembly interpreter in C

#37
post #28
post #26

Earlier quoted context omitted.

Well for that execution of unsafe Assemblies was already enabled anyway, so there isn't much that the verifier can do. Which is something that WASM isn't being honest about, corruption of internal data structures is allowed. If I can control what goes into memory just by calling module public functions with the right data set and access patterns, CFI won't help a thing. Suddenly the authorization module that would au…

Note for C++ on the CLR that you can use /clr:safe as an MSVC compilation argument. This errors out when trying to access to random pointers at compile time. /clr:pure uses unsafe and supports those cases though. And yeah, WebAssembly only doing bounds checking within a single memory block and not actually offering true bounds checking is a big downgrade, and a pretty much unjustified one (+ it's rare among JITted la…

If you care about "true" bounds checking, just compile to Wasm from a safe source language. Besides, Wasm does support multiple memory blocks so a potentially-unsafe module need not "taint" anything else.

Re: Wasm3 – A high performance WebAssembly interpreter in C

#38
post #28

Earlier quoted context omitted.

Note for C++ on the CLR that you can use /clr:safe as an MSVC compilation argument. This errors out when trying to access to random pointers at compile time. /clr:pure uses unsafe and supports those cases though. And yeah, WebAssembly only doing bounds checking within a single memory block and not actually offering true bounds checking is a big downgrade, and a pretty much unjustified one (+ it's rare among JITted la…

If you care about "true" bounds checking, just compile to Wasm from a safe source language. Besides, Wasm does support multiple memory blocks so a potentially-unsafe module need not "taint" anything else.

Security is as strong as the weakest link.

Re: Wasm3 – A high performance WebAssembly interpreter in C

#39
post #28

Earlier quoted context omitted.

Note for C++ on the CLR that you can use /clr:safe as an MSVC compilation argument. This errors out when trying to access to random pointers at compile time. /clr:pure uses unsafe and supports those cases though. And yeah, WebAssembly only doing bounds checking within a single memory block and not actually offering true bounds checking is a big downgrade, and a pretty much unjustified one (+ it's rare among JITted la…

If you care about "true" bounds checking, just compile to Wasm from a safe source language. Besides, Wasm does support multiple memory blocks so a potentially-unsafe module need not "taint" anything else.

Memory blocks have a page granularity, which makes them useless for pervasive checking. (+ you can do the same thing to a reasonable extent with C even, with guard pages.)

Re: Wasm3 – A high performance WebAssembly interpreter in C

#40

Earlier quoted context omitted.

IR getting converted into an interpreter-oriented bytecode is pretty common. Mono does it for its interpreter and IIRC, Spidermonkey has historically done that as well. I'm not sure if V8 has ever interpreted from an IR (maybe now?) but you could view their original 'baseline JIT' model as converting into an interpreter-focused IR, where the IR just happened to be extremely unoptimized x86 assembly. Translating the s…

> The necessity of doing coloring to assign registers efficiently is kind of unfortunate Register based VMs like Lua don't do this. The register allocation is incredibly simple https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lj_parse.c#L3...

But that's an allocator to virtual registers that don't try to correspond to (a valid number of) physical CPU registers. Sure it's easy to allocate to a large number of registers. It's harder to do it to a small number, like the project discussed here seems to claim to do.
Post reply on HN