Skip to content

Commit 58471ad

Browse files
authored
[Strings] GC variants for string.encode (WebAssembly#4817)
1 parent 880e835 commit 58471ad

12 files changed

Lines changed: 187 additions & 25 deletions

scripts/gen-s-parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,8 @@
624624
("string.is_usv_sequence", "makeStringMeasure(s, StringMeasureIsUSV)"),
625625
("string.encode_wtf8", "makeStringEncode(s, StringEncodeWTF8)"),
626626
("string.encode_wtf16", "makeStringEncode(s, StringEncodeWTF16)"),
627+
("string.encode_wtf8_array", "makeStringEncode(s, StringEncodeWTF8Array)"),
628+
("string.encode_wtf16_array", "makeStringEncode(s, StringEncodeWTF16Array)"),
627629
("string.concat", "makeStringConcat(s)"),
628630
("string.eq", "makeStringEq(s)"),
629631
("string.as_wtf8", "makeStringAs(s, StringAsWTF8)"),

src/gen-s-parser.inc

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3165,12 +3165,28 @@ switch (op[0]) {
31653165
switch (op[8]) {
31663166
case 'n': {
31673167
switch (op[17]) {
3168-
case '1':
3169-
if (strcmp(op, "string.encode_wtf16") == 0) { return makeStringEncode(s, StringEncodeWTF16); }
3170-
goto parse_error;
3171-
case '8':
3172-
if (strcmp(op, "string.encode_wtf8") == 0) { return makeStringEncode(s, StringEncodeWTF8); }
3173-
goto parse_error;
3168+
case '1': {
3169+
switch (op[19]) {
3170+
case '\0':
3171+
if (strcmp(op, "string.encode_wtf16") == 0) { return makeStringEncode(s, StringEncodeWTF16); }
3172+
goto parse_error;
3173+
case '_':
3174+
if (strcmp(op, "string.encode_wtf16_array") == 0) { return makeStringEncode(s, StringEncodeWTF16Array); }
3175+
goto parse_error;
3176+
default: goto parse_error;
3177+
}
3178+
}
3179+
case '8': {
3180+
switch (op[18]) {
3181+
case '\0':
3182+
if (strcmp(op, "string.encode_wtf8") == 0) { return makeStringEncode(s, StringEncodeWTF8); }
3183+
goto parse_error;
3184+
case '_':
3185+
if (strcmp(op, "string.encode_wtf8_array") == 0) { return makeStringEncode(s, StringEncodeWTF8Array); }
3186+
goto parse_error;
3187+
default: goto parse_error;
3188+
}
3189+
}
31743190
default: goto parse_error;
31753191
}
31763192
}
@@ -8879,20 +8895,44 @@ switch (op[0]) {
88798895
switch (op[8]) {
88808896
case 'n': {
88818897
switch (op[17]) {
8882-
case '1':
8883-
if (op == "string.encode_wtf16"sv) {
8884-
auto ret = makeStringEncode(ctx, in, StringEncodeWTF16);
8885-
CHECK_ERR(ret);
8886-
return *ret;
8898+
case '1': {
8899+
switch (op[19]) {
8900+
case '\0':
8901+
if (op == "string.encode_wtf16"sv) {
8902+
auto ret = makeStringEncode(ctx, in, StringEncodeWTF16);
8903+
CHECK_ERR(ret);
8904+
return *ret;
8905+
}
8906+
goto parse_error;
8907+
case '_':
8908+
if (op == "string.encode_wtf16_array"sv) {
8909+
auto ret = makeStringEncode(ctx, in, StringEncodeWTF16Array);
8910+
CHECK_ERR(ret);
8911+
return *ret;
8912+
}
8913+
goto parse_error;
8914+
default: goto parse_error;
88878915
}
8888-
goto parse_error;
8889-
case '8':
8890-
if (op == "string.encode_wtf8"sv) {
8891-
auto ret = makeStringEncode(ctx, in, StringEncodeWTF8);
8892-
CHECK_ERR(ret);
8893-
return *ret;
8916+
}
8917+
case '8': {
8918+
switch (op[18]) {
8919+
case '\0':
8920+
if (op == "string.encode_wtf8"sv) {
8921+
auto ret = makeStringEncode(ctx, in, StringEncodeWTF8);
8922+
CHECK_ERR(ret);
8923+
return *ret;
8924+
}
8925+
goto parse_error;
8926+
case '_':
8927+
if (op == "string.encode_wtf8_array"sv) {
8928+
auto ret = makeStringEncode(ctx, in, StringEncodeWTF8Array);
8929+
CHECK_ERR(ret);
8930+
return *ret;
8931+
}
8932+
goto parse_error;
8933+
default: goto parse_error;
88948934
}
8895-
goto parse_error;
8935+
}
88968936
default: goto parse_error;
88978937
}
88988938
}

src/passes/Print.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,15 @@ struct PrintExpressionContents
23302330
case StringEncodeWTF16:
23312331
printMedium(o, "string.encode_wtf16");
23322332
break;
2333+
case StringEncodeUTF8Array:
2334+
printMedium(o, "string.encode_wtf8_array utf8");
2335+
break;
2336+
case StringEncodeWTF8Array:
2337+
printMedium(o, "string.encode_wtf8_array wtf8");
2338+
break;
2339+
case StringEncodeWTF16Array:
2340+
printMedium(o, "string.encode_wtf16_array");
2341+
break;
23332342
default:
23342343
WASM_UNREACHABLE("invalid string.encode*");
23352344
}

src/wasm-binary.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,8 @@ enum ASTNodes {
11611161
StringViewIterSlice = 0xa4,
11621162
StringNewWTF8Array = 0xb0,
11631163
StringNewWTF16Array = 0xb1,
1164+
StringEncodeWTF8Array = 0xb2,
1165+
StringEncodeWTF16Array = 0xb3,
11641166
};
11651167

11661168
enum MemoryAccess {

src/wasm-builder.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,12 +1012,15 @@ class Builder {
10121012
ret->finalize();
10131013
return ret;
10141014
}
1015-
StringEncode*
1016-
makeStringEncode(StringEncodeOp op, Expression* ref, Expression* ptr) {
1015+
StringEncode* makeStringEncode(StringEncodeOp op,
1016+
Expression* ref,
1017+
Expression* ptr,
1018+
Expression* start = nullptr) {
10171019
auto* ret = wasm.allocator.alloc<StringEncode>();
10181020
ret->op = op;
10191021
ret->ref = ref;
10201022
ret->ptr = ptr;
1023+
ret->start = start;
10211024
ret->finalize();
10221025
return ret;
10231026
}

src/wasm-delegations-fields.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ switch (DELEGATE_ID) {
737737
case Expression::Id::StringEncodeId: {
738738
DELEGATE_START(StringEncode);
739739
DELEGATE_FIELD_INT(StringEncode, op);
740+
DELEGATE_FIELD_OPTIONAL_CHILD(StringEncode, start);
740741
DELEGATE_FIELD_CHILD(StringEncode, ptr);
741742
DELEGATE_FIELD_CHILD(StringEncode, ref);
742743
DELEGATE_END(StringEncode);

src/wasm.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,9 @@ enum StringEncodeOp {
608608
StringEncodeUTF8,
609609
StringEncodeWTF8,
610610
StringEncodeWTF16,
611+
StringEncodeUTF8Array,
612+
StringEncodeWTF8Array,
613+
StringEncodeWTF16Array,
611614
};
612615

613616
enum StringAsOp {
@@ -1746,8 +1749,15 @@ class StringEncode : public SpecificExpression<Expression::StringEncodeId> {
17461749
StringEncodeOp op;
17471750

17481751
Expression* ref;
1752+
1753+
// In linear memory variations this is the pointer in linear memory. In the
1754+
// GC variations this is an Array.
17491755
Expression* ptr;
17501756

1757+
// Used only in GC variations, where it is the index in |ptr| to start
1758+
// encoding from.
1759+
Expression* start = nullptr;
1760+
17511761
void finalize();
17521762
};
17531763

src/wasm/wasm-binary.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7261,6 +7261,7 @@ bool WasmBinaryBuilder::maybeVisitStringMeasure(Expression*& out,
72617261
bool WasmBinaryBuilder::maybeVisitStringEncode(Expression*& out,
72627262
uint32_t code) {
72637263
StringEncodeOp op;
7264+
Expression* start = nullptr;
72647265
// TODO: share this code with string.measure?
72657266
if (code == BinaryConsts::StringEncodeWTF8) {
72667267
auto policy = getU32LEB();
@@ -7276,12 +7277,28 @@ bool WasmBinaryBuilder::maybeVisitStringEncode(Expression*& out,
72767277
}
72777278
} else if (code == BinaryConsts::StringEncodeWTF16) {
72787279
op = StringEncodeWTF16;
7280+
} else if (code == BinaryConsts::StringEncodeWTF8Array) {
7281+
auto policy = getU32LEB();
7282+
switch (policy) {
7283+
case BinaryConsts::StringPolicy::UTF8:
7284+
op = StringEncodeUTF8Array;
7285+
break;
7286+
case BinaryConsts::StringPolicy::WTF8:
7287+
op = StringEncodeWTF8Array;
7288+
break;
7289+
default:
7290+
throwError("bad policy for string.encode");
7291+
}
7292+
start = popNonVoidExpression();
7293+
} else if (code == BinaryConsts::StringEncodeWTF16Array) {
7294+
op = StringEncodeWTF16Array;
7295+
start = popNonVoidExpression();
72797296
} else {
72807297
return false;
72817298
}
72827299
auto* ptr = popNonVoidExpression();
72837300
auto* ref = popNonVoidExpression();
7284-
out = Builder(wasm).makeStringEncode(op, ref, ptr);
7301+
out = Builder(wasm).makeStringEncode(op, ref, ptr, start);
72857302
return true;
72867303
}
72877304

src/wasm/wasm-s-parser.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2985,6 +2985,7 @@ Expression* SExpressionWasmBuilder::makeStringMeasure(Element& s,
29852985
Expression* SExpressionWasmBuilder::makeStringEncode(Element& s,
29862986
StringEncodeOp op) {
29872987
size_t i = 1;
2988+
Expression* start = nullptr;
29882989
if (op == StringEncodeWTF8) {
29892990
const char* str = s[i++]->c_str();
29902991
if (strncmp(str, "utf8", 4) == 0) {
@@ -2994,9 +2995,21 @@ Expression* SExpressionWasmBuilder::makeStringEncode(Element& s,
29942995
} else {
29952996
throw ParseException("bad string.new op", s.line, s.col);
29962997
}
2998+
} else if (op == StringEncodeWTF8Array) {
2999+
const char* str = s[i++]->c_str();
3000+
if (strncmp(str, "utf8", 4) == 0) {
3001+
op = StringEncodeUTF8Array;
3002+
} else if (strncmp(str, "wtf8", 4) == 0) {
3003+
op = StringEncodeWTF8Array;
3004+
} else {
3005+
throw ParseException("bad string.new op", s.line, s.col);
3006+
}
3007+
start = parseExpression(s[i + 2]);
3008+
} else if (op == StringEncodeWTF16Array) {
3009+
start = parseExpression(s[i + 2]);
29973010
}
29983011
return Builder(wasm).makeStringEncode(
2999-
op, parseExpression(s[i]), parseExpression(s[i + 1]));
3012+
op, parseExpression(s[i]), parseExpression(s[i + 1]), start);
30003013
}
30013014

30023015
Expression* SExpressionWasmBuilder::makeStringConcat(Element& s) {

src/wasm/wasm-stack.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,6 +2301,17 @@ void BinaryInstWriter::visitStringEncode(StringEncode* curr) {
23012301
case StringEncodeWTF16:
23022302
o << U32LEB(BinaryConsts::StringEncodeWTF16);
23032303
break;
2304+
case StringEncodeUTF8Array:
2305+
o << U32LEB(BinaryConsts::StringEncodeWTF8Array)
2306+
<< U32LEB(BinaryConsts::StringPolicy::UTF8);
2307+
break;
2308+
case StringEncodeWTF8Array:
2309+
o << U32LEB(BinaryConsts::StringEncodeWTF8Array)
2310+
<< U32LEB(BinaryConsts::StringPolicy::WTF8);
2311+
break;
2312+
case StringEncodeWTF16Array:
2313+
o << U32LEB(BinaryConsts::StringEncodeWTF16Array);
2314+
break;
23042315
default:
23052316
WASM_UNREACHABLE("invalid string.new*");
23062317
}

0 commit comments

Comments
 (0)