Index: src/compiler/escape-analysis-reducer.cc |
diff --git a/src/compiler/escape-analysis-reducer.cc b/src/compiler/escape-analysis-reducer.cc |
index df8b65dab2e336b23bf1a695d37f3d43cac6ef27..4567d671da745661e594dbe6985cf9c42c646411 100644 |
--- a/src/compiler/escape-analysis-reducer.cc |
+++ b/src/compiler/escape-analysis-reducer.cc |
@@ -18,7 +18,8 @@ EscapeAnalysisReducer::EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph, |
jsgraph_(jsgraph), |
escape_analysis_(escape_analysis), |
zone_(zone), |
- visited_(static_cast<int>(jsgraph->graph()->NodeCount()), zone) {} |
+ visited_(static_cast<int>(jsgraph->graph()->NodeCount() * 2), zone), |
+ exists_virtual_allocate_(true) {} |
Reduction EscapeAnalysisReducer::Reduce(Node* node) { |
@@ -37,11 +38,41 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) { |
return ReduceReferenceEqual(node); |
case IrOpcode::kObjectIsSmi: |
return ReduceObjectIsSmi(node); |
+ case IrOpcode::kFrameState: |
+ case IrOpcode::kStateValues: { |
+ if (node->id() >= static_cast<NodeId>(visited_.length()) || |
+ visited_.Contains(node->id())) { |
+ break; |
+ } |
+ bool needs_visit = false; |
+ for (int i = 0; i < node->InputCount(); i++) { |
+ Node* input = node->InputAt(i); |
+ switch (input->opcode()) { |
+ case IrOpcode::kAllocate: |
+ case IrOpcode::kFinishRegion: |
+ needs_visit = needs_visit || escape_analysis()->IsVirtual(input); |
+ break; |
+ case IrOpcode::kFrameState: |
+ case IrOpcode::kStateValues: |
+ needs_visit = |
+ needs_visit || |
+ input->id() >= static_cast<NodeId>(visited_.length()) || |
+ !visited_.Contains(input->id()); |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ if (!needs_visit) { |
+ visited_.Add(node->id()); |
+ } |
+ break; |
+ } |
default: |
// TODO(sigurds): Change this to GetFrameStateInputCount once |
// it is working. For now we use EffectInputCount > 0 to determine |
// whether a node might have a frame state input. |
- if (node->op()->EffectInputCount() > 0) { |
+ if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { |
return ReduceFrameStateUses(node); |
} |
break; |
@@ -174,7 +205,7 @@ Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) { |
for (int i = 0; i < node->InputCount(); ++i) { |
Node* input = node->InputAt(i); |
if (input->opcode() == IrOpcode::kFrameState) { |
- if (Node* ret = ReduceFrameState(input, node, false)) { |
+ if (Node* ret = ReduceDeoptState(input, node, false)) { |
node->ReplaceInput(i, ret); |
changed = true; |
} |
@@ -188,76 +219,61 @@ Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) { |
// Returns the clone if it duplicated the node, and null otherwise. |
-Node* EscapeAnalysisReducer::ReduceFrameState(Node* node, Node* effect, |
+Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect, |
bool multiple_users) { |
- DCHECK(node->opcode() == IrOpcode::kFrameState); |
+ DCHECK(node->opcode() == IrOpcode::kFrameState || |
+ node->opcode() == IrOpcode::kStateValues); |
+ if (node->id() < static_cast<NodeId>(visited_.length()) && |
+ visited_.Contains(node->id())) { |
+ return nullptr; |
+ } |
if (FLAG_trace_turbo_escape) { |
- PrintF("Reducing FrameState %d\n", node->id()); |
+ PrintF("Reducing %s %d\n", node->op()->mnemonic(), node->id()); |
} |
Node* clone = nullptr; |
+ bool node_multiused = node->UseCount() > 1; |
+ bool multiple_users_rec = multiple_users || node_multiused; |
for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |
Node* input = NodeProperties::GetValueInput(node, i); |
- Node* ret = |
- input->opcode() == IrOpcode::kStateValues |
- ? ReduceStateValueInputs(input, effect, node->UseCount() > 1) |
- : ReduceStateValueInput(node, i, effect, node->UseCount() > 1); |
- if (ret) { |
- if (node->UseCount() > 1 || multiple_users) { |
- if (FLAG_trace_turbo_escape) { |
- PrintF(" Cloning #%d", node->id()); |
- } |
- node = clone = jsgraph()->graph()->CloneNode(node); |
- if (FLAG_trace_turbo_escape) { |
- PrintF(" to #%d\n", node->id()); |
+ if (input->opcode() == IrOpcode::kStateValues) { |
+ if (Node* ret = ReduceDeoptState(input, effect, multiple_users_rec)) { |
+ if (node_multiused || (multiple_users && !clone)) { |
+ if (FLAG_trace_turbo_escape) { |
+ PrintF(" Cloning #%d", node->id()); |
+ } |
+ node = clone = jsgraph()->graph()->CloneNode(node); |
+ if (FLAG_trace_turbo_escape) { |
+ PrintF(" to #%d\n", node->id()); |
+ } |
+ node_multiused = false; |
} |
- multiple_users = false; // Don't clone anymore. |
+ NodeProperties::ReplaceValueInput(node, ret, i); |
+ } |
+ } else { |
+ if (Node* ret = ReduceStateValueInput(node, i, effect, node_multiused, |
+ clone, multiple_users)) { |
+ DCHECK_NULL(clone); |
+ node_multiused = false; // Don't clone anymore. |
+ node = clone = ret; |
} |
- NodeProperties::ReplaceValueInput(node, ret, i); |
} |
} |
- Node* outer_frame_state = NodeProperties::GetFrameStateInput(node, 0); |
- if (outer_frame_state->opcode() == IrOpcode::kFrameState) { |
- if (Node* ret = |
- ReduceFrameState(outer_frame_state, effect, node->UseCount() > 1)) { |
- if (node->UseCount() > 1 || multiple_users) { |
- if (FLAG_trace_turbo_escape) { |
- PrintF(" Cloning #%d", node->id()); |
- } |
- node = clone = jsgraph()->graph()->CloneNode(node); |
- if (FLAG_trace_turbo_escape) { |
- PrintF(" to #%d\n", node->id()); |
+ if (node->opcode() == IrOpcode::kFrameState) { |
+ Node* outer_frame_state = NodeProperties::GetFrameStateInput(node, 0); |
+ if (outer_frame_state->opcode() == IrOpcode::kFrameState) { |
+ if (Node* ret = |
+ ReduceDeoptState(outer_frame_state, effect, multiple_users_rec)) { |
+ if (node_multiused || (multiple_users && !clone)) { |
+ if (FLAG_trace_turbo_escape) { |
+ PrintF(" Cloning #%d", node->id()); |
+ } |
+ node = clone = jsgraph()->graph()->CloneNode(node); |
+ if (FLAG_trace_turbo_escape) { |
+ PrintF(" to #%d\n", node->id()); |
+ } |
} |
- multiple_users = false; |
+ NodeProperties::ReplaceFrameStateInput(node, 0, ret); |
} |
- NodeProperties::ReplaceFrameStateInput(node, 0, ret); |
- } |
- } |
- return clone; |
-} |
- |
- |
-// Returns the clone if it duplicated the node, and null otherwise. |
-Node* EscapeAnalysisReducer::ReduceStateValueInputs(Node* node, Node* effect, |
- bool multiple_users) { |
- if (FLAG_trace_turbo_escape) { |
- PrintF("Reducing StateValue #%d\n", node->id()); |
- } |
- DCHECK(node->opcode() == IrOpcode::kStateValues); |
- DCHECK_NOT_NULL(effect); |
- Node* clone = nullptr; |
- for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |
- Node* input = NodeProperties::GetValueInput(node, i); |
- Node* ret = nullptr; |
- if (input->opcode() == IrOpcode::kStateValues) { |
- ret = ReduceStateValueInputs(input, effect, multiple_users); |
- } else { |
- ret = ReduceStateValueInput(node, i, effect, multiple_users); |
- } |
- if (ret) { |
- node = ret; |
- DCHECK_NULL(clone); |
- clone = ret; |
- multiple_users = false; |
} |
} |
return clone; |
@@ -267,6 +283,8 @@ Node* EscapeAnalysisReducer::ReduceStateValueInputs(Node* node, Node* effect, |
// Returns the clone if it duplicated the node, and null otherwise. |
Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, |
Node* effect, |
+ bool node_multiused, |
+ bool already_cloned, |
bool multiple_users) { |
Node* input = NodeProperties::GetValueInput(node, node_index); |
if (FLAG_trace_turbo_escape) { |
@@ -279,7 +297,7 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, |
if (escape_analysis()->IsVirtual(input)) { |
if (Node* object_state = |
escape_analysis()->GetOrCreateObjectState(effect, input)) { |
- if (node->UseCount() > 1 || multiple_users) { |
+ if (node_multiused || (multiple_users && !already_cloned)) { |
if (FLAG_trace_turbo_escape) { |
PrintF("Cloning #%d", node->id()); |
} |
@@ -287,6 +305,8 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, |
if (FLAG_trace_turbo_escape) { |
PrintF(" to #%d\n", node->id()); |
} |
+ node_multiused = false; |
+ already_cloned = true; |
} |
NodeProperties::ReplaceValueInput(node, object_state, node_index); |
if (FLAG_trace_turbo_escape) { |