Chromium Code Reviews| 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()); |
| } |