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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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; | 284 const bool with_checks = false; |
| 285 const bool complete = false; | |
| 285 PolymorphicInstanceCallInstr* specialized = | 286 PolymorphicInstanceCallInstr* specialized = |
| 286 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), | 287 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), |
| 287 ic_data, | 288 ic_data, |
| 288 with_checks); | 289 with_checks, |
|
Florian Schneider
2016/04/08 22:39:38
for style consistency:
/* with_checks = */ false
rmacnak
2016/04/11 17:20:23
Done.
| |
| 290 complete); | |
| 289 call->ReplaceWith(specialized, current_iterator()); | 291 call->ReplaceWith(specialized, current_iterator()); |
| 290 } | 292 } |
| 291 | 293 |
| 292 | 294 |
| 293 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { | 295 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { |
| 294 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); | 296 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); |
| 295 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { | 297 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { |
| 296 return instr; | 298 return instr; |
| 297 } | 299 } |
| 298 return NULL; | 300 return NULL; |
| (...skipping 2135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2434 has_one_target = !polymorphic_target; | 2436 has_one_target = !polymorphic_target; |
| 2435 } | 2437 } |
| 2436 | 2438 |
| 2437 if (has_one_target) { | 2439 if (has_one_target) { |
| 2438 RawFunction::Kind function_kind = | 2440 RawFunction::Kind function_kind = |
| 2439 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 2441 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
| 2440 if (!flow_graph()->InstanceCallNeedsClassCheck( | 2442 if (!flow_graph()->InstanceCallNeedsClassCheck( |
| 2441 instr, function_kind)) { | 2443 instr, function_kind)) { |
| 2442 PolymorphicInstanceCallInstr* call = | 2444 PolymorphicInstanceCallInstr* call = |
| 2443 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2445 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| 2444 /* with_checks = */ false); | 2446 /* with_checks = */ false, |
| 2447 /* complete = */ true); | |
| 2445 instr->ReplaceWith(call, current_iterator()); | 2448 instr->ReplaceWith(call, current_iterator()); |
| 2446 return; | 2449 return; |
| 2447 } | 2450 } |
| 2448 } | 2451 } |
| 2449 switch (instr->token_kind()) { | 2452 switch (instr->token_kind()) { |
| 2450 case Token::kEQ: | 2453 case Token::kEQ: |
| 2451 case Token::kLT: | 2454 case Token::kLT: |
| 2452 case Token::kLTE: | 2455 case Token::kLTE: |
| 2453 case Token::kGT: | 2456 case Token::kGT: |
| 2454 case Token::kGTE: | 2457 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. | 2510 // Create fake IC data with the resolved target. |
| 2508 const ICData& ic_data = ICData::Handle( | 2511 const ICData& ic_data = ICData::Handle( |
| 2509 ICData::New(flow_graph_->function(), | 2512 ICData::New(flow_graph_->function(), |
| 2510 instr->function_name(), | 2513 instr->function_name(), |
| 2511 args_desc_array, | 2514 args_desc_array, |
| 2512 Thread::kNoDeoptId, | 2515 Thread::kNoDeoptId, |
| 2513 /* args_tested = */ 1)); | 2516 /* args_tested = */ 1)); |
| 2514 ic_data.AddReceiverCheck(receiver_class.id(), function); | 2517 ic_data.AddReceiverCheck(receiver_class.id(), function); |
| 2515 PolymorphicInstanceCallInstr* call = | 2518 PolymorphicInstanceCallInstr* call = |
| 2516 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, | 2519 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
| 2517 /* with_checks = */ false); | 2520 /* with_checks = */ false, |
| 2521 /* complete = */ true); | |
| 2518 instr->ReplaceWith(call, current_iterator()); | 2522 instr->ReplaceWith(call, current_iterator()); |
| 2519 return; | 2523 return; |
| 2520 } | 2524 } |
| 2521 } | 2525 } |
| 2522 } | 2526 } |
| 2523 | 2527 |
| 2528 Definition* callee_receiver = instr->ArgumentAt(0); | |
| 2529 const Function& function = flow_graph_->function(); | |
| 2530 if (function.IsDynamicFunction() && | |
| 2531 flow_graph_->IsReceiver(callee_receiver)) { | |
| 2532 // Call receiver is method receiver. | |
| 2533 Class& receiver_class = Class::Handle(Z, function.Owner()); | |
| 2534 GrowableArray<intptr_t> class_ids(6); | |
| 2535 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { | |
| 2536 if (class_ids.length() <= 5) { | |
| 2537 ASSERT(class_ids.length() > 0); | |
| 2538 if (FLAG_trace_cha) { | |
| 2539 THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n", | |
| 2540 class_ids.length(), | |
| 2541 receiver_class.ToCString(), | |
| 2542 instr->function_name().ToCString()); | |
| 2543 } | |
| 2544 | |
| 2545 const Array& args_desc_array = Array::Handle(Z, | |
| 2546 ArgumentsDescriptor::New(instr->ArgumentCount(), | |
| 2547 instr->argument_names())); | |
| 2548 ArgumentsDescriptor args_desc(args_desc_array); | |
| 2549 | |
| 2550 const ICData& ic_data = ICData::Handle( | |
| 2551 ICData::New(function, | |
| 2552 instr->function_name(), | |
| 2553 args_desc_array, | |
| 2554 Thread::kNoDeoptId, | |
| 2555 /* args_tested = */ 1)); | |
| 2556 | |
| 2557 Function& target = Function::Handle(Z); | |
| 2558 Class& cls = Class::Handle(Z); | |
| 2559 bool includes_dispatcher_case = false; | |
| 2560 for (intptr_t i = 0; i < class_ids.length(); i++) { | |
| 2561 intptr_t cid = class_ids[i]; | |
| 2562 cls = isolate()->class_table()->At(cid); | |
| 2563 target = Resolver::ResolveDynamicForReceiverClass( | |
| 2564 cls, | |
| 2565 instr->function_name(), | |
| 2566 args_desc); | |
| 2567 if (target.IsNull()) { | |
| 2568 // noSuchMethod, call through getter or closurization | |
| 2569 includes_dispatcher_case = true; | |
| 2570 } else { | |
| 2571 ic_data.AddReceiverCheck(cid, target); | |
| 2572 } | |
| 2573 } | |
| 2574 if (!includes_dispatcher_case) { | |
| 2575 ASSERT(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 |