| 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 |