[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:
parent
6862a4bce3
commit
fac19a2413
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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(),
|
||||
|
Loading…
Reference in New Issue
Block a user