Commit 59a38a9a authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Add early detection of object state cycles.

This makes sure cycles in the object states graph are detected early by
escape analysis instead of late in the scheduler. This is mainly done
for improved debuggability.

R=bmeurer@chromium.org
BUG=chromium:613923

Review-Url: https://codereview.chromium.org/2354263002
Cr-Commit-Position: refs/heads/master@{#39614}
parent 0acde6f9
...@@ -305,6 +305,11 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, ...@@ -305,6 +305,11 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index,
if (input->opcode() == IrOpcode::kFinishRegion || if (input->opcode() == IrOpcode::kFinishRegion ||
input->opcode() == IrOpcode::kAllocate) { input->opcode() == IrOpcode::kAllocate) {
if (escape_analysis()->IsVirtual(input)) { if (escape_analysis()->IsVirtual(input)) {
if (escape_analysis()->IsCyclicObjectState(effect, input)) {
// TODO(mstarzinger): Represent cyclic object states differently to
// ensure the scheduler can properly handle such object states.
FATAL("Cyclic object state detected by escape analysis.");
}
if (Node* object_state = if (Node* object_state =
escape_analysis()->GetOrCreateObjectState(effect, input)) { escape_analysis()->GetOrCreateObjectState(effect, input)) {
if (node_multiused || (multiple_users && !already_cloned)) { if (node_multiused || (multiple_users && !already_cloned)) {
......
...@@ -854,6 +854,7 @@ EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, ...@@ -854,6 +854,7 @@ EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
status_analysis_(new (zone) EscapeStatusAnalysis(this, graph, zone)), status_analysis_(new (zone) EscapeStatusAnalysis(this, graph, zone)),
virtual_states_(zone), virtual_states_(zone),
replacements_(zone), replacements_(zone),
cycle_detection_(zone),
cache_(nullptr) {} cache_(nullptr) {}
EscapeAnalysis::~EscapeAnalysis() {} EscapeAnalysis::~EscapeAnalysis() {}
...@@ -1558,6 +1559,27 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { ...@@ -1558,6 +1559,27 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
return nullptr; return nullptr;
} }
bool EscapeAnalysis::IsCyclicObjectState(Node* effect, Node* node) {
if ((node->opcode() == IrOpcode::kFinishRegion ||
node->opcode() == IrOpcode::kAllocate) &&
IsVirtual(node)) {
if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()],
ResolveReplacement(node))) {
if (cycle_detection_.find(vobj) != cycle_detection_.end()) return true;
cycle_detection_.insert(vobj);
bool cycle_detected = false;
for (size_t i = 0; i < vobj->field_count(); ++i) {
if (Node* field = vobj->GetField(i)) {
if (IsCyclicObjectState(effect, field)) cycle_detected = true;
}
}
cycle_detection_.erase(vobj);
return cycle_detected;
}
}
return false;
}
void EscapeAnalysis::DebugPrintState(VirtualState* state) { void EscapeAnalysis::DebugPrintState(VirtualState* state) {
PrintF("Dumping virtual state %p\n", static_cast<void*>(state)); PrintF("Dumping virtual state %p\n", static_cast<void*>(state));
for (Alias alias = 0; alias < status_analysis_->AliasCount(); ++alias) { for (Alias alias = 0; alias < status_analysis_->AliasCount(); ++alias) {
......
...@@ -32,6 +32,7 @@ class EscapeAnalysis { ...@@ -32,6 +32,7 @@ class EscapeAnalysis {
bool IsEscaped(Node* node); bool IsEscaped(Node* node);
bool CompareVirtualObjects(Node* left, Node* right); bool CompareVirtualObjects(Node* left, Node* right);
Node* GetOrCreateObjectState(Node* effect, Node* node); Node* GetOrCreateObjectState(Node* effect, Node* node);
bool IsCyclicObjectState(Node* effect, Node* node);
bool ExistsVirtualAllocate(); bool ExistsVirtualAllocate();
private: private:
...@@ -75,6 +76,7 @@ class EscapeAnalysis { ...@@ -75,6 +76,7 @@ class EscapeAnalysis {
EscapeStatusAnalysis* status_analysis_; EscapeStatusAnalysis* status_analysis_;
ZoneVector<VirtualState*> virtual_states_; ZoneVector<VirtualState*> virtual_states_;
ZoneVector<Node*> replacements_; ZoneVector<Node*> replacements_;
ZoneSet<VirtualObject*> cycle_detection_;
MergeCache* cache_; MergeCache* cache_;
DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis);
......
...@@ -468,8 +468,7 @@ TEST_F(EscapeAnalysisTest, DeoptReplacement) { ...@@ -468,8 +468,7 @@ TEST_F(EscapeAnalysisTest, DeoptReplacement) {
ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0));
} }
TEST_F(EscapeAnalysisTest, DISABLED_DeoptReplacementIdentity) {
TEST_F(EscapeAnalysisTest, DeoptReplacementIdentity) {
Node* object1 = Constant(1); Node* object1 = Constant(1);
BeginRegion(); BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize * 2)); Node* allocation = Allocate(Constant(kPointerSize * 2));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment