diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-04-05 14:49:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-05 14:49:25 -0700 |
commit | 5b5789495a97602869f18d552b2a9e1814edefae (patch) | |
tree | f70e304fc85dca03ebd6d2311007476700e1ffd0 | |
parent | 82151243bbd4c018191721dce5381c8e449f3c77 (diff) | |
download | binaryen-5b5789495a97602869f18d552b2a9e1814edefae.tar.gz binaryen-5b5789495a97602869f18d552b2a9e1814edefae.tar.bz2 binaryen-5b5789495a97602869f18d552b2a9e1814edefae.zip |
when creating blocks in binary format parsing, we know if a block has a break to it - use that to avoid rescanning blocks for unreachability purposes (#1495)
-rw-r--r-- | src/wasm-binary.h | 1 | ||||
-rw-r--r-- | src/wasm.h | 13 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 2 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 28 |
4 files changed, 31 insertions, 13 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index e03fd29ea..b8eb86d31 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -890,6 +890,7 @@ public: BreakTarget(Name name, int arity) : name(name), arity(arity) {} }; std::vector<BreakTarget> breakStack; + // the names that breaks target. this lets us know if a block has breaks to it or not. std::unordered_set<Name> breakTargetNames; std::vector<Expression*> expressionStack; diff --git a/src/wasm.h b/src/wasm.h index f5802052b..9d8648308 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -250,13 +250,20 @@ public: Name name; ExpressionList list; + // set the type purely based on its contents. this scans the block, so it is not fast. + void finalize(); + // set the type given you know its type, which is the case when parsing // s-expression or binary, as explicit types are given. the only additional work - // this does is to set the type to unreachable in the cases that is needed. + // this does is to set the type to unreachable in the cases that is needed + // (which may require scanning the block) void finalize(Type type_); - // set the type purely based on its contents. this scans the block, so it is not fast - void finalize(); + // set the type given you know its type, and you know if there is a break to this + // block. this avoids the need to scan the contents of the block in the case that + // it might be unreachable, so it is recommended if you already know the type + // and breakability anyhow. + void finalize(Type type_, bool hasBreak); }; class If : public SpecificExpression<Expression::IfId> { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 7a459eb7f..f70f74c56 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2375,7 +2375,7 @@ void WasmBinaryBuilder::visitBlock(Block *curr) { throw ParseException("block cannot pop from outside"); } pushBlockElements(curr, start, end); - curr->finalize(curr->type); + curr->finalize(curr->type, breakTargetNames.find(curr->name) != breakTargetNames.end() /* hasBreak */); breakStack.pop_back(); breakTargetNames.erase(curr->name); } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index cf847d5aa..5fc2ee715 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -171,7 +171,7 @@ static Type mergeTypes(std::vector<Type>& types) { // a block is unreachable if one of its elements is unreachable, // and there are no branches to it -static void handleUnreachable(Block* block) { +static void handleUnreachable(Block* block, bool breakabilityKnown=false, bool hasBreak=false) { if (block->type == unreachable) return; // nothing to do if (block->list.size() == 0) return; // nothing to do // if we are concrete, stop - even an unreachable child @@ -182,7 +182,10 @@ static void handleUnreachable(Block* block) { for (auto* child : block->list) { if (child->type == unreachable) { // there is an unreachable child, so we are unreachable, unless we have a break - if (!BranchUtils::BranchSeeker::hasNamed(block, block->name)) { + if (!breakabilityKnown) { + hasBreak = BranchUtils::BranchSeeker::hasNamed(block, block->name); + } + if (!hasBreak) { block->type = unreachable; } return; @@ -190,13 +193,6 @@ static void handleUnreachable(Block* block) { } } -void Block::finalize(Type type_) { - type = type_; - if (type == none && list.size() > 0) { - handleUnreachable(this); - } -} - void Block::finalize() { if (!name.is()) { if (list.size() > 0) { @@ -231,6 +227,20 @@ void Block::finalize() { handleUnreachable(this); } +void Block::finalize(Type type_) { + type = type_; + if (type == none && list.size() > 0) { + handleUnreachable(this); + } +} + +void Block::finalize(Type type_, bool hasBreak) { + type = type_; + if (type == none && list.size() > 0) { + handleUnreachable(this, true, hasBreak); + } +} + void If::finalize(Type type_) { type = type_; if (type == none && (condition->type == unreachable || (ifFalse && ifTrue->type == unreachable && ifFalse->type == unreachable))) { |