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

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

Issue 2412653002: VM Propagate receiver type from calls to unique selectors in AOT compilation. (Closed)
Patch Set: addressed comments, added test 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
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 static bool CanUnboxDouble() { 47 static bool CanUnboxDouble() {
48 return FlowGraphCompiler::SupportsUnboxedDoubles(); 48 return FlowGraphCompiler::SupportsUnboxedDoubles();
49 } 49 }
50 50
51 51
52 static bool CanConvertUnboxedMintToDouble() { 52 static bool CanConvertUnboxedMintToDouble() {
53 return FlowGraphCompiler::CanConvertUnboxedMintToDouble(); 53 return FlowGraphCompiler::CanConvertUnboxedMintToDouble();
54 } 54 }
55 55
56 56
57 // Returns named function that is a unique dynamic target, i.e.,
58 // - the target is identified by its name alone, since it occurs only once.
59 // - target's class has no subclasses, and neither is subclassed, i.e.,
60 // the receiver type can be only the function's class.
61 // Returns Function::null() if there is no unique dynamic target for
62 // given 'fname'. 'fname' must be a symbol.
63 static void GetUniqueDynamicTarget(Isolate* isolate,
64 const String& fname,
65 Object* function) {
66 UniqueFunctionsSet functions_set(
67 isolate->object_store()->unique_dynamic_targets());
68 ASSERT(fname.IsSymbol());
69 *function = functions_set.GetOrNull(fname);
70 ASSERT(functions_set.Release().raw() ==
71 isolate->object_store()->unique_dynamic_targets());
72 }
73
74
75 AotOptimizer::AotOptimizer(FlowGraph* flow_graph,
76 bool use_speculative_inlining,
77 GrowableArray<intptr_t>* inlining_black_list)
78 : FlowGraphVisitor(flow_graph->reverse_postorder()),
79 flow_graph_(flow_graph),
80 use_speculative_inlining_(use_speculative_inlining),
81 inlining_black_list_(inlining_black_list),
82 has_unique_no_such_method_(false) {
83 ASSERT(!use_speculative_inlining || (inlining_black_list != NULL));
84 Function& target_function = Function::Handle();
85 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
86 GetUniqueDynamicTarget(
87 isolate(), Symbols::NoSuchMethod(), &target_function);
88 has_unique_no_such_method_ = !target_function.IsNull();
89 }
90 }
91
92
57 // Optimize instance calls using ICData. 93 // Optimize instance calls using ICData.
58 void AotOptimizer::ApplyICData() { 94 void AotOptimizer::ApplyICData() {
59 VisitBlocks(); 95 VisitBlocks();
60 } 96 }
61 97
62 98
63 void AotOptimizer::PopulateWithICData() { 99 void AotOptimizer::PopulateWithICData() {
64 ASSERT(current_iterator_ == NULL); 100 ASSERT(current_iterator_ == NULL);
65 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 101 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
66 !block_it.Done(); 102 !block_it.Done();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 } 152 }
117 } 153 }
118 154
119 155
120 // TODO(srdjan): Test/support other number types as well. 156 // TODO(srdjan): Test/support other number types as well.
121 static bool IsNumberCid(intptr_t cid) { 157 static bool IsNumberCid(intptr_t cid) {
122 return (cid == kSmiCid) || (cid == kDoubleCid); 158 return (cid == kSmiCid) || (cid == kDoubleCid);
123 } 159 }
124 160
125 161
126 // Returns named function that is a unique dynamic target, i.e.,
127 // - the target is identified by its name alone, since it occurs only once.
128 // - target's class has no subclasses, and neither is subclassed, i.e.,
129 // the receiver type can be only the function's class.
130 // Returns Function::null() if there is no unique dynamic target for
131 // given 'fname'. 'fname' must be a symbol.
132 static void GetUniqueDynamicTarget(Isolate* isolate,
133 const String& fname,
134 Object* function) {
135 UniqueFunctionsSet functions_set(
136 isolate->object_store()->unique_dynamic_targets());
137 ASSERT(fname.IsSymbol());
138 *function = functions_set.GetOrNull(fname);
139 ASSERT(functions_set.Release().raw() ==
140 isolate->object_store()->unique_dynamic_targets());
141 }
142
143
144 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { 162 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
145 ASSERT(call->HasICData()); 163 ASSERT(call->HasICData());
146 if (call->ic_data()->NumberOfUsedChecks() > 0) { 164 if (call->ic_data()->NumberOfUsedChecks() > 0) {
147 // This occurs when an instance call has too many checks, will be converted 165 // This occurs when an instance call has too many checks, will be converted
148 // to megamorphic call. 166 // to megamorphic call.
149 return false; 167 return false;
150 } 168 }
151 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); 169 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
152 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); 170 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
153 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { 171 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 238
221 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { 239 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
222 // Check if the target is unique. 240 // Check if the target is unique.
223 Function& target_function = Function::Handle(Z); 241 Function& target_function = Function::Handle(Z);
224 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); 242 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function);
225 // Calls with named arguments must be resolved/checked at runtime. 243 // Calls with named arguments must be resolved/checked at runtime.
226 if (!target_function.IsNull() && 244 if (!target_function.IsNull() &&
227 !target_function.HasOptionalNamedParameters() && 245 !target_function.HasOptionalNamedParameters() &&
228 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, 246 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0,
229 /* error_message = */ NULL)) { 247 /* error_message = */ NULL)) {
230 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id(); 248 const Class& cls = Class::Handle(Z, target_function.Owner());
231 const ICData& ic_data = ICData::ZoneHandle(Z, 249 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
232 ICData::NewFrom(*call->ic_data(), 1)); 250 const ICData& ic_data = ICData::ZoneHandle(Z,
233 ic_data.AddReceiverCheck(cid, target_function); 251 ICData::NewFrom(*call->ic_data(), 1));
234 call->set_ic_data(&ic_data); 252 ic_data.AddReceiverCheck(cls.id(), target_function);
235 return true; 253 call->set_ic_data(&ic_data);
254 if (has_unique_no_such_method_) {
255 call->set_has_unique_selector(true);
256 }
257 return true;
258 }
236 } 259 }
237 } 260 }
238 261
239 return false; 262 return false;
240 } 263 }
241 264
242 265
243 const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data, 266 const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data,
244 intptr_t cid) { 267 intptr_t cid) {
245 ASSERT(ic_data.NumArgsTested() == 1); 268 ASSERT(ic_data.NumArgsTested() == 1);
(...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 PolymorphicInstanceCallInstr* call = 2011 PolymorphicInstanceCallInstr* call =
1989 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 2012 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
1990 /* with_checks = */ true, 2013 /* with_checks = */ true,
1991 /* complete = */ false); 2014 /* complete = */ false);
1992 instr->ReplaceWith(call, current_iterator()); 2015 instr->ReplaceWith(call, current_iterator());
1993 return; 2016 return;
1994 } 2017 }
1995 } 2018 }
1996 2019
1997 2020
2021 void AotOptimizer::VisitPolymorphicInstanceCall(
2022 PolymorphicInstanceCallInstr* call) {
2023 if (call->with_checks()) {
2024 const intptr_t receiver_cid =
2025 call->PushArgumentAt(0)->value()->Type()->ToCid();
2026 if (receiver_cid != kDynamicCid) {
2027 const Class& receiver_class = Class::Handle(Z,
2028 isolate()->class_table()->At(receiver_cid));
2029
2030 const Array& args_desc_array = Array::Handle(Z,
2031 ArgumentsDescriptor::New(call->ArgumentCount(),
2032 call->instance_call()->argument_names()));
2033 ArgumentsDescriptor args_desc(args_desc_array);
2034 const Function& function = Function::Handle(Z,
2035 Resolver::ResolveDynamicForReceiverClass(
2036 receiver_class,
2037 call->instance_call()->function_name(),
2038 args_desc));
2039 if (!function.IsNull()) {
2040 call->set_with_checks(false);
2041 }
2042 }
2043 }
2044 }
2045
2046
1998 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { 2047 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) {
1999 if (!IsAllowedForInlining(call->deopt_id())) { 2048 if (!IsAllowedForInlining(call->deopt_id())) {
2000 // Inlining disabled after a speculative inlining attempt. 2049 // Inlining disabled after a speculative inlining attempt.
2001 return; 2050 return;
2002 } 2051 }
2003 MethodRecognizer::Kind recognized_kind = 2052 MethodRecognizer::Kind recognized_kind =
2004 MethodRecognizer::RecognizeKind(call->function()); 2053 MethodRecognizer::RecognizeKind(call->function());
2005 switch (recognized_kind) { 2054 switch (recognized_kind) {
2006 case MethodRecognizer::kObjectConstructor: 2055 case MethodRecognizer::kObjectConstructor:
2007 case MethodRecognizer::kObjectArrayAllocate: 2056 case MethodRecognizer::kObjectArrayAllocate:
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
2178 check->env(), FlowGraph::kEffect); 2227 check->env(), FlowGraph::kEffect);
2179 current_iterator()->RemoveCurrentFromGraph(); 2228 current_iterator()->RemoveCurrentFromGraph();
2180 } 2229 }
2181 } 2230 }
2182 } 2231 }
2183 } 2232 }
2184 2233
2185 #endif // DART_PRECOMPILER 2234 #endif // DART_PRECOMPILER
2186 2235
2187 } // namespace dart 2236 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698