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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 56 static bool ShouldInlineSimd() { | 56 static bool ShouldInlineSimd() { |
| 57 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 57 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
| 58 } | 58 } |
| 59 | 59 |
| 60 | 60 |
| 61 static bool CanUnboxDouble() { | 61 static bool CanUnboxDouble() { |
| 62 return FlowGraphCompiler::SupportsUnboxedDoubles(); | 62 return FlowGraphCompiler::SupportsUnboxedDoubles(); |
| 63 } | 63 } |
| 64 | 64 |
| 65 | 65 |
| 66 static bool CanConvertUnboxedMintToDouble() { | |
| 67 #if defined(TARGET_ARCH_IA32) | |
| 68 return true; | |
| 69 #else | |
|
Florian Schneider
2014/09/19 09:49:00
I think there should be a TODO for the other platf
Cutch
2014/09/19 16:17:41
Added a note about ARM and a TODO to check for MIP
| |
| 70 return false; | |
| 71 #endif | |
| 72 } | |
| 73 | |
| 66 // Optimize instance calls using ICData. | 74 // Optimize instance calls using ICData. |
| 67 void FlowGraphOptimizer::ApplyICData() { | 75 void FlowGraphOptimizer::ApplyICData() { |
| 68 VisitBlocks(); | 76 VisitBlocks(); |
| 69 } | 77 } |
| 70 | 78 |
| 71 | 79 |
| 72 // Optimize instance calls using cid. This is called after optimizer | 80 // Optimize instance calls using cid. This is called after optimizer |
| 73 // converted instance calls to instructions. Any remaining | 81 // converted instance calls to instructions. Any remaining |
| 74 // instance calls are either megamorphic calls, cannot be optimized or | 82 // instance calls are either megamorphic calls, cannot be optimized or |
| 75 // have no runtime type feedback collected. | 83 // have no runtime type feedback collected. |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 638 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 631 converted = new UnboxInt32Instr(use->CopyWithType(), deopt_id); | 639 converted = new UnboxInt32Instr(use->CopyWithType(), deopt_id); |
| 632 } else if ((from == kUnboxedInt32) && (to == kTagged)) { | 640 } else if ((from == kUnboxedInt32) && (to == kTagged)) { |
| 633 converted = new BoxInt32Instr(use->CopyWithType()); | 641 converted = new BoxInt32Instr(use->CopyWithType()); |
| 634 } else if ((from == kTagged) && (to == kUnboxedUint32)) { | 642 } else if ((from == kTagged) && (to == kUnboxedUint32)) { |
| 635 const intptr_t deopt_id = (deopt_target != NULL) ? | 643 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 636 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 644 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 637 converted = new UnboxUint32Instr(use->CopyWithType(), deopt_id); | 645 converted = new UnboxUint32Instr(use->CopyWithType(), deopt_id); |
| 638 } else if (from == kUnboxedMint && to == kUnboxedDouble) { | 646 } else if (from == kUnboxedMint && to == kUnboxedDouble) { |
| 639 ASSERT(CanUnboxDouble()); | 647 ASSERT(CanUnboxDouble()); |
| 640 // Convert by boxing/unboxing. | |
| 641 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. | |
| 642 BoxIntegerInstr* boxed = | |
| 643 new(I) BoxIntegerInstr(use->CopyWithType()); | |
| 644 use->BindTo(boxed); | |
| 645 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | |
| 646 | |
| 647 const intptr_t deopt_id = (deopt_target != NULL) ? | 648 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 648 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 649 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 649 converted = new(I) UnboxDoubleInstr(new(I) Value(boxed), deopt_id); | 650 if (CanConvertUnboxedMintToDouble()) { |
| 650 | 651 // Fast path. |
| 652 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id); | |
| 653 } else { | |
| 654 // Slow path. | |
| 655 BoxIntegerInstr* boxed = new(I) BoxIntegerInstr(use->CopyWithType()); | |
| 656 use->BindTo(boxed); | |
| 657 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | |
| 658 converted = new(I) UnboxDoubleInstr(new(I) Value(boxed), deopt_id); | |
| 659 } | |
| 651 } else if ((from == kUnboxedDouble) && (to == kTagged)) { | 660 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 652 ASSERT(CanUnboxDouble()); | 661 ASSERT(CanUnboxDouble()); |
| 653 converted = new(I) BoxDoubleInstr(use->CopyWithType()); | 662 converted = new(I) BoxDoubleInstr(use->CopyWithType()); |
| 654 | |
| 655 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 663 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 656 ASSERT(CanUnboxDouble()); | 664 ASSERT(CanUnboxDouble()); |
| 657 ASSERT((deopt_target != NULL) || | 665 ASSERT((deopt_target != NULL) || |
| 658 (use->Type()->ToCid() == kDoubleCid)); | 666 (use->Type()->ToCid() == kDoubleCid)); |
| 659 const intptr_t deopt_id = (deopt_target != NULL) ? | 667 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 660 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 668 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 661 ConstantInstr* constant = use->definition()->AsConstant(); | 669 ConstantInstr* constant = use->definition()->AsConstant(); |
| 662 if ((constant != NULL) && constant->value().IsSmi()) { | 670 if ((constant != NULL) && constant->value().IsSmi()) { |
| 663 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); | 671 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); |
| 664 const Double& dbl_obj = | 672 const Double& dbl_obj = |
| (...skipping 2379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3044 call->deopt_id(), | 3052 call->deopt_id(), |
| 3045 call->token_pos()); | 3053 call->token_pos()); |
| 3046 ReplaceCall(call, store_op); | 3054 ReplaceCall(call, store_op); |
| 3047 return true; | 3055 return true; |
| 3048 } | 3056 } |
| 3049 return false; | 3057 return false; |
| 3050 } | 3058 } |
| 3051 | 3059 |
| 3052 if (CanUnboxDouble() && | 3060 if (CanUnboxDouble() && |
| 3053 (recognized_kind == MethodRecognizer::kIntegerToDouble) && | 3061 (recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 3054 (ic_data.NumberOfChecks() == 1) && | 3062 (ic_data.NumberOfChecks() == 1)) { |
| 3055 (class_ids[0] == kSmiCid)) { | 3063 if (class_ids[0] == kSmiCid) { |
| 3056 AddReceiverCheck(call); | 3064 AddReceiverCheck(call); |
| 3057 ReplaceCall(call, | 3065 ReplaceCall(call, |
| 3058 new(I) SmiToDoubleInstr( | 3066 new(I) SmiToDoubleInstr( |
| 3059 new(I) Value(call->ArgumentAt(0)), | 3067 new(I) Value(call->ArgumentAt(0)), |
| 3060 call->token_pos())); | 3068 call->token_pos())); |
| 3061 return true; | 3069 return true; |
| 3070 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { | |
| 3071 AddReceiverCheck(call); | |
| 3072 ReplaceCall(call, | |
| 3073 new(I) MintToDoubleInstr(new(I) Value(call->ArgumentAt(0)), | |
| 3074 call->deopt_id())); | |
| 3075 return true; | |
| 3076 } | |
| 3062 } | 3077 } |
| 3063 | 3078 |
| 3064 if (class_ids[0] == kDoubleCid) { | 3079 if (class_ids[0] == kDoubleCid) { |
| 3065 if (!CanUnboxDouble()) { | 3080 if (!CanUnboxDouble()) { |
| 3066 return false; | 3081 return false; |
| 3067 } | 3082 } |
| 3068 switch (recognized_kind) { | 3083 switch (recognized_kind) { |
| 3069 case MethodRecognizer::kDoubleToInteger: { | 3084 case MethodRecognizer::kDoubleToInteger: { |
| 3070 AddReceiverCheck(call); | 3085 AddReceiverCheck(call); |
| 3071 ASSERT(call->HasICData()); | 3086 ASSERT(call->HasICData()); |
| (...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4497 } | 4512 } |
| 4498 InvokeMathCFunctionInstr* invoke = | 4513 InvokeMathCFunctionInstr* invoke = |
| 4499 new(I) InvokeMathCFunctionInstr(args, | 4514 new(I) InvokeMathCFunctionInstr(args, |
| 4500 call->deopt_id(), | 4515 call->deopt_id(), |
| 4501 recognized_kind, | 4516 recognized_kind, |
| 4502 call->token_pos()); | 4517 call->token_pos()); |
| 4503 ReplaceCall(call, invoke); | 4518 ReplaceCall(call, invoke); |
| 4504 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) { | 4519 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) { |
| 4505 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 4520 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { |
| 4506 const ICData& ic_data = *call->ic_data(); | 4521 const ICData& ic_data = *call->ic_data(); |
| 4507 if (CanUnboxDouble() && ArgIsAlways(kSmiCid, ic_data, 0)) { | 4522 if (CanUnboxDouble()) { |
| 4508 Definition* arg = call->ArgumentAt(0); | 4523 if (ArgIsAlways(kSmiCid, ic_data, 1)) { |
| 4509 InsertBefore(call, | 4524 Definition* arg = call->ArgumentAt(1); |
| 4510 new(I) CheckSmiInstr( | 4525 AddCheckSmi(arg, call->deopt_id(), call->env(), call); |
| 4511 new(I) Value(arg), | 4526 ReplaceCall(call, |
| 4512 call->deopt_id(), | 4527 new(I) SmiToDoubleInstr(new(I) Value(arg), |
| 4513 call->token_pos()), | 4528 call->token_pos())); |
| 4514 call->env(), | 4529 } else if (ArgIsAlways(kMintCid, ic_data, 1) && |
| 4515 FlowGraph::kEffect); | 4530 CanConvertUnboxedMintToDouble()) { |
| 4516 ReplaceCall(call, | 4531 Definition* arg = call->ArgumentAt(1); |
| 4517 new(I) SmiToDoubleInstr(new(I) Value(arg), | 4532 ReplaceCall(call, |
| 4518 call->token_pos())); | 4533 new(I) MintToDoubleInstr(new(I) Value(arg), |
| 4534 call->deopt_id())); | |
| 4535 } | |
| 4519 } | 4536 } |
| 4520 } | 4537 } |
| 4521 } else if (call->function().IsFactory()) { | 4538 } else if (call->function().IsFactory()) { |
| 4522 const Class& function_class = | 4539 const Class& function_class = |
| 4523 Class::Handle(I, call->function().Owner()); | 4540 Class::Handle(I, call->function().Owner()); |
| 4524 if ((function_class.library() == Library::CoreLibrary()) || | 4541 if ((function_class.library() == Library::CoreLibrary()) || |
| 4525 (function_class.library() == Library::TypedDataLibrary())) { | 4542 (function_class.library() == Library::TypedDataLibrary())) { |
| 4526 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); | 4543 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); |
| 4527 switch (cid) { | 4544 switch (cid) { |
| 4528 case kArrayCid: { | 4545 case kArrayCid: { |
| (...skipping 3888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8417 const Object& value = instr->value()->definition()->constant_value(); | 8434 const Object& value = instr->value()->definition()->constant_value(); |
| 8418 if (IsConstant(value) && value.IsInteger()) { | 8435 if (IsConstant(value) && value.IsInteger()) { |
| 8419 SetValue(instr, Double::Handle(I, | 8436 SetValue(instr, Double::Handle(I, |
| 8420 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 8437 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); |
| 8421 } else if (IsNonConstant(value)) { | 8438 } else if (IsNonConstant(value)) { |
| 8422 SetValue(instr, non_constant_); | 8439 SetValue(instr, non_constant_); |
| 8423 } | 8440 } |
| 8424 } | 8441 } |
| 8425 | 8442 |
| 8426 | 8443 |
| 8444 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { | |
| 8445 const Object& value = instr->value()->definition()->constant_value(); | |
| 8446 if (IsConstant(value) && value.IsInteger()) { | |
| 8447 SetValue(instr, Double::Handle(I, | |
| 8448 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | |
| 8449 } else if (IsNonConstant(value)) { | |
| 8450 SetValue(instr, non_constant_); | |
| 8451 } | |
| 8452 } | |
| 8453 | |
| 8454 | |
| 8427 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { | 8455 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { |
| 8428 const Object& value = instr->value()->definition()->constant_value(); | 8456 const Object& value = instr->value()->definition()->constant_value(); |
| 8429 if (IsConstant(value) && value.IsInteger()) { | 8457 if (IsConstant(value) && value.IsInteger()) { |
| 8430 SetValue(instr, Double::Handle(I, | 8458 SetValue(instr, Double::Handle(I, |
| 8431 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 8459 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); |
| 8432 } else if (IsNonConstant(value)) { | 8460 } else if (IsNonConstant(value)) { |
| 8433 SetValue(instr, non_constant_); | 8461 SetValue(instr, non_constant_); |
| 8434 } | 8462 } |
| 8435 } | 8463 } |
| 8436 | 8464 |
| (...skipping 1647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10084 | 10112 |
| 10085 // Insert materializations at environment uses. | 10113 // Insert materializations at environment uses. |
| 10086 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10114 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10087 CreateMaterializationAt( | 10115 CreateMaterializationAt( |
| 10088 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10116 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 10089 } | 10117 } |
| 10090 } | 10118 } |
| 10091 | 10119 |
| 10092 | 10120 |
| 10093 } // namespace dart | 10121 } // namespace dart |
| OLD | NEW |