Closed Bug 1774837 Opened 2 years ago Closed 2 years ago

Update heaptype hierarchy

Categories

(Core :: JavaScript: WebAssembly, task, P3)

task

Tracking

()

RESOLVED FIXED
109 Branch
Tracking Status
firefox109 --- fixed

People

(Reporter: rhunt, Assigned: rhunt)

References

(Blocks 1 open bug)

Details

Attachments

(4 files)

Since we've last updated our GC proposal implementation there is now:

  • anyref (added back since ref-types removed it)
  • dataref - super type of struct/array
  • arrayref - super type of arrays

anyref is a little tricky, because it's specified to actually just be a renaming of externref. If we do this we need to be careful around configuration flags for if GC is enabled or not.

This is changing with the adoption of '3-pronged subtyping hierarchy' [1] [2]. I will write up notes as soon as I understand this.

[1] https://github.com/WebAssembly/gc/pull/310
[2] https://github.com/WebAssembly/gc/issues/307

Summary: Add missing heaptypes → Update heaptype hierarchy

V8 has a doc describing their next milestone and it includes this [1]. It has a great diagram that shows the new heap type hierarchy.

[1] https://docs.google.com/document/d/14xWenN0lUoHa9TiDJd8yYR8ZKjgOhgO7iEmfrAuA1_M/edit#heading=h.9dwoku9340md

Right now we have 'externref' and 'funcref', so we already have two of the 'three pronged' type hierarchy. The third prong is 'anyref'.

The real prize for doing all this work is that we can have a separate representation for 'anyref' than we do for 'externref'. 'anyref' can be our internal wasm representation of just a pointer. 'externref' can be represented as JS NaN-boxed Value without the implicit boxing that we currently need to do (see BoxAnyRef). There are then explicit coercions added to convert an 'externref' into and 'anyref' and back (extern.externalize/internalize).

To start, we'll want to keep 'externref' using the same representation as 'anyref' (the wasm::AnyRef representation of a JSObject*). Giving them separate representations is just an optimization and likely to be a good amount of work.

The work in this bug (or sub bugs) is going to be adding a bunch of new cases to RefType:

  • anyref - the super type of all wasm internal references
  • dataref - the super type of wasm structs and wasm arrays
  • arrayref - the super type of wasm arrays
  • nullref - the type of null wasm internal references
  • nullexternref - the type of null external (AKA JavaScript) values
  • nullfuncref - the type of null wasm functions

The 'null*ref' types are meant to be used as the immediate for the 'ref.null' instruction.

Unfortunately, there are a bunch of locations we switch on refTypeKind() [1] in the engine and most of these new cases should behave identically. I think the first step here may be refactoring these switches to just check some predicates on RefType, so we can update the predicates for each new heap type without updating all switches. e.g. maybe we need a isInternalRef() predicate?

I don't know what the right predicates would be yet, some switches are asking for 'what reference representation is this?', some are asking 'does this need a coercion from JS value?', others are asking 'is this reference exposable to JS'? Some of the checks seems sort of suspicious too, not sure if they're all required.

Adding a new heap type requires:

  1. Extending TypeCode with the new constant
  2. Updating Decoder::readHeapType
  3. Adding the subtype rule to TypeContext
  4. Updating RefType/ValType/FieldType::isValid
  5. Extending ToJSValue and ToWebAssemblyValue (WasmValue.h) to handle the new reftype
  6. Likely adding the new heaptype to FuncType::temporarilyUnsupportedReftypeForEntry and temporarilyUnsupportedReftypeForExit
    - Otherwise WasmStubs needs to be updated
  7. Updating all remaining switches on refTypeKind to take the new value and do the 'right thing' :)

We can implement the extern.externalize/internalize instructions as just no-ops that return their input. Once we have a different representation for anyref vs externref, we would need to perform a conversion here.

Testing is a bit tricky here. Here are some ideas:

  1. functions can take these new heap types as params and results
  2. these functions can be called from JS or wasm
  3. Subtypes of these heap types can be passed as arguments to these functions
    - e.g. struct can be passed to a function param of anyref/dataref
  4. ref.null null*ref for all types works
  5. We can take an externref, internalize it, externalize it back, and have the same value (using JS == and === operators)
  6. We can take a struct or array, externalize it, internalize it back and have ref.eq == true with the original value

We may have some existing tests for eqref that could be coalesced with these.

[1] https://searchfox.org/mozilla-central/search?q=symbol:_ZNK2js4wasm10PackedType11refTypeKindEv&redirect=false

Blocks: 1784277
Blocks: 1784154

In preparation for adding new heap types, and therefore entries to RefType::Kind,
this commit replaces some switches on RefType::Kind with equivalent predicates
that won't require updating with each new heap type added.

Assignee: nobody → rhunt
Status: NEW → ASSIGNED

This commit adds the 'any' heap type.

Our type hierarchies are now:

anyref
  |
eqref  ------------
  |                \
(concrete structs) |
        (concrete arrays)

funcref
  |
(concrete funcs)

externref

anyref contains all of eqref in addition to any values that
are the result of extern.internalize. anyref is not allowed
to be used on the JS-Wasm so it is made to be not 'exposable'
which will ensure our stub functions handle it correctly.

Depends on D159788

This commit adds arrayref and structref, the super heap types of
all concrete arrays and structs (resp).

These new heap types are unexposable to JS like anyref.

This commit also updates the typing of array.len to accept any
arrayref:

array.len : [arrayref] -> i32

V8 implemented this by adding a new opcode and deprecating the
old one. We do the same, and will remove the old opcode when
we can.

Depends on D159790

Depends on D159777

Pushed by rhunt@eqrion.net: https://hg.mozilla.org/integration/autoland/rev/d742fcd792d0 Vendor in new wasm-tools crate versions. r=yury,supply-chain-reviewers https://hg.mozilla.org/integration/autoland/rev/dacfeb170af2 wasm: Remove some RefType::Kind switches as they're too general. r=jseward https://hg.mozilla.org/integration/autoland/rev/344893f8f016 wasm: Add anyref. r=jseward https://hg.mozilla.org/integration/autoland/rev/31a9bed122c0 wasm: Add structref and arrayref, updating array.len typing. r=jseward
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: