Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FYI: prototyping work in wabt and V8 #81

Closed
jakobkummerow opened this issue Mar 18, 2020 · 43 comments
Closed

FYI: prototyping work in wabt and V8 #81

jakobkummerow opened this issue Mar 18, 2020 · 43 comments

Comments

@jakobkummerow
Copy link
Contributor

Just FYI to anyone who's interested: we have started prototyping this proposal in both wabt and V8.
We've consolidated the plan for the prototypes in this document to ensure that both implementations are compatible.

I'd like to emphasize that we're not trying to shortcut or sidestep the ongoing discussion about the specifics of the proposal. The prototypes will not ship (they will remain behind off-by-default flags). We will ship whatever the outcome of the proposal/spec process will be. The prototypes do not constitute an expression of preference/opinion on any of the open questions.

Instead, the idea is to (1) start making progress with the core implementation work we will (most likely) have to do at some point anyway, and (2) hopefully be able to provide feedback to the ongoing discussion, e.g. around practical feasibility of structural type checking, although to be really meaningful this might require some Wasm producers (i.e., source languages) to volunteer to invest the effort to produce modules targeting the prototypes.

@lars-t-hansen
Copy link
Contributor

That's great news. Firefox has also had a prototype for about a year or so, documented here.

@rossberg
Copy link
Member

Excellent news! I'll push forward with the reference interpreter, probably focussing on the function refs and type imports proposals first.

@Horcrux7
Copy link

@lars-t-hansen Do you plan to adapt the binary coding of Firefox GC as soon as the implementation in WABT progresses?

I ask because I use your code for my tests.

@skuzmich
Copy link

skuzmich commented Mar 18, 2020

Kotlin/Wasm prototype also currently targets Firefox GC instruction set. In order to fully port it to WABT and V8 we would need optref, ref.cast and ref.test on top of the MVA.

@RossTate
Copy link
Contributor

Cool! Regarding (2), it will be helpful if you make it easy to turn on and off optimizations, since some optimizations we can rely on now we might not be able to rely on in the future, so it'd be nice to know how critical that reliance is.

And yes, we need to get some languages to work on targeting this extension. Great to hear that Kotlin is already working on it! I think OCaml is working on it too. I'll see if I can rally some more, ideally from the dynamic languages.

@binji
Copy link
Member

binji commented Mar 18, 2020

@skuzmich thanks for the info! I'll make sure to work on those next.

@lars-t-hansen
Copy link
Contributor

@lars-t-hansen Do you plan to adapt the binary coding of Firefox GC as soon as the implementation in WABT progresses?

In general, the Firefox implementation can be changed to be compatible with whatever, as few people are using it. I've not looked at what @binji's done yet, but if it's incompatible with what I have then I guess we have to make the designs converge.

@binji
Copy link
Member

binji commented Mar 19, 2020

I took a quick look, it seems like the main differences are these:

name v8/wabt FF
structtype form 0x5f 0x50
ref.eq 0xd3 0xf0
struct.new 0xfb00 0xfc50
struct.get 0xfb03 0xfc51
struct.set 0xfb06 0xfc52
struct.narrow X 0xfc53

@skuzmich
Copy link

Another major difference is that FF (ref T) is v8 (optref T)

@lars-t-hansen
Copy link
Contributor

FF also requires the presence of a special section in the module to enable the feature at all, https://github.com/lars-t-hansen/moz-gc-experiments/blob/master/version2.md#special-section-required. This was just paranoia on my part. If we're converging on some basic aspects of the design and some shared opcodes I could remove that requirement.

@lars-t-hansen
Copy link
Contributor

Another major difference is that FF (ref T) is v8 (optref T)

That's just syntax, right? Easy enough to fix...

@binji
Copy link
Member

binji commented Mar 20, 2020

I think optref is nullable and ref is non-nullable.
edit: ah, sorry I see what you mean. :-)

@Horcrux7
Copy link

@jakobkummerow It there any build of V8 that include this prototype for testing?

@jakobkummerow
Copy link
Contributor Author

@Horcrux7 Not yet. The V8-side work is far from complete (even the "MVA" subset). I'll post an update here when there's something to play with.

@Horcrux7
Copy link

@jakobkummerow I think the MVA subset should be enough for first test.

@lars-t-hansen
Copy link
Contributor

Firefox update landing before long: https://bugzilla.mozilla.org/show_bug.cgi?id=1624363 though this will only have optref for now, buyer beware.

@sabine
Copy link

sabine commented Apr 18, 2020

Is there already something I can use to run .wat files that contain white and green instructions from the Google document linked above?

The reason I ask is that it would be really nice to run the code emitted by an experimental compiler backend in someone else's GC prototype.

@binji
Copy link
Member

binji commented Apr 20, 2020

@sabine you may be able to use the wabt interpreter, if your cases are simple enough. See the GC branch: https://github.com/WebAssembly/wabt/tree/gc

@eqrion
Copy link
Contributor

eqrion commented Apr 30, 2020

