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 3541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3552 if (defn->IsRedefinition()) { | 3552 if (defn->IsRedefinition()) { |
| 3553 defn = defn->AsRedefinition()->value()->definition(); | 3553 defn = defn->AsRedefinition()->value()->definition(); |
| 3554 } else { | 3554 } else { |
| 3555 defn = defn->AsAssertAssignable()->value()->definition(); | 3555 defn = defn->AsAssertAssignable()->value()->definition(); |
| 3556 } | 3556 } |
| 3557 } | 3557 } |
| 3558 return defn; | 3558 return defn; |
| 3559 } | 3559 } |
| 3560 | 3560 |
| 3561 | 3561 |
| 3562 // Returns true if checking against this type is a direct class id comparison. | |
| 3563 static bool TypeCheckAsClassEquality(const AbstractType& type) { | |
| 3564 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); | |
| 3565 // Requires CHA, which can be applied in optimized code only, | |
|
regis
2014/03/03 17:54:25
Comment ending with a comma.
Florian Schneider
2014/03/03 18:09:50
Done.
| |
| 3566 if (!FLAG_use_cha) return false; | |
| 3567 if (!type.IsInstantiated()) return false; | |
| 3568 const Class& type_class = Class::Handle(type.type_class()); | |
| 3569 // Signature classes have different type checking rules. | |
| 3570 if (type_class.IsSignatureClass()) return false; | |
| 3571 // Could be an interface check? | |
| 3572 if (type_class.is_implemented()) return false; | |
| 3573 const intptr_t type_cid = type_class.id(); | |
| 3574 if (CHA::HasSubclasses(type_cid)) return false; | |
| 3575 const intptr_t num_type_args = type_class.NumTypeArguments(); | |
| 3576 if (num_type_args > 0) { | |
| 3577 // Only raw types can be directly compared, thus disregarding type | |
| 3578 // arguments. | |
| 3579 const intptr_t num_type_params = type_class.NumTypeParameters(); | |
| 3580 const intptr_t from_index = num_type_args - num_type_params; | |
| 3581 const TypeArguments& type_arguments = | |
| 3582 TypeArguments::Handle(type.arguments()); | |
| 3583 const bool is_raw_type = type_arguments.IsNull() || | |
| 3584 type_arguments.IsRaw(from_index, num_type_params); | |
| 3585 return is_raw_type; | |
| 3586 } | |
| 3587 return true; | |
| 3588 } | |
| 3589 | |
| 3590 | |
| 3562 // TODO(srdjan): Use ICData to check if always true or false. | 3591 // TODO(srdjan): Use ICData to check if always true or false. |
| 3563 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 3592 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| 3564 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 3593 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 3565 Definition* left = call->ArgumentAt(0); | 3594 Definition* left = call->ArgumentAt(0); |
| 3566 Definition* instantiator = call->ArgumentAt(1); | 3595 Definition* instantiator = call->ArgumentAt(1); |
| 3567 Definition* type_args = call->ArgumentAt(2); | 3596 Definition* type_args = call->ArgumentAt(2); |
| 3568 const AbstractType& type = | 3597 const AbstractType& type = |
| 3569 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 3598 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
| 3570 const bool negate = Bool::Cast( | 3599 const bool negate = Bool::Cast( |
| 3571 OriginalDefinition(call->ArgumentAt(4))->AsConstant()->value()).value(); | 3600 OriginalDefinition(call->ArgumentAt(4))->AsConstant()->value()).value(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3583 PushArgumentInstr* push = call->PushArgumentAt(i); | 3612 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 3584 push->ReplaceUsesWith(push->value()->definition()); | 3613 push->ReplaceUsesWith(push->value()->definition()); |
| 3585 push->RemoveFromGraph(); | 3614 push->RemoveFromGraph(); |
| 3586 } | 3615 } |
| 3587 call->ReplaceUsesWith(bool_const); | 3616 call->ReplaceUsesWith(bool_const); |
| 3588 ASSERT(current_iterator()->Current() == call); | 3617 ASSERT(current_iterator()->Current() == call); |
| 3589 current_iterator()->RemoveCurrentFromGraph(); | 3618 current_iterator()->RemoveCurrentFromGraph(); |
| 3590 return; | 3619 return; |
| 3591 } | 3620 } |
| 3592 } | 3621 } |
| 3622 | |
| 3623 if (TypeCheckAsClassEquality(type)) { | |
|
srdjan
2014/03/03 18:13:25
For next CL eventually: how about supporting a set
Florian Schneider
2014/03/04 10:22:52
Definitely.
| |
| 3624 LoadClassIdInstr* left_cid = new LoadClassIdInstr(new Value(left)); | |
| 3625 InsertBefore(call, | |
| 3626 left_cid, | |
| 3627 NULL, | |
| 3628 Definition::kValue); | |
| 3629 const intptr_t type_cid = Class::Handle(type.type_class()).id(); | |
| 3630 ConstantInstr* cid = | |
| 3631 flow_graph()->GetConstant(Smi::Handle(Smi::New(type_cid))); | |
| 3632 | |
| 3633 StrictCompareInstr* check_cid = | |
| 3634 new StrictCompareInstr(call->token_pos(), | |
| 3635 negate ? Token::kNE_STRICT : Token::kEQ_STRICT, | |
| 3636 new Value(left_cid), | |
| 3637 new Value(cid), | |
| 3638 false); // No number check. | |
| 3639 ReplaceCall(call, check_cid); | |
| 3640 return; | |
| 3641 } | |
| 3642 | |
| 3593 InstanceOfInstr* instance_of = | 3643 InstanceOfInstr* instance_of = |
| 3594 new InstanceOfInstr(call->token_pos(), | 3644 new InstanceOfInstr(call->token_pos(), |
| 3595 new Value(left), | 3645 new Value(left), |
| 3596 new Value(instantiator), | 3646 new Value(instantiator), |
| 3597 new Value(type_args), | 3647 new Value(type_args), |
| 3598 type, | 3648 type, |
| 3599 negate, | 3649 negate, |
| 3600 call->deopt_id()); | 3650 call->deopt_id()); |
| 3601 ReplaceCall(call, instance_of); | 3651 ReplaceCall(call, instance_of); |
| 3602 } | 3652 } |
| (...skipping 5007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8610 } | 8660 } |
| 8611 | 8661 |
| 8612 // Insert materializations at environment uses. | 8662 // Insert materializations at environment uses. |
| 8613 for (intptr_t i = 0; i < exits.length(); i++) { | 8663 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8614 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8664 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8615 } | 8665 } |
| 8616 } | 8666 } |
| 8617 | 8667 |
| 8618 | 8668 |
| 8619 } // namespace dart | 8669 } // namespace dart |
| OLD | NEW |