Commit 3720f905 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-gc] Fix: externref is not a subtype of eqref

Bug: v8:7748
Change-Id: I30eb7b08b40159e399730eef5866e1f0fbf706e1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2299368
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68892}
parent b09ed9f3
......@@ -100,7 +100,7 @@ class HeapType {
return !is_bottom() && representation_ >= kFirstSentinel;
}
constexpr bool is_index() const { return !is_bottom() && !is_generic(); }
constexpr bool is_index() const { return representation_ < kFirstSentinel; }
constexpr bool is_bottom() const { return representation_ == kBottom; }
......
......@@ -151,9 +151,9 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsSubtypeOfImpl(ValueType subtype,
if (sub_heap == super_heap) {
return true;
}
// eqref is a supertype of all reference types except funcref.
// eqref is a supertype of i31ref and all custom types.
if (super_heap.representation() == HeapType::kEq) {
return sub_heap.representation() != HeapType::kFunc;
return (sub_heap.is_index() || sub_heap.representation() == HeapType::kI31);
}
// At the moment, generic heap types are not subtyping-related otherwise.
if (sub_heap.is_generic() || super_heap.is_generic()) {
......
......@@ -3417,12 +3417,8 @@ TEST_F(FunctionBodyDecoderTest, RefEq) {
TestModuleBuilder builder;
module = builder.module();
byte struct_type_index = builder.AddStruct({F(kWasmI32, true)});
ValueType eqref_subtypes[] = {kWasmExnRef,
kWasmExternRef,
kWasmEqRef,
ValueType eqref_subtypes[] = {kWasmEqRef,
kWasmI31Ref,
ValueType::Ref(HeapType::kExn, kNonNullable),
ValueType::Ref(HeapType::kExtern, kNonNullable),
ValueType::Ref(HeapType::kEq, kNonNullable),
ValueType::Ref(HeapType::kI31, kNullable),
ref(struct_type_index),
......@@ -3433,7 +3429,11 @@ TEST_F(FunctionBodyDecoderTest, RefEq) {
kWasmF32,
kWasmF64,
kWasmS128,
kWasmExnRef,
kWasmExternRef,
kWasmFuncRef,
ValueType::Ref(HeapType::kExn, kNonNullable),
ValueType::Ref(HeapType::kExtern, kNonNullable),
ValueType::Ref(HeapType::kFunc, kNonNullable)};
for (ValueType type1 : eqref_subtypes) {
......
......@@ -667,11 +667,11 @@ TEST_F(WasmModuleVerifyTest, GlobalRttSubOfCanon) {
WASM_FEATURE_SCOPE(typed_funcref);
WASM_FEATURE_SCOPE(gc);
static const byte data[] = {SECTION(
Global, ENTRY_COUNT(1), WASM_RTT(2, kLocalExternRef), 1,
WASM_RTT_CANON(kLocalEqRef), WASM_RTT_SUB(kLocalExternRef), kExprEnd)};
Global, ENTRY_COUNT(1), WASM_RTT(2, kLocalI31Ref), 1,
WASM_RTT_CANON(kLocalEqRef), WASM_RTT_SUB(kLocalI31Ref), kExprEnd)};
ModuleResult result = DecodeModule(data, data + sizeof(data));
WasmInitExpr expected = WasmInitExpr::RttSub(
HeapType::kExtern, WasmInitExpr::RttCanon(HeapType::kEq));
HeapType::kI31, WasmInitExpr::RttCanon(HeapType::kEq));
EXPECT_OK(result);
EXPECT_EQ(result.value()->globals.front().init, expected);
}
......@@ -681,14 +681,13 @@ TEST_F(WasmModuleVerifyTest, GlobalRttSubOfSubOfCanon) {
WASM_FEATURE_SCOPE(typed_funcref);
WASM_FEATURE_SCOPE(gc);
static const byte data[] = {
SECTION(Global, ENTRY_COUNT(1), WASM_RTT(3, kLocalExternRef), 1,
WASM_RTT_CANON(kLocalEqRef), WASM_RTT_SUB(kLocalExternRef),
WASM_RTT_SUB(kLocalExternRef), kExprEnd)};
SECTION(Global, ENTRY_COUNT(1), WASM_RTT(3, kLocalEqRef), 1,
WASM_RTT_CANON(kLocalEqRef), WASM_RTT_SUB(kLocalEqRef),
WASM_RTT_SUB(kLocalEqRef), kExprEnd)};
ModuleResult result = DecodeModule(data, data + sizeof(data));
WasmInitExpr expected = WasmInitExpr::RttSub(
HeapType::kExtern,
WasmInitExpr::RttSub(HeapType::kExtern,
WasmInitExpr::RttCanon(HeapType::kEq)));
HeapType::kEq, WasmInitExpr::RttSub(
HeapType::kEq, WasmInitExpr::RttCanon(HeapType::kEq)));
EXPECT_OK(result);
EXPECT_EQ(result.value()->globals.front().init, expected);
}
......@@ -705,11 +704,11 @@ TEST_F(WasmModuleVerifyTest, GlobalRttSubOfGlobal) {
kExternalGlobal, // import kind
WASM_RTT(1, kLocalEqRef), // type
0), // mutability
SECTION(Global, ENTRY_COUNT(1), WASM_RTT(2, kLocalExternRef), 1,
WASM_GET_GLOBAL(0), WASM_RTT_SUB(kLocalExternRef), kExprEnd)};
SECTION(Global, ENTRY_COUNT(1), WASM_RTT(2, kLocalI31Ref), 1,
WASM_GET_GLOBAL(0), WASM_RTT_SUB(kLocalI31Ref), kExprEnd)};
ModuleResult result = DecodeModule(data, data + sizeof(data));
WasmInitExpr expected =
WasmInitExpr::RttSub(HeapType::kExtern, WasmInitExpr::GlobalGet(0));
WasmInitExpr::RttSub(HeapType::kI31, WasmInitExpr::GlobalGet(0));
EXPECT_OK(result);
EXPECT_EQ(result.value()->globals[1].init, expected);
}
......@@ -748,12 +747,12 @@ TEST_F(WasmModuleVerifyTest, RttSubGlobalTypeError) {
WASM_FEATURE_SCOPE(typed_funcref);
WASM_FEATURE_SCOPE(gc);
static const byte data[] = {SECTION(
Global, ENTRY_COUNT(1), WASM_RTT(1 /* Should be 2 */, kLocalExternRef), 1,
WASM_RTT_CANON(kLocalEqRef), WASM_RTT_SUB(kLocalExternRef), kExprEnd)};
Global, ENTRY_COUNT(1), WASM_RTT(1 /* Should be 2 */, kLocalI31Ref), 1,
WASM_RTT_CANON(kLocalEqRef), WASM_RTT_SUB(kLocalI31Ref), kExprEnd)};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_NOT_OK(result,
"type error in init expression, expected (rtt 1 extern), got "
"(rtt 2 extern)");
"type error in init expression, expected (rtt 1 i31), got "
"(rtt 2 i31)");
}
TEST_F(WasmModuleVerifyTest, ZeroExceptions) {
......
......@@ -72,9 +72,11 @@ TEST_F(WasmSubtypingTest, Subtyping) {
}
for (ValueType ref_type : ref_types) {
// Reference types are a subtype of eqref, except funcref.
// Concrete reference types and i31ref are subtypes of eqref,
// exnref/externref/funcref are not.
CHECK_EQ(IsSubtypeOf(ref_type, kWasmEqRef, module),
ref_type != kWasmFuncRef);
ref_type != kWasmFuncRef && ref_type != kWasmExternRef &&
ref_type != kWasmExnRef);
// Each reference type is a subtype of itself.
CHECK(IsSubtypeOf(ref_type, ref_type, module));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment