Closed alexcrichton closed 5 months ago
Good question! The wording limiting atomic operations to anyref
(or (ref null (shared any)
of course) and its subtypes is intentional, under the assumption that engines might represent other types in a way that would not allow lock-free atomic accesses. For example I believe wasmtime was at some point using fat pointers for functions (is that right?) and I know wasm2c uses an extremely large representation for exnref. This is similar to how we don't provide atomic accesses to v128 types.
If that makes sense to everyone, I can add a note clarifying the intent to the text.
Ah ok that sounds good! I don't have a use case in mind for supporting this but I mistakenly assumed that the intention was to support atomic operations on tables. In that sense I think it'd be good to have a clarification. Wasmtime currently has a pointer-per-funcref but we've considered moving to a flatter representation (as you mention) but we haven't made the transition yet and I was thinking about that when reading over this.
Thinking a bit more on this though, the intention is that table.{get,set}
still work on shared tables, right? If so engines with larger-than-pointer-size representations will still need to somehow rationalize what it means to concurrently table.{get,set}
. For example we wouldn't want a table.get
to produce a "half and half" funcref if it were to race with a table.set
. Mostly I say this in the sense that the omission of these atomic instructions for funcref
, for example, does not mean that engines can completely ignore the concurrent behavior here I think. There will still need to be some sort of atomic handling in place to handle larger-than-pointer-width funcrefs/externrefs/exnrefs I think
Good point, we'll still need to spec that even non-synchronizing accesses to references should never tear. In practice that might mean a performance hit for accessing shared tables or globals for some types.
Good point, we'll still need to spec that even non-synchronizing accesses to references should never tear. In practice that might mean a performance hit for accessing shared tables or globals for some types.
The reasonable strategies I can think of to avoid tearing on large representations also seem like they would support atomic accesses. I'm fine with being conservative for now but it's worth thinking about whether we'll want to relax our anyref
restriction in future.
Currently the explainer says "valid for anyref tables" which I believe doesn't include other "top" types like
externref
andfuncref
. Is it the intention that these instructions work for funcref/externref as well though?I can see how
cmpxchg
shouldn't work with funcref/externref, however, hence the limitation toeqref
, so this is just about the get/set/xchg instructions.