| 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 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // compile time static type of the value. However, establishing here that | 458 // compile time static type of the value. However, establishing here that |
| 459 // the static type is a subtype of the destination type does not guarantee | 459 // the static type is a subtype of the destination type does not guarantee |
| 460 // that the run time type will also be a subtype of the destination type, | 460 // that the run time type will also be a subtype of the destination type, |
| 461 // because the subtype relation is not transitive. | 461 // because the subtype relation is not transitive. |
| 462 // However, the 'more specific than' relation is transitive and is used | 462 // However, the 'more specific than' relation is transitive and is used |
| 463 // here. In other words, if the static type of the value is more specific | 463 // here. In other words, if the static type of the value is more specific |
| 464 // than the destination type, the run time type of the value, which is | 464 // than the destination type, the run time type of the value, which is |
| 465 // guaranteed to be a subtype of the static type, is also guaranteed to be | 465 // guaranteed to be a subtype of the static type, is also guaranteed to be |
| 466 // a subtype of the destination type and the type check can therefore be | 466 // a subtype of the destination type and the type check can therefore be |
| 467 // eliminated. | 467 // eliminated. |
| 468 Error& malformed_error = Error::Handle(); | 468 return static_type.IsMoreSpecificThan(dst_type, NULL); |
| 469 return static_type.IsMoreSpecificThan(dst_type, &malformed_error); | |
| 470 } | 469 } |
| 471 | 470 |
| 472 | 471 |
| 473 // Returns true if the type check can be skipped, for example, if the | 472 // Returns true if the type check can be skipped, for example, if the |
| 474 // destination type is Dynamic or if the static type of the value is a subtype | 473 // destination type is Dynamic or if the static type of the value is a subtype |
| 475 // of the destination type. | 474 // of the destination type. |
| 476 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos, | 475 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos, |
| 477 Value* value, | 476 Value* value, |
| 478 const AbstractType& dst_type, | 477 const AbstractType& dst_type, |
| 479 const String& dst_name) { | 478 const String& dst_name) { |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 | 729 |
| 731 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { | 730 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { |
| 732 ASSERT(Token::IsTypeTestOperator(node->kind())); | 731 ASSERT(Token::IsTypeTestOperator(node->kind())); |
| 733 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 732 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 734 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 733 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 735 const AbstractType& type = node->right()->AsTypeNode()->type(); | 734 const AbstractType& type = node->right()->AsTypeNode()->type(); |
| 736 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 735 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 737 const bool negate_result = (node->kind() == Token::kISNOT); | 736 const bool negate_result = (node->kind() == Token::kISNOT); |
| 738 // All objects are instances of type T if Object type is a subtype of type T. | 737 // All objects are instances of type T if Object type is a subtype of type T. |
| 739 const Type& object_type = Type::Handle(Type::ObjectType()); | 738 const Type& object_type = Type::Handle(Type::ObjectType()); |
| 740 Error& malformed_error = Error::Handle(); | 739 if (type.IsInstantiated() && object_type.IsSubtypeOf(type, NULL)) { |
| 741 if (type.IsInstantiated() && | |
| 742 object_type.IsSubtypeOf(type, &malformed_error)) { | |
| 743 // Must evaluate left side. | 740 // Must evaluate left side. |
| 744 EffectGraphVisitor for_left_value(owner(), temp_index()); | 741 EffectGraphVisitor for_left_value(owner(), temp_index()); |
| 745 node->left()->Visit(&for_left_value); | 742 node->left()->Visit(&for_left_value); |
| 746 Append(for_left_value); | 743 Append(for_left_value); |
| 747 ReturnComputation(new ConstantVal(negate_result ? bool_false : bool_true)); | 744 ReturnComputation(new ConstantVal(negate_result ? bool_false : bool_true)); |
| 748 return; | 745 return; |
| 749 } | 746 } |
| 750 | 747 |
| 751 // Eliminate the test if it can be performed successfully at compile time. | 748 // Eliminate the test if it can be performed successfully at compile time. |
| 752 if ((node->left() != NULL) && | 749 if ((node->left() != NULL) && |
| 753 node->left()->IsLiteralNode() && | 750 node->left()->IsLiteralNode() && |
| 754 type.IsInstantiated()) { | 751 type.IsInstantiated()) { |
| 755 const Instance& literal_value = node->left()->AsLiteralNode()->literal(); | 752 const Instance& literal_value = node->left()->AsLiteralNode()->literal(); |
| 756 const Class& cls = Class::Handle(literal_value.clazz()); | 753 const Class& cls = Class::Handle(literal_value.clazz()); |
| 757 ConstantVal* result = NULL; | 754 ConstantVal* result = NULL; |
| 758 if (cls.IsNullClass()) { | 755 if (cls.IsNullClass()) { |
| 759 // A null object is only an instance of Object and Dynamic, which has | 756 // A null object is only an instance of Object and Dynamic, which has |
| 760 // already been checked above (if the type is instantiated). So we can | 757 // already been checked above (if the type is instantiated). So we can |
| 761 // return false here if the instance is null (and if the type is | 758 // return false here if the instance is null (and if the type is |
| 762 // instantiated). | 759 // instantiated). |
| 763 result = new ConstantVal(negate_result ? bool_true : bool_false); | 760 result = new ConstantVal(negate_result ? bool_true : bool_false); |
| 764 } else { | 761 } else { |
| 765 Error& malformed_error = Error::Handle(); | 762 if (literal_value.IsInstanceOf(type, TypeArguments::Handle(), NULL)) { |
| 766 if (literal_value.IsInstanceOf(type, | |
| 767 TypeArguments::Handle(), | |
| 768 &malformed_error)) { | |
| 769 result = new ConstantVal(negate_result ? bool_false : bool_true); | 763 result = new ConstantVal(negate_result ? bool_false : bool_true); |
| 770 } else { | 764 } else { |
| 771 ASSERT(malformed_error.IsNull()); | |
| 772 result = new ConstantVal(negate_result ? bool_true : bool_false); | 765 result = new ConstantVal(negate_result ? bool_true : bool_false); |
| 773 } | 766 } |
| 774 } | 767 } |
| 775 ReturnComputation(result); | 768 ReturnComputation(result); |
| 776 return; | 769 return; |
| 777 } | 770 } |
| 778 | 771 |
| 779 ValueGraphVisitor for_left_value(owner(), temp_index()); | 772 ValueGraphVisitor for_left_value(owner(), temp_index()); |
| 780 node->left()->Visit(&for_left_value); | 773 node->left()->Visit(&for_left_value); |
| 781 Append(for_left_value); | 774 Append(for_left_value); |
| (...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 const bool requires_type_arguments = cls.HasTypeArguments(); | 1482 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 1490 | 1483 |
| 1491 ZoneGrowableArray<Value*>* allocate_arguments = | 1484 ZoneGrowableArray<Value*>* allocate_arguments = |
| 1492 new ZoneGrowableArray<Value*>(); | 1485 new ZoneGrowableArray<Value*>(); |
| 1493 if (requires_type_arguments) { | 1486 if (requires_type_arguments) { |
| 1494 BuildConstructorTypeArguments(node, allocate_arguments); | 1487 BuildConstructorTypeArguments(node, allocate_arguments); |
| 1495 } | 1488 } |
| 1496 // In checked mode, if the type arguments are uninstantiated, they may need to | 1489 // In checked mode, if the type arguments are uninstantiated, they may need to |
| 1497 // be checked against declared bounds at run time. | 1490 // be checked against declared bounds at run time. |
| 1498 Computation* allocate_comp = NULL; | 1491 Computation* allocate_comp = NULL; |
| 1499 Error& malformed_error = Error::Handle(); | |
| 1500 if (FLAG_enable_type_checks && | 1492 if (FLAG_enable_type_checks && |
| 1501 requires_type_arguments && | 1493 requires_type_arguments && |
| 1502 !node->type_arguments().IsNull() && | 1494 !node->type_arguments().IsNull() && |
| 1503 !node->type_arguments().IsInstantiated() && | 1495 !node->type_arguments().IsInstantiated() && |
| 1504 !node->type_arguments().IsWithinBoundsOf(cls, | 1496 !node->type_arguments().IsWithinBoundsOf(cls, |
| 1505 node->type_arguments(), | 1497 node->type_arguments(), |
| 1506 &malformed_error)) { | 1498 NULL)) { |
| 1507 // The uninstantiated type arguments cannot be verified to be within their | 1499 // The uninstantiated type arguments cannot be verified to be within their |
| 1508 // bounds at compile time, so verify them at runtime. | 1500 // bounds at compile time, so verify them at runtime. |
| 1509 // Although the type arguments may be uninstantiated at compile time, they | 1501 // Although the type arguments may be uninstantiated at compile time, they |
| 1510 // may represent the identity vector and may be replaced by the instantiated | 1502 // may represent the identity vector and may be replaced by the instantiated |
| 1511 // type arguments of the instantiator at run time. | 1503 // type arguments of the instantiator at run time. |
| 1512 allocate_comp = new AllocateObjectWithBoundsCheckComp(node, | 1504 allocate_comp = new AllocateObjectWithBoundsCheckComp(node, |
| 1513 owner()->try_index(), | 1505 owner()->try_index(), |
| 1514 allocate_arguments); | 1506 allocate_arguments); |
| 1515 } else { | 1507 } else { |
| 1516 allocate_comp = new AllocateObjectComp(node, | 1508 allocate_comp = new AllocateObjectComp(node, |
| (...skipping 1179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2696 char* chars = reinterpret_cast<char*>( | 2688 char* chars = reinterpret_cast<char*>( |
| 2697 Isolate::Current()->current_zone()->Allocate(len)); | 2689 Isolate::Current()->current_zone()->Allocate(len)); |
| 2698 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2690 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2699 const Error& error = Error::Handle( | 2691 const Error& error = Error::Handle( |
| 2700 LanguageError::New(String::Handle(String::New(chars)))); | 2692 LanguageError::New(String::Handle(String::New(chars)))); |
| 2701 Isolate::Current()->long_jump_base()->Jump(1, error); | 2693 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2702 } | 2694 } |
| 2703 | 2695 |
| 2704 | 2696 |
| 2705 } // namespace dart | 2697 } // namespace dart |
| OLD | NEW |