Skip to content

Commit

Permalink
[Wasm-GC] Add support for final attribute
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=250107

Reviewed by Justin Michaud.

Adds support for `final` attribute on `sub` types. This enables types to be
marked final, in which case they cannot be inherited from. This changes the
default for shorthands like `struct` to be final.

As a result, the representation of subtypes needs to change to allow 0 or 1
supertypes (previously, 0 supertype subs were normalized to not using a Subtype
constructor). To accommodate this, the representation is changed to allow
an arbitrary number of supertypes (though restricted to 0 or 1 in practice).

This patch also fixes some additional bugs found in related code, such as a
missing subtype check for certain kinds of `rec` types and fixing a case where
type indices were resolved too early in array operation validation.

In addition to tests for final attributes, this patch updates tests where the a
new `sub` is needed due to changes in default finality. It also updates GC spec
tests where needed to the version in commit
c7de5a1c1e261808a0c7744177589f6eb25da145 of the GC proposal repo.

* JSTests/wasm/gc-spec-tests/ref_cast.wast.js:
* JSTests/wasm/gc-spec-tests/type-subtyping.wast.js:
* JSTests/wasm/gc/arrays.js:
(testArrayNewDefault):
(testArrayGet):
* JSTests/wasm/gc/bug247874.js:
(i.instantiate.module.type.struct.type.sub.0.struct.field.i32.global.import.string_appeared_here.string_appeared_here): Deleted.
* JSTests/wasm/gc/casts.js:
(testSubtypeCasts):
* JSTests/wasm/gc/structs.js:
(testStructNewDefault):
* JSTests/wasm/gc/sub.js:
(testSubDeclaration):
* JSTests/wasm/wasm.json:
* Source/JavaScriptCore/wasm/WasmBBQJIT.cpp:
(JSC::Wasm::BBQJIT::sizeOfType):
(JSC::Wasm::BBQJIT::toValueKind):
(JSC::Wasm::BBQJIT::getGlobal):
(JSC::Wasm::BBQJIT::setGlobal):
(JSC::Wasm::BBQJIT::addTopLevel):
(JSC::Wasm::BBQJIT::emitCatchImpl):
(JSC::Wasm::BBQJIT::emitCCall):
* Source/JavaScriptCore/wasm/WasmCallingConvention.h:
(JSC::Wasm::WasmCallingConvention::numberOfStackResults const):
(JSC::Wasm::WasmCallingConvention::numberOfStackArguments const):
* Source/JavaScriptCore/wasm/WasmFormat.h:
(JSC::Wasm::arrayrefType):
* Source/JavaScriptCore/wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parseArrayTypeDefinition):
* Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp:
(JSC::Wasm::LLIntGenerator::callInformationForCaller):
(JSC::Wasm::LLIntGenerator::callInformationForCallee):
(JSC::Wasm::LLIntGenerator::addArguments):
* Source/JavaScriptCore/wasm/WasmSectionParser.cpp:
(JSC::Wasm::SectionParser::parseType):
(JSC::Wasm::SectionParser::parseRecursionGroup):
(JSC::Wasm::SectionParser::checkSubtypeValidity):
(JSC::Wasm::SectionParser::parseSubtype):
* Source/JavaScriptCore/wasm/WasmSectionParser.h:
* Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp:
(JSC::Wasm::Subtype::dump const):
(JSC::Wasm::Subtype::cleanup):
(JSC::Wasm::computeSubtypeHash):
(JSC::Wasm::TypeDefinition::hash const):
(JSC::Wasm::TypeDefinition::tryCreateSubtype):
(JSC::Wasm::TypeDefinition::replacePlaceholders const):
(JSC::Wasm::TypeDefinition::hasRecursiveReference const):
(JSC::Wasm::TypeInformation::signatureForLLIntBuiltin):
(JSC::Wasm::SubtypeParameterTypes::hash):
(JSC::Wasm::SubtypeParameterTypes::equal):
(JSC::Wasm::SubtypeParameterTypes::translate):
(JSC::Wasm::TypeInformation::TypeInformation):
(JSC::Wasm::TypeInformation::typeDefinitionForSubtype):
(JSC::Wasm::TypeInformation::canonicalRTTForType):
* Source/JavaScriptCore/wasm/WasmTypeDefinition.h:
(JSC::Wasm::typeKindSizeInBytes):
(JSC::Wasm::Subtype::Subtype):
(JSC::Wasm::Subtype::supertypeCount const):
(JSC::Wasm::Subtype::isFinal const):
(JSC::Wasm::Subtype::firstSuperType const):
(JSC::Wasm::Subtype::superType const):
(JSC::Wasm::Subtype::getSuperType):
(JSC::Wasm::TypeDefinition::TypeDefinition):
* Source/JavaScriptCore/wasm/js/JSWebAssemblyStruct.cpp:
(JSC::JSWebAssemblyStruct::set):
* Source/JavaScriptCore/wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):
* Source/JavaScriptCore/wasm/wasm.json:

