Skip to content

Commit 70f860e

Browse files
authored
[Strings] Implement stringview_wtf16.slice (#6404)
1 parent 84cc9fa commit 70f860e

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

scripts/fuzz_opt.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,9 @@ def is_git_repo():
333333
'exception-handling.wast',
334334
'translate-eh-old-to-new.wast',
335335
'rse-eh.wast',
336-
# Non-UTF8 strings trap in V8
336+
# Non-UTF8 strings trap in V8, and have limitations in our interpreter
337337
'string-lowering.wast',
338+
'precompute-strings.wast',
338339
]
339340

340341

src/wasm-interpreter.h

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,12 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
19031903
return Literal(curr->string.toString());
19041904
}
19051905

1906-
bool hasNonAsciiUpTo(const Literals& values, Index end) {
1906+
// Returns if there is a non-ascii character in a list of values, looking only
1907+
// up to an index that is provided (not inclusive). If the index is not
1908+
// provided we look in the entire list.
1909+
bool hasNonAsciiUpTo(const Literals& values,
1910+
std::optional<Index> maybeEnd = std::nullopt) {
1911+
Index end = maybeEnd ? *maybeEnd : values.size();
19071912
for (Index i = 0; i < end; ++i) {
19081913
if (uint32_t(values[i].geti32()) > 127) {
19091914
return true;
@@ -1930,7 +1935,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
19301935

19311936
// This is only correct if all the bytes stored in `values` correspond to
19321937
// single unicode code points. See `visitStringWTF16Get` for details.
1933-
if (hasNonAsciiUpTo(data->values, data->values.size())) {
1938+
if (hasNonAsciiUpTo(data->values)) {
19341939
return Flow(NONCONSTANT_FLOW);
19351940
}
19361941

@@ -1998,7 +2003,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
19982003
}
19992004

20002005
// We don't handle non-ascii code points correctly yet.
2001-
if (hasNonAsciiUpTo(refValues, refValues.size())) {
2006+
if (hasNonAsciiUpTo(refValues)) {
20022007
return Flow(NONCONSTANT_FLOW);
20032008
}
20042009

@@ -2138,7 +2143,47 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
21382143
return Flow(NONCONSTANT_FLOW);
21392144
}
21402145
Flow visitStringSliceWTF(StringSliceWTF* curr) {
2141-
return Flow(NONCONSTANT_FLOW);
2146+
// For now we only support JS-style strings.
2147+
if (curr->op != StringSliceWTF16) {
2148+
return Flow(NONCONSTANT_FLOW);
2149+
}
2150+
2151+
Flow ref = visit(curr->ref);
2152+
if (ref.breaking()) {
2153+
return ref;
2154+
}
2155+
Flow start = visit(curr->start);
2156+
if (start.breaking()) {
2157+
return start;
2158+
}
2159+
Flow end = visit(curr->end);
2160+
if (end.breaking()) {
2161+
return end;
2162+
}
2163+
2164+
auto refData = ref.getSingleValue().getGCData();
2165+
if (!refData) {
2166+
trap("null ref");
2167+
}
2168+
auto& refValues = refData->values;
2169+
auto startVal = start.getSingleValue().getUnsigned();
2170+
auto endVal = end.getSingleValue().getUnsigned();
2171+
if (endVal > refValues.size()) {
2172+
trap("array oob");
2173+
}
2174+
if (hasNonAsciiUpTo(refValues, endVal)) {
2175+
return Flow(NONCONSTANT_FLOW);
2176+
}
2177+
Literals contents;
2178+
if (endVal > startVal) {
2179+
contents.reserve(endVal - startVal);
2180+
for (size_t i = startVal; i < endVal; i++) {
2181+
if (i < refValues.size()) {
2182+
contents.push_back(refValues[i]);
2183+
}
2184+
}
2185+
}
2186+
return makeGCData(contents, curr->type);
21422187
}
21432188
Flow visitStringSliceIter(StringSliceIter* curr) {
21442189
return Flow(NONCONSTANT_FLOW);

test/lit/exec/strings.wast

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,17 @@
244244
)
245245
)
246246
)
247+
248+
;; CHECK: [fuzz-exec] calling slice
249+
;; CHECK-NEXT: [fuzz-exec] note result: slice => string("def")
250+
(func $slice (export "slice") (result (ref string))
251+
;; Slicing [3:6] here should definitely output "def".
252+
(stringview_wtf16.slice
253+
(string.const "abcdefgh")
254+
(i32.const 3)
255+
(i32.const 6)
256+
)
257+
)
247258
)
248259
;; CHECK: [fuzz-exec] calling new_wtf16_array
249260
;; CHECK-NEXT: [fuzz-exec] note result: new_wtf16_array => string("ello")
@@ -309,6 +320,9 @@
309320
;; CHECK-NEXT: [LoggingExternalInterface logging 98]
310321
;; CHECK-NEXT: [LoggingExternalInterface logging 99]
311322
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
323+
324+
;; CHECK: [fuzz-exec] calling slice
325+
;; CHECK-NEXT: [fuzz-exec] note result: slice => string("def")
312326
;; CHECK-NEXT: [fuzz-exec] comparing compare.1
313327
;; CHECK-NEXT: [fuzz-exec] comparing compare.10
314328
;; CHECK-NEXT: [fuzz-exec] comparing compare.2
@@ -329,3 +343,4 @@
329343
;; CHECK-NEXT: [fuzz-exec] comparing get_codeunit
330344
;; CHECK-NEXT: [fuzz-exec] comparing get_length
331345
;; CHECK-NEXT: [fuzz-exec] comparing new_wtf16_array
346+
;; CHECK-NEXT: [fuzz-exec] comparing slice

test/lit/passes/precompute-strings.wast

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,33 @@
129129
(i32.const 0)
130130
)
131131
)
132+
133+
;; CHECK: (func $slice (type $1) (result (ref string))
134+
;; CHECK-NEXT: (string.const "def")
135+
;; CHECK-NEXT: )
136+
(func $slice (export "slice") (result (ref string))
137+
;; Slicing [3:6] here should definitely output "def".
138+
(stringview_wtf16.slice
139+
(string.const "abcdefgh")
140+
(i32.const 3)
141+
(i32.const 6)
142+
)
143+
)
144+
145+
;; CHECK: (func $slice-bad (type $1) (result (ref string))
146+
;; CHECK-NEXT: (stringview_wtf16.slice
147+
;; CHECK-NEXT: (string.const "abcd\c2\a3fgh")
148+
;; CHECK-NEXT: (i32.const 3)
149+
;; CHECK-NEXT: (i32.const 6)
150+
;; CHECK-NEXT: )
151+
;; CHECK-NEXT: )
152+
(func $slice-bad (export "slice-bad") (result (ref string))
153+
;; This slice contains non-ascii, so we do not optimize.
154+
(stringview_wtf16.slice
155+
;; abcd£fgh
156+
(string.const "abcd\C2\A3fgh")
157+
(i32.const 3)
158+
(i32.const 6)
159+
)
160+
)
132161
)

0 commit comments

Comments
 (0)