From af39b32154df6c755a83c54adeb91a198f16f96a Mon Sep 17 00:00:00 2001 From: Manos Koukoutos Date: Wed, 20 Jul 2022 05:05:57 +0000 Subject: [PATCH] [wasm-gc] Remove nominal types Some tests and testing infrastructure had to be changed because it relied on nominal types. Drive-by: Support function supertypes in wasm-module-builder.js. Bug: v8:7748 Change-Id: Ife92431d1842ff9de91e296a50421aa48f02c0de Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3776197 Reviewed-by: Jakob Kummerow Commit-Queue: Manos Koukoutos Cr-Commit-Position: refs/heads/main@{#81862} --- src/wasm/module-decoder-impl.h | 156 +++--------------- src/wasm/wasm-constants.h | 3 - .../regress/wasm/regress-inlining-throw.js | 1 - test/mjsunit/wasm/gc-nominal.js | 4 - test/mjsunit/wasm/gc-optimizations.js | 1 - test/mjsunit/wasm/load-immutable.js | 1 - .../wasm/runtime-type-canonicalization.js | 1 + test/mjsunit/wasm/wasm-module-builder.js | 81 +++------ .../unittests/wasm/module-decoder-unittest.cc | 134 +-------------- 9 files changed, 56 insertions(+), 326 deletions(-) diff --git a/src/wasm/module-decoder-impl.h b/src/wasm/module-decoder-impl.h index ace9d63708..06343d6c99 100644 --- a/src/wasm/module-decoder-impl.h +++ b/src/wasm/module-decoder-impl.h @@ -597,9 +597,6 @@ class ModuleDecoderTemplate : public Decoder { case kWasmFunctionTypeCode: return "func"; case kWasmStructTypeCode: return "struct"; case kWasmArrayTypeCode: return "array"; - case kWasmFunctionNominalCode: return "function-nominal"; - case kWasmStructNominalCode: return "struct-nominal"; - case kWasmArrayNominalCode: return "array-nominal"; default: return "unknown"; // clang-format on } @@ -622,13 +619,6 @@ class ModuleDecoderTemplate : public Decoder { const ArrayType* type = consume_array(module_->signature_zone.get()); return {type, kNoSuperType}; } - case kWasmFunctionNominalCode: - case kWasmArrayNominalCode: - case kWasmStructNominalCode: - tracer_.NextLine(); - errorf(pc() - 1, - "mixing nominal and isorecursive types is not allowed"); - return {}; default: tracer_.NextLine(); errorf(pc() - 1, "unknown type form: %d", kind); @@ -645,67 +635,6 @@ class ModuleDecoderTemplate : public Decoder { return true; } - TypeDefinition consume_nominal_type_definition() { - DCHECK(enabled_features_.has_gc()); - size_t num_types = module_->types.size(); - uint8_t kind = consume_u8(" kind: ", tracer_); - tracer_.Description(TypeKindName(kind)); - switch (kind) { - case kWasmFunctionNominalCode: { - const FunctionSig* sig = consume_sig(module_->signature_zone.get()); - uint32_t super_index = kNoSuperType; - HeapType super_type = consume_super_type(); - if (super_type.is_index()) { - super_index = super_type.representation(); - } else if (V8_UNLIKELY(super_type != HeapType::kFunc)) { - errorf(pc() - 1, "type %zu: invalid supertype %d", num_types, - super_type.code()); - return {}; - } - return {sig, super_index}; - } - case kWasmStructNominalCode: { - const StructType* type = consume_struct(module_->signature_zone.get()); - uint32_t super_index = kNoSuperType; - HeapType super_type = consume_super_type(); - if (super_type.is_index()) { - super_index = super_type.representation(); - } else if (V8_UNLIKELY(super_type != HeapType::kData)) { - errorf(pc() - 1, "type %zu: invalid supertype %d", num_types, - super_type.code()); - return {}; - } - return {type, super_index}; - } - case kWasmArrayNominalCode: { - const ArrayType* type = consume_array(module_->signature_zone.get()); - uint32_t super_index = kNoSuperType; - HeapType super_type = consume_super_type(); - if (super_type.is_index()) { - super_index = super_type.representation(); - } else if (V8_UNLIKELY(super_type != HeapType::kData)) { - errorf(pc() - 1, "type %zu: invalid supertype %d", num_types, - super_type.code()); - return {}; - } - return {type, super_index}; - } - case kWasmFunctionTypeCode: - case kWasmArrayTypeCode: - case kWasmStructTypeCode: - case kWasmSubtypeCode: - case kWasmRecursiveTypeGroupCode: - tracer_.NextLine(); - errorf(pc() - 1, - "mixing nominal and isorecursive types is not allowed"); - return {}; - default: - tracer_.NextLine(); - errorf(pc() - 1, "unknown type form: %d", kind); - return {}; - } - } - TypeDefinition consume_subtype_definition() { DCHECK(enabled_features_.has_gc()); uint8_t kind = read_u8(pc(), "type kind"); @@ -761,9 +690,6 @@ class ModuleDecoderTemplate : public Decoder { case kWasmStructTypeCode: case kWasmSubtypeCode: case kWasmRecursiveTypeGroupCode: - case kWasmFunctionNominalCode: - case kWasmStructNominalCode: - case kWasmArrayNominalCode: errorf( "Unknown type code 0x%02x, enable with --experimental-wasm-gc", opcode); @@ -777,62 +703,37 @@ class ModuleDecoderTemplate : public Decoder { return; } - if (types_count > 0) { - uint8_t first_type_opcode = this->read_u8(pc()); - if (first_type_opcode == kWasmFunctionNominalCode || - first_type_opcode == kWasmStructNominalCode || - first_type_opcode == kWasmArrayNominalCode) { - // wasm-gc nominal type section decoding. - // In a nominal module, all types belong in the same recursive group. We - // use the type vector's capacity to mark the end of the current - // recursive group. - module_->types.reserve(types_count); - for (uint32_t i = 0; ok() && i < types_count; ++i) { - TRACE("DecodeType[%d] module+%d\n", i, - static_cast(pc_ - start_)); + for (uint32_t i = 0; ok() && i < types_count; ++i) { + TRACE("DecodeType[%d] module+%d\n", i, static_cast(pc_ - start_)); + uint8_t kind = read_u8(pc(), "type kind"); + if (kind == kWasmRecursiveTypeGroupCode) { + consume_bytes(1, "rec. group definition", tracer_); + tracer_.NextLine(); + uint32_t group_size = + consume_count("recursive group size", kV8MaxWasmTypes); + if (module_->types.size() + group_size > kV8MaxWasmTypes) { + errorf(pc(), "Type definition count exceeds maximum %zu", + kV8MaxWasmTypes); + return; + } + // Reserve space for the current recursive group, so we are + // allowed to reference its elements. + module_->types.reserve(module_->types.size() + group_size); + for (uint32_t j = 0; j < group_size; j++) { tracer_.TypeOffset(pc_offset()); - TypeDefinition type = consume_nominal_type_definition(); + TypeDefinition type = consume_subtype_definition(); if (ok()) module_->add_type(type); } if (ok() && FLAG_wasm_type_canonicalization) { - type_canon->AddRecursiveGroup(module_.get(), types_count); + type_canon->AddRecursiveGroup(module_.get(), group_size); } } else { - // wasm-gc isorecursive type section decoding. - for (uint32_t i = 0; ok() && i < types_count; ++i) { - TRACE("DecodeType[%d] module+%d\n", i, - static_cast(pc_ - start_)); - uint8_t kind = read_u8(pc(), "type kind"); - if (kind == kWasmRecursiveTypeGroupCode) { - consume_bytes(1, "rec. group definition", tracer_); - tracer_.NextLine(); - uint32_t group_size = - consume_count("recursive group size", kV8MaxWasmTypes); - if (module_->types.size() + group_size > kV8MaxWasmTypes) { - errorf(pc(), "Type definition count exceeds maximum %zu", - kV8MaxWasmTypes); - return; - } - // Reserve space for the current recursive group, so we are - // allowed to reference its elements. - module_->types.reserve(module_->types.size() + group_size); - for (uint32_t j = 0; j < group_size; j++) { - tracer_.TypeOffset(pc_offset()); - TypeDefinition type = consume_subtype_definition(); - if (ok()) module_->add_type(type); - } - if (ok() && FLAG_wasm_type_canonicalization) { - type_canon->AddRecursiveGroup(module_.get(), group_size); - } - } else { - tracer_.TypeOffset(pc_offset()); - TypeDefinition type = consume_subtype_definition(); - if (ok()) { - module_->add_type(type); - if (FLAG_wasm_type_canonicalization) { - type_canon->AddRecursiveGroup(module_.get(), 1); - } - } + tracer_.TypeOffset(pc_offset()); + TypeDefinition type = consume_subtype_definition(); + if (ok()) { + module_->add_type(type); + if (FLAG_wasm_type_canonicalization) { + type_canon->AddRecursiveGroup(module_.get(), 1); } } } @@ -846,16 +747,11 @@ class ModuleDecoderTemplate : public Decoder { // {consume_super_type} has checked this. DCHECK_LT(explicit_super, module_->types.size()); int depth = GetSubtypingDepth(module, i); + DCHECK_GE(depth, 0); if (depth > static_cast(kV8MaxRttSubtypingDepth)) { errorf("type %d: subtyping depth is greater than allowed", i); continue; } - // TODO(7748): Replace this with a DCHECK once we reject inheritance - // cycles for nominal modules. - if (depth == -1) { - errorf("type %d: cyclic inheritance", i); - continue; - } if (!ValidSubtypeDefinition(i, explicit_super, module, module)) { errorf("type %d has invalid explicit supertype %d", i, explicit_super); continue; diff --git a/src/wasm/wasm-constants.h b/src/wasm/wasm-constants.h index e5b051370d..0cbc0cfabe 100644 --- a/src/wasm/wasm-constants.h +++ b/src/wasm/wasm-constants.h @@ -61,9 +61,6 @@ enum ValueTypeCode : uint8_t { constexpr uint8_t kWasmFunctionTypeCode = 0x60; constexpr uint8_t kWasmStructTypeCode = 0x5f; constexpr uint8_t kWasmArrayTypeCode = 0x5e; -constexpr uint8_t kWasmFunctionNominalCode = 0x5d; -constexpr uint8_t kWasmStructNominalCode = 0x5c; -constexpr uint8_t kWasmArrayNominalCode = 0x5b; constexpr uint8_t kWasmSubtypeCode = 0x50; constexpr uint8_t kWasmRecursiveTypeGroupCode = 0x4f; diff --git a/test/mjsunit/regress/wasm/regress-inlining-throw.js b/test/mjsunit/regress/wasm/regress-inlining-throw.js index bccc568334..821b392b4a 100644 --- a/test/mjsunit/regress/wasm/regress-inlining-throw.js +++ b/test/mjsunit/regress/wasm/regress-inlining-throw.js @@ -8,7 +8,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); var builder = new WasmModuleBuilder(); -builder.setNominal(); let supertype = builder.addStruct([makeField(kWasmI32, true)]); let subtype = builder.addStruct( [makeField(kWasmI32, true), makeField(kWasmI32, true)], supertype); diff --git a/test/mjsunit/wasm/gc-nominal.js b/test/mjsunit/wasm/gc-nominal.js index 0ac2909ccb..da1b020474 100644 --- a/test/mjsunit/wasm/gc-nominal.js +++ b/test/mjsunit/wasm/gc-nominal.js @@ -9,7 +9,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); (function TestNominalTypesBasic() { print(arguments.callee.name); var builder = new WasmModuleBuilder(); - builder.setNominal(); let struct1 = builder.addStruct([makeField(kWasmI32, true)]); let struct2 = builder.addStruct( [makeField(kWasmI32, true), makeField(kWasmI32, true)], struct1); @@ -39,7 +38,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); (function TestSubtypingDepthTooLarge() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); - builder.setNominal(); builder.addStruct([]); for (let i = 0; i < 32; i++) builder.addStruct([], i); assertThrows( @@ -50,7 +48,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); (function TestArrayNewDataStatic() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); - builder.setNominal(); builder.setEarlyDataCountSection(); let array_type_index = builder.addArray(kWasmI16, true); @@ -110,7 +107,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); (function TestArrayNewData() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); - builder.setNominal(); builder.setEarlyDataCountSection(); let array_type_index = builder.addArray(kWasmI16, true); diff --git a/test/mjsunit/wasm/gc-optimizations.js b/test/mjsunit/wasm/gc-optimizations.js index 344854d1cc..0ce775d8cb 100644 --- a/test/mjsunit/wasm/gc-optimizations.js +++ b/test/mjsunit/wasm/gc-optimizations.js @@ -363,7 +363,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); (function AllocationFolding() { print(arguments.callee.name); var builder = new WasmModuleBuilder(); - builder.setNominal(); let struct_index = builder.addStruct([makeField(kWasmI32, true)]); let struct_2 = builder.addStruct([ diff --git a/test/mjsunit/wasm/load-immutable.js b/test/mjsunit/wasm/load-immutable.js index 48f4add07f..89c6f223c4 100644 --- a/test/mjsunit/wasm/load-immutable.js +++ b/test/mjsunit/wasm/load-immutable.js @@ -77,7 +77,6 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); (function ImmutableLoadThroughEffect() { var builder = new WasmModuleBuilder(); - builder.setNominal(); var struct = builder.addStruct([ makeField(kWasmI32, false), makeField(kWasmI32, true)]); diff --git a/test/mjsunit/wasm/runtime-type-canonicalization.js b/test/mjsunit/wasm/runtime-type-canonicalization.js index dc89fed3c8..b5b2febe8f 100644 --- a/test/mjsunit/wasm/runtime-type-canonicalization.js +++ b/test/mjsunit/wasm/runtime-type-canonicalization.js @@ -7,6 +7,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); let builder = new WasmModuleBuilder(); +builder.setSingletonRecGroups(); let struct_index = builder.addStruct([makeField(kWasmI32, true)]); let identical_struct_index = builder.addStruct([makeField(kWasmI32, true)]); diff --git a/test/mjsunit/wasm/wasm-module-builder.js b/test/mjsunit/wasm/wasm-module-builder.js index a00b5eb98b..05dae5d541 100644 --- a/test/mjsunit/wasm/wasm-module-builder.js +++ b/test/mjsunit/wasm/wasm-module-builder.js @@ -79,9 +79,6 @@ let kLocalNamesCode = 2; let kWasmFunctionTypeForm = 0x60; let kWasmStructTypeForm = 0x5f; let kWasmArrayTypeForm = 0x5e; -let kWasmFunctionNominalForm = 0x5d; -let kWasmStructNominalForm = 0x5c; -let kWasmArrayNominalForm = 0x5b; let kWasmSubtypeForm = 0x50; let kWasmRecursiveTypeGroupForm = 0x4f; @@ -1265,7 +1262,11 @@ class WasmModuleBuilder { this.num_imported_globals = 0; this.num_imported_tables = 0; this.num_imported_tags = 0; - this.nominal = false; // Controls only how gc-modules are printed. + // If a wasm-gc type is detected, all types are put by default into a single + // recursive group. This field overrides this behavior and puts each type in + // a separate rec. group instead. + // TODO(7748): Support more flexible rec. groups. + this.singleton_rec_groups = false; this.early_data_count_section = false; return this; } @@ -1327,11 +1328,11 @@ class WasmModuleBuilder { // TODO(7748): Support recursive groups. - // TODO(7748): Support function supertypes. - addType(type) { - this.types.push(type); + addType(type, supertype_idx = kNoSuperType) { var pl = type.params.length; // should have params var rl = type.results.length; // should have results + type.supertype = supertype_idx; + this.types.push(type); return this.types.length - 1; } @@ -1592,8 +1593,8 @@ class WasmModuleBuilder { return this; } - setNominal() { - this.nominal = true; + setSingletonRecGroups() { + this.singleton_rec_groups = true; } setEarlyDataCountSection() { @@ -1616,54 +1617,35 @@ class WasmModuleBuilder { if (wasm.types.length > 0) { if (debug) print('emitting types @ ' + binary.length); binary.emit_section(kTypeSectionCode, section => { + // If any type is a wasm-gc type, wrap everything in a recursive group. + // TODO(7748): Support more flexible rec. groups. + if (!this.singleton_rec_groups && + wasm.types.findIndex(type => type instanceof WasmStruct || + type instanceof WasmArray) >= 0) { + section.emit_u32v(1); + section.emit_u8(kWasmRecursiveTypeGroupForm); + } section.emit_u32v(wasm.types.length); + for (let type of wasm.types) { + if (type.supertype != kNoSuperType) { + section.emit_u8(kWasmSubtypeForm); + section.emit_u8(1); // supertype count + section.emit_u32v(type.supertype); + } if (type instanceof WasmStruct) { - if (!this.nominal && type.supertype != kNoSuperType) { - section.emit_u8(kWasmSubtypeForm); - section.emit_u8(1); // supertype count - section.emit_u32v(type.supertype); - } - section.emit_u8(this.nominal ? kWasmStructNominalForm - : kWasmStructTypeForm); + section.emit_u8(kWasmStructTypeForm); section.emit_u32v(type.fields.length); for (let field of type.fields) { section.emit_type(field.type); section.emit_u8(field.mutability ? 1 : 0); } - if (this.nominal) { - if (type.supertype === kNoSuperType) { - section.emit_u8(kDataRefCode); - } else { - section.emit_heap_type(type.supertype); - } - } } else if (type instanceof WasmArray) { - if (!this.nominal && type.supertype != kNoSuperType) { - section.emit_u8(kWasmSubtypeForm); - section.emit_u8(1); // supertype count - section.emit_u32v(type.supertype); - } - section.emit_u8(this.nominal ? kWasmArrayNominalForm - : kWasmArrayTypeForm); + section.emit_u8(kWasmArrayTypeForm); section.emit_type(type.type); section.emit_u8(type.mutability ? 1 : 0); - if (this.nominal) { - if (type.supertype === kNoSuperType) { - section.emit_u8(kDataRefCode); - } else { - section.emit_heap_type(type.supertype); - } - } } else { - /* TODO(7748): Support function supertypes. - if (!this.nominal && type.supertype != kNoSuperType) { - section.emit_u8(kWasmSubtypeForm); - section.emit_u8(1); // supertype count - section.emit_u32v(type.supertype); - } */ - section.emit_u8(this.nominal ? kWasmFunctionNominalForm - : kWasmFunctionTypeForm); + section.emit_u8(kWasmFunctionTypeForm); section.emit_u32v(type.params.length); for (let param of type.params) { section.emit_type(param); @@ -1672,15 +1654,6 @@ class WasmModuleBuilder { for (let result of type.results) { section.emit_type(result); } - if (this.nominal) { - /* TODO(7748): Support function supertypes. - if (type.supertype === kNoSuperType) { - section.emit_u8(kFuncRefCode); - } else { - section.emit_heap_type(type.supertype); - }*/ - section.emit_u8(kFuncRefCode); - } } } }); diff --git a/test/unittests/wasm/module-decoder-unittest.cc b/test/unittests/wasm/module-decoder-unittest.cc index 51390ef121..4943bfe85a 100644 --- a/test/unittests/wasm/module-decoder-unittest.cc +++ b/test/unittests/wasm/module-decoder-unittest.cc @@ -857,13 +857,13 @@ TEST_F(WasmModuleVerifyTest, ArrayNewFixedInitExpr) { 0, 3, WASM_I32V(10), WASM_I32V(20), WASM_I32V(30)))}; EXPECT_VERIFIES(basic); - static const byte basic_nominal[] = { + static const byte basic_static[] = { SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI16Code, true)), SECTION(Global, ENTRY_COUNT(1), // -- kRefCode, 0, 0, // type, mutability WASM_INIT_EXPR_ARRAY_NEW_FIXED_STATIC( 0, 3, WASM_I32V(10), WASM_I32V(20), WASM_I32V(30)))}; - EXPECT_VERIFIES(basic_nominal); + EXPECT_VERIFIES(basic_static); static const byte basic_immutable[] = { SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI32Code, false)), @@ -987,136 +987,6 @@ TEST_F(WasmModuleVerifyTest, InvalidStructTypeDef) { EXPECT_FAILURE_WITH_MSG(invalid_mutability, "invalid mutability"); } -TEST_F(WasmModuleVerifyTest, NominalStructTypeDef) { - WASM_FEATURE_SCOPE(typed_funcref); - WASM_FEATURE_SCOPE(gc); - - // Inheritance: t1 <: t2 <: t0 - static const byte all_good[] = { - SECTION(Type, ENTRY_COUNT(3), // -- - kWasmStructNominalCode, // type #0 - 1, // field count - kI32Code, 1, // mut i32 - kDataRefCode, // root of type hierarchy - - kWasmStructNominalCode, // type #1 - 2, // field count - kI32Code, 1, // mut i32 (inherited) - kI64Code, 1, // mut i32 (added) - 2, // supertype - - kWasmStructNominalCode, // type #2 - 1, // field count - kI32Code, 1, // mut i32 (inherited) - 0)}; // supertype - EXPECT_VERIFIES(all_good); - ModuleResult result = DecodeModule(all_good, all_good + sizeof(all_good)); - EXPECT_OK(result); - WasmModule* module = result.value().get(); - EXPECT_EQ(kNoSuperType, module->supertype(0)); - EXPECT_EQ(2u, module->supertype(1)); - EXPECT_EQ(0u, module->supertype(2)); - - static const byte self_or_mutual_ref[] = { - SECTION(Type, ENTRY_COUNT(4), // -- - kWasmStructNominalCode, 0, // empty struct - kDataRefCode, // root of hierarchy - - kWasmStructNominalCode, // type1 - 1, // field count - kRefNullCode, 1, 1, // mut (ref null type1) - 0, // supertype - - kWasmStructNominalCode, // type 2 - 1, // field count - kRefNullCode, 3, 1, // mut (ref null type3) - 0, // supertype - - kWasmStructNominalCode, // type 3 - 1, // field count - kRefNullCode, 2, 1, // mut (ref null type2) - 0)}; // supertype - EXPECT_VERIFIES(self_or_mutual_ref); - - static const byte mutual_ref_with_subtyping[] = { - SECTION(Type, - ENTRY_COUNT(3), // -- - kWasmStructNominalCode, // - 1, // field count - kRefNullCode, 0, 0, // ref type0 - kDataRefCode, // root of hierarchy - - kWasmStructNominalCode, // -- - 1, // field count - kRefNullCode, 2, 0, // ref type2 - 0, // supertype - - kWasmStructNominalCode, // -- - 1, // field count - kRefNullCode, 1, 0, // ref type1 - 0)}; // supertype - EXPECT_VERIFIES(mutual_ref_with_subtyping); - - static const byte inheritance_cycle[] = { - SECTION(Type, ENTRY_COUNT(2), // -- - kWasmStructNominalCode, 0, 1, // no fields, supertype 1 - kWasmStructNominalCode, 0, 0)}; // no fields, supertype 0 - EXPECT_FAILURE_WITH_MSG(inheritance_cycle, "cyclic inheritance"); - - static const byte invalid_field[] = { - SECTION(Type, ENTRY_COUNT(2), // -- - kWasmStructTypeCode, U32V_1(1), kI32Code, 1, // t0: [i32] - kWasmStructNominalCode, U32V_1(2), // t1: - kI64Code, 1, // i64 (invalid inheritance) - kI32Code, 1, U32V_1(0))}; // i32 (added), supertype 0 - EXPECT_FAILURE_WITH_MSG( - invalid_field, "mixing nominal and isorecursive types is not allowed"); - - static const byte structural_supertype[] = { - SECTION(Type, ENTRY_COUNT(2), // -- - kWasmStructTypeCode, 0, // empty struct - kWasmStructNominalCode, 0, // also empty - 0)}; // supertype is structural type - EXPECT_FAILURE_WITH_MSG( - structural_supertype, - "mixing nominal and isorecursive types is not allowed"); - - static const byte supertype_oob[] = { - SECTION(Type, ENTRY_COUNT(1), // -- - kWasmStructNominalCode, - 0, // empty struct - 13)}; // supertype with invalid index - EXPECT_FAILURE_WITH_MSG(supertype_oob, "Type index 13 is out of bounds"); -} - -TEST_F(WasmModuleVerifyTest, NominalFunctionTypeDef) { - WASM_FEATURE_SCOPE(typed_funcref); - WASM_FEATURE_SCOPE(gc); - EXPERIMENTAL_FLAG_SCOPE(gc); // Needed for subtype checking. - - static const byte all_good[] = { - SECTION(Type, ENTRY_COUNT(2), // -- - kWasmFunctionNominalCode, // type #0 - 1, // params count - kRefCode, 0, // ref #0 - 1, // results count - kRefNullCode, 0, // (ref null 0) - kFuncRefCode, // root of type hierarchy - - kWasmFunctionNominalCode, // type #1 - 1, // params count - kRefNullCode, 0, // refined (contravariant) - 1, // results count - kRefCode, 0, // refined (covariant) - 0)}; // supertype - EXPECT_VERIFIES(all_good); - ModuleResult result = DecodeModule(all_good, all_good + sizeof(all_good)); - EXPECT_OK(result); - WasmModule* module = result.value().get(); - EXPECT_EQ(kNoSuperType, module->supertype(0)); - EXPECT_EQ(0u, module->supertype(1)); -} - TEST_F(WasmModuleVerifyTest, InvalidArrayTypeDef) { WASM_FEATURE_SCOPE(typed_funcref); WASM_FEATURE_SCOPE(gc);