[stringref] Add stringref type, section, feature flag definitions

Bug: v8:12868
Change-Id: I69e149aa607ee77dd00267a0bbe4e5828dceb75e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3647350
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Andy Wingo <wingo@igalia.com>
Cr-Commit-Position: refs/heads/main@{#80526}
This commit is contained in:
Andy Wingo 2022-05-13 16:25:48 +02:00 committed by V8 LUCI CQ
parent 8bba185fe5
commit 59518b083a
9 changed files with 161 additions and 12 deletions

View File

@ -216,6 +216,18 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc,
case kAnyRefCode:
case kFuncRefCode:
return HeapType::from_code(code);
case kStringRefCode:
case kStringViewWtf8Code:
case kStringViewWtf16Code:
case kStringViewIterCode:
if (!VALIDATE(enabled.has_stringref())) {
DecodeError<validate>(decoder, pc,
"invalid heap type '%s', enable with "
"--experimental-wasm-stringref",
HeapType::from_code(code).name().c_str());
return HeapType(HeapType::kBottom);
}
return HeapType::from_code(code);
default:
DecodeError<validate>(decoder, pc, "Unknown heap type %" PRId64,
heap_index);
@ -289,6 +301,19 @@ ValueType read_value_type(Decoder* decoder, const byte* pc,
: kNullable;
return ValueType::Ref(heap_type, nullability);
}
case kStringRefCode:
case kStringViewWtf8Code:
case kStringViewWtf16Code:
case kStringViewIterCode: {
if (!VALIDATE(enabled.has_stringref())) {
DecodeError<validate>(decoder, pc,
"invalid value type '%sref', enable with "
"--experimental-wasm-stringref",
HeapType::from_code(code).name().c_str());
return kWasmBottom;
}
return ValueType::Ref(HeapType::from_code(code), kNullable);
}
case kI32Code:
return kWasmI32;
case kI64Code:

View File

@ -87,6 +87,8 @@ const char* SectionName(SectionCode code) {
return "Data";
case kTagSectionCode:
return "Tag";
case kStringRefSectionCode:
return "StringRef";
case kDataCountSectionCode:
return "DataCount";
case kNameSectionCode:
@ -418,13 +420,25 @@ class ModuleDecoderImpl : public Decoder {
return;
}
break;
case kTagSectionCode:
case kTagSectionCode: {
if (!CheckUnorderedSection(section_code)) return;
if (!CheckSectionOrder(section_code, kMemorySectionCode,
kGlobalSectionCode)) {
SectionCode next = enabled_features_.has_stringref()
? kStringRefSectionCode
: kGlobalSectionCode;
if (!CheckSectionOrder(section_code, kMemorySectionCode, next)) {
return;
}
break;
}
case kStringRefSectionCode: {
if (!CheckUnorderedSection(section_code)) return;
SectionCode prev =
enabled_features_.has_eh() ? kTagSectionCode : kMemorySectionCode;
if (!CheckSectionOrder(section_code, prev, kGlobalSectionCode)) {
return;
}
break;
}
case kNameSectionCode:
// TODO(titzer): report out of place name section as a warning.
// Be lenient with placement of name section. All except first
@ -541,6 +555,16 @@ class ModuleDecoderImpl : public Decoder {
SectionName(section_code));
}
break;
case kStringRefSectionCode:
if (enabled_features_.has_stringref()) {
DecodeStringRefSection();
} else {
errorf(pc(),
"unexpected section <%s> (enable with "
"--experimental-wasm-stringref)",
SectionName(section_code));
}
break;
default:
errorf(pc(), "unexpected section <%s>", SectionName(section_code));
return;
@ -1451,6 +1475,8 @@ class ModuleDecoderImpl : public Decoder {
}
}
void DecodeStringRefSection() { UNIMPLEMENTED(); }
bool CheckMismatchedCounts() {
// The declared vs. defined function count is normally checked when
// decoding the code section, but we have to check it here too in case the

View File

@ -66,6 +66,10 @@ class HeapType {
kData, // shorthand: o
kArray, // shorthand: g
kAny, // shorthand: a. Aka kExtern.
kString, // shorthand: s.
kStringViewWtf8, // shorthand: x.
kStringViewWtf16, // shorthand: y.
kStringViewIter, // shorthand: z.
// This value is used to represent failures in the parsing of heap types and
// does not correspond to a wasm heap type. It has to be last in this list.
kBottom
@ -86,6 +90,14 @@ class HeapType {
return HeapType(kData);
case ValueTypeCode::kArrayRefCode:
return HeapType(kArray);
case ValueTypeCode::kStringRefCode:
return HeapType(kString);
case ValueTypeCode::kStringViewWtf8Code:
return HeapType(kStringViewWtf8);
case ValueTypeCode::kStringViewWtf16Code:
return HeapType(kStringViewWtf16);
case ValueTypeCode::kStringViewIterCode:
return HeapType(kStringViewIter);
default:
return HeapType(kBottom);
}
@ -140,6 +152,14 @@ class HeapType {
return std::string("array");
case kAny:
return std::string(FLAG_experimental_wasm_gc ? "any" : "extern");
case kString:
return std::string("string");
case kStringViewWtf8:
return std::string("stringview_wtf8");
case kStringViewWtf16:
return std::string("stringview_wtf16");
case kStringViewIter:
return std::string("stringview_iter");
default:
return std::to_string(representation_);
}
@ -163,6 +183,14 @@ class HeapType {
return mask | kArrayRefCode;
case kAny:
return mask | kAnyRefCode;
case kString:
return mask | kStringRefCode;
case kStringViewWtf8:
return mask | kStringViewWtf8Code;
case kStringViewWtf16:
return mask | kStringViewWtf16Code;
case kStringViewIter:
return mask | kStringViewIterCode;
default:
return static_cast<int32_t>(representation_);
}
@ -464,6 +492,14 @@ class ValueType {
return kEqRefCode;
case HeapType::kAny:
return kAnyRefCode;
case HeapType::kString:
return kStringRefCode;
case HeapType::kStringViewWtf8:
return kStringViewWtf8Code;
case HeapType::kStringViewWtf16:
return kStringViewWtf16Code;
case HeapType::kStringViewIter:
return kStringViewIterCode;
default:
return kOptRefCode;
}
@ -504,7 +540,11 @@ class ValueType {
case kOptRef:
return heap_representation() != HeapType::kFunc &&
heap_representation() != HeapType::kEq &&
heap_representation() != HeapType::kAny;
heap_representation() != HeapType::kAny &&
heap_representation() != HeapType::kString &&
heap_representation() != HeapType::kStringViewWtf8 &&
heap_representation() != HeapType::kStringViewWtf16 &&
heap_representation() != HeapType::kStringViewIter;
default:
return false;
}
@ -615,6 +655,14 @@ constexpr ValueType kWasmDataRef =
ValueType::Ref(HeapType::kData, kNonNullable);
constexpr ValueType kWasmArrayRef =
ValueType::Ref(HeapType::kArray, kNonNullable);
constexpr ValueType kWasmStringRef =
ValueType::Ref(HeapType::kString, kNullable);
constexpr ValueType kWasmStringViewWtf8 =
ValueType::Ref(HeapType::kStringViewWtf8, kNullable);
constexpr ValueType kWasmStringViewWtf16 =
ValueType::Ref(HeapType::kStringViewWtf16, kNullable);
constexpr ValueType kWasmStringViewIter =
ValueType::Ref(HeapType::kStringViewIter, kNullable);
// Constants used by the generic js-to-wasm wrapper.
constexpr int kWasmValueKindBitsMask = (1u << ValueType::kKindBits) - 1;

View File

@ -49,7 +49,11 @@ enum ValueTypeCode : uint8_t {
kRttWithDepthCode = 0x69,
kRttCode = 0x68,
kDataRefCode = 0x67,
kArrayRefCode = 0x66
kArrayRefCode = 0x66,
kStringRefCode = 0x65,
kStringViewWtf8Code = 0x64,
kStringViewWtf16Code = 0x63,
kStringViewIterCode = 0x62,
};
// Binary encoding of type definitions.
@ -103,6 +107,7 @@ enum SectionCode : int8_t {
kDataSectionCode = 11, // Data segments
kDataCountSectionCode = 12, // Number of data segments
kTagSectionCode = 13, // Tag section
kStringRefSectionCode = 14, // Stringref literal section
// The following sections are custom sections, and are identified using a
// string rather than an integer. Their enumeration values are not guaranteed
@ -116,7 +121,7 @@ enum SectionCode : int8_t {
// Helper values
kFirstSectionInModule = kTypeSectionCode,
kLastKnownModuleSection = kTagSectionCode,
kLastKnownModuleSection = kStringRefSectionCode,
kFirstUnorderedSection = kDataCountSectionCode,
};

View File

@ -70,7 +70,12 @@
/* Extended Constant Expressions Proposal. */ \
/* https://github.com/WebAssembly/extended-const */ \
/* V8 side owner: manoskouk */ \
V(extended_const, "extended constant expressions", false)
V(extended_const, "extended constant expressions", false) \
\
/* Reference-Typed Strings Proposal. */ \
/* https://github.com/WebAssembly/stringref */ \
/* V8 side owner: jkummerow */ \
V(stringref, "reference-typed strings", false)
// #############################################################################
// Staged features (disabled by default, but enabled via --wasm-staging (also

View File

@ -1529,6 +1529,10 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
case internal::wasm::HeapType::kI31:
case internal::wasm::HeapType::kData:
case internal::wasm::HeapType::kArray:
case internal::wasm::HeapType::kString:
case internal::wasm::HeapType::kStringViewWtf8:
case internal::wasm::HeapType::kStringViewWtf16:
case internal::wasm::HeapType::kStringViewIter:
default:
// TODO(7748): Implement these.
UNIMPLEMENTED();
@ -1719,6 +1723,10 @@ void EncodeExceptionValues(v8::Isolate* isolate,
case i::wasm::HeapType::kI31:
case i::wasm::HeapType::kData:
case i::wasm::HeapType::kArray:
case i::wasm::HeapType::kString:
case i::wasm::HeapType::kStringViewWtf8:
case i::wasm::HeapType::kStringViewWtf16:
case i::wasm::HeapType::kStringViewIter:
values_out->set(index++, *Utils::OpenHandle(*value));
break;
case internal::wasm::HeapType::kBottom:
@ -2282,6 +2290,10 @@ void WebAssemblyExceptionGetArg(
case i::wasm::HeapType::kI31:
case i::wasm::HeapType::kData:
case i::wasm::HeapType::kArray:
case i::wasm::HeapType::kString:
case i::wasm::HeapType::kStringViewWtf8:
case i::wasm::HeapType::kStringViewWtf16:
case i::wasm::HeapType::kStringViewIter:
decode_index++;
break;
case i::wasm::HeapType::kBottom:
@ -2339,7 +2351,11 @@ void WebAssemblyExceptionGetArg(
case i::wasm::HeapType::kEq:
case i::wasm::HeapType::kI31:
case i::wasm::HeapType::kArray:
case i::wasm::HeapType::kData: {
case i::wasm::HeapType::kData:
case i::wasm::HeapType::kString:
case i::wasm::HeapType::kStringViewWtf8:
case i::wasm::HeapType::kStringViewWtf16:
case i::wasm::HeapType::kStringViewIter: {
auto obj = values->get(decode_index);
result = Utils::ToLocal(i::Handle<i::Object>(obj, i_isolate));
break;
@ -2436,6 +2452,10 @@ void WebAssemblyGlobalGetValueCommon(
case i::wasm::HeapType::kData:
case i::wasm::HeapType::kArray:
case i::wasm::HeapType::kEq:
case i::wasm::HeapType::kString:
case i::wasm::HeapType::kStringViewWtf8:
case i::wasm::HeapType::kStringViewWtf16:
case i::wasm::HeapType::kStringViewIter:
default:
// TODO(7748): Implement these.
UNIMPLEMENTED();
@ -2529,6 +2549,10 @@ void WebAssemblyGlobalSetValue(
case i::wasm::HeapType::kData:
case i::wasm::HeapType::kArray:
case i::wasm::HeapType::kEq:
case i::wasm::HeapType::kString:
case i::wasm::HeapType::kStringViewWtf8:
case i::wasm::HeapType::kStringViewWtf16:
case i::wasm::HeapType::kStringViewIter:
default:
// TODO(7748): Implement these.
UNIMPLEMENTED();

View File

@ -390,7 +390,11 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
case wasm::HeapType::kData:
case wasm::HeapType::kArray:
case wasm::HeapType::kI31:
// TODO(7748): Implement once we have struct/arrays/i31ref tables.
case wasm::HeapType::kString:
case wasm::HeapType::kStringViewWtf8:
case wasm::HeapType::kStringViewWtf16:
case wasm::HeapType::kStringViewIter:
// TODO(7748): Implement once we have struct/arrays/i31ref/string tables.
UNREACHABLE();
case wasm::HeapType::kBottom:
UNREACHABLE();

View File

@ -177,6 +177,13 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsSubtypeOfImpl(
case HeapType::kArray:
return super_heap == HeapType::kArray || super_heap == HeapType::kData ||
super_heap == HeapType::kEq || super_heap == HeapType::kAny;
case HeapType::kString:
case HeapType::kStringViewWtf8:
case HeapType::kStringViewWtf16:
case HeapType::kStringViewIter:
// stringref is a subtype of anyref (aka externref) under wasm-gc.
return sub_heap == super_heap ||
(FLAG_experimental_wasm_gc && super_heap == HeapType::kAny);
case HeapType::kBottom:
UNREACHABLE();
default:
@ -199,6 +206,11 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsSubtypeOfImpl(
return false;
case HeapType::kAny:
return true;
case HeapType::kString:
case HeapType::kStringViewWtf8:
case HeapType::kStringViewWtf16:
case HeapType::kStringViewIter:
return false;
case HeapType::kBottom:
UNREACHABLE();
default:

View File

@ -13,15 +13,15 @@ function assertInvalid(fn, message) {
`WebAssembly.Module(): ${message}`);
}
let kStringSectionCodeStr = '0x0' + kStringRefSectionCode.toString(16);
let enableMessage = 'enable with --experimental-wasm-stringref'
assertInvalid(builder => builder.addLiteralStringRef("foo"),
`unknown section code #${kStringSectionCodeStr} @+10`);
`unexpected section <StringRef> (${enableMessage}) @+10`);
for (let [name, code] of [['string', kWasmStringRef],
['stringview_wtf8', kWasmStringViewWtf8],
['stringview_wtf16', kWasmStringViewWtf16],
['stringview_iter', kWasmStringViewIter]]) {
let message = `invalid value type 0x${(code & kLeb128Mask).toString(16)}`;
let message = `invalid value type '${name}ref', ${enableMessage}`;
let default_init = WasmInitExpr.RefNull(code);
assertInvalid(b => b.addType(makeSig([code], [])),