[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:
parent
b99f17a26f
commit
adb8867337
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user