We're looking at updating SpiderMonkey for the changes introduced by removing funcref/anyref subtyping in WebAssembly/reference-types#69. One question that arose is what to do for our GC prototype, and I think it'd be good to align with other prototypes.

One approach that we're considering is to keep all subtyping logic, but conditionally enable it for when the GC prototype is enabled. So when GC is not-enabled, there would be no subtypes. But when GC is enabled, the old subtyping model of funcref :> anyref/externref and ref T :> anyref/externref would be re-enabled. The advantage of this is that it's likely the easiest change and would be maximally compatible with existing users.

Another option would be to create a new subtyping hierarchy for the GC types such as a gcref that is the super type of all ref T. This would need a more detailed proposal and would also break existing prototypes.

@jakobkummerow
Copy link
Contributor Author

In V8's upcoming GC prototype, our situation is that we're approaching this from the other direction (as we don't have an existing prototype to modify), and our preliminary plan is to build only the subtyping that we absolutely need, considering that the larger questions around how subtyping should work are still in flux (as evidenced e.g. by the recent funcref change, as well as the larger nominal-vs-structural discussion). At a minimum, we think we'll need ref T :> optref T :> eqref, for T being any struct or array type (essentially making eqref the supertype of all managed types, what you call gcref in your last paragraph).

I'm open to thoughts about implementing more. Since we'll use a unified representation internally anyway, adding eqref :> anyref would be easy. Keeping funcref :> anyref when the experimental-gc flag is present would also be feasible, if you think that'd be desirable.

@Horcrux7
Copy link

Is there a newer version of the prototype which reflect the latest changes for removing subtyping?

@rossberg
Copy link
Member

rossberg commented Jun 2, 2020

@Horcrux7, subtyping was only removed from the reference types proposal. It's still included in the GC proposal.

@Horcrux7
Copy link

Horcrux7 commented Jun 2, 2020

@rossberg With the "removing subtyping" there are some incompatible changes like the extra parameter for ref.null and ref.is_null. Also the type 0x11 is named externalref now. If there is a type anyref in the GC spec it required a new code. Or it must be renamed. Then I think the type nullref is obsolete. Or come it again with the GC spec?

@jakobkummerow
Copy link
Contributor Author

jakobkummerow commented Jun 9, 2020

Status update: we have updated our "prototype specification" document to reflect the latest changes to the relevant proposals, as well as our plans for a "milestone 2". Aside from that, we have kept the specification as backwards-compatible as possible.

We have also introduced columns to indicate the implementation status (currently for SpiderMonkey/V8/WABT, happy to add others if there are any) and are inviting representatives of those prototypes to indicate their status there if they wish. The idea is that interested users/consumers can easily see how far along the various prototypes are, and which implementation might fit their current needs.

The link to the doc is still https://bit.ly/3cWcm6Q.

@sabine
Copy link

sabine commented Jun 24, 2020

Are there currently plans to implement i31ref? With the recent change to anyref not being a supertype of things, I'm a little confused whether there will be an i31ref in the future.

@rossberg
Copy link
Member

@sabine, to clarify, anyref was merely removed (deferred) from the initial reftypes proposal. It has moved to the type imports proposal, which is a prerequisite of this one. Both type imports and the GC proposal as it stands would be of rather limited use without some version of anyref.

@jakobkummerow
Copy link
Contributor Author

Regarding implementation plans: as our document https://bit.ly/3cWcm6Q describes, we haven't committed to implementing i31ref yet. That doesn't rule out that we might implement it in Q3; it only means that so far it hasn't had priority. Do you have a particular need or use case for it (that's not adequately served by (struct $fake_i31 (field mut i32)) for the time being)?

@sabine
Copy link

sabine commented Jun 26, 2020

@jakobkummerow Using the workaround of boxing all the i31s is alright, for now, but clearly not good for performance (the integer unboxing strategy of OCaml already comes at the cost of having to do 31-bit arithmetic; the gain that traditionally offsets this cost is that there is no indirection through the heap when accessing the unboxed integer).

I'm only worried that, if i31ref was, in general, at risk of getting scrapped (without a replacement feature) or at risk of getting delayed for a long time (more than 2 years), then relying on this workaround and planning to use i31ref in the future (which would require the least amount of changes to the existing compiler and probably result in the least amount of additional complexity introduced to the compiler) would be a bad direction to head in. In that case, it would make sense for me to explore other options that can enable parametric polymorphism with unboxed (31-bit-)integers (e.g. run-time code specialization or having a linker that does full-program analysis) and to learn how to change the existing compiler to be able to make use of them.

Edit: to elaborate: When I translate the compiler primitives that operate on unboxed 31-bit integers (i31ref) to the workaround in the naive way, every single one of these operations first unboxes (i.e. reads the i31 value stored in the field of struct $fake_i31), then does i31 arithmetic, and then boxes (writes the result to the field of the $fake_i31 struct) the value again. (Which is perfectly fine for a proof-of-concept.)

@RossTate
Copy link
Contributor

@sabine, it's hard to say what the future of i31ref is. In particular, WebAssembly is supposed to be fairly flexible with regards to implementation strategies, and the precise choice of 31 bits means that i31ref is designed around a specific GC-implementation strategy. That doesn't mean it's going away, and even if it does go away that doesn't mean that an alternative won't be made available, and even if such an alternative isn't available in the MVP (which is supposed to minimal) that doesn't mean it won't be made available later. So there's enough uncertainty that it's worth investigating other options, though you probably want to defer picking a particular option until more has been pinned down.

One thing I'll note specific to OCaml is that its semantics for int is already platform specific: 31 bits on 32-bit machines and 63 bits on 64-bit machines. Given that a number of programs already deal with this variation, they might be amenable to simply using 32 bits for int. But you know OCaml's ecosystem better than me, so your better positioned to make that call; I just wanted to put the suggestion out there.

@sabine
Copy link

sabine commented Jun 27, 2020

@RossTate let's continue this in #100, to not derail this thread further.

@rossberg
Copy link
Member

Just to be clear, there currently is no plan for dropping i31ref. The GC proposal clearly needs a way to express unboxed scalars, and in a way that is predictable and works across platforms.

One could argue that this is just a performance improvement, and technically that's true. However, it also is such a fundamental feature that it should be part of the basic design evaluation that we want to do with the MVP. Without a proven way to incorporate unboxed scalars, practical usability of the GC extension will remain completely unclear for a whole range of languages.

@jakobkummerow
Copy link
Contributor Author

We will add i31ref to the V8 prototype soon.

@aardappel
Copy link

@jakobkummerow would love to hear along what paths adding i31ref causes conditionals.

@rossberg that still appears to be a matter of opinion.

@sabine
Copy link

sabine commented Jul 17, 2020

Side question: to use the V8 prototype, we use the instructions at https://v8.dev/docs/build to build V8 from source, or is there a simpler/quicker method to get a build of the bleeding-edge V8?

@skuzmich
Copy link

https://github.com/GoogleChromeLabs/jsvu is a handy tool that downloads and updates canary builds of V8 and other engines.

@Horcrux7
Copy link

@sabine I use https://github.com/nodejs/node-v8
It is a node build with v8-canary. You can download directly the binaries. But currently it is broken for Windows. Only the other platforms are available.

@Horcrux7
Copy link

@jakobkummerow Are you interested in bug reports or is it too early for that? Currently I have a crash with 0xC0000005.

@binji
Copy link
Member

binji commented Sep 17, 2020

FYI: I haven't made much progress on wabt, but I have implemented milestone2 support in wasp: https://github.com/binji/wasp

The plan is to merge the wasp library into wabt, but for now wasp has its own tool to do the text -> binary conversion.

@jakobkummerow
Copy link
Contributor Author

@Horcrux7 yes, I'm interested in bug reports. Probably makes sense not to derail this thread; you can email me (address in the doc linked in the OP) or file a bug at crbug.com/v8/new and assign it to me. Please include repro instructions :-)

@skuzmich skuzmich mentioned this issue Nov 26, 2020
@jakobkummerow
Copy link
Contributor Author

Heads up: we're planning to adopt the lastest changes to the proposal, which will break backwards compatibility. Please comment on this draft doc: https://docs.google.com/document/d/1yAWU3dbs8kUa_wcnnirDxUu9nEBsNfq0Xo90OWx6yuo/edit# if you have questions/comments/concerns.

rossberg pushed a commit that referenced this issue Feb 24, 2021
@jakobkummerow
Copy link
Contributor Author

FYI, we are currently adding support for two experimental instructions that are not (yet?) included in this proposal:

  • array.copy: copy a range of elements from one array to another, similar to bulk memory operations
  • rtt.fresh_sub: like rtt.sub, but always creating a fresh RTT (never caching or canonicalizing), making it possible to express Java's type system in terms of RTT-based operations.

Both instructions are described in our existing document: https://bit.ly/3cWcm6Q. To use them, pass the new flag --experimental-wasm-gc-experiments to d8. The existing --experimental-wasm-gc flag will continue to enable only the features that are part of this proposal.

The idea is to gather data, and in particular to verify the assumption that these instructions provide practical benefits. Depending on the results, we will either officially request that they (or something like them) be included in the GC proposal, or drop them again.

@tlively
Copy link
Member

tlively commented Jun 16, 2022

Closing this issue since it hasn't been used for announcements in over a year, although note that we have continued to keep the link @jakobkummerow shared pointing to the latest version of the informal prototype spec as it has evolved.

@tlively tlively closed this as completed Jun 16, 2022
@jakobkummerow
Copy link
Contributor Author

Here's an announcement :-) (but I'm happy to keep this issue closed)

For a while now, "milestone 5" of the prototype spec has been the de-facto state of things despite officially still being marked as "draft". I've just made it official to reflect reality. It's at the old link: https://bit.ly/3cWcm6Q

A number of backwards-incompatible changes have accumulated recently; we're planning to incorporate those in the next version of the prototype spec, so that'll be a breaking change. Details TBD -- I guess we'll prepare patches (and/or land code behind flags), make some announcement, and then flip the switch (in a coordinated manner across both V8 and Binaryen).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests