| 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 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 jsgraph_(jsgraph), | 471 jsgraph_(jsgraph), |
| 472 bytecode_array_(handle(info()->shared_info()->bytecode_array())), | 472 bytecode_array_(handle(info()->shared_info()->bytecode_array())), |
| 473 exception_handler_table_( | 473 exception_handler_table_( |
| 474 handle(HandlerTable::cast(bytecode_array()->handler_table()))), | 474 handle(HandlerTable::cast(bytecode_array()->handler_table()))), |
| 475 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 475 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
| 476 FrameStateType::kInterpretedFunction, | 476 FrameStateType::kInterpretedFunction, |
| 477 bytecode_array()->parameter_count(), | 477 bytecode_array()->parameter_count(), |
| 478 bytecode_array()->register_count(), info()->shared_info(), | 478 bytecode_array()->register_count(), info()->shared_info(), |
| 479 CALL_MAINTAINS_NATIVE_CONTEXT)), | 479 CALL_MAINTAINS_NATIVE_CONTEXT)), |
| 480 merge_environments_(local_zone), | 480 merge_environments_(local_zone), |
| 481 loop_header_environments_(local_zone), | |
| 482 exception_handlers_(local_zone), | 481 exception_handlers_(local_zone), |
| 483 current_exception_handler_(0), | 482 current_exception_handler_(0), |
| 484 input_buffer_size_(0), | 483 input_buffer_size_(0), |
| 485 input_buffer_(nullptr), | 484 input_buffer_(nullptr), |
| 486 exit_controls_(local_zone) {} | 485 exit_controls_(local_zone) {} |
| 487 | 486 |
| 488 Node* BytecodeGraphBuilder::GetNewTarget() { | 487 Node* BytecodeGraphBuilder::GetNewTarget() { |
| 489 if (!new_target_.is_set()) { | 488 if (!new_target_.is_set()) { |
| 490 int params = bytecode_array()->parameter_count(); | 489 int params = bytecode_array()->parameter_count(); |
| 491 int index = Linkage::GetJSCallNewTargetParamIndex(params); | 490 int index = Linkage::GetJSCallNewTargetParamIndex(params); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 void BytecodeGraphBuilder::VisitBytecodes() { | 610 void BytecodeGraphBuilder::VisitBytecodes() { |
| 612 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 611 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
| 613 analysis.Analyze(); | 612 analysis.Analyze(); |
| 614 set_branch_analysis(&analysis); | 613 set_branch_analysis(&analysis); |
| 615 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 614 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
| 616 set_bytecode_iterator(&iterator); | 615 set_bytecode_iterator(&iterator); |
| 617 while (!iterator.done()) { | 616 while (!iterator.done()) { |
| 618 int current_offset = iterator.current_offset(); | 617 int current_offset = iterator.current_offset(); |
| 619 if (analysis.is_reachable(current_offset)) { | 618 if (analysis.is_reachable(current_offset)) { |
| 620 EnterAndExitExceptionHandlers(current_offset); | 619 EnterAndExitExceptionHandlers(current_offset); |
| 621 MergeEnvironmentsOfForwardBranches(current_offset); | 620 SwitchToMergeEnvironment(current_offset); |
| 622 BuildLoopHeaderForBackwardBranches(current_offset); | 621 BuildLoopHeaderEnvironment(current_offset); |
| 623 | 622 |
| 624 switch (iterator.current_bytecode()) { | 623 switch (iterator.current_bytecode()) { |
| 625 #define BYTECODE_CASE(name, ...) \ | 624 #define BYTECODE_CASE(name, ...) \ |
| 626 case interpreter::Bytecode::k##name: \ | 625 case interpreter::Bytecode::k##name: \ |
| 627 Visit##name(); \ | 626 Visit##name(); \ |
| 628 break; | 627 break; |
| 629 BYTECODE_LIST(BYTECODE_CASE) | 628 BYTECODE_LIST(BYTECODE_CASE) |
| 630 #undef BYTECODE_CODE | 629 #undef BYTECODE_CODE |
| 631 } | 630 } |
| 632 } | 631 } |
| (...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 void BytecodeGraphBuilder::VisitForInNextWide() { BuildForInNext(); } | 1594 void BytecodeGraphBuilder::VisitForInNextWide() { BuildForInNext(); } |
| 1596 | 1595 |
| 1597 void BytecodeGraphBuilder::VisitForInStep() { | 1596 void BytecodeGraphBuilder::VisitForInStep() { |
| 1598 FrameStateBeforeAndAfter states(this); | 1597 FrameStateBeforeAndAfter states(this); |
| 1599 Node* index = | 1598 Node* index = |
| 1600 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); | 1599 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); |
| 1601 index = NewNode(javascript()->ForInStep(), index); | 1600 index = NewNode(javascript()->ForInStep(), index); |
| 1602 environment()->BindAccumulator(index, &states); | 1601 environment()->BindAccumulator(index, &states); |
| 1603 } | 1602 } |
| 1604 | 1603 |
| 1605 | 1604 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { |
| 1606 void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches( | 1605 if (merge_environments_[current_offset] != nullptr) { |
| 1607 int source_offset, int target_offset) { | 1606 if (environment() != nullptr) { |
| 1608 DCHECK_GE(source_offset, target_offset); | 1607 merge_environments_[current_offset]->Merge(environment()); |
| 1609 const ZoneVector<int>* branch_sites = | |
| 1610 branch_analysis()->BackwardBranchesTargetting(target_offset); | |
| 1611 if (branch_sites->back() == source_offset) { | |
| 1612 // The set of back branches is complete, merge them. | |
| 1613 DCHECK_GE(branch_sites->at(0), target_offset); | |
| 1614 Environment* merged = merge_environments_[branch_sites->at(0)]; | |
| 1615 for (size_t i = 1; i < branch_sites->size(); i++) { | |
| 1616 DCHECK_GE(branch_sites->at(i), target_offset); | |
| 1617 merged->Merge(merge_environments_[branch_sites->at(i)]); | |
| 1618 } | 1608 } |
| 1619 // And now merge with loop header environment created when loop | 1609 set_environment(merge_environments_[current_offset]); |
| 1620 // header was visited. | |
| 1621 loop_header_environments_[target_offset]->Merge(merged); | |
| 1622 } | 1610 } |
| 1623 } | 1611 } |
| 1624 | 1612 |
| 1625 | 1613 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
| 1626 void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches( | 1614 if (branch_analysis()->backward_branches_target(current_offset)) { |
| 1627 int source_offset) { | 1615 // Add loop header and store a copy so we can connect merged back |
| 1628 if (branch_analysis()->forward_branches_target(source_offset)) { | 1616 // edge inputs to the loop header. |
| 1629 // Merge environments of branches that reach this bytecode. | 1617 merge_environments_[current_offset] = environment()->CopyForLoop(); |
| 1630 auto branch_sites = | |
| 1631 branch_analysis()->ForwardBranchesTargetting(source_offset); | |
| 1632 DCHECK_LT(branch_sites->at(0), source_offset); | |
| 1633 Environment* merged = merge_environments_[branch_sites->at(0)]; | |
| 1634 for (size_t i = 1; i < branch_sites->size(); i++) { | |
| 1635 DCHECK_LT(branch_sites->at(i), source_offset); | |
| 1636 merged->Merge(merge_environments_[branch_sites->at(i)]); | |
| 1637 } | |
| 1638 if (environment()) { | |
| 1639 merged->Merge(environment()); | |
| 1640 } | |
| 1641 set_environment(merged); | |
| 1642 } | 1618 } |
| 1643 } | 1619 } |
| 1644 | 1620 |
| 1645 | 1621 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { |
| 1646 void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches( | 1622 if (merge_environments_[target_offset] == nullptr) { |
| 1647 int source_offset) { | 1623 // Append merge nodes to the environment. We may merge here with another |
| 1648 if (branch_analysis()->backward_branches_target(source_offset)) { | 1624 // environment. So add a place holder for merge nodes. We may add redundant |
| 1649 // Add loop header and store a copy so we can connect merged back | 1625 // but will be eliminated in a later pass. |
| 1650 // edge inputs to the loop header. | 1626 // TODO(mstarzinger): Be smarter about this! |
| 1651 loop_header_environments_[source_offset] = environment()->CopyForLoop(); | 1627 NewMerge(); |
| 1652 } | 1628 merge_environments_[target_offset] = environment(); |
| 1653 } | 1629 } else { |
| 1654 | 1630 merge_environments_[target_offset]->Merge(environment()); |
| 1655 | |
| 1656 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { | |
| 1657 DCHECK_NULL(merge_environments_[source_offset]); | |
| 1658 // Append merge nodes to the environment. We may merge here with another | |
| 1659 // environment. So add a place holder for merge nodes. We may add redundant | |
| 1660 // but will be eliminated in a later pass. | |
| 1661 // TODO(mstarzinger): This can be simplified by propagating environment | |
| 1662 // forward along the direction of the dataflow. | |
| 1663 NewMerge(); | |
| 1664 merge_environments_[source_offset] = environment(); | |
| 1665 if (source_offset >= target_offset) { | |
| 1666 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset); | |
| 1667 } | 1631 } |
| 1668 set_environment(nullptr); | 1632 set_environment(nullptr); |
| 1669 } | 1633 } |
| 1670 | 1634 |
| 1671 | 1635 |
| 1672 void BytecodeGraphBuilder::BuildJump() { | 1636 void BytecodeGraphBuilder::BuildJump() { |
| 1673 int source_offset = bytecode_iterator().current_offset(); | 1637 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
| 1674 int target_offset = bytecode_iterator().GetJumpTargetOffset(); | |
| 1675 BuildJump(source_offset, target_offset); | |
| 1676 } | 1638 } |
| 1677 | 1639 |
| 1678 | 1640 |
| 1679 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | 1641 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { |
| 1680 int source_offset = bytecode_iterator().current_offset(); | |
| 1681 NewBranch(condition); | 1642 NewBranch(condition); |
| 1682 Environment* if_false_environment = environment()->CopyForConditional(); | 1643 Environment* if_false_environment = environment()->CopyForConditional(); |
| 1683 NewIfTrue(); | 1644 NewIfTrue(); |
| 1684 BuildJump(source_offset, bytecode_iterator().GetJumpTargetOffset()); | 1645 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
| 1685 set_environment(if_false_environment); | 1646 set_environment(if_false_environment); |
| 1686 NewIfFalse(); | 1647 NewIfFalse(); |
| 1687 } | 1648 } |
| 1688 | 1649 |
| 1689 | 1650 |
| 1690 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { | 1651 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { |
| 1691 Node* accumulator = environment()->LookupAccumulator(); | 1652 Node* accumulator = environment()->LookupAccumulator(); |
| 1692 Node* condition = | 1653 Node* condition = |
| 1693 NewNode(javascript()->StrictEqual(), accumulator, comperand); | 1654 NewNode(javascript()->StrictEqual(), accumulator, comperand); |
| 1694 BuildConditionalJump(condition); | 1655 BuildConditionalJump(condition); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 // Update the current control dependency for control-producing nodes. | 1751 // Update the current control dependency for control-producing nodes. |
| 1791 if (NodeProperties::IsControl(result)) { | 1752 if (NodeProperties::IsControl(result)) { |
| 1792 environment()->UpdateControlDependency(result); | 1753 environment()->UpdateControlDependency(result); |
| 1793 } | 1754 } |
| 1794 // Update the current effect dependency for effect-producing nodes. | 1755 // Update the current effect dependency for effect-producing nodes. |
| 1795 if (result->op()->EffectOutputCount() > 0) { | 1756 if (result->op()->EffectOutputCount() > 0) { |
| 1796 environment()->UpdateEffectDependency(result); | 1757 environment()->UpdateEffectDependency(result); |
| 1797 } | 1758 } |
| 1798 // Add implicit exception continuation for throwing nodes. | 1759 // Add implicit exception continuation for throwing nodes. |
| 1799 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { | 1760 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { |
| 1800 int throw_offset = bytecode_iterator().current_offset(); | |
| 1801 int handler_offset = exception_handlers_.top().handler_offset_; | 1761 int handler_offset = exception_handlers_.top().handler_offset_; |
| 1802 // TODO(mstarzinger): Thread through correct prediction! | 1762 // TODO(mstarzinger): Thread through correct prediction! |
| 1803 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; | 1763 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; |
| 1804 // TODO(mstarzinger): For now we mutate the branch analysis result and | |
| 1805 // add the artificial control flow from throw-site to handler-entry. | |
| 1806 // This can be simplified by pushing environment forward along the | |
| 1807 // direction of the data-flow. | |
| 1808 branch_analysis_->AddExceptionalBranch(throw_offset, handler_offset); | |
| 1809 Environment* success_env = environment()->CopyForConditional(); | 1764 Environment* success_env = environment()->CopyForConditional(); |
| 1810 const Operator* op = common()->IfException(hint); | 1765 const Operator* op = common()->IfException(hint); |
| 1811 Node* effect = environment()->GetEffectDependency(); | 1766 Node* effect = environment()->GetEffectDependency(); |
| 1812 Node* on_exception = graph()->NewNode(op, effect, result); | 1767 Node* on_exception = graph()->NewNode(op, effect, result); |
| 1813 environment()->UpdateControlDependency(on_exception); | 1768 environment()->UpdateControlDependency(on_exception); |
| 1814 environment()->UpdateEffectDependency(on_exception); | 1769 environment()->UpdateEffectDependency(on_exception); |
| 1815 environment()->BindAccumulator(on_exception); | 1770 environment()->BindAccumulator(on_exception); |
| 1816 BuildJump(throw_offset, handler_offset); | 1771 MergeIntoSuccessorEnvironment(handler_offset); |
| 1817 set_environment(success_env); | 1772 set_environment(success_env); |
| 1818 } | 1773 } |
| 1819 // Add implicit success continuation for throwing nodes. | 1774 // Add implicit success continuation for throwing nodes. |
| 1820 if (!result->op()->HasProperty(Operator::kNoThrow)) { | 1775 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 1821 const Operator* if_success = common()->IfSuccess(); | 1776 const Operator* if_success = common()->IfSuccess(); |
| 1822 Node* on_success = graph()->NewNode(if_success, result); | 1777 Node* on_success = graph()->NewNode(if_success, result); |
| 1823 environment()->UpdateControlDependency(on_success); | 1778 environment()->UpdateControlDependency(on_success); |
| 1824 } | 1779 } |
| 1825 } | 1780 } |
| 1826 } | 1781 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1907 | 1862 |
| 1908 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 1863 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
| 1909 if (environment()->IsMarkedAsUnreachable()) return; | 1864 if (environment()->IsMarkedAsUnreachable()) return; |
| 1910 environment()->MarkAsUnreachable(); | 1865 environment()->MarkAsUnreachable(); |
| 1911 exit_controls_.push_back(exit); | 1866 exit_controls_.push_back(exit); |
| 1912 } | 1867 } |
| 1913 | 1868 |
| 1914 } // namespace compiler | 1869 } // namespace compiler |
| 1915 } // namespace internal | 1870 } // namespace internal |
| 1916 } // namespace v8 | 1871 } // namespace v8 |
| OLD | NEW |