Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: runtime/vm/flow_graph_inliner.cc

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

Powered by Google App Engine
This is Rietveld 408576698