Skip to content

Commit 92c10bc

Browse files
authored
Optimize stack writer on deeply nested blocks, fixes #1903 (#1905)
also remove some old debugging
1 parent 9628a03 commit 92c10bc

File tree

1 file changed

+55
-43
lines changed

1 file changed

+55
-43
lines changed

src/wasm-stack.h

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -359,24 +359,62 @@ void StackWriter<Mode, Parent>::visitChild(Expression* curr) {
359359

360360
template<StackWriterMode Mode, typename Parent>
361361
void StackWriter<Mode, Parent>::visitBlock(Block* curr) {
362-
if (Mode == StackWriterMode::Binaryen2Stack) {
363-
stackIR.push_back(makeStackInst(StackInst::BlockBegin, curr));
364-
} else {
365-
if (debug) std::cerr << "zz node: Block" << std::endl;
366-
o << int8_t(BinaryConsts::Block);
367-
o << binaryType(curr->type != unreachable ? curr->type : none);
368-
}
369-
breakStack.push_back(curr->name); // TODO: we don't need to do this in Binaryen2Stack
370-
Index i = 0;
371-
for (auto* child : curr->list) {
372-
if (debug) std::cerr << " " << size_t(curr) << "\n zz Block element " << i++ << std::endl;
373-
visitChild(child);
374-
}
375-
// in Stack2Binary the block ending is in the stream later on
376-
if (Mode == StackWriterMode::Stack2Binary) {
377-
return;
362+
auto tilChildren = [this](Block* curr) {
363+
if (Mode == StackWriterMode::Binaryen2Stack) {
364+
stackIR.push_back(makeStackInst(StackInst::BlockBegin, curr));
365+
} else {
366+
o << int8_t(BinaryConsts::Block);
367+
o << binaryType(curr->type != unreachable ? curr->type : none);
368+
}
369+
breakStack.push_back(curr->name); // TODO: we don't need to do this in Binaryen2Stack
370+
};
371+
auto visitChildren = [this](Block* curr, Index from) {
372+
auto& list = curr->list;
373+
while (from < list.size()) {
374+
visitChild(list[from++]);
375+
}
376+
};
377+
auto afterChildren = [this](Block* curr) {
378+
// in Stack2Binary the block ending is in the stream later on
379+
if (Mode != StackWriterMode::Stack2Binary) {
380+
visitBlockEnd(curr);
381+
}
382+
};
383+
// Handle very deeply nested blocks in the first position efficiently,
384+
// avoiding heavy recursion.
385+
// We only start to do this if we see it will help us (to avoid allocation
386+
// of the vector).
387+
// Note that Stack2Binary mode we don't need to visit children anyhow, so
388+
// we don't need this optimization.
389+
if (Mode != StackWriterMode::Stack2Binary) {
390+
if (!curr->list.empty() && curr->list[0]->is<Block>()) {
391+
std::vector<Block*> parents;
392+
Block* child;
393+
while (!curr->list.empty() &&
394+
(child = curr->list[0]->dynCast<Block>())) {
395+
parents.push_back(curr);
396+
tilChildren(curr);
397+
curr = child;
398+
}
399+
// Emit the current block, which does not have a block as
400+
// a child in the first position.
401+
tilChildren(curr);
402+
visitChildren(curr, 0);
403+
afterChildren(curr);
404+
// Finish the later parts of all the parent blocks.
405+
while (!parents.empty()) {
406+
auto* parent = parents.back();
407+
parents.pop_back();
408+
visitChildren(parent, 1);
409+
afterChildren(parent);
410+
}
411+
return;
412+
}
378413
}
379-
visitBlockEnd(curr);
414+
// Simple case of not having a nested block in the first position.
415+
tilChildren(curr);
416+
visitChildren(curr, 0);
417+
afterChildren(curr);
380418
}
381419

382420
template<StackWriterMode Mode, typename Parent>
@@ -403,7 +441,6 @@ void StackWriter<Mode, Parent>::visitBlockEnd(Block* curr) {
403441

404442
template<StackWriterMode Mode, typename Parent>
405443
void StackWriter<Mode, Parent>::visitIf(If* curr) {
406-
if (debug) std::cerr << "zz node: If" << std::endl;
407444
if (curr->condition->type == unreachable) {
408445
// this if-else is unreachable because of the condition, i.e., the condition
409446
// does not exit. So don't emit the if, but do consume the condition
@@ -465,7 +502,6 @@ void StackWriter<Mode, Parent>::visitIfEnd(If* curr) {
465502

466503
template<StackWriterMode Mode, typename Parent>
467504
void StackWriter<Mode, Parent>::visitLoop(Loop* curr) {
468-
if (debug) std::cerr << "zz node: Loop" << std::endl;
469505
if (Mode == StackWriterMode::Binaryen2Stack) {
470506
stackIR.push_back(makeStackInst(StackInst::LoopBegin, curr));
471507
} else {
@@ -502,7 +538,6 @@ void StackWriter<Mode, Parent>::visitLoopEnd(Loop* curr) {
502538

503539
template<StackWriterMode Mode, typename Parent>
504540
void StackWriter<Mode, Parent>::visitBreak(Break* curr) {
505-
if (debug) std::cerr << "zz node: Break" << std::endl;
506541
if (curr->value) {
507542
visitChild(curr->value);
508543
}
@@ -525,7 +560,6 @@ void StackWriter<Mode, Parent>::visitBreak(Break* curr) {
525560

526561
template<StackWriterMode Mode, typename Parent>
527562
void StackWriter<Mode, Parent>::visitSwitch(Switch* curr) {
528-
if (debug) std::cerr << "zz node: Switch" << std::endl;
529563
if (curr->value) {
530564
visitChild(curr->value);
531565
}
@@ -547,7 +581,6 @@ void StackWriter<Mode, Parent>::visitSwitch(Switch* curr) {
547581

548582
template<StackWriterMode Mode, typename Parent>
549583
void StackWriter<Mode, Parent>::visitCall(Call* curr) {
550-
if (debug) std::cerr << "zz node: Call" << std::endl;
551584
for (auto* operand : curr->operands) {
552585
visitChild(operand);
553586
}
@@ -561,7 +594,6 @@ void StackWriter<Mode, Parent>::visitCall(Call* curr) {
561594

562595
template<StackWriterMode Mode, typename Parent>
563596
void StackWriter<Mode, Parent>::visitCallIndirect(CallIndirect* curr) {
564-
if (debug) std::cerr << "zz node: CallIndirect" << std::endl;
565597
for (auto* operand : curr->operands) {
566598
visitChild(operand);
567599
}
@@ -578,14 +610,12 @@ void StackWriter<Mode, Parent>::visitCallIndirect(CallIndirect* curr) {
578610

579611
template<StackWriterMode Mode, typename Parent>
580612
void StackWriter<Mode, Parent>::visitGetLocal(GetLocal* curr) {
581-
if (debug) std::cerr << "zz node: GetLocal " << (o.size() + 1) << std::endl;
582613
if (justAddToStack(curr)) return;
583614
o << int8_t(BinaryConsts::GetLocal) << U32LEB(mappedLocals[curr->index]);
584615
}
585616

586617
template<StackWriterMode Mode, typename Parent>
587618
void StackWriter<Mode, Parent>::visitSetLocal(SetLocal* curr) {
588-
if (debug) std::cerr << "zz node: Set|TeeLocal" << std::endl;
589619
visitChild(curr->value);
590620
if (!justAddToStack(curr)) {
591621
o << int8_t(curr->isTee() ? BinaryConsts::TeeLocal : BinaryConsts::SetLocal) << U32LEB(mappedLocals[curr->index]);
@@ -597,22 +627,19 @@ void StackWriter<Mode, Parent>::visitSetLocal(SetLocal* curr) {
597627

598628
template<StackWriterMode Mode, typename Parent>
599629
void StackWriter<Mode, Parent>::visitGetGlobal(GetGlobal* curr) {
600-
if (debug) std::cerr << "zz node: GetGlobal " << (o.size() + 1) << std::endl;
601630
if (justAddToStack(curr)) return;
602631
o << int8_t(BinaryConsts::GetGlobal) << U32LEB(parent.getGlobalIndex(curr->name));
603632
}
604633

605634
template<StackWriterMode Mode, typename Parent>
606635
void StackWriter<Mode, Parent>::visitSetGlobal(SetGlobal* curr) {
607-
if (debug) std::cerr << "zz node: SetGlobal" << std::endl;
608636
visitChild(curr->value);
609637
if (justAddToStack(curr)) return;
610638
o << int8_t(BinaryConsts::SetGlobal) << U32LEB(parent.getGlobalIndex(curr->name));
611639
}
612640

613641
template<StackWriterMode Mode, typename Parent>
614642
void StackWriter<Mode, Parent>::visitLoad(Load* curr) {
615-
if (debug) std::cerr << "zz node: Load" << std::endl;
616643
visitChild(curr->ptr);
617644
if (curr->type == unreachable) {
618645
// don't even emit it; we don't know the right type
@@ -678,7 +705,6 @@ void StackWriter<Mode, Parent>::visitLoad(Load* curr) {
678705

679706
template<StackWriterMode Mode, typename Parent>
680707
void StackWriter<Mode, Parent>::visitStore(Store* curr) {
681-
if (debug) std::cerr << "zz node: Store" << std::endl;
682708
visitChild(curr->ptr);
683709
visitChild(curr->value);
684710
if (curr->type == unreachable) {
@@ -744,7 +770,6 @@ void StackWriter<Mode, Parent>::visitStore(Store* curr) {
744770

745771
template<StackWriterMode Mode, typename Parent>
746772
void StackWriter<Mode, Parent>::visitAtomicRMW(AtomicRMW* curr) {
747-
if (debug) std::cerr << "zz node: AtomicRMW" << std::endl;
748773
visitChild(curr->ptr);
749774
// stop if the rest isn't reachable anyhow
750775
if (curr->ptr->type == unreachable) return;
@@ -799,7 +824,6 @@ void StackWriter<Mode, Parent>::visitAtomicRMW(AtomicRMW* curr) {
799824

800825
template<StackWriterMode Mode, typename Parent>
801826
void StackWriter<Mode, Parent>::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
802-
if (debug) std::cerr << "zz node: AtomicCmpxchg" << std::endl;
803827
visitChild(curr->ptr);
804828
// stop if the rest isn't reachable anyhow
805829
if (curr->ptr->type == unreachable) return;
@@ -840,7 +864,6 @@ void StackWriter<Mode, Parent>::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
840864

841865
template<StackWriterMode Mode, typename Parent>
842866
void StackWriter<Mode, Parent>::visitAtomicWait(AtomicWait* curr) {
843-
if (debug) std::cerr << "zz node: AtomicWait" << std::endl;
844867
visitChild(curr->ptr);
845868
// stop if the rest isn't reachable anyhow
846869
if (curr->ptr->type == unreachable) return;
@@ -868,7 +891,6 @@ void StackWriter<Mode, Parent>::visitAtomicWait(AtomicWait* curr) {
868891

869892
template<StackWriterMode Mode, typename Parent>
870893
void StackWriter<Mode, Parent>::visitAtomicWake(AtomicWake* curr) {
871-
if (debug) std::cerr << "zz node: AtomicWake" << std::endl;
872894
visitChild(curr->ptr);
873895
// stop if the rest isn't reachable anyhow
874896
if (curr->ptr->type == unreachable) return;
@@ -1001,7 +1023,6 @@ void StackWriter<Mode, Parent>::visitMemoryFill(MemoryFill* curr) {
10011023

10021024
template<StackWriterMode Mode, typename Parent>
10031025
void StackWriter<Mode, Parent>::visitConst(Const* curr) {
1004-
if (debug) std::cerr << "zz node: Const" << curr << " : " << curr->type << std::endl;
10051026
if (justAddToStack(curr)) return;
10061027
switch (curr->type) {
10071028
case i32: {
@@ -1032,12 +1053,10 @@ void StackWriter<Mode, Parent>::visitConst(Const* curr) {
10321053
case unreachable:
10331054
WASM_UNREACHABLE();
10341055
}
1035-
if (debug) std::cerr << "zz const node done.\n";
10361056
}
10371057

10381058
template<StackWriterMode Mode, typename Parent>
10391059
void StackWriter<Mode, Parent>::visitUnary(Unary* curr) {
1040-
if (debug) std::cerr << "zz node: Unary" << std::endl;
10411060
visitChild(curr->value);
10421061
if (curr->type == unreachable) {
10431062
emitExtraUnreachable();
@@ -1144,7 +1163,6 @@ void StackWriter<Mode, Parent>::visitUnary(Unary* curr) {
11441163

11451164
template<StackWriterMode Mode, typename Parent>
11461165
void StackWriter<Mode, Parent>::visitBinary(Binary* curr) {
1147-
if (debug) std::cerr << "zz node: Binary" << std::endl;
11481166
visitChild(curr->left);
11491167
visitChild(curr->right);
11501168
if (curr->type == unreachable) {
@@ -1317,7 +1335,6 @@ void StackWriter<Mode, Parent>::visitBinary(Binary* curr) {
13171335

13181336
template<StackWriterMode Mode, typename Parent>
13191337
void StackWriter<Mode, Parent>::visitSelect(Select* curr) {
1320-
if (debug) std::cerr << "zz node: Select" << std::endl;
13211338
visitChild(curr->ifTrue);
13221339
visitChild(curr->ifFalse);
13231340
visitChild(curr->condition);
@@ -1331,7 +1348,6 @@ void StackWriter<Mode, Parent>::visitSelect(Select* curr) {
13311348

13321349
template<StackWriterMode Mode, typename Parent>
13331350
void StackWriter<Mode, Parent>::visitReturn(Return* curr) {
1334-
if (debug) std::cerr << "zz node: Return" << std::endl;
13351351
if (curr->value) {
13361352
visitChild(curr->value);
13371353
}
@@ -1342,7 +1358,6 @@ void StackWriter<Mode, Parent>::visitReturn(Return* curr) {
13421358

13431359
template<StackWriterMode Mode, typename Parent>
13441360
void StackWriter<Mode, Parent>::visitHost(Host* curr) {
1345-
if (debug) std::cerr << "zz node: Host" << std::endl;
13461361
switch (curr->op) {
13471362
case CurrentMemory: {
13481363
break;
@@ -1368,21 +1383,18 @@ void StackWriter<Mode, Parent>::visitHost(Host* curr) {
13681383

13691384
template<StackWriterMode Mode, typename Parent>
13701385
void StackWriter<Mode, Parent>::visitNop(Nop* curr) {
1371-
if (debug) std::cerr << "zz node: Nop" << std::endl;
13721386
if (justAddToStack(curr)) return;
13731387
o << int8_t(BinaryConsts::Nop);
13741388
}
13751389

13761390
template<StackWriterMode Mode, typename Parent>
13771391
void StackWriter<Mode, Parent>::visitUnreachable(Unreachable* curr) {
1378-
if (debug) std::cerr << "zz node: Unreachable" << std::endl;
13791392
if (justAddToStack(curr)) return;
13801393
o << int8_t(BinaryConsts::Unreachable);
13811394
}
13821395

13831396
template<StackWriterMode Mode, typename Parent>
13841397
void StackWriter<Mode, Parent>::visitDrop(Drop* curr) {
1385-
if (debug) std::cerr << "zz node: Drop" << std::endl;
13861398
visitChild(curr->value);
13871399
if (justAddToStack(curr)) return;
13881400
o << int8_t(BinaryConsts::Drop);

0 commit comments

Comments
 (0)