| 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..9eb7f830b45a7091ab7f76d17fc33363200264f1 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();
|
| @@ -406,6 +408,30 @@ bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
|
| return false;
|
| }
|
|
|
| +void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) {
|
| + 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 effect.
|
| + Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
|
| + GetEffectDependency(), loop_exit);
|
| + UpdateEffectDependency(effect_rename);
|
| +
|
| + // Rename the current context.
|
| + context_ = graph()->NewNode(common()->LoopExitValue(), context_, loop_exit);
|
| +
|
| + // Rename the environmnent values.
|
| + for (size_t i = 0; i < values_.size(); i++) {
|
| + Node* rename =
|
| + graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
|
| + values_[i] = rename;
|
| + }
|
| +}
|
|
|
| void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
|
| int offset,
|
| @@ -571,8 +597,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 +1144,7 @@ void BytecodeGraphBuilder::BuildThrow() {
|
| }
|
|
|
| void BytecodeGraphBuilder::VisitThrow() {
|
| + BuildLoopExitsForFunctionExit();
|
| BuildThrow();
|
| Node* call = environment()->LookupAccumulator();
|
| Node* control = NewNode(common()->Throw(), call);
|
| @@ -1122,6 +1152,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 +1469,7 @@ void BytecodeGraphBuilder::VisitOsrPoll() {
|
| }
|
|
|
| void BytecodeGraphBuilder::VisitReturn() {
|
| + BuildLoopExitsForFunctionExit();
|
| Node* control =
|
| NewNode(common()->Return(), environment()->LookupAccumulator());
|
| MergeControlToLeaveFunction(control);
|
| @@ -1583,6 +1615,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 +1634,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());
|
| }
|
|
|