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/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 11 matching lines...) Expand all Loading... |
22 #include "vm/object_store.h" | 22 #include "vm/object_store.h" |
23 #include "vm/parser.h" | 23 #include "vm/parser.h" |
24 #include "vm/precompiler.h" | 24 #include "vm/precompiler.h" |
25 #include "vm/resolver.h" | 25 #include "vm/resolver.h" |
26 #include "vm/scopes.h" | 26 #include "vm/scopes.h" |
27 #include "vm/stack_frame.h" | 27 #include "vm/stack_frame.h" |
28 #include "vm/symbols.h" | 28 #include "vm/symbols.h" |
29 | 29 |
30 namespace dart { | 30 namespace dart { |
31 | 31 |
| 32 DEFINE_FLAG(int, max_exhaustive_polymorphic_checks, 5, |
| 33 "If a call receiver is known to be of at most this many classes, " |
| 34 "generate exhaustive class tests instead of a megamorphic call"); |
| 35 |
32 // Quick access to the current isolate and zone. | 36 // Quick access to the current isolate and zone. |
33 #define I (isolate()) | 37 #define I (isolate()) |
34 #define Z (zone()) | 38 #define Z (zone()) |
35 | 39 |
36 static bool ShouldInlineSimd() { | 40 static bool ShouldInlineSimd() { |
37 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 41 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
38 } | 42 } |
39 | 43 |
40 | 44 |
41 static bool CanUnboxDouble() { | 45 static bool CanUnboxDouble() { |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 if (receiver_cid == kDynamicCid) { | 278 if (receiver_cid == kDynamicCid) { |
275 return; // No information about receiver was infered. | 279 return; // No information about receiver was infered. |
276 } | 280 } |
277 | 281 |
278 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); | 282 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); |
279 if (ic_data.raw() == call->ic_data().raw()) { | 283 if (ic_data.raw() == call->ic_data().raw()) { |
280 // No specialization. | 284 // No specialization. |
281 return; | 285 return; |
282 } | 286 } |
283 | 287 |
284 const bool with_checks = false; | |
285 PolymorphicInstanceCallInstr* specialized = | 288 PolymorphicInstanceCallInstr* specialized = |
286 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), | 289 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), |
287 ic_data, | 290 ic_data, |
288 with_checks); | 291 /* with_checks = */ false, |
| 292 /* complete = */ false); |
289 call->ReplaceWith(specialized, current_iterator()); | 293 call->ReplaceWith(specialized, current_iterator()); |
290 } | 294 } |
291 | 295 |
292 | 296 |
293 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { | 297 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { |
294 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); | 298 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); |
295 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { | 299 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { |
296 return instr; | 300 return instr; |
297 } | 301 } |
298 return NULL; | 302 return NULL; |
(...skipping 2135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2434 has_one_target = !polymorphic_target; | 2438 has_one_target = !polymorphic_target; |
2435 } | 2439 } |
2436 | 2440 |
2437 if (has_one_target) { | 2441 if (has_one_target) { |
2438 RawFunction::Kind function_kind = | 2442 RawFunction::Kind function_kind = |
2439 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 2443 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
2440 if (!flow_graph()->InstanceCallNeedsClassCheck( | 2444 if (!flow_graph()->InstanceCallNeedsClassCheck( |
2441 instr, function_kind)) { | 2445 instr, function_kind)) { |
2442 PolymorphicInstanceCallInstr* call = | 2446 PolymorphicInstanceCallInstr* call = |
2443 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2447 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
2444 /* with_checks = */ false); | 2448 /* with_checks = */ false, |
| 2449 /* complete = */ true); |
2445 instr->ReplaceWith(call, current_iterator()); | 2450 instr->ReplaceWith(call, current_iterator()); |
2446 return; | 2451 return; |
2447 } | 2452 } |
2448 } | 2453 } |
2449 switch (instr->token_kind()) { | 2454 switch (instr->token_kind()) { |
2450 case Token::kEQ: | 2455 case Token::kEQ: |
2451 case Token::kLT: | 2456 case Token::kLT: |
2452 case Token::kLTE: | 2457 case Token::kLTE: |
2453 case Token::kGT: | 2458 case Token::kGT: |
2454 case Token::kGTE: | 2459 case Token::kGTE: |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2507 // Create fake IC data with the resolved target. | 2512 // Create fake IC data with the resolved target. |
2508 const ICData& ic_data = ICData::Handle( | 2513 const ICData& ic_data = ICData::Handle( |
2509 ICData::New(flow_graph_->function(), | 2514 ICData::New(flow_graph_->function(), |
2510 instr->function_name(), | 2515 instr->function_name(), |
2511 args_desc_array, | 2516 args_desc_array, |
2512 Thread::kNoDeoptId, | 2517 Thread::kNoDeoptId, |
2513 /* args_tested = */ 1)); | 2518 /* args_tested = */ 1)); |
2514 ic_data.AddReceiverCheck(receiver_class.id(), function); | 2519 ic_data.AddReceiverCheck(receiver_class.id(), function); |
2515 PolymorphicInstanceCallInstr* call = | 2520 PolymorphicInstanceCallInstr* call = |
2516 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, | 2521 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
2517 /* with_checks = */ false); | 2522 /* with_checks = */ false, |
| 2523 /* complete = */ true); |
2518 instr->ReplaceWith(call, current_iterator()); | 2524 instr->ReplaceWith(call, current_iterator()); |
2519 return; | 2525 return; |
2520 } | 2526 } |
2521 } | 2527 } |
2522 } | 2528 } |
2523 | 2529 |
| 2530 Definition* callee_receiver = instr->ArgumentAt(0); |
| 2531 const Function& function = flow_graph_->function(); |
| 2532 if (function.IsDynamicFunction() && |
| 2533 flow_graph_->IsReceiver(callee_receiver)) { |
| 2534 // Call receiver is method receiver. |
| 2535 Class& receiver_class = Class::Handle(Z, function.Owner()); |
| 2536 GrowableArray<intptr_t> class_ids(6); |
| 2537 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { |
| 2538 if (class_ids.length() <= FLAG_max_exhaustive_polymorphic_checks) { |
| 2539 if (FLAG_trace_cha) { |
| 2540 THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n", |
| 2541 class_ids.length(), |
| 2542 receiver_class.ToCString(), |
| 2543 instr->function_name().ToCString()); |
| 2544 } |
| 2545 |
| 2546 const Array& args_desc_array = Array::Handle(Z, |
| 2547 ArgumentsDescriptor::New(instr->ArgumentCount(), |
| 2548 instr->argument_names())); |
| 2549 ArgumentsDescriptor args_desc(args_desc_array); |
| 2550 |
| 2551 const ICData& ic_data = ICData::Handle( |
| 2552 ICData::New(function, |
| 2553 instr->function_name(), |
| 2554 args_desc_array, |
| 2555 Thread::kNoDeoptId, |
| 2556 /* args_tested = */ 1)); |
| 2557 |
| 2558 Function& target = Function::Handle(Z); |
| 2559 Class& cls = Class::Handle(Z); |
| 2560 bool includes_dispatcher_case = false; |
| 2561 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 2562 intptr_t cid = class_ids[i]; |
| 2563 cls = isolate()->class_table()->At(cid); |
| 2564 target = Resolver::ResolveDynamicForReceiverClass( |
| 2565 cls, |
| 2566 instr->function_name(), |
| 2567 args_desc); |
| 2568 if (target.IsNull()) { |
| 2569 // noSuchMethod, call through getter or closurization |
| 2570 includes_dispatcher_case = true; |
| 2571 } else { |
| 2572 ic_data.AddReceiverCheck(cid, target); |
| 2573 } |
| 2574 } |
| 2575 if (!includes_dispatcher_case && (ic_data.NumberOfChecks() > 0)) { |
| 2576 PolymorphicInstanceCallInstr* call = |
| 2577 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
| 2578 /* with_checks = */ true, |
| 2579 /* complete = */ true); |
| 2580 instr->ReplaceWith(call, current_iterator()); |
| 2581 return; |
| 2582 } |
| 2583 } |
| 2584 } |
| 2585 } |
| 2586 |
2524 // More than one targets. Generate generic polymorphic call without | 2587 // More than one targets. Generate generic polymorphic call without |
2525 // deoptimization. | 2588 // deoptimization. |
2526 if (instr->ic_data()->NumberOfUsedChecks() > 0) { | 2589 if (instr->ic_data()->NumberOfUsedChecks() > 0) { |
2527 ASSERT(!FLAG_polymorphic_with_deopt); | 2590 ASSERT(!FLAG_polymorphic_with_deopt); |
2528 // OK to use checks with PolymorphicInstanceCallInstr since no | 2591 // OK to use checks with PolymorphicInstanceCallInstr since no |
2529 // deoptimization is allowed. | 2592 // deoptimization is allowed. |
2530 PolymorphicInstanceCallInstr* call = | 2593 PolymorphicInstanceCallInstr* call = |
2531 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2594 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
2532 /* with_checks = */ true); | 2595 /* with_checks = */ true, |
| 2596 /* complete = */ false); |
2533 instr->ReplaceWith(call, current_iterator()); | 2597 instr->ReplaceWith(call, current_iterator()); |
2534 return; | 2598 return; |
2535 } | 2599 } |
2536 } | 2600 } |
2537 | 2601 |
2538 | 2602 |
2539 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { | 2603 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { |
2540 if (!CanUnboxDouble()) { | 2604 if (!CanUnboxDouble()) { |
2541 return; | 2605 return; |
2542 } | 2606 } |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2757 | 2821 |
2758 // Discard the environment from the original instruction because the store | 2822 // Discard the environment from the original instruction because the store |
2759 // can't deoptimize. | 2823 // can't deoptimize. |
2760 instr->RemoveEnvironment(); | 2824 instr->RemoveEnvironment(); |
2761 ReplaceCall(instr, store); | 2825 ReplaceCall(instr, store); |
2762 return true; | 2826 return true; |
2763 } | 2827 } |
2764 | 2828 |
2765 | 2829 |
2766 } // namespace dart | 2830 } // namespace dart |
OLD | NEW |