Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Unified Diff: src/compiler/typer.cc

Issue 769303002: [turbofan] Reuse forward fixpoint algorithm in Typer by making it a Reducer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/typer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/typer.cc
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 67b73ebad00f1896104c65864d415ac24694906b..e5b7b839708ec537d23ce6978b99712ea45dc148 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -4,6 +4,7 @@
#include "src/bootstrapper.h"
#include "src/compiler/graph-inl.h"
+#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/node-properties-inl.h"
@@ -217,10 +218,42 @@ Typer::~Typer() {
}
-class Typer::Visitor : public NullNodeVisitor {
+class Typer::Visitor : public Reducer {
public:
explicit Visitor(Typer* typer) : typer_(typer) {}
+ virtual Reduction Reduce(Node* node) OVERRIDE {
+ if (node->op()->ValueOutputCount() == 0) return NoChange();
+ switch (node->opcode()) {
+#define DECLARE_CASE(x) \
+ case IrOpcode::k##x: \
+ return UpdateBounds(node, TypeBinaryOp(node, x##Typer));
+ JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
+#undef DECLARE_CASE
+
+#define DECLARE_CASE(x) \
+ case IrOpcode::k##x: \
+ return UpdateBounds(node, Type##x(node));
+ DECLARE_CASE(Start)
+ // VALUE_OP_LIST without JS_SIMPLE_BINOP_LIST:
+ COMMON_OP_LIST(DECLARE_CASE)
+ SIMPLIFIED_OP_LIST(DECLARE_CASE)
+ MACHINE_OP_LIST(DECLARE_CASE)
+ JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
+ JS_OBJECT_OP_LIST(DECLARE_CASE)
+ JS_CONTEXT_OP_LIST(DECLARE_CASE)
+ JS_OTHER_OP_LIST(DECLARE_CASE)
+#undef DECLARE_CASE
+
+#define DECLARE_CASE(x) case IrOpcode::k##x:
+ DECLARE_CASE(End)
+ INNER_CONTROL_OP_LIST(DECLARE_CASE)
+#undef DECLARE_CASE
+ break;
+ }
+ return NoChange();
+ }
+
Bounds TypeNode(Node* node) {
switch (node->opcode()) {
#define DECLARE_CASE(x) \
@@ -252,7 +285,10 @@ class Typer::Visitor : public NullNodeVisitor {
Type* TypeConstant(Handle<Object> value);
- protected:
+ private:
+ Typer* typer_;
+ MaybeHandle<Context> context_;
+
#define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
DECLARE_METHOD(Start)
VALUE_OP_LIST(DECLARE_METHOD)
@@ -283,10 +319,6 @@ class Typer::Visitor : public NullNodeVisitor {
Graph* graph() { return typer_->graph(); }
MaybeHandle<Context> context() { return typer_->context(); }
- private:
- Typer* typer_;
- MaybeHandle<Context> context_;
-
typedef Type* (*UnaryTyperFun)(Type*, Typer* t);
typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t);
@@ -319,97 +351,60 @@ class Typer::Visitor : public NullNodeVisitor {
static Type* JSUnaryNotTyper(Type*, Typer*);
static Type* JSLoadPropertyTyper(Type*, Type*, Typer*);
static Type* JSCallFunctionTyper(Type*, Typer*);
-};
-
-class Typer::RunVisitor : public Typer::Visitor {
- public:
- explicit RunVisitor(Typer* typer)
- : Visitor(typer),
- redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
-
- void Post(Node* node) {
- if (node->op()->ValueOutputCount() > 0) {
- Bounds bounds = TypeNode(node);
- NodeProperties::SetBounds(node, bounds);
- // Remember incompletely typed nodes for least fixpoint iteration.
- if (!NodeProperties::AllValueInputsAreTyped(node)) redo.insert(node);
+ Reduction UpdateBounds(Node* node, Bounds current) {
+ if (NodeProperties::IsTyped(node)) {
+ // Widen the bounds of a previously typed node.
+ Bounds previous = NodeProperties::GetBounds(node);
+ // 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 (!(previous.Narrows(current) && current.Narrows(previous))) {
+ // If something changed, revisit all uses.
+ return Changed(node);
+ }
+ return NoChange();
+ } else {
+ // No previous type, simply update the bounds.
+ NodeProperties::SetBounds(node, current);
+ return Changed(node);
}
}
-
- NodeSet redo;
};
-class Typer::WidenVisitor : public Typer::Visitor {
- public:
- 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);
- }
-
- while (!queue_.empty()) {
- Node* node = queue_.front();
- queue_.pop();
-
- if (node->op()->ValueOutputCount() > 0) {
- // Enable future queuing (and thus re-typing) of this node.
- enabled_[node->id()] = true;
-
- // Compute the new type.
- Bounds previous = BoundsOrNone(node);
- Bounds current = TypeNode(node);
-
- // 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);
- }
+void Typer::Run() {
+ {
+ // TODO(titzer): this is a hack. Reset types for interior nodes first.
+ NodeDeque deque(zone());
+ NodeMarker<bool> marked(graph(), 2);
+ deque.push_front(graph()->end());
+ marked.Set(graph()->end(), true);
+ while (!deque.empty()) {
+ Node* node = deque.front();
+ deque.pop_front();
+ // TODO(titzer): there shouldn't be a need to retype constants.
+ if (node->op()->ValueOutputCount() > 0)
+ NodeProperties::RemoveBounds(node);
+ for (Node* input : node->inputs()) {
+ if (!marked.Get(input)) {
+ marked.Set(input, true);
+ deque.push_back(input);
}
}
- // If there is no value output, we deliberately leave the node disabled
- // for queuing - there is no need to type it.
- }
- }
-
- 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_;
-};
-
-
-void Typer::Run() {
- RunVisitor typing(this);
- graph_->VisitNodeInputsFromEnd(&typing);
- // Find least fixpoint.
- WidenVisitor widen(this);
- widen.Run(&typing.redo);
+ Visitor visitor(this);
+ GraphReducer graph_reducer(graph(), zone());
+ graph_reducer.AddReducer(&visitor);
+ graph_reducer.ReduceGraph();
}
@@ -1302,12 +1297,17 @@ Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
Bounds outer = Operand(node, 0);
- DCHECK(outer.upper->Maybe(Type::Internal()));
+ Type* context_type = outer.upper;
+ if (context_type->Is(Type::None())) {
+ // Upper bound of context is not yet known.
+ return Bounds(Type::None(), Type::Any());
+ }
+
+ DCHECK(context_type->Maybe(Type::Internal()));
// TODO(rossberg): More precisely, instead of the above assertion, we should
// back-propagate the constraint that it has to be a subtype of Internal.
ContextAccess access = OpParameter<ContextAccess>(node);
- Type* context_type = outer.upper;
MaybeHandle<Context> context;
if (context_type->IsConstant()) {
context = Handle<Context>::cast(context_type->AsConstant()->Value());
« no previous file with comments | « src/compiler/typer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698