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_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 // For now, we can only return a meaningful result if the value is constant. |
| 299 if (dst_type.IsMalformed()) { | 297 if (!BindsToConstant()) { |
| 300 return false; | 298 return false; |
| 301 } | 299 } |
| 302 | 300 |
| 303 // If the value is the null constant, its type (NullType) is more specific | 301 // 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()) { | 302 if (BindsToConstantNull()) { |
| 303 *is_null = true; | |
| 307 return true; | 304 return true; |
| 308 } | 305 } |
| 309 | 306 |
| 310 // Functions that do not explicitly return a value, implicitly return null, | 307 // Consider the compile type of the value to check for sentinels, which are |
| 311 // except generative constructors, which return the object being constructed. | 308 // also treated as null. |
| 312 // It is therefore acceptable for void functions to return null. | 309 const AbstractType& compile_type = AbstractType::Handle(CompileType()); |
| 313 // In case of a null constant, we have already returned true above, else we | 310 ASSERT(!compile_type.IsMalformed()); |
| 314 // return false here. | 311 ASSERT(!compile_type.IsVoidType()); |
| 315 if (dst_type.IsVoidType()) { | 312 |
| 313 // There are only three instances that can be of type Null: | |
| 314 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). | |
| 315 // The inline code and run time code performing the type check will only | |
| 316 // encounter the 2 sentinel values if type check elimination was disabled. | |
| 317 // Otherwise, the type check of a sentinel value will be eliminated here, | |
| 318 // because these sentinel values can only be encountered as constants, never | |
| 319 // as actual value of a heap object being type checked. | |
| 320 if (compile_type.IsNullType()) { | |
| 321 *is_null = true; | |
| 322 return true; | |
| 323 } | |
| 324 | |
| 325 return false; | |
| 326 } | |
| 327 | |
| 328 | |
| 329 // TODO(regis): Support a set of compile types for the given value. | |
| 330 bool Value::CanComputeIsInstanceOf(const AbstractType& type, | |
| 331 bool* is_instance) const { | |
| 332 // We cannot give an answer if the given type is malformed. | |
| 333 if (type.IsMalformed()) { | |
| 316 return false; | 334 return false; |
| 317 } | 335 } |
| 318 | 336 |
| 337 // We should never test for an instance of null. | |
| 338 ASSERT(!type.IsNullType()); | |
| 339 | |
| 319 // Consider the compile type of the value. | 340 // Consider the compile type of the value. |
| 320 const AbstractType& compile_type = AbstractType::Handle(CompileType()); | 341 const AbstractType& compile_type = AbstractType::Handle(CompileType()); |
| 321 ASSERT(!compile_type.IsMalformed()); | 342 ASSERT(!compile_type.IsMalformed()); |
| 322 | 343 |
| 323 // If the compile type of the value is void, we are type checking the result | 344 // 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 | 345 // of a void function, which was checked to be null at the return statement |
| 325 // inside the function. | 346 // inside the function. |
| 326 if (compile_type.IsVoidType()) { | 347 if (compile_type.IsVoidType()) { |
| 348 ASSERT(FLAG_enable_type_checks); | |
| 327 return true; | 349 return true; |
|
zerny-google
2012/09/18 11:20:24
is_instance does not appear to be set when this re
regis
2012/09/18 14:55:44
Good catch!
| |
| 328 } | 350 } |
| 329 | 351 |
| 330 // If the compile type of the value is NullType, the type test is eliminated. | 352 // The Null type is only a subtype of Object and of Dynamic. |
| 331 // There are only three instances that can be of Class Null: | 353 // Functions that do not explicitly return a value, implicitly return null, |
| 332 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). | 354 // except generative constructors, which return the object being constructed. |
| 333 // The inline code and run time code performing the type check will never | 355 // 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()) { | 356 if (compile_type.IsNullType()) { |
| 357 *is_instance = | |
| 358 type.IsObjectType() || type.IsDynamicType() || type.IsVoidType(); | |
| 339 return true; | 359 return true; |
| 340 } | 360 } |
| 341 | 361 |
| 362 // Until we support a set of compile types, we can only give answers for | |
| 363 // constant values. Indeed, a variable of the proper compile time type may | |
| 364 // still hold null at run time and therefore fail the test. | |
| 365 if (!BindsToConstant()) { | |
| 366 return false; | |
| 367 } | |
| 368 | |
| 369 // A non-null constant is not an instance of void. | |
| 370 if (type.IsVoidType()) { | |
| 371 *is_instance = false; | |
| 372 return true; | |
| 373 } | |
| 374 | |
| 375 // Since the value is a constant, its type is instantiated. | |
| 376 ASSERT(compile_type.IsInstantiated()); | |
| 377 | |
| 342 // The run time type of the value is guaranteed to be a subtype of the | 378 // 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 | 379 // 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 | 380 // 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 | 381 // the run time type will also be a subtype of the given type, because the |
| 346 // type, because the subtype relation is not transitive. | 382 // subtype relation is not transitive when an uninstantiated type is |
| 347 // However, the 'more specific than' relation is transitive and is used | 383 // involved. |
| 348 // here. In other words, if the compile type of the value is more specific | 384 Error& malformed_error = Error::Handle(); |
| 349 // than the destination type, the run time type of the value, which is | 385 if (type.IsInstantiated()) { |
| 350 // guaranteed to be a subtype of the compile type, is also guaranteed to be | 386 // 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 | 387 // the type test produced a malformed error (e.g. an upper bound error). |
| 352 // eliminated. | 388 *is_instance = compile_type.IsSubtypeOf(type, &malformed_error); |
| 353 return compile_type.IsMoreSpecificThan(dst_type, NULL); | 389 } else { |
| 390 // However, the 'more specific than' relation is transitive and used here. | |
| 391 // In other words, if the compile type of the value is more specific than | |
| 392 // the given type, the run time type of the value, which is guaranteed to be | |
| 393 // a subtype of the compile type, is also guaranteed to be a subtype of the | |
| 394 // given type. | |
| 395 *is_instance = compile_type.IsMoreSpecificThan(type, &malformed_error); | |
| 396 } | |
| 397 return malformed_error.IsNull(); | |
| 354 } | 398 } |
| 355 | 399 |
| 356 | 400 |
| 357 bool Value::NeedsStoreBuffer() const { | 401 bool Value::NeedsStoreBuffer() const { |
| 358 const intptr_t cid = ResultCid(); | 402 const intptr_t cid = ResultCid(); |
| 359 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) { | 403 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) { |
| 360 return false; | 404 return false; |
| 361 } | 405 } |
| 362 return !BindsToConstant(); | 406 return !BindsToConstant(); |
| 363 } | 407 } |
| (...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1692 value->set_use_index(use_index++); | 1736 value->set_use_index(use_index++); |
| 1693 value->AddToEnvUseList(); | 1737 value->AddToEnvUseList(); |
| 1694 } | 1738 } |
| 1695 instr->set_env(copy); | 1739 instr->set_env(copy); |
| 1696 } | 1740 } |
| 1697 | 1741 |
| 1698 | 1742 |
| 1699 #undef __ | 1743 #undef __ |
| 1700 | 1744 |
| 1701 } // namespace dart | 1745 } // namespace dart |
| OLD | NEW |