[stringrefs] Create non-nullable references to strings/views

The string and view creating instructions string.new*, string.const,
string.concat, and string.as_* should all return non-nullable reference
types.

See https://github.com/WebAssembly/stringref/issues/42

Bug: v8:12868
Change-Id: I2a39aadd339a49b4aa2d145492cba85e6ab14b71
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3858236
Commit-Queue: Matthias Liedtke <mliedtke@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Auto-Submit: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82792}
This commit is contained in:
Jakob Kummerow 2022-08-29 17:36:43 +02:00 committed by V8 LUCI CQ
parent 6862a4bce3
commit fac19a2413
4 changed files with 35 additions and 13 deletions

View File

@ -6829,6 +6829,10 @@ class LiftoffCompiler {
__ PushRegister(kRef, result_reg);
}
void StringAsWtf16(FullDecoder* decoder, const Value& str, Value* result) {
RefAsNonNull(decoder, str, result);
}
void StringViewWtf16GetCodeUnit(FullDecoder* decoder, const Value& view,
const Value& pos, Value* result) {
LiftoffRegList pinned;

View File

@ -1134,6 +1134,7 @@ struct ControlBase : public PcForErrors<validate> {
const Value& bytes, Value* next_pos, Value* bytes_written) \
F(StringViewWtf8Slice, const Value& view, const Value& start, \
const Value& end, Value* result) \
F(StringAsWtf16, const Value& str, Value* result) \
F(StringViewWtf16GetCodeUnit, const Value& view, const Value& pos, \
Value* result) \
F(StringViewWtf16Encode, const MemoryIndexImmediate<validate>& memory, \
@ -5122,7 +5123,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
ValueType addr_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value offset = Peek(1, 0, addr_type);
Value size = Peek(0, 1, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf8, imm, offset, size,
&result);
Drop(2);
@ -5136,7 +5137,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
ValueType addr_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value offset = Peek(1, 0, addr_type);
Value size = Peek(0, 1, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf16, imm, offset, size,
&result);
Drop(2);
@ -5146,7 +5147,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringConst: {
StringConstImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringConst, imm, &result);
Push(result);
return opcode_length + imm.length;
@ -5203,7 +5204,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
NON_CONST_ONLY
Value head = Peek(1, 0, kWasmStringRef);
Value tail = Peek(0, 1, kWasmStringRef);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringConcat, head, tail, &result);
Drop(2);
Push(result);
@ -5231,7 +5232,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringAsWtf8: {
NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef);
Value result = CreateValue(kWasmStringViewWtf8);
Value result = CreateValue(ValueType::Ref(HeapType::kStringViewWtf8));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringAsWtf8, str, &result);
Drop(str);
Push(result);
@ -5273,7 +5274,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value view = Peek(2, 0, kWasmStringViewWtf8);
Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringViewWtf8Slice, view, start,
end, &result);
Drop(3);
@ -5283,8 +5284,8 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringAsWtf16: {
NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef);
Value result = CreateValue(kWasmStringViewWtf16);
CALL_INTERFACE_IF_OK_AND_REACHABLE(Forward, str, &result);
Value result = CreateValue(ValueType::Ref(HeapType::kStringViewWtf16));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringAsWtf16, str, &result);
Drop(str);
Push(result);
return opcode_length;
@ -5330,7 +5331,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value view = Peek(2, 0, kWasmStringViewWtf16);
Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringViewWtf16Slice, view, start,
end, &result);
Drop(3);
@ -5341,7 +5342,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringAsIter: {
NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef);
Value result = CreateValue(kWasmStringViewIter);
Value result = CreateValue(ValueType::Ref(HeapType::kStringViewIter));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringAsIter, str, &result);
Drop(str);
Push(result);
@ -5382,7 +5383,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
NON_CONST_ONLY
Value view = Peek(1, 0, kWasmStringViewIter);
Value codepoints = Peek(0, 1, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringViewIterSlice, view,
codepoints, &result);
Drop(2);
@ -5396,7 +5397,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value array = PeekPackedArray(2, 0, kWasmI8, WasmArrayAccess::kRead);
Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf8Array, imm, array,
start, end, &result);
Drop(3);
@ -5409,7 +5410,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value array = PeekPackedArray(2, 0, kWasmI16, WasmArrayAccess::kRead);
Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, kWasmI32);
Value result = CreateValue(kWasmStringRef);
Value result = CreateValue(ValueType::Ref(HeapType::kString));
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf16Array, array, start,
end, &result);
Drop(3);

View File

@ -1510,6 +1510,15 @@ class WasmGraphBuildingInterface {
end.node, decoder->position()));
}
void StringAsWtf16(FullDecoder* decoder, const Value& str, Value* result) {
// Since we implement stringview_wtf16 as string, that's the type we'll
// use for the Node. (The decoder's Value type must be stringview_wtf16
// because static type validation relies on it.)
result->node =
builder_->SetType(builder_->RefAsNonNull(str.node, decoder->position()),
ValueType::Ref(HeapType::kString));
}
void StringViewWtf16GetCodeUnit(FullDecoder* decoder, const Value& view,
const Value& pos, Value* result) {
result->node = builder_->StringViewWtf16GetCodeUnit(

View File

@ -665,6 +665,12 @@ function makeWtf16TestDataSegment() {
builder.addMemory(1, undefined, true /* exported */, false);
builder.addFunction("view_from_null", kSig_v_v).exportFunc().addBody([
kExprRefNull, kStringRefCode,
...GCInstr(kExprStringAsWtf16),
kExprDrop,
]);
builder.addFunction("length", kSig_i_w)
.exportFunc()
.addBody([
@ -816,6 +822,8 @@ function makeWtf16TestDataSegment() {
assertEquals("oo", instance.exports.slice("foo", 1, 100));
assertEquals("", instance.exports.slice("foo", 1, 0));
assertThrows(() => instance.exports.view_from_null(),
WebAssembly.RuntimeError, 'dereferencing a null pointer');
assertThrows(() => instance.exports.length_null(),
WebAssembly.RuntimeError, "dereferencing a null pointer");
assertThrows(() => instance.exports.get_codeunit_null(),