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 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 inlined_entries_[i]->AsGraphEntry()->UnuseAllInputs(); | 1507 inlined_entries_[i]->AsGraphEntry()->UnuseAllInputs(); |
1508 | 1508 |
1509 JoinEntryInstr* new_join = | 1509 JoinEntryInstr* new_join = |
1510 BranchSimplifier::ToJoinEntry(zone(), old_target); | 1510 BranchSimplifier::ToJoinEntry(zone(), old_target); |
1511 old_target->ReplaceAsPredecessorWith(new_join); | 1511 old_target->ReplaceAsPredecessorWith(new_join); |
1512 for (intptr_t j = 0; j < old_target->dominated_blocks().length(); ++j) { | 1512 for (intptr_t j = 0; j < old_target->dominated_blocks().length(); ++j) { |
1513 BlockEntryInstr* block = old_target->dominated_blocks()[j]; | 1513 BlockEntryInstr* block = old_target->dominated_blocks()[j]; |
1514 new_join->AddDominatedBlock(block); | 1514 new_join->AddDominatedBlock(block); |
1515 } | 1515 } |
1516 // Create a new target with the join as unconditional successor. | 1516 // Create a new target with the join as unconditional successor. |
1517 TargetEntryInstr* new_target = | 1517 TargetEntryInstr* new_target = new TargetEntryInstr( |
1518 new TargetEntryInstr(AllocateBlockId(), old_target->try_index()); | 1518 AllocateBlockId(), old_target->try_index(), Thread::kNoDeoptId); |
1519 new_target->InheritDeoptTarget(zone(), new_join); | 1519 new_target->InheritDeoptTarget(zone(), new_join); |
1520 GotoInstr* new_goto = new (Z) GotoInstr(new_join); | 1520 GotoInstr* new_goto = new (Z) GotoInstr(new_join, Thread::kNoDeoptId); |
1521 new_goto->InheritDeoptTarget(zone(), new_join); | 1521 new_goto->InheritDeoptTarget(zone(), new_join); |
1522 new_target->LinkTo(new_goto); | 1522 new_target->LinkTo(new_goto); |
1523 new_target->set_last_instruction(new_goto); | 1523 new_target->set_last_instruction(new_goto); |
1524 new_join->predecessors_.Add(new_target); | 1524 new_join->predecessors_.Add(new_target); |
1525 | 1525 |
1526 // Record the new target for the first variant. | 1526 // Record the new target for the first variant. |
1527 inlined_entries_[i] = new_target; | 1527 inlined_entries_[i] = new_target; |
1528 } | 1528 } |
1529 ASSERT(inlined_entries_[i]->IsTargetEntry()); | 1529 ASSERT(inlined_entries_[i]->IsTargetEntry()); |
1530 // Record the shared join for this variant. | 1530 // Record the shared join for this variant. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1649 owner_->caller_graph()->alloc_ssa_temp_index()); | 1649 owner_->caller_graph()->alloc_ssa_temp_index()); |
1650 if (FlowGraphInliner::TryInlineRecognizedMethod( | 1650 if (FlowGraphInliner::TryInlineRecognizedMethod( |
1651 owner_->caller_graph(), receiver_cid, target, call_, redefinition, | 1651 owner_->caller_graph(), receiver_cid, target, call_, redefinition, |
1652 call_->instance_call()->token_pos(), | 1652 call_->instance_call()->token_pos(), |
1653 *call_->instance_call()->ic_data(), &entry, &last)) { | 1653 *call_->instance_call()->ic_data(), &entry, &last)) { |
1654 // Create a graph fragment. | 1654 // Create a graph fragment. |
1655 redefinition->InsertAfter(entry); | 1655 redefinition->InsertAfter(entry); |
1656 InlineExitCollector* exit_collector = | 1656 InlineExitCollector* exit_collector = |
1657 new (Z) InlineExitCollector(owner_->caller_graph(), call_); | 1657 new (Z) InlineExitCollector(owner_->caller_graph(), call_); |
1658 | 1658 |
1659 ReturnInstr* result = new (Z) | 1659 ReturnInstr* result = |
1660 ReturnInstr(call_->instance_call()->token_pos(), new (Z) Value(last)); | 1660 new (Z) ReturnInstr(call_->instance_call()->token_pos(), |
| 1661 new (Z) Value(last), Thread::kNoDeoptId); |
1661 owner_->caller_graph()->AppendTo( | 1662 owner_->caller_graph()->AppendTo( |
1662 last, result, | 1663 last, result, |
1663 call_->env(), // Return can become deoptimization target. | 1664 call_->env(), // Return can become deoptimization target. |
1664 FlowGraph::kEffect); | 1665 FlowGraph::kEffect); |
1665 entry->set_last_instruction(result); | 1666 entry->set_last_instruction(result); |
1666 exit_collector->AddExit(result); | 1667 exit_collector->AddExit(result); |
1667 ParsedFunction* temp_parsed_function = | 1668 ParsedFunction* temp_parsed_function = |
1668 new ParsedFunction(Thread::Current(), target); | 1669 new ParsedFunction(Thread::Current(), target); |
1669 GraphEntryInstr* graph_entry = new (Z) | 1670 GraphEntryInstr* graph_entry = new (Z) |
1670 GraphEntryInstr(*temp_parsed_function, entry, Compiler::kNoOSRDeoptId); | 1671 GraphEntryInstr(*temp_parsed_function, entry, Compiler::kNoOSRDeoptId); |
1671 // Update polymorphic inliner state. | 1672 // Update polymorphic inliner state. |
1672 inlined_entries_.Add(graph_entry); | 1673 inlined_entries_.Add(graph_entry); |
1673 exit_collector_->Union(exit_collector); | 1674 exit_collector_->Union(exit_collector); |
1674 return true; | 1675 return true; |
1675 } | 1676 } |
1676 return false; | 1677 return false; |
1677 } | 1678 } |
1678 | 1679 |
1679 | 1680 |
1680 // Build a DAG to dispatch to the inlined function bodies. Load the class | 1681 // Build a DAG to dispatch to the inlined function bodies. Load the class |
1681 // id of the receiver and make explicit comparisons for each inlined body, | 1682 // id of the receiver and make explicit comparisons for each inlined body, |
1682 // in frequency order. If all variants are inlined, the entry to the last | 1683 // in frequency order. If all variants are inlined, the entry to the last |
1683 // inlined body is guarded by a CheckClassId instruction which can deopt. | 1684 // inlined body is guarded by a CheckClassId instruction which can deopt. |
1684 // If not all variants are inlined, we add a PolymorphicInstanceCall | 1685 // If not all variants are inlined, we add a PolymorphicInstanceCall |
1685 // instruction to handle the non-inlined variants. | 1686 // instruction to handle the non-inlined variants. |
1686 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { | 1687 TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { |
1687 const intptr_t try_idx = call_->GetBlock()->try_index(); | 1688 const intptr_t try_idx = call_->GetBlock()->try_index(); |
1688 | 1689 |
1689 // Start with a fresh target entry. | 1690 // Start with a fresh target entry. |
1690 TargetEntryInstr* entry = | 1691 TargetEntryInstr* entry = new (Z) TargetEntryInstr( |
1691 new (Z) TargetEntryInstr(AllocateBlockId(), try_idx); | 1692 AllocateBlockId(), try_idx, Thread::Current()->GetNextDeoptId()); |
1692 entry->InheritDeoptTarget(zone(), call_); | 1693 entry->InheritDeoptTarget(zone(), call_); |
1693 | 1694 |
1694 // This function uses a cursor (a pointer to the 'current' instruction) to | 1695 // This function uses a cursor (a pointer to the 'current' instruction) to |
1695 // build the graph. The next instruction will be inserted after the | 1696 // build the graph. The next instruction will be inserted after the |
1696 // cursor. | 1697 // cursor. |
1697 BlockEntryInstr* current_block = entry; | 1698 BlockEntryInstr* current_block = entry; |
1698 Instruction* cursor = entry; | 1699 Instruction* cursor = entry; |
1699 | 1700 |
1700 Definition* receiver = call_->ArgumentAt(0); | 1701 Definition* receiver = call_->ArgumentAt(0); |
1701 // There are at least two variants including non-inlined ones, so we have | 1702 // There are at least two variants including non-inlined ones, so we have |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1752 for (intptr_t j = 0; j < target->dominated_blocks().length(); ++j) { | 1753 for (intptr_t j = 0; j < target->dominated_blocks().length(); ++j) { |
1753 BlockEntryInstr* block = target->dominated_blocks()[j]; | 1754 BlockEntryInstr* block = target->dominated_blocks()[j]; |
1754 current_block->AddDominatedBlock(block); | 1755 current_block->AddDominatedBlock(block); |
1755 } | 1756 } |
1756 } else if (callee_entry->IsJoinEntry()) { | 1757 } else if (callee_entry->IsJoinEntry()) { |
1757 // Shared inlined body and this is a subsequent entry. We have | 1758 // Shared inlined body and this is a subsequent entry. We have |
1758 // already constructed a join and set its dominator. Add a jump to | 1759 // already constructed a join and set its dominator. Add a jump to |
1759 // the join. | 1760 // the join. |
1760 JoinEntryInstr* join = callee_entry->AsJoinEntry(); | 1761 JoinEntryInstr* join = callee_entry->AsJoinEntry(); |
1761 ASSERT(join->dominator() != NULL); | 1762 ASSERT(join->dominator() != NULL); |
1762 GotoInstr* goto_join = new GotoInstr(join); | 1763 GotoInstr* goto_join = new GotoInstr(join, Thread::kNoDeoptId); |
1763 goto_join->InheritDeoptTarget(zone(), join); | 1764 goto_join->InheritDeoptTarget(zone(), join); |
1764 cursor->LinkTo(goto_join); | 1765 cursor->LinkTo(goto_join); |
1765 current_block->set_last_instruction(goto_join); | 1766 current_block->set_last_instruction(goto_join); |
1766 } else { | 1767 } else { |
1767 // There is no possibility of a TargetEntry (the first entry to a | 1768 // There is no possibility of a TargetEntry (the first entry to a |
1768 // shared inlined body) because this is the last inlined entry. | 1769 // shared inlined body) because this is the last inlined entry. |
1769 UNREACHABLE(); | 1770 UNREACHABLE(); |
1770 } | 1771 } |
1771 cursor = NULL; | 1772 cursor = NULL; |
1772 } else { | 1773 } else { |
(...skipping 10 matching lines...) Expand all Loading... |
1783 // special instruction that uses subtraction and unsigned comparison to | 1784 // special instruction that uses subtraction and unsigned comparison to |
1784 // do this with a single branch. | 1785 // do this with a single branch. |
1785 const Smi& cid_end = Smi::ZoneHandle(Smi::New(variant.cid_end)); | 1786 const Smi& cid_end = Smi::ZoneHandle(Smi::New(variant.cid_end)); |
1786 ConstantInstr* cid_constant_end = | 1787 ConstantInstr* cid_constant_end = |
1787 owner_->caller_graph()->GetConstant(cid_end); | 1788 owner_->caller_graph()->GetConstant(cid_end); |
1788 RelationalOpInstr* compare_top = new RelationalOpInstr( | 1789 RelationalOpInstr* compare_top = new RelationalOpInstr( |
1789 call_->instance_call()->token_pos(), Token::kLTE, | 1790 call_->instance_call()->token_pos(), Token::kLTE, |
1790 new Value(load_cid), new Value(cid_constant_end), kSmiCid, | 1791 new Value(load_cid), new Value(cid_constant_end), kSmiCid, |
1791 call_->deopt_id()); | 1792 call_->deopt_id()); |
1792 BranchInstr* branch_top = upper_limit_branch = | 1793 BranchInstr* branch_top = upper_limit_branch = |
1793 new BranchInstr(compare_top); | 1794 new BranchInstr(compare_top, Thread::kNoDeoptId); |
1794 branch_top->InheritDeoptTarget(zone(), call_); | 1795 branch_top->InheritDeoptTarget(zone(), call_); |
1795 cursor = AppendInstruction(cursor, branch_top); | 1796 cursor = AppendInstruction(cursor, branch_top); |
1796 current_block->set_last_instruction(branch_top); | 1797 current_block->set_last_instruction(branch_top); |
1797 | 1798 |
1798 TargetEntryInstr* below_target = | 1799 TargetEntryInstr* below_target = new TargetEntryInstr( |
1799 new TargetEntryInstr(AllocateBlockId(), try_idx); | 1800 AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1800 below_target->InheritDeoptTarget(zone(), call_); | 1801 below_target->InheritDeoptTarget(zone(), call_); |
1801 current_block->AddDominatedBlock(below_target); | 1802 current_block->AddDominatedBlock(below_target); |
1802 cursor = current_block = below_target; | 1803 cursor = current_block = below_target; |
1803 *branch_top->true_successor_address() = below_target; | 1804 *branch_top->true_successor_address() = below_target; |
1804 | 1805 |
1805 RelationalOpInstr* compare_bottom = new RelationalOpInstr( | 1806 RelationalOpInstr* compare_bottom = new RelationalOpInstr( |
1806 call_->instance_call()->token_pos(), Token::kGTE, | 1807 call_->instance_call()->token_pos(), Token::kGTE, |
1807 new Value(load_cid), new Value(cid_constant), kSmiCid, | 1808 new Value(load_cid), new Value(cid_constant), kSmiCid, |
1808 call_->deopt_id()); | 1809 call_->deopt_id()); |
1809 branch = new BranchInstr(compare_bottom); | 1810 branch = new BranchInstr(compare_bottom, Thread::kNoDeoptId); |
1810 } else { | 1811 } else { |
1811 StrictCompareInstr* compare = new StrictCompareInstr( | 1812 StrictCompareInstr* compare = new StrictCompareInstr( |
1812 call_->instance_call()->token_pos(), Token::kEQ_STRICT, | 1813 call_->instance_call()->token_pos(), Token::kEQ_STRICT, |
1813 new Value(load_cid), new Value(cid_constant), | 1814 new Value(load_cid), new Value(cid_constant), |
1814 false); // No number check. | 1815 /* number_check = */ false, Thread::kNoDeoptId); |
1815 branch = new BranchInstr(compare); | 1816 branch = new BranchInstr(compare, Thread::kNoDeoptId); |
1816 } | 1817 } |
1817 | 1818 |
1818 branch->InheritDeoptTarget(zone(), call_); | 1819 branch->InheritDeoptTarget(zone(), call_); |
1819 cursor = AppendInstruction(cursor, branch); | 1820 cursor = AppendInstruction(cursor, branch); |
1820 current_block->set_last_instruction(branch); | 1821 current_block->set_last_instruction(branch); |
1821 cursor = NULL; | 1822 cursor = NULL; |
1822 | 1823 |
1823 // 2. Handle a match by linking to the inlined body. There are three | 1824 // 2. Handle a match by linking to the inlined body. There are three |
1824 // cases (unshared, shared first predecessor, and shared subsequent | 1825 // cases (unshared, shared first predecessor, and shared subsequent |
1825 // predecessors). | 1826 // predecessors). |
(...skipping 10 matching lines...) Expand all Loading... |
1836 true_target = callee_entry->AsTargetEntry(); | 1837 true_target = callee_entry->AsTargetEntry(); |
1837 BlockEntryInstr* join = true_target->last_instruction()->SuccessorAt(0); | 1838 BlockEntryInstr* join = true_target->last_instruction()->SuccessorAt(0); |
1838 current_block->AddDominatedBlock(join); | 1839 current_block->AddDominatedBlock(join); |
1839 } else { | 1840 } else { |
1840 // Shared inlined body and this is a subsequent entry. We have | 1841 // Shared inlined body and this is a subsequent entry. We have |
1841 // already constructed a join. We need a fresh target that jumps to | 1842 // already constructed a join. We need a fresh target that jumps to |
1842 // the join. | 1843 // the join. |
1843 JoinEntryInstr* join = callee_entry->AsJoinEntry(); | 1844 JoinEntryInstr* join = callee_entry->AsJoinEntry(); |
1844 ASSERT(join != NULL); | 1845 ASSERT(join != NULL); |
1845 ASSERT(join->dominator() != NULL); | 1846 ASSERT(join->dominator() != NULL); |
1846 true_target = new TargetEntryInstr(AllocateBlockId(), try_idx); | 1847 true_target = new TargetEntryInstr(AllocateBlockId(), try_idx, |
| 1848 Thread::kNoDeoptId); |
1847 true_target->InheritDeoptTarget(zone(), join); | 1849 true_target->InheritDeoptTarget(zone(), join); |
1848 GotoInstr* goto_join = new GotoInstr(join); | 1850 GotoInstr* goto_join = new GotoInstr(join, Thread::kNoDeoptId); |
1849 goto_join->InheritDeoptTarget(zone(), join); | 1851 goto_join->InheritDeoptTarget(zone(), join); |
1850 true_target->LinkTo(goto_join); | 1852 true_target->LinkTo(goto_join); |
1851 true_target->set_last_instruction(goto_join); | 1853 true_target->set_last_instruction(goto_join); |
1852 } | 1854 } |
1853 *branch->true_successor_address() = true_target; | 1855 *branch->true_successor_address() = true_target; |
1854 current_block->AddDominatedBlock(true_target); | 1856 current_block->AddDominatedBlock(true_target); |
1855 | 1857 |
1856 // 3. Prepare to handle a match failure on the next iteration or the | 1858 // 3. Prepare to handle a match failure on the next iteration or the |
1857 // fall-through code below for non-inlined variants. | 1859 // fall-through code below for non-inlined variants. |
1858 | 1860 |
1859 TargetEntryInstr* false_target = | 1861 TargetEntryInstr* false_target = |
1860 new TargetEntryInstr(AllocateBlockId(), try_idx); | 1862 new TargetEntryInstr(AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1861 false_target->InheritDeoptTarget(zone(), call_); | 1863 false_target->InheritDeoptTarget(zone(), call_); |
1862 *branch->false_successor_address() = false_target; | 1864 *branch->false_successor_address() = false_target; |
1863 cid_test_entry_block->AddDominatedBlock(false_target); | 1865 cid_test_entry_block->AddDominatedBlock(false_target); |
1864 | 1866 |
1865 cursor = current_block = false_target; | 1867 cursor = current_block = false_target; |
1866 | 1868 |
1867 if (test_is_range) { | 1869 if (test_is_range) { |
1868 // If we tested against a range of Cids there are two different tests | 1870 // If we tested against a range of Cids there are two different tests |
1869 // that can go to the no-cid-match target. | 1871 // that can go to the no-cid-match target. |
1870 JoinEntryInstr* join = new JoinEntryInstr(AllocateBlockId(), try_idx); | 1872 JoinEntryInstr* join = |
1871 TargetEntryInstr* false_target2 = | 1873 new JoinEntryInstr(AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1872 new TargetEntryInstr(AllocateBlockId(), try_idx); | 1874 TargetEntryInstr* false_target2 = new TargetEntryInstr( |
| 1875 AllocateBlockId(), try_idx, Thread::kNoDeoptId); |
1873 *upper_limit_branch->false_successor_address() = false_target2; | 1876 *upper_limit_branch->false_successor_address() = false_target2; |
1874 cid_test_entry_block->AddDominatedBlock(false_target2); | 1877 cid_test_entry_block->AddDominatedBlock(false_target2); |
1875 cid_test_entry_block->AddDominatedBlock(join); | 1878 cid_test_entry_block->AddDominatedBlock(join); |
1876 GotoInstr* goto_1 = new GotoInstr(join); | 1879 GotoInstr* goto_1 = new GotoInstr(join, Thread::kNoDeoptId); |
1877 GotoInstr* goto_2 = new GotoInstr(join); | 1880 GotoInstr* goto_2 = new GotoInstr(join, Thread::kNoDeoptId); |
1878 false_target->LinkTo(goto_1); | 1881 false_target->LinkTo(goto_1); |
1879 false_target2->LinkTo(goto_2); | 1882 false_target2->LinkTo(goto_2); |
1880 false_target->set_last_instruction(goto_1); | 1883 false_target->set_last_instruction(goto_1); |
1881 false_target2->set_last_instruction(goto_2); | 1884 false_target2->set_last_instruction(goto_2); |
1882 | 1885 |
1883 join->InheritDeoptTarget(zone(), call_); | 1886 join->InheritDeoptTarget(zone(), call_); |
1884 false_target2->InheritDeoptTarget(zone(), call_); | 1887 false_target2->InheritDeoptTarget(zone(), call_); |
1885 goto_1->InheritDeoptTarget(zone(), call_); | 1888 goto_1->InheritDeoptTarget(zone(), call_); |
1886 goto_2->InheritDeoptTarget(zone(), call_); | 1889 goto_2->InheritDeoptTarget(zone(), call_); |
1887 | 1890 |
(...skipping 13 matching lines...) Expand all Loading... |
1901 cursor = push; | 1904 cursor = push; |
1902 } | 1905 } |
1903 PolymorphicInstanceCallInstr* fallback_call = | 1906 PolymorphicInstanceCallInstr* fallback_call = |
1904 new PolymorphicInstanceCallInstr( | 1907 new PolymorphicInstanceCallInstr( |
1905 call_->instance_call(), *non_inlined_variants_, | 1908 call_->instance_call(), *non_inlined_variants_, |
1906 /* with_checks = */ true, call_->complete()); | 1909 /* with_checks = */ true, call_->complete()); |
1907 fallback_call->set_ssa_temp_index( | 1910 fallback_call->set_ssa_temp_index( |
1908 owner_->caller_graph()->alloc_ssa_temp_index()); | 1911 owner_->caller_graph()->alloc_ssa_temp_index()); |
1909 fallback_call->InheritDeoptTarget(zone(), call_); | 1912 fallback_call->InheritDeoptTarget(zone(), call_); |
1910 fallback_call->set_total_call_count(call_->CallCount()); | 1913 fallback_call->set_total_call_count(call_->CallCount()); |
1911 ReturnInstr* fallback_return = new ReturnInstr( | 1914 ReturnInstr* fallback_return = |
1912 call_->instance_call()->token_pos(), new Value(fallback_call)); | 1915 new ReturnInstr(call_->instance_call()->token_pos(), |
| 1916 new Value(fallback_call), Thread::kNoDeoptId); |
1913 fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_, | 1917 fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_, |
1914 fallback_call); | 1918 fallback_call); |
1915 AppendInstruction(AppendInstruction(cursor, fallback_call), | 1919 AppendInstruction(AppendInstruction(cursor, fallback_call), |
1916 fallback_return); | 1920 fallback_return); |
1917 exit_collector_->AddExit(fallback_return); | 1921 exit_collector_->AddExit(fallback_return); |
1918 cursor = NULL; | 1922 cursor = NULL; |
1919 } else { | 1923 } else { |
1920 if (follow_with_deopt) { | 1924 if (follow_with_deopt) { |
1921 DeoptimizeInstr* deopt = new DeoptimizeInstr( | 1925 DeoptimizeInstr* deopt = new DeoptimizeInstr( |
1922 ICData::kDeoptPolymorphicInstanceCallTestFail, call_->deopt_id()); | 1926 ICData::kDeoptPolymorphicInstanceCallTestFail, call_->deopt_id()); |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2286 static bool InlineGetIndexed(FlowGraph* flow_graph, | 2290 static bool InlineGetIndexed(FlowGraph* flow_graph, |
2287 MethodRecognizer::Kind kind, | 2291 MethodRecognizer::Kind kind, |
2288 Instruction* call, | 2292 Instruction* call, |
2289 Definition* receiver, | 2293 Definition* receiver, |
2290 TargetEntryInstr** entry, | 2294 TargetEntryInstr** entry, |
2291 Definition** last) { | 2295 Definition** last) { |
2292 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); | 2296 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); |
2293 | 2297 |
2294 Definition* array = receiver; | 2298 Definition* array = receiver; |
2295 Definition* index = call->ArgumentAt(1); | 2299 Definition* index = call->ArgumentAt(1); |
2296 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2300 *entry = new (Z) |
2297 call->GetBlock()->try_index()); | 2301 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2302 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2298 (*entry)->InheritDeoptTarget(Z, call); | 2303 (*entry)->InheritDeoptTarget(Z, call); |
2299 Instruction* cursor = *entry; | 2304 Instruction* cursor = *entry; |
2300 | 2305 |
2301 array_cid = PrepareInlineIndexedOp(flow_graph, call, array_cid, &array, index, | 2306 array_cid = PrepareInlineIndexedOp(flow_graph, call, array_cid, &array, index, |
2302 &cursor); | 2307 &cursor); |
2303 | 2308 |
2304 intptr_t deopt_id = Thread::kNoDeoptId; | 2309 intptr_t deopt_id = Thread::kNoDeoptId; |
2305 if ((array_cid == kTypedDataInt32ArrayCid) || | 2310 if ((array_cid == kTypedDataInt32ArrayCid) || |
2306 (array_cid == kTypedDataUint32ArrayCid)) { | 2311 (array_cid == kTypedDataUint32ArrayCid)) { |
2307 // Deoptimization may be needed if result does not always fit in a Smi. | 2312 // Deoptimization may be needed if result does not always fit in a Smi. |
(...skipping 27 matching lines...) Expand all Loading... |
2335 TokenPosition token_pos, | 2340 TokenPosition token_pos, |
2336 const Cids* value_check, | 2341 const Cids* value_check, |
2337 TargetEntryInstr** entry, | 2342 TargetEntryInstr** entry, |
2338 Definition** last) { | 2343 Definition** last) { |
2339 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); | 2344 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); |
2340 | 2345 |
2341 Definition* array = receiver; | 2346 Definition* array = receiver; |
2342 Definition* index = call->ArgumentAt(1); | 2347 Definition* index = call->ArgumentAt(1); |
2343 Definition* stored_value = call->ArgumentAt(2); | 2348 Definition* stored_value = call->ArgumentAt(2); |
2344 | 2349 |
2345 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2350 *entry = new (Z) |
2346 call->GetBlock()->try_index()); | 2351 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2352 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2347 (*entry)->InheritDeoptTarget(Z, call); | 2353 (*entry)->InheritDeoptTarget(Z, call); |
2348 Instruction* cursor = *entry; | 2354 Instruction* cursor = *entry; |
2349 if (flow_graph->isolate()->type_checks()) { | 2355 if (flow_graph->isolate()->type_checks()) { |
2350 // Only type check for the value. A type check for the index is not | 2356 // Only type check for the value. A type check for the index is not |
2351 // needed here because we insert a deoptimizing smi-check for the case | 2357 // needed here because we insert a deoptimizing smi-check for the case |
2352 // the index is not a smi. | 2358 // the index is not a smi. |
2353 const AbstractType& value_type = | 2359 const AbstractType& value_type = |
2354 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); | 2360 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); |
2355 Definition* type_args = NULL; | 2361 Definition* type_args = NULL; |
2356 switch (array_cid) { | 2362 switch (array_cid) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2472 Instruction* call, | 2478 Instruction* call, |
2473 Definition* receiver, | 2479 Definition* receiver, |
2474 TargetEntryInstr** entry, | 2480 TargetEntryInstr** entry, |
2475 Definition** last) { | 2481 Definition** last) { |
2476 if (!CanUnboxDouble()) { | 2482 if (!CanUnboxDouble()) { |
2477 return false; | 2483 return false; |
2478 } | 2484 } |
2479 Definition* left = receiver; | 2485 Definition* left = receiver; |
2480 Definition* right = call->ArgumentAt(1); | 2486 Definition* right = call->ArgumentAt(1); |
2481 | 2487 |
2482 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2488 *entry = new (Z) |
2483 call->GetBlock()->try_index()); | 2489 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2490 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2484 (*entry)->InheritDeoptTarget(Z, call); | 2491 (*entry)->InheritDeoptTarget(Z, call); |
2485 // Arguments are checked. No need for class check. | 2492 // Arguments are checked. No need for class check. |
2486 BinaryDoubleOpInstr* double_bin_op = new (Z) | 2493 BinaryDoubleOpInstr* double_bin_op = new (Z) |
2487 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), | 2494 BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right), |
2488 call->deopt_id(), call->token_pos()); | 2495 call->deopt_id(), call->token_pos()); |
2489 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); | 2496 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); |
2490 *last = double_bin_op; | 2497 *last = double_bin_op; |
2491 | 2498 |
2492 return true; | 2499 return true; |
2493 } | 2500 } |
2494 | 2501 |
2495 | 2502 |
2496 static bool InlineDoubleTestOp(FlowGraph* flow_graph, | 2503 static bool InlineDoubleTestOp(FlowGraph* flow_graph, |
2497 Instruction* call, | 2504 Instruction* call, |
2498 Definition* receiver, | 2505 Definition* receiver, |
2499 MethodRecognizer::Kind kind, | 2506 MethodRecognizer::Kind kind, |
2500 TargetEntryInstr** entry, | 2507 TargetEntryInstr** entry, |
2501 Definition** last) { | 2508 Definition** last) { |
2502 if (!CanUnboxDouble()) { | 2509 if (!CanUnboxDouble()) { |
2503 return false; | 2510 return false; |
2504 } | 2511 } |
2505 | 2512 |
2506 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2513 *entry = new (Z) |
2507 call->GetBlock()->try_index()); | 2514 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2515 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2508 (*entry)->InheritDeoptTarget(Z, call); | 2516 (*entry)->InheritDeoptTarget(Z, call); |
2509 // Arguments are checked. No need for class check. | 2517 // Arguments are checked. No need for class check. |
2510 | 2518 |
2511 DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr( | 2519 DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr( |
2512 kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos()); | 2520 kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos()); |
2513 flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue); | 2521 flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue); |
2514 *last = double_test_op; | 2522 *last = double_test_op; |
2515 | 2523 |
2516 return true; | 2524 return true; |
2517 } | 2525 } |
2518 | 2526 |
2519 | 2527 |
2520 static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph, | 2528 static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph, |
2521 Instruction* call, | 2529 Instruction* call, |
2522 Definition* receiver, | 2530 Definition* receiver, |
2523 TargetEntryInstr** entry, | 2531 TargetEntryInstr** entry, |
2524 Definition** last) { | 2532 Definition** last) { |
2525 Definition* left = receiver; | 2533 Definition* left = receiver; |
2526 Definition* right = call->ArgumentAt(1); | 2534 Definition* right = call->ArgumentAt(1); |
2527 | 2535 |
2528 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2536 *entry = new (Z) |
2529 call->GetBlock()->try_index()); | 2537 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2538 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2530 (*entry)->InheritDeoptTarget(Z, call); | 2539 (*entry)->InheritDeoptTarget(Z, call); |
2531 // Right arguments is known to be smi: other._bitAndFromSmi(this); | 2540 // Right arguments is known to be smi: other._bitAndFromSmi(this); |
2532 BinarySmiOpInstr* smi_op = | 2541 BinarySmiOpInstr* smi_op = |
2533 new (Z) BinarySmiOpInstr(Token::kBIT_AND, new (Z) Value(left), | 2542 new (Z) BinarySmiOpInstr(Token::kBIT_AND, new (Z) Value(left), |
2534 new (Z) Value(right), call->deopt_id()); | 2543 new (Z) Value(right), call->deopt_id()); |
2535 flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue); | 2544 flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue); |
2536 *last = smi_op; | 2545 *last = smi_op; |
2537 | 2546 |
2538 return true; | 2547 return true; |
2539 } | 2548 } |
2540 | 2549 |
2541 | 2550 |
2542 static bool InlineGrowableArraySetter(FlowGraph* flow_graph, | 2551 static bool InlineGrowableArraySetter(FlowGraph* flow_graph, |
2543 intptr_t offset, | 2552 intptr_t offset, |
2544 StoreBarrierType store_barrier_type, | 2553 StoreBarrierType store_barrier_type, |
2545 Instruction* call, | 2554 Instruction* call, |
2546 Definition* receiver, | 2555 Definition* receiver, |
2547 TargetEntryInstr** entry, | 2556 TargetEntryInstr** entry, |
2548 Definition** last) { | 2557 Definition** last) { |
2549 Definition* array = receiver; | 2558 Definition* array = receiver; |
2550 Definition* value = call->ArgumentAt(1); | 2559 Definition* value = call->ArgumentAt(1); |
2551 | 2560 |
2552 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2561 *entry = new (Z) |
2553 call->GetBlock()->try_index()); | 2562 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2563 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2554 (*entry)->InheritDeoptTarget(Z, call); | 2564 (*entry)->InheritDeoptTarget(Z, call); |
2555 | 2565 |
2556 // This is an internal method, no need to check argument types. | 2566 // This is an internal method, no need to check argument types. |
2557 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr( | 2567 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr( |
2558 offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type, | 2568 offset, new (Z) Value(array), new (Z) Value(value), store_barrier_type, |
2559 call->token_pos()); | 2569 call->token_pos()); |
2560 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); | 2570 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); |
2561 *last = store; | 2571 *last = store; |
2562 | 2572 |
2563 return true; | 2573 return true; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2628 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, | 2638 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, |
2629 Instruction* call, | 2639 Instruction* call, |
2630 Definition* receiver, | 2640 Definition* receiver, |
2631 intptr_t array_cid, | 2641 intptr_t array_cid, |
2632 intptr_t view_cid, | 2642 intptr_t view_cid, |
2633 TargetEntryInstr** entry, | 2643 TargetEntryInstr** entry, |
2634 Definition** last) { | 2644 Definition** last) { |
2635 ASSERT(array_cid != kIllegalCid); | 2645 ASSERT(array_cid != kIllegalCid); |
2636 Definition* array = receiver; | 2646 Definition* array = receiver; |
2637 Definition* index = call->ArgumentAt(1); | 2647 Definition* index = call->ArgumentAt(1); |
2638 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2648 *entry = new (Z) |
2639 call->GetBlock()->try_index()); | 2649 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2650 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2640 (*entry)->InheritDeoptTarget(Z, call); | 2651 (*entry)->InheritDeoptTarget(Z, call); |
2641 Instruction* cursor = *entry; | 2652 Instruction* cursor = *entry; |
2642 | 2653 |
2643 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, | 2654 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, |
2644 index, &cursor); | 2655 index, &cursor); |
2645 | 2656 |
2646 intptr_t deopt_id = Thread::kNoDeoptId; | 2657 intptr_t deopt_id = Thread::kNoDeoptId; |
2647 if ((array_cid == kTypedDataInt32ArrayCid) || | 2658 if ((array_cid == kTypedDataInt32ArrayCid) || |
2648 (array_cid == kTypedDataUint32ArrayCid)) { | 2659 (array_cid == kTypedDataUint32ArrayCid)) { |
2649 // Deoptimization may be needed if result does not always fit in a Smi. | 2660 // Deoptimization may be needed if result does not always fit in a Smi. |
(...skipping 21 matching lines...) Expand all Loading... |
2671 const Function& target, | 2682 const Function& target, |
2672 Instruction* call, | 2683 Instruction* call, |
2673 Definition* receiver, | 2684 Definition* receiver, |
2674 intptr_t array_cid, | 2685 intptr_t array_cid, |
2675 intptr_t view_cid, | 2686 intptr_t view_cid, |
2676 TargetEntryInstr** entry, | 2687 TargetEntryInstr** entry, |
2677 Definition** last) { | 2688 Definition** last) { |
2678 ASSERT(array_cid != kIllegalCid); | 2689 ASSERT(array_cid != kIllegalCid); |
2679 Definition* array = receiver; | 2690 Definition* array = receiver; |
2680 Definition* index = call->ArgumentAt(1); | 2691 Definition* index = call->ArgumentAt(1); |
2681 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2692 *entry = new (Z) |
2682 call->GetBlock()->try_index()); | 2693 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2694 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2683 (*entry)->InheritDeoptTarget(Z, call); | 2695 (*entry)->InheritDeoptTarget(Z, call); |
2684 Instruction* cursor = *entry; | 2696 Instruction* cursor = *entry; |
2685 | 2697 |
2686 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, | 2698 PrepareInlineByteArrayBaseOp(flow_graph, call, array_cid, view_cid, &array, |
2687 index, &cursor); | 2699 index, &cursor); |
2688 | 2700 |
2689 // Extract the instance call so we can use the function_name in the stored | 2701 // Extract the instance call so we can use the function_name in the stored |
2690 // value check ICData. | 2702 // value check ICData. |
2691 InstanceCallInstr* i_call = NULL; | 2703 InstanceCallInstr* i_call = NULL; |
2692 if (call->IsPolymorphicInstanceCall()) { | 2704 if (call->IsPolymorphicInstanceCall()) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2837 Definition* receiver, | 2849 Definition* receiver, |
2838 intptr_t cid, | 2850 intptr_t cid, |
2839 TargetEntryInstr** entry, | 2851 TargetEntryInstr** entry, |
2840 Definition** last) { | 2852 Definition** last) { |
2841 if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) { | 2853 if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) { |
2842 return false; | 2854 return false; |
2843 } | 2855 } |
2844 Definition* str = receiver; | 2856 Definition* str = receiver; |
2845 Definition* index = call->ArgumentAt(1); | 2857 Definition* index = call->ArgumentAt(1); |
2846 | 2858 |
2847 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2859 *entry = new (Z) |
2848 call->GetBlock()->try_index()); | 2860 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2861 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2849 (*entry)->InheritDeoptTarget(Z, call); | 2862 (*entry)->InheritDeoptTarget(Z, call); |
2850 | 2863 |
2851 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); | 2864 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); |
2852 | 2865 |
2853 OneByteStringFromCharCodeInstr* char_at = | 2866 OneByteStringFromCharCodeInstr* char_at = |
2854 new (Z) OneByteStringFromCharCodeInstr(new (Z) Value(*last)); | 2867 new (Z) OneByteStringFromCharCodeInstr(new (Z) Value(*last)); |
2855 | 2868 |
2856 flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue); | 2869 flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
2857 *last = char_at; | 2870 *last = char_at; |
2858 | 2871 |
2859 return true; | 2872 return true; |
2860 } | 2873 } |
2861 | 2874 |
2862 | 2875 |
2863 static bool InlineStringCodeUnitAt(FlowGraph* flow_graph, | 2876 static bool InlineStringCodeUnitAt(FlowGraph* flow_graph, |
2864 Instruction* call, | 2877 Instruction* call, |
2865 Definition* receiver, | 2878 Definition* receiver, |
2866 intptr_t cid, | 2879 intptr_t cid, |
2867 TargetEntryInstr** entry, | 2880 TargetEntryInstr** entry, |
2868 Definition** last) { | 2881 Definition** last) { |
2869 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 2882 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
2870 (cid == kExternalOneByteStringCid) || | 2883 (cid == kExternalOneByteStringCid) || |
2871 (cid == kExternalTwoByteStringCid)); | 2884 (cid == kExternalTwoByteStringCid)); |
2872 Definition* str = receiver; | 2885 Definition* str = receiver; |
2873 Definition* index = call->ArgumentAt(1); | 2886 Definition* index = call->ArgumentAt(1); |
2874 | 2887 |
2875 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2888 *entry = new (Z) |
2876 call->GetBlock()->try_index()); | 2889 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2890 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2877 (*entry)->InheritDeoptTarget(Z, call); | 2891 (*entry)->InheritDeoptTarget(Z, call); |
2878 | 2892 |
2879 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); | 2893 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); |
2880 | 2894 |
2881 return true; | 2895 return true; |
2882 } | 2896 } |
2883 | 2897 |
2884 | 2898 |
2885 // Only used for monomorphic calls. | 2899 // Only used for monomorphic calls. |
2886 bool FlowGraphInliner::TryReplaceInstanceCallWithInline( | 2900 bool FlowGraphInliner::TryReplaceInstanceCallWithInline( |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2978 static bool InlineFloat32x4Method(FlowGraph* flow_graph, | 2992 static bool InlineFloat32x4Method(FlowGraph* flow_graph, |
2979 Instruction* call, | 2993 Instruction* call, |
2980 Definition* receiver, | 2994 Definition* receiver, |
2981 MethodRecognizer::Kind kind, | 2995 MethodRecognizer::Kind kind, |
2982 TargetEntryInstr** entry, | 2996 TargetEntryInstr** entry, |
2983 Definition** last) { | 2997 Definition** last) { |
2984 if (!ShouldInlineSimd()) { | 2998 if (!ShouldInlineSimd()) { |
2985 return false; | 2999 return false; |
2986 } | 3000 } |
2987 | 3001 |
2988 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3002 *entry = new (Z) |
2989 call->GetBlock()->try_index()); | 3003 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3004 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
2990 (*entry)->InheritDeoptTarget(Z, call); | 3005 (*entry)->InheritDeoptTarget(Z, call); |
2991 Instruction* cursor = *entry; | 3006 Instruction* cursor = *entry; |
2992 switch (kind) { | 3007 switch (kind) { |
2993 case MethodRecognizer::kFloat32x4ShuffleX: | 3008 case MethodRecognizer::kFloat32x4ShuffleX: |
2994 case MethodRecognizer::kFloat32x4ShuffleY: | 3009 case MethodRecognizer::kFloat32x4ShuffleY: |
2995 case MethodRecognizer::kFloat32x4ShuffleZ: | 3010 case MethodRecognizer::kFloat32x4ShuffleZ: |
2996 case MethodRecognizer::kFloat32x4ShuffleW: { | 3011 case MethodRecognizer::kFloat32x4ShuffleW: { |
2997 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(receiver), | 3012 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(receiver), |
2998 0, // mask ignored. | 3013 0, // mask ignored. |
2999 call->deopt_id()); | 3014 call->deopt_id()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3096 | 3111 |
3097 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph, | 3112 static bool InlineSimdShuffleMethod(FlowGraph* flow_graph, |
3098 Instruction* call, | 3113 Instruction* call, |
3099 Definition* receiver, | 3114 Definition* receiver, |
3100 MethodRecognizer::Kind kind, | 3115 MethodRecognizer::Kind kind, |
3101 TargetEntryInstr** entry, | 3116 TargetEntryInstr** entry, |
3102 Definition** last) { | 3117 Definition** last) { |
3103 if (!ShouldInlineSimd()) { | 3118 if (!ShouldInlineSimd()) { |
3104 return false; | 3119 return false; |
3105 } | 3120 } |
3106 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3121 *entry = new (Z) |
3107 call->GetBlock()->try_index()); | 3122 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3123 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3108 (*entry)->InheritDeoptTarget(Z, call); | 3124 (*entry)->InheritDeoptTarget(Z, call); |
3109 Instruction* cursor = *entry; | 3125 Instruction* cursor = *entry; |
3110 Definition* mask_definition = call->ArgumentAt(1); | 3126 Definition* mask_definition = call->ArgumentAt(1); |
3111 intptr_t mask = 0; | 3127 intptr_t mask = 0; |
3112 if (!CheckMask(mask_definition, &mask)) { | 3128 if (!CheckMask(mask_definition, &mask)) { |
3113 return false; | 3129 return false; |
3114 } | 3130 } |
3115 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(call->ArgumentAt(0)), | 3131 *last = new (Z) Simd32x4ShuffleInstr(kind, new (Z) Value(call->ArgumentAt(0)), |
3116 mask, call->deopt_id()); | 3132 mask, call->deopt_id()); |
3117 flow_graph->AppendTo( | 3133 flow_graph->AppendTo( |
3118 cursor, *last, | 3134 cursor, *last, |
3119 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3135 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3120 FlowGraph::kValue); | 3136 FlowGraph::kValue); |
3121 return true; | 3137 return true; |
3122 } | 3138 } |
3123 | 3139 |
3124 | 3140 |
3125 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph, | 3141 static bool InlineSimdShuffleMixMethod(FlowGraph* flow_graph, |
3126 Instruction* call, | 3142 Instruction* call, |
3127 Definition* receiver, | 3143 Definition* receiver, |
3128 MethodRecognizer::Kind kind, | 3144 MethodRecognizer::Kind kind, |
3129 TargetEntryInstr** entry, | 3145 TargetEntryInstr** entry, |
3130 Definition** last) { | 3146 Definition** last) { |
3131 if (!ShouldInlineSimd()) { | 3147 if (!ShouldInlineSimd()) { |
3132 return false; | 3148 return false; |
3133 } | 3149 } |
3134 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3150 *entry = new (Z) |
3135 call->GetBlock()->try_index()); | 3151 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3152 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3136 (*entry)->InheritDeoptTarget(Z, call); | 3153 (*entry)->InheritDeoptTarget(Z, call); |
3137 Instruction* cursor = *entry; | 3154 Instruction* cursor = *entry; |
3138 Definition* mask_definition = call->ArgumentAt(2); | 3155 Definition* mask_definition = call->ArgumentAt(2); |
3139 intptr_t mask = 0; | 3156 intptr_t mask = 0; |
3140 if (!CheckMask(mask_definition, &mask)) { | 3157 if (!CheckMask(mask_definition, &mask)) { |
3141 return false; | 3158 return false; |
3142 } | 3159 } |
3143 *last = new (Z) Simd32x4ShuffleMixInstr(kind, new (Z) Value(receiver), | 3160 *last = new (Z) Simd32x4ShuffleMixInstr(kind, new (Z) Value(receiver), |
3144 new (Z) Value(call->ArgumentAt(1)), | 3161 new (Z) Value(call->ArgumentAt(1)), |
3145 mask, call->deopt_id()); | 3162 mask, call->deopt_id()); |
3146 flow_graph->AppendTo( | 3163 flow_graph->AppendTo( |
3147 cursor, *last, | 3164 cursor, *last, |
3148 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3165 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3149 FlowGraph::kValue); | 3166 FlowGraph::kValue); |
3150 return true; | 3167 return true; |
3151 } | 3168 } |
3152 | 3169 |
3153 | 3170 |
3154 static bool InlineInt32x4Method(FlowGraph* flow_graph, | 3171 static bool InlineInt32x4Method(FlowGraph* flow_graph, |
3155 Instruction* call, | 3172 Instruction* call, |
3156 Definition* receiver, | 3173 Definition* receiver, |
3157 MethodRecognizer::Kind kind, | 3174 MethodRecognizer::Kind kind, |
3158 TargetEntryInstr** entry, | 3175 TargetEntryInstr** entry, |
3159 Definition** last) { | 3176 Definition** last) { |
3160 if (!ShouldInlineSimd()) { | 3177 if (!ShouldInlineSimd()) { |
3161 return false; | 3178 return false; |
3162 } | 3179 } |
3163 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3180 *entry = new (Z) |
3164 call->GetBlock()->try_index()); | 3181 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3182 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3165 (*entry)->InheritDeoptTarget(Z, call); | 3183 (*entry)->InheritDeoptTarget(Z, call); |
3166 Instruction* cursor = *entry; | 3184 Instruction* cursor = *entry; |
3167 switch (kind) { | 3185 switch (kind) { |
3168 case MethodRecognizer::kInt32x4GetFlagX: | 3186 case MethodRecognizer::kInt32x4GetFlagX: |
3169 case MethodRecognizer::kInt32x4GetFlagY: | 3187 case MethodRecognizer::kInt32x4GetFlagY: |
3170 case MethodRecognizer::kInt32x4GetFlagZ: | 3188 case MethodRecognizer::kInt32x4GetFlagZ: |
3171 case MethodRecognizer::kInt32x4GetFlagW: { | 3189 case MethodRecognizer::kInt32x4GetFlagW: { |
3172 *last = new (Z) | 3190 *last = new (Z) |
3173 Int32x4GetFlagInstr(kind, new (Z) Value(receiver), call->deopt_id()); | 3191 Int32x4GetFlagInstr(kind, new (Z) Value(receiver), call->deopt_id()); |
3174 break; | 3192 break; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3209 | 3227 |
3210 static bool InlineFloat64x2Method(FlowGraph* flow_graph, | 3228 static bool InlineFloat64x2Method(FlowGraph* flow_graph, |
3211 Instruction* call, | 3229 Instruction* call, |
3212 Definition* receiver, | 3230 Definition* receiver, |
3213 MethodRecognizer::Kind kind, | 3231 MethodRecognizer::Kind kind, |
3214 TargetEntryInstr** entry, | 3232 TargetEntryInstr** entry, |
3215 Definition** last) { | 3233 Definition** last) { |
3216 if (!ShouldInlineSimd()) { | 3234 if (!ShouldInlineSimd()) { |
3217 return false; | 3235 return false; |
3218 } | 3236 } |
3219 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3237 *entry = new (Z) |
3220 call->GetBlock()->try_index()); | 3238 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3239 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3221 (*entry)->InheritDeoptTarget(Z, call); | 3240 (*entry)->InheritDeoptTarget(Z, call); |
3222 Instruction* cursor = *entry; | 3241 Instruction* cursor = *entry; |
3223 switch (kind) { | 3242 switch (kind) { |
3224 case MethodRecognizer::kFloat64x2GetX: | 3243 case MethodRecognizer::kFloat64x2GetX: |
3225 case MethodRecognizer::kFloat64x2GetY: { | 3244 case MethodRecognizer::kFloat64x2GetY: { |
3226 *last = new (Z) Simd64x2ShuffleInstr(kind, new (Z) Value(receiver), | 3245 *last = new (Z) Simd64x2ShuffleInstr(kind, new (Z) Value(receiver), |
3227 0, // mask is ignored. | 3246 0, // mask is ignored. |
3228 call->deopt_id()); | 3247 call->deopt_id()); |
3229 break; | 3248 break; |
3230 } | 3249 } |
(...skipping 29 matching lines...) Expand all Loading... |
3260 | 3279 |
3261 | 3280 |
3262 static bool InlineSimdConstructor(FlowGraph* flow_graph, | 3281 static bool InlineSimdConstructor(FlowGraph* flow_graph, |
3263 Instruction* call, | 3282 Instruction* call, |
3264 MethodRecognizer::Kind kind, | 3283 MethodRecognizer::Kind kind, |
3265 TargetEntryInstr** entry, | 3284 TargetEntryInstr** entry, |
3266 Definition** last) { | 3285 Definition** last) { |
3267 if (!ShouldInlineSimd()) { | 3286 if (!ShouldInlineSimd()) { |
3268 return false; | 3287 return false; |
3269 } | 3288 } |
3270 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3289 *entry = new (Z) |
3271 call->GetBlock()->try_index()); | 3290 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3291 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3272 (*entry)->InheritDeoptTarget(Z, call); | 3292 (*entry)->InheritDeoptTarget(Z, call); |
3273 Instruction* cursor = *entry; | 3293 Instruction* cursor = *entry; |
3274 switch (kind) { | 3294 switch (kind) { |
3275 case MethodRecognizer::kFloat32x4Zero: | 3295 case MethodRecognizer::kFloat32x4Zero: |
3276 *last = new (Z) Float32x4ZeroInstr(); | 3296 *last = new (Z) Float32x4ZeroInstr(); |
3277 break; | 3297 break; |
3278 case MethodRecognizer::kFloat32x4Splat: | 3298 case MethodRecognizer::kFloat32x4Splat: |
3279 *last = new (Z) Float32x4SplatInstr(new (Z) Value(call->ArgumentAt(1)), | 3299 *last = new (Z) Float32x4SplatInstr(new (Z) Value(call->ArgumentAt(1)), |
3280 call->deopt_id()); | 3300 call->deopt_id()); |
3281 break; | 3301 break; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3341 | 3361 |
3342 | 3362 |
3343 static bool InlineMathCFunction(FlowGraph* flow_graph, | 3363 static bool InlineMathCFunction(FlowGraph* flow_graph, |
3344 Instruction* call, | 3364 Instruction* call, |
3345 MethodRecognizer::Kind kind, | 3365 MethodRecognizer::Kind kind, |
3346 TargetEntryInstr** entry, | 3366 TargetEntryInstr** entry, |
3347 Definition** last) { | 3367 Definition** last) { |
3348 if (!CanUnboxDouble()) { | 3368 if (!CanUnboxDouble()) { |
3349 return false; | 3369 return false; |
3350 } | 3370 } |
3351 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3371 *entry = new (Z) |
3352 call->GetBlock()->try_index()); | 3372 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3373 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3353 (*entry)->InheritDeoptTarget(Z, call); | 3374 (*entry)->InheritDeoptTarget(Z, call); |
3354 Instruction* cursor = *entry; | 3375 Instruction* cursor = *entry; |
3355 | 3376 |
3356 switch (kind) { | 3377 switch (kind) { |
3357 case MethodRecognizer::kMathSqrt: { | 3378 case MethodRecognizer::kMathSqrt: { |
3358 *last = new (Z) | 3379 *last = new (Z) |
3359 MathUnaryInstr(MathUnaryInstr::kSqrt, | 3380 MathUnaryInstr(MathUnaryInstr::kSqrt, |
3360 new (Z) Value(call->ArgumentAt(0)), call->deopt_id()); | 3381 new (Z) Value(call->ArgumentAt(0)), call->deopt_id()); |
3361 break; | 3382 break; |
3362 } | 3383 } |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3703 case MethodRecognizer::kMathSin: | 3724 case MethodRecognizer::kMathSin: |
3704 case MethodRecognizer::kMathCos: | 3725 case MethodRecognizer::kMathCos: |
3705 case MethodRecognizer::kMathTan: | 3726 case MethodRecognizer::kMathTan: |
3706 case MethodRecognizer::kMathAsin: | 3727 case MethodRecognizer::kMathAsin: |
3707 case MethodRecognizer::kMathAcos: | 3728 case MethodRecognizer::kMathAcos: |
3708 case MethodRecognizer::kMathAtan: | 3729 case MethodRecognizer::kMathAtan: |
3709 case MethodRecognizer::kMathAtan2: | 3730 case MethodRecognizer::kMathAtan2: |
3710 return InlineMathCFunction(flow_graph, call, kind, entry, last); | 3731 return InlineMathCFunction(flow_graph, call, kind, entry, last); |
3711 | 3732 |
3712 case MethodRecognizer::kObjectConstructor: { | 3733 case MethodRecognizer::kObjectConstructor: { |
3713 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3734 *entry = new (Z) |
3714 call->GetBlock()->try_index()); | 3735 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3736 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3715 (*entry)->InheritDeoptTarget(Z, call); | 3737 (*entry)->InheritDeoptTarget(Z, call); |
3716 ASSERT(!call->HasUses()); | 3738 ASSERT(!call->HasUses()); |
3717 *last = NULL; // Empty body. | 3739 *last = NULL; // Empty body. |
3718 return true; | 3740 return true; |
3719 } | 3741 } |
3720 | 3742 |
3721 case MethodRecognizer::kObjectArrayAllocate: { | 3743 case MethodRecognizer::kObjectArrayAllocate: { |
3722 Value* num_elements = new (Z) Value(call->ArgumentAt(1)); | 3744 Value* num_elements = new (Z) Value(call->ArgumentAt(1)); |
3723 if (num_elements->BindsToConstant() && | 3745 if (num_elements->BindsToConstant() && |
3724 num_elements->BoundConstant().IsSmi()) { | 3746 num_elements->BoundConstant().IsSmi()) { |
3725 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 3747 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
3726 if (length >= 0 && length <= Array::kMaxElements) { | 3748 if (length >= 0 && length <= Array::kMaxElements) { |
3727 Value* type = new (Z) Value(call->ArgumentAt(0)); | 3749 Value* type = new (Z) Value(call->ArgumentAt(0)); |
3728 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3750 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
3729 call->GetBlock()->try_index()); | 3751 call->GetBlock()->try_index(), |
| 3752 Thread::kNoDeoptId); |
3730 (*entry)->InheritDeoptTarget(Z, call); | 3753 (*entry)->InheritDeoptTarget(Z, call); |
3731 *last = | 3754 *last = new (Z) CreateArrayInstr(call->token_pos(), type, |
3732 new (Z) CreateArrayInstr(call->token_pos(), type, num_elements); | 3755 num_elements, Thread::kNoDeoptId); |
3733 flow_graph->AppendTo( | 3756 flow_graph->AppendTo( |
3734 *entry, *last, | 3757 *entry, *last, |
3735 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3758 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3736 FlowGraph::kValue); | 3759 FlowGraph::kValue); |
3737 return true; | 3760 return true; |
3738 } | 3761 } |
3739 } | 3762 } |
3740 return false; | 3763 return false; |
3741 } | 3764 } |
3742 | 3765 |
3743 case MethodRecognizer::kObjectRuntimeType: { | 3766 case MethodRecognizer::kObjectRuntimeType: { |
3744 Type& type = Type::ZoneHandle(Z); | 3767 Type& type = Type::ZoneHandle(Z); |
3745 if (RawObject::IsStringClassId(receiver_cid)) { | 3768 if (RawObject::IsStringClassId(receiver_cid)) { |
3746 type = Type::StringType(); | 3769 type = Type::StringType(); |
3747 } else if (receiver_cid == kDoubleCid) { | 3770 } else if (receiver_cid == kDoubleCid) { |
3748 type = Type::Double(); | 3771 type = Type::Double(); |
3749 } else if (RawObject::IsIntegerClassId(receiver_cid)) { | 3772 } else if (RawObject::IsIntegerClassId(receiver_cid)) { |
3750 type = Type::IntType(); | 3773 type = Type::IntType(); |
3751 } else if (receiver_cid != kClosureCid) { | 3774 } else if (receiver_cid != kClosureCid) { |
3752 const Class& cls = Class::Handle( | 3775 const Class& cls = Class::Handle( |
3753 Z, flow_graph->isolate()->class_table()->At(receiver_cid)); | 3776 Z, flow_graph->isolate()->class_table()->At(receiver_cid)); |
3754 if (!cls.IsGeneric()) { | 3777 if (!cls.IsGeneric()) { |
3755 type = cls.CanonicalType(); | 3778 type = cls.CanonicalType(); |
3756 } | 3779 } |
3757 } | 3780 } |
3758 | 3781 |
3759 if (!type.IsNull()) { | 3782 if (!type.IsNull()) { |
3760 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3783 *entry = new (Z) |
3761 call->GetBlock()->try_index()); | 3784 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3785 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3762 (*entry)->InheritDeoptTarget(Z, call); | 3786 (*entry)->InheritDeoptTarget(Z, call); |
3763 *last = new (Z) ConstantInstr(type); | 3787 *last = new (Z) ConstantInstr(type); |
3764 flow_graph->AppendTo( | 3788 flow_graph->AppendTo( |
3765 *entry, *last, | 3789 *entry, *last, |
3766 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3790 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3767 FlowGraph::kValue); | 3791 FlowGraph::kValue); |
3768 return true; | 3792 return true; |
3769 } | 3793 } |
3770 return false; | 3794 return false; |
3771 } | 3795 } |
3772 | 3796 |
3773 case MethodRecognizer::kOneByteStringSetAt: { | 3797 case MethodRecognizer::kOneByteStringSetAt: { |
3774 // This is an internal method, no need to check argument types nor | 3798 // This is an internal method, no need to check argument types nor |
3775 // range. | 3799 // range. |
3776 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 3800 *entry = new (Z) |
3777 call->GetBlock()->try_index()); | 3801 TargetEntryInstr(flow_graph->allocate_block_id(), |
| 3802 call->GetBlock()->try_index(), Thread::kNoDeoptId); |
3778 (*entry)->InheritDeoptTarget(Z, call); | 3803 (*entry)->InheritDeoptTarget(Z, call); |
3779 Definition* str = call->ArgumentAt(0); | 3804 Definition* str = call->ArgumentAt(0); |
3780 Definition* index = call->ArgumentAt(1); | 3805 Definition* index = call->ArgumentAt(1); |
3781 Definition* value = call->ArgumentAt(2); | 3806 Definition* value = call->ArgumentAt(2); |
3782 *last = | 3807 *last = |
3783 new (Z) StoreIndexedInstr(new (Z) Value(str), new (Z) Value(index), | 3808 new (Z) StoreIndexedInstr(new (Z) Value(str), new (Z) Value(index), |
3784 new (Z) Value(value), kNoStoreBarrier, | 3809 new (Z) Value(value), kNoStoreBarrier, |
3785 1, // Index scale | 3810 1, // Index scale |
3786 kOneByteStringCid, kAlignedAccess, | 3811 kOneByteStringCid, kAlignedAccess, |
3787 call->deopt_id(), call->token_pos()); | 3812 call->deopt_id(), call->token_pos()); |
3788 flow_graph->AppendTo( | 3813 flow_graph->AppendTo( |
3789 *entry, *last, | 3814 *entry, *last, |
3790 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, | 3815 call->deopt_id() != Thread::kNoDeoptId ? call->env() : NULL, |
3791 FlowGraph::kEffect); | 3816 FlowGraph::kEffect); |
3792 return true; | 3817 return true; |
3793 } | 3818 } |
3794 | 3819 |
3795 default: | 3820 default: |
3796 return false; | 3821 return false; |
3797 } | 3822 } |
3798 } | 3823 } |
3799 | 3824 |
3800 | 3825 |
3801 } // namespace dart | 3826 } // namespace dart |
3802 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 3827 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
OLD | NEW |