| 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/ast/ast.h" | 7 #include "src/ast/ast.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler/bytecode-branch-analysis.h" | 10 #include "src/compiler/bytecode-branch-analysis.h" |
| (...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 | 641 |
| 642 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { | 642 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { |
| 643 FeedbackVectorSlot slot; | 643 FeedbackVectorSlot slot; |
| 644 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { | 644 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { |
| 645 slot = feedback_vector()->ToSlot(slot_id); | 645 slot = feedback_vector()->ToSlot(slot_id); |
| 646 } | 646 } |
| 647 return VectorSlotPair(feedback_vector(), slot); | 647 return VectorSlotPair(feedback_vector(), slot); |
| 648 } | 648 } |
| 649 | 649 |
| 650 bool BytecodeGraphBuilder::CreateGraph() { | 650 bool BytecodeGraphBuilder::CreateGraph() { |
| 651 // Set up the basic structure of the graph. Outputs for {Start} are | |
| 652 // the formal parameters (including the receiver) plus context and | |
| 653 // closure. | |
| 654 | |
| 655 // Set up the basic structure of the graph. Outputs for {Start} are the formal | 651 // Set up the basic structure of the graph. Outputs for {Start} are the formal |
| 656 // parameters (including the receiver) plus new target, number of arguments, | 652 // parameters (including the receiver) plus new target, number of arguments, |
| 657 // context and closure. | 653 // context and closure. |
| 658 int actual_parameter_count = bytecode_array()->parameter_count() + 4; | 654 int actual_parameter_count = bytecode_array()->parameter_count() + 4; |
| 659 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); | 655 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); |
| 660 | 656 |
| 661 Environment env(this, bytecode_array()->register_count(), | 657 Environment env(this, bytecode_array()->register_count(), |
| 662 bytecode_array()->parameter_count(), graph()->start(), | 658 bytecode_array()->parameter_count(), graph()->start(), |
| 663 GetFunctionContext()); | 659 GetFunctionContext()); |
| 664 set_environment(&env); | 660 set_environment(&env); |
| 665 | 661 |
| 666 // For OSR add an {OsrNormalEntry} as the start of the top-level environment. | |
| 667 // It will be replaced with {Dead} after typing and optimizations. | |
| 668 if (!osr_ast_id_.IsNone()) NewNode(common()->OsrNormalEntry()); | |
| 669 | |
| 670 VisitBytecodes(); | 662 VisitBytecodes(); |
| 671 | 663 |
| 672 // Finish the basic structure of the graph. | 664 // Finish the basic structure of the graph. |
| 673 DCHECK_NE(0u, exit_controls_.size()); | 665 DCHECK_NE(0u, exit_controls_.size()); |
| 674 int const input_count = static_cast<int>(exit_controls_.size()); | 666 int const input_count = static_cast<int>(exit_controls_.size()); |
| 675 Node** const inputs = &exit_controls_.front(); | 667 Node** const inputs = &exit_controls_.front(); |
| 676 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); | 668 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); |
| 677 graph()->SetEnd(end); | 669 graph()->SetEnd(end); |
| 678 | 670 |
| 679 ClearNonLiveSlotsInFrameStates(); | 671 ClearNonLiveSlotsInFrameStates(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 697 | 689 |
| 698 void BytecodeGraphBuilder::VisitBytecodes() { | 690 void BytecodeGraphBuilder::VisitBytecodes() { |
| 699 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 691 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
| 700 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); | 692 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); |
| 701 analysis.Analyze(); | 693 analysis.Analyze(); |
| 702 loop_analysis.Analyze(); | 694 loop_analysis.Analyze(); |
| 703 set_branch_analysis(&analysis); | 695 set_branch_analysis(&analysis); |
| 704 set_loop_analysis(&loop_analysis); | 696 set_loop_analysis(&loop_analysis); |
| 705 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 697 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
| 706 set_bytecode_iterator(&iterator); | 698 set_bytecode_iterator(&iterator); |
| 699 BuildOSRNormalEntryPoint(); |
| 707 while (!iterator.done()) { | 700 while (!iterator.done()) { |
| 708 int current_offset = iterator.current_offset(); | 701 int current_offset = iterator.current_offset(); |
| 709 EnterAndExitExceptionHandlers(current_offset); | 702 EnterAndExitExceptionHandlers(current_offset); |
| 710 SwitchToMergeEnvironment(current_offset); | 703 SwitchToMergeEnvironment(current_offset); |
| 711 if (environment() != nullptr) { | 704 if (environment() != nullptr) { |
| 712 BuildLoopHeaderEnvironment(current_offset); | 705 BuildLoopHeaderEnvironment(current_offset); |
| 706 BuildOSRLoopEntryPoint(current_offset); |
| 713 | 707 |
| 714 switch (iterator.current_bytecode()) { | 708 switch (iterator.current_bytecode()) { |
| 715 #define BYTECODE_CASE(name, ...) \ | 709 #define BYTECODE_CASE(name, ...) \ |
| 716 case interpreter::Bytecode::k##name: \ | 710 case interpreter::Bytecode::k##name: \ |
| 717 Visit##name(); \ | 711 Visit##name(); \ |
| 718 break; | 712 break; |
| 719 BYTECODE_LIST(BYTECODE_CASE) | 713 BYTECODE_LIST(BYTECODE_CASE) |
| 720 #undef BYTECODE_CODE | 714 #undef BYTECODE_CODE |
| 721 } | 715 } |
| 722 } | 716 } |
| (...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { | 1619 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { |
| 1626 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); | 1620 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); |
| 1627 } | 1621 } |
| 1628 | 1622 |
| 1629 void BytecodeGraphBuilder::VisitStackCheck() { | 1623 void BytecodeGraphBuilder::VisitStackCheck() { |
| 1630 FrameStateBeforeAndAfter states(this); | 1624 FrameStateBeforeAndAfter states(this); |
| 1631 Node* node = NewNode(javascript()->StackCheck()); | 1625 Node* node = NewNode(javascript()->StackCheck()); |
| 1632 environment()->RecordAfterState(node, &states); | 1626 environment()->RecordAfterState(node, &states); |
| 1633 } | 1627 } |
| 1634 | 1628 |
| 1635 void BytecodeGraphBuilder::VisitOsrPoll() { | 1629 void BytecodeGraphBuilder::VisitOsrPoll() {} |
| 1636 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge | |
| 1637 // the polling with existing bytecode. This will also guarantee that we are | |
| 1638 // not missing the OSR entry point, which we wouldn't catch right now. | |
| 1639 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { | |
| 1640 environment()->PrepareForOsr(); | |
| 1641 } | |
| 1642 } | |
| 1643 | 1630 |
| 1644 void BytecodeGraphBuilder::VisitReturn() { | 1631 void BytecodeGraphBuilder::VisitReturn() { |
| 1645 BuildLoopExitsForFunctionExit(); | 1632 BuildLoopExitsForFunctionExit(); |
| 1646 Node* control = | 1633 Node* control = |
| 1647 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1634 NewNode(common()->Return(), environment()->LookupAccumulator()); |
| 1648 MergeControlToLeaveFunction(control); | 1635 MergeControlToLeaveFunction(control); |
| 1649 } | 1636 } |
| 1650 | 1637 |
| 1651 void BytecodeGraphBuilder::VisitDebugger() { | 1638 void BytecodeGraphBuilder::VisitDebugger() { |
| 1652 FrameStateBeforeAndAfter states(this); | 1639 FrameStateBeforeAndAfter states(this); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1805 merge_environments_[target_offset]->Merge(environment()); | 1792 merge_environments_[target_offset]->Merge(environment()); |
| 1806 } | 1793 } |
| 1807 set_environment(nullptr); | 1794 set_environment(nullptr); |
| 1808 } | 1795 } |
| 1809 | 1796 |
| 1810 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1797 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
| 1811 exit_controls_.push_back(exit); | 1798 exit_controls_.push_back(exit); |
| 1812 set_environment(nullptr); | 1799 set_environment(nullptr); |
| 1813 } | 1800 } |
| 1814 | 1801 |
| 1802 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { |
| 1803 if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) { |
| 1804 // For OSR add a special {OsrLoopEntry} node into the current loop header. |
| 1805 // It will be turned into a usable entry by the OSR deconstruction. |
| 1806 environment()->PrepareForOsr(); |
| 1807 } |
| 1808 } |
| 1809 |
| 1810 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { |
| 1811 if (!osr_ast_id_.IsNone()) { |
| 1812 // For OSR add an {OsrNormalEntry} as the the top-level environment start. |
| 1813 // It will be replaced with {Dead} by the OSR deconstruction. |
| 1814 NewNode(common()->OsrNormalEntry()); |
| 1815 // Note that the requested OSR entry point must be the target of a backward |
| 1816 // branch, otherwise there will not be a proper loop header available. |
| 1817 DCHECK(branch_analysis()->backward_branches_target(osr_ast_id_.ToInt())); |
| 1818 } |
| 1819 } |
| 1820 |
| 1815 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { | 1821 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { |
| 1816 int origin_offset = bytecode_iterator().current_offset(); | 1822 int origin_offset = bytecode_iterator().current_offset(); |
| 1817 // Only build loop exits for forward edges. | 1823 // Only build loop exits for forward edges. |
| 1818 if (target_offset > origin_offset) { | 1824 if (target_offset > origin_offset) { |
| 1819 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); | 1825 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); |
| 1820 } | 1826 } |
| 1821 } | 1827 } |
| 1822 | 1828 |
| 1823 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { | 1829 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { |
| 1824 int origin_offset = bytecode_iterator().current_offset(); | 1830 int origin_offset = bytecode_iterator().current_offset(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2076 // Phi does not exist yet, introduce one. | 2082 // Phi does not exist yet, introduce one. |
| 2077 value = NewPhi(inputs, value, control); | 2083 value = NewPhi(inputs, value, control); |
| 2078 value->ReplaceInput(inputs - 1, other); | 2084 value->ReplaceInput(inputs - 1, other); |
| 2079 } | 2085 } |
| 2080 return value; | 2086 return value; |
| 2081 } | 2087 } |
| 2082 | 2088 |
| 2083 } // namespace compiler | 2089 } // namespace compiler |
| 2084 } // namespace internal | 2090 } // namespace internal |
| 2085 } // namespace v8 | 2091 } // namespace v8 |
| OLD | NEW |