WebAssembly / interface-types

Other
641 stars 57 forks source link

How much would "anyref" as a new value type help? #9

Closed titzer closed 5 years ago

titzer commented 6 years ago

We have a pretty uncontroversial plan to introduce an anyref type to WASM in the future. Instead of restricting this type to tables only, what if we also allow anyref as a WASM value type (not to be stored in linear memory) and table_get and table_set operations? If anyref remains an opaque type for now (i.e. no new operators), I think this has minimal impact on engine complexity. (For non-JS embedded engines there are implementation strategies that don't require pointer maps, see below*)

This could remove a lot of table/slot management complexity, especially for references that never need to be stored into memory, where table/slot management is just overhead. Instead, user code can implement its own WASM wrappers around imports and exports to manage tables and slots so that slot indexes can be stored into the linear memory.

I think this would be more forward-compatible, since I can imagine a world where managed data is dominant and JS/WASM interop is much smoother. In that future world the table bindings would be legacy complexity that we'd probably want to remove.

lukewagner commented 6 years ago

That's a really good point: in the absence of GC data types (or with them turned off), anyref could be implemented with, e.g., ObjC ARC, maintaining the ability of wasm to operate in a GC-free mode. For browsers, this does still effectively make some amount of wasm GC integration block the Host Binding feature, but OTOH it removes a growing swath of complexity that is essentially working around the lack of an anyref value type.

So if we only have anyref, this would lose the static type info that allows efficient calls into WebIDL bindings (avoiding the type check). So presumably we'd also allow references to type imports as value types as well?

Another question is whether, in the web embedding, anyref would be the same as the WebIDL any which can hold any JS value. This would be necessary to bind to calls that take/return a WebIDL any.

But with that, it seems like we would avoid:

The remaining uses of the binding section would be:

magcius commented 6 years ago

A few questions:

titzer commented 6 years ago

@lukewagner That's a good argument about strong types for WebIDL. Worth considering whether imported host types (of representation anyref) would be substantially different than anyref alone.

Looking back at https://github.com/WebAssembly/gc/issues/27, I noticed that @DLehenbauer basically proposed this 21 days ago.

titzer commented 6 years ago

@lukewagner I also think we definitely want anyref to mean reference types only and have a separate any only to be added later as needed. I imagine that the V8 implementation of any would use NaN boxing while anyref would continue to use our current strategy of a SMI tag. Also, any with a SIMD value might implement a heap allocation...back to madness...

lukewagner commented 6 years ago

@titzer Yeah, NaN-boxing vs. pointer-to-GC-cell is the same thing I was wondering about. While it seems we'll want any in the limit, the Host Bindings feature may be viable without it.

@magcius

rossberg commented 6 years ago

Agreed that supporting anyref would be much better than the ongoing explosion of features for host bindings.

Regarding anyref vs any: I had assumed that the GC extension would eventually allow types like (ref i32) or similar. Semantically, they are references to ints, but an engine could optimise them into tagged ints where applicable. Under this approach, they would naturally inhabit anyref, and so would all JS values. A separate "any" type wouldn't be needed (nor make much sense).

I guess I'm missing something regarding the representation of a separate 'any' type. How could a Wasm engine itself benefit from NaN-boxing when all the bits in a NaN are already observable by Wasm programs? AFAICS an engine would need to box all float values injected into type 'any' anyways.

titzer commented 6 years ago

I think we want to avoid boxing floating point values that are injected into any, so that would probably mean that a float -> any conversion would have to be explicit and do NaN pattern canonicalization.

eholk commented 6 years ago

We considered something similar for exception handling. See some discussion at https://github.com/WebAssembly/exception-handling/issues/30#issuecomment-339510570

There we abandoned this idea because it introduced some thorny lifetime issues. If there's more interest in this kind of feature now, maybe we could also simplify the exception handling proposal.

rossberg commented 6 years ago

Proposal for basic reference types is here.

pchickey commented 5 years ago

Closing as out-of-date: these concepts don't map to the current proposal, which has evolved a lot since this issue was opened.