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