Index: src/compiler/bytecode-graph-builder.cc |
diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc |
index 4ec83f85d8123e03bb52162444c7e59a77ada2fa..63f3d46a482bee493ea784942ff4e2dcfa423a2e 100644 |
--- a/src/compiler/bytecode-graph-builder.cc |
+++ b/src/compiler/bytecode-graph-builder.cc |
@@ -62,6 +62,8 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { |
void Merge(Environment* other); |
void PrepareForOsr(); |
+ void PrepareForLoopExit(Node* loop); |
+ |
private: |
explicit Environment(const Environment* copy); |
void PrepareForLoop(); |
@@ -465,6 +467,28 @@ bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( |
1, output_poke_start, output_poke_end); |
} |
+void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { |
Michael Starzinger
2016/07/29 08:54:46
nit: Can we move this up a few functions close to
Jarin
2016/07/29 11:36:46
Done.
|
+ DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); |
+ |
+ Node* control = GetControlDependency(); |
+ |
+ // Create the loop exit node. |
+ Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); |
+ UpdateControlDependency(loop_exit); |
+ |
+ // Rename the environmnent values. |
Michael Starzinger
2016/07/29 08:58:21
Is it OK not to handle "context_" here?
Jarin
2016/07/29 11:36:46
Not ok, great catch! (Well, not ok if we want to a
|
+ for (size_t i = 0; i < values()->size(); i++) { |
+ Node* rename = |
+ graph()->NewNode(common()->LoopExitValue(), (*values())[i], loop_exit); |
Michael Starzinger
2016/07/29 08:54:46
nit: Just "values_[i]".
Jarin
2016/07/29 11:36:46
Done.
|
+ (*values())[i] = rename; |
Michael Starzinger
2016/07/29 08:54:45
nit: Just "values_[i]".
Jarin
2016/07/29 11:36:46
Done.
|
+ } |
+ |
+ // Rename the effect. |
Michael Starzinger
2016/07/29 08:54:46
nit: Can we handle the effect before the values, j
Jarin
2016/07/29 11:36:46
Done.
|
+ Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), |
+ GetEffectDependency(), loop_exit); |
+ UpdateEffectDependency(effect_rename); |
+} |
+ |
BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
CompilationInfo* info, |
JSGraph* jsgraph) |
@@ -571,8 +595,11 @@ bool BytecodeGraphBuilder::CreateGraph() { |
void BytecodeGraphBuilder::VisitBytecodes() { |
BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
+ BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); |
analysis.Analyze(); |
+ loop_analysis.Analyze(); |
set_branch_analysis(&analysis); |
+ set_loop_analysis(&loop_analysis); |
interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
set_bytecode_iterator(&iterator); |
while (!iterator.done()) { |
@@ -1115,6 +1142,7 @@ void BytecodeGraphBuilder::BuildThrow() { |
} |
void BytecodeGraphBuilder::VisitThrow() { |
+ BuildLoopExitsForFunctionExit(); |
BuildThrow(); |
Node* call = environment()->LookupAccumulator(); |
Node* control = NewNode(common()->Throw(), call); |
@@ -1122,6 +1150,7 @@ void BytecodeGraphBuilder::VisitThrow() { |
} |
void BytecodeGraphBuilder::VisitReThrow() { |
+ BuildLoopExitsForFunctionExit(); |
Node* value = environment()->LookupAccumulator(); |
Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); |
Node* control = NewNode(common()->Throw(), call); |
@@ -1438,6 +1467,7 @@ void BytecodeGraphBuilder::VisitOsrPoll() { |
} |
void BytecodeGraphBuilder::VisitReturn() { |
+ BuildLoopExitsForFunctionExit(); |
Node* control = |
NewNode(common()->Return(), environment()->LookupAccumulator()); |
MergeControlToLeaveFunction(control); |
@@ -1583,6 +1613,7 @@ void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
} |
void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { |
+ BuildLoopExitsForBranch(target_offset); |
if (merge_environments_[target_offset] == nullptr) { |
// Append merge nodes to the environment. We may merge here with another |
// environment. So add a place holder for merge nodes. We may add redundant |
@@ -1601,6 +1632,28 @@ void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
set_environment(nullptr); |
} |
+void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { |
+ int origin_offset = bytecode_iterator().current_offset(); |
+ // Only build loop exits for forward edges. |
+ if (target_offset > origin_offset) { |
+ BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); |
+ } |
+} |
+ |
+void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { |
+ int origin_offset = bytecode_iterator().current_offset(); |
+ int current_loop = loop_analysis()->GetLoopOffsetFor(origin_offset); |
+ while (loop_offset < current_loop) { |
+ Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); |
+ environment()->PrepareForLoopExit(loop_node); |
+ current_loop = loop_analysis()->GetParentLoopFor(current_loop); |
+ } |
+} |
+ |
+void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() { |
+ BuildLoopExitsUntilLoop(-1); |
+} |
+ |
void BytecodeGraphBuilder::BuildJump() { |
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
} |