Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler/bytecode-branch-analysis.h" | 7 #include "src/compiler/bytecode-branch-analysis.h" |
| 8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
| 9 #include "src/compiler/operator-properties.h" | 9 #include "src/compiler/operator-properties.h" |
| 10 #include "src/interpreter/bytecodes.h" | 10 #include "src/interpreter/bytecodes.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 } | 55 } |
| 56 | 56 |
| 57 Node* Context() const { return context_; } | 57 Node* Context() const { return context_; } |
| 58 void SetContext(Node* new_context) { context_ = new_context; } | 58 void SetContext(Node* new_context) { context_ = new_context; } |
| 59 | 59 |
| 60 Environment* CopyForConditional() const; | 60 Environment* CopyForConditional() const; |
| 61 Environment* CopyForLoop(); | 61 Environment* CopyForLoop(); |
| 62 void Merge(Environment* other); | 62 void Merge(Environment* other); |
| 63 void PrepareForOsr(); | 63 void PrepareForOsr(); |
| 64 | 64 |
| 65 void PrepareForLoopExit(Node* loop); | |
| 66 | |
| 65 private: | 67 private: |
| 66 explicit Environment(const Environment* copy); | 68 explicit Environment(const Environment* copy); |
| 67 void PrepareForLoop(); | 69 void PrepareForLoop(); |
| 68 bool StateValuesAreUpToDate(Node** state_values, int offset, int count, | 70 bool StateValuesAreUpToDate(Node** state_values, int offset, int count, |
| 69 int output_poke_start, int output_poke_end); | 71 int output_poke_start, int output_poke_end); |
| 70 bool StateValuesRequireUpdate(Node** state_values, int offset, int count); | 72 bool StateValuesRequireUpdate(Node** state_values, int offset, int count); |
| 71 void UpdateStateValues(Node** state_values, int offset, int count); | 73 void UpdateStateValues(Node** state_values, int offset, int count); |
| 72 | 74 |
| 73 int RegisterToValuesIndex(interpreter::Register the_register) const; | 75 int RegisterToValuesIndex(interpreter::Register the_register) const; |
| 74 | 76 |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 458 int output_poke_end = output_poke_start + output_poke_count; | 460 int output_poke_end = output_poke_start + output_poke_count; |
| 459 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), | 461 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), |
| 460 output_poke_start, output_poke_end) && | 462 output_poke_start, output_poke_end) && |
| 461 StateValuesAreUpToDate(®isters_state_values_, register_base(), | 463 StateValuesAreUpToDate(®isters_state_values_, register_base(), |
| 462 register_count(), output_poke_start, | 464 register_count(), output_poke_start, |
| 463 output_poke_end) && | 465 output_poke_end) && |
| 464 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), | 466 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), |
| 465 1, output_poke_start, output_poke_end); | 467 1, output_poke_start, output_poke_end); |
| 466 } | 468 } |
| 467 | 469 |
| 470 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.
| |
| 471 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); | |
| 472 | |
| 473 Node* control = GetControlDependency(); | |
| 474 | |
| 475 // Create the loop exit node. | |
| 476 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); | |
| 477 UpdateControlDependency(loop_exit); | |
| 478 | |
| 479 // 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
| |
| 480 for (size_t i = 0; i < values()->size(); i++) { | |
| 481 Node* rename = | |
| 482 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.
| |
| 483 (*values())[i] = rename; | |
|
Michael Starzinger
2016/07/29 08:54:45
nit: Just "values_[i]".
Jarin
2016/07/29 11:36:46
Done.
| |
| 484 } | |
| 485 | |
| 486 // 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.
| |
| 487 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), | |
| 488 GetEffectDependency(), loop_exit); | |
| 489 UpdateEffectDependency(effect_rename); | |
| 490 } | |
| 491 | |
| 468 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 492 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
| 469 CompilationInfo* info, | 493 CompilationInfo* info, |
| 470 JSGraph* jsgraph) | 494 JSGraph* jsgraph) |
| 471 : local_zone_(local_zone), | 495 : local_zone_(local_zone), |
| 472 jsgraph_(jsgraph), | 496 jsgraph_(jsgraph), |
| 473 bytecode_array_(handle(info->shared_info()->bytecode_array())), | 497 bytecode_array_(handle(info->shared_info()->bytecode_array())), |
| 474 exception_handler_table_( | 498 exception_handler_table_( |
| 475 handle(HandlerTable::cast(bytecode_array()->handler_table()))), | 499 handle(HandlerTable::cast(bytecode_array()->handler_table()))), |
| 476 feedback_vector_(handle(info->closure()->feedback_vector())), | 500 feedback_vector_(handle(info->closure()->feedback_vector())), |
| 477 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 501 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 int const input_count = static_cast<int>(exit_controls_.size()); | 588 int const input_count = static_cast<int>(exit_controls_.size()); |
| 565 Node** const inputs = &exit_controls_.front(); | 589 Node** const inputs = &exit_controls_.front(); |
| 566 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); | 590 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); |
| 567 graph()->SetEnd(end); | 591 graph()->SetEnd(end); |
| 568 | 592 |
| 569 return true; | 593 return true; |
| 570 } | 594 } |
| 571 | 595 |
| 572 void BytecodeGraphBuilder::VisitBytecodes() { | 596 void BytecodeGraphBuilder::VisitBytecodes() { |
| 573 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 597 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
| 598 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); | |
| 574 analysis.Analyze(); | 599 analysis.Analyze(); |
| 600 loop_analysis.Analyze(); | |
| 575 set_branch_analysis(&analysis); | 601 set_branch_analysis(&analysis); |
| 602 set_loop_analysis(&loop_analysis); | |
| 576 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 603 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
| 577 set_bytecode_iterator(&iterator); | 604 set_bytecode_iterator(&iterator); |
| 578 while (!iterator.done()) { | 605 while (!iterator.done()) { |
| 579 int current_offset = iterator.current_offset(); | 606 int current_offset = iterator.current_offset(); |
| 580 EnterAndExitExceptionHandlers(current_offset); | 607 EnterAndExitExceptionHandlers(current_offset); |
| 581 SwitchToMergeEnvironment(current_offset); | 608 SwitchToMergeEnvironment(current_offset); |
| 582 if (environment() != nullptr) { | 609 if (environment() != nullptr) { |
| 583 BuildLoopHeaderEnvironment(current_offset); | 610 BuildLoopHeaderEnvironment(current_offset); |
| 584 | 611 |
| 585 switch (iterator.current_bytecode()) { | 612 switch (iterator.current_bytecode()) { |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1108 } | 1135 } |
| 1109 | 1136 |
| 1110 void BytecodeGraphBuilder::BuildThrow() { | 1137 void BytecodeGraphBuilder::BuildThrow() { |
| 1111 FrameStateBeforeAndAfter states(this); | 1138 FrameStateBeforeAndAfter states(this); |
| 1112 Node* value = environment()->LookupAccumulator(); | 1139 Node* value = environment()->LookupAccumulator(); |
| 1113 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); | 1140 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); |
| 1114 environment()->BindAccumulator(call, &states); | 1141 environment()->BindAccumulator(call, &states); |
| 1115 } | 1142 } |
| 1116 | 1143 |
| 1117 void BytecodeGraphBuilder::VisitThrow() { | 1144 void BytecodeGraphBuilder::VisitThrow() { |
| 1145 BuildLoopExitsForFunctionExit(); | |
| 1118 BuildThrow(); | 1146 BuildThrow(); |
| 1119 Node* call = environment()->LookupAccumulator(); | 1147 Node* call = environment()->LookupAccumulator(); |
| 1120 Node* control = NewNode(common()->Throw(), call); | 1148 Node* control = NewNode(common()->Throw(), call); |
| 1121 MergeControlToLeaveFunction(control); | 1149 MergeControlToLeaveFunction(control); |
| 1122 } | 1150 } |
| 1123 | 1151 |
| 1124 void BytecodeGraphBuilder::VisitReThrow() { | 1152 void BytecodeGraphBuilder::VisitReThrow() { |
| 1153 BuildLoopExitsForFunctionExit(); | |
| 1125 Node* value = environment()->LookupAccumulator(); | 1154 Node* value = environment()->LookupAccumulator(); |
| 1126 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); | 1155 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); |
| 1127 Node* control = NewNode(common()->Throw(), call); | 1156 Node* control = NewNode(common()->Throw(), call); |
| 1128 MergeControlToLeaveFunction(control); | 1157 MergeControlToLeaveFunction(control); |
| 1129 } | 1158 } |
| 1130 | 1159 |
| 1131 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { | 1160 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { |
| 1132 FrameStateBeforeAndAfter states(this); | 1161 FrameStateBeforeAndAfter states(this); |
| 1133 Node* left = | 1162 Node* left = |
| 1134 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); | 1163 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1431 void BytecodeGraphBuilder::VisitOsrPoll() { | 1460 void BytecodeGraphBuilder::VisitOsrPoll() { |
| 1432 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge | 1461 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge |
| 1433 // the polling with existing bytecode. This will also guarantee that we are | 1462 // the polling with existing bytecode. This will also guarantee that we are |
| 1434 // not missing the OSR entry point, which we wouldn't catch right now. | 1463 // not missing the OSR entry point, which we wouldn't catch right now. |
| 1435 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { | 1464 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { |
| 1436 environment()->PrepareForOsr(); | 1465 environment()->PrepareForOsr(); |
| 1437 } | 1466 } |
| 1438 } | 1467 } |
| 1439 | 1468 |
| 1440 void BytecodeGraphBuilder::VisitReturn() { | 1469 void BytecodeGraphBuilder::VisitReturn() { |
| 1470 BuildLoopExitsForFunctionExit(); | |
| 1441 Node* control = | 1471 Node* control = |
| 1442 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1472 NewNode(common()->Return(), environment()->LookupAccumulator()); |
| 1443 MergeControlToLeaveFunction(control); | 1473 MergeControlToLeaveFunction(control); |
| 1444 } | 1474 } |
| 1445 | 1475 |
| 1446 void BytecodeGraphBuilder::VisitDebugger() { | 1476 void BytecodeGraphBuilder::VisitDebugger() { |
| 1447 FrameStateBeforeAndAfter states(this); | 1477 FrameStateBeforeAndAfter states(this); |
| 1448 Node* call = | 1478 Node* call = |
| 1449 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); | 1479 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); |
| 1450 environment()->BindAccumulator(call, &states); | 1480 environment()->BindAccumulator(call, &states); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1576 | 1606 |
| 1577 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { | 1607 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
| 1578 if (branch_analysis()->backward_branches_target(current_offset)) { | 1608 if (branch_analysis()->backward_branches_target(current_offset)) { |
| 1579 // Add loop header and store a copy so we can connect merged back | 1609 // Add loop header and store a copy so we can connect merged back |
| 1580 // edge inputs to the loop header. | 1610 // edge inputs to the loop header. |
| 1581 merge_environments_[current_offset] = environment()->CopyForLoop(); | 1611 merge_environments_[current_offset] = environment()->CopyForLoop(); |
| 1582 } | 1612 } |
| 1583 } | 1613 } |
| 1584 | 1614 |
| 1585 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { | 1615 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { |
| 1616 BuildLoopExitsForBranch(target_offset); | |
| 1586 if (merge_environments_[target_offset] == nullptr) { | 1617 if (merge_environments_[target_offset] == nullptr) { |
| 1587 // Append merge nodes to the environment. We may merge here with another | 1618 // Append merge nodes to the environment. We may merge here with another |
| 1588 // environment. So add a place holder for merge nodes. We may add redundant | 1619 // environment. So add a place holder for merge nodes. We may add redundant |
| 1589 // but will be eliminated in a later pass. | 1620 // but will be eliminated in a later pass. |
| 1590 // TODO(mstarzinger): Be smarter about this! | 1621 // TODO(mstarzinger): Be smarter about this! |
| 1591 NewMerge(); | 1622 NewMerge(); |
| 1592 merge_environments_[target_offset] = environment(); | 1623 merge_environments_[target_offset] = environment(); |
| 1593 } else { | 1624 } else { |
| 1594 merge_environments_[target_offset]->Merge(environment()); | 1625 merge_environments_[target_offset]->Merge(environment()); |
| 1595 } | 1626 } |
| 1596 set_environment(nullptr); | 1627 set_environment(nullptr); |
| 1597 } | 1628 } |
| 1598 | 1629 |
| 1599 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1630 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
| 1600 exit_controls_.push_back(exit); | 1631 exit_controls_.push_back(exit); |
| 1601 set_environment(nullptr); | 1632 set_environment(nullptr); |
| 1602 } | 1633 } |
| 1603 | 1634 |
| 1635 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { | |
| 1636 int origin_offset = bytecode_iterator().current_offset(); | |
| 1637 // Only build loop exits for forward edges. | |
| 1638 if (target_offset > origin_offset) { | |
| 1639 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); | |
| 1640 } | |
| 1641 } | |
| 1642 | |
| 1643 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { | |
| 1644 int origin_offset = bytecode_iterator().current_offset(); | |
| 1645 int current_loop = loop_analysis()->GetLoopOffsetFor(origin_offset); | |
| 1646 while (loop_offset < current_loop) { | |
| 1647 Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); | |
| 1648 environment()->PrepareForLoopExit(loop_node); | |
| 1649 current_loop = loop_analysis()->GetParentLoopFor(current_loop); | |
| 1650 } | |
| 1651 } | |
| 1652 | |
| 1653 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() { | |
| 1654 BuildLoopExitsUntilLoop(-1); | |
| 1655 } | |
| 1656 | |
| 1604 void BytecodeGraphBuilder::BuildJump() { | 1657 void BytecodeGraphBuilder::BuildJump() { |
| 1605 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 1658 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
| 1606 } | 1659 } |
| 1607 | 1660 |
| 1608 | 1661 |
| 1609 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | 1662 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { |
| 1610 NewBranch(condition); | 1663 NewBranch(condition); |
| 1611 Environment* if_false_environment = environment()->CopyForConditional(); | 1664 Environment* if_false_environment = environment()->CopyForConditional(); |
| 1612 NewIfTrue(); | 1665 NewIfTrue(); |
| 1613 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 1666 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1832 // Phi does not exist yet, introduce one. | 1885 // Phi does not exist yet, introduce one. |
| 1833 value = NewPhi(inputs, value, control); | 1886 value = NewPhi(inputs, value, control); |
| 1834 value->ReplaceInput(inputs - 1, other); | 1887 value->ReplaceInput(inputs - 1, other); |
| 1835 } | 1888 } |
| 1836 return value; | 1889 return value; |
| 1837 } | 1890 } |
| 1838 | 1891 |
| 1839 } // namespace compiler | 1892 } // namespace compiler |
| 1840 } // namespace internal | 1893 } // namespace internal |
| 1841 } // namespace v8 | 1894 } // namespace v8 |
| OLD | NEW |