| 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 |