Chromium Code Reviews| 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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 if (receiver_cid == kDynamicCid) { | 274 if (receiver_cid == kDynamicCid) { |
| 275 return; // No information about receiver was infered. | 275 return; // No information about receiver was infered. |
| 276 } | 276 } |
| 277 | 277 |
| 278 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); | 278 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); |
| 279 if (ic_data.raw() == call->ic_data().raw()) { | 279 if (ic_data.raw() == call->ic_data().raw()) { |
| 280 // No specialization. | 280 // No specialization. |
| 281 return; | 281 return; |
| 282 } | 282 } |
| 283 | 283 |
| 284 const bool with_checks = false; | |
| 285 PolymorphicInstanceCallInstr* specialized = | 284 PolymorphicInstanceCallInstr* specialized = |
| 286 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), | 285 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), |
| 287 ic_data, | 286 ic_data, |
| 288 with_checks); | 287 /* with_checks = */ false, |
| 288 /* complete = */ false); | |
| 289 call->ReplaceWith(specialized, current_iterator()); | 289 call->ReplaceWith(specialized, current_iterator()); |
| 290 } | 290 } |
| 291 | 291 |
| 292 | 292 |
| 293 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { | 293 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { |
| 294 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); | 294 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); |
| 295 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { | 295 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { |
| 296 return instr; | 296 return instr; |
| 297 } | 297 } |
| 298 return NULL; | 298 return NULL; |
| (...skipping 2135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2434 has_one_target = !polymorphic_target; | 2434 has_one_target = !polymorphic_target; |
| 2435 } | 2435 } |
| 2436 | 2436 |
| 2437 if (has_one_target) { | 2437 if (has_one_target) { |
| 2438 RawFunction::Kind function_kind = | 2438 RawFunction::Kind function_kind = |
| 2439 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 2439 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
| 2440 if (!flow_graph()->InstanceCallNeedsClassCheck( | 2440 if (!flow_graph()->InstanceCallNeedsClassCheck( |
| 2441 instr, function_kind)) { | 2441 instr, function_kind)) { |
| 2442 PolymorphicInstanceCallInstr* call = | 2442 PolymorphicInstanceCallInstr* call = |
| 2443 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2443 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| 2444 /* with_checks = */ false); | 2444 /* with_checks = */ false, |
| 2445 /* complete = */ true); | |
| 2445 instr->ReplaceWith(call, current_iterator()); | 2446 instr->ReplaceWith(call, current_iterator()); |
| 2446 return; | 2447 return; |
| 2447 } | 2448 } |
| 2448 } | 2449 } |
| 2449 switch (instr->token_kind()) { | 2450 switch (instr->token_kind()) { |
| 2450 case Token::kEQ: | 2451 case Token::kEQ: |
| 2451 case Token::kLT: | 2452 case Token::kLT: |
| 2452 case Token::kLTE: | 2453 case Token::kLTE: |
| 2453 case Token::kGT: | 2454 case Token::kGT: |
| 2454 case Token::kGTE: | 2455 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. | 2508 // Create fake IC data with the resolved target. |
| 2508 const ICData& ic_data = ICData::Handle( | 2509 const ICData& ic_data = ICData::Handle( |
| 2509 ICData::New(flow_graph_->function(), | 2510 ICData::New(flow_graph_->function(), |
| 2510 instr->function_name(), | 2511 instr->function_name(), |
| 2511 args_desc_array, | 2512 args_desc_array, |
| 2512 Thread::kNoDeoptId, | 2513 Thread::kNoDeoptId, |
| 2513 /* args_tested = */ 1)); | 2514 /* args_tested = */ 1)); |
| 2514 ic_data.AddReceiverCheck(receiver_class.id(), function); | 2515 ic_data.AddReceiverCheck(receiver_class.id(), function); |
| 2515 PolymorphicInstanceCallInstr* call = | 2516 PolymorphicInstanceCallInstr* call = |
| 2516 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, | 2517 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
| 2517 /* with_checks = */ false); | 2518 /* with_checks = */ false, |
| 2519 /* complete = */ true); | |
| 2518 instr->ReplaceWith(call, current_iterator()); | 2520 instr->ReplaceWith(call, current_iterator()); |
| 2519 return; | 2521 return; |
| 2520 } | 2522 } |
| 2521 } | 2523 } |
| 2522 } | 2524 } |
| 2523 | 2525 |
| 2526 Definition* callee_receiver = instr->ArgumentAt(0); | |
| 2527 const Function& function = flow_graph_->function(); | |
| 2528 if (function.IsDynamicFunction() && | |
| 2529 flow_graph_->IsReceiver(callee_receiver)) { | |
| 2530 // Call receiver is method receiver. | |
| 2531 Class& receiver_class = Class::Handle(Z, function.Owner()); | |
| 2532 GrowableArray<intptr_t> class_ids(6); | |
| 2533 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { | |
| 2534 if (class_ids.length() <= 5) { | |
|
srdjan
2016/04/11 18:10:42
How about parametrizing 5 (with a flag), or at lea
rmacnak
2016/04/11 19:33:42
Added FLAG_max_exhaustive_polymorphic_checks
| |
| 2535 if (FLAG_trace_cha) { | |
| 2536 THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n", | |
| 2537 class_ids.length(), | |
| 2538 receiver_class.ToCString(), | |
| 2539 instr->function_name().ToCString()); | |
| 2540 } | |
| 2541 | |
| 2542 const Array& args_desc_array = Array::Handle(Z, | |
| 2543 ArgumentsDescriptor::New(instr->ArgumentCount(), | |
| 2544 instr->argument_names())); | |
| 2545 ArgumentsDescriptor args_desc(args_desc_array); | |
| 2546 | |
| 2547 const ICData& ic_data = ICData::Handle( | |
| 2548 ICData::New(function, | |
| 2549 instr->function_name(), | |
| 2550 args_desc_array, | |
| 2551 Thread::kNoDeoptId, | |
| 2552 /* args_tested = */ 1)); | |
| 2553 | |
| 2554 Function& target = Function::Handle(Z); | |
| 2555 Class& cls = Class::Handle(Z); | |
| 2556 bool includes_dispatcher_case = false; | |
| 2557 for (intptr_t i = 0; i < class_ids.length(); i++) { | |
| 2558 intptr_t cid = class_ids[i]; | |
| 2559 cls = isolate()->class_table()->At(cid); | |
| 2560 target = Resolver::ResolveDynamicForReceiverClass( | |
| 2561 cls, | |
| 2562 instr->function_name(), | |
| 2563 args_desc); | |
| 2564 if (target.IsNull()) { | |
| 2565 // noSuchMethod, call through getter or closurization | |
| 2566 includes_dispatcher_case = true; | |
| 2567 } else { | |
| 2568 ic_data.AddReceiverCheck(cid, target); | |
| 2569 } | |
| 2570 } | |
| 2571 if (!includes_dispatcher_case && (ic_data.NumberOfChecks() > 0)) { | |
| 2572 PolymorphicInstanceCallInstr* call = | |
|
Florian Schneider
2016/04/11 17:42:25
Could you change IL printing for PolymorphicInstan
rmacnak
2016/04/11 19:33:42
Done.
| |
| 2573 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, | |
| 2574 /* with_checks = */ true, | |
| 2575 /* complete = */ true); | |
| 2576 instr->ReplaceWith(call, current_iterator()); | |
| 2577 return; | |
| 2578 } | |
| 2579 } | |
| 2580 } | |
| 2581 } | |
| 2582 | |
| 2524 // More than one targets. Generate generic polymorphic call without | 2583 // More than one targets. Generate generic polymorphic call without |
| 2525 // deoptimization. | 2584 // deoptimization. |
| 2526 if (instr->ic_data()->NumberOfUsedChecks() > 0) { | 2585 if (instr->ic_data()->NumberOfUsedChecks() > 0) { |
| 2527 ASSERT(!FLAG_polymorphic_with_deopt); | 2586 ASSERT(!FLAG_polymorphic_with_deopt); |
| 2528 // OK to use checks with PolymorphicInstanceCallInstr since no | 2587 // OK to use checks with PolymorphicInstanceCallInstr since no |
| 2529 // deoptimization is allowed. | 2588 // deoptimization is allowed. |
| 2530 PolymorphicInstanceCallInstr* call = | 2589 PolymorphicInstanceCallInstr* call = |
| 2531 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2590 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| 2532 /* with_checks = */ true); | 2591 /* with_checks = */ true, |
| 2592 /* complete = */ false); | |
| 2533 instr->ReplaceWith(call, current_iterator()); | 2593 instr->ReplaceWith(call, current_iterator()); |
| 2534 return; | 2594 return; |
| 2535 } | 2595 } |
| 2536 } | 2596 } |
| 2537 | 2597 |
| 2538 | 2598 |
| 2539 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { | 2599 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { |
| 2540 if (!CanUnboxDouble()) { | 2600 if (!CanUnboxDouble()) { |
| 2541 return; | 2601 return; |
| 2542 } | 2602 } |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2757 | 2817 |
| 2758 // Discard the environment from the original instruction because the store | 2818 // Discard the environment from the original instruction because the store |
| 2759 // can't deoptimize. | 2819 // can't deoptimize. |
| 2760 instr->RemoveEnvironment(); | 2820 instr->RemoveEnvironment(); |
| 2761 ReplaceCall(instr, store); | 2821 ReplaceCall(instr, store); |
| 2762 return true; | 2822 return true; |
| 2763 } | 2823 } |
| 2764 | 2824 |
| 2765 | 2825 |
| 2766 } // namespace dart | 2826 } // namespace dart |
| OLD | NEW |