Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index 994a6384fdeba69e2cc9e13fee934e80e521ef15..6b32258d111bdc277bce729b4b6324487654e051 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -252,7 +252,7 @@ class Typer::RunVisitor : public Typer::Visitor { |
redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} |
GenericGraphVisit::Control Post(Node* node) { |
- if (node->op()->ValueOutputCount() > 0 && !NodeProperties::IsTyped(node)) { |
+ if (node->op()->ValueOutputCount() > 0) { |
Bounds bounds = TypeNode(node); |
NodeProperties::SetBounds(node, bounds); |
// Remember incompletely typed nodes for least fixpoint iteration. |
@@ -291,33 +291,64 @@ class Typer::NarrowVisitor : public Typer::Visitor { |
class Typer::WidenVisitor : public Typer::Visitor { |
public: |
- explicit WidenVisitor(Typer* typer) : Visitor(typer) {} |
+ explicit WidenVisitor(Typer* typer) |
+ : Visitor(typer), |
+ local_zone_(zone()->isolate()), |
+ enabled_(graph()->NodeCount(), true, &local_zone_), |
+ queue_(&local_zone_) {} |
+ |
+ void Run(NodeSet* nodes) { |
+ // Queue all the roots. |
+ for (Node* node : *nodes) { |
+ Queue(node); |
+ } |
- GenericGraphVisit::Control Pre(Node* node) { |
- if (node->op()->ValueOutputCount() > 0) { |
- Bounds previous = BoundsOrNone(node); |
- Bounds current = TypeNode(node); |
+ while (!queue_.empty()) { |
+ Node* node = queue_.front(); |
+ queue_.pop(); |
- // Speed up termination in the presence of range types: |
- current.upper = Weaken(current.upper, previous.upper); |
- current.lower = Weaken(current.lower, previous.lower); |
+ if (node->op()->ValueOutputCount() > 0) { |
+ // Enable future queuing (and thus re-typing) of this node. |
+ enabled_[node->id()] = true; |
- DCHECK(previous.lower->Is(current.lower)); |
- DCHECK(previous.upper->Is(current.upper)); |
+ // Compute the new type. |
+ Bounds previous = BoundsOrNone(node); |
+ Bounds current = TypeNode(node); |
- NodeProperties::SetBounds(node, current); |
- // Stop when nothing changed (but allow re-entry in case it does later). |
- return previous.Narrows(current) && current.Narrows(previous) |
- ? GenericGraphVisit::DEFER |
- : GenericGraphVisit::REENTER; |
- } else { |
- return GenericGraphVisit::SKIP; |
+ // Speed up termination in the presence of range types: |
+ current.upper = Weaken(current.upper, previous.upper); |
+ current.lower = Weaken(current.lower, previous.lower); |
+ |
+ // Types should not get less precise. |
+ DCHECK(previous.lower->Is(current.lower)); |
+ DCHECK(previous.upper->Is(current.upper)); |
+ |
+ NodeProperties::SetBounds(node, current); |
+ // If something changed, push all uses into the queue. |
+ if (!(previous.Narrows(current) && current.Narrows(previous))) { |
+ for (Node* use : node->uses()) { |
+ Queue(use); |
+ } |
+ } |
+ } |
+ // If there is no value output, we deliberately leave the node disabled |
+ // for queuing - there is no need to type it. |
} |
} |
- GenericGraphVisit::Control Post(Node* node) { |
- return GenericGraphVisit::REENTER; |
+ void Queue(Node* node) { |
+ // If the node is enabled for queuing, push it to the queue and disable it |
+ // (to avoid queuing it multiple times). |
+ if (enabled_[node->id()]) { |
+ queue_.push(node); |
+ enabled_[node->id()] = false; |
+ } |
} |
+ |
+ private: |
+ Zone local_zone_; |
+ BoolVector enabled_; |
+ ZoneQueue<Node*> queue_; |
}; |
@@ -326,9 +357,7 @@ void Typer::Run() { |
graph_->VisitNodeInputsFromEnd(&typing); |
// Find least fixpoint. |
WidenVisitor widen(this); |
- for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) { |
- graph_->VisitNodeUsesFrom(*it, &widen); |
- } |
+ widen.Run(&typing.redo); |
} |