Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: runtime/vm/object.cc

Issue 81363002: Improve type test and type equality for generics (issue 15148). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 2760 matching lines...) Expand 10 before | Expand all | Expand 10 after
2771 return (test_kind == Class::kIsMoreSpecificThan) || 2771 return (test_kind == Class::kIsMoreSpecificThan) ||
2772 other.IsObjectClass() || other.IsNullClass(); 2772 other.IsObjectClass() || other.IsNullClass();
2773 } 2773 }
2774 // Check for ObjectType. Any type that is not NullType or DynamicType 2774 // Check for ObjectType. Any type that is not NullType or DynamicType
2775 // (already checked above), is more specific than ObjectType. 2775 // (already checked above), is more specific than ObjectType.
2776 if (other.IsObjectClass()) { 2776 if (other.IsObjectClass()) {
2777 return true; 2777 return true;
2778 } 2778 }
2779 // Check for reflexivity. 2779 // Check for reflexivity.
2780 if (thsi.raw() == other.raw()) { 2780 if (thsi.raw() == other.raw()) {
2781 const intptr_t len = thsi.NumTypeArguments(); 2781 const intptr_t num_type_args = thsi.NumTypeArguments();
2782 if (len == 0) { 2782 if (num_type_args == 0) {
2783 return true; 2783 return true;
2784 } 2784 }
2785 const intptr_t num_type_params = thsi.NumTypeParameters();
2786 const intptr_t from_index = num_type_args - num_type_params;
2785 // Since we do not truncate the type argument vector of a subclass (see 2787 // Since we do not truncate the type argument vector of a subclass (see
2786 // below), we only check a prefix of the proper length. 2788 // below), we only check a subvector of the proper length.
2787 // Check for covariance. 2789 // Check for covariance.
2788 if (other_type_arguments.IsNull() || other_type_arguments.IsRaw(len)) { 2790 if (other_type_arguments.IsNull() ||
2791 other_type_arguments.IsRaw(from_index, num_type_params)) {
2789 return true; 2792 return true;
2790 } 2793 }
2791 if (type_arguments.IsNull() || type_arguments.IsRaw(len)) { 2794 if (type_arguments.IsNull() ||
2795 type_arguments.IsRaw(from_index, num_type_params)) {
2792 // Other type can't be more specific than this one because for that 2796 // Other type can't be more specific than this one because for that
2793 // it would have to have all dynamic type arguments which is checked 2797 // it would have to have all dynamic type arguments which is checked
2794 // above. 2798 // above.
2795 return test_kind == Class::kIsSubtypeOf; 2799 return test_kind == Class::kIsSubtypeOf;
2796 } 2800 }
2797 return type_arguments.TypeTest(test_kind, 2801 return type_arguments.TypeTest(test_kind,
2798 other_type_arguments, 2802 other_type_arguments,
2799 len, 2803 from_index,
2804 num_type_params,
2800 bound_error); 2805 bound_error);
2801 } 2806 }
2802 const bool other_is_function_class = other.IsFunctionClass(); 2807 const bool other_is_function_class = other.IsFunctionClass();
2803 if (other.IsSignatureClass() || other_is_function_class) { 2808 if (other.IsSignatureClass() || other_is_function_class) {
2804 const Function& other_fun = Function::Handle(other.signature_function()); 2809 const Function& other_fun = Function::Handle(other.signature_function());
2805 if (thsi.IsSignatureClass()) { 2810 if (thsi.IsSignatureClass()) {
2806 if (other_is_function_class) { 2811 if (other_is_function_class) {
2807 return true; 2812 return true;
2808 } 2813 }
2809 // Check for two function types. 2814 // Check for two function types.
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
3452 } 3457 }
3453 } 3458 }
3454 strings.SetAt(s++, Symbols::RAngleBracket()); 3459 strings.SetAt(s++, Symbols::RAngleBracket());
3455 ASSERT(s == num_strings); 3460 ASSERT(s == num_strings);
3456 name = String::ConcatAll(strings); 3461 name = String::ConcatAll(strings);
3457 return Symbols::New(name); 3462 return Symbols::New(name);
3458 } 3463 }
3459 3464
3460 3465
3461 bool AbstractTypeArguments::Equals(const AbstractTypeArguments& other) const { 3466 bool AbstractTypeArguments::Equals(const AbstractTypeArguments& other) const {
3462 ASSERT(!IsNull()); // Use AbstractTypeArguments::AreEqual().
3463 if (this->raw() == other.raw()) { 3467 if (this->raw() == other.raw()) {
3464 return true; 3468 return true;
3465 } 3469 }
3466 if (other.IsNull()) { 3470 if (IsNull() || other.IsNull()) {
3467 return false; 3471 return false;
3468 } 3472 }
3469 const intptr_t num_types = Length(); 3473 const intptr_t num_types = Length();
3470 if (num_types != other.Length()) { 3474 if (num_types != other.Length()) {
3471 return false; 3475 return false;
3472 } 3476 }
3473 AbstractType& type = AbstractType::Handle(); 3477 AbstractType& type = AbstractType::Handle();
3474 AbstractType& other_type = AbstractType::Handle(); 3478 AbstractType& other_type = AbstractType::Handle();
3475 for (intptr_t i = 0; i < num_types; i++) { 3479 for (intptr_t i = 0; i < num_types; i++) {
3476 type = TypeAt(i); 3480 type = TypeAt(i);
3477 other_type = other.TypeAt(i); 3481 other_type = other.TypeAt(i);
3478 if (!type.Equals(other_type)) { 3482 if (!type.Equals(other_type)) {
3479 return false; 3483 return false;
3480 } 3484 }
3481 } 3485 }
3482 return true; 3486 return true;
3483 } 3487 }
3484 3488
3485 3489
3486 bool AbstractTypeArguments::AreEqual(
3487 const AbstractTypeArguments& arguments,
3488 const AbstractTypeArguments& other_arguments) {
3489 if (arguments.raw() == other_arguments.raw()) {
3490 return true;
3491 }
3492 if (arguments.IsNull()) {
3493 return other_arguments.IsDynamicTypes(false, other_arguments.Length());
3494 }
3495 if (other_arguments.IsNull()) {
3496 return arguments.IsDynamicTypes(false, arguments.Length());
3497 }
3498 return arguments.Equals(other_arguments);
3499 }
3500
3501
3502 RawAbstractTypeArguments* AbstractTypeArguments::InstantiateFrom( 3490 RawAbstractTypeArguments* AbstractTypeArguments::InstantiateFrom(
3503 const AbstractTypeArguments& instantiator_type_arguments, 3491 const AbstractTypeArguments& instantiator_type_arguments,
3504 Error* bound_error) const { 3492 Error* bound_error) const {
3505 // AbstractTypeArguments is an abstract class. 3493 // AbstractTypeArguments is an abstract class.
3506 UNREACHABLE(); 3494 UNREACHABLE();
3507 return NULL; 3495 return NULL;
3508 } 3496 }
3509 3497
3510 3498
3511 bool AbstractTypeArguments::IsDynamicTypes(bool raw_instantiated, 3499 bool AbstractTypeArguments::IsDynamicTypes(bool raw_instantiated,
3500 intptr_t from_index,
3512 intptr_t len) const { 3501 intptr_t len) const {
3513 ASSERT(Length() >= len); 3502 ASSERT(Length() >= (from_index + len));
3514 AbstractType& type = AbstractType::Handle(); 3503 AbstractType& type = AbstractType::Handle();
3515 Class& type_class = Class::Handle(); 3504 Class& type_class = Class::Handle();
3516 for (intptr_t i = 0; i < len; i++) { 3505 for (intptr_t i = 0; i < len; i++) {
3517 type = TypeAt(i); 3506 type = TypeAt(from_index + i);
3518 ASSERT(!type.IsNull()); 3507 ASSERT(!type.IsNull());
3519 if (!type.HasResolvedTypeClass()) { 3508 if (!type.HasResolvedTypeClass()) {
3520 if (raw_instantiated && type.IsTypeParameter()) { 3509 if (raw_instantiated && type.IsTypeParameter()) {
3521 // An uninstantiated type parameter is equivalent to dynamic (even in 3510 // An uninstantiated type parameter is equivalent to dynamic (even in
3522 // the presence of a malformed bound in checked mode). 3511 // the presence of a malformed bound in checked mode).
3523 continue; 3512 continue;
3524 } 3513 }
3525 ASSERT((!raw_instantiated && type.IsTypeParameter()) || 3514 ASSERT((!raw_instantiated && type.IsTypeParameter()) ||
3526 type.IsBoundedType() || 3515 type.IsBoundedType() ||
3527 type.IsMalformed()); 3516 type.IsMalformed());
3528 return false; 3517 return false;
3529 } 3518 }
3530 type_class = type.type_class(); 3519 type_class = type.type_class();
3531 if (!type_class.IsDynamicClass()) { 3520 if (!type_class.IsDynamicClass()) {
3532 return false; 3521 return false;
3533 } 3522 }
3534 } 3523 }
3535 return true; 3524 return true;
3536 } 3525 }
3537 3526
3538 3527
3539 bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind, 3528 bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind,
3540 const AbstractTypeArguments& other, 3529 const AbstractTypeArguments& other,
3530 intptr_t from_index,
3541 intptr_t len, 3531 intptr_t len,
3542 Error* bound_error) const { 3532 Error* bound_error) const {
3543 ASSERT(Length() >= len); 3533 ASSERT(Length() >= (from_index + len));
3544 ASSERT(!other.IsNull()); 3534 ASSERT(!other.IsNull());
3545 ASSERT(other.Length() >= len); 3535 ASSERT(other.Length() >= (from_index + len));
3546 AbstractType& type = AbstractType::Handle(); 3536 AbstractType& type = AbstractType::Handle();
3547 AbstractType& other_type = AbstractType::Handle(); 3537 AbstractType& other_type = AbstractType::Handle();
3548 for (intptr_t i = 0; i < len; i++) { 3538 for (intptr_t i = 0; i < len; i++) {
3549 type = TypeAt(i); 3539 type = TypeAt(from_index + i);
3550 ASSERT(!type.IsNull()); 3540 ASSERT(!type.IsNull());
3551 other_type = other.TypeAt(i); 3541 other_type = other.TypeAt(from_index + i);
3552 ASSERT(!other_type.IsNull()); 3542 ASSERT(!other_type.IsNull());
3553 if (!type.TypeTest(test_kind, other_type, bound_error)) { 3543 if (!type.TypeTest(test_kind, other_type, bound_error)) {
3554 return false; 3544 return false;
3555 } 3545 }
3556 } 3546 }
3557 return true; 3547 return true;
3558 } 3548 }
3559 3549
3560 3550
3561 const char* AbstractTypeArguments::ToCString() const { 3551 const char* AbstractTypeArguments::ToCString() const {
(...skipping 8434 matching lines...) Expand 10 before | Expand all | Expand 10 after
11996 Type& instantiated_type = Type::Handle( 11986 Type& instantiated_type = Type::Handle(
11997 Type::New(cls, type_arguments, token_pos())); 11987 Type::New(cls, type_arguments, token_pos()));
11998 ASSERT(type_arguments.IsNull() || 11988 ASSERT(type_arguments.IsNull() ||
11999 (type_arguments.Length() == cls.NumTypeArguments())); 11989 (type_arguments.Length() == cls.NumTypeArguments()));
12000 instantiated_type.SetIsFinalized(); 11990 instantiated_type.SetIsFinalized();
12001 return instantiated_type.raw(); 11991 return instantiated_type.raw();
12002 } 11992 }
12003 11993
12004 11994
12005 bool Type::Equals(const Instance& other) const { 11995 bool Type::Equals(const Instance& other) const {
11996 ASSERT(!IsNull());
12006 if (raw() == other.raw()) { 11997 if (raw() == other.raw()) {
12007 return true; 11998 return true;
12008 } 11999 }
12009 if (!other.IsType()) { 12000 if (!other.IsType()) {
12010 return false; 12001 return false;
12011 } 12002 }
12012 const Type& other_type = Type::Cast(other); 12003 const Type& other_type = Type::Cast(other);
12013 ASSERT(IsResolved() && other_type.IsResolved()); 12004 ASSERT(IsResolved() && other_type.IsResolved());
12014 if (IsMalformed() || other_type.IsMalformed()) { 12005 if (IsMalformed() || other_type.IsMalformed()) {
12015 return false; 12006 return false;
12016 } 12007 }
12017 if (type_class() != other_type.type_class()) { 12008 if (type_class() != other_type.type_class()) {
12018 return false; 12009 return false;
12019 } 12010 }
12020 if (!IsFinalized() || !other_type.IsFinalized()) { 12011 if (!IsFinalized() || !other_type.IsFinalized()) {
12021 return false; 12012 return false;
12022 } 12013 }
12023 return AbstractTypeArguments::AreEqual( 12014 if (arguments() == other_type.arguments()) {
12024 AbstractTypeArguments::Handle(arguments()), 12015 return true;
12025 AbstractTypeArguments::Handle(other_type.arguments())); 12016 }
12017 const Class& cls = Class::Handle(type_class());
12018 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
12019 arguments());
12020 const AbstractTypeArguments& other_type_args = AbstractTypeArguments::Handle(
12021 other_type.arguments());
12022 const intptr_t num_type_args = cls.NumTypeArguments();
12023 const intptr_t num_type_params = cls.NumTypeParameters();
12024 const intptr_t from_index = num_type_args - num_type_params;
12025 if (type_args.IsNull()) {
12026 return other_type_args.IsRaw(from_index, num_type_params);
12027 }
12028 if (other_type_args.IsNull()) {
12029 return type_args.IsRaw(from_index, num_type_params);
12030 }
12031 ASSERT(type_args.Length() >= (from_index + num_type_params));
12032 ASSERT(other_type_args.Length() >= (from_index + num_type_params));
12033 AbstractType& type_arg = AbstractType::Handle();
12034 AbstractType& other_type_arg = AbstractType::Handle();
12035 for (intptr_t i = 0; i < num_type_params; i++) {
12036 type_arg = type_args.TypeAt(from_index + i);
12037 other_type_arg = other_type_args.TypeAt(from_index + i);
12038 if (!type_arg.Equals(other_type_arg)) {
12039 return false;
12040 }
12041 }
12042 return true;
12026 } 12043 }
12027 12044
12028 12045
12029 RawAbstractType* Type::CloneUnfinalized() const { 12046 RawAbstractType* Type::CloneUnfinalized() const {
12030 ASSERT(IsResolved()); 12047 ASSERT(IsResolved());
12031 if (IsFinalized()) { 12048 if (IsFinalized()) {
12032 return raw(); 12049 return raw();
12033 } 12050 }
12034 ASSERT(!IsMalformed()); // Malformed types are finalized. 12051 ASSERT(!IsMalformed()); // Malformed types are finalized.
12035 ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization. 12052 ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
(...skipping 29 matching lines...) Expand all
12065 break; 12082 break;
12066 } 12083 }
12067 ASSERT(type.IsFinalized()); 12084 ASSERT(type.IsFinalized());
12068 if (this->Equals(type)) { 12085 if (this->Equals(type)) {
12069 return type.raw(); 12086 return type.raw();
12070 } 12087 }
12071 index++; 12088 index++;
12072 } 12089 }
12073 // Canonicalize the type arguments. 12090 // Canonicalize the type arguments.
12074 AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments()); 12091 AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments());
12092 ASSERT(type_args.IsNull() || (type_args.Length() == cls.NumTypeArguments()));
12075 type_args = type_args.Canonicalize(); 12093 type_args = type_args.Canonicalize();
12076 set_arguments(type_args); 12094 set_arguments(type_args);
12077 // The type needs to be added to the list. Grow the list if it is full. 12095 // The type needs to be added to the list. Grow the list if it is full.
12078 if (index == canonical_types_len) { 12096 if (index == canonical_types_len) {
12079 const intptr_t kLengthIncrement = 2; // Raw and parameterized. 12097 const intptr_t kLengthIncrement = 2; // Raw and parameterized.
12080 const intptr_t new_length = canonical_types.Length() + kLengthIncrement; 12098 const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
12081 const Array& new_canonical_types = 12099 const Array& new_canonical_types =
12082 Array::Handle(Array::Grow(canonical_types, new_length, Heap::kOld)); 12100 Array::Handle(Array::Grow(canonical_types, new_length, Heap::kOld));
12083 cls.set_canonical_types(new_canonical_types); 12101 cls.set_canonical_types(new_canonical_types);
12084 new_canonical_types.SetAt(index, *this); 12102 new_canonical_types.SetAt(index, *this);
(...skipping 2784 matching lines...) Expand 10 before | Expand all | Expand 10 after
14869 JSONObject jsobj(stream); 14887 JSONObject jsobj(stream);
14870 } 14888 }
14871 14889
14872 14890
14873 bool Array::Equals(const Instance& other) const { 14891 bool Array::Equals(const Instance& other) const {
14874 if (this->raw() == other.raw()) { 14892 if (this->raw() == other.raw()) {
14875 // Both handles point to the same raw instance. 14893 // Both handles point to the same raw instance.
14876 return true; 14894 return true;
14877 } 14895 }
14878 14896
14897 // An Array may be compared to an ImmutableArray.
14879 if (!other.IsArray() || other.IsNull()) { 14898 if (!other.IsArray() || other.IsNull()) {
14880 return false; 14899 return false;
14881 } 14900 }
14882 14901
14883 // Must have the same type arguments. 14902 // Both arrays must have the same type arguments.
14884 if (!AbstractTypeArguments::AreEqual( 14903 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
14885 AbstractTypeArguments::Handle(GetTypeArguments()), 14904 GetTypeArguments());
14886 AbstractTypeArguments::Handle(other.GetTypeArguments()))) { 14905 const AbstractTypeArguments& other_type_args = AbstractTypeArguments::Handle(
14906 other.GetTypeArguments());
14907 if (!type_args.Equals(other_type_args)) {
14887 return false; 14908 return false;
14888 } 14909 }
14889 14910
14890 const Array& other_arr = Array::Cast(other); 14911 const Array& other_arr = Array::Cast(other);
14891 14912
14892 intptr_t len = this->Length(); 14913 intptr_t len = this->Length();
14893 if (len != other_arr.Length()) { 14914 if (len != other_arr.Length()) {
14894 return false; 14915 return false;
14895 } 14916 }
14896 14917
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
15095 return false; 15116 return false;
15096 } 15117 }
15097 15118
15098 const GrowableObjectArray& other_arr = GrowableObjectArray::Cast(other); 15119 const GrowableObjectArray& other_arr = GrowableObjectArray::Cast(other);
15099 15120
15100 // The capacity and length of both objects must be equal. 15121 // The capacity and length of both objects must be equal.
15101 if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) { 15122 if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) {
15102 return false; 15123 return false;
15103 } 15124 }
15104 15125
15105 // Both must have the same type arguments. 15126 // Both arrays must have the same type arguments.
15106 if (!AbstractTypeArguments::AreEqual( 15127 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
15107 AbstractTypeArguments::Handle(GetTypeArguments()), 15128 GetTypeArguments());
15108 AbstractTypeArguments::Handle(other.GetTypeArguments()))) { 15129 const AbstractTypeArguments& other_type_args = AbstractTypeArguments::Handle(
15130 other.GetTypeArguments());
15131 if (!type_args.Equals(other_type_args)) {
15109 return false; 15132 return false;
15110 } 15133 }
15111 15134
15112 // The data part in both arrays must be identical. 15135 // The data part in both arrays must be identical.
15113 const Array& contents = Array::Handle(data()); 15136 const Array& contents = Array::Handle(data());
15114 const Array& other_contents = Array::Handle(other_arr.data()); 15137 const Array& other_contents = Array::Handle(other_arr.data());
15115 for (intptr_t i = 0; i < Length(); i++) { 15138 for (intptr_t i = 0; i < Length(); i++) {
15116 if (contents.At(i) != other_contents.At(i)) { 15139 if (contents.At(i) != other_contents.At(i)) {
15117 return false; 15140 return false;
15118 } 15141 }
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after
15933 return "_MirrorReference"; 15956 return "_MirrorReference";
15934 } 15957 }
15935 15958
15936 15959
15937 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 15960 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
15938 JSONObject jsobj(stream); 15961 JSONObject jsobj(stream);
15939 } 15962 }
15940 15963
15941 15964
15942 } // namespace dart 15965 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698