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

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

Issue 2451893002: Revert "Recognize and optimize a.runtimeType == b.runtimeType pattern." (Closed)
Patch Set: Created 4 years, 1 month 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/aot_optimizer.h ('k') | runtime/vm/bootstrap_natives.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 4
5 #include "vm/aot_optimizer.h" 5 #include "vm/aot_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 Object* function) { 65 Object* function) {
66 UniqueFunctionsSet functions_set( 66 UniqueFunctionsSet functions_set(
67 isolate->object_store()->unique_dynamic_targets()); 67 isolate->object_store()->unique_dynamic_targets());
68 ASSERT(fname.IsSymbol()); 68 ASSERT(fname.IsSymbol());
69 *function = functions_set.GetOrNull(fname); 69 *function = functions_set.GetOrNull(fname);
70 ASSERT(functions_set.Release().raw() == 70 ASSERT(functions_set.Release().raw() ==
71 isolate->object_store()->unique_dynamic_targets()); 71 isolate->object_store()->unique_dynamic_targets());
72 } 72 }
73 73
74 74
75 AotOptimizer::AotOptimizer(Precompiler* precompiler, 75 AotOptimizer::AotOptimizer(FlowGraph* flow_graph,
76 FlowGraph* flow_graph,
77 bool use_speculative_inlining, 76 bool use_speculative_inlining,
78 GrowableArray<intptr_t>* inlining_black_list) 77 GrowableArray<intptr_t>* inlining_black_list)
79 : FlowGraphVisitor(flow_graph->reverse_postorder()), 78 : FlowGraphVisitor(flow_graph->reverse_postorder()),
80 precompiler_(precompiler),
81 flow_graph_(flow_graph), 79 flow_graph_(flow_graph),
82 use_speculative_inlining_(use_speculative_inlining), 80 use_speculative_inlining_(use_speculative_inlining),
83 inlining_black_list_(inlining_black_list), 81 inlining_black_list_(inlining_black_list),
84 has_unique_no_such_method_(false) { 82 has_unique_no_such_method_(false) {
85 ASSERT(!use_speculative_inlining || (inlining_black_list != NULL)); 83 ASSERT(!use_speculative_inlining || (inlining_black_list != NULL));
86 Function& target_function = Function::Handle(); 84 Function& target_function = Function::Handle();
87 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { 85 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
88 GetUniqueDynamicTarget( 86 GetUniqueDynamicTarget(
89 isolate(), Symbols::NoSuchMethod(), &target_function); 87 isolate(), Symbols::NoSuchMethod(), &target_function);
90 has_unique_no_such_method_ = !target_function.IsNull(); 88 has_unique_no_such_method_ = !target_function.IsNull();
(...skipping 28 matching lines...) Expand all
119 call->checked_argument_count(), false)); 117 call->checked_argument_count(), false));
120 call->set_ic_data(&ic_data); 118 call->set_ic_data(&ic_data);
121 } 119 }
122 } 120 }
123 } 121 }
124 current_iterator_ = NULL; 122 current_iterator_ = NULL;
125 } 123 }
126 } 124 }
127 125
128 126
129 bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) {
130 if ((precompiler_ == NULL) || !precompiler_->get_runtime_type_is_unique()) {
131 return false;
132 }
133
134 if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) {
135 return false;
136 }
137
138 // There is only a single function Object.get:runtimeType that can be invoked
139 // by this call. Convert dynamic invocation to a static one.
140 const Class& cls = Class::Handle(Z, I->object_store()->object_class());
141 const Array& args_desc_array = Array::Handle(Z,
142 ArgumentsDescriptor::New(call->ArgumentCount(),
143 call->argument_names()));
144 ArgumentsDescriptor args_desc(args_desc_array);
145 const Function& function = Function::Handle(Z,
146 Resolver::ResolveDynamicForReceiverClass(
147 cls,
148 call->function_name(),
149 args_desc));
150 ASSERT(!function.IsNull());
151
152 ZoneGrowableArray<PushArgumentInstr*>* args =
153 new (Z) ZoneGrowableArray<PushArgumentInstr*>(
154 call->ArgumentCount());
155 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
156 args->Add(call->PushArgumentAt(i));
157 }
158 StaticCallInstr* static_call = new (Z) StaticCallInstr(
159 call->token_pos(),
160 Function::ZoneHandle(Z, function.raw()),
161 call->argument_names(),
162 args,
163 call->deopt_id());
164 static_call->set_result_cid(kTypeCid);
165 call->ReplaceWith(static_call, current_iterator());
166 return true;
167 }
168
169
170 // Optimize instance calls using cid. This is called after optimizer 127 // Optimize instance calls using cid. This is called after optimizer
171 // converted instance calls to instructions. Any remaining 128 // converted instance calls to instructions. Any remaining
172 // instance calls are either megamorphic calls, cannot be optimized or 129 // instance calls are either megamorphic calls, cannot be optimized or
173 // have no runtime type feedback collected. 130 // have no runtime type feedback collected.
174 // Attempts to convert an instance call (IC call) using propagated class-ids, 131 // Attempts to convert an instance call (IC call) using propagated class-ids,
175 // e.g., receiver class id, guarded-cid, or by guessing cid-s. 132 // e.g., receiver class id, guarded-cid, or by guessing cid-s.
176 void AotOptimizer::ApplyClassIds() { 133 void AotOptimizer::ApplyClassIds() {
177 ASSERT(current_iterator_ == NULL); 134 ASSERT(current_iterator_ == NULL);
178 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 135 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
179 !block_it.Done(); 136 !block_it.Done();
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 to_remove_right->RemoveFromGraph(); 622 to_remove_right->RemoveFromGraph();
666 } 623 }
667 return true; 624 return true;
668 } 625 }
669 return false; 626 return false;
670 } 627 }
671 628
672 629
673 static bool SmiFitsInDouble() { return kSmiBits < 53; } 630 static bool SmiFitsInDouble() { return kSmiBits < 53; }
674 631
675
676 static bool IsGetRuntimeType(Definition* defn) {
677 StaticCallInstr* call = defn->AsStaticCall();
678 return (call != NULL) &&
679 (call->function().recognized_kind() ==
680 MethodRecognizer::kObjectRuntimeType);
681 }
682
683
684 // Recognize a.runtimeType == b.runtimeType and fold it into
685 // Object._haveSameRuntimeType(a, b).
686 // Note: this optimization is not speculative.
687 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) {
688 const ICData& ic_data = *call->ic_data();
689 ASSERT(ic_data.NumArgsTested() == 2);
690
691 ASSERT(call->ArgumentCount() == 2);
692 Definition* left = call->ArgumentAt(0);
693 Definition* right = call->ArgumentAt(1);
694
695 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
696 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
697 const Class& cls = Class::Handle(Z, I->object_store()->object_class());
698 const Function& have_same_runtime_type = Function::ZoneHandle(Z,
699 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
700 ASSERT(!have_same_runtime_type.IsNull());
701
702 ZoneGrowableArray<PushArgumentInstr*>* args =
703 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
704 PushArgumentInstr* arg = new (Z) PushArgumentInstr(
705 new (Z) Value(left->ArgumentAt(0)));
706 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
707 args->Add(arg);
708 arg = new (Z) PushArgumentInstr(
709 new (Z) Value(right->ArgumentAt(0)));
710 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
711 args->Add(arg);
712 StaticCallInstr* static_call = new (Z) StaticCallInstr(
713 call->token_pos(),
714 have_same_runtime_type,
715 Object::null_array(), // argument_names
716 args,
717 call->deopt_id());
718 static_call->set_result_cid(kBoolCid);
719 ReplaceCall(call, static_call);
720 return true;
721 }
722
723 return false;
724 }
725
726
727 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 632 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
728 Token::Kind op_kind) { 633 Token::Kind op_kind) {
729 const ICData& ic_data = *call->ic_data(); 634 const ICData& ic_data = *call->ic_data();
730 ASSERT(ic_data.NumArgsTested() == 2); 635 ASSERT(ic_data.NumArgsTested() == 2);
731 636
732 ASSERT(call->ArgumentCount() == 2); 637 ASSERT(call->ArgumentCount() == 2);
733 Definition* left = call->ArgumentAt(0); 638 Definition* left = call->ArgumentAt(0);
734 Definition* right = call->ArgumentAt(1); 639 Definition* right = call->ArgumentAt(1);
735 640
736 intptr_t cid = kIllegalCid; 641 intptr_t cid = kIllegalCid;
737 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 642 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
738 return TryStringLengthOneEquality(call, op_kind); 643 if (TryStringLengthOneEquality(call, op_kind)) {
644 return true;
645 } else {
646 return false;
647 }
739 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { 648 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
740 InsertBefore(call, 649 InsertBefore(call,
741 new(Z) CheckSmiInstr(new(Z) Value(left), 650 new(Z) CheckSmiInstr(new(Z) Value(left),
742 call->deopt_id(), 651 call->deopt_id(),
743 call->token_pos()), 652 call->token_pos()),
744 call->env(), 653 call->env(),
745 FlowGraph::kEffect); 654 FlowGraph::kEffect);
746 InsertBefore(call, 655 InsertBefore(call,
747 new(Z) CheckSmiInstr(new(Z) Value(right), 656 new(Z) CheckSmiInstr(new(Z) Value(right),
748 call->deopt_id(), 657 call->deopt_id(),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 const ICData& unary_checks_1 = 703 const ICData& unary_checks_1 =
795 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)); 704 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecksForArgNr(1));
796 AddCheckClass(right, 705 AddCheckClass(right,
797 unary_checks_1, 706 unary_checks_1,
798 call->deopt_id(), 707 call->deopt_id(),
799 call->env(), 708 call->env(),
800 call); 709 call);
801 cid = kSmiCid; 710 cid = kSmiCid;
802 } else { 711 } else {
803 // Shortcut for equality with null. 712 // Shortcut for equality with null.
804 // TODO(vegorov): this optimization is not speculative and should
805 // be hoisted out of this function.
806 ConstantInstr* right_const = right->AsConstant(); 713 ConstantInstr* right_const = right->AsConstant();
807 ConstantInstr* left_const = left->AsConstant(); 714 ConstantInstr* left_const = left->AsConstant();
808 if ((right_const != NULL && right_const->value().IsNull()) || 715 if ((right_const != NULL && right_const->value().IsNull()) ||
809 (left_const != NULL && left_const->value().IsNull())) { 716 (left_const != NULL && left_const->value().IsNull())) {
810 StrictCompareInstr* comp = 717 StrictCompareInstr* comp =
811 new(Z) StrictCompareInstr(call->token_pos(), 718 new(Z) StrictCompareInstr(call->token_pos(),
812 Token::kEQ_STRICT, 719 Token::kEQ_STRICT,
813 new(Z) Value(left), 720 new(Z) Value(left),
814 new(Z) Value(right), 721 new(Z) Value(right),
815 false); // No number check. 722 false); // No number check.
(...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after
1843 } 1750 }
1844 if (Token::IsTypeCastOperator(op_kind)) { 1751 if (Token::IsTypeCastOperator(op_kind)) {
1845 ReplaceWithTypeCast(instr); 1752 ReplaceWithTypeCast(instr);
1846 return; 1753 return;
1847 } 1754 }
1848 1755
1849 if (TryInlineFieldAccess(instr)) { 1756 if (TryInlineFieldAccess(instr)) {
1850 return; 1757 return;
1851 } 1758 }
1852 1759
1853 if (RecognizeRuntimeTypeGetter(instr)) {
1854 return;
1855 }
1856
1857 if ((op_kind == Token::kEQ) && TryReplaceWithHaveSameRuntimeType(instr)) {
1858 return;
1859 }
1860
1861 const ICData& unary_checks = 1760 const ICData& unary_checks =
1862 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); 1761 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
1863 if (IsAllowedForInlining(instr->deopt_id()) && 1762 if (IsAllowedForInlining(instr->deopt_id()) &&
1864 (unary_checks.NumberOfChecks() > 0)) { 1763 (unary_checks.NumberOfChecks() > 0)) {
1865 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { 1764 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
1866 return; 1765 return;
1867 } 1766 }
1868 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { 1767 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) {
1869 return; 1768 return;
1870 } 1769 }
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
2328 check->env(), FlowGraph::kEffect); 2227 check->env(), FlowGraph::kEffect);
2329 current_iterator()->RemoveCurrentFromGraph(); 2228 current_iterator()->RemoveCurrentFromGraph();
2330 } 2229 }
2331 } 2230 }
2332 } 2231 }
2333 } 2232 }
2334 2233
2335 #endif // DART_PRECOMPILER 2234 #endif // DART_PRECOMPILER
2336 2235
2337 } // namespace dart 2236 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/bootstrap_natives.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698