Skip to content

Commit 24d71aa

Browse files
authored
[EH] Change Walker::TaskFunc back to function pointer (#3899)
`Walker::TaskFunc` has changed from a function pointer to `std::function` in #3494, mainly to make the EH support for `CFGWalker` easier. We didn't notice much performance difference then, but it was recently reported that it creased binaryen.js code size and performance. This changes `Walker::TaskFunc` back to a function pointer and does a little more work to manage catch index in `CFGWalker` side. Hopefully fixes #3857.
1 parent dede877 commit 24d71aa

File tree

4 files changed

+155
-14
lines changed

4 files changed

+155
-14
lines changed

src/cfg/cfg-traversal.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
101101
// but their usage does not overlap in time, and this is more efficient.
102102
std::vector<std::vector<BasicBlock*>> processCatchStack;
103103

104+
// Stack to store the catch indices within catch bodies. To be used in
105+
// doStartCatch and doEndCatch.
106+
std::vector<Index> catchIndexStack;
107+
104108
BasicBlock* startBasicBlock() {
105109
currBasicBlock = ((SubType*)this)->makeBasicBlock();
106110
basicBlocks.push_back(std::unique_ptr<BasicBlock>(currBasicBlock));
@@ -304,16 +308,20 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
304308
self->processCatchStack.push_back(self->unwindCatchStack.back());
305309
self->unwindCatchStack.pop_back();
306310
self->unwindExprStack.pop_back();
311+
self->catchIndexStack.push_back(0);
307312
}
308313

309-
static void doStartCatch(SubType* self, Expression** currp, Index i) {
314+
static void doStartCatch(SubType* self, Expression** currp) {
310315
// Get the block that starts this catch
311-
self->currBasicBlock = self->processCatchStack.back()[i];
316+
self->currBasicBlock =
317+
self->processCatchStack.back()[self->catchIndexStack.back()];
312318
}
313319

314-
static void doEndCatch(SubType* self, Expression** currp, Index i) {
320+
static void doEndCatch(SubType* self, Expression** currp) {
315321
// We are done with this catch; set the block that ends it
316-
self->processCatchStack.back()[i] = self->currBasicBlock;
322+
self->processCatchStack.back()[self->catchIndexStack.back()] =
323+
self->currBasicBlock;
324+
self->catchIndexStack.back()++;
317325
}
318326

319327
static void doEndTry(SubType* self, Expression** currp) {
@@ -326,6 +334,7 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
326334
self->link(self->tryStack.back(), self->currBasicBlock);
327335
self->tryStack.pop_back();
328336
self->processCatchStack.pop_back();
337+
self->catchIndexStack.pop_back();
329338
}
330339

331340
static void doEndThrow(SubType* self, Expression** currp) {
@@ -381,17 +390,10 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> {
381390
case Expression::Id::TryId: {
382391
self->pushTask(SubType::doEndTry, currp);
383392
auto& catchBodies = curr->cast<Try>()->catchBodies;
384-
using namespace std::placeholders;
385393
for (Index i = 0; i < catchBodies.size(); i++) {
386-
auto doEndCatchI = [i](SubType* self, Expression** currp) {
387-
doEndCatch(self, currp, i);
388-
};
389-
self->pushTask(doEndCatchI, currp);
394+
self->pushTask(doEndCatch, currp);
390395
self->pushTask(SubType::scan, &catchBodies[i]);
391-
auto doStartCatchI = [i](SubType* self, Expression** currp) {
392-
doStartCatch(self, currp, i);
393-
};
394-
self->pushTask(doStartCatchI, currp);
396+
self->pushTask(doStartCatch, currp);
395397
}
396398
self->pushTask(SubType::doStartCatches, currp);
397399
self->pushTask(SubType::scan, &curr->cast<Try>()->body);

src/wasm-traversal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ struct Walker : public VisitorType {
282282
// nested.
283283

284284
// Tasks receive the this pointer and a pointer to the pointer to operate on
285-
using TaskFunc = std::function<void(SubType*, Expression**)>;
285+
typedef void (*TaskFunc)(SubType*, Expression**);
286286

287287
struct Task {
288288
TaskFunc func;

test/passes/rse_all-features.txt

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
(type $i32_i32_=>_none (func (param i32 i32)))
55
(type $i32_f64_=>_none (func (param i32 f64)))
66
(event $e (attr 0) (param i32))
7+
(event $e2 (attr 0) (param))
78
(func $basic (param $x i32) (param $y f64)
89
(local $a f32)
910
(local $b i64)
@@ -645,4 +646,84 @@
645646
(i32.const 1)
646647
)
647648
)
649+
(func $nested-catch1
650+
(local $x i32)
651+
(try $try
652+
(do
653+
(throw $e
654+
(i32.const 0)
655+
)
656+
)
657+
(catch $e
658+
(drop
659+
(pop i32)
660+
)
661+
)
662+
(catch $e2
663+
(try $try6
664+
(do
665+
(throw $e
666+
(i32.const 0)
667+
)
668+
)
669+
(catch $e
670+
(drop
671+
(pop i32)
672+
)
673+
)
674+
(catch $e2
675+
(local.set $x
676+
(i32.const 1)
677+
)
678+
)
679+
)
680+
)
681+
)
682+
(local.set $x
683+
(i32.const 1)
684+
)
685+
)
686+
(func $nested-catch2
687+
(local $x i32)
688+
(try $try
689+
(do
690+
(throw $e
691+
(i32.const 0)
692+
)
693+
)
694+
(catch $e
695+
(drop
696+
(pop i32)
697+
)
698+
(local.set $x
699+
(i32.const 1)
700+
)
701+
)
702+
(catch_all
703+
(try $try7
704+
(do
705+
(throw $e
706+
(i32.const 0)
707+
)
708+
)
709+
(catch $e
710+
(drop
711+
(pop i32)
712+
)
713+
(local.set $x
714+
(i32.const 1)
715+
)
716+
)
717+
(catch_all
718+
(local.set $x
719+
(i32.const 1)
720+
)
721+
)
722+
)
723+
)
724+
)
725+
(drop
726+
(i32.const 1)
727+
)
728+
)
648729
)

test/passes/rse_all-features.wast

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@
288288
)
289289

290290
(event $e (attr 0) (param i32))
291+
(event $e2 (attr 0))
291292
(func $try1
292293
(local $x i32)
293294
(try
@@ -416,4 +417,61 @@
416417
;; so the local.set may not run. So this should NOT be dropped.
417418
(local.set $x (i32.const 1))
418419
)
420+
(func $nested-catch1
421+
(local $x i32)
422+
(try
423+
(do
424+
(throw $e (i32.const 0))
425+
)
426+
(catch $e
427+
(drop (pop i32))
428+
)
429+
(catch $e2
430+
(try
431+
(do
432+
(throw $e (i32.const 0))
433+
)
434+
(catch $e
435+
(drop (pop i32))
436+
)
437+
(catch $e2
438+
(local.set $x (i32.const 1))
439+
)
440+
)
441+
)
442+
)
443+
;; This should NOT be dropped because the exception might not be caught by
444+
;; the inner catches, and the local.set above us may not have run, and
445+
;; other possible code paths do not even set the local.
446+
(local.set $x (i32.const 1))
447+
)
448+
(func $nested-catch2
449+
(local $x i32)
450+
(try
451+
(do
452+
(throw $e (i32.const 0))
453+
)
454+
(catch $e
455+
(drop (pop i32))
456+
(local.set $x (i32.const 1))
457+
)
458+
(catch_all
459+
(try
460+
(do
461+
(throw $e (i32.const 0))
462+
)
463+
(catch $e
464+
(drop (pop i32))
465+
(local.set $x (i32.const 1))
466+
)
467+
(catch_all
468+
(local.set $x (i32.const 1))
469+
)
470+
)
471+
)
472+
)
473+
;; This should be dropped because the exception is guaranteed to be caught
474+
;; by one of the catches and it will set the local to 1.
475+
(local.set $x (i32.const 1))
476+
)
419477
)

0 commit comments

Comments
 (0)