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

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

Issue 2379733002: Recognize and optimize a.runtimeType == b.runtimeType pattern. (Closed)
Patch Set: Done Created 4 years, 2 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
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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 call->checked_argument_count(), false)); 81 call->checked_argument_count(), false));
82 call->set_ic_data(&ic_data); 82 call->set_ic_data(&ic_data);
83 } 83 }
84 } 84 }
85 } 85 }
86 current_iterator_ = NULL; 86 current_iterator_ = NULL;
87 } 87 }
88 } 88 }
89 89
90 90
91 bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) {
92 if ((precompiler_ == NULL) || !precompiler_->get_runtime_type_is_unique()) {
93 return false;
94 }
95
96 if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) {
97 return false;
98 }
99
100 // There is only a single function Object.get:runtimeType that can be invoked
101 // by this call. Convert dynamic invocation to a static one.
102 const Class& cls =
103 Class::Handle(Z, thread()->isolate()->object_store()->object_class());
siva 2016/09/29 02:28:20 there seems to be an I in this file so I->object_s
Vyacheslav Egorov (Google) 2016/09/29 15:01:43 Done.
104 const Array& args_desc_array = Array::Handle(Z,
105 ArgumentsDescriptor::New(call->ArgumentCount(),
106 call->argument_names()));
107 ArgumentsDescriptor args_desc(args_desc_array);
108 const Function& function = Function::Handle(Z,
109 Resolver::ResolveDynamicForReceiverClass(
110 cls,
111 call->function_name(),
112 args_desc));
113 ASSERT(!function.IsNull());
114
115 ZoneGrowableArray<PushArgumentInstr*>* args =
116 new (Z) ZoneGrowableArray<PushArgumentInstr*>(
117 call->ArgumentCount());
118 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
119 args->Add(call->PushArgumentAt(i));
120 }
121 StaticCallInstr* static_call = new (Z) StaticCallInstr(
122 call->token_pos(),
123 Function::ZoneHandle(Z, function.raw()),
124 call->argument_names(),
125 args,
126 call->deopt_id());
127 static_call->set_result_cid(kTypeCid);
128 call->ReplaceWith(static_call, current_iterator());
129 return true;
130 }
131
132
91 // Optimize instance calls using cid. This is called after optimizer 133 // Optimize instance calls using cid. This is called after optimizer
92 // converted instance calls to instructions. Any remaining 134 // converted instance calls to instructions. Any remaining
93 // instance calls are either megamorphic calls, cannot be optimized or 135 // instance calls are either megamorphic calls, cannot be optimized or
94 // have no runtime type feedback collected. 136 // have no runtime type feedback collected.
95 // Attempts to convert an instance call (IC call) using propagated class-ids, 137 // Attempts to convert an instance call (IC call) using propagated class-ids,
96 // e.g., receiver class id, guarded-cid, or by guessing cid-s. 138 // e.g., receiver class id, guarded-cid, or by guessing cid-s.
97 void AotOptimizer::ApplyClassIds() { 139 void AotOptimizer::ApplyClassIds() {
98 ASSERT(current_iterator_ == NULL); 140 ASSERT(current_iterator_ == NULL);
99 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 141 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
100 !block_it.Done(); 142 !block_it.Done();
101 block_it.Advance()) { 143 block_it.Advance()) {
102 ForwardInstructionIterator it(block_it.Current()); 144 ForwardInstructionIterator it(block_it.Current());
103 current_iterator_ = &it; 145 current_iterator_ = &it;
104 for (; !it.Done(); it.Advance()) { 146 for (; !it.Done(); it.Advance()) {
105 Instruction* instr = it.Current(); 147 Instruction* instr = it.Current();
106 if (instr->IsInstanceCall()) { 148 if (instr->IsInstanceCall()) {
107 InstanceCallInstr* call = instr->AsInstanceCall(); 149 InstanceCallInstr* call = instr->AsInstanceCall();
108 if (call->HasICData()) { 150 if (RecognizeRuntimeTypeGetter(call)) {
Florian Schneider 2016/09/28 22:49:24 Any reason why this is here and not in AotOptimize
Vyacheslav Egorov (Google) 2016/09/29 00:31:22 Because we will never get into VisitInstanceCall i
Florian Schneider 2016/09/29 18:03:28 Yes, I meant that the ApplyICData phase always vis
Vyacheslav Egorov (Google) 2016/09/30 09:56:28 Fair enough. Moved it into VisitInstanceCall.
151 continue;
152 } else if (call->HasICData()) {
109 if (TryCreateICData(call)) { 153 if (TryCreateICData(call)) {
110 VisitInstanceCall(call); 154 VisitInstanceCall(call);
111 } 155 }
112 } 156 }
113 } 157 }
114 } 158 }
115 current_iterator_ = NULL; 159 current_iterator_ = NULL;
116 } 160 }
117 } 161 }
118 162
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 to_remove_right->RemoveFromGraph(); 643 to_remove_right->RemoveFromGraph();
600 } 644 }
601 return true; 645 return true;
602 } 646 }
603 return false; 647 return false;
604 } 648 }
605 649
606 650
607 static bool SmiFitsInDouble() { return kSmiBits < 53; } 651 static bool SmiFitsInDouble() { return kSmiBits < 53; }
608 652
653 static bool IsGetRuntimeType(Definition* defn) {
654 StaticCallInstr* call = defn->AsStaticCall();
655 return (call != NULL) &&
656 (call->function().recognized_kind() ==
657 MethodRecognizer::kObjectRuntimeType);
658 }
659
609 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 660 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
610 Token::Kind op_kind) { 661 Token::Kind op_kind) {
611 const ICData& ic_data = *call->ic_data(); 662 const ICData& ic_data = *call->ic_data();
612 ASSERT(ic_data.NumArgsTested() == 2); 663 ASSERT(ic_data.NumArgsTested() == 2);
613 664
614 ASSERT(call->ArgumentCount() == 2); 665 ASSERT(call->ArgumentCount() == 2);
615 Definition* left = call->ArgumentAt(0); 666 Definition* left = call->ArgumentAt(0);
616 Definition* right = call->ArgumentAt(1); 667 Definition* right = call->ArgumentAt(1);
617 668
669 // Recognize a.runtimeType == b.runtimeType and fold it into
670 // Object._haveSameRuntimeType(a, b).
671 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
672 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
673 const Class& cls =
674 Class::Handle(Z, thread()->isolate()->object_store()->object_class());
siva 2016/09/29 02:28:20 Ditto comment about I
Vyacheslav Egorov (Google) 2016/09/29 15:01:43 Done.
675 const Function& hasSameRuntimeType = Function::ZoneHandle(Z,
676 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
677 ASSERT(!hasSameRuntimeType.IsNull());
678
679 ZoneGrowableArray<PushArgumentInstr*>* args =
680 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
681 PushArgumentInstr* arg = new (Z) PushArgumentInstr(
682 new (Z) Value(left->ArgumentAt(0)));
683 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
684 args->Add(arg);
685 arg = new (Z) PushArgumentInstr(
686 new (Z) Value(right->ArgumentAt(0)));
687 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
688 args->Add(arg);
689 StaticCallInstr* static_call = new (Z) StaticCallInstr(
690 call->token_pos(),
691 hasSameRuntimeType,
692 Object::null_array(), // argument_names
693 args,
694 call->deopt_id());
695 static_call->set_result_cid(kBoolCid);
696 ReplaceCall(call, static_call);
697 return true;
698 }
699
618 intptr_t cid = kIllegalCid; 700 intptr_t cid = kIllegalCid;
619 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 701 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
620 if (TryStringLengthOneEquality(call, op_kind)) { 702 return TryStringLengthOneEquality(call, op_kind);
621 return true;
622 } else {
623 return false;
624 }
625 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { 703 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
626 InsertBefore(call, 704 InsertBefore(call,
627 new(Z) CheckSmiInstr(new(Z) Value(left), 705 new(Z) CheckSmiInstr(new(Z) Value(left),
628 call->deopt_id(), 706 call->deopt_id(),
629 call->token_pos()), 707 call->token_pos()),
630 call->env(), 708 call->env(),
631 FlowGraph::kEffect); 709 FlowGraph::kEffect);
632 InsertBefore(call, 710 InsertBefore(call,
633 new(Z) CheckSmiInstr(new(Z) Value(right), 711 new(Z) CheckSmiInstr(new(Z) Value(right),
634 call->deopt_id(), 712 call->deopt_id(),
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after
2178 check->env(), FlowGraph::kEffect); 2256 check->env(), FlowGraph::kEffect);
2179 current_iterator()->RemoveCurrentFromGraph(); 2257 current_iterator()->RemoveCurrentFromGraph();
2180 } 2258 }
2181 } 2259 }
2182 } 2260 }
2183 } 2261 }
2184 2262
2185 #endif // DART_PRECOMPILER 2263 #endif // DART_PRECOMPILER
2186 2264
2187 } // namespace dart 2265 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698