WebAssembly / threads

Threads and Atomics in WebAssembly
https://webassembly.github.io/threads/
Other
703 stars 50 forks source link

Lock objects (GC feature + WebIDL tie-ins) #136

Open lars-t-hansen opened 5 years ago

lars-t-hansen commented 5 years ago

(This is a post-all-the-MVPs feature; I'm recording it because the issue came up again in a conversation.)

When we added shared memory to JS it was motivated in large part by compiling C/C++ to asm.js, a focus that was at least in part inherited from NaCl/PNaCl; let's call this the "asm.js" use case for short. In this world there is only flat memory; asm.js has no host object support at all.

Thus when it came time to spec the atomic operations we were in a bind about locks: On the one hand we could add a lock data type and lock and unlock as primitive operations in both the code and the memory model. This would be nice for users and especially the JS side of the programs (well-tested lock primitives with good performance, and lock objects that could be postMessage'd to other threads) and perhaps for JIT compilers (in principle it's easier to move operations into critical sections than to move them across lower-level atomic operations). On the other hand, it created a specification and implementation headache since lock "objects" would have to be specified external to asm.js with some sort of "integer handle" model, leading to a GC problem at least, or locks would have to be allocated in flat shared memory and would not have any kind of encapsulation - there are many problems. Furthermore, the semantics of lock objects might not map cleanly onto the semantics of whatever source language or thread library we were compiling from, so a flexible mechanism was required anyway. And thus we got atomics and futexes.

Wasm changes the calculus somewhat here with its typed references. We can now have a primitive lock object type (ref Lock) and lock and unlock operations in the instruction set and as JS methods (and other data types and operations besides). Code compiled from a language that has awareness of wasm gc objects and not from a legacy language such as C++ could perhaps make use of such lock objects. Our JIT compilers could generate good code and exploit optimization opportunities.

Wasm also changes the calculus with the WebIDL bindings, in that we could get much of the benefit of lock objects just with type imports and inlined methods on known built-in types. It leaves non-WebIDL embeddings high and dry, but it's good for the web (to the extent shared memory and locks are good for the web) and allows us to experiment more.

No code would be precluded from using flat memory for their own locks, of course, so this would all be strictly additive no matter which way we go.

binji commented 5 years ago

@conrad-watt thoughts on how something like this would work with the memory model?

conrad-watt commented 5 years ago

It should be a straightforward extension to the axiomatic model. Generally locks enforce a very simple total order across all lock/unlock operations on the same object, so there's no real room for surprising weak behaviours.