Canonical link: https://commits.webkit.org/266890@main
  • Loading branch information
takikawa committed Aug 15, 2023
1 parent 9544bcf commit b8f9d49
Show file tree
Hide file tree
Showing 20 changed files with 581 additions and 197 deletions.
2 changes: 1 addition & 1 deletion JSTests/wasm/gc-spec-tests/ref_cast.wast.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ assert_trap(() => call($1, "ref_cast_array", [6]));
assert_trap(() => call($1, "ref_cast_array", [7]));

// ref_cast.wast:99
let $2 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\xbd\x80\x80\x80\x00\x09\x5f\x00\x50\x01\x00\x5f\x01\x7f\x00\x50\x01\x00\x5f\x01\x7f\x00\x50\x01\x01\x5f\x02\x7f\x00\x7f\x00\x50\x01\x02\x5f\x02\x7f\x00\x7f\x00\x50\x01\x00\x5f\x02\x7f\x00\x7f\x00\x50\x01\x00\x5f\x00\x50\x01\x06\x5f\x02\x7f\x00\x7f\x00\x60\x00\x00\x03\x84\x80\x80\x80\x00\x03\x08\x08\x08\x04\x84\x80\x80\x80\x00\x01\x67\x00\x14\x07\x99\x80\x80\x80\x00\x02\x08\x74\x65\x73\x74\x2d\x73\x75\x62\x00\x01\x0a\x74\x65\x73\x74\x2d\x63\x61\x6e\x6f\x6e\x00\x02\x0a\xfa\x82\x80\x80\x00\x03\xba\x80\x80\x80\x00\x00\x41\x00\xfb\x02\x00\x26\x00\x41\x0a\xfb\x02\x00\x26\x00\x41\x01\xfb\x02\x01\x26\x00\x41\x0b\xfb\x02\x02\x26\x00\x41\x02\xfb\x02\x03\x26\x00\x41\x0c\xfb\x02\x04\x26\x00\x41\x03\xfb\x02\x05\x26\x00\x41\x04\xfb\x02\x07\x26\x00\x0b\xbc\x81\x80\x80\x00\x00\x10\x00\xd0\x67\xfb\x49\x00\x1a\x41\x00\x25\x00\xfb\x49\x00\x1a\x41\x01\x25\x00\xfb\x49\x00\x1a\x41\x02\x25\x00\xfb\x49\x00\x1a\x41\x03\x25\x00\xfb\x49\x00\x1a\x41\x04\x25\x00\xfb\x49\x00\x1a\xd0\x67\xfb\x49\x00\x1a\x41\x01\x25\x00\xfb\x49\x01\x1a\x41\x02\x25\x00\xfb\x49\x01\x1a\xd0\x67\xfb\x49\x00\x1a\x41\x02\x25\x00\xfb\x49\x03\x1a\xd0\x67\xfb\x49\x00\x1a\x41\x03\x25\x00\xfb\x49\x05\x1a\x41\x04\x25\x00\xfb\x49\x07\x1a\x41\x00\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x00\x1a\x41\x02\x25\x00\xfb\x41\x00\x1a\x41\x03\x25\x00\xfb\x41\x00\x1a\x41\x04\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x01\x1a\x41\x02\x25\x00\xfb\x41\x01\x1a\x41\x02\x25\x00\xfb\x41\x03\x1a\x41\x03\x25\x00\xfb\x41\x05\x1a\x41\x04\x25\x00\xfb\x41\x07\x1a\x0b\xf4\x80\x80\x80\x00\x00\x10\x00\x41\x00\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x00\x1a\x41\x02\x25\x00\xfb\x41\x00\x1a\x41\x03\x25\x00\xfb\x41\x00\x1a\x41\x04\x25\x00\xfb\x41\x00\x1a\x41\x0a\x25\x00\xfb\x41\x00\x1a\x41\x0b\x25\x00\xfb\x41\x00\x1a\x41\x0c\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x02\x1a\x41\x02\x25\x00\xfb\x41\x02\x1a\x41\x0b\x25\x00\xfb\x41\x01\x1a\x41\x0c\x25\x00\xfb\x41\x01\x1a\x41\x02\x25\x00\xfb\x41\x04\x1a\x41\x0c\x25\x00\xfb\x41\x03\x1a\x0b");
let $2 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\xbf\x80\x80\x80\x00\x09\x50\x00\x5f\x00\x50\x01\x00\x5f\x01\x7f\x00\x50\x01\x00\x5f\x01\x7f\x00\x50\x01\x01\x5f\x02\x7f\x00\x7f\x00\x50\x01\x02\x5f\x02\x7f\x00\x7f\x00\x50\x01\x00\x5f\x02\x7f\x00\x7f\x00\x50\x01\x00\x5f\x00\x50\x01\x06\x5f\x02\x7f\x00\x7f\x00\x60\x00\x00\x03\x84\x80\x80\x80\x00\x03\x08\x08\x08\x04\x84\x80\x80\x80\x00\x01\x67\x00\x14\x07\x99\x80\x80\x80\x00\x02\x08\x74\x65\x73\x74\x2d\x73\x75\x62\x00\x01\x0a\x74\x65\x73\x74\x2d\x63\x61\x6e\x6f\x6e\x00\x02\x0a\xfa\x82\x80\x80\x00\x03\xba\x80\x80\x80\x00\x00\x41\x00\xfb\x02\x00\x26\x00\x41\x0a\xfb\x02\x00\x26\x00\x41\x01\xfb\x02\x01\x26\x00\x41\x0b\xfb\x02\x02\x26\x00\x41\x02\xfb\x02\x03\x26\x00\x41\x0c\xfb\x02\x04\x26\x00\x41\x03\xfb\x02\x05\x26\x00\x41\x04\xfb\x02\x07\x26\x00\x0b\xbc\x81\x80\x80\x00\x00\x10\x00\xd0\x67\xfb\x49\x00\x1a\x41\x00\x25\x00\xfb\x49\x00\x1a\x41\x01\x25\x00\xfb\x49\x00\x1a\x41\x02\x25\x00\xfb\x49\x00\x1a\x41\x03\x25\x00\xfb\x49\x00\x1a\x41\x04\x25\x00\xfb\x49\x00\x1a\xd0\x67\xfb\x49\x00\x1a\x41\x01\x25\x00\xfb\x49\x01\x1a\x41\x02\x25\x00\xfb\x49\x01\x1a\xd0\x67\xfb\x49\x00\x1a\x41\x02\x25\x00\xfb\x49\x03\x1a\xd0\x67\xfb\x49\x00\x1a\x41\x03\x25\x00\xfb\x49\x05\x1a\x41\x04\x25\x00\xfb\x49\x07\x1a\x41\x00\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x00\x1a\x41\x02\x25\x00\xfb\x41\x00\x1a\x41\x03\x25\x00\xfb\x41\x00\x1a\x41\x04\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x01\x1a\x41\x02\x25\x00\xfb\x41\x01\x1a\x41\x02\x25\x00\xfb\x41\x03\x1a\x41\x03\x25\x00\xfb\x41\x05\x1a\x41\x04\x25\x00\xfb\x41\x07\x1a\x0b\xf4\x80\x80\x80\x00\x00\x10\x00\x41\x00\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x00\x1a\x41\x02\x25\x00\xfb\x41\x00\x1a\x41\x03\x25\x00\xfb\x41\x00\x1a\x41\x04\x25\x00\xfb\x41\x00\x1a\x41\x0a\x25\x00\xfb\x41\x00\x1a\x41\x0b\x25\x00\xfb\x41\x00\x1a\x41\x0c\x25\x00\xfb\x41\x00\x1a\x41\x01\x25\x00\xfb\x41\x02\x1a\x41\x02\x25\x00\xfb\x41\x02\x1a\x41\x0b\x25\x00\xfb\x41\x01\x1a\x41\x0c\x25\x00\xfb\x41\x01\x1a\x41\x02\x25\x00\xfb\x41\x04\x1a\x41\x0c\x25\x00\xfb\x41\x03\x1a\x0b");

// ref_cast.wast:185
run(() => call($2, "test-sub", []));
Expand Down
306 changes: 271 additions & 35 deletions JSTests/wasm/gc-spec-tests/type-subtyping.wast.js

Large diffs are not rendered by default.

29 changes: 23 additions & 6 deletions JSTests/wasm/gc/arrays.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function testArrayNew() {
instantiate(`
(module
;; Test with subtype as well.
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(func (result (ref 0))
(array.new 1 (i32.const 42) (i32.const 5)))
Expand All @@ -157,7 +157,7 @@ function testArrayNewDefault() {
instantiate(`
(module
;; Test with subtype as well.
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(func (result (ref 0))
(array.new_default 1 (i32.const 5)))
Expand All @@ -183,7 +183,7 @@ function testArrayGet() {
let m = instantiate(`
(module
;; Test with a subtype as well.
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(func (export "f") (result i32)
(array.new 1 (i32.const 0) (i32.const 5))
Expand Down Expand Up @@ -371,12 +371,12 @@ function testArraySet() {
let m = instantiate(`
(module
;; Test with a subtype as well.
(type (array (mut i32)))
(type (sub (array (mut i32))))
(type (sub 0 (array (mut i32))))
(global (mut (ref null 0)) (ref.null 0))
(global (mut (ref null 1)) (ref.null 1))
(func (export "init")
(global.set 0 (array.new 1 (i32.const 42) (i32.const 5)))
(array.set 1 (global.get 0) (i32.const 3) (i32.const 84)))
(array.set 0 (global.get 0) (i32.const 3) (i32.const 84)))
(func (export "get") (param i32) (result i32)
(array.get 1 (global.get 0) (local.get 0)))
)
Expand All @@ -386,6 +386,23 @@ function testArraySet() {
assert.eq(m.exports.get(3), 84);
}

// Should fail because the array type in the global (index 0) isn't a subtype of the
// type of the array.set index (index 1).
assert.throws(
() => compile(`
(module
(type (sub (array (mut i32))))
(type (sub 0 (array (mut i32))))
(global (mut (ref null 0)) (ref.null 0))
(func (export "init")
(global.set 0 (array.new 1 (i32.const 42) (i32.const 5)))
(array.set 1 (global.get 0) (i32.const 3) (i32.const 84)))
)
`),
WebAssembly.CompileError,
"WebAssembly.Module doesn't validate: array.set arrayref to type ((I32, immutable)) expected arrayref, in function at index 0"
);

{
let m = instantiate(`
(module
Expand Down
4 changes: 2 additions & 2 deletions JSTests/wasm/gc/bug247874.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ for (let i = 0; i < 10; i++) {
instantiate(`(module (type (func)))`);
let m1 = instantiate(`
(module
(type (struct))
(type (sub (struct)))
(type (sub 0 (struct (field i32))))
(global (export "g") (ref null 1) (ref.null 1))
)
`);
instantiate(`
(module
(type (struct))
(type (sub (struct)))
(type (sub 0 (struct (field i32))))
(global (import "m" "g") (ref null 1))
)
Expand Down
20 changes: 10 additions & 10 deletions JSTests/wasm/gc/casts.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ function testStructCasts() {
function testSubtypeCasts() {
instantiate(`
(module
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(start 1)
(func (param arrayref)
Expand All @@ -528,7 +528,7 @@ function testSubtypeCasts() {
assert.eq(
instantiate(`
(module
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(func (param arrayref) (result i32)
(ref.test (ref 0) (local.get 0)))
Expand All @@ -540,7 +540,7 @@ function testSubtypeCasts() {

instantiate(`
(module
(type (struct (field i32)))
(type (sub (struct (field i32))))
(type (sub 0 (struct (field i32) (field i64))))
(start 1)
(func (param structref)
Expand All @@ -552,7 +552,7 @@ function testSubtypeCasts() {
assert.eq(
instantiate(`
(module
(type (struct (field i32)))
(type (sub (struct (field i32))))
(type (sub 0 (struct (field i32) (field i64))))
(func (param structref) (result i32)
(ref.test (ref 0) (local.get 0)))
Expand All @@ -564,7 +564,7 @@ function testSubtypeCasts() {

instantiate(`
(module
(type (func (result i32)))
(type (sub (func (result i32))))
(type (sub 0 (func (result i32))))
(elem declare funcref (ref.func 0))
(start 2)
Expand All @@ -578,7 +578,7 @@ function testSubtypeCasts() {
assert.eq(
instantiate(`
(module
(type (func (result i32)))
(type (sub (func (result i32))))
(type (sub 0 (func (result i32))))
(elem declare funcref (ref.func 0))
(func (type 1) (i32.const 42))
Expand All @@ -593,7 +593,7 @@ function testSubtypeCasts() {
assert.throws(
() => instantiate(`
(module
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(start 1)
(func (param arrayref)
Expand All @@ -608,7 +608,7 @@ function testSubtypeCasts() {
assert.eq(
instantiate(`
(module
(type (array i32))
(type (sub (array i32)))
(type (sub 0 (array i32)))
(func (param arrayref) (result i32)
(ref.test (ref 1) (local.get 0)))
Expand All @@ -621,7 +621,7 @@ function testSubtypeCasts() {
assert.throws(
() => instantiate(`
(module
(type (func (result i32)))
(type (sub (func (result i32))))
(type (sub 0 (func (result i32))))
(elem declare funcref (ref.func 0))
(start 2)
Expand All @@ -638,7 +638,7 @@ function testSubtypeCasts() {
assert.eq(
instantiate(`
(module
(type (func (result i32)))
(type (sub (func (result i32))))
(type (sub 0 (func (result i32))))
(elem declare funcref (ref.func 0))
(func (type 0) (i32.const 42))
Expand Down
10 changes: 5 additions & 5 deletions JSTests/wasm/gc/structs.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ function testStructNew() {
instantiate(`
(module
;; Also test with subtype.
(type (struct))
(type (sub (struct)))
(type $Empty (sub 0 (struct)))
(func (export "main")
(drop
Expand Down Expand Up @@ -296,7 +296,7 @@ function testStructNewDefault() {
instantiate(`
(module
;; Also test with subtype.
(type (struct))
(type (sub (struct)))
(type $Empty (sub 0 (struct)))
(func (export "main")
(drop
Expand Down Expand Up @@ -412,7 +412,7 @@ function testStructGet() {
let main = instantiate(`
(module
;; Test subtype case as well.
(type (struct (field i32)))
(type (sub (struct (field i32))))
(type $Point (sub 0 (struct (field $x i32))))
(func (export "main") (result i32)
(struct.get $Point $x
Expand Down Expand Up @@ -799,7 +799,7 @@ function testStructSet() {
let main = instantiate(`
(module
;; Test subtype case as well.
(type (struct (field (mut i32))))
(type (sub (struct (field (mut i32)))))
(type $Point (sub 0 (struct (field $x (mut i32)))))
(func $doTest (param $p (ref $Point)) (result i32)
(struct.set $Point $x
Expand All @@ -825,7 +825,7 @@ function testStructSet() {
{
let main = instantiate(`
(module
(type $Point (struct (field $x (mut i32))))
(type $Point (sub (struct (field $x (mut i32)))))
(type $Sub (sub 0 (struct (field (mut i32) (mut i32)))))
(func $doTest (result i32) (local $p (ref null $Sub))
(local.set $p (struct.new $Sub (i32.const 0) (i32.const 1)))
Expand Down
Loading

0 comments on commit b8f9d49

Please sign in to comment.