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 2388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2399 } | 2399 } |
2400 | 2400 |
2401 | 2401 |
2402 bool AotOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) { | 2402 bool AotOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) { |
2403 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { | 2403 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { |
2404 if ((*inlining_black_list_)[i] == call_deopt_id) return true; | 2404 if ((*inlining_black_list_)[i] == call_deopt_id) return true; |
2405 } | 2405 } |
2406 return false; | 2406 return false; |
2407 } | 2407 } |
2408 | 2408 |
2409 // Special optimizations when running in --noopt mode. | 2409 |
2410 void AotOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) { | 2410 // Tries to optimize instance call by replacing it with a faster instruction |
| 2411 // (e.g, binary op, field load, ..). |
| 2412 void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 2413 ASSERT(FLAG_precompiled_mode); |
2411 // TODO(srdjan): Investigate other attempts, as they are not allowed to | 2414 // TODO(srdjan): Investigate other attempts, as they are not allowed to |
2412 // deoptimize. | 2415 // deoptimize. |
2413 | 2416 |
2414 // Type test is special as it always gets converted into inlined code. | 2417 // Type test is special as it always gets converted into inlined code. |
2415 const Token::Kind op_kind = instr->token_kind(); | 2418 const Token::Kind op_kind = instr->token_kind(); |
2416 if (Token::IsTypeTestOperator(op_kind)) { | 2419 if (Token::IsTypeTestOperator(op_kind)) { |
2417 ReplaceWithInstanceOf(instr); | 2420 ReplaceWithInstanceOf(instr); |
2418 return; | 2421 return; |
2419 } | 2422 } |
2420 if (Token::IsTypeCastOperator(op_kind)) { | 2423 if (Token::IsTypeCastOperator(op_kind)) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2477 RawFunction::Kind function_kind = | 2480 RawFunction::Kind function_kind = |
2478 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 2481 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
2479 if (!InstanceCallNeedsClassCheck(instr, function_kind)) { | 2482 if (!InstanceCallNeedsClassCheck(instr, function_kind)) { |
2480 PolymorphicInstanceCallInstr* call = | 2483 PolymorphicInstanceCallInstr* call = |
2481 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2484 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
2482 /* with_checks = */ false); | 2485 /* with_checks = */ false); |
2483 instr->ReplaceWith(call, current_iterator()); | 2486 instr->ReplaceWith(call, current_iterator()); |
2484 return; | 2487 return; |
2485 } | 2488 } |
2486 } | 2489 } |
| 2490 switch (instr->token_kind()) { |
| 2491 case Token::kBIT_OR: |
| 2492 case Token::kBIT_XOR: |
| 2493 case Token::kBIT_AND: |
| 2494 case Token::kADD: |
| 2495 case Token::kSUB: { |
| 2496 if (HasOnlyTwoOf(*instr->ic_data(), kSmiCid)) { |
| 2497 Definition* left = instr->ArgumentAt(0); |
| 2498 Definition* right = instr->ArgumentAt(1); |
| 2499 CheckedSmiOpInstr* smi_op = |
| 2500 new(Z) CheckedSmiOpInstr(instr->token_kind(), |
| 2501 new(Z) Value(left), |
| 2502 new(Z) Value(right), |
| 2503 instr); |
| 2504 |
| 2505 ReplaceCall(instr, smi_op); |
| 2506 return; |
| 2507 } |
| 2508 } |
| 2509 default: |
| 2510 break; |
| 2511 } |
2487 | 2512 |
2488 // More than one targets. Generate generic polymorphic call without | 2513 // More than one targets. Generate generic polymorphic call without |
2489 // deoptimization. | 2514 // deoptimization. |
2490 if (instr->ic_data()->NumberOfUsedChecks() > 0) { | 2515 if (instr->ic_data()->NumberOfUsedChecks() > 0) { |
2491 ASSERT(!FLAG_polymorphic_with_deopt); | 2516 ASSERT(!FLAG_polymorphic_with_deopt); |
2492 // OK to use checks with PolymorphicInstanceCallInstr since no | 2517 // OK to use checks with PolymorphicInstanceCallInstr since no |
2493 // deoptimization is allowed. | 2518 // deoptimization is allowed. |
2494 PolymorphicInstanceCallInstr* call = | 2519 PolymorphicInstanceCallInstr* call = |
2495 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2520 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
2496 /* with_checks = */ true); | 2521 /* with_checks = */ true); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2532 ICData::New(flow_graph_->function(), | 2557 ICData::New(flow_graph_->function(), |
2533 instr->function_name(), | 2558 instr->function_name(), |
2534 args_desc_array, | 2559 args_desc_array, |
2535 Thread::kNoDeoptId, | 2560 Thread::kNoDeoptId, |
2536 /* args_tested = */ 1)); | 2561 /* args_tested = */ 1)); |
2537 ic_data.AddReceiverCheck(receiver_class.id(), function); | 2562 ic_data.AddReceiverCheck(receiver_class.id(), function); |
2538 PolymorphicInstanceCallInstr* call = | 2563 PolymorphicInstanceCallInstr* call = |
2539 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, | 2564 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
2540 /* with_checks = */ false); | 2565 /* with_checks = */ false); |
2541 instr->ReplaceWith(call, current_iterator()); | 2566 instr->ReplaceWith(call, current_iterator()); |
2542 return; | |
2543 } | 2567 } |
2544 } | 2568 } |
2545 | 2569 |
2546 | 2570 |
2547 // Tries to optimize instance call by replacing it with a faster instruction | |
2548 // (e.g, binary op, field load, ..). | |
2549 void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | |
2550 ASSERT(FLAG_precompiled_mode); | |
2551 InstanceCallNoopt(instr); | |
2552 } | |
2553 | |
2554 | |
2555 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { | 2571 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { |
2556 if (!CanUnboxDouble()) { | 2572 if (!CanUnboxDouble()) { |
2557 return; | 2573 return; |
2558 } | 2574 } |
2559 MethodRecognizer::Kind recognized_kind = | 2575 MethodRecognizer::Kind recognized_kind = |
2560 MethodRecognizer::RecognizeKind(call->function()); | 2576 MethodRecognizer::RecognizeKind(call->function()); |
2561 MathUnaryInstr::MathUnaryKind unary_kind; | 2577 MathUnaryInstr::MathUnaryKind unary_kind; |
2562 switch (recognized_kind) { | 2578 switch (recognized_kind) { |
2563 case MethodRecognizer::kMathSqrt: | 2579 case MethodRecognizer::kMathSqrt: |
2564 unary_kind = MathUnaryInstr::kSqrt; | 2580 unary_kind = MathUnaryInstr::kSqrt; |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2807 | 2823 |
2808 // Discard the environment from the original instruction because the store | 2824 // Discard the environment from the original instruction because the store |
2809 // can't deoptimize. | 2825 // can't deoptimize. |
2810 instr->RemoveEnvironment(); | 2826 instr->RemoveEnvironment(); |
2811 ReplaceCall(instr, store); | 2827 ReplaceCall(instr, store); |
2812 return true; | 2828 return true; |
2813 } | 2829 } |
2814 | 2830 |
2815 | 2831 |
2816 } // namespace dart | 2832 } // namespace dart |
OLD | NEW |