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

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

Issue 2891713002: Cleanup: Make CheckClassId instruction more general so it (Closed)
Patch Set: Feedback from Martin 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_compiler_x64.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('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 1526 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 } 1537 }
1538 } 1538 }
1539 1539
1540 return false; 1540 return false;
1541 } 1541 }
1542 1542
1543 1543
1544 bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) { 1544 bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) {
1545 if ((!FLAG_precompiled_mode || 1545 if ((!FLAG_precompiled_mode ||
1546 owner_->inliner_->use_speculative_inlining()) && 1546 owner_->inliner_->use_speculative_inlining()) &&
1547 target_info.cid_start == target_info.cid_end && 1547 target_info.IsSingleCid() &&
1548 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { 1548 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) {
1549 owner_->inlined_ = true; 1549 owner_->inlined_ = true;
1550 return true; 1550 return true;
1551 } 1551 }
1552 1552
1553 GrowableArray<Value*> arguments(call_->ArgumentCount()); 1553 GrowableArray<Value*> arguments(call_->ArgumentCount());
1554 for (int i = 0; i < call_->ArgumentCount(); ++i) { 1554 for (int i = 0; i < call_->ArgumentCount(); ++i) {
1555 arguments.Add(call_->PushArgumentAt(i)->value()); 1555 arguments.Add(call_->PushArgumentAt(i)->value());
1556 } 1556 }
1557 InlinedCallData call_data(call_, &arguments, caller_function_, 1557 InlinedCallData call_data(call_, &arguments, caller_function_,
(...skipping 10 matching lines...) Expand all
1568 exit_collector_->Union(call_data.exit_collector); 1568 exit_collector_->Union(call_data.exit_collector);
1569 1569
1570 // Replace parameter stubs and constants. Replace the receiver argument 1570 // Replace parameter stubs and constants. Replace the receiver argument
1571 // with a redefinition to prevent code from the inlined body from being 1571 // with a redefinition to prevent code from the inlined body from being
1572 // hoisted above the inlined entry. 1572 // hoisted above the inlined entry.
1573 ASSERT(arguments.length() > 0); 1573 ASSERT(arguments.length() > 0);
1574 Value* actual = arguments[0]; 1574 Value* actual = arguments[0];
1575 RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z)); 1575 RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z));
1576 redefinition->set_ssa_temp_index( 1576 redefinition->set_ssa_temp_index(
1577 owner_->caller_graph()->alloc_ssa_temp_index()); 1577 owner_->caller_graph()->alloc_ssa_temp_index());
1578 if (target_info.cid_start == target_info.cid_end) { 1578 if (target_info.IsSingleCid()) {
1579 redefinition->UpdateType(CompileType::FromCid(target_info.cid_start)); 1579 redefinition->UpdateType(CompileType::FromCid(target_info.cid_start));
1580 } 1580 }
1581 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry()); 1581 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry());
1582 Definition* stub = (*call_data.parameter_stubs)[0]; 1582 Definition* stub = (*call_data.parameter_stubs)[0];
1583 stub->ReplaceUsesWith(redefinition); 1583 stub->ReplaceUsesWith(redefinition);
1584 1584
1585 for (intptr_t i = 1; i < arguments.length(); ++i) { 1585 for (intptr_t i = 1; i < arguments.length(); ++i) {
1586 actual = arguments[i]; 1586 actual = arguments[i];
1587 if (actual != NULL) { 1587 if (actual != NULL) {
1588 stub = (*call_data.parameter_stubs)[i]; 1588 stub = (*call_data.parameter_stubs)[i];
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 BlockEntryInstr* current_block = entry; 1687 BlockEntryInstr* current_block = entry;
1688 Instruction* cursor = entry; 1688 Instruction* cursor = entry;
1689 1689
1690 Definition* receiver = call_->ArgumentAt(0); 1690 Definition* receiver = call_->ArgumentAt(0);
1691 // There are at least two variants including non-inlined ones, so we have 1691 // There are at least two variants including non-inlined ones, so we have
1692 // at least one branch on the class id. 1692 // at least one branch on the class id.
1693 LoadClassIdInstr* load_cid = 1693 LoadClassIdInstr* load_cid =
1694 new (Z) LoadClassIdInstr(new (Z) Value(receiver)); 1694 new (Z) LoadClassIdInstr(new (Z) Value(receiver));
1695 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index()); 1695 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index());
1696 cursor = AppendInstruction(cursor, load_cid); 1696 cursor = AppendInstruction(cursor, load_cid);
1697 bool follow_with_deopt = false;
1698 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) { 1697 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
1699 const CidRange& variant = inlined_variants_[i]; 1698 const CidRange& variant = inlined_variants_[i];
1700 bool test_is_range = (variant.cid_start != variant.cid_end); 1699 bool test_is_range = !variant.IsSingleCid();
1701 bool is_last_test = (i == inlined_variants_.length() - 1); 1700 bool is_last_test = (i == inlined_variants_.length() - 1);
1702 // 1. Guard the body with a class id check. We don't need any check if 1701 // 1. Guard the body with a class id check. We don't need any check if
1703 // it's the last test and global analysis has told us that the call is 1702 // it's the last test and global analysis has told us that the call is
1704 // complete. TODO(erikcorry): Enhance CheckClassIdInstr so it can take an 1703 // complete.
1705 // arbitrary CidRangeTarget. Currently we don't go into this branch if the 1704 if (is_last_test && non_inlined_variants_->is_empty()) {
1706 // last test is a range test - instead we set the follow_with_deopt flag.
1707 if (is_last_test && (!test_is_range || call_->complete()) &&
1708 non_inlined_variants_->is_empty()) {
1709 // If it is the last variant use a check class id instruction which can 1705 // If it is the last variant use a check class id instruction which can
1710 // deoptimize, followed unconditionally by the body. Omit the check if 1706 // deoptimize, followed unconditionally by the body. Omit the check if
1711 // we know that we have covered all possible classes. 1707 // we know that we have covered all possible classes.
1712 if (!call_->complete()) { 1708 if (!call_->complete()) {
1713 ASSERT(!test_is_range); // See condition above.
1714 RedefinitionInstr* cid_redefinition = 1709 RedefinitionInstr* cid_redefinition =
1715 new RedefinitionInstr(new (Z) Value(load_cid)); 1710 new RedefinitionInstr(new (Z) Value(load_cid));
1716 cid_redefinition->set_ssa_temp_index( 1711 cid_redefinition->set_ssa_temp_index(
1717 owner_->caller_graph()->alloc_ssa_temp_index()); 1712 owner_->caller_graph()->alloc_ssa_temp_index());
1718 cursor = AppendInstruction(cursor, cid_redefinition); 1713 cursor = AppendInstruction(cursor, cid_redefinition);
1719 CheckClassIdInstr* check_class_id = 1714 CheckClassIdInstr* check_class_id = new (Z) CheckClassIdInstr(
1720 new (Z) CheckClassIdInstr(new (Z) Value(cid_redefinition), 1715 new (Z) Value(cid_redefinition), variant, call_->deopt_id());
1721 variant.cid_start, call_->deopt_id());
1722 check_class_id->InheritDeoptTarget(zone(), call_); 1716 check_class_id->InheritDeoptTarget(zone(), call_);
1723 cursor = AppendInstruction(cursor, check_class_id); 1717 cursor = AppendInstruction(cursor, check_class_id);
1724 } 1718 }
1725 1719
1726 // The next instruction is the first instruction of the inlined body. 1720 // The next instruction is the first instruction of the inlined body.
1727 // Handle the two possible cases (unshared and shared subsequent 1721 // Handle the two possible cases (unshared and shared subsequent
1728 // predecessors) separately. 1722 // predecessors) separately.
1729 BlockEntryInstr* callee_entry = inlined_entries_[i]; 1723 BlockEntryInstr* callee_entry = inlined_entries_[i];
1730 if (callee_entry->IsGraphEntry()) { 1724 if (callee_entry->IsGraphEntry()) {
1731 // Unshared. Graft the normal entry on after the check class 1725 // Unshared. Graft the normal entry on after the check class
(...skipping 21 matching lines...) Expand all
1753 goto_join->InheritDeoptTarget(zone(), join); 1747 goto_join->InheritDeoptTarget(zone(), join);
1754 cursor->LinkTo(goto_join); 1748 cursor->LinkTo(goto_join);
1755 current_block->set_last_instruction(goto_join); 1749 current_block->set_last_instruction(goto_join);
1756 } else { 1750 } else {
1757 // There is no possibility of a TargetEntry (the first entry to a 1751 // There is no possibility of a TargetEntry (the first entry to a
1758 // shared inlined body) because this is the last inlined entry. 1752 // shared inlined body) because this is the last inlined entry.
1759 UNREACHABLE(); 1753 UNREACHABLE();
1760 } 1754 }
1761 cursor = NULL; 1755 cursor = NULL;
1762 } else { 1756 } else {
1763 if (is_last_test && test_is_range) follow_with_deopt = true;
1764 // For all variants except the last, use a branch on the loaded class 1757 // For all variants except the last, use a branch on the loaded class
1765 // id. 1758 // id.
1766 const Smi& cid = Smi::ZoneHandle(Smi::New(variant.cid_start)); 1759 const Smi& cid = Smi::ZoneHandle(Smi::New(variant.cid_start));
1767 ConstantInstr* cid_constant = owner_->caller_graph()->GetConstant(cid); 1760 ConstantInstr* cid_constant = owner_->caller_graph()->GetConstant(cid);
1768 BranchInstr* branch; 1761 BranchInstr* branch;
1769 BranchInstr* upper_limit_branch = NULL; 1762 BranchInstr* upper_limit_branch = NULL;
1770 BlockEntryInstr* cid_test_entry_block = current_block; 1763 BlockEntryInstr* cid_test_entry_block = current_block;
1771 if (test_is_range) { 1764 if (test_is_range) {
1772 // Double branch for testing a range of Cids. TODO(erikcorry): Make a 1765 // Double branch for testing a range of Cids. TODO(erikcorry): Make a
1773 // special instruction that uses subtraction and unsigned comparison to 1766 // special instruction that uses subtraction and unsigned comparison to
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1900 fallback_call->set_total_call_count(call_->CallCount()); 1893 fallback_call->set_total_call_count(call_->CallCount());
1901 ReturnInstr* fallback_return = new ReturnInstr( 1894 ReturnInstr* fallback_return = new ReturnInstr(
1902 call_->instance_call()->token_pos(), new Value(fallback_call)); 1895 call_->instance_call()->token_pos(), new Value(fallback_call));
1903 fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_, 1896 fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_,
1904 fallback_call); 1897 fallback_call);
1905 AppendInstruction(AppendInstruction(cursor, fallback_call), 1898 AppendInstruction(AppendInstruction(cursor, fallback_call),
1906 fallback_return); 1899 fallback_return);
1907 exit_collector_->AddExit(fallback_return); 1900 exit_collector_->AddExit(fallback_return);
1908 cursor = NULL; 1901 cursor = NULL;
1909 } else { 1902 } else {
1910 if (follow_with_deopt) {
1911 DeoptimizeInstr* deopt = new DeoptimizeInstr(
1912 ICData::kDeoptPolymorphicInstanceCallTestFail, call_->deopt_id());
1913 deopt->InheritDeoptTarget(zone(), call_);
1914 cursor = AppendInstruction(cursor, deopt);
1915 cursor = NULL;
1916 }
1917
1918 // Remove push arguments of the call. 1903 // Remove push arguments of the call.
1919 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { 1904 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) {
1920 PushArgumentInstr* push = call_->PushArgumentAt(i); 1905 PushArgumentInstr* push = call_->PushArgumentAt(i);
1921 push->ReplaceUsesWith(push->value()->definition()); 1906 push->ReplaceUsesWith(push->value()->definition());
1922 push->RemoveFromGraph(); 1907 push->RemoveFromGraph();
1923 } 1908 }
1924 } 1909 }
1925 return entry; 1910 return entry;
1926 } 1911 }
1927 1912
(...skipping 1855 matching lines...) Expand 10 before | Expand all | Expand 10 after
3783 } 3768 }
3784 3769
3785 default: 3770 default:
3786 return false; 3771 return false;
3787 } 3772 }
3788 } 3773 }
3789 3774
3790 3775
3791 } // namespace dart 3776 } // namespace dart
3792 #endif // !defined(DART_PRECOMPILED_RUNTIME) 3777 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698