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

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

Issue 2822323002: More work on finalization of recursive types (fixes #29357). (Closed)
Patch Set: Created 3 years, 8 months 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
« no previous file with comments | « no previous file | runtime/vm/object.h » ('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) 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/code_generator.h" 7 #include "vm/code_generator.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/hash_table.h" 9 #include "vm/hash_table.h"
10 #include "vm/heap.h" 10 #include "vm/heap.h"
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 const intptr_t num_type_params = type_cls.NumTypeParameters(); 667 const intptr_t num_type_params = type_cls.NumTypeParameters();
668 const intptr_t first_type_param = num_type_args - num_type_params; 668 const intptr_t first_type_param = num_type_args - num_type_params;
669 // If the type is not generic (num_type_params == 0) or if its type parameters 669 // If the type is not generic (num_type_params == 0) or if its type parameters
670 // are instantiated, no divergence can occur. Note that if the type parameters 670 // are instantiated, no divergence can occur. Note that if the type parameters
671 // are null, i.e. if the generic type is raw, they are considered 671 // are null, i.e. if the generic type is raw, they are considered
672 // instantiated and no divergence can occur. 672 // instantiated and no divergence can occur.
673 if ((num_type_params == 0) || 673 if ((num_type_params == 0) ||
674 arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) { 674 arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) {
675 return; 675 return;
676 } 676 }
677 // The type parameters are not instantiated. Verify that there is no other 677 // Consider mutually recursive and uninstantiated types pending finalization
678 // type pending finalization with the same type class, but different 678 // with the same type class and report an error if they are not equal in their
679 // uninstantiated type parameters. 679 // raw form, i.e. where each type parameter is substituted with dynamic.
680 // This test eliminates divergent types without restricting recursive types
681 // typically found in the wild.
680 TypeArguments& pending_arguments = TypeArguments::Handle(zone); 682 TypeArguments& pending_arguments = TypeArguments::Handle(zone);
681 const intptr_t num_pending_types = pending_types->length(); 683 const intptr_t num_pending_types = pending_types->length();
682 for (intptr_t i = num_pending_types - 1; i >= 0; i--) { 684 for (intptr_t i = num_pending_types - 1; i >= 0; i--) {
683 const AbstractType& pending_type = pending_types->At(i); 685 const AbstractType& pending_type = pending_types->At(i);
684 if (FLAG_trace_type_finalization) { 686 if (FLAG_trace_type_finalization) {
685 THR_Print(" Comparing with pending type '%s': %s\n", 687 THR_Print(" Comparing with pending type '%s': %s\n",
686 String::Handle(pending_type.Name()).ToCString(), 688 String::Handle(pending_type.Name()).ToCString(),
687 pending_type.ToCString()); 689 pending_type.ToCString());
688 } 690 }
689 if ((pending_type.raw() != type.raw()) && pending_type.IsType() && 691 if ((pending_type.raw() != type.raw()) && pending_type.IsType() &&
690 (pending_type.type_class() == type_cls.raw())) { 692 (pending_type.type_class() == type_cls.raw())) {
691 pending_arguments = pending_type.arguments(); 693 pending_arguments = pending_type.arguments();
692 if (!pending_arguments.IsSubvectorEquivalent(arguments, first_type_param, 694 if (!pending_arguments.IsSubvectorEquivalent(arguments, first_type_param,
693 num_type_params) && 695 num_type_params) &&
694 !pending_arguments.IsSubvectorInstantiated(first_type_param, 696 !pending_arguments.IsSubvectorInstantiated(first_type_param,
695 num_type_params)) { 697 num_type_params)) {
696 // Reject the non-contractive recursive type. 698 const TypeArguments& instantiated_arguments = TypeArguments::Handle(
697 const String& type_name = String::Handle(zone, type.Name()); 699 zone, arguments.InstantiateFrom(Object::null_type_arguments(),
698 ReportError(cls, type.token_pos(), "illegal recursive type '%s'", 700 Object::null_type_arguments(), NULL,
699 type_name.ToCString()); 701 NULL, NULL, Heap::kNew));
702 const TypeArguments& instantiated_pending_arguments =
703 TypeArguments::Handle(zone, pending_arguments.InstantiateFrom(
704 Object::null_type_arguments(),
705 Object::null_type_arguments(), NULL,
706 NULL, NULL, Heap::kNew));
707 if (!instantiated_pending_arguments.IsSubvectorEquivalent(
708 instantiated_arguments, first_type_param, num_type_params)) {
709 const String& type_name = String::Handle(zone, type.Name());
710 ReportError(cls, type.token_pos(), "illegal recursive type '%s'",
711 type_name.ToCString());
712 }
700 } 713 }
701 } 714 }
702 } 715 }
703 } 716 }
704 717
705 718
706 // Expand the type arguments of the given type and finalize its full type 719 // Expand the type arguments of the given type and finalize its full type
707 // argument vector. Return the number of type arguments (0 for a raw type). 720 // argument vector. Return the number of type arguments (0 for a raw type).
708 intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments( 721 intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
709 const Class& cls, 722 const Class& cls,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 // Make the type raw and continue without reporting any error. 760 // Make the type raw and continue without reporting any error.
748 // A static warning should have been reported. 761 // A static warning should have been reported.
749 arguments = TypeArguments::null(); 762 arguments = TypeArguments::null();
750 type.set_arguments(arguments); 763 type.set_arguments(arguments);
751 } 764 }
752 765
753 // Mark the type as being finalized in order to detect self reference and 766 // Mark the type as being finalized in order to detect self reference and
754 // postpone bound checking (if required) until after all types in the graph of 767 // postpone bound checking (if required) until after all types in the graph of
755 // mutually recursive types are finalized. 768 // mutually recursive types are finalized.
756 type.SetIsBeingFinalized(); 769 type.SetIsBeingFinalized();
757 if (pending_types != NULL) { 770 ASSERT(pending_types != NULL);
758 pending_types->Add(type); 771 pending_types->Add(type);
759 }
760 772
761 // The full type argument vector consists of the type arguments of the 773 // The full type argument vector consists of the type arguments of the
762 // super types of type_class, which are initialized from the parsed 774 // super types of type_class, which are initialized from the parsed
763 // type arguments, followed by the parsed type arguments. 775 // type arguments, followed by the parsed type arguments.
764 TypeArguments& full_arguments = TypeArguments::Handle(zone); 776 TypeArguments& full_arguments = TypeArguments::Handle(zone);
765 if (FLAG_reify && (num_type_arguments > 0)) { 777 if (FLAG_reify && (num_type_arguments > 0)) {
766 // If no type arguments were parsed and if the super types do not prepend 778 // If no type arguments were parsed and if the super types do not prepend
767 // type arguments to the vector, we can leave the vector as null. 779 // type arguments to the vector, we can leave the vector as null.
768 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { 780 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
769 full_arguments = TypeArguments::New(num_type_arguments); 781 full_arguments = TypeArguments::New(num_type_arguments);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 "Instantiating TypeRef '%s': '%s'\n" 930 "Instantiating TypeRef '%s': '%s'\n"
919 " instantiator: '%s'\n", 931 " instantiator: '%s'\n",
920 String::Handle(super_type_arg.Name()).ToCString(), 932 String::Handle(super_type_arg.Name()).ToCString(),
921 ref_type.ToCString(), arguments.ToCString()); 933 ref_type.ToCString(), arguments.ToCString());
922 } 934 }
923 // In the typical case of an F-bounded type, the instantiation of the 935 // In the typical case of an F-bounded type, the instantiation of the
924 // super_type_arg from arguments is a fixpoint. Take the shortcut. 936 // super_type_arg from arguments is a fixpoint. Take the shortcut.
925 // Example: class B<T>; class D<T> extends B<D<T>>; 937 // Example: class B<T>; class D<T> extends B<D<T>>;
926 // While finalizing D<T>, the super type arg D<T> (a typeref) gets 938 // While finalizing D<T>, the super type arg D<T> (a typeref) gets
927 // instantiated from vector [T], yielding itself. 939 // instantiated from vector [T], yielding itself.
928 if (super_type_arg.IsTypeRef() && super_type_arg.IsBeingFinalized() && 940 if (super_type_arg.IsTypeRef() &&
929 (super_type_arg.arguments() == arguments.raw())) { 941 (super_type_arg.arguments() == arguments.raw())) {
942 ASSERT(super_type_arg.IsBeingFinalized());
930 arguments.SetTypeAt(i, super_type_arg); 943 arguments.SetTypeAt(i, super_type_arg);
931 continue; 944 continue;
932 } 945 }
933 Error& error = Error::Handle(); 946 Error& error = Error::Handle();
934 super_type_arg = super_type_arg.InstantiateFrom( 947 super_type_arg = super_type_arg.InstantiateFrom(
935 arguments, Object::null_type_arguments(), &error, 948 arguments, Object::null_type_arguments(), &error,
936 instantiation_trail, NULL, Heap::kOld); 949 instantiation_trail, NULL, Heap::kOld);
937 if (!error.IsNull()) { 950 if (!error.IsNull()) {
938 // InstantiateFrom does not report an error if the type is still 951 // InstantiateFrom does not report an error if the type is still
939 // uninstantiated. Instead, it will return a new BoundedType so 952 // uninstantiated. Instead, it will return a new BoundedType so
940 // that the check is postponed to run time. 953 // that the check is postponed to run time.
941 ASSERT(super_type_arg.IsInstantiated()); 954 ASSERT(super_type_arg.IsInstantiated());
942 // Keep only the first bound error. 955 // Keep only the first bound error.
943 if (bound_error->IsNull()) { 956 if (bound_error->IsNull()) {
944 *bound_error = error.raw(); 957 *bound_error = error.raw();
945 } 958 }
946 } 959 }
947 if (super_type_arg.IsBeingFinalized()) { 960 if (super_type_arg.IsBeingFinalized()) {
948 // The super_type_arg was instantiated from a type being finalized. 961 // The super_type_arg was instantiated from a type being finalized.
949 // We need to finish finalizing its type arguments. 962 // We need to finish finalizing its type arguments.
950 ASSERT(super_type_arg.IsTypeRef()); 963 ASSERT(super_type_arg.IsTypeRef());
951 AbstractType& ref_super_type_arg = 964 AbstractType& ref_super_type_arg =
952 AbstractType::Handle(TypeRef::Cast(super_type_arg).type()); 965 AbstractType::Handle(TypeRef::Cast(super_type_arg).type());
966 if (FLAG_trace_type_finalization) {
967 THR_Print("Instantiated TypeRef '%s': '%s'\n",
968 String::Handle(super_type_arg.Name()).ToCString(),
969 ref_super_type_arg.ToCString());
970 }
971 CheckRecursiveType(cls, ref_super_type_arg, pending_types);
972 pending_types->Add(ref_super_type_arg);
973 const Class& super_cls =
974 Class::Handle(ref_super_type_arg.type_class());
975 const TypeArguments& super_args =
976 TypeArguments::Handle(ref_super_type_arg.arguments());
977 // Mark as finalized before finalizing to avoid cycles.
953 ref_super_type_arg.SetIsFinalized(); 978 ref_super_type_arg.SetIsFinalized();
954 const Class& cls = Class::Handle(ref_super_type_arg.type_class()); 979 // Since the instantiator is different, do not pass the current
980 // instantiation trail, but create a new one by passing NULL.
955 FinalizeTypeArguments( 981 FinalizeTypeArguments(
956 cls, TypeArguments::Handle(ref_super_type_arg.arguments()), 982 super_cls, super_args,
957 cls.NumTypeArguments() - cls.NumTypeParameters(), bound_error, 983 super_cls.NumTypeArguments() - super_cls.NumTypeParameters(),
958 pending_types, instantiation_trail); 984 bound_error, pending_types, NULL);
985 if (FLAG_trace_type_finalization) {
986 THR_Print("Finalized instantiated TypeRef '%s': '%s'\n",
987 String::Handle(super_type_arg.Name()).ToCString(),
988 ref_super_type_arg.ToCString());
989 }
959 } 990 }
960 } 991 }
961 } 992 }
962 arguments.SetTypeAt(i, super_type_arg); 993 arguments.SetTypeAt(i, super_type_arg);
963 } 994 }
964 FinalizeTypeArguments(super_class, arguments, super_offset, bound_error, 995 FinalizeTypeArguments(super_class, arguments, super_offset, bound_error,
965 pending_types, instantiation_trail); 996 pending_types, instantiation_trail);
966 } 997 }
967 } 998 }
968 999
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 } 1235 }
1205 1236
1206 // We do not canonicalize type parameters. 1237 // We do not canonicalize type parameters.
1207 return type_parameter.raw(); 1238 return type_parameter.raw();
1208 } 1239 }
1209 1240
1210 // At this point, we can only have a Type. 1241 // At this point, we can only have a Type.
1211 ASSERT(type.IsType()); 1242 ASSERT(type.IsType());
1212 1243
1213 // This type is the root type of the type graph if no pending types queue is 1244 // This type is the root type of the type graph if no pending types queue is
1214 // allocated yet, and if canonicalization is required. 1245 // allocated yet.
1215 const bool is_root_type = 1246 const bool is_root_type = pending_types == NULL;
1216 (pending_types == NULL) && (finalization >= kCanonicalize);
1217 if (is_root_type) { 1247 if (is_root_type) {
1218 pending_types = new PendingTypes(zone, 4); 1248 pending_types = new PendingTypes(zone, 4);
1219 } 1249 }
1220 1250
1221 const intptr_t num_expanded_type_arguments = 1251 const intptr_t num_expanded_type_arguments =
1222 ExpandAndFinalizeTypeArguments(cls, type, pending_types); 1252 ExpandAndFinalizeTypeArguments(cls, type, pending_types);
1223 1253
1224 // Self referencing types may get finalized indirectly. 1254 // Self referencing types may get finalized indirectly.
1225 if (!type.IsFinalized()) { 1255 if (!type.IsFinalized()) {
1226 // If the type is a function type, we also need to finalize the types in its 1256 // If the type is a function type, we also need to finalize the types in its
(...skipping 2543 matching lines...) Expand 10 before | Expand all | Expand 10 after
3770 ProgramVisitor::VisitFunctions(&function_visitor); 3800 ProgramVisitor::VisitFunctions(&function_visitor);
3771 3801
3772 class ClearCodeClassVisitor : public ClassVisitor { 3802 class ClearCodeClassVisitor : public ClassVisitor {
3773 void Visit(const Class& cls) { cls.DisableAllocationStub(); } 3803 void Visit(const Class& cls) { cls.DisableAllocationStub(); }
3774 }; 3804 };
3775 ClearCodeClassVisitor class_visitor; 3805 ClearCodeClassVisitor class_visitor;
3776 ProgramVisitor::VisitClasses(&class_visitor); 3806 ProgramVisitor::VisitClasses(&class_visitor);
3777 } 3807 }
3778 3808
3779 } // namespace dart 3809 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698