Commit fac19a24 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by V8 LUCI CQ

[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: 's avatarMatthias Liedtke <mliedtke@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82792}
parent 6862a4bc
...@@ -6829,6 +6829,10 @@ class LiftoffCompiler { ...@@ -6829,6 +6829,10 @@ class LiftoffCompiler {
__ PushRegister(kRef, result_reg); __ PushRegister(kRef, result_reg);
} }
void StringAsWtf16(FullDecoder* decoder, const Value& str, Value* result) {
RefAsNonNull(decoder, str, result);
}
void StringViewWtf16GetCodeUnit(FullDecoder* decoder, const Value& view, void StringViewWtf16GetCodeUnit(FullDecoder* decoder, const Value& view,
const Value& pos, Value* result) { const Value& pos, Value* result) {
LiftoffRegList pinned; LiftoffRegList pinned;
......
...@@ -1134,6 +1134,7 @@ struct ControlBase : public PcForErrors<validate> { ...@@ -1134,6 +1134,7 @@ struct ControlBase : public PcForErrors<validate> {
const Value& bytes, Value* next_pos, Value* bytes_written) \ const Value& bytes, Value* next_pos, Value* bytes_written) \
F(StringViewWtf8Slice, const Value& view, const Value& start, \ F(StringViewWtf8Slice, const Value& view, const Value& start, \
const Value& end, Value* result) \ const Value& end, Value* result) \
F(StringAsWtf16, const Value& str, Value* result) \
F(StringViewWtf16GetCodeUnit, const Value& view, const Value& pos, \ F(StringViewWtf16GetCodeUnit, const Value& view, const Value& pos, \
Value* result) \ Value* result) \
F(StringViewWtf16Encode, const MemoryIndexImmediate<validate>& memory, \ F(StringViewWtf16Encode, const MemoryIndexImmediate<validate>& memory, \
...@@ -5122,7 +5123,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5122,7 +5123,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
ValueType addr_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32; ValueType addr_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value offset = Peek(1, 0, addr_type); Value offset = Peek(1, 0, addr_type);
Value size = Peek(0, 1, kWasmI32); 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf8, imm, offset, size,
&result); &result);
Drop(2); Drop(2);
...@@ -5136,7 +5137,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5136,7 +5137,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
ValueType addr_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32; ValueType addr_type = this->module_->is_memory64 ? kWasmI64 : kWasmI32;
Value offset = Peek(1, 0, addr_type); Value offset = Peek(1, 0, addr_type);
Value size = Peek(0, 1, kWasmI32); 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf16, imm, offset, size,
&result); &result);
Drop(2); Drop(2);
...@@ -5146,7 +5147,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5146,7 +5147,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringConst: { case kExprStringConst: {
StringConstImmediate<validate> imm(this, this->pc_ + opcode_length); StringConstImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0; 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); CALL_INTERFACE_IF_OK_AND_REACHABLE(StringConst, imm, &result);
Push(result); Push(result);
return opcode_length + imm.length; return opcode_length + imm.length;
...@@ -5203,7 +5204,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5203,7 +5204,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
NON_CONST_ONLY NON_CONST_ONLY
Value head = Peek(1, 0, kWasmStringRef); Value head = Peek(1, 0, kWasmStringRef);
Value tail = Peek(0, 1, 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); CALL_INTERFACE_IF_OK_AND_REACHABLE(StringConcat, head, tail, &result);
Drop(2); Drop(2);
Push(result); Push(result);
...@@ -5231,7 +5232,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5231,7 +5232,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringAsWtf8: { case kExprStringAsWtf8: {
NON_CONST_ONLY NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef); 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); CALL_INTERFACE_IF_OK_AND_REACHABLE(StringAsWtf8, str, &result);
Drop(str); Drop(str);
Push(result); Push(result);
...@@ -5273,7 +5274,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5273,7 +5274,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value view = Peek(2, 0, kWasmStringViewWtf8); Value view = Peek(2, 0, kWasmStringViewWtf8);
Value start = Peek(1, 1, kWasmI32); Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringViewWtf8Slice, view, start,
end, &result); end, &result);
Drop(3); Drop(3);
...@@ -5283,8 +5284,8 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5283,8 +5284,8 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringAsWtf16: { case kExprStringAsWtf16: {
NON_CONST_ONLY NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef); Value str = Peek(0, 0, kWasmStringRef);
Value result = CreateValue(kWasmStringViewWtf16); Value result = CreateValue(ValueType::Ref(HeapType::kStringViewWtf16));
CALL_INTERFACE_IF_OK_AND_REACHABLE(Forward, str, &result); CALL_INTERFACE_IF_OK_AND_REACHABLE(StringAsWtf16, str, &result);
Drop(str); Drop(str);
Push(result); Push(result);
return opcode_length; return opcode_length;
...@@ -5330,7 +5331,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5330,7 +5331,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value view = Peek(2, 0, kWasmStringViewWtf16); Value view = Peek(2, 0, kWasmStringViewWtf16);
Value start = Peek(1, 1, kWasmI32); Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringViewWtf16Slice, view, start,
end, &result); end, &result);
Drop(3); Drop(3);
...@@ -5341,7 +5342,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5341,7 +5342,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprStringAsIter: { case kExprStringAsIter: {
NON_CONST_ONLY NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef); 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); CALL_INTERFACE_IF_OK_AND_REACHABLE(StringAsIter, str, &result);
Drop(str); Drop(str);
Push(result); Push(result);
...@@ -5382,7 +5383,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5382,7 +5383,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
NON_CONST_ONLY NON_CONST_ONLY
Value view = Peek(1, 0, kWasmStringViewIter); Value view = Peek(1, 0, kWasmStringViewIter);
Value codepoints = Peek(0, 1, kWasmI32); 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringViewIterSlice, view,
codepoints, &result); codepoints, &result);
Drop(2); Drop(2);
...@@ -5396,7 +5397,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5396,7 +5397,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value array = PeekPackedArray(2, 0, kWasmI8, WasmArrayAccess::kRead); Value array = PeekPackedArray(2, 0, kWasmI8, WasmArrayAccess::kRead);
Value start = Peek(1, 1, kWasmI32); Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf8Array, imm, array,
start, end, &result); start, end, &result);
Drop(3); Drop(3);
...@@ -5409,7 +5410,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5409,7 +5410,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Value array = PeekPackedArray(2, 0, kWasmI16, WasmArrayAccess::kRead); Value array = PeekPackedArray(2, 0, kWasmI16, WasmArrayAccess::kRead);
Value start = Peek(1, 1, kWasmI32); Value start = Peek(1, 1, kWasmI32);
Value end = Peek(0, 2, 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, CALL_INTERFACE_IF_OK_AND_REACHABLE(StringNewWtf16Array, array, start,
end, &result); end, &result);
Drop(3); Drop(3);
......
...@@ -1510,6 +1510,15 @@ class WasmGraphBuildingInterface { ...@@ -1510,6 +1510,15 @@ class WasmGraphBuildingInterface {
end.node, decoder->position())); 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, void StringViewWtf16GetCodeUnit(FullDecoder* decoder, const Value& view,
const Value& pos, Value* result) { const Value& pos, Value* result) {
result->node = builder_->StringViewWtf16GetCodeUnit( result->node = builder_->StringViewWtf16GetCodeUnit(
......
...@@ -665,6 +665,12 @@ function makeWtf16TestDataSegment() { ...@@ -665,6 +665,12 @@ function makeWtf16TestDataSegment() {
builder.addMemory(1, undefined, true /* exported */, false); 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) builder.addFunction("length", kSig_i_w)
.exportFunc() .exportFunc()
.addBody([ .addBody([
...@@ -816,6 +822,8 @@ function makeWtf16TestDataSegment() { ...@@ -816,6 +822,8 @@ function makeWtf16TestDataSegment() {
assertEquals("oo", instance.exports.slice("foo", 1, 100)); assertEquals("oo", instance.exports.slice("foo", 1, 100));
assertEquals("", instance.exports.slice("foo", 1, 0)); assertEquals("", instance.exports.slice("foo", 1, 0));
assertThrows(() => instance.exports.view_from_null(),
WebAssembly.RuntimeError, 'dereferencing a null pointer');
assertThrows(() => instance.exports.length_null(), assertThrows(() => instance.exports.length_null(),
WebAssembly.RuntimeError, "dereferencing a null pointer"); WebAssembly.RuntimeError, "dereferencing a null pointer");
assertThrows(() => instance.exports.get_codeunit_null(), assertThrows(() => instance.exports.get_codeunit_null(),
......
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