OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 #if !defined(DART_PRECOMPILED_RUNTIME) | 4 #if !defined(DART_PRECOMPILED_RUNTIME) |
5 #include "vm/flow_graph_inliner.h" | 5 #include "vm/flow_graph_inliner.h" |
6 | 6 |
7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
8 #include "vm/precompiler.h" | 8 #include "vm/precompiler.h" |
9 #include "vm/block_scheduler.h" | 9 #include "vm/block_scheduler.h" |
10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
(...skipping 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1473 inlined_entries_[i]->AsGraphEntry()->UnuseAllInputs(); | 1473 inlined_entries_[i]->AsGraphEntry()->UnuseAllInputs(); |
1474 | 1474 |
1475 JoinEntryInstr* new_join = | 1475 JoinEntryInstr* new_join = |
1476 BranchSimplifier::ToJoinEntry(zone(), old_target); | 1476 BranchSimplifier::ToJoinEntry(zone(), old_target); |
1477 old_target->ReplaceAsPredecessorWith(new_join); | 1477 old_target->ReplaceAsPredecessorWith(new_join); |
1478 for (intptr_t j = 0; j < old_target->dominated_blocks().length(); ++j) { | 1478 for (intptr_t j = 0; j < old_target->dominated_blocks().length(); ++j) { |
1479 BlockEntryInstr* block = old_target->dominated_blocks()[j]; | 1479 BlockEntryInstr* block = old_target->dominated_blocks()[j]; |
1480 new_join->AddDominatedBlock(block); | 1480 new_join->AddDominatedBlock(block); |
1481 } | 1481 } |
1482 // Create a new target with the join as unconditional successor. | 1482 // Create a new target with the join as unconditional successor. |
1483 TargetEntryInstr* new_target = | 1483 TargetEntryInstr* new_target = new TargetEntryInstr( |
1484 new TargetEntryInstr(AllocateBlockId(), old_target->try_index()); | 1484 AllocateBlockId(), old_target->try_index(), Thread::kNoDeoptId); |
1485 new_target->InheritDeoptTarget(zone(), new_join); | 1485 new_target->InheritDeoptTarget(zone(), new_join); |
1486 GotoInstr* new_goto = new (Z) GotoInstr(new_join); | 1486 GotoInstr* new_goto = new (Z) GotoInstr(new_join, Thread::kNoDeoptId); |
1487 new_goto->InheritDeoptTarget(zone(), new_join); | 1487 new_goto->InheritDeoptTarget(zone(), new_join); |
1488 new_target->LinkTo(new_goto); | 1488 new_target->LinkTo(new_goto); |
1489 new_target->set_last_instruction(new_goto); | 1489 new_target->set_last_instruction(new_goto); |
1490 new_join->predecessors_.Add(new_target); | 1490 new_join->predecessors_.Add(new_target); |
1491 | 1491 |
1492 // Record the new target for the first variant. | 1492 // Record the new target for the first variant. |
1493 inlined_entries_[i] = new_target; | 1493 inlined_entries_[i] = new_target; |
1494 } | 1494 } |
1495 ASSERT(inlined_entries_[i]->IsTargetEntry()); | 1495 ASSERT(inlined_entries_[i]->IsTargetEntry()); |
1496 // Record the shared join for this variant. | 1496 // Record the shared join for this variant. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1615 owner_->caller_graph()->alloc_ssa_temp_index()); | 1615 owner_->caller_graph()->alloc_ssa_temp_index()); |
1616 if (FlowGraphInliner::TryInlineRecognizedMethod( | 1616 if (FlowGraphInliner::TryInlineRecognizedMethod( |
1617 owner_->caller_graph(), receiver_cid, target, call_, redefinition, | 1617 owner_->caller_graph(), receiver_cid, target, call_, redefinition, |
1618 call_->instance_call()->token_pos(), | 1618 call_->instance_call()->token_pos(), |
1619 *call_->instance_call()->ic_data(), &entry, &last)) { | 1619 *call_->instance_call()->ic_data(), &entry, &last)) { |
1620 // Create a graph fragment. | 1620 // Create a graph fragment. |
1621 redefinition->InsertAfter(entry); | 1621 redefinition->InsertAfter(entry); |
1622 InlineExitCollector* exit_collector = | 1622 InlineExitCollector* exit_collector = |
1623 new (Z) InlineExitCollector(owner_->caller_graph(), call_); | 1623 new (Z) InlineExitCollector(owner_->caller_graph(), call_); |
1624 | 1624 |
1625 ReturnInstr* result = new (Z) | 1625 ReturnInstr* result = |
1626 ReturnInstr(call_->instance_call()->token_pos(), new (Z) Value(last)); | 1626 new (Z) ReturnInstr(call_->instance_call()->token_pos(), |
1627 new (Z) Value(last), Thread::kNoDeoptId); | |
1627 owner_->caller_graph()->AppendTo( | 1628 owner_->caller_graph()->AppendTo( |
1628 last, result, | 1629 last, result, |
1629 call_->env(), // Return can become deoptimization target. | 1630 call_->env(), // Return can become deoptimization target. |
1630 FlowGraph::kEffect); | 1631 FlowGraph::kEffect); |
1631 entry->set_last_instruction(result); | 1632 entry->set_last_instruction(result); |
1632 exit_collector->AddExit(result); | 1633 exit_collector->AddExit(result); |
1633 ParsedFunction* temp_parsed_function = | 1634 ParsedFunction* temp_parsed_function = |
1634 new ParsedFunction(Thread::Current(), target); | 1635 new ParsedFunction(Thread::Current(), target); |
1635 GraphEntryInstr* graph_entry = new (Z) | 1636 GraphEntryInstr* graph_entry = new (Z) |
1636 GraphEntryInstr(*temp_parsed_function, entry, Compiler::kNoOSRDeoptId); | 1637 GraphEntryInstr(*temp_parsed_function, entry, Compiler::kNoOSRDeoptId); |
1637 // Update polymorphic inliner state. | 1638 // Update polymorphic inliner state. |
1638 inlined_entries_.Add(graph_entry); | 1639 inlined_entries_.Add(graph_entry); |
1639 exit_collector_->Union(exit_collector); | 1640 exit_collector_->Union(exit_collector); |
1640 return true; | 1641 return true; |
1641 } | 1642 } |
1642 return false; | 1643 return false; |
1643 } | 1644 } |
1644 | 1645 |
1645 | 1646 |
1646 // Build a DAG to dispatch to the inlined function bodies. Load the class | 1647 // Build a DAG to dispatch to the inlined function bodies. Load the class |
1647 // id of the receiver and make explicit comparisons for each inlined body, | 1648 // id of the receiver and make explicit comparisons for each inlined body, |
1648 // in frequency order. If all variants are inlined, the entry to the last | 1649 // in frequency order. If all variants are inlined, the entry to the last |
1649 // inlined body is guarded by a CheckClassId instruction which can deopt. | 1650 // inlined body is guarded by a CheckClassId instruction which can deopt. |
1650 // If not all variants are inlined, we add a PolymorphicInstanceCall | 1651 // If not all variants are inlined, we add a PolymorphicInstanceCall |
1651 // instruction to handle the non-inlined variants. | 1652 // instruction to handle the non-inlined variants. |
1652 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { | 1653 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { |
1653 const intptr_t try_idx = call_->GetBlock()->try_index(); | 1654 const intptr_t try_idx = call_->GetBlock()->try_index(); |
1654 | 1655 |
1655 // Start with a fresh target entry. | 1656 // Start with a fresh target entry. |
1656 TargetEntryInstr* entry = | 1657 TargetEntryInstr* entry = new (Z) TargetEntryInstr( |
1657 new (Z) TargetEntryInstr(AllocateBlockId(), try_idx); | 1658 AllocateBlockId(), try_idx, Thread::Current()->GetNextDeoptId()); |
1658 entry->InheritDeoptTarget(zone(), call_); | 1659 entry->InheritDeoptTarget(zone(), call_); |
1659 | 1660 |
1660 // This function uses a cursor (a pointer to the 'current' instruction) to | 1661 // This function uses a cursor (a pointer to the 'current' instruction) to |
1661 // build the graph. The next instruction will be inserted after the | 1662 // build the graph. The next instruction will be inserted after the |
1662 // cursor. | 1663 // cursor. |
1663 BlockEntryInstr* current_block = entry; | 1664 BlockEntryInstr* current_block = entry; |
1664 Instruction* cursor = entry; | 1665 Instruction* cursor = entry; |
1665 | 1666 |
1666 Definition* receiver = call_->ArgumentAt(0); | 1667 Definition* receiver = call_->ArgumentAt(0); |
1667 // There are at least two variants including non-inlined ones, so we have | 1668 // There are at least two variants including non-inlined ones, so we have |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1712 for (intptr_t j = 0; j < target->dominated_blocks().length(); ++j) { | 1713 for (intptr_t j = 0; j < target->dominated_blocks().length(); ++j) { |
1713 BlockEntryInstr* block = target->dominated_blocks()[j]; | 1714 BlockEntryInstr* block = target->dominated_blocks()[j]; |
1714 current_block->AddDominatedBlock(block); | 1715 current_block->AddDominatedBlock(block); |
1715 } | 1716 } |
1716 } else if (callee_entry->IsJoinEntry()) { | 1717 } else if (callee_entry->IsJoinEntry()) { |
1717 // Shared inlined body and this is a subsequent entry. We have | 1718 // Shared inlined body and this is a subsequent entry. We have |
1718 // already constructed a join and set its dominator. Add a jump to | 1719 // already constructed a join and set its dominator. Add a jump to |
1719 // the join. | 1720 // the join. |
1720 JoinEntryInstr* join = callee_entry->AsJoinEntry(); | 1721 JoinEntryInstr* join = callee_entry->AsJoinEntry(); |
1721 ASSERT(join->dominator() != NULL); | 1722 ASSERT(join->dominator() != NULL); |
1722 GotoInstr* goto_join = new GotoInstr(join); | 1723 GotoInstr* goto_join = new GotoInstr(join, Thread::kNoDeoptId); |
1723 goto_join->InheritDeoptTarget(zone(), join); | 1724 goto_join->InheritDeoptTarget(zone(), join); |
1724 cursor->LinkTo(goto_join); | 1725 cursor->LinkTo(goto_join); |
1725 current_block->set_last_instruction(goto_join); | 1726 current_block->set_last_instruction(goto_join); |
1726 } else { | 1727 } else { |
1727 // There is no possibility of a TargetEntry (the first entry to a | 1728 // There is no possibility of a TargetEntry (the first entry to a |
1728 // shared inlined body) because this is the last inlined entry. | 1729 // shared inlined body) because this is the last inlined entry. |
1729 UNREACHABLE(); | 1730 UNREACHABLE(); |
1730 } | 1731 } |
1731 cursor = NULL; | 1732 cursor = NULL; |
1732 } else { | 1733 } else { |
1733 // For all variants except the last, use a branch on the loaded class | 1734 // For all variants except the last, use a branch on the loaded class |
1734 // id. | 1735 // id. |
1735 const Smi& cid = Smi::ZoneHandle(Smi::New(variant.cid_start)); | 1736 const Smi& cid = Smi::ZoneHandle(Smi::New(variant.cid_start)); |
1736 ConstantInstr* cid_constant = owner_->caller_graph()->GetConstant(cid); | 1737 ConstantInstr* cid_constant = owner_->caller_graph()->GetConstant(cid); |
1737 BranchInstr* branch; | 1738 BranchInstr* branch; |
1738 BranchInstr* upper_limit_branch = NULL; | 1739 BranchInstr* upper_limit_branch = NULL; |
1739 BlockEntryInstr* cid_test_entry_block = current_block; | 1740 BlockEntryInstr* cid_test_entry_block = current_block; |
1740 if (test_is_range) { | 1741 if (test_is_range) { |
1741 // Double branch for testing a range of Cids. TODO(erikcorry): Make a | 1742 // Double branch for testing a range of Cids. TODO(erikcorry): Make a |
1742 // special instruction that uses subtraction and unsigned comparison to | 1743 // special instruction that uses subtraction and unsigned comparison to |
1743 // do this with a single branch. | 1744 // do this with a single branch. |
1744 const Smi& cid_end = Smi::ZoneHandle(Smi::New(variant.cid_end)); | 1745 const Smi& cid_end = Smi::ZoneHandle(Smi::New(variant.cid_end)); |
1745 ConstantInstr* cid_constant_end = | 1746 ConstantInstr* cid_constant_end = |
1746 owner_->caller_graph()->GetConstant(cid_end); | 1747 owner_->caller_graph()->GetConstant(cid_end); |
1747 RelationalOpInstr* compare_top = new RelationalOpInstr( | 1748 RelationalOpInstr* compare_top = new RelationalOpInstr( |
1748 call_->instance_call()->token_pos(), Token::kLTE, | 1749 call_->instance_call()->token_pos(), Token::kLTE, |
1749 new Value(load_cid), new Value(cid_constant_end), kSmiCid, | 1750 new Value(load_cid), new Value(cid_constant_end), kSmiCid, |
1750 call_->deopt_id()); | 1751 call_->deopt_id()); |
1751 BranchInstr* branch_top = upper_limit_branch = | 1752 BranchInstr* branch_top = upper_limit_branch = |
1752 new BranchInstr(compare_top); | 1753 new BranchInstr(compare_top, Thread::kNoDeoptId); |
1753 branch_top->InheritDeoptTarget(zone(), call_); | 1754 branch_top->InheritDeoptTarget(zone(), call_); |
1754 cursor = AppendInstruction(cursor, branch_top); | 1755 cursor = AppendInstruction(cursor, branch_top); |
1755 current_block->set_last_instruction(branch_top); | 1756 current_block->set_last_instruction(branch_top); |
1756 | 1757 |
1757 TargetEntryInstr* below_target = | 1758 TargetEntryInstr* below_target = new TargetEntryInstr( |
1758 new TargetEntryInstr(AllocateBlockId(), try_idx); | 1759 AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1759 below_target->InheritDeoptTarget(zone(), call_); | 1760 below_target->InheritDeoptTarget(zone(), call_); |
1760 current_block->AddDominatedBlock(below_target); | 1761 current_block->AddDominatedBlock(below_target); |
1761 cursor = current_block = below_target; | 1762 cursor = current_block = below_target; |
1762 *branch_top->true_successor_address() = below_target; | 1763 *branch_top->true_successor_address() = below_target; |
1763 | 1764 |
1764 RelationalOpInstr* compare_bottom = new RelationalOpInstr( | 1765 RelationalOpInstr* compare_bottom = new RelationalOpInstr( |
1765 call_->instance_call()->token_pos(), Token::kGTE, | 1766 call_->instance_call()->token_pos(), Token::kGTE, |
1766 new Value(load_cid), new Value(cid_constant), kSmiCid, | 1767 new Value(load_cid), new Value(cid_constant), kSmiCid, |
1767 call_->deopt_id()); | 1768 call_->deopt_id()); |
1768 branch = new BranchInstr(compare_bottom); | 1769 branch = new BranchInstr(compare_bottom, Thread::kNoDeoptId); |
1769 } else { | 1770 } else { |
1770 StrictCompareInstr* compare = new StrictCompareInstr( | 1771 StrictCompareInstr* compare = new StrictCompareInstr( |
1771 call_->instance_call()->token_pos(), Token::kEQ_STRICT, | 1772 call_->instance_call()->token_pos(), Token::kEQ_STRICT, |
1772 new Value(load_cid), new Value(cid_constant), | 1773 new Value(load_cid), new Value(cid_constant), |
1773 false); // No number check. | 1774 /* number_check = */ false, Thread::kNoDeoptId); |
1774 branch = new BranchInstr(compare); | 1775 branch = new BranchInstr(compare, Thread::kNoDeoptId); |
1775 } | 1776 } |
1776 | 1777 |
1777 branch->InheritDeoptTarget(zone(), call_); | 1778 branch->InheritDeoptTarget(zone(), call_); |
1778 cursor = AppendInstruction(cursor, branch); | 1779 cursor = AppendInstruction(cursor, branch); |
1779 current_block->set_last_instruction(branch); | 1780 current_block->set_last_instruction(branch); |
1780 cursor = NULL; | 1781 cursor = NULL; |
1781 | 1782 |
1782 // 2. Handle a match by linking to the inlined body. There are three | 1783 // 2. Handle a match by linking to the inlined body. There are three |
1783 // cases (unshared, shared first predecessor, and shared subsequent | 1784 // cases (unshared, shared first predecessor, and shared subsequent |
1784 // predecessors). | 1785 // predecessors). |
(...skipping 10 matching lines...) Expand all Loading... | |
1795 true_target = callee_entry->AsTargetEntry(); | 1796 true_target = callee_entry->AsTargetEntry(); |
1796 BlockEntryInstr* join = true_target->last_instruction()->SuccessorAt(0); | 1797 BlockEntryInstr* join = true_target->last_instruction()->SuccessorAt(0); |
1797 current_block->AddDominatedBlock(join); | 1798 current_block->AddDominatedBlock(join); |
1798 } else { | 1799 } else { |
1799 // Shared inlined body and this is a subsequent entry. We have | 1800 // Shared inlined body and this is a subsequent entry. We have |
1800 // already constructed a join. We need a fresh target that jumps to | 1801 // already constructed a join. We need a fresh target that jumps to |
1801 // the join. | 1802 // the join. |
1802 JoinEntryInstr* join = callee_entry->AsJoinEntry(); | 1803 JoinEntryInstr* join = callee_entry->AsJoinEntry(); |
1803 ASSERT(join != NULL); | 1804 ASSERT(join != NULL); |
1804 ASSERT(join->dominator() != NULL); | 1805 ASSERT(join->dominator() != NULL); |
1805 true_target = new TargetEntryInstr(AllocateBlockId(), try_idx); | 1806 true_target = new TargetEntryInstr(AllocateBlockId(), try_idx, |
1807 Thread::kNoDeoptId); | |
1806 true_target->InheritDeoptTarget(zone(), join); | 1808 true_target->InheritDeoptTarget(zone(), join); |
1807 GotoInstr* goto_join = new GotoInstr(join); | 1809 GotoInstr* goto_join = new GotoInstr(join, Thread::kNoDeoptId); |
1808 goto_join->InheritDeoptTarget(zone(), join); | 1810 goto_join->InheritDeoptTarget(zone(), join); |
1809 true_target->LinkTo(goto_join); | 1811 true_target->LinkTo(goto_join); |
1810 true_target->set_last_instruction(goto_join); | 1812 true_target->set_last_instruction(goto_join); |
1811 } | 1813 } |
1812 *branch->true_successor_address() = true_target; | 1814 *branch->true_successor_address() = true_target; |
1813 current_block->AddDominatedBlock(true_target); | 1815 current_block->AddDominatedBlock(true_target); |
1814 | 1816 |
1815 // 3. Prepare to handle a match failure on the next iteration or the | 1817 // 3. Prepare to handle a match failure on the next iteration or the |
1816 // fall-through code below for non-inlined variants. | 1818 // fall-through code below for non-inlined variants. |
1817 | 1819 |
1818 TargetEntryInstr* false_target = | 1820 TargetEntryInstr* false_target = |
1819 new TargetEntryInstr(AllocateBlockId(), try_idx); | 1821 new TargetEntryInstr(AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1820 false_target->InheritDeoptTarget(zone(), call_); | 1822 false_target->InheritDeoptTarget(zone(), call_); |
1821 *branch->false_successor_address() = false_target; | 1823 *branch->false_successor_address() = false_target; |
1822 cid_test_entry_block->AddDominatedBlock(false_target); | 1824 cid_test_entry_block->AddDominatedBlock(false_target); |
1823 | 1825 |
1824 cursor = current_block = false_target; | 1826 cursor = current_block = false_target; |
1825 | 1827 |
1826 if (test_is_range) { | 1828 if (test_is_range) { |
1827 // If we tested against a range of Cids there are two different tests | 1829 // If we tested against a range of Cids there are two different tests |
1828 // that can go to the no-cid-match target. | 1830 // that can go to the no-cid-match target. |
1829 JoinEntryInstr* join = new JoinEntryInstr(AllocateBlockId(), try_idx); | 1831 JoinEntryInstr* join = |
1830 TargetEntryInstr* false_target2 = | 1832 new JoinEntryInstr(AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1831 new TargetEntryInstr(AllocateBlockId(), try_idx); | 1833 TargetEntryInstr* false_target2 = new TargetEntryInstr( |
1834 AllocateBlockId(), try_idx, Thread::kNoDeoptId); | |
1832 *upper_limit_branch->false_successor_address() = false_target2; | 1835 *upper_limit_branch->false_successor_address() = false_target2; |
1833 cid_test_entry_block->AddDominatedBlock(false_target2); | 1836 cid_test_entry_block->AddDominatedBlock(false_target2); |
1834 cid_test_entry_block->AddDominatedBlock(join); | 1837 cid_test_entry_block->AddDominatedBlock(join); |
1835 GotoInstr* goto_1 = new GotoInstr(join); | 1838 GotoInstr* goto_1 = new GotoInstr(join, Thread::kNoDeoptId); |
1836 GotoInstr* goto_2 = new GotoInstr(join); | 1839 GotoInstr* goto_2 = new GotoInstr(join, Thread::kNoDeoptId); |
1837 false_target->LinkTo(goto_1); | 1840 false_target->LinkTo(goto_1); |
1838 false_target2->LinkTo(goto_2); | 1841 false_target2->LinkTo(goto_2); |
1839 false_target->set_last_instruction(goto_1); | 1842 false_target->set_last_instruction(goto_1); |
1840 false_target2->set_last_instruction(goto_2); | 1843 false_target2->set_last_instruction(goto_2); |
1841 | 1844 |
1842 join->InheritDeoptTarget(zone(), call_); | 1845 join->InheritDeoptTarget(zone(), call_); |
1843 false_target2->InheritDeoptTarget(zone(), call_); | 1846 false_target2->InheritDeoptTarget(zone(), call_); |
1844 goto_1->InheritDeoptTarget(zone(), call_); | 1847 goto_1->InheritDeoptTarget(zone(), call_); |
1845 goto_2->InheritDeoptTarget(zone(), call_); | 1848 goto_2->InheritDeoptTarget(zone(), call_); |
1846 | 1849 |
(...skipping 12 matching lines...) Expand all Loading... | |
1859 cursor->LinkTo(push); | 1862 cursor->LinkTo(push); |
1860 cursor = push; | 1863 cursor = push; |
1861 } | 1864 } |
1862 PolymorphicInstanceCallInstr* fallback_call = | 1865 PolymorphicInstanceCallInstr* fallback_call = |
1863 new PolymorphicInstanceCallInstr( | 1866 new PolymorphicInstanceCallInstr( |
1864 call_->instance_call(), *non_inlined_variants_, call_->complete()); | 1867 call_->instance_call(), *non_inlined_variants_, call_->complete()); |
1865 fallback_call->set_ssa_temp_index( | 1868 fallback_call->set_ssa_temp_index( |
1866 owner_->caller_graph()->alloc_ssa_temp_index()); | 1869 owner_->caller_graph()->alloc_ssa_temp_index()); |
1867 fallback_call->InheritDeoptTarget(zone(), call_); | 1870 fallback_call->InheritDeoptTarget(zone(), call_); |
1868 fallback_call->set_total_call_count(call_->CallCount()); | 1871 fallback_call->set_total_call_count(call_->CallCount()); |
1869 ReturnInstr* fallback_return = new ReturnInstr( | 1872 ReturnInstr* fallback_return = |
1870 call_->instance_call()->token_pos(), new Value(fallback_call)); | 1873 new ReturnInstr(call_->instance_call()->token_pos(), |
1874 new Value(fallback_call), Thread::kNoDeoptId); | |
1871 fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_, | 1875 fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_, |
1872 fallback_call); | 1876 fallback_call); |
1873 AppendInstruction(AppendInstruction(cursor, fallback_call), | 1877 AppendInstruction(AppendInstruction(cursor, fallback_call), |
1874 fallback_return); | 1878 fallback_return); |
1875 exit_collector_->AddExit(fallback_return); | 1879 exit_collector_->AddExit(fallback_return); |
1876 cursor = NULL; | 1880 cursor = NULL; |
1877 } else { | 1881 } else { |
1878 // Remove push arguments of the call. | 1882 // Remove push arguments of the call. |
1879 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { | 1883 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { |
1880 PushArgumentInstr* push = call_->PushArgumentAt(i); | 1884 PushArgumentInstr* push = call_->PushArgumentAt(i); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2236 static bool InlineGetIndexed(FlowGraph* flow_graph, | 2240 static bool InlineGetIndexed(FlowGraph* flow_graph, |
2237 MethodRecognizer::Kind kind, | 2241 MethodRecognizer::Kind kind, |
2238 Instruction* call, | 2242 Instruction* call, |
2239 Definition* receiver, | 2243 Definition* receiver, |
2240 TargetEntryInstr** entry, | 2244 TargetEntryInstr** entry, |
2241 Definition** last) { | 2245 Definition** last) { |
2242 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); | 2246 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); |
2243 | 2247 |
2244 Definition* array = receiver; | 2248 Definition* array = receiver; |
2245 Definition* index = call->ArgumentAt(1); | 2249 Definition* index = call->ArgumentAt(1); |
2246 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2250 *entry = new (Z) |
2247 call->GetBlock()->try_index()); | 2251 TargetEntryInstr(flow_graph->allocate_block_id(), |
2252 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2248 (*entry)->InheritDeoptTarget(Z, call); | 2253 (*entry)->InheritDeoptTarget(Z, call); |
2249 Instruction* cursor = *entry; | 2254 Instruction* cursor = *entry; |
2250 | 2255 |
2251 array_cid = PrepareInlineIndexedOp(flow_graph, call, array_cid, &array, index, | 2256 array_cid = PrepareInlineIndexedOp(flow_graph, call, array_cid, &array, index, |
2252 &cursor); | 2257 &cursor); |
2253 | 2258 |
2254 intptr_t deopt_id = Thread::kNoDeoptId; | 2259 intptr_t deopt_id = Thread::kNoDeoptId; |
2255 if ((array_cid == kTypedDataInt32ArrayCid) || | 2260 if ((array_cid == kTypedDataInt32ArrayCid) || |
2256 (array_cid == kTypedDataUint32ArrayCid)) { | 2261 (array_cid == kTypedDataUint32ArrayCid)) { |
2257 // Deoptimization may be needed if result does not always fit in a Smi. | 2262 // Deoptimization may be needed if result does not always fit in a Smi. |
(...skipping 27 matching lines...) Expand all Loading... | |
2285 TokenPosition token_pos, | 2290 TokenPosition token_pos, |
2286 const Cids* value_check, | 2291 const Cids* value_check, |
2287 TargetEntryInstr** entry, | 2292 TargetEntryInstr** entry, |
2288 Definition** last) { | 2293 Definition** last) { |
2289 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); | 2294 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); |
2290 | 2295 |
2291 Definition* array = receiver; | 2296 Definition* array = receiver; |
2292 Definition* index = call->ArgumentAt(1); | 2297 Definition* index = call->ArgumentAt(1); |
2293 Definition* stored_value = call->ArgumentAt(2); | 2298 Definition* stored_value = call->ArgumentAt(2); |
2294 | 2299 |
2295 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2300 *entry = new (Z) |
2296 call->GetBlock()->try_index()); | 2301 TargetEntryInstr(flow_graph->allocate_block_id(), |
2302 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2297 (*entry)->InheritDeoptTarget(Z, call); | 2303 (*entry)->InheritDeoptTarget(Z, call); |
2298 Instruction* cursor = *entry; | 2304 Instruction* cursor = *entry; |
2299 if (flow_graph->isolate()->type_checks()) { | 2305 if (flow_graph->isolate()->type_checks()) { |
2300 // Only type check for the value. A type check for the index is not | 2306 // Only type check for the value. A type check for the index is not |
2301 // needed here because we insert a deoptimizing smi-check for the case | 2307 // needed here because we insert a deoptimizing smi-check for the case |
2302 // the index is not a smi. | 2308 // the index is not a smi. |
2303 const AbstractType& value_type = | 2309 const AbstractType& value_type = |
2304 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); | 2310 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); |
2305 Definition* type_args = NULL; | 2311 Definition* type_args = NULL; |
2306 switch (array_cid) { | 2312 switch (array_cid) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2422 Instruction* call, | 2428 Instruction* call, |
2423 Definition* receiver, | 2429 Definition* receiver, |
2424 TargetEntryInstr** entry, | 2430 TargetEntryInstr** entry, |
2425 Definition** last) { | 2431 Definition** last) { |
2426 if (!CanUnboxDouble()) { | 2432 if (!CanUnboxDouble()) { |
2427 return false; | 2433 return false; |
2428 } | 2434 } |
2429 Definition* left = receiver; | 2435 Definition* left = receiver; |
2430 Definition* right = call->ArgumentAt(1); | 2436 Definition* right = call->ArgumentAt(1); |
2431 | 2437 |
2432 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2438 *entry = new (Z) |
2433 call->GetBlock()->try_index()); | 2439 TargetEntryInstr(flow_graph->allocate_block_id(), |
2440 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2434 (*entry)->InheritDeoptTarget(Z, call); | 2441 (*entry)->InheritDeoptTarget(Z, call); |
2435 // Arguments are checked. No need for class check. | 2442 // Arguments are checked. No need for class check. |
2436 BinaryDoubleOpInstr* double_bin_op = new (Z) | 2443 BinaryDoubleOpInstr* double_bin_op = new (Z) |
2437 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), | 2444 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), |
2438 call->deopt_id(), call->token_pos()); | 2445 call->deopt_id(), call->token_pos()); |
2439 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); | 2446 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); |
2440 *last = double_bin_op; | 2447 *last = double_bin_op; |
2441 | 2448 |
2442 return true; | 2449 return true; |
2443 } | 2450 } |
2444 | 2451 |
2445 | 2452 |
2446 static bool InlineDoubleTestOp(FlowGraph* flow_graph, | 2453 static bool InlineDoubleTestOp(FlowGraph* flow_graph, |
2447 Instruction* call, | 2454 Instruction* call, |
2448 Definition* receiver, | 2455 Definition* receiver, |
2449 MethodRecognizer::Kind kind, | 2456 MethodRecognizer::Kind kind, |
2450 TargetEntryInstr** entry, | 2457 TargetEntryInstr** entry, |
2451 Definition** last) { | 2458 Definition** last) { |
2452 if (!CanUnboxDouble()) { | 2459 if (!CanUnboxDouble()) { |
2453 return false; | 2460 return false; |
2454 } | 2461 } |
2455 | 2462 |
2456 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2463 *entry = new (Z) |
2457 call->GetBlock()->try_index()); | 2464 TargetEntryInstr(flow_graph->allocate_block_id(), |
2465 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2458 (*entry)->InheritDeoptTarget(Z, call); | 2466 (*entry)->InheritDeoptTarget(Z, call); |
2459 // Arguments are checked. No need for class check. | 2467 // Arguments are checked. No need for class check. |
2460 | 2468 |
2461 DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr( | 2469 DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr( |
2462 kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos()); | 2470 kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos()); |
2463 flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue); | 2471 flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue); |
2464 *last = double_test_op; | 2472 *last = double_test_op; |
2465 | 2473 |
2466 return true; | 2474 return true; |
2467 } | 2475 } |
2468 | 2476 |
2469 | 2477 |
2470 static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph, | 2478 static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph, |
2471 Instruction* call, | 2479 Instruction* call, |
2472 Definition* receiver, | 2480 Definition* receiver, |
2473 TargetEntryInstr** entry, | 2481 TargetEntryInstr** entry, |
2474 Definition** last) { | 2482 Definition** last) { |
2475 Definition* left = receiver; | 2483 Definition* left = receiver; |
2476 Definition* right = call->ArgumentAt(1); | 2484 Definition* right = call->ArgumentAt(1); |
2477 | 2485 |
2478 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2486 *entry = new (Z) |
2479 call->GetBlock()->try_index()); | 2487 TargetEntryInstr(flow_graph->allocate_block_id(), |
2488 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2480 (*entry)->InheritDeoptTarget(Z, call); | 2489 (*entry)->InheritDeoptTarget(Z, call); |
2481 // Right arguments is known to be smi: other._bitAndFromSmi(this); | 2490 // Right arguments is known to be smi: other._bitAndFromSmi(this); |
2482 BinarySmiOpInstr* smi_op = | 2491 BinarySmiOpInstr* smi_op = |
2483 new (Z) BinarySmiOpInstr(Token::kBIT_AND, new (Z) Value(left), | 2492 new (Z) BinarySmiOpInstr(Token::kBIT_AND, new (Z) Value(left), |
2484 new (Z) Value(right), call->deopt_id()); | 2493 new (Z) Value(right), call->deopt_id()); |
2485 flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue); | 2494 flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue); |
2486 *last = smi_op; | 2495 *last = smi_op; |
2487 | 2496 |
2488 return true; | 2497 return true; |
2489 } | 2498 } |
2490 | 2499 |
2491 | 2500 |
2492 static bool InlineGrowableArraySetter(FlowGraph* flow_graph, | 2501 static bool InlineGrowableArraySetter(FlowGraph* flow_graph, |
2493 intptr_t offset, | 2502 intptr_t offset, |
2494 StoreBarrierType store_barrier_type, | 2503 StoreBarrierType store_barrier_type, |
2495 Instruction* call, | 2504 Instruction* call, |
2496 Definition* receiver, | 2505 Definition* receiver, |
2497 TargetEntryInstr** entry, | 2506 TargetEntryInstr** entry, |
2498 Definition** last) { | 2507 Definition** last) { |
2499 Definition* array = receiver; | 2508 Definition* array = receiver; |
2500 Definition* value = call->ArgumentAt(1); | 2509 Definition* value = call->ArgumentAt(1); |
2501 | 2510 |
2502 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2511 *entry = new (Z) |
2503 call->GetBlock()->try_index()); | 2512 TargetEntryInstr(flow_graph->allocate_block_id(), |
2513 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2504 (*entry)->InheritDeoptTarget(Z, call); | 2514 (*entry)->InheritDeoptTarget(Z, call); |
2505 | 2515 |
2506 // This is an internal method, no need to check argument types. | 2516 // This is an internal method, no need to check argument types. |
2507 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr( | 2517 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr( |
2508 offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type, | 2518 offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type, |
2509 call->token_pos()); | 2519 call->token_pos()); |
2510 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); | 2520 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); |
2511 *last = store; | 2521 *last = store; |
2512 | 2522 |
2513 return true; | 2523 return true; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2578 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, | 2588 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, |
2579 Instruction* call, | 2589 Instruction* call, |
2580 Definition* receiver, | 2590 Definition* receiver, |
2581 intptr_t array_cid, | 2591 intptr_t array_cid, |
2582 intptr_t view_cid, | 2592 intptr_t view_cid, |
2583 TargetEntryInstr** entry, | 2593 TargetEntryInstr** entry, |
2584 Definition** last) { | 2594 Definition** last) { |
2585 ASSERT(array_cid != kIllegalCid); | 2595 ASSERT(array_cid != kIllegalCid); |
2586 Definition* array = receiver; | 2596 Definition* array = receiver; |
2587 Definition* index = call->ArgumentAt(1); | 2597 Definition* index = call->ArgumentAt(1); |
2588 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2598 *entry = new (Z) |
2589 call->GetBlock()->try_index()); | 2599 TargetEntryInstr(flow_graph->allocate_block_id(), |
2600 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2590 (*entry)->InheritDeoptTarget(Z, call); | 2601 (*entry)->InheritDeoptTarget(Z, call); |
2591 Instruction* cursor = *entry; | 2602 Instruction* cursor = *entry; |
2592 | 2603 |
2593 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, | 2604 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, |
2594 index, &cursor); | 2605 index, &cursor); |
2595 | 2606 |
2596 intptr_t deopt_id = Thread::kNoDeoptId; | 2607 intptr_t deopt_id = Thread::kNoDeoptId; |
2597 if ((array_cid == kTypedDataInt32ArrayCid) || | 2608 if ((array_cid == kTypedDataInt32ArrayCid) || |
2598 (array_cid == kTypedDataUint32ArrayCid)) { | 2609 (array_cid == kTypedDataUint32ArrayCid)) { |
2599 // Deoptimization may be needed if result does not always fit in a Smi. | 2610 // Deoptimization may be needed if result does not always fit in a Smi. |
(...skipping 21 matching lines...) Expand all Loading... | |
2621 const Function& target, | 2632 const Function& target, |
2622 Instruction* call, | 2633 Instruction* call, |
2623 Definition* receiver, | 2634 Definition* receiver, |
2624 intptr_t array_cid, | 2635 intptr_t array_cid, |
2625 intptr_t view_cid, | 2636 intptr_t view_cid, |
2626 TargetEntryInstr** entry, | 2637 TargetEntryInstr** entry, |
2627 Definition** last) { | 2638 Definition** last) { |
2628 ASSERT(array_cid != kIllegalCid); | 2639 ASSERT(array_cid != kIllegalCid); |
2629 Definition* array = receiver; | 2640 Definition* array = receiver; |
2630 Definition* index = call->ArgumentAt(1); | 2641 Definition* index = call->ArgumentAt(1); |
2631 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2642 *entry = new (Z) |
2632 call->GetBlock()->try_index()); | 2643 TargetEntryInstr(flow_graph->allocate_block_id(), |
2644 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2633 (*entry)->InheritDeoptTarget(Z, call); | 2645 (*entry)->InheritDeoptTarget(Z, call); |
2634 Instruction* cursor = *entry; | 2646 Instruction* cursor = *entry; |
2635 | 2647 |
2636 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, | 2648 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, |
2637 index, &cursor); | 2649 index, &cursor); |
2638 | 2650 |
2639 // Extract the instance call so we can use the function_name in the stored | 2651 // Extract the instance call so we can use the function_name in the stored |
2640 // value check ICData. | 2652 // value check ICData. |
2641 InstanceCallInstr* i_call = NULL; | 2653 InstanceCallInstr* i_call = NULL; |
2642 if (call->IsPolymorphicInstanceCall()) { | 2654 if (call->IsPolymorphicInstanceCall()) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2787 Definition* receiver, | 2799 Definition* receiver, |
2788 intptr_t cid, | 2800 intptr_t cid, |
2789 TargetEntryInstr** entry, | 2801 TargetEntryInstr** entry, |
2790 Definition** last) { | 2802 Definition** last) { |
2791 if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) { | 2803 if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) { |
2792 return false; | 2804 return false; |
2793 } | 2805 } |
2794 Definition* str = receiver; | 2806 Definition* str = receiver; |
2795 Definition* index = call->ArgumentAt(1); | 2807 Definition* index = call->ArgumentAt(1); |
2796 | 2808 |
2797 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2809 *entry = new (Z) |
2798 call->GetBlock()->try_index()); | 2810 TargetEntryInstr(flow_graph->allocate_block_id(), |
2811 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2799 (*entry)->InheritDeoptTarget(Z, call); | 2812 (*entry)->InheritDeoptTarget(Z, call); |
2800 | 2813 |
2801 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); | 2814 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); |
2802 | 2815 |
2803 OneByteStringFromCharCodeInstr* char_at = | 2816 OneByteStringFromCharCodeInstr* char_at = |
2804 new (Z) OneByteStringFromCharCodeInstr(new (Z) Value(*last)); | 2817 new (Z) OneByteStringFromCharCodeInstr(new (Z) Value(*last)); |
2805 | 2818 |
2806 flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue); | 2819 flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
2807 *last = char_at; | 2820 *last = char_at; |
2808 | 2821 |
2809 return true; | 2822 return true; |
2810 } | 2823 } |
2811 | 2824 |
2812 | 2825 |
2813 static bool InlineStringCodeUnitAt(FlowGraph* flow_graph, | 2826 static bool InlineStringCodeUnitAt(FlowGraph* flow_graph, |
2814 Instruction* call, | 2827 Instruction* call, |
2815 Definition* receiver, | 2828 Definition* receiver, |
2816 intptr_t cid, | 2829 intptr_t cid, |
2817 TargetEntryInstr** entry, | 2830 TargetEntryInstr** entry, |
2818 Definition** last) { | 2831 Definition** last) { |
2819 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 2832 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
2820 (cid == kExternalOneByteStringCid) || | 2833 (cid == kExternalOneByteStringCid) || |
2821 (cid == kExternalTwoByteStringCid)); | 2834 (cid == kExternalTwoByteStringCid)); |
2822 Definition* str = receiver; | 2835 Definition* str = receiver; |
2823 Definition* index = call->ArgumentAt(1); | 2836 Definition* index = call->ArgumentAt(1); |
2824 | 2837 |
2825 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2838 *entry = new (Z) |
2826 call->GetBlock()->try_index()); | 2839 TargetEntryInstr(flow_graph->allocate_block_id(), |
2840 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2827 (*entry)->InheritDeoptTarget(Z, call); | 2841 (*entry)->InheritDeoptTarget(Z, call); |
2828 | 2842 |
2829 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); | 2843 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); |
2830 | 2844 |
2831 return true; | 2845 return true; |
2832 } | 2846 } |
2833 | 2847 |
2834 | 2848 |
2835 // Only used for monomorphic calls. | 2849 // Only used for monomorphic calls. |
2836 bool FlowGraphInliner::TryReplaceInstanceCallWithInline( | 2850 bool FlowGraphInliner::TryReplaceInstanceCallWithInline( |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2928 static bool InlineFloat32x4Method(FlowGraph* flow_graph, | 2942 static bool InlineFloat32x4Method(FlowGraph* flow_graph, |
2929 Instruction* call, | 2943 Instruction* call, |
2930 Definition* receiver, | 2944 Definition* receiver, |
2931 MethodRecognizer::Kind kind, | 2945 MethodRecognizer::Kind kind, |
2932 TargetEntryInstr** entry, | 2946 TargetEntryInstr** entry, |
2933 Definition** last) { | 2947 Definition** last) { |
2934 if (!ShouldInlineSimd()) { | 2948 if (!ShouldInlineSimd()) { |
2935 return false; | 2949 return false; |
2936 } | 2950 } |
2937 | 2951 |
2938 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2952 *entry = new (Z) |
2939 call->GetBlock()->try_index()); | 2953 TargetEntryInstr(flow_graph->allocate_block_id(), |
2954 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
2940 (*entry)->InheritDeoptTarget(Z, call); | 2955 (*entry)->InheritDeoptTarget(Z, call); |
2941 Instruction* cursor = *entry; | 2956 Instruction* cursor = *entry; |
2942 switch (kind) { | 2957 switch (kind) { |
2943 case MethodRecognizer::kFloat32x4ShuffleX: | 2958 case MethodRecognizer::kFloat32x4ShuffleX: |
2944 case MethodRecognizer::kFloat32x4ShuffleY: | 2959 case MethodRecognizer::kFloat32x4ShuffleY: |
2945 case MethodRecognizer::kFloat32x4ShuffleZ: | 2960 case MethodRecognizer::kFloat32x4ShuffleZ: |
2946 case MethodRecognizer::kFloat32x4ShuffleW: { | 2961 case MethodRecognizer::kFloat32x4ShuffleW: { |
2947 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(receiver), | 2962 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(receiver), |
2948 0, // mask ignored. | 2963 0, // mask ignored. |
2949 call->deopt_id()); | 2964 call->deopt_id()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3046 | 3061 |
3047 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph, | 3062 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph, |
3048 Instruction* call, | 3063 Instruction* call, |
3049 Definition* receiver, | 3064 Definition* receiver, |
3050 MethodRecognizer::Kind kind, | 3065 MethodRecognizer::Kind kind, |
3051 TargetEntryInstr** entry, | 3066 TargetEntryInstr** entry, |
3052 Definition** last) { | 3067 Definition** last) { |
3053 if (!ShouldInlineSimd()) { | 3068 if (!ShouldInlineSimd()) { |
3054 return false; | 3069 return false; |
3055 } | 3070 } |
3056 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3071 *entry = new (Z) |
3057 call->GetBlock()->try_index()); | 3072 TargetEntryInstr(flow_graph->allocate_block_id(), |
3073 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3058 (*entry)->InheritDeoptTarget(Z, call); | 3074 (*entry)->InheritDeoptTarget(Z, call); |
3059 Instruction* cursor = *entry; | 3075 Instruction* cursor = *entry; |
3060 Definition* mask_definition = call->ArgumentAt(1); | 3076 Definition* mask_definition = call->ArgumentAt(1); |
3061 intptr_t mask = 0; | 3077 intptr_t mask = 0; |
3062 if (!CheckMask(mask_definition, &mask)) { | 3078 if (!CheckMask(mask_definition, &mask)) { |
3063 return false; | 3079 return false; |
3064 } | 3080 } |
3065 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(call->ArgumentAt(0)), | 3081 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(call->ArgumentAt(0)), |
3066 mask, call->deopt_id()); | 3082 mask, call->deopt_id()); |
3067 flow_graph->AppendTo( | 3083 flow_graph->AppendTo( |
3068 cursor, *last, | 3084 cursor, *last, |
3069 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3085 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3070 FlowGraph::kValue); | 3086 FlowGraph::kValue); |
3071 return true; | 3087 return true; |
3072 } | 3088 } |
3073 | 3089 |
3074 | 3090 |
3075 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph, | 3091 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph, |
3076 Instruction* call, | 3092 Instruction* call, |
3077 Definition* receiver, | 3093 Definition* receiver, |
3078 MethodRecognizer::Kind kind, | 3094 MethodRecognizer::Kind kind, |
3079 TargetEntryInstr** entry, | 3095 TargetEntryInstr** entry, |
3080 Definition** last) { | 3096 Definition** last) { |
3081 if (!ShouldInlineSimd()) { | 3097 if (!ShouldInlineSimd()) { |
3082 return false; | 3098 return false; |
3083 } | 3099 } |
3084 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3100 *entry = new (Z) |
3085 call->GetBlock()->try_index()); | 3101 TargetEntryInstr(flow_graph->allocate_block_id(), |
3102 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3086 (*entry)->InheritDeoptTarget(Z, call); | 3103 (*entry)->InheritDeoptTarget(Z, call); |
3087 Instruction* cursor = *entry; | 3104 Instruction* cursor = *entry; |
3088 Definition* mask_definition = call->ArgumentAt(2); | 3105 Definition* mask_definition = call->ArgumentAt(2); |
3089 intptr_t mask = 0; | 3106 intptr_t mask = 0; |
3090 if (!CheckMask(mask_definition, &mask)) { | 3107 if (!CheckMask(mask_definition, &mask)) { |
3091 return false; | 3108 return false; |
3092 } | 3109 } |
3093 *last = new (Z) Simd32x4ShuffleMixInstr(kind, new (Z) Value(receiver), | 3110 *last = new (Z) Simd32x4ShuffleMixInstr(kind, new (Z) Value(receiver), |
3094 new (Z) Value(call->ArgumentAt(1)), | 3111 new (Z) Value(call->ArgumentAt(1)), |
3095 mask, call->deopt_id()); | 3112 mask, call->deopt_id()); |
3096 flow_graph->AppendTo( | 3113 flow_graph->AppendTo( |
3097 cursor, *last, | 3114 cursor, *last, |
3098 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3115 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3099 FlowGraph::kValue); | 3116 FlowGraph::kValue); |
3100 return true; | 3117 return true; |
3101 } | 3118 } |
3102 | 3119 |
3103 | 3120 |
3104 static bool InlineInt32x4Method(FlowGraph* flow_graph, | 3121 static bool InlineInt32x4Method(FlowGraph* flow_graph, |
3105 Instruction* call, | 3122 Instruction* call, |
3106 Definition* receiver, | 3123 Definition* receiver, |
3107 MethodRecognizer::Kind kind, | 3124 MethodRecognizer::Kind kind, |
3108 TargetEntryInstr** entry, | 3125 TargetEntryInstr** entry, |
3109 Definition** last) { | 3126 Definition** last) { |
3110 if (!ShouldInlineSimd()) { | 3127 if (!ShouldInlineSimd()) { |
3111 return false; | 3128 return false; |
3112 } | 3129 } |
3113 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3130 *entry = new (Z) |
3114 call->GetBlock()->try_index()); | 3131 TargetEntryInstr(flow_graph->allocate_block_id(), |
3132 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3115 (*entry)->InheritDeoptTarget(Z, call); | 3133 (*entry)->InheritDeoptTarget(Z, call); |
3116 Instruction* cursor = *entry; | 3134 Instruction* cursor = *entry; |
3117 switch (kind) { | 3135 switch (kind) { |
3118 case MethodRecognizer::kInt32x4GetFlagX: | 3136 case MethodRecognizer::kInt32x4GetFlagX: |
3119 case MethodRecognizer::kInt32x4GetFlagY: | 3137 case MethodRecognizer::kInt32x4GetFlagY: |
3120 case MethodRecognizer::kInt32x4GetFlagZ: | 3138 case MethodRecognizer::kInt32x4GetFlagZ: |
3121 case MethodRecognizer::kInt32x4GetFlagW: { | 3139 case MethodRecognizer::kInt32x4GetFlagW: { |
3122 *last = new (Z) | 3140 *last = new (Z) |
3123 Int32x4GetFlagInstr(kind, new (Z) Value(receiver), call->deopt_id()); | 3141 Int32x4GetFlagInstr(kind, new (Z) Value(receiver), call->deopt_id()); |
3124 break; | 3142 break; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3159 | 3177 |
3160 static bool InlineFloat64x2Method(FlowGraph* flow_graph, | 3178 static bool InlineFloat64x2Method(FlowGraph* flow_graph, |
3161 Instruction* call, | 3179 Instruction* call, |
3162 Definition* receiver, | 3180 Definition* receiver, |
3163 MethodRecognizer::Kind kind, | 3181 MethodRecognizer::Kind kind, |
3164 TargetEntryInstr** entry, | 3182 TargetEntryInstr** entry, |
3165 Definition** last) { | 3183 Definition** last) { |
3166 if (!ShouldInlineSimd()) { | 3184 if (!ShouldInlineSimd()) { |
3167 return false; | 3185 return false; |
3168 } | 3186 } |
3169 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3187 *entry = new (Z) |
3170 call->GetBlock()->try_index()); | 3188 TargetEntryInstr(flow_graph->allocate_block_id(), |
3189 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3171 (*entry)->InheritDeoptTarget(Z, call); | 3190 (*entry)->InheritDeoptTarget(Z, call); |
3172 Instruction* cursor = *entry; | 3191 Instruction* cursor = *entry; |
3173 switch (kind) { | 3192 switch (kind) { |
3174 case MethodRecognizer::kFloat64x2GetX: | 3193 case MethodRecognizer::kFloat64x2GetX: |
3175 case MethodRecognizer::kFloat64x2GetY: { | 3194 case MethodRecognizer::kFloat64x2GetY: { |
3176 *last = new (Z) Simd64x2ShuffleInstr(kind, new (Z) Value(receiver), | 3195 *last = new (Z) Simd64x2ShuffleInstr(kind, new (Z) Value(receiver), |
3177 0, // mask is ignored. | 3196 0, // mask is ignored. |
3178 call->deopt_id()); | 3197 call->deopt_id()); |
3179 break; | 3198 break; |
3180 } | 3199 } |
(...skipping 29 matching lines...) Expand all Loading... | |
3210 | 3229 |
3211 | 3230 |
3212 static bool InlineSimdConstructor(FlowGraph* flow_graph, | 3231 static bool InlineSimdConstructor(FlowGraph* flow_graph, |
3213 Instruction* call, | 3232 Instruction* call, |
3214 MethodRecognizer::Kind kind, | 3233 MethodRecognizer::Kind kind, |
3215 TargetEntryInstr** entry, | 3234 TargetEntryInstr** entry, |
3216 Definition** last) { | 3235 Definition** last) { |
3217 if (!ShouldInlineSimd()) { | 3236 if (!ShouldInlineSimd()) { |
3218 return false; | 3237 return false; |
3219 } | 3238 } |
3220 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3239 *entry = new (Z) |
3221 call->GetBlock()->try_index()); | 3240 TargetEntryInstr(flow_graph->allocate_block_id(), |
3241 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3222 (*entry)->InheritDeoptTarget(Z, call); | 3242 (*entry)->InheritDeoptTarget(Z, call); |
3223 Instruction* cursor = *entry; | 3243 Instruction* cursor = *entry; |
3224 switch (kind) { | 3244 switch (kind) { |
3225 case MethodRecognizer::kFloat32x4Zero: | 3245 case MethodRecognizer::kFloat32x4Zero: |
3226 *last = new (Z) Float32x4ZeroInstr(); | 3246 *last = new (Z) Float32x4ZeroInstr(); |
3227 break; | 3247 break; |
3228 case MethodRecognizer::kFloat32x4Splat: | 3248 case MethodRecognizer::kFloat32x4Splat: |
3229 *last = new (Z) Float32x4SplatInstr(new (Z) Value(call->ArgumentAt(1)), | 3249 *last = new (Z) Float32x4SplatInstr(new (Z) Value(call->ArgumentAt(1)), |
3230 call->deopt_id()); | 3250 call->deopt_id()); |
3231 break; | 3251 break; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3291 | 3311 |
3292 | 3312 |
3293 static bool InlineMathCFunction(FlowGraph* flow_graph, | 3313 static bool InlineMathCFunction(FlowGraph* flow_graph, |
3294 Instruction* call, | 3314 Instruction* call, |
3295 MethodRecognizer::Kind kind, | 3315 MethodRecognizer::Kind kind, |
3296 TargetEntryInstr** entry, | 3316 TargetEntryInstr** entry, |
3297 Definition** last) { | 3317 Definition** last) { |
3298 if (!CanUnboxDouble()) { | 3318 if (!CanUnboxDouble()) { |
3299 return false; | 3319 return false; |
3300 } | 3320 } |
3301 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3321 *entry = new (Z) |
3302 call->GetBlock()->try_index()); | 3322 TargetEntryInstr(flow_graph->allocate_block_id(), |
3323 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3303 (*entry)->InheritDeoptTarget(Z, call); | 3324 (*entry)->InheritDeoptTarget(Z, call); |
3304 Instruction* cursor = *entry; | 3325 Instruction* cursor = *entry; |
3305 | 3326 |
3306 switch (kind) { | 3327 switch (kind) { |
3307 case MethodRecognizer::kMathSqrt: { | 3328 case MethodRecognizer::kMathSqrt: { |
3308 *last = new (Z) | 3329 *last = new (Z) |
3309 MathUnaryInstr(MathUnaryInstr::kSqrt, | 3330 MathUnaryInstr(MathUnaryInstr::kSqrt, |
3310 new (Z) Value(call->ArgumentAt(0)), call->deopt_id()); | 3331 new (Z) Value(call->ArgumentAt(0)), call->deopt_id()); |
3311 break; | 3332 break; |
3312 } | 3333 } |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3653 case MethodRecognizer::kMathSin: | 3674 case MethodRecognizer::kMathSin: |
3654 case MethodRecognizer::kMathCos: | 3675 case MethodRecognizer::kMathCos: |
3655 case MethodRecognizer::kMathTan: | 3676 case MethodRecognizer::kMathTan: |
3656 case MethodRecognizer::kMathAsin: | 3677 case MethodRecognizer::kMathAsin: |
3657 case MethodRecognizer::kMathAcos: | 3678 case MethodRecognizer::kMathAcos: |
3658 case MethodRecognizer::kMathAtan: | 3679 case MethodRecognizer::kMathAtan: |
3659 case MethodRecognizer::kMathAtan2: | 3680 case MethodRecognizer::kMathAtan2: |
3660 return InlineMathCFunction(flow_graph, call, kind, entry, last); | 3681 return InlineMathCFunction(flow_graph, call, kind, entry, last); |
3661 | 3682 |
3662 case MethodRecognizer::kObjectConstructor: { | 3683 case MethodRecognizer::kObjectConstructor: { |
3663 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3684 *entry = new (Z) |
3664 call->GetBlock()->try_index()); | 3685 TargetEntryInstr(flow_graph->allocate_block_id(), |
3686 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3665 (*entry)->InheritDeoptTarget(Z, call); | 3687 (*entry)->InheritDeoptTarget(Z, call); |
3666 ASSERT(!call->HasUses()); | 3688 ASSERT(!call->HasUses()); |
3667 *last = NULL; // Empty body. | 3689 *last = NULL; // Empty body. |
3668 return true; | 3690 return true; |
3669 } | 3691 } |
3670 | 3692 |
3671 case MethodRecognizer::kObjectArrayAllocate: { | 3693 case MethodRecognizer::kObjectArrayAllocate: { |
3672 Value* num_elements = new (Z) Value(call->ArgumentAt(1)); | 3694 Value* num_elements = new (Z) Value(call->ArgumentAt(1)); |
3673 if (num_elements->BindsToConstant() && | 3695 if (num_elements->BindsToConstant() && |
3674 num_elements->BoundConstant().IsSmi()) { | 3696 num_elements->BoundConstant().IsSmi()) { |
3675 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 3697 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
3676 if (length >= 0 && length <= Array::kMaxElements) { | 3698 if (length >= 0 && length <= Array::kMaxElements) { |
3677 Value* type = new (Z) Value(call->ArgumentAt(0)); | 3699 Value* type = new (Z) Value(call->ArgumentAt(0)); |
3678 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3700 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
3679 call->GetBlock()->try_index()); | 3701 call->GetBlock()->try_index(), |
3702 Thread::kNoDeoptId); | |
3680 (*entry)->InheritDeoptTarget(Z, call); | 3703 (*entry)->InheritDeoptTarget(Z, call); |
3681 *last = | 3704 *last = new (Z) CreateArrayInstr(call->token_pos(), type, |
rmacnak
2017/05/24 22:59:34
Actually it looks like we've just been neglecting
Vyacheslav Egorov (Google)
2017/05/25 08:44:04
Good catch! Sorry I missed it in the original revi
| |
3682 new (Z) CreateArrayInstr(call->token_pos(), type, num_elements); | 3705 num_elements, call->deopt_id()); |
3683 flow_graph->AppendTo( | 3706 flow_graph->AppendTo( |
3684 *entry, *last, | 3707 *entry, *last, |
3685 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3708 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3686 FlowGraph::kValue); | 3709 FlowGraph::kValue); |
3687 return true; | 3710 return true; |
3688 } | 3711 } |
3689 } | 3712 } |
3690 return false; | 3713 return false; |
3691 } | 3714 } |
3692 | 3715 |
3693 case MethodRecognizer::kObjectRuntimeType: { | 3716 case MethodRecognizer::kObjectRuntimeType: { |
3694 Type& type = Type::ZoneHandle(Z); | 3717 Type& type = Type::ZoneHandle(Z); |
3695 if (RawObject::IsStringClassId(receiver_cid)) { | 3718 if (RawObject::IsStringClassId(receiver_cid)) { |
3696 type = Type::StringType(); | 3719 type = Type::StringType(); |
3697 } else if (receiver_cid == kDoubleCid) { | 3720 } else if (receiver_cid == kDoubleCid) { |
3698 type = Type::Double(); | 3721 type = Type::Double(); |
3699 } else if (RawObject::IsIntegerClassId(receiver_cid)) { | 3722 } else if (RawObject::IsIntegerClassId(receiver_cid)) { |
3700 type = Type::IntType(); | 3723 type = Type::IntType(); |
3701 } else if (receiver_cid != kClosureCid) { | 3724 } else if (receiver_cid != kClosureCid) { |
3702 const Class& cls = Class::Handle( | 3725 const Class& cls = Class::Handle( |
3703 Z, flow_graph->isolate()->class_table()->At(receiver_cid)); | 3726 Z, flow_graph->isolate()->class_table()->At(receiver_cid)); |
3704 if (!cls.IsGeneric()) { | 3727 if (!cls.IsGeneric()) { |
3705 type = cls.CanonicalType(); | 3728 type = cls.CanonicalType(); |
3706 } | 3729 } |
3707 } | 3730 } |
3708 | 3731 |
3709 if (!type.IsNull()) { | 3732 if (!type.IsNull()) { |
3710 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3733 *entry = new (Z) |
3711 call->GetBlock()->try_index()); | 3734 TargetEntryInstr(flow_graph->allocate_block_id(), |
3735 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3712 (*entry)->InheritDeoptTarget(Z, call); | 3736 (*entry)->InheritDeoptTarget(Z, call); |
3713 *last = new (Z) ConstantInstr(type); | 3737 *last = new (Z) ConstantInstr(type); |
3714 flow_graph->AppendTo( | 3738 flow_graph->AppendTo( |
3715 *entry, *last, | 3739 *entry, *last, |
3716 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3740 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3717 FlowGraph::kValue); | 3741 FlowGraph::kValue); |
3718 return true; | 3742 return true; |
3719 } | 3743 } |
3720 return false; | 3744 return false; |
3721 } | 3745 } |
3722 | 3746 |
3723 case MethodRecognizer::kOneByteStringSetAt: { | 3747 case MethodRecognizer::kOneByteStringSetAt: { |
3724 // This is an internal method, no need to check argument types nor | 3748 // This is an internal method, no need to check argument types nor |
3725 // range. | 3749 // range. |
3726 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3750 *entry = new (Z) |
3727 call->GetBlock()->try_index()); | 3751 TargetEntryInstr(flow_graph->allocate_block_id(), |
3752 call->GetBlock()->try_index(), Thread::kNoDeoptId); | |
3728 (*entry)->InheritDeoptTarget(Z, call); | 3753 (*entry)->InheritDeoptTarget(Z, call); |
3729 Definition* str = call->ArgumentAt(0); | 3754 Definition* str = call->ArgumentAt(0); |
3730 Definition* index = call->ArgumentAt(1); | 3755 Definition* index = call->ArgumentAt(1); |
3731 Definition* value = call->ArgumentAt(2); | 3756 Definition* value = call->ArgumentAt(2); |
3732 *last = | 3757 *last = |
3733 new (Z) StoreIndexedInstr(new (Z) Value(str), new (Z) Value(index), | 3758 new (Z) StoreIndexedInstr(new (Z) Value(str), new (Z) Value(index), |
3734 new (Z) Value(value), kNoStoreBarrier, | 3759 new (Z) Value(value), kNoStoreBarrier, |
3735 1, // Index scale | 3760 1, // Index scale |
3736 kOneByteStringCid, kAlignedAccess, | 3761 kOneByteStringCid, kAlignedAccess, |
3737 call->deopt_id(), call->token_pos()); | 3762 call->deopt_id(), call->token_pos()); |
3738 flow_graph->AppendTo( | 3763 flow_graph->AppendTo( |
3739 *entry, *last, | 3764 *entry, *last, |
3740 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3765 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3741 FlowGraph::kEffect); | 3766 FlowGraph::kEffect); |
3742 return true; | 3767 return true; |
3743 } | 3768 } |
3744 | 3769 |
3745 default: | 3770 default: |
3746 return false; | 3771 return false; |
3747 } | 3772 } |
3748 } | 3773 } |
3749 | 3774 |
3750 | 3775 |
3751 } // namespace dart | 3776 } // namespace dart |
3752 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 3777 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
OLD | NEW |