| 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_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 ForwardInstructionIterator it(entry); | 284 ForwardInstructionIterator it(entry); |
| 285 current_iterator_ = ⁢ | 285 current_iterator_ = ⁢ |
| 286 for (; !it.Done(); it.Advance()) { | 286 for (; !it.Done(); it.Advance()) { |
| 287 it.Current()->Accept(this); | 287 it.Current()->Accept(this); |
| 288 } | 288 } |
| 289 current_iterator_ = NULL; | 289 current_iterator_ = NULL; |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 | 292 |
| 293 | 293 |
| 294 // Returns true if the compile type of this value is more specific than the | |
| 295 // given dst_type. | |
| 296 // TODO(regis): Support a set of compile types for the given value. | 294 // TODO(regis): Support a set of compile types for the given value. |
| 297 bool Value::CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const { | 295 bool Value::CanComputeIsNull(bool* is_null) const { |
| 298 // No type is more specific than a malformed type. | 296 ASSERT(is_null != NULL); |
| 299 if (dst_type.IsMalformed()) { | 297 // For now, we can only return a meaningful result if the value is constant. |
| 298 if (!BindsToConstant()) { |
| 300 return false; | 299 return false; |
| 301 } | 300 } |
| 302 | 301 |
| 303 // If the value is the null constant, its type (NullType) is more specific | 302 // Return true if the constant value is Object::null. |
| 304 // than the destination type, even if the destination type is the void type, | |
| 305 // since a void function is allowed to return null. | |
| 306 if (BindsToConstantNull()) { | 303 if (BindsToConstantNull()) { |
| 304 *is_null = true; |
| 307 return true; | 305 return true; |
| 308 } | 306 } |
| 309 | 307 |
| 310 // Functions that do not explicitly return a value, implicitly return null, | 308 // Consider the compile type of the value to check for sentinels, which are |
| 311 // except generative constructors, which return the object being constructed. | 309 // also treated as null. |
| 312 // It is therefore acceptable for void functions to return null. | 310 const AbstractType& compile_type = AbstractType::Handle(CompileType()); |
| 313 // In case of a null constant, we have already returned true above, else we | 311 ASSERT(!compile_type.IsMalformed()); |
| 314 // return false here. | 312 ASSERT(!compile_type.IsVoidType()); |
| 315 if (dst_type.IsVoidType()) { | 313 |
| 314 // There are only three instances that can be of type Null: |
| 315 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). |
| 316 // The inline code and run time code performing the type check will only |
| 317 // encounter the 2 sentinel values if type check elimination was disabled. |
| 318 // Otherwise, the type check of a sentinel value will be eliminated here, |
| 319 // because these sentinel values can only be encountered as constants, never |
| 320 // as actual value of a heap object being type checked. |
| 321 if (compile_type.IsNullType()) { |
| 322 *is_null = true; |
| 323 return true; |
| 324 } |
| 325 |
| 326 return false; |
| 327 } |
| 328 |
| 329 |
| 330 // TODO(regis): Support a set of compile types for the given value. |
| 331 bool Value::CanComputeIsInstanceOf(const AbstractType& type, |
| 332 bool* is_instance) const { |
| 333 ASSERT(is_instance != NULL); |
| 334 // We cannot give an answer if the given type is malformed. |
| 335 if (type.IsMalformed()) { |
| 316 return false; | 336 return false; |
| 317 } | 337 } |
| 318 | 338 |
| 339 // We should never test for an instance of null. |
| 340 ASSERT(!type.IsNullType()); |
| 341 |
| 319 // Consider the compile type of the value. | 342 // Consider the compile type of the value. |
| 320 const AbstractType& compile_type = AbstractType::Handle(CompileType()); | 343 const AbstractType& compile_type = AbstractType::Handle(CompileType()); |
| 321 ASSERT(!compile_type.IsMalformed()); | 344 ASSERT(!compile_type.IsMalformed()); |
| 322 | 345 |
| 323 // If the compile type of the value is void, we are type checking the result | 346 // If the compile type of the value is void, we are type checking the result |
| 324 // of a void function, which was checked to be null at the return statement | 347 // of a void function, which was checked to be null at the return statement |
| 325 // inside the function. | 348 // inside the function. |
| 326 if (compile_type.IsVoidType()) { | 349 if (compile_type.IsVoidType()) { |
| 350 ASSERT(FLAG_enable_type_checks); |
| 351 *is_instance = true; |
| 327 return true; | 352 return true; |
| 328 } | 353 } |
| 329 | 354 |
| 330 // If the compile type of the value is NullType, the type test is eliminated. | 355 // The Null type is only a subtype of Object and of Dynamic. |
| 331 // There are only three instances that can be of Class Null: | 356 // Functions that do not explicitly return a value, implicitly return null, |
| 332 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). | 357 // except generative constructors, which return the object being constructed. |
| 333 // The inline code and run time code performing the type check will never | 358 // It is therefore acceptable for void functions to return null. |
| 334 // encounter the 2 sentinel values. The type check of a sentinel value | |
| 335 // will always be eliminated here, because these sentinel values can only | |
| 336 // be encountered as constants, never as actual value of a heap object | |
| 337 // being type checked. | |
| 338 if (compile_type.IsNullType()) { | 359 if (compile_type.IsNullType()) { |
| 360 *is_instance = |
| 361 type.IsObjectType() || type.IsDynamicType() || type.IsVoidType(); |
| 339 return true; | 362 return true; |
| 340 } | 363 } |
| 341 | 364 |
| 365 // Until we support a set of compile types, we can only give answers for |
| 366 // constant values. Indeed, a variable of the proper compile time type may |
| 367 // still hold null at run time and therefore fail the test. |
| 368 if (!BindsToConstant()) { |
| 369 return false; |
| 370 } |
| 371 |
| 372 // A non-null constant is not an instance of void. |
| 373 if (type.IsVoidType()) { |
| 374 *is_instance = false; |
| 375 return true; |
| 376 } |
| 377 |
| 378 // Since the value is a constant, its type is instantiated. |
| 379 ASSERT(compile_type.IsInstantiated()); |
| 380 |
| 342 // The run time type of the value is guaranteed to be a subtype of the | 381 // The run time type of the value is guaranteed to be a subtype of the |
| 343 // compile time type of the value. However, establishing here that | 382 // compile time type of the value. However, establishing here that the |
| 344 // the compile time type is a subtype of the destination type does not | 383 // compile time type is a subtype of the given type does not guarantee that |
| 345 // guarantee that the run time type will also be a subtype of the destination | 384 // the run time type will also be a subtype of the given type, because the |
| 346 // type, because the subtype relation is not transitive. | 385 // subtype relation is not transitive when an uninstantiated type is |
| 347 // However, the 'more specific than' relation is transitive and is used | 386 // involved. |
| 348 // here. In other words, if the compile type of the value is more specific | 387 Error& malformed_error = Error::Handle(); |
| 349 // than the destination type, the run time type of the value, which is | 388 if (type.IsInstantiated()) { |
| 350 // guaranteed to be a subtype of the compile type, is also guaranteed to be | 389 // Perform the test on the compile-time type and provide the answer, unless |
| 351 // a subtype of the destination type and the type check can therefore be | 390 // the type test produced a malformed error (e.g. an upper bound error). |
| 352 // eliminated. | 391 *is_instance = compile_type.IsSubtypeOf(type, &malformed_error); |
| 353 return compile_type.IsMoreSpecificThan(dst_type, NULL); | 392 } else { |
| 393 // However, the 'more specific than' relation is transitive and used here. |
| 394 // In other words, if the compile type of the value is more specific than |
| 395 // the given type, the run time type of the value, which is guaranteed to be |
| 396 // a subtype of the compile type, is also guaranteed to be a subtype of the |
| 397 // given type. |
| 398 *is_instance = compile_type.IsMoreSpecificThan(type, &malformed_error); |
| 399 } |
| 400 return malformed_error.IsNull(); |
| 354 } | 401 } |
| 355 | 402 |
| 356 | 403 |
| 357 bool Value::NeedsStoreBuffer() const { | 404 bool Value::NeedsStoreBuffer() const { |
| 358 const intptr_t cid = ResultCid(); | 405 const intptr_t cid = ResultCid(); |
| 359 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) { | 406 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) { |
| 360 return false; | 407 return false; |
| 361 } | 408 } |
| 362 return !BindsToConstant(); | 409 return !BindsToConstant(); |
| 363 } | 410 } |
| (...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1707 value->set_use_index(use_index++); | 1754 value->set_use_index(use_index++); |
| 1708 value->AddToEnvUseList(); | 1755 value->AddToEnvUseList(); |
| 1709 } | 1756 } |
| 1710 instr->env()->outer_ = copy; | 1757 instr->env()->outer_ = copy; |
| 1711 } | 1758 } |
| 1712 | 1759 |
| 1713 | 1760 |
| 1714 #undef __ | 1761 #undef __ |
| 1715 | 1762 |
| 1716 } // namespace dart | 1763 } // namespace dart |
| OLD | NEW |