| 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 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 const bool requires_type_arguments = cls.HasTypeArguments(); | 1506 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 1514 | 1507 |
| 1515 ZoneGrowableArray<Value*>* allocate_arguments = | 1508 ZoneGrowableArray<Value*>* allocate_arguments = |
| 1516 new ZoneGrowableArray<Value*>(); | 1509 new ZoneGrowableArray<Value*>(); |
| 1517 if (requires_type_arguments) { | 1510 if (requires_type_arguments) { |
| 1518 BuildConstructorTypeArguments(node, allocate_arguments); | 1511 BuildConstructorTypeArguments(node, allocate_arguments); |
| 1519 } | 1512 } |
| 1520 // In checked mode, if the type arguments are uninstantiated, they may need to | 1513 // In checked mode, if the type arguments are uninstantiated, they may need to |
| 1521 // be checked against declared bounds at run time. | 1514 // be checked against declared bounds at run time. |
| 1522 Computation* allocate_comp = NULL; | 1515 Computation* allocate_comp = NULL; |
| 1523 Error& malformed_error = Error::Handle(); | |
| 1524 if (FLAG_enable_type_checks && | 1516 if (FLAG_enable_type_checks && |
| 1525 requires_type_arguments && | 1517 requires_type_arguments && |
| 1526 !node->type_arguments().IsNull() && | 1518 !node->type_arguments().IsNull() && |
| 1527 !node->type_arguments().IsInstantiated() && | 1519 !node->type_arguments().IsInstantiated() && |
| 1528 !node->type_arguments().IsWithinBoundsOf(cls, | 1520 !node->type_arguments().IsWithinBoundsOf(cls, |
| 1529 node->type_arguments(), | 1521 node->type_arguments(), |
| 1530 &malformed_error)) { | 1522 NULL)) { |
| 1531 // The uninstantiated type arguments cannot be verified to be within their | 1523 // The uninstantiated type arguments cannot be verified to be within their |
| 1532 // bounds at compile time, so verify them at runtime. | 1524 // bounds at compile time, so verify them at runtime. |
| 1533 // Although the type arguments may be uninstantiated at compile time, they | 1525 // Although the type arguments may be uninstantiated at compile time, they |
| 1534 // may represent the identity vector and may be replaced by the instantiated | 1526 // may represent the identity vector and may be replaced by the instantiated |
| 1535 // type arguments of the instantiator at run time. | 1527 // type arguments of the instantiator at run time. |
| 1536 allocate_comp = new AllocateObjectWithBoundsCheckComp(node, | 1528 allocate_comp = new AllocateObjectWithBoundsCheckComp(node, |
| 1537 owner()->try_index(), | 1529 owner()->try_index(), |
| 1538 allocate_arguments); | 1530 allocate_arguments); |
| 1539 } else { | 1531 } else { |
| 1540 allocate_comp = new AllocateObjectComp(node, | 1532 allocate_comp = new AllocateObjectComp(node, |
| (...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2730 char* chars = reinterpret_cast<char*>( | 2722 char* chars = reinterpret_cast<char*>( |
| 2731 Isolate::Current()->current_zone()->Allocate(len)); | 2723 Isolate::Current()->current_zone()->Allocate(len)); |
| 2732 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2724 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2733 const Error& error = Error::Handle( | 2725 const Error& error = Error::Handle( |
| 2734 LanguageError::New(String::Handle(String::New(chars)))); | 2726 LanguageError::New(String::Handle(String::New(chars)))); |
| 2735 Isolate::Current()->long_jump_base()->Jump(1, error); | 2727 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2736 } | 2728 } |
| 2737 | 2729 |
| 2738 | 2730 |
| 2739 } // namespace dart | 2731 } // namespace dart |
| OLD | NEW |