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

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

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