| 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/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 // specific than the given dst_type. | 333 // specific than the given dst_type. |
| 334 static bool IsStaticTypeMoreSpecific(Value* value, | 334 static bool IsStaticTypeMoreSpecific(Value* value, |
| 335 const AbstractType& dst_type) { | 335 const AbstractType& dst_type) { |
| 336 ASSERT(!dst_type.IsMalformed()); | 336 ASSERT(!dst_type.IsMalformed()); |
| 337 | 337 |
| 338 // Any type is more specific than the Dynamic type and than the Object type. | 338 // Any type is more specific than the Dynamic type and than the Object type. |
| 339 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { | 339 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { |
| 340 return true; | 340 return true; |
| 341 } | 341 } |
| 342 | 342 |
| 343 // It is a compile-time error to explicitly return a value (including null) |
| 344 // from a void function. However, functions that do not explicitly return a |
| 345 // value, implicitly return null. This includes void functions. Therefore, we |
| 346 // skip the type test here and trust the parser to only return null in void |
| 347 // function. |
| 348 if (dst_type.IsVoidType()) { |
| 349 // TODO(regis): Should we perform this null test at run-time? |
| 350 return true; |
| 351 } |
| 352 |
| 343 // Do not perform type check elimination if this optimization is turned off. | 353 // Do not perform type check elimination if this optimization is turned off. |
| 344 if (!FLAG_eliminate_type_checks) { | 354 if (!FLAG_eliminate_type_checks) { |
| 345 return false; | 355 return false; |
| 346 } | 356 } |
| 347 | 357 |
| 348 // If nothing is known about the value, as is the case for passed-in | 358 // If nothing is known about the value, as is the case for passed-in |
| 349 // parameters, and since dst_type is not one of the tested cases above, then | 359 // parameters, and since dst_type is not one of the tested cases above, then |
| 350 // the type test cannot be eliminated. | 360 // the type test cannot be eliminated. |
| 351 if (value == NULL) { | 361 if (value == NULL) { |
| 352 return false; | 362 return false; |
| 353 } | 363 } |
| 354 | 364 |
| 355 // If the value is the null constant, its type (NullType) is more specific | |
| 356 // than the destination type, even if the destination type is the void type, | |
| 357 // since a void function is allowed to return null. | |
| 358 if (value->IsConstant() && value->AsConstant()->value().IsNull()) { | |
| 359 return true; | |
| 360 } | |
| 361 | |
| 362 // Functions that do not explicitly return a value, implicitly return null, | |
| 363 // except generative constructors, which return the object being constructed. | |
| 364 // It is therefore acceptable for void functions to return null. | |
| 365 // In case of a null constant, we have already returned true above, else we | |
| 366 // return false here. | |
| 367 if (dst_type.IsVoidType()) { | |
| 368 return false; | |
| 369 } | |
| 370 | |
| 371 // Consider the static type of the value. | 365 // Consider the static type of the value. |
| 372 const AbstractType& static_type = AbstractType::Handle(value->StaticType()); | 366 const AbstractType& static_type = AbstractType::Handle(value->StaticType()); |
| 373 ASSERT(!static_type.IsMalformed()); | 367 ASSERT(!static_type.IsMalformed()); |
| 374 | 368 |
| 375 // If the static type of the value is void, we are type checking the result of | 369 // If the static type of the value is void, the only allowed value is null, |
| 376 // a void function, which was checked to be null at the return statement | 370 // which must be verified by the type test. |
| 377 // inside the function. | 371 // TODO(regis): Eliminate the test if the value is constant null. |
| 378 if (static_type.IsVoidType()) { | 372 if (static_type.IsVoidType()) { |
| 379 return true; | 373 return false; |
| 380 } | 374 } |
| 381 | 375 |
| 382 // If the static type of the value is NullType, the type test is eliminated. | 376 // If the static type of the value is NullType, the type test is eliminated. |
| 383 // There are only three instances that can be of Class Null: | 377 // There are only three instances that can be of Class Null: |
| 384 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). | 378 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). |
| 385 // The inline code and run time code performing the type check will never | 379 // The inline code and run time code performing the type check will never |
| 386 // encounter the 2 sentinel values. The type check of a sentinel value | 380 // encounter the 2 sentinel values. The type check of a sentinel value |
| 387 // will always be eliminated here, because these sentinel values can only | 381 // will always be eliminated here, because these sentinel values can only |
| 388 // be encountered as constants, never as actual value of a heap object | 382 // be encountered as constants, never as actual value of a heap object |
| 389 // being type checked. | 383 // being type checked. |
| (...skipping 2281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2671 char* chars = reinterpret_cast<char*>( | 2665 char* chars = reinterpret_cast<char*>( |
| 2672 Isolate::Current()->current_zone()->Allocate(len)); | 2666 Isolate::Current()->current_zone()->Allocate(len)); |
| 2673 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2667 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2674 const Error& error = Error::Handle( | 2668 const Error& error = Error::Handle( |
| 2675 LanguageError::New(String::Handle(String::New(chars)))); | 2669 LanguageError::New(String::Handle(String::New(chars)))); |
| 2676 Isolate::Current()->long_jump_base()->Jump(1, error); | 2670 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2677 } | 2671 } |
| 2678 | 2672 |
| 2679 | 2673 |
| 2680 } // namespace dart | 2674 } // namespace dart |
| OLD | NEW |