[turbofan] Clean up cached nodes in JSGraph.

R=mstarzinger@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#27870}
This commit is contained in:
titzer 2015-04-16 01:41:44 -07:00 committed by Commit bot
parent aae2c01740
commit addb10633c
4 changed files with 69 additions and 74 deletions

View File

@ -100,7 +100,7 @@ class ControlReducerImpl {
// Gather all nodes backwards-reachable from end (through inputs). // Gather all nodes backwards-reachable from end (through inputs).
ReachabilityMarker marked(graph()); ReachabilityMarker marked(graph());
NodeVector nodes(zone_); NodeVector nodes(zone_);
AddNodesReachableFromEnd(marked, nodes); AddNodesReachableFromRoots(marked, nodes);
// Walk forward through control nodes, looking for back edges to nodes // Walk forward through control nodes, looking for back edges to nodes
// that are not connected to end. Those are non-terminating loops (NTLs). // that are not connected to end. Those are non-terminating loops (NTLs).
@ -158,7 +158,6 @@ class ControlReducerImpl {
} }
// Trim references from dead nodes to live nodes first. // Trim references from dead nodes to live nodes first.
jsgraph_->GetCachedNodes(&nodes);
TrimNodes(marked, nodes); TrimNodes(marked, nodes);
// Any control nodes not reachable from start are dead, even loops. // Any control nodes not reachable from start are dead, even loops.
@ -251,13 +250,14 @@ class ControlReducerImpl {
return ret; return ret;
} }
void AddNodesReachableFromEnd(ReachabilityMarker& marked, NodeVector& nodes) { void AddNodesReachableFromRoots(ReachabilityMarker& marked,
NodeVector& nodes) {
jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots.
Node* end = graph()->end(); Node* end = graph()->end();
marked.SetReachableFromEnd(end); marked.SetReachableFromEnd(end);
if (!end->IsDead()) { if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root.
nodes.push_back(end); for (Node* node : nodes) marked.SetReachableFromEnd(node);
AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); AddBackwardsReachableNodes(marked, nodes, 0);
}
} }
void AddBackwardsReachableNodes(ReachabilityMarker& marked, NodeVector& nodes, void AddBackwardsReachableNodes(ReachabilityMarker& marked, NodeVector& nodes,
@ -276,10 +276,8 @@ class ControlReducerImpl {
// Gather all nodes backwards-reachable from end through inputs. // Gather all nodes backwards-reachable from end through inputs.
ReachabilityMarker marked(graph()); ReachabilityMarker marked(graph());
NodeVector nodes(zone_); NodeVector nodes(zone_);
AddNodesReachableFromEnd(marked, nodes);
// Process cached nodes in the JSGraph too.
jsgraph_->GetCachedNodes(&nodes); jsgraph_->GetCachedNodes(&nodes);
AddNodesReachableFromRoots(marked, nodes);
TrimNodes(marked, nodes); TrimNodes(marked, nodes);
} }

View File

@ -17,77 +17,60 @@ Node* JSGraph::ImmovableHeapConstant(Handle<HeapObject> object) {
} }
#define CACHED(name, expr) \
cached_nodes_[name] ? cached_nodes_[name] : (cached_nodes_[name] = (expr))
Node* JSGraph::CEntryStubConstant(int result_size) { Node* JSGraph::CEntryStubConstant(int result_size) {
if (result_size == 1) { if (result_size == 1) {
if (!c_entry_stub_constant_.is_set()) { return CACHED(kCEntryStubConstant,
c_entry_stub_constant_.set(
ImmovableHeapConstant(CEntryStub(isolate(), 1).GetCode())); ImmovableHeapConstant(CEntryStub(isolate(), 1).GetCode()));
} }
return c_entry_stub_constant_.get();
}
return ImmovableHeapConstant(CEntryStub(isolate(), result_size).GetCode()); return ImmovableHeapConstant(CEntryStub(isolate(), result_size).GetCode());
} }
Node* JSGraph::UndefinedConstant() { Node* JSGraph::UndefinedConstant() {
if (!undefined_constant_.is_set()) { return CACHED(kUndefinedConstant,
undefined_constant_.set(
ImmovableHeapConstant(factory()->undefined_value())); ImmovableHeapConstant(factory()->undefined_value()));
}
return undefined_constant_.get();
} }
Node* JSGraph::TheHoleConstant() { Node* JSGraph::TheHoleConstant() {
if (!the_hole_constant_.is_set()) { return CACHED(kTheHoleConstant,
the_hole_constant_.set(ImmovableHeapConstant(factory()->the_hole_value())); ImmovableHeapConstant(factory()->the_hole_value()));
}
return the_hole_constant_.get();
} }
Node* JSGraph::TrueConstant() { Node* JSGraph::TrueConstant() {
if (!true_constant_.is_set()) { return CACHED(kTrueConstant, ImmovableHeapConstant(factory()->true_value()));
true_constant_.set(ImmovableHeapConstant(factory()->true_value()));
}
return true_constant_.get();
} }
Node* JSGraph::FalseConstant() { Node* JSGraph::FalseConstant() {
if (!false_constant_.is_set()) { return CACHED(kFalseConstant,
false_constant_.set(ImmovableHeapConstant(factory()->false_value())); ImmovableHeapConstant(factory()->false_value()));
}
return false_constant_.get();
} }
Node* JSGraph::NullConstant() { Node* JSGraph::NullConstant() {
if (!null_constant_.is_set()) { return CACHED(kNullConstant, ImmovableHeapConstant(factory()->null_value()));
null_constant_.set(ImmovableHeapConstant(factory()->null_value()));
}
return null_constant_.get();
} }
Node* JSGraph::ZeroConstant() { Node* JSGraph::ZeroConstant() {
if (!zero_constant_.is_set()) zero_constant_.set(NumberConstant(0.0)); return CACHED(kZeroConstant, NumberConstant(0.0));
return zero_constant_.get();
} }
Node* JSGraph::OneConstant() { Node* JSGraph::OneConstant() {
if (!one_constant_.is_set()) one_constant_.set(NumberConstant(1.0)); return CACHED(kOneConstant, NumberConstant(1.0));
return one_constant_.get();
} }
Node* JSGraph::NaNConstant() { Node* JSGraph::NaNConstant() {
if (!nan_constant_.is_set()) { return CACHED(kNaNConstant,
nan_constant_.set(NumberConstant(std::numeric_limits<double>::quiet_NaN())); NumberConstant(std::numeric_limits<double>::quiet_NaN()));
}
return nan_constant_.get();
} }
@ -201,35 +184,27 @@ Node* JSGraph::ExternalConstant(ExternalReference reference) {
Node* JSGraph::EmptyFrameState() { Node* JSGraph::EmptyFrameState() {
if (!empty_frame_state_.is_set()) { if (cached_nodes_[kEmptyFrameState] == nullptr) {
Node* values = graph()->NewNode(common()->StateValues(0)); Node* values = graph()->NewNode(common()->StateValues(0));
Node* state_node = graph()->NewNode( Node* state_node = graph()->NewNode(
common()->FrameState(JS_FRAME, BailoutId::None(), common()->FrameState(JS_FRAME, BailoutId::None(),
OutputFrameStateCombine::Ignore()), OutputFrameStateCombine::Ignore()),
values, values, values, NoContextConstant(), UndefinedConstant()); values, values, values, NoContextConstant(), UndefinedConstant());
empty_frame_state_.set(state_node); cached_nodes_[kEmptyFrameState] = state_node;
} }
return empty_frame_state_.get(); return cached_nodes_[kEmptyFrameState];
} }
Node* JSGraph::DeadControl() { Node* JSGraph::DeadControl() {
if (!dead_control_.is_set()) { return CACHED(kDeadControl, graph()->NewNode(common()->Dead()));
Node* dead_node = graph()->NewNode(common()->Dead());
dead_control_.set(dead_node);
}
return dead_control_.get();
} }
void JSGraph::GetCachedNodes(NodeVector* nodes) { void JSGraph::GetCachedNodes(NodeVector* nodes) {
cache_.GetCachedNodes(nodes); cache_.GetCachedNodes(nodes);
SetOncePointer<Node>* ptrs[] = { for (size_t i = 0; i < arraysize(cached_nodes_); i++) {
&c_entry_stub_constant_, &undefined_constant_, &the_hole_constant_, if (cached_nodes_[i]) nodes->push_back(cached_nodes_[i]);
&true_constant_, &false_constant_, &null_constant_,
&zero_constant_, &one_constant_, &nan_constant_};
for (size_t i = 0; i < arraysize(ptrs); i++) {
if (ptrs[i]->is_set()) nodes->push_back(ptrs[i]->get());
} }
} }

View File

@ -30,7 +30,9 @@ class JSGraph : public ZoneObject {
common_(common), common_(common),
javascript_(javascript), javascript_(javascript),
machine_(machine), machine_(machine),
cache_(zone()) {} cache_(zone()) {
for (int i = 0; i < kNumCachedNodes; i++) cached_nodes_[i] = nullptr;
}
// Canonicalized global constants. // Canonicalized global constants.
Node* CEntryStubConstant(int result_size); Node* CEntryStubConstant(int result_size);
@ -128,26 +130,28 @@ class JSGraph : public ZoneObject {
void GetCachedNodes(NodeVector* nodes); void GetCachedNodes(NodeVector* nodes);
private: private:
enum CachedNode {
kCEntryStubConstant,
kUndefinedConstant,
kTheHoleConstant,
kTrueConstant,
kFalseConstant,
kNullConstant,
kZeroConstant,
kOneConstant,
kNaNConstant,
kEmptyFrameState,
kDeadControl,
kNumCachedNodes // Must remain last.
};
Isolate* isolate_; Isolate* isolate_;
Graph* graph_; Graph* graph_;
CommonOperatorBuilder* common_; CommonOperatorBuilder* common_;
JSOperatorBuilder* javascript_; JSOperatorBuilder* javascript_;
MachineOperatorBuilder* machine_; MachineOperatorBuilder* machine_;
// TODO(titzer): make this into a simple array.
SetOncePointer<Node> c_entry_stub_constant_;
SetOncePointer<Node> undefined_constant_;
SetOncePointer<Node> the_hole_constant_;
SetOncePointer<Node> true_constant_;
SetOncePointer<Node> false_constant_;
SetOncePointer<Node> null_constant_;
SetOncePointer<Node> zero_constant_;
SetOncePointer<Node> one_constant_;
SetOncePointer<Node> nan_constant_;
SetOncePointer<Node> empty_frame_state_;
SetOncePointer<Node> dead_control_;
CommonNodeCache cache_; CommonNodeCache cache_;
Node* cached_nodes_[kNumCachedNodes];
Node* ImmovableHeapConstant(Handle<HeapObject> value); Node* ImmovableHeapConstant(Handle<HeapObject> value);
Node* NumberConstant(double value); Node* NumberConstant(double value);

View File

@ -400,6 +400,24 @@ TEST(Trim_constants) {
} }
TEST(Trim_EmptyFrameState1) {
ControlReducerTester T;
Node* node = T.jsgraph.EmptyFrameState();
T.Trim();
for (Node* input : node->inputs()) {
CHECK_NOT_NULL(input);
}
}
TEST(Trim_EmptyFrameState2) {
ControlReducerTester T;
CheckTrimConstant(&T, T.jsgraph.EmptyFrameState());
}
TEST(CReducePhi1) { TEST(CReducePhi1) {
ControlReducerTester R; ControlReducerTester R;