| 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) {
|
|
|