Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 109 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 110 BlockEntryInstr* entry = block_order_[i]; | 110 BlockEntryInstr* entry = block_order_[i]; |
| 111 entry->Accept(this); | 111 entry->Accept(this); |
| 112 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 112 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 113 it.Current()->Accept(this); | 113 it.Current()->Accept(this); |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 // Returns true if the static type of this value is more specific than the | |
| 120 // given dst_type. | |
| 121 // TODO(regis): Should we support a set of static types? | |
| 122 bool Value::StaticTypeIsMoreSpecificThan(const AbstractType& dst_type) { | |
| 123 ASSERT(!dst_type.IsMalformed()); // Should be tested by caller. | |
| 124 ASSERT(!dst_type.IsDynamicType()); // Should be tested by caller. | |
| 125 ASSERT(!dst_type.IsObjectType()); // Should be tested by caller. | |
| 126 | |
| 127 // If the value is the null constant, its type (NullType) is more specific | |
| 128 // than the destination type, even if the destination type is the void type, | |
| 129 // since a void function is allowed to return null. | |
| 130 if (IsConstant() && AsConstant()->value().IsNull()) { | |
| 131 return true; | |
| 132 } | |
| 133 | |
| 134 // Functions that do not explicitly return a value, implicitly return null, | |
| 135 // except generative constructors, which return the object being constructed. | |
| 136 // It is therefore acceptable for void functions to return null. | |
| 137 // In case of a null constant, we have already returned true above, else we | |
| 138 // return false here. | |
| 139 if (dst_type.IsVoidType()) { | |
| 140 return false; | |
| 141 } | |
| 142 | |
| 143 // Consider the static type of the value. | |
| 144 const AbstractType& static_type = AbstractType::Handle(StaticType()); | |
| 145 ASSERT(!static_type.IsMalformed()); | |
| 146 | |
| 147 // If the static type of the value is void, we are type checking the result of | |
| 148 // a void function, which was checked to be null at the return statement | |
| 149 // inside the function. | |
| 150 if (static_type.IsVoidType()) { | |
| 151 return true; | |
| 152 } | |
| 153 | |
| 154 // If the static type of the value is NullType, the type test is eliminated. | |
| 155 // There are only three instances that can be of Class Null: | |
| 156 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). | |
| 157 // The inline code and run time code performing the type check will never | |
| 158 // encounter the 2 sentinel values. The type check of a sentinel value | |
| 159 // will always be eliminated here, because these sentinel values can only | |
| 160 // be encountered as constants, never as actual value of a heap object | |
| 161 // being type checked. | |
| 162 if (static_type.IsNullType()) { | |
| 163 return true; | |
| 164 } | |
| 165 | |
| 166 // The run time type of the value is guaranteed to be a subtype of the | |
| 167 // compile time static type of the value. However, establishing here that | |
| 168 // the static type is a subtype of the destination type does not guarantee | |
| 169 // that the run time type will also be a subtype of the destination type, | |
| 170 // because the subtype relation is not transitive. | |
| 171 // However, the 'more specific than' relation is transitive and is used | |
| 172 // here. In other words, if the static type of the value is more specific | |
| 173 // than the destination type, the run time type of the value, which is | |
| 174 // guaranteed to be a subtype of the static type, is also guaranteed to be | |
| 175 // a subtype of the destination type and the type check can therefore be | |
| 176 // eliminated. | |
| 177 return static_type.IsMoreSpecificThan(dst_type, NULL); | |
| 178 } | |
| 179 | |
| 180 | |
| 119 intptr_t AllocateObjectComp::InputCount() const { | 181 intptr_t AllocateObjectComp::InputCount() const { |
| 120 return arguments().length(); | 182 return arguments().length(); |
| 121 } | 183 } |
| 122 | 184 |
| 123 | 185 |
| 124 intptr_t AllocateObjectWithBoundsCheckComp::InputCount() const { | 186 intptr_t AllocateObjectWithBoundsCheckComp::InputCount() const { |
| 125 return arguments().length(); | 187 return arguments().length(); |
| 126 } | 188 } |
| 127 | 189 |
| 128 | 190 |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 } | 382 } |
| 321 | 383 |
| 322 | 384 |
| 323 void PhiInstr::SetInputAt(intptr_t i, Value* value) { | 385 void PhiInstr::SetInputAt(intptr_t i, Value* value) { |
| 324 inputs_[i] = value; | 386 inputs_[i] = value; |
| 325 } | 387 } |
| 326 | 388 |
| 327 | 389 |
| 328 RawAbstractType* PhiInstr::StaticType() const { | 390 RawAbstractType* PhiInstr::StaticType() const { |
| 329 // TODO(regis): Return the least upper bound of the input static types. | 391 // TODO(regis): Return the least upper bound of the input static types. |
| 330 return Type::DynamicType(); | 392 // It is much simpler to compute the least specific of the input static types, |
| 393 // and it may be good enough in practice. | |
| 394 // Even better: we could keep the set of the input static types intact. | |
|
srdjan
2012/08/01 15:07:36
Computing the least specific type is not helping e
regis
2012/08/01 17:10:35
We agree. This will happen in a later cl.
| |
| 395 AbstractType& least_specific_type = | |
| 396 AbstractType::Handle(InputAt(0)->StaticType()); | |
| 397 AbstractType& input_type = AbstractType::Handle(); | |
| 398 for (intptr_t i = 1; i < InputCount(); i++) { | |
| 399 input_type = InputAt(i)->StaticType(); | |
| 400 if (input_type.IsMoreSpecificThan(least_specific_type, NULL)) { | |
| 401 // Type least_specific_type is less specific than input_type. No change. | |
| 402 } else if (least_specific_type.IsMoreSpecificThan(input_type, NULL)) { | |
| 403 // Type input_type is less specific than the current least_specific_type. | |
| 404 least_specific_type = input_type.raw(); | |
| 405 } else { | |
| 406 // The types are unrelated. No need to continue. | |
| 407 least_specific_type = Type::ObjectType(); | |
| 408 break; | |
| 409 } | |
| 410 } | |
| 411 return least_specific_type.raw(); | |
| 331 } | 412 } |
| 332 | 413 |
| 333 | 414 |
| 334 intptr_t ParameterInstr::InputCount() const { | 415 intptr_t ParameterInstr::InputCount() const { |
| 335 return 0; | 416 return 0; |
| 336 } | 417 } |
| 337 | 418 |
| 338 | 419 |
| 339 Value* ParameterInstr::InputAt(intptr_t i) const { | 420 Value* ParameterInstr::InputAt(intptr_t i) const { |
| 340 UNREACHABLE(); | 421 UNREACHABLE(); |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 | 899 |
| 819 | 900 |
| 820 RawAbstractType* CreateClosureComp::StaticType() const { | 901 RawAbstractType* CreateClosureComp::StaticType() const { |
| 821 const Function& fun = function(); | 902 const Function& fun = function(); |
| 822 const Class& signature_class = Class::Handle(fun.signature_class()); | 903 const Class& signature_class = Class::Handle(fun.signature_class()); |
| 823 return signature_class.SignatureType(); | 904 return signature_class.SignatureType(); |
| 824 } | 905 } |
| 825 | 906 |
| 826 | 907 |
| 827 RawAbstractType* AllocateObjectComp::StaticType() const { | 908 RawAbstractType* AllocateObjectComp::StaticType() const { |
| 828 UNREACHABLE(); | 909 // TODO(regis): Be more specific. |
| 829 return AbstractType::null(); | 910 return Type::DynamicType(); |
| 830 } | 911 } |
| 831 | 912 |
| 832 | 913 |
| 833 RawAbstractType* AllocateObjectWithBoundsCheckComp::StaticType() const { | 914 RawAbstractType* AllocateObjectWithBoundsCheckComp::StaticType() const { |
| 834 UNREACHABLE(); | 915 UNREACHABLE(); |
| 835 return AbstractType::null(); | 916 return AbstractType::null(); |
| 836 } | 917 } |
| 837 | 918 |
| 838 | 919 |
| 839 RawAbstractType* LoadVMFieldComp::StaticType() const { | 920 RawAbstractType* LoadVMFieldComp::StaticType() const { |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1359 if (compiler->is_ssa()) { | 1440 if (compiler->is_ssa()) { |
| 1360 ASSERT(locs()->in(0).IsRegister()); | 1441 ASSERT(locs()->in(0).IsRegister()); |
| 1361 __ PushRegister(locs()->in(0).reg()); | 1442 __ PushRegister(locs()->in(0).reg()); |
| 1362 } | 1443 } |
| 1363 } | 1444 } |
| 1364 | 1445 |
| 1365 | 1446 |
| 1366 #undef __ | 1447 #undef __ |
| 1367 | 1448 |
| 1368 } // namespace dart | 1449 } // namespace dart |
| OLD | NEW |