Skip to content

Commit 4a907b0

Browse files
authored
[Parser][NFC] Solve performance issue by adding maybeLabelidx (#6514)
Creating an error in the parser is an extremely expensive operation for very large files because it has to traverse the input buffer and count newlines to compute the error message. Despite that, there are a few places were we create errors just to discard them and continue parsing. The most notable of these places was where we parsed the list of label index immediates for the br_table instruction. The parser determined the end of the list by intercepting the error produced when trying to parse one more label index. Fix this significant performance problem causing parsing to be quadratic by introducing and using `maybeLabelidx`, which tries to parse a label index but does not produce an error if it fails.
1 parent d39b4fa commit 4a907b0

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

src/parser/parsers.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,9 @@ template<typename Ctx> Result<typename Ctx::ElemIdxT> elemidx(Ctx&);
330330
template<typename Ctx> Result<typename Ctx::DataIdxT> dataidx(Ctx&);
331331
template<typename Ctx> Result<typename Ctx::LocalIdxT> localidx(Ctx&);
332332
template<typename Ctx>
333+
MaybeResult<typename Ctx::LabelIdxT> maybeLabelidx(Ctx&,
334+
bool inDelegate = false);
335+
template<typename Ctx>
333336
Result<typename Ctx::LabelIdxT> labelidx(Ctx&, bool inDelegate = false);
334337
template<typename Ctx> Result<typename Ctx::TagIdxT> tagidx(Ctx&);
335338
template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx&);
@@ -1969,16 +1972,18 @@ Result<> makeBreakTable(Ctx& ctx,
19691972
Index pos,
19701973
const std::vector<Annotation>& annotations) {
19711974
std::vector<typename Ctx::LabelIdxT> labels;
1975+
// Parse at least one label; return an error only if we parse none.
19721976
while (true) {
1973-
// Parse at least one label; return an error only if we parse none.
1974-
auto label = labelidx(ctx);
1975-
if (labels.empty()) {
1976-
CHECK_ERR(label);
1977-
} else if (label.getErr()) {
1977+
auto label = maybeLabelidx(ctx);
1978+
if (!label) {
19781979
break;
19791980
}
1981+
CHECK_ERR(label);
19801982
labels.push_back(*label);
19811983
}
1984+
if (labels.empty()) {
1985+
return ctx.in.err("expected label");
1986+
}
19821987
auto defaultLabel = labels.back();
19831988
labels.pop_back();
19841989
return ctx.makeSwitch(pos, annotations, labels, defaultLabel);
@@ -2701,17 +2706,26 @@ template<typename Ctx> Result<typename Ctx::LocalIdxT> localidx(Ctx& ctx) {
27012706
return ctx.in.err("expected local index or identifier");
27022707
}
27032708

2709+
template<typename Ctx>
2710+
Result<typename Ctx::LabelIdxT> labelidx(Ctx& ctx, bool inDelegate) {
2711+
if (auto idx = maybeLabelidx(ctx, inDelegate)) {
2712+
CHECK_ERR(idx);
2713+
return *idx;
2714+
}
2715+
return ctx.in.err("expected label index or identifier");
2716+
}
2717+
27042718
// labelidx ::= x:u32 => x
27052719
// | v:id => x (if labels[x] = v)
27062720
template<typename Ctx>
2707-
Result<typename Ctx::LabelIdxT> labelidx(Ctx& ctx, bool inDelegate) {
2721+
MaybeResult<typename Ctx::LabelIdxT> maybeLabelidx(Ctx& ctx, bool inDelegate) {
27082722
if (auto x = ctx.in.takeU32()) {
27092723
return ctx.getLabelFromIdx(*x, inDelegate);
27102724
}
27112725
if (auto id = ctx.in.takeID()) {
27122726
return ctx.getLabelFromName(*id, inDelegate);
27132727
}
2714-
return ctx.in.err("expected label index or identifier");
2728+
return {};
27152729
}
27162730

27172731
// tagidx ::= x:u32 => x

0 commit comments

Comments
 (0)