WebAssembly / shared-everything-threads

A draft proposal for spawning threads in WebAssembly
Other
44 stars 1 forks source link

Question about thread-local function optimization #41

Open eqrion opened 9 months ago

eqrion commented 9 months ago

Per the explainer, thread-local WA.Function starts as null on all threads and then transitions to non-null exactly once on a thread when the initialize method is called.

As an engine-internal optimization, setting a thread-local global to a thread-local function wrapper can skip a layer of indirection and set the global to refer directly to the bound function, since it will never change or be observed from another thread. This optimization only works because the dynamic contexts of thread-local globals and thread-local function wrappers are the same, i.e. an entire thread or agent.

How can the above be possible? When the global.set for a thread-local global happens, the initialize method may not have happened yet. From core wasm's perspective this is a non-null (ref func shared), so I don't think we can say that it traps due to null or type mismatch.

tlively commented 9 months ago

Yes, this part is definitely hand-wavy and could benefit from validation from implementers.

In more detail, the global does actually have to store the shareable function wrapper in case there is a global.get that ends up publishing the function reference somewhere it will be visible to other threads. The optimization is that it could also store the unwrapped function for the special case of (call_ref $f (global.get $g)) or where the engine otherwise determines that the funcref won't escape to another thread. You're right that this would only work on threads where the function is initialized before it is set to the global, but there will always be that fallback path available.