Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index a36d6896f1876953c9c8cc5a25fe21c4f8c4baa5..a346d7aecc224bc00cf9d05de4290f3b24d2270a 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -212,7 +212,8 @@ Typer::~Typer() { |
class Typer::Visitor : public Reducer { |
public: |
- explicit Visitor(Typer* typer) : typer_(typer) {} |
+ explicit Visitor(Typer* typer) |
+ : typer_(typer), weakened_nodes_(typer->zone()) {} |
Reduction Reduce(Node* node) OVERRIDE { |
if (node->op()->ValueOutputCount() == 0) return NoChange(); |
@@ -280,6 +281,7 @@ class Typer::Visitor : public Reducer { |
private: |
Typer* typer_; |
MaybeHandle<Context> context_; |
+ ZoneSet<NodeId> weakened_nodes_; |
#define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); |
DECLARE_METHOD(Start) |
@@ -297,13 +299,18 @@ class Typer::Visitor : public Reducer { |
} |
Bounds WrapContextBoundsForInput(Node* node); |
- Type* Weaken(Type* current_type, Type* previous_type); |
+ Type* Weaken(Node* node, Type* current_type, Type* previous_type); |
Zone* zone() { return typer_->zone(); } |
Isolate* isolate() { return typer_->isolate(); } |
Graph* graph() { return typer_->graph(); } |
MaybeHandle<Context> context() { return typer_->context(); } |
+ void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); } |
+ bool IsWeakened(NodeId node_id) { |
+ return weakened_nodes_.find(node_id) != weakened_nodes_.end(); |
+ } |
+ |
typedef Type* (*UnaryTyperFun)(Type*, Typer* t); |
typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); |
@@ -351,8 +358,8 @@ class Typer::Visitor : public Reducer { |
Bounds previous = NodeProperties::GetBounds(node); |
if (node->opcode() == IrOpcode::kPhi) { |
// Speed up termination in the presence of range types: |
- current.upper = Weaken(current.upper, previous.upper); |
- current.lower = Weaken(current.lower, previous.lower); |
+ current.upper = Weaken(node, current.upper, previous.upper); |
+ current.lower = Weaken(node, current.lower, previous.lower); |
} |
// Types should not get less precise. |
@@ -1288,7 +1295,8 @@ Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { |
// the fixpoint calculation in case there appears to be a loop |
// in the graph. In the current implementation, we are |
// increasing the limits to the closest power of two. |
-Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) { |
+Type* Typer::Visitor::Weaken(Node* node, Type* current_type, |
+ Type* previous_type) { |
static const double kWeakenMinLimits[] = { |
0.0, -1073741824.0, -2147483648.0, -4294967296.0, -8589934592.0, |
-17179869184.0, -34359738368.0, -68719476736.0, -137438953472.0, |
@@ -1306,24 +1314,35 @@ Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) { |
STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits)); |
// If the types have nothing to do with integers, return the types. |
- if (!current_type->Maybe(typer_->integer) || |
- !previous_type->Maybe(typer_->integer)) { |
+ if (!previous_type->Maybe(typer_->integer)) { |
return current_type; |
} |
- |
- Type::RangeType* previous = |
- Type::Intersect(previous_type, typer_->integer, zone())->GetRange(); |
- Type::RangeType* current = |
- Type::Intersect(current_type, typer_->integer, zone())->GetRange(); |
- if (current == nullptr || previous == nullptr) { |
- return current_type; |
+ DCHECK(current_type->Maybe(typer_->integer)); |
+ |
+ Type* current_integer = |
+ Type::Intersect(current_type, typer_->integer, zone()); |
+ Type* previous_integer = |
+ Type::Intersect(previous_type, typer_->integer, zone()); |
+ |
+ // Once we start weakening a node, we should always weaken. |
+ if (!IsWeakened(node->id())) { |
+ // Only weaken if there is range involved; we should converge quickly |
+ // for all other types (the exception is a union of many constants, |
+ // but we currently do not increase the number of constants in unions). |
+ Type::RangeType* previous = previous_integer->GetRange(); |
+ Type::RangeType* current = current_integer->GetRange(); |
+ if (current == nullptr || previous == nullptr) { |
+ return current_type; |
+ } |
+ // Range is involved => we are weakening. |
+ SetWeakened(node->id()); |
} |
- double current_min = current->Min(); |
+ double current_min = current_integer->Min(); |
double new_min = current_min; |
// Find the closest lower entry in the list of allowed |
// minima (or negative infinity if there is no such entry). |
- if (current_min != previous->Min()) { |
+ if (current_min != previous_integer->Min()) { |
new_min = typer_->integer->AsRange()->Min(); |
for (double const min : kWeakenMinLimits) { |
if (min <= current_min) { |
@@ -1333,11 +1352,11 @@ Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) { |
} |
} |
- double current_max = current->Max(); |
+ double current_max = current_integer->Max(); |
double new_max = current_max; |
// Find the closest greater entry in the list of allowed |
// maxima (or infinity if there is no such entry). |
- if (current_max != previous->Max()) { |
+ if (current_max != previous_integer->Max()) { |
new_max = typer_->integer->AsRange()->Max(); |
for (double const max : kWeakenMaxLimits) { |
if (max >= current_max) { |