OLD | NEW |
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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "vm/precompiler.h" | 21 #include "vm/precompiler.h" |
22 #include "vm/resolver.h" | 22 #include "vm/resolver.h" |
23 #include "vm/scopes.h" | 23 #include "vm/scopes.h" |
24 #include "vm/stack_frame.h" | 24 #include "vm/stack_frame.h" |
25 #include "vm/symbols.h" | 25 #include "vm/symbols.h" |
26 | 26 |
27 namespace dart { | 27 namespace dart { |
28 | 28 |
29 DEFINE_FLAG(int, getter_setter_ratio, 13, | 29 DEFINE_FLAG(int, getter_setter_ratio, 13, |
30 "Ratio of getter/setter usage used for double field unboxing heuristics"); | 30 "Ratio of getter/setter usage used for double field unboxing heuristics"); |
31 DEFINE_FLAG(bool, guess_other_cid, true, | 31 DEFINE_FLAG(bool, guess_icdata_cid, true, |
32 "Artificially create type feedback for arithmetic etc. operations" | 32 "Artificially create type feedback for arithmetic etc. operations" |
33 " by guessing the other unknown argument cid"); | 33 " by guessing the other unknown argument cid"); |
34 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); | 34 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); |
35 DEFINE_FLAG(bool, dead_store_elimination, true, "Eliminate dead stores"); | 35 DEFINE_FLAG(bool, dead_store_elimination, true, "Eliminate dead stores"); |
36 DEFINE_FLAG(int, max_polymorphic_checks, 4, | 36 DEFINE_FLAG(int, max_polymorphic_checks, 4, |
37 "Maximum number of polymorphic check, otherwise it is megamorphic."); | 37 "Maximum number of polymorphic check, otherwise it is megamorphic."); |
38 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, | 38 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, |
39 "Maximum number of polymorphic checks in equality operator," | 39 "Maximum number of polymorphic checks in equality operator," |
40 " otherwise use megamorphic dispatch."); | 40 " otherwise use megamorphic dispatch."); |
41 DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos"); | 41 DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos"); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 189 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { |
190 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); | 190 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); |
191 } | 191 } |
192 | 192 |
193 const Token::Kind op_kind = call->token_kind(); | 193 const Token::Kind op_kind = call->token_kind(); |
194 if (Token::IsRelationalOperator(op_kind) || | 194 if (Token::IsRelationalOperator(op_kind) || |
195 Token::IsEqualityOperator(op_kind) || | 195 Token::IsEqualityOperator(op_kind) || |
196 Token::IsBinaryOperator(op_kind)) { | 196 Token::IsBinaryOperator(op_kind)) { |
197 // Guess cid: if one of the inputs is a number assume that the other | 197 // Guess cid: if one of the inputs is a number assume that the other |
198 // is a number of same type. | 198 // is a number of same type. |
199 if (FLAG_guess_other_cid) { | 199 if (FLAG_guess_icdata_cid) { |
200 const intptr_t cid_0 = class_ids[0]; | 200 const intptr_t cid_0 = class_ids[0]; |
201 const intptr_t cid_1 = class_ids[1]; | 201 const intptr_t cid_1 = class_ids[1]; |
202 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { | 202 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { |
203 class_ids[0] = cid_1; | 203 class_ids[0] = cid_1; |
204 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { | 204 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { |
205 class_ids[1] = cid_0; | 205 class_ids[1] = cid_0; |
206 } | 206 } |
207 } | 207 } |
208 } | 208 } |
209 | 209 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 if (class_ids.length() > 1) { | 247 if (class_ids.length() > 1) { |
248 ic_data.AddCheck(class_ids, function); | 248 ic_data.AddCheck(class_ids, function); |
249 } else { | 249 } else { |
250 ASSERT(class_ids.length() == 1); | 250 ASSERT(class_ids.length() == 1); |
251 ic_data.AddReceiverCheck(class_ids[0], function); | 251 ic_data.AddReceiverCheck(class_ids[0], function); |
252 } | 252 } |
253 call->set_ic_data(&ic_data); | 253 call->set_ic_data(&ic_data); |
254 return true; | 254 return true; |
255 } | 255 } |
256 | 256 |
| 257 if (Compiler::always_optimize() && |
| 258 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) { |
| 259 // Check if the target is unique. |
| 260 Function& target_function = Function::Handle(Z); |
| 261 Precompiler::GetUniqueDynamicTarget( |
| 262 isolate(), call->function_name(), &target_function); |
| 263 // Calls with named arguments must be resolved/checked at runtime. |
| 264 String& error_message = String::Handle(Z); |
| 265 if (!target_function.IsNull() && |
| 266 !target_function.HasOptionalNamedParameters() && |
| 267 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, |
| 268 &error_message)) { |
| 269 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id(); |
| 270 const ICData& ic_data = ICData::ZoneHandle(Z, |
| 271 ICData::NewFrom(*call->ic_data(), 1)); |
| 272 ic_data.AddReceiverCheck(cid, target_function); |
| 273 call->set_ic_data(&ic_data); |
| 274 return true; |
| 275 } |
| 276 } |
| 277 |
257 // Check if getter or setter in function's class and class is currently leaf. | 278 // Check if getter or setter in function's class and class is currently leaf. |
258 if ((call->token_kind() == Token::kGET) || | 279 if (FLAG_guess_icdata_cid && |
259 (call->token_kind() == Token::kSET)) { | 280 ((call->token_kind() == Token::kGET) || |
| 281 (call->token_kind() == Token::kSET))) { |
260 const Class& owner_class = Class::Handle(Z, function().Owner()); | 282 const Class& owner_class = Class::Handle(Z, function().Owner()); |
261 if (!owner_class.is_abstract() && | 283 if (!owner_class.is_abstract() && |
262 !CHA::HasSubclasses(owner_class) && | 284 !CHA::HasSubclasses(owner_class) && |
263 !CHA::IsImplemented(owner_class)) { | 285 !CHA::IsImplemented(owner_class)) { |
264 const Array& args_desc_array = Array::Handle(Z, | 286 const Array& args_desc_array = Array::Handle(Z, |
265 ArgumentsDescriptor::New(call->ArgumentCount(), | 287 ArgumentsDescriptor::New(call->ArgumentCount(), |
266 call->argument_names())); | 288 call->argument_names())); |
267 ArgumentsDescriptor args_desc(args_desc_array); | 289 ArgumentsDescriptor args_desc(args_desc_array); |
268 const Function& function = Function::Handle(Z, | 290 const Function& function = Function::Handle(Z, |
269 Resolver::ResolveDynamicForReceiverClass(owner_class, | 291 Resolver::ResolveDynamicForReceiverClass(owner_class, |
270 call->function_name(), | 292 call->function_name(), |
271 args_desc)); | 293 args_desc)); |
272 if (!function.IsNull()) { | 294 if (!function.IsNull()) { |
273 const ICData& ic_data = ICData::ZoneHandle(Z, | 295 const ICData& ic_data = ICData::ZoneHandle(Z, |
274 ICData::NewFrom(*call->ic_data(), class_ids.length())); | 296 ICData::NewFrom(*call->ic_data(), class_ids.length())); |
275 ic_data.AddReceiverCheck(owner_class.id(), function); | 297 ic_data.AddReceiverCheck(owner_class.id(), function); |
276 call->set_ic_data(&ic_data); | 298 call->set_ic_data(&ic_data); |
277 return true; | 299 return true; |
278 } | 300 } |
279 } | 301 } |
280 } | 302 } |
281 | 303 |
282 if (FLAG_precompilation && | |
283 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) { | |
284 // Check if the target is unique. | |
285 Function& target_function = Function::Handle(Z); | |
286 Precompiler::GetUniqueDynamicTarget( | |
287 isolate(), call->function_name(), &target_function); | |
288 // Calls with named arguments must be resolved/checked at runtime. | |
289 String& error_message = String::Handle(Z); | |
290 if (!target_function.IsNull() && | |
291 !target_function.HasOptionalNamedParameters() && | |
292 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, | |
293 &error_message)) { | |
294 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id(); | |
295 const ICData& ic_data = ICData::ZoneHandle(Z, | |
296 ICData::NewFrom(*call->ic_data(), 1)); | |
297 ic_data.AddReceiverCheck(cid, target_function); | |
298 call->set_ic_data(&ic_data); | |
299 return true; | |
300 } | |
301 } | |
302 | |
303 return false; | 304 return false; |
304 } | 305 } |
305 | 306 |
306 | 307 |
307 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, | 308 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
308 intptr_t cid) { | 309 intptr_t cid) { |
309 ASSERT(ic_data.NumArgsTested() == 1); | 310 ASSERT(ic_data.NumArgsTested() == 1); |
310 | 311 |
311 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { | 312 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { |
312 return ic_data; // Nothing to do | 313 return ic_data; // Nothing to do |
(...skipping 8540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8853 | 8854 |
8854 // Insert materializations at environment uses. | 8855 // Insert materializations at environment uses. |
8855 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8856 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8856 CreateMaterializationAt( | 8857 CreateMaterializationAt( |
8857 exits_collector_.exits()[i], alloc, *slots); | 8858 exits_collector_.exits()[i], alloc, *slots); |
8858 } | 8859 } |
8859 } | 8860 } |
8860 | 8861 |
8861 | 8862 |
8862 } // namespace dart | 8863 } // namespace dart |
OLD | NEW |