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