[turbofan] Add explicit set for nodes with weakened types.

To ensure termination, we need to be sure that once we start weakening
a node, we keep weakening that node in subsequent re-typings. Until now,
we were guessing that we previously weakened from the type. This
change introduces a set of nodes that have already be weakened, so
that we have a reliable way to detect previous weakening.

BUG=chromium:468799
LOG=n
R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1019883002

Cr-Commit-Position: refs/heads/master@{#27331}
This commit is contained in:
jarin 2015-03-20 02:12:42 -07:00 committed by Commit bot
parent b99f17a26f
commit adb8867337

View File

@ -212,7 +212,8 @@ Typer::~Typer() {
class Typer::Visitor : public Reducer { class Typer::Visitor : public Reducer {
public: public:
explicit Visitor(Typer* typer) : typer_(typer) {} explicit Visitor(Typer* typer)
: typer_(typer), weakened_nodes_(typer->zone()) {}
Reduction Reduce(Node* node) OVERRIDE { Reduction Reduce(Node* node) OVERRIDE {
if (node->op()->ValueOutputCount() == 0) return NoChange(); if (node->op()->ValueOutputCount() == 0) return NoChange();
@ -280,6 +281,7 @@ class Typer::Visitor : public Reducer {
private: private:
Typer* typer_; Typer* typer_;
MaybeHandle<Context> context_; MaybeHandle<Context> context_;
ZoneSet<NodeId> weakened_nodes_;
#define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
DECLARE_METHOD(Start) DECLARE_METHOD(Start)
@ -297,13 +299,18 @@ class Typer::Visitor : public Reducer {
} }
Bounds WrapContextBoundsForInput(Node* node); 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(); } Zone* zone() { return typer_->zone(); }
Isolate* isolate() { return typer_->isolate(); } Isolate* isolate() { return typer_->isolate(); }
Graph* graph() { return typer_->graph(); } Graph* graph() { return typer_->graph(); }
MaybeHandle<Context> context() { return typer_->context(); } 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* (*UnaryTyperFun)(Type*, Typer* t);
typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t);
@ -351,8 +358,8 @@ class Typer::Visitor : public Reducer {
Bounds previous = NodeProperties::GetBounds(node); Bounds previous = NodeProperties::GetBounds(node);
if (node->opcode() == IrOpcode::kPhi) { if (node->opcode() == IrOpcode::kPhi) {
// Speed up termination in the presence of range types: // Speed up termination in the presence of range types:
current.upper = Weaken(current.upper, previous.upper); current.upper = Weaken(node, current.upper, previous.upper);
current.lower = Weaken(current.lower, previous.lower); current.lower = Weaken(node, current.lower, previous.lower);
} }
// Types should not get less precise. // Types should not get less precise.
@ -1293,7 +1300,8 @@ Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
// the fixpoint calculation in case there appears to be a loop // the fixpoint calculation in case there appears to be a loop
// in the graph. In the current implementation, we are // in the graph. In the current implementation, we are
// increasing the limits to the closest power of two. // 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[] = { static const double kWeakenMinLimits[] = {
0.0, -1073741824.0, -2147483648.0, -4294967296.0, -8589934592.0, 0.0, -1073741824.0, -2147483648.0, -4294967296.0, -8589934592.0,
-17179869184.0, -34359738368.0, -68719476736.0, -137438953472.0, -17179869184.0, -34359738368.0, -68719476736.0, -137438953472.0,
@ -1311,24 +1319,35 @@ Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) {
STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits)); STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
// If the types have nothing to do with integers, return the types. // If the types have nothing to do with integers, return the types.
if (!current_type->Maybe(typer_->integer) || if (!previous_type->Maybe(typer_->integer)) {
!previous_type->Maybe(typer_->integer)) {
return current_type; return current_type;
} }
DCHECK(current_type->Maybe(typer_->integer));
Type::RangeType* previous = Type* current_integer =
Type::Intersect(previous_type, typer_->integer, zone())->GetRange(); Type::Intersect(current_type, typer_->integer, zone());
Type::RangeType* current = Type* previous_integer =
Type::Intersect(current_type, typer_->integer, zone())->GetRange(); Type::Intersect(previous_type, typer_->integer, zone());
if (current == nullptr || previous == nullptr) {
return current_type; // 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; double new_min = current_min;
// Find the closest lower entry in the list of allowed // Find the closest lower entry in the list of allowed
// minima (or negative infinity if there is no such entry). // 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(); new_min = typer_->integer->AsRange()->Min();
for (double const min : kWeakenMinLimits) { for (double const min : kWeakenMinLimits) {
if (min <= current_min) { if (min <= current_min) {
@ -1338,11 +1357,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; double new_max = current_max;
// Find the closest greater entry in the list of allowed // Find the closest greater entry in the list of allowed
// maxima (or infinity if there is no such entry). // 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(); new_max = typer_->integer->AsRange()->Max();
for (double const max : kWeakenMaxLimits) { for (double const max : kWeakenMaxLimits) {
if (max >= current_max) { if (max >= current_max) {