| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 2521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2532 Bool& prev = Bool::Handle(); | 2532 Bool& prev = Bool::Handle(); |
| 2533 Class& cls = Class::Handle(); | 2533 Class& cls = Class::Handle(); |
| 2534 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { | 2534 for (int i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 2535 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); | 2535 cls = class_table.At(ic_data.GetReceiverClassIdAt(i)); |
| 2536 if (cls.HasTypeArguments()) return Bool::null(); | 2536 if (cls.HasTypeArguments()) return Bool::null(); |
| 2537 const bool is_subtype = cls.IsSubtypeOf(TypeArguments::Handle(), | 2537 const bool is_subtype = cls.IsSubtypeOf(TypeArguments::Handle(), |
| 2538 type_class, | 2538 type_class, |
| 2539 TypeArguments::Handle(), | 2539 TypeArguments::Handle(), |
| 2540 NULL); | 2540 NULL); |
| 2541 if (prev.IsNull()) { | 2541 if (prev.IsNull()) { |
| 2542 prev = is_subtype ? Bool::True().raw() : Bool::False().raw(); | 2542 prev = Bool::Get(is_subtype).raw(); |
| 2543 } else { | 2543 } else { |
| 2544 if (is_subtype != prev.value()) return Bool::null(); | 2544 if (is_subtype != prev.value()) return Bool::null(); |
| 2545 } | 2545 } |
| 2546 } | 2546 } |
| 2547 return prev.raw(); | 2547 return prev.raw(); |
| 2548 } | 2548 } |
| 2549 | 2549 |
| 2550 | 2550 |
| 2551 // TODO(srdjan): Use ICData to check if always true or false. | 2551 // TODO(srdjan): Use ICData to check if always true or false. |
| 2552 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 2552 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| 2553 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 2553 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 2554 Definition* left = call->ArgumentAt(0); | 2554 Definition* left = call->ArgumentAt(0); |
| 2555 Definition* instantiator = call->ArgumentAt(1); | 2555 Definition* instantiator = call->ArgumentAt(1); |
| 2556 Definition* type_args = call->ArgumentAt(2); | 2556 Definition* type_args = call->ArgumentAt(2); |
| 2557 const AbstractType& type = | 2557 const AbstractType& type = |
| 2558 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 2558 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); |
| 2559 const bool negate = | 2559 const bool negate = |
| 2560 Bool::Cast(call->ArgumentAt(4)->AsConstant()->value()).value(); | 2560 Bool::Cast(call->ArgumentAt(4)->AsConstant()->value()).value(); |
| 2561 const ICData& unary_checks = | 2561 const ICData& unary_checks = |
| 2562 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 2562 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); |
| 2563 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 2563 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
| 2564 Bool& as_bool = Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type)); | 2564 Bool& as_bool = Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type)); |
| 2565 if (!as_bool.IsNull()) { | 2565 if (!as_bool.IsNull()) { |
| 2566 AddReceiverCheck(call); | 2566 AddReceiverCheck(call); |
| 2567 if (negate) { | 2567 if (negate) { |
| 2568 as_bool = Bool::Get(!as_bool.value()); | 2568 as_bool = Bool::Get(!as_bool.value()).raw(); |
| 2569 } | 2569 } |
| 2570 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); | 2570 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); |
| 2571 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 2571 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 2572 PushArgumentInstr* push = call->PushArgumentAt(i); | 2572 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 2573 push->ReplaceUsesWith(push->value()->definition()); | 2573 push->ReplaceUsesWith(push->value()->definition()); |
| 2574 push->RemoveFromGraph(); | 2574 push->RemoveFromGraph(); |
| 2575 } | 2575 } |
| 2576 call->ReplaceUsesWith(bool_const); | 2576 call->ReplaceUsesWith(bool_const); |
| 2577 ASSERT(current_iterator()->Current() == call); | 2577 ASSERT(current_iterator()->Current() == call); |
| 2578 current_iterator()->RemoveCurrentFromGraph(); | 2578 current_iterator()->RemoveCurrentFromGraph(); |
| (...skipping 3412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5991 } | 5991 } |
| 5992 } | 5992 } |
| 5993 | 5993 |
| 5994 | 5994 |
| 5995 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 5995 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
| 5996 const Object& left = instr->left()->definition()->constant_value(); | 5996 const Object& left = instr->left()->definition()->constant_value(); |
| 5997 const Object& right = instr->right()->definition()->constant_value(); | 5997 const Object& right = instr->right()->definition()->constant_value(); |
| 5998 | 5998 |
| 5999 if (instr->left()->definition() == instr->right()->definition()) { | 5999 if (instr->left()->definition() == instr->right()->definition()) { |
| 6000 // Fold x === x, and x !== x to true/false. | 6000 // Fold x === x, and x !== x to true/false. |
| 6001 SetValue(instr, | 6001 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT)); |
| 6002 (instr->kind() == Token::kEQ_STRICT) | |
| 6003 ? Bool::True() | |
| 6004 : Bool::False()); | |
| 6005 return; | 6002 return; |
| 6006 } | 6003 } |
| 6007 | 6004 |
| 6008 if (IsNonConstant(left) || IsNonConstant(right)) { | 6005 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 6009 // TODO(vegorov): incorporate nullability information into the lattice. | 6006 // TODO(vegorov): incorporate nullability information into the lattice. |
| 6010 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || | 6007 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || |
| 6011 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { | 6008 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { |
| 6012 bool result = left.IsNull() ? instr->right()->Type()->IsNull() | 6009 bool result = left.IsNull() ? instr->right()->Type()->IsNull() |
| 6013 : instr->left()->Type()->IsNull(); | 6010 : instr->left()->Type()->IsNull(); |
| 6014 if (instr->kind() == Token::kNE_STRICT) result = !result; | 6011 if (instr->kind() == Token::kNE_STRICT) result = !result; |
| 6015 SetValue(instr, result ? Bool::True() : Bool::False()); | 6012 SetValue(instr, Bool::Get(result)); |
| 6016 } else { | 6013 } else { |
| 6017 SetValue(instr, non_constant_); | 6014 SetValue(instr, non_constant_); |
| 6018 } | 6015 } |
| 6019 } else if (IsConstant(left) && IsConstant(right)) { | 6016 } else if (IsConstant(left) && IsConstant(right)) { |
| 6020 bool result = (left.raw() == right.raw()); | 6017 bool result = (left.raw() == right.raw()); |
| 6021 if (instr->kind() == Token::kNE_STRICT) result = !result; | 6018 if (instr->kind() == Token::kNE_STRICT) result = !result; |
| 6022 SetValue(instr, result ? Bool::True() : Bool::False()); | 6019 SetValue(instr, Bool::Get(result)); |
| 6023 } | 6020 } |
| 6024 } | 6021 } |
| 6025 | 6022 |
| 6026 | 6023 |
| 6027 static bool CompareIntegers(Token::Kind kind, | 6024 static bool CompareIntegers(Token::Kind kind, |
| 6028 const Integer& left, | 6025 const Integer& left, |
| 6029 const Integer& right) { | 6026 const Integer& right) { |
| 6030 const int result = left.CompareWith(right); | 6027 const int result = left.CompareWith(right); |
| 6031 switch (kind) { | 6028 switch (kind) { |
| 6032 case Token::kEQ: return (result == 0); | 6029 case Token::kEQ: return (result == 0); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6044 | 6041 |
| 6045 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { | 6042 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 6046 const Object& left = instr->left()->definition()->constant_value(); | 6043 const Object& left = instr->left()->definition()->constant_value(); |
| 6047 const Object& right = instr->right()->definition()->constant_value(); | 6044 const Object& right = instr->right()->definition()->constant_value(); |
| 6048 | 6045 |
| 6049 if (instr->left()->definition() == instr->right()->definition()) { | 6046 if (instr->left()->definition() == instr->right()->definition()) { |
| 6050 // Fold x == x, and x != x to true/false for numbers and checked strict | 6047 // Fold x == x, and x != x to true/false for numbers and checked strict |
| 6051 // comparisons. | 6048 // comparisons. |
| 6052 if (instr->IsCheckedStrictEqual() || | 6049 if (instr->IsCheckedStrictEqual() || |
| 6053 RawObject::IsIntegerClassId(instr->operation_cid())) { | 6050 RawObject::IsIntegerClassId(instr->operation_cid())) { |
| 6054 return SetValue(instr, | 6051 return SetValue(instr, Bool::Get(instr->kind() == Token::kEQ)); |
| 6055 (instr->kind() == Token::kEQ) | |
| 6056 ? Bool::True() | |
| 6057 : Bool::False()); | |
| 6058 } | 6052 } |
| 6059 } | 6053 } |
| 6060 | 6054 |
| 6061 if (IsNonConstant(left) || IsNonConstant(right)) { | 6055 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 6062 SetValue(instr, non_constant_); | 6056 SetValue(instr, non_constant_); |
| 6063 } else if (IsConstant(left) && IsConstant(right)) { | 6057 } else if (IsConstant(left) && IsConstant(right)) { |
| 6064 if (left.IsInteger() && right.IsInteger()) { | 6058 if (left.IsInteger() && right.IsInteger()) { |
| 6065 const bool result = CompareIntegers(instr->kind(), | 6059 const bool result = CompareIntegers(instr->kind(), |
| 6066 Integer::Cast(left), | 6060 Integer::Cast(left), |
| 6067 Integer::Cast(right)); | 6061 Integer::Cast(right)); |
| 6068 SetValue(instr, result ? Bool::True() : Bool::False()); | 6062 SetValue(instr, Bool::Get(result)); |
| 6069 } else if (left.IsString() && right.IsString()) { | 6063 } else if (left.IsString() && right.IsString()) { |
| 6070 const bool result = String::Cast(left).Equals(String::Cast(right)); | 6064 const bool result = String::Cast(left).Equals(String::Cast(right)); |
| 6071 SetValue(instr, | 6065 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); |
| 6072 ((instr->kind() == Token::kEQ) == result) | |
| 6073 ? Bool::True() | |
| 6074 : Bool::False()); | |
| 6075 } else { | 6066 } else { |
| 6076 SetValue(instr, non_constant_); | 6067 SetValue(instr, non_constant_); |
| 6077 } | 6068 } |
| 6078 } | 6069 } |
| 6079 } | 6070 } |
| 6080 | 6071 |
| 6081 | 6072 |
| 6082 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { | 6073 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { |
| 6083 const Object& left = instr->left()->definition()->constant_value(); | 6074 const Object& left = instr->left()->definition()->constant_value(); |
| 6084 const Object& right = instr->right()->definition()->constant_value(); | 6075 const Object& right = instr->right()->definition()->constant_value(); |
| 6085 if (IsNonConstant(left) || IsNonConstant(right)) { | 6076 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 6086 SetValue(instr, non_constant_); | 6077 SetValue(instr, non_constant_); |
| 6087 } else if (IsConstant(left) && IsConstant(right)) { | 6078 } else if (IsConstant(left) && IsConstant(right)) { |
| 6088 if (left.IsInteger() && right.IsInteger()) { | 6079 if (left.IsInteger() && right.IsInteger()) { |
| 6089 const bool result = CompareIntegers(instr->kind(), | 6080 const bool result = CompareIntegers(instr->kind(), |
| 6090 Integer::Cast(left), | 6081 Integer::Cast(left), |
| 6091 Integer::Cast(right)); | 6082 Integer::Cast(right)); |
| 6092 SetValue(instr, result ? Bool::True() : Bool::False()); | 6083 SetValue(instr, Bool::Get(result)); |
| 6093 } else { | 6084 } else { |
| 6094 SetValue(instr, non_constant_); | 6085 SetValue(instr, non_constant_); |
| 6095 } | 6086 } |
| 6096 } | 6087 } |
| 6097 } | 6088 } |
| 6098 | 6089 |
| 6099 | 6090 |
| 6100 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { | 6091 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { |
| 6101 SetValue(instr, non_constant_); | 6092 SetValue(instr, non_constant_); |
| 6102 } | 6093 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6142 SetValue(instr, instr->value()->definition()->constant_value()); | 6133 SetValue(instr, instr->value()->definition()->constant_value()); |
| 6143 } | 6134 } |
| 6144 | 6135 |
| 6145 | 6136 |
| 6146 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { | 6137 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { |
| 6147 const Object& value = instr->value()->definition()->constant_value(); | 6138 const Object& value = instr->value()->definition()->constant_value(); |
| 6148 if (IsNonConstant(value)) { | 6139 if (IsNonConstant(value)) { |
| 6149 SetValue(instr, non_constant_); | 6140 SetValue(instr, non_constant_); |
| 6150 } else if (IsConstant(value)) { | 6141 } else if (IsConstant(value)) { |
| 6151 bool val = value.raw() != Bool::True().raw(); | 6142 bool val = value.raw() != Bool::True().raw(); |
| 6152 SetValue(instr, val ? Bool::True() : Bool::False()); | 6143 SetValue(instr, Bool::Get(val)); |
| 6153 } | 6144 } |
| 6154 } | 6145 } |
| 6155 | 6146 |
| 6156 | 6147 |
| 6157 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) { | 6148 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) { |
| 6158 const Object& value = instr->value()->definition()->constant_value(); | 6149 const Object& value = instr->value()->definition()->constant_value(); |
| 6159 if (IsNonConstant(value)) { | 6150 if (IsNonConstant(value)) { |
| 6160 SetValue(instr, non_constant_); | 6151 SetValue(instr, non_constant_); |
| 6161 } else if (IsConstant(value)) { | 6152 } else if (IsConstant(value)) { |
| 6162 // TODO(kmillikin): Handle instanceof on constants. | 6153 // TODO(kmillikin): Handle instanceof on constants. |
| (...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7543 } | 7534 } |
| 7544 | 7535 |
| 7545 // Insert materializations at environment uses. | 7536 // Insert materializations at environment uses. |
| 7546 for (intptr_t i = 0; i < exits.length(); i++) { | 7537 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7547 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7538 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7548 } | 7539 } |
| 7549 } | 7540 } |
| 7550 | 7541 |
| 7551 | 7542 |
| 7552 } // namespace dart | 7543 } // namespace dart |
| OLD | NEW |