| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 // production mode and checked mode, because the finalized type may be written | 620 // production mode and checked mode, because the finalized type may be written |
| 621 // to a snapshot. It would be wrong to ignore bounds when generating the | 621 // to a snapshot. It would be wrong to ignore bounds when generating the |
| 622 // snapshot in production mode and then use the unchecked type in checked mode | 622 // snapshot in production mode and then use the unchecked type in checked mode |
| 623 // after reading it from the snapshot. | 623 // after reading it from the snapshot. |
| 624 // However, we do not immediately report a bound error, which would be wrong | 624 // However, we do not immediately report a bound error, which would be wrong |
| 625 // in production mode, but simply postpone the bound checking to runtime. | 625 // in production mode, but simply postpone the bound checking to runtime. |
| 626 const intptr_t num_type_params = cls.NumTypeParameters(); | 626 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 627 const intptr_t offset = cls.NumTypeArguments() - num_type_params; | 627 const intptr_t offset = cls.NumTypeArguments() - num_type_params; |
| 628 AbstractType& type_arg = AbstractType::Handle(); | 628 AbstractType& type_arg = AbstractType::Handle(); |
| 629 AbstractType& cls_type_param = AbstractType::Handle(); | 629 AbstractType& cls_type_param = AbstractType::Handle(); |
| 630 AbstractType& bound = AbstractType::Handle(); | 630 AbstractType& declared_bound = AbstractType::Handle(); |
| 631 AbstractType& instantiated_bound = AbstractType::Handle(); |
| 631 const TypeArguments& cls_type_params = | 632 const TypeArguments& cls_type_params = |
| 632 TypeArguments::Handle(cls.type_parameters()); | 633 TypeArguments::Handle(cls.type_parameters()); |
| 633 ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) || | 634 ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) || |
| 634 (cls_type_params.Length() == num_type_params)); | 635 (cls_type_params.Length() == num_type_params)); |
| 635 for (intptr_t i = 0; i < num_type_params; i++) { | 636 for (intptr_t i = 0; i < num_type_params; i++) { |
| 636 type_arg = arguments.TypeAt(offset + i); | 637 type_arg = arguments.TypeAt(offset + i); |
| 637 if (type_arg.IsDynamicType()) { | 638 if (type_arg.IsDynamicType()) { |
| 638 continue; | 639 continue; |
| 639 } | 640 } |
| 640 cls_type_param = cls_type_params.TypeAt(i); | 641 cls_type_param = cls_type_params.TypeAt(i); |
| 641 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); | 642 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); |
| 642 ASSERT(type_param.IsFinalized()); | 643 ASSERT(type_param.IsFinalized()); |
| 643 bound = type_param.bound(); | 644 declared_bound = type_param.bound(); |
| 644 if (!bound.IsObjectType() && !bound.IsDynamicType()) { | 645 if (!declared_bound.IsObjectType() && !declared_bound.IsDynamicType()) { |
| 645 Error& malformed_error = Error::Handle(); | 646 Error& malformed_error = Error::Handle(); |
| 646 // Note that the bound may be malformed, in which case the bound check | 647 // Note that the bound may be malformed, in which case the bound check |
| 647 // will return an error and the bound check will be postponed to run time. | 648 // will return an error and the bound check will be postponed to run time. |
| 648 // Note also that the bound may still be unfinalized. | 649 // Note also that the bound may still be unfinalized. |
| 649 if (!bound.IsFinalized()) { | 650 if (!declared_bound.IsFinalized()) { |
| 650 ASSERT(bound.IsBeingFinalized()); | 651 ASSERT(declared_bound.IsBeingFinalized()); |
| 651 // The bound refers to type parameters, creating a cycle; postpone | 652 // The bound refers to type parameters, creating a cycle; postpone |
| 652 // bound check to run time, when the bound will be finalized. | 653 // bound check to run time, when the bound will be finalized. |
| 653 // TODO(regis): Do we need to instantiate an uninstantiated bound here? | 654 // TODO(regis): Do we need to instantiate an uninstantiated bound here? |
| 654 type_arg = BoundedType::New(type_arg, bound, type_param); | 655 type_arg = BoundedType::New(type_arg, declared_bound, type_param); |
| 655 arguments.SetTypeAt(offset + i, type_arg); | 656 arguments.SetTypeAt(offset + i, type_arg); |
| 656 continue; | 657 continue; |
| 657 } | 658 } |
| 658 if (!bound.IsInstantiated()) { | 659 if (declared_bound.IsInstantiated()) { |
| 659 bound = bound.InstantiateFrom(arguments, &malformed_error); | 660 instantiated_bound = declared_bound.raw(); |
| 661 } else { |
| 662 instantiated_bound = |
| 663 declared_bound.InstantiateFrom(arguments, &malformed_error); |
| 660 } | 664 } |
| 661 // TODO(regis): We could simplify this code if we could differentiate | 665 // TODO(regis): We could simplify this code if we could differentiate |
| 662 // between a failed bound check and a bound check that is undecidable at | 666 // between a failed bound check and a bound check that is undecidable at |
| 663 // compile time. | 667 // compile time. |
| 664 if (malformed_error.IsNull()) { | 668 // Shortcut the special case where we check a type parameter against its |
| 665 type_param.CheckBound(type_arg, bound, &malformed_error); | 669 // declared upper bound. |
| 670 if (malformed_error.IsNull() && |
| 671 (!type_arg.Equals(type_param) || |
| 672 !instantiated_bound.Equals(declared_bound))) { |
| 673 type_param.CheckBound(type_arg, instantiated_bound, &malformed_error); |
| 666 } | 674 } |
| 667 if (!malformed_error.IsNull()) { | 675 if (!malformed_error.IsNull()) { |
| 668 if (!type_arg.IsInstantiated() || !bound.IsInstantiated()) { | 676 if (!type_arg.IsInstantiated() || |
| 669 type_arg = BoundedType::New(type_arg, bound, type_param); | 677 !instantiated_bound.IsInstantiated()) { |
| 678 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); |
| 670 arguments.SetTypeAt(offset + i, type_arg); | 679 arguments.SetTypeAt(offset + i, type_arg); |
| 671 } else if (bound_error->IsNull()) { | 680 } else if (bound_error->IsNull()) { |
| 672 *bound_error = malformed_error.raw(); | 681 *bound_error = malformed_error.raw(); |
| 673 } | 682 } |
| 674 } | 683 } |
| 675 } | 684 } |
| 676 } | 685 } |
| 677 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 686 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 678 if (!super_type.IsNull()) { | 687 if (!super_type.IsNull()) { |
| 679 const Class& super_class = Class::Handle(super_type.type_class()); | 688 const Class& super_class = Class::Handle(super_type.type_class()); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 const intptr_t num_type_params = cls.NumTypeParameters(); | 1023 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 1015 TypeParameter& type_param = TypeParameter::Handle(); | 1024 TypeParameter& type_param = TypeParameter::Handle(); |
| 1016 AbstractType& bound = AbstractType::Handle(); | 1025 AbstractType& bound = AbstractType::Handle(); |
| 1017 const AbstractTypeArguments& type_params = | 1026 const AbstractTypeArguments& type_params = |
| 1018 AbstractTypeArguments::Handle(cls.type_parameters()); | 1027 AbstractTypeArguments::Handle(cls.type_parameters()); |
| 1019 ASSERT((type_params.IsNull() && (num_type_params == 0)) || | 1028 ASSERT((type_params.IsNull() && (num_type_params == 0)) || |
| 1020 (type_params.Length() == num_type_params)); | 1029 (type_params.Length() == num_type_params)); |
| 1021 for (intptr_t i = 0; i < num_type_params; i++) { | 1030 for (intptr_t i = 0; i < num_type_params; i++) { |
| 1022 type_param ^= type_params.TypeAt(i); | 1031 type_param ^= type_params.TypeAt(i); |
| 1023 bound = type_param.bound(); | 1032 bound = type_param.bound(); |
| 1024 if (bound.IsFinalized()) { | 1033 if (bound.IsFinalized() || bound.IsBeingFinalized()) { |
| 1034 // A bound involved in F-bounded quantification may form a cycle. |
| 1025 continue; | 1035 continue; |
| 1026 } | 1036 } |
| 1027 ResolveType(cls, bound, kCanonicalize); | 1037 ResolveType(cls, bound, kCanonicalize); |
| 1028 bound = FinalizeType(cls, bound, kCanonicalize); | 1038 bound = FinalizeType(cls, bound, kCanonicalize); |
| 1029 type_param.set_bound(bound); | 1039 type_param.set_bound(bound); |
| 1030 } | 1040 } |
| 1031 } | 1041 } |
| 1032 | 1042 |
| 1033 | 1043 |
| 1034 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { | 1044 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
| (...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 void ClassFinalizer::ReportError(const char* format, ...) { | 1995 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1986 va_list args; | 1996 va_list args; |
| 1987 va_start(args, format); | 1997 va_start(args, format); |
| 1988 const Error& error = Error::Handle( | 1998 const Error& error = Error::Handle( |
| 1989 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1999 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1990 va_end(args); | 2000 va_end(args); |
| 1991 ReportError(error); | 2001 ReportError(error); |
| 1992 } | 2002 } |
| 1993 | 2003 |
| 1994 } // namespace dart | 2004 } // namespace dart |
| OLD | NEW |