Commit c3f60e8c authored by Andy Wingo's avatar Andy Wingo Committed by V8 LUCI CQ

[stringrefs] Add wtf8_policy immediate to string.measure_wtf8

Following change in https://github.com/WebAssembly/stringref/pull/22.

Bug: v8:12868
Change-Id: Ic7728bff5d03ab547cb26ff41d6966f95bfb6b62
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3717986
Commit-Queue: Andy Wingo <wingo@igalia.com>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81308}
parent 22698d26
...@@ -6078,34 +6078,25 @@ class LiftoffCompiler { ...@@ -6078,34 +6078,25 @@ class LiftoffCompiler {
__ PushRegister(kRef, result_reg); __ PushRegister(kRef, result_reg);
} }
void StringMeasureUtf8(FullDecoder* decoder, const Value& str, void StringMeasureWtf8(FullDecoder* decoder,
Value* result) { const Wtf8PolicyImmediate<validate>& imm,
LiftoffRegList pinned; const Value& str, Value* result) {
LiftoffRegister string_reg = pinned.set(__ PopToRegister(pinned));
MaybeEmitNullCheck(decoder, string_reg.gp(), pinned, str.type);
LiftoffAssembler::VarState string_var(kRef, string_reg, 0);
CallRuntimeStub(WasmCode::kWasmStringMeasureUtf8,
MakeSig::Returns(kI32).Params(kRef),
{
string_var,
},
decoder->position());
RegisterDebugSideTableEntry(decoder, DebugSideTableBuilder::kDidSpill);
LiftoffRegister result_reg(kReturnRegister0);
__ PushRegister(kI32, result_reg);
}
void StringMeasureWtf8(FullDecoder* decoder, const Value& str,
Value* result) {
LiftoffRegList pinned; LiftoffRegList pinned;
LiftoffRegister string_reg = pinned.set(__ PopToRegister(pinned)); LiftoffRegister string_reg = pinned.set(__ PopToRegister(pinned));
MaybeEmitNullCheck(decoder, string_reg.gp(), pinned, str.type); MaybeEmitNullCheck(decoder, string_reg.gp(), pinned, str.type);
LiftoffAssembler::VarState string_var(kRef, string_reg, 0); LiftoffAssembler::VarState string_var(kRef, string_reg, 0);
CallRuntimeStub(WasmCode::kWasmStringMeasureWtf8, WasmCode::RuntimeStubId stub_id;
MakeSig::Returns(kI32).Params(kRef), switch (imm.value) {
case kWtf8PolicyReject:
stub_id = WasmCode::kWasmStringMeasureUtf8;
break;
case kWtf8PolicyAccept:
case kWtf8PolicyReplace:
stub_id = WasmCode::kWasmStringMeasureWtf8;
break;
}
CallRuntimeStub(stub_id, MakeSig::Returns(kI32).Params(kRef),
{ {
string_var, string_var,
}, },
......
...@@ -1137,8 +1137,8 @@ struct ControlBase : public PcForErrors<validate> { ...@@ -1137,8 +1137,8 @@ struct ControlBase : public PcForErrors<validate> {
const Value& offset, const Value& size, Value* result) \ const Value& offset, const Value& size, Value* result) \
F(StringNewWtf16, const MemoryIndexImmediate<validate>& imm, \ F(StringNewWtf16, const MemoryIndexImmediate<validate>& imm, \
const Value& offset, const Value& size, Value* result) \ const Value& offset, const Value& size, Value* result) \
F(StringMeasureUtf8, const Value& str, Value* result) \ F(StringMeasureWtf8, const Wtf8PolicyImmediate<validate>& imm, \
F(StringMeasureWtf8, const Value& str, Value* result) \ const Value& str, Value* result) \
F(StringMeasureWtf16, const Value& str, Value* result) \ F(StringMeasureWtf16, const Value& str, Value* result) \
F(StringEncodeWtf8, const EncodeWtf8Immediate<validate>& memory, \ F(StringEncodeWtf8, const EncodeWtf8Immediate<validate>& memory, \
const Value& str, const Value& address) \ const Value& str, const Value& address) \
...@@ -2028,8 +2028,10 @@ class WasmDecoder : public Decoder { ...@@ -2028,8 +2028,10 @@ class WasmDecoder : public Decoder {
StringConstImmediate<validate> imm(decoder, pc + length); StringConstImmediate<validate> imm(decoder, pc + length);
return length + imm.length; return length + imm.length;
} }
case kExprStringMeasureUtf8: case kExprStringMeasureWtf8: {
case kExprStringMeasureWtf8: Wtf8PolicyImmediate<validate> imm(decoder, pc + length);
return length + imm.length;
}
case kExprStringMeasureWtf16: case kExprStringMeasureWtf16:
case kExprStringConcat: case kExprStringConcat:
case kExprStringEq: case kExprStringEq:
...@@ -2250,7 +2252,6 @@ class WasmDecoder : public Decoder { ...@@ -2250,7 +2252,6 @@ class WasmDecoder : public Decoder {
} }
case kExprStringConst: case kExprStringConst:
return { 0, 1 }; return { 0, 1 };
case kExprStringMeasureUtf8:
case kExprStringMeasureWtf8: case kExprStringMeasureWtf8:
case kExprStringMeasureWtf16: case kExprStringMeasureWtf16:
case kExprStringIsUSVSequence: case kExprStringIsUSVSequence:
...@@ -5223,23 +5224,16 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5223,23 +5224,16 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
Push(result); Push(result);
return opcode_length + imm.length; return opcode_length + imm.length;
} }
case kExprStringMeasureUtf8: {
NON_CONST_ONLY
Value str = Peek(0, 0, kWasmStringRef);
Value result = CreateValue(kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringMeasureUtf8, str, &result);
Drop(str);
Push(result);
return opcode_length;
}
case kExprStringMeasureWtf8: { case kExprStringMeasureWtf8: {
NON_CONST_ONLY NON_CONST_ONLY
Wtf8PolicyImmediate<validate> imm(this, this->pc_ + opcode_length);
Value str = Peek(0, 0, kWasmStringRef); Value str = Peek(0, 0, kWasmStringRef);
Value result = CreateValue(kWasmI32); Value result = CreateValue(kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(StringMeasureWtf8, str, &result); CALL_INTERFACE_IF_OK_AND_REACHABLE(StringMeasureWtf8, imm, str,
&result);
Drop(str); Drop(str);
Push(result); Push(result);
return opcode_length; return opcode_length + imm.length;
} }
case kExprStringMeasureWtf16: { case kExprStringMeasureWtf16: {
NON_CONST_ONLY NON_CONST_ONLY
......
...@@ -1413,16 +1413,20 @@ class WasmGraphBuildingInterface { ...@@ -1413,16 +1413,20 @@ class WasmGraphBuildingInterface {
result->node = builder_->StringConst(imm.index); result->node = builder_->StringConst(imm.index);
} }
void StringMeasureUtf8(FullDecoder* decoder, const Value& str, void StringMeasureWtf8(FullDecoder* decoder,
Value* result) { const Wtf8PolicyImmediate<validate>& imm,
result->node = builder_->StringMeasureUtf8(str.node, NullCheckFor(str.type), const Value& str, Value* result) {
decoder->position()); switch (imm.value) {
} case kWtf8PolicyReject:
result->node = builder_->StringMeasureUtf8(
void StringMeasureWtf8(FullDecoder* decoder, const Value& str, str.node, NullCheckFor(str.type), decoder->position());
Value* result) { break;
result->node = builder_->StringMeasureWtf8(str.node, NullCheckFor(str.type), case kWtf8PolicyAccept:
decoder->position()); case kWtf8PolicyReplace:
result->node = builder_->StringMeasureWtf8(
str.node, NullCheckFor(str.type), decoder->position());
break;
}
} }
void StringMeasureWtf16(FullDecoder* decoder, const Value& str, void StringMeasureWtf16(FullDecoder* decoder, const Value& str,
......
...@@ -151,7 +151,8 @@ enum NameSectionKindCode : uint8_t { ...@@ -151,7 +151,8 @@ enum NameSectionKindCode : uint8_t {
enum StringRefWtf8Policy : uint8_t { enum StringRefWtf8Policy : uint8_t {
kWtf8PolicyReject = 0, // Strict UTF-8; no isolated surrogates allowed. kWtf8PolicyReject = 0, // Strict UTF-8; no isolated surrogates allowed.
kWtf8PolicyAccept = 1, // Follow WTF-8 encoding of isolates surrogates. kWtf8PolicyAccept = 1, // Follow WTF-8 encoding of isolates surrogates.
kWtf8PolicyReplace = 2, // Replace isolated surrogates with U+FFFD. kWtf8PolicyReplace = 2, // Replace isolated surrogates and decoding errors
// with U+FFFD.
kLastWtf8Policy = kWtf8PolicyReplace kLastWtf8Policy = kWtf8PolicyReplace
}; };
......
...@@ -742,7 +742,6 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -742,7 +742,6 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(StringNewWtf8, 0xfb80, _, "string.new_wtf8") \ V(StringNewWtf8, 0xfb80, _, "string.new_wtf8") \
V(StringNewWtf16, 0xfb81, _, "string.new_wtf16") \ V(StringNewWtf16, 0xfb81, _, "string.new_wtf16") \
V(StringConst, 0xfb82, _, "string.const") \ V(StringConst, 0xfb82, _, "string.const") \
V(StringMeasureUtf8, 0xfb83, _, "string.measure_utf8") \
V(StringMeasureWtf8, 0xfb84, _, "string.measure_wtf8") \ V(StringMeasureWtf8, 0xfb84, _, "string.measure_wtf8") \
V(StringMeasureWtf16, 0xfb85, _, "string.measure_wtf16") \ V(StringMeasureWtf16, 0xfb85, _, "string.measure_wtf16") \
V(StringEncodeWtf8, 0xfb86, _, "string.encode_wtf8") \ V(StringEncodeWtf8, 0xfb86, _, "string.encode_wtf8") \
......
...@@ -186,34 +186,50 @@ function HasIsolatedSurrogate(str) { ...@@ -186,34 +186,50 @@ function HasIsolatedSurrogate(str) {
.exportFunc() .exportFunc()
.addBody([ .addBody([
kExprLocalGet, 0, kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureUtf8 kGCPrefix, kExprStringMeasureWtf8, 0
]); ]);
builder.addFunction("string_measure_wtf8", kSig_i_w) builder.addFunction("string_measure_wtf8", kSig_i_w)
.exportFunc() .exportFunc()
.addBody([ .addBody([
kExprLocalGet, 0, kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureWtf8 kGCPrefix, kExprStringMeasureWtf8, 1
]);
builder.addFunction("string_measure_wtf8_replace", kSig_i_w)
.exportFunc()
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureWtf8, 2
]); ]);
builder.addFunction("string_measure_utf8_null", kSig_i_v) builder.addFunction("string_measure_utf8_null", kSig_i_v)
.exportFunc() .exportFunc()
.addBody([ .addBody([
kExprRefNull, kStringRefCode, kExprRefNull, kStringRefCode,
kGCPrefix, kExprStringMeasureUtf8 kGCPrefix, kExprStringMeasureWtf8, 0
]); ]);
builder.addFunction("string_measure_wtf8_null", kSig_i_v) builder.addFunction("string_measure_wtf8_null", kSig_i_v)
.exportFunc() .exportFunc()
.addBody([ .addBody([
kExprRefNull, kStringRefCode, kExprRefNull, kStringRefCode,
kGCPrefix, kExprStringMeasureWtf8 kGCPrefix, kExprStringMeasureWtf8, 1
]);
builder.addFunction("string_measure_wtf8_replace_null", kSig_i_v)
.exportFunc()
.addBody([
kExprRefNull, kStringRefCode,
kGCPrefix, kExprStringMeasureWtf8, 2
]); ]);
let instance = builder.instantiate(); let instance = builder.instantiate();
for (let str of interestingStrings) { for (let str of interestingStrings) {
let wtf8 = encodeWtf8(str); let wtf8 = encodeWtf8(str);
assertEquals(wtf8.length, instance.exports.string_measure_wtf8(str)); assertEquals(wtf8.length, instance.exports.string_measure_wtf8(str));
assertEquals(wtf8.length,
instance.exports.string_measure_wtf8_replace(str));
if (HasIsolatedSurrogate(str)) { if (HasIsolatedSurrogate(str)) {
assertEquals(-1, instance.exports.string_measure_utf8(str)); assertEquals(-1, instance.exports.string_measure_utf8(str));
} else { } else {
...@@ -225,6 +241,8 @@ function HasIsolatedSurrogate(str) { ...@@ -225,6 +241,8 @@ function HasIsolatedSurrogate(str) {
WebAssembly.RuntimeError, "dereferencing a null pointer"); WebAssembly.RuntimeError, "dereferencing a null pointer");
assertThrows(() => instance.exports.string_measure_wtf8_null(), assertThrows(() => instance.exports.string_measure_wtf8_null(),
WebAssembly.RuntimeError, "dereferencing a null pointer"); WebAssembly.RuntimeError, "dereferencing a null pointer");
assertThrows(() => instance.exports.string_measure_wtf8_replace_null(),
WebAssembly.RuntimeError, "dereferencing a null pointer");
})(); })();
(function TestStringMeasureWtf16() { (function TestStringMeasureWtf16() {
......
...@@ -91,16 +91,22 @@ let kSig_w_zi = makeSig([kWasmStringViewIter, kWasmI32], ...@@ -91,16 +91,22 @@ let kSig_w_zi = makeSig([kWasmStringViewIter, kWasmI32],
kGCPrefix, kExprStringConst, 0 kGCPrefix, kExprStringConst, 0
]); ]);
builder.addFunction("string.measure_utf8", kSig_i_w) builder.addFunction("string.measure_wtf8/utf-8", kSig_i_w)
.addBody([ .addBody([
kExprLocalGet, 0, kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureUtf8 kGCPrefix, kExprStringMeasureWtf8, 0
]); ]);
builder.addFunction("string.measure_wtf8", kSig_i_w) builder.addFunction("string.measure_wtf8/wtf-8", kSig_i_w)
.addBody([ .addBody([
kExprLocalGet, 0, kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureWtf8 kGCPrefix, kExprStringMeasureWtf8, 1
]);
builder.addFunction("string.measure_wtf8/replace", kSig_i_w)
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureWtf8, 2
]); ]);
builder.addFunction("string.measure_wtf16", kSig_i_w) builder.addFunction("string.measure_wtf16", kSig_i_w)
...@@ -309,3 +315,14 @@ assertInvalid( ...@@ -309,3 +315,14 @@ assertInvalid(
}, },
"Compiling function #0:\"string.encode_wtf8/bad-policy\" failed: " + "Compiling function #0:\"string.encode_wtf8/bad-policy\" failed: " +
"expected wtf8 policy 0, 1, or 2, but found 3 @+37"); "expected wtf8 policy 0, 1, or 2, but found 3 @+37");
assertInvalid(
builder => {
builder.addFunction("string.measure_wtf8/bad-policy", kSig_i_w)
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStringMeasureWtf8, 3
]);
},
"Compiling function #0:\"string.measure_wtf8/bad-policy\" failed: " +
"expected wtf8 policy 0, 1, or 2, but found 3 @+29");
...@@ -536,7 +536,6 @@ let kExprBrOnNonArray = 0x67; ...@@ -536,7 +536,6 @@ let kExprBrOnNonArray = 0x67;
let kExprStringNewWtf8 = 0x80; let kExprStringNewWtf8 = 0x80;
let kExprStringNewWtf16 = 0x81; let kExprStringNewWtf16 = 0x81;
let kExprStringConst = 0x82; let kExprStringConst = 0x82;
let kExprStringMeasureUtf8 = 0x83;
let kExprStringMeasureWtf8 = 0x84; let kExprStringMeasureWtf8 = 0x84;
let kExprStringMeasureWtf16 = 0x85; let kExprStringMeasureWtf16 = 0x85;
let kExprStringEncodeWtf8 = 0x86; let kExprStringEncodeWtf8 = 0x86;
......
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