[wasm-stringrefs] Remove subtyping between string view / iter and any
The intention is to be restrictive for now: modules should not start to depend on this subtyping while the stringref type hierarchy question is being settled (see https://github.com/WebAssembly/stringref/issues/3 for details). Bug: v8:12868 Change-Id: I0140e72f92550c88393dc84bb1fa3ce65840a048 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3865019 Commit-Queue: Matthias Liedtke <mliedtke@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#82937}
This commit is contained in:
parent
2f95d10f6b
commit
c6efb4da12
@ -219,14 +219,13 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl(
|
||||
return super_heap == HeapType::kArray || super_heap == HeapType::kData ||
|
||||
super_heap == HeapType::kEq || super_heap == HeapType::kAny;
|
||||
case HeapType::kString:
|
||||
// TODO(7748): Remove views from any subtype hierarchy as views can't be
|
||||
// externalized as of now.
|
||||
case HeapType::kStringViewWtf8:
|
||||
case HeapType::kStringViewWtf16:
|
||||
case HeapType::kStringViewIter:
|
||||
// stringref is a subtype of anyref under wasm-gc.
|
||||
return sub_heap == super_heap ||
|
||||
(v8_flags.experimental_wasm_gc && super_heap == HeapType::kAny);
|
||||
case HeapType::kStringViewWtf8:
|
||||
case HeapType::kStringViewWtf16:
|
||||
case HeapType::kStringViewIter:
|
||||
return sub_heap == super_heap;
|
||||
case HeapType::kBottom:
|
||||
UNREACHABLE();
|
||||
case HeapType::kNone:
|
||||
@ -480,6 +479,9 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
|
||||
: HeapType::kNoExtern;
|
||||
case HeapType::kExtern:
|
||||
return HeapType::kExtern;
|
||||
case HeapType::kString:
|
||||
case HeapType::kStringViewIter:
|
||||
return heap1 == heap2 ? heap1.representation() : HeapType::kBottom;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-gc
|
||||
// Flags: --experimental-wasm-gc --experimental-wasm-stringref
|
||||
|
||||
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
@ -43,7 +43,7 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
const size = 10;
|
||||
const maxSize = 15;
|
||||
const maxSize = 20;
|
||||
let table = new WebAssembly.Table({
|
||||
initial: size, maximum: maxSize, element: typeName
|
||||
});
|
||||
@ -148,6 +148,18 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
if (typeName == "anyref") {
|
||||
builder.addFunction("tableSetFromExtern",
|
||||
makeSig([kWasmI32, kWasmExternRef], []))
|
||||
.addBody([
|
||||
kExprLocalGet, 0,
|
||||
kExprLocalGet, 1,
|
||||
kGCPrefix, kExprExternInternalize,
|
||||
kExprTableSet, 0,
|
||||
])
|
||||
.exportFunc();
|
||||
}
|
||||
|
||||
let instance = builder.instantiate({ imports: { table } });
|
||||
let wasm = instance.exports;
|
||||
|
||||
@ -185,8 +197,20 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
assertEquals(12, wasm.tableGetArrayVal(7));
|
||||
assertEquals(0, wasm.eq(table.get(6), table.get(7))); // Not the same.
|
||||
|
||||
// Set stringref.
|
||||
if (typeName == "anyref") {
|
||||
table.set(8, "TestString");
|
||||
assertEquals("TestString", wasm.tableGet(8));
|
||||
assertEquals("TestString", table.get(8));
|
||||
let largeString = "Another test string, this time larger to prevent"
|
||||
+ " any kind of short string optimization.";
|
||||
wasm.tableSetFromExtern(9, largeString);
|
||||
assertEquals(largeString, wasm.tableGet(9));
|
||||
assertEquals(largeString, table.get(9));
|
||||
}
|
||||
|
||||
// Ensure all objects are externalized, so they can be handled by JS.
|
||||
for (let i = 0; i < size; ++i) {
|
||||
for (let i = 0; i < table.length; ++i) {
|
||||
JSON.stringify(table.get(i));
|
||||
}
|
||||
|
||||
@ -200,6 +224,11 @@ for (let [typeName, type] of Object.entries(tableTypes)) {
|
||||
table.grow(1, null);
|
||||
table.grow(1, undefined);
|
||||
}
|
||||
if (typeName == "anyref") {
|
||||
table.grow(1, "Grow using a string");
|
||||
assertEquals("Grow using a string", wasm.tableGet(14));
|
||||
assertEquals("Grow using a string", table.get(14));
|
||||
}
|
||||
|
||||
// Set from JS with wrapped wasm value of incompatible type.
|
||||
let invalidValues = {
|
||||
|
@ -129,14 +129,15 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
constexpr ValueType numeric_types[] = {kWasmI32, kWasmI64, kWasmF32, kWasmF64,
|
||||
kWasmS128};
|
||||
constexpr ValueType ref_types[] = {
|
||||
kWasmFuncRef, kWasmEqRef, // --
|
||||
kWasmDataRef, kWasmArrayRef, // --
|
||||
kWasmI31Ref, kWasmAnyRef, // --
|
||||
kWasmExternRef, kWasmNullExternRef, // --
|
||||
kWasmNullRef, kWasmNullFuncRef, // --
|
||||
refNull(0), ref(0), // struct
|
||||
refNull(2), ref(2), // array
|
||||
refNull(11), ref(11) // signature
|
||||
kWasmFuncRef, kWasmEqRef, // --
|
||||
kWasmDataRef, kWasmArrayRef, // --
|
||||
kWasmI31Ref, kWasmAnyRef, // --
|
||||
kWasmExternRef, kWasmNullExternRef, // --
|
||||
kWasmNullRef, kWasmNullFuncRef, // --
|
||||
kWasmStringRef, kWasmStringViewIter, // --
|
||||
refNull(0), ref(0), // struct
|
||||
refNull(2), ref(2), // array
|
||||
refNull(11), ref(11) // signature
|
||||
};
|
||||
|
||||
// Some macros to help managing types and modules.
|
||||
@ -198,11 +199,15 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
const bool is_any_func = ref_type == kWasmFuncRef ||
|
||||
ref_type == kWasmNullFuncRef ||
|
||||
ref_type == refNull(11) || ref_type == ref(11);
|
||||
const bool is_string_view = ref_type == kWasmStringViewIter ||
|
||||
ref_type == kWasmStringViewWtf8 ||
|
||||
ref_type == kWasmStringViewWtf16;
|
||||
SCOPED_TRACE("ref_type: " + ref_type.name());
|
||||
// Concrete reference types, i31ref and dataref are subtypes of eqref,
|
||||
// externref/funcref/anyref/functions are not.
|
||||
SUBTYPE_IFF(ref_type, kWasmEqRef,
|
||||
ref_type != kWasmAnyRef && !is_any_func && !is_extern);
|
||||
ref_type != kWasmAnyRef && !is_any_func && !is_extern &&
|
||||
!is_string_view && ref_type != kWasmStringRef);
|
||||
// Struct/array types are subtypes of dataref.
|
||||
SUBTYPE_IFF(ref_type, kWasmDataRef,
|
||||
ref_type == kWasmDataRef || ref_type == kWasmArrayRef ||
|
||||
@ -217,8 +222,10 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
SUBTYPE_IFF(ref_type, kWasmFuncRef, is_any_func);
|
||||
// Each reference type is a subtype of itself.
|
||||
SUBTYPE(ref_type, ref_type);
|
||||
// Each non-func, non-extern reference type is a subtype of anyref.
|
||||
SUBTYPE_IFF(ref_type, kWasmAnyRef, !is_any_func && !is_extern);
|
||||
// Each non-func, non-extern, non-string-view, non-string-iter reference
|
||||
// type is a subtype of anyref.
|
||||
SUBTYPE_IFF(ref_type, kWasmAnyRef,
|
||||
!is_any_func && !is_extern && !is_string_view);
|
||||
// Only anyref is a subtype of anyref.
|
||||
SUBTYPE_IFF(kWasmAnyRef, ref_type, ref_type == kWasmAnyRef);
|
||||
// Only externref and nullexternref are subtypes of externref.
|
||||
@ -349,8 +356,16 @@ TEST_F(WasmSubtypingTest, Subtyping) {
|
||||
|
||||
// Reference type vs. itself and anyref.
|
||||
for (ValueType type : ref_types) {
|
||||
SCOPED_TRACE(type.name());
|
||||
UNION(type, type, type);
|
||||
INTERSECTION(type, type, type);
|
||||
if (type == kWasmStringViewIter || type == kWasmStringViewWtf8 ||
|
||||
type == kWasmStringViewWtf16) {
|
||||
// String view and string iter aren't subtypes of any but have the same
|
||||
// null sentinel nullref (ref null none).
|
||||
INTERSECTION(type, kWasmAnyRef, kWasmNullRef);
|
||||
continue;
|
||||
}
|
||||
if (type == kWasmFuncRef || type == kWasmNullFuncRef || type == ref(11) ||
|
||||
type == refNull(11) || type == kWasmExternRef ||
|
||||
type == kWasmNullExternRef) {
|
||||
|
Loading…
Reference in New Issue
Block a user