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

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

Issue 2900963008: Reapply "Shuffle around deopt id allocation... (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 = 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
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