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

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

Issue 1674383002: Keep a trail while checking upper bounds in the VM in order to properly handle (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comments Created 4 years, 10 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 | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.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) 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/heap.h" 9 #include "vm/heap.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 Function& target_target = Function::Handle(target.RedirectionTarget()); 433 Function& target_target = Function::Handle(target.RedirectionTarget());
434 if (target_target.IsNull()) { 434 if (target_target.IsNull()) {
435 ASSERT(target_type.IsMalformed()); 435 ASSERT(target_type.IsMalformed());
436 } else { 436 } else {
437 // If the target type refers to type parameters, substitute them with the 437 // If the target type refers to type parameters, substitute them with the
438 // type arguments of the redirection type. 438 // type arguments of the redirection type.
439 if (!target_type.IsInstantiated()) { 439 if (!target_type.IsInstantiated()) {
440 const TypeArguments& type_args = TypeArguments::Handle(type.arguments()); 440 const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
441 Error& bound_error = Error::Handle(); 441 Error& bound_error = Error::Handle();
442 target_type ^= target_type.InstantiateFrom( 442 target_type ^= target_type.InstantiateFrom(
443 type_args, &bound_error, NULL, Heap::kOld); 443 type_args, &bound_error, NULL, NULL, Heap::kOld);
444 if (bound_error.IsNull()) { 444 if (bound_error.IsNull()) {
445 target_type ^= FinalizeType(cls, target_type, kCanonicalize); 445 target_type ^= FinalizeType(cls, target_type, kCanonicalize);
446 } else { 446 } else {
447 ASSERT(target_type.IsInstantiated() && type_args.IsInstantiated()); 447 ASSERT(target_type.IsInstantiated() && type_args.IsInstantiated());
448 const Script& script = Script::Handle(target_class.script()); 448 const Script& script = Script::Handle(target_class.script());
449 FinalizeMalformedType(bound_error, script, target_type, 449 FinalizeMalformedType(bound_error, script, target_type,
450 "cannot resolve redirecting factory"); 450 "cannot resolve redirecting factory");
451 target_target = Function::null(); 451 target_target = Function::null();
452 } 452 }
453 } 453 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 if ((num_type_params == 0) || 617 if ((num_type_params == 0) ||
618 arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) { 618 arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) {
619 return; 619 return;
620 } 620 }
621 // The type parameters are not instantiated. Verify that there is no other 621 // The type parameters are not instantiated. Verify that there is no other
622 // type pending finalization with the same type class, but different 622 // type pending finalization with the same type class, but different
623 // uninstantiated type parameters. 623 // uninstantiated type parameters.
624 TypeArguments& pending_arguments = TypeArguments::Handle(zone); 624 TypeArguments& pending_arguments = TypeArguments::Handle(zone);
625 const intptr_t num_pending_types = pending_types->length(); 625 const intptr_t num_pending_types = pending_types->length();
626 for (intptr_t i = num_pending_types - 1; i >= 0; i--) { 626 for (intptr_t i = num_pending_types - 1; i >= 0; i--) {
627 const Type& pending_type = Type::Cast(pending_types->At(i)); 627 const AbstractType& pending_type = pending_types->At(i);
628 if (FLAG_trace_type_finalization) { 628 if (FLAG_trace_type_finalization) {
629 THR_Print(" Comparing with pending type '%s': %s\n", 629 THR_Print(" Comparing with pending type '%s': %s\n",
630 String::Handle(pending_type.Name()).ToCString(), 630 String::Handle(pending_type.Name()).ToCString(),
631 pending_type.ToCString()); 631 pending_type.ToCString());
632 } 632 }
633 if ((pending_type.raw() != type.raw()) && 633 if ((pending_type.raw() != type.raw()) &&
634 pending_type.IsType() &&
634 (pending_type.type_class() == type_cls.raw())) { 635 (pending_type.type_class() == type_cls.raw())) {
635 pending_arguments = pending_type.arguments(); 636 pending_arguments = pending_type.arguments();
636 if (!pending_arguments.IsSubvectorEquivalent(arguments, 637 if (!pending_arguments.IsSubvectorEquivalent(arguments,
637 first_type_param, 638 first_type_param,
638 num_type_params) && 639 num_type_params) &&
639 !pending_arguments.IsSubvectorInstantiated(first_type_param, 640 !pending_arguments.IsSubvectorInstantiated(first_type_param,
640 num_type_params)) { 641 num_type_params)) {
641 // Reject the non-contractive recursive type. 642 // Reject the non-contractive recursive type.
642 const String& type_name = String::Handle(zone, type.Name()); 643 const String& type_name = String::Handle(zone, type.Name());
643 ReportError(cls, type.token_pos(), 644 ReportError(cls, type.token_pos(),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 ASSERT(!type_arg.IsBeingFinalized()); 735 ASSERT(!type_arg.IsBeingFinalized());
735 type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types); 736 type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
736 if (type_arg.IsMalformed()) { 737 if (type_arg.IsMalformed()) {
737 // Malformed type arguments are mapped to dynamic. 738 // Malformed type arguments are mapped to dynamic.
738 type_arg = Type::DynamicType(); 739 type_arg = Type::DynamicType();
739 } 740 }
740 full_arguments.SetTypeAt(offset + i, type_arg); 741 full_arguments.SetTypeAt(offset + i, type_arg);
741 } 742 }
742 } 743 }
743 if (offset > 0) { 744 if (offset > 0) {
744 TrailPtr trail = new Trail(Z, 4); 745 TrailPtr instantiation_trail = new Trail(Z, 4);
745 Error& bound_error = Error::Handle(); 746 Error& bound_error = Error::Handle(Z);
746 FinalizeTypeArguments(type_class, full_arguments, offset, 747 FinalizeTypeArguments(type_class, full_arguments, offset,
747 &bound_error, pending_types, trail); 748 &bound_error, pending_types, instantiation_trail);
748 } 749 }
749 if (full_arguments.IsRaw(0, num_type_arguments)) { 750 if (full_arguments.IsRaw(0, num_type_arguments)) {
750 // The parameterized_type is raw. Set its argument vector to null, which 751 // The parameterized_type is raw. Set its argument vector to null, which
751 // is more efficient in type tests. 752 // is more efficient in type tests.
752 full_arguments = TypeArguments::null(); 753 full_arguments = TypeArguments::null();
753 } 754 }
754 type.set_arguments(full_arguments); 755 type.set_arguments(full_arguments);
755 } else { 756 } else {
756 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. 757 ASSERT(full_arguments.IsNull()); // Use null vector for raw type.
757 } 758 }
758 } 759 }
759 760
760 // Self referencing types may get finalized indirectly. 761 // Self referencing types may get finalized indirectly.
761 if (!type.IsFinalized()) { 762 if (!type.IsFinalized()) {
762 ASSERT(full_arguments.IsNull() || 763 ASSERT(full_arguments.IsNull() ||
763 !full_arguments.IsRaw(0, num_type_arguments)); 764 !full_arguments.IsRaw(0, num_type_arguments));
765 if (FLAG_trace_type_finalization) {
766 THR_Print("Marking type '%s' as finalized for class '%s'\n",
767 String::Handle(Z, type.Name()).ToCString(),
768 String::Handle(Z, cls.Name()).ToCString());
769 }
764 // Mark the type as finalized. 770 // Mark the type as finalized.
765 type.SetIsFinalized(); 771 type.SetIsFinalized();
766 // Do not yet remove the type from the pending_types array. 772 // Do not yet remove the type from the pending_types array.
767 } 773 }
768 return full_arguments.IsNull() ? 0 : full_arguments.Length(); 774 return full_arguments.IsNull() ? 0 : full_arguments.Length();
769 } 775 }
770 776
771 777
772 // Finalize the type argument vector 'arguments' of the type defined by the 778 // Finalize the type argument vector 'arguments' of the type defined by the
773 // class 'cls' parameterized with the type arguments 'cls_args'. 779 // class 'cls' parameterized with the type arguments 'cls_args'.
(...skipping 27 matching lines...) Expand all
801 // several type argument vectors may be mutually recursive and finalized at the 807 // several type argument vectors may be mutually recursive and finalized at the
802 // same time. Canonicalization happens when pending types are processed. 808 // same time. Canonicalization happens when pending types are processed.
803 // The trail is required to correctly instantiate a recursive type argument 809 // The trail is required to correctly instantiate a recursive type argument
804 // of the super type. 810 // of the super type.
805 void ClassFinalizer::FinalizeTypeArguments( 811 void ClassFinalizer::FinalizeTypeArguments(
806 const Class& cls, 812 const Class& cls,
807 const TypeArguments& arguments, 813 const TypeArguments& arguments,
808 intptr_t num_uninitialized_arguments, 814 intptr_t num_uninitialized_arguments,
809 Error* bound_error, 815 Error* bound_error,
810 PendingTypes* pending_types, 816 PendingTypes* pending_types,
811 TrailPtr trail) { 817 TrailPtr instantiation_trail) {
812 ASSERT(arguments.Length() >= cls.NumTypeArguments()); 818 ASSERT(arguments.Length() >= cls.NumTypeArguments());
813 if (!cls.is_type_finalized()) { 819 if (!cls.is_type_finalized()) {
814 FinalizeTypeParameters(cls, pending_types); 820 FinalizeTypeParameters(cls, pending_types);
815 ResolveUpperBounds(cls); 821 ResolveUpperBounds(cls);
816 } 822 }
817 AbstractType& super_type = AbstractType::Handle(cls.super_type()); 823 AbstractType& super_type = AbstractType::Handle(cls.super_type());
818 if (!super_type.IsNull()) { 824 if (!super_type.IsNull()) {
819 const Class& super_class = Class::Handle(super_type.type_class()); 825 const Class& super_class = Class::Handle(super_type.type_class());
820 const intptr_t num_super_type_params = super_class.NumTypeParameters(); 826 const intptr_t num_super_type_params = super_class.NumTypeParameters();
821 const intptr_t num_super_type_args = super_class.NumTypeArguments(); 827 const intptr_t num_super_type_args = super_class.NumTypeArguments();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 AbstractType& ref_type = AbstractType::Handle( 867 AbstractType& ref_type = AbstractType::Handle(
862 TypeRef::Cast(super_type_arg).type()); 868 TypeRef::Cast(super_type_arg).type());
863 THR_Print("Instantiating TypeRef '%s': '%s'\n" 869 THR_Print("Instantiating TypeRef '%s': '%s'\n"
864 " instantiator: '%s'\n", 870 " instantiator: '%s'\n",
865 String::Handle(super_type_arg.Name()).ToCString(), 871 String::Handle(super_type_arg.Name()).ToCString(),
866 ref_type.ToCString(), 872 ref_type.ToCString(),
867 arguments.ToCString()); 873 arguments.ToCString());
868 } 874 }
869 Error& error = Error::Handle(); 875 Error& error = Error::Handle();
870 super_type_arg = super_type_arg.InstantiateFrom( 876 super_type_arg = super_type_arg.InstantiateFrom(
871 arguments, &error, trail, Heap::kOld); 877 arguments, &error, instantiation_trail, NULL, Heap::kOld);
872 if (!error.IsNull()) { 878 if (!error.IsNull()) {
873 // InstantiateFrom does not report an error if the type is still 879 // InstantiateFrom does not report an error if the type is still
874 // uninstantiated. Instead, it will return a new BoundedType so 880 // uninstantiated. Instead, it will return a new BoundedType so
875 // that the check is postponed to run time. 881 // that the check is postponed to run time.
876 ASSERT(super_type_arg.IsInstantiated()); 882 ASSERT(super_type_arg.IsInstantiated());
877 // Keep only the first bound error. 883 // Keep only the first bound error.
878 if (bound_error->IsNull()) { 884 if (bound_error->IsNull()) {
879 *bound_error = error.raw(); 885 *bound_error = error.raw();
880 } 886 }
881 } 887 }
882 if (!super_type_arg.IsFinalized() && 888 if (!super_type_arg.IsFinalized() &&
883 !super_type_arg.IsBeingFinalized()) { 889 !super_type_arg.IsBeingFinalized()) {
884 // The super_type_arg was instantiated from a type being finalized. 890 // The super_type_arg was instantiated from a type being finalized.
885 // We need to finish finalizing its type arguments. 891 // We need to finish finalizing its type arguments.
886 if (super_type_arg.IsTypeRef()) { 892 if (super_type_arg.IsTypeRef()) {
887 super_type_arg = TypeRef::Cast(super_type_arg).type(); 893 super_type_arg = TypeRef::Cast(super_type_arg).type();
888 } 894 }
889 Type::Cast(super_type_arg).SetIsBeingFinalized(); 895 Type::Cast(super_type_arg).SetIsBeingFinalized();
890 pending_types->Add(super_type_arg); 896 pending_types->Add(super_type_arg);
891 const Class& cls = Class::Handle(super_type_arg.type_class()); 897 const Class& cls = Class::Handle(super_type_arg.type_class());
892 FinalizeTypeArguments( 898 FinalizeTypeArguments(
893 cls, 899 cls,
894 TypeArguments::Handle(super_type_arg.arguments()), 900 TypeArguments::Handle(super_type_arg.arguments()),
895 cls.NumTypeArguments() - cls.NumTypeParameters(), 901 cls.NumTypeArguments() - cls.NumTypeParameters(),
896 bound_error, 902 bound_error,
897 pending_types, 903 pending_types,
898 trail); 904 instantiation_trail);
899 Type::Cast(super_type_arg).SetIsFinalized(); 905 Type::Cast(super_type_arg).SetIsFinalized();
900 } 906 }
901 } 907 }
902 } 908 }
903 arguments.SetTypeAt(i, super_type_arg); 909 arguments.SetTypeAt(i, super_type_arg);
904 } 910 }
905 FinalizeTypeArguments(super_class, arguments, super_offset, 911 FinalizeTypeArguments(super_class, arguments, super_offset,
906 bound_error, pending_types, trail); 912 bound_error, pending_types, instantiation_trail);
907 } 913 }
908 } 914 }
909 915
910 916
911 // Check the type argument vector 'arguments' against the corresponding bounds 917 // Check the type argument vector 'arguments' against the corresponding bounds
912 // of the type parameters of class 'cls' and, recursively, of its superclasses. 918 // of the type parameters of class 'cls' and, recursively, of its superclasses.
913 // Replace a type argument that cannot be checked at compile time by a 919 // Replace a type argument that cannot be checked at compile time by a
914 // BoundedType, thereby postponing the bound check to run time. 920 // BoundedType, thereby postponing the bound check to run time.
915 // Return a bound error if a type argument is not within bound at compile time. 921 // Return a bound error if a type argument is not within bound at compile time.
916 void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls, 922 void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
917 const TypeArguments& arguments, 923 const TypeArguments& arguments,
918 Error* bound_error) { 924 Error* bound_error) {
919 if (!cls.is_type_finalized()) { 925 if (!cls.is_type_finalized()) {
920 FinalizeTypeParameters(cls); 926 FinalizeTypeParameters(cls);
921 FinalizeUpperBounds(cls); 927 FinalizeUpperBounds(cls, kFinalize); // No canonicalization yet.
922 } 928 }
923 // Note that when finalizing a type, we need to verify the bounds in both 929 // Note that when finalizing a type, we need to verify the bounds in both
924 // production mode and checked mode, because the finalized type may be written 930 // production mode and checked mode, because the finalized type may be written
925 // to a snapshot. It would be wrong to ignore bounds when generating the 931 // to a snapshot. It would be wrong to ignore bounds when generating the
926 // snapshot in production mode and then use the unchecked type in checked mode 932 // snapshot in production mode and then use the unchecked type in checked mode
927 // after reading it from the snapshot. 933 // after reading it from the snapshot.
928 // However, we do not immediately report a bound error, which would be wrong 934 // However, we do not immediately report a bound error, which would be wrong
929 // in production mode, but simply postpone the bound checking to runtime. 935 // in production mode, but simply postpone the bound checking to runtime.
930 const intptr_t num_type_params = cls.NumTypeParameters(); 936 const intptr_t num_type_params = cls.NumTypeParameters();
931 const intptr_t offset = cls.NumTypeArguments() - num_type_params; 937 const intptr_t offset = cls.NumTypeArguments() - num_type_params;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 declared_bound = FinalizeType(cls, declared_bound, kCanonicalize); 969 declared_bound = FinalizeType(cls, declared_bound, kCanonicalize);
964 type_param.set_bound(declared_bound); 970 type_param.set_bound(declared_bound);
965 } 971 }
966 ASSERT(declared_bound.IsFinalized() || declared_bound.IsBeingFinalized()); 972 ASSERT(declared_bound.IsFinalized() || declared_bound.IsBeingFinalized());
967 Error& error = Error::Handle(); 973 Error& error = Error::Handle();
968 // Note that the bound may be malformed, in which case the bound check 974 // Note that the bound may be malformed, in which case the bound check
969 // will return an error and the bound check will be postponed to run time. 975 // will return an error and the bound check will be postponed to run time.
970 if (declared_bound.IsInstantiated()) { 976 if (declared_bound.IsInstantiated()) {
971 instantiated_bound = declared_bound.raw(); 977 instantiated_bound = declared_bound.raw();
972 } else { 978 } else {
973 instantiated_bound = 979 instantiated_bound = declared_bound.InstantiateFrom(
974 declared_bound.InstantiateFrom(arguments, &error, NULL, Heap::kOld); 980 arguments, &error, NULL, NULL, Heap::kOld);
975 } 981 }
976 if (!instantiated_bound.IsFinalized()) { 982 if (!instantiated_bound.IsFinalized()) {
977 // The bound refers to type parameters, creating a cycle; postpone 983 // The bound refers to type parameters, creating a cycle; postpone
978 // bound check to run time, when the bound will be finalized. 984 // bound check to run time, when the bound will be finalized.
979 // The bound may not necessarily be 'IsBeingFinalized' yet, as is the 985 // The bound may not necessarily be 'IsBeingFinalized' yet, as is the
980 // case with a pair of type parameters of the same class referring to 986 // case with a pair of type parameters of the same class referring to
981 // each other via their bounds. 987 // each other via their bounds.
982 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); 988 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param);
983 arguments.SetTypeAt(offset + i, type_arg); 989 arguments.SetTypeAt(offset + i, type_arg);
984 continue; 990 continue;
985 } 991 }
986 // Shortcut the special case where we check a type parameter against its 992 // Shortcut the special case where we check a type parameter against its
987 // declared upper bound. 993 // declared upper bound.
988 if (error.IsNull() && 994 if (error.IsNull() &&
989 !(type_arg.Equals(type_param) && 995 !(type_arg.Equals(type_param) &&
990 instantiated_bound.Equals(declared_bound))) { 996 instantiated_bound.Equals(declared_bound))) {
991 // If type_arg is a type parameter, its declared bound may not be 997 // If type_arg is a type parameter, its declared bound may not be
992 // resolved yet. 998 // resolved yet.
993 if (type_arg.IsTypeParameter()) { 999 if (type_arg.IsTypeParameter()) {
994 const Class& type_arg_cls = Class::Handle( 1000 const Class& type_arg_cls = Class::Handle(
995 TypeParameter::Cast(type_arg).parameterized_class()); 1001 TypeParameter::Cast(type_arg).parameterized_class());
996 AbstractType& bound = AbstractType::Handle( 1002 AbstractType& bound = AbstractType::Handle(
997 TypeParameter::Cast(type_arg).bound()); 1003 TypeParameter::Cast(type_arg).bound());
998 bound = ResolveType(type_arg_cls, bound); 1004 bound = ResolveType(type_arg_cls, bound);
999 TypeParameter::Cast(type_arg).set_bound(bound); 1005 TypeParameter::Cast(type_arg).set_bound(bound);
1000 } 1006 }
1001 // This may be called only if type needs to be finalized, therefore 1007 // This may be called only if type needs to be finalized, therefore
1002 // seems OK to allocate finalized types in old space. 1008 // seems OK to allocate finalized types in old space.
1003 if (!type_param.CheckBound(type_arg, instantiated_bound, 1009 if (!type_param.CheckBound(type_arg, instantiated_bound,
1004 &error, Heap::kOld) && error.IsNull()) { 1010 &error, NULL, Heap::kOld) &&
1011 error.IsNull()) {
1005 // The bound cannot be checked at compile time; postpone to run time. 1012 // The bound cannot be checked at compile time; postpone to run time.
1006 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); 1013 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param);
1007 arguments.SetTypeAt(offset + i, type_arg); 1014 arguments.SetTypeAt(offset + i, type_arg);
1008 } 1015 }
1009 } 1016 }
1010 if (!error.IsNull() && bound_error->IsNull()) { 1017 if (!error.IsNull() && bound_error->IsNull()) {
1011 *bound_error = error.raw(); 1018 *bound_error = error.raw();
1012 } 1019 }
1013 } 1020 }
1014 } 1021 }
1015 AbstractType& super_type = AbstractType::Handle(cls.super_type()); 1022 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1016 if (!super_type.IsNull()) { 1023 if (!super_type.IsNull()) {
1017 const Class& super_class = Class::Handle(super_type.type_class()); 1024 const Class& super_class = Class::Handle(super_type.type_class());
1018 CheckTypeArgumentBounds(super_class, arguments, bound_error); 1025 CheckTypeArgumentBounds(super_class, arguments, bound_error);
1019 } 1026 }
1020 } 1027 }
1021 1028
1022 1029
1023 void ClassFinalizer::CheckTypeBounds(const Class& cls, 1030 void ClassFinalizer::CheckTypeBounds(const Class& cls,
1024 const AbstractType& type) { 1031 const AbstractType& type) {
1032 Zone* Z = Thread::Current()->zone();
1025 ASSERT(type.IsType() || type.IsFunctionType()); 1033 ASSERT(type.IsType() || type.IsFunctionType());
1026 ASSERT(type.IsFinalized()); 1034 ASSERT(type.IsFinalized());
1027 TypeArguments& arguments = TypeArguments::Handle(type.arguments()); 1035 ASSERT(!type.IsCanonical());
1036 TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
1028 if (arguments.IsNull()) { 1037 if (arguments.IsNull()) {
1029 return; 1038 return;
1030 } 1039 }
1031 const Class& type_class = Class::Handle(type.type_class()); 1040 if (FLAG_trace_type_finalization) {
1032 Error& bound_error = Error::Handle(); 1041 THR_Print("Checking bounds of type '%s' for class '%s'\n",
1042 String::Handle(Z, type.Name()).ToCString(),
1043 String::Handle(Z, cls.Name()).ToCString());
1044 }
1045 const Class& type_class = Class::Handle(Z, type.type_class());
1046 Error& bound_error = Error::Handle(Z);
1033 CheckTypeArgumentBounds(type_class, arguments, &bound_error); 1047 CheckTypeArgumentBounds(type_class, arguments, &bound_error);
1034 type.set_arguments(arguments); 1048 // CheckTypeArgumentBounds may have indirectly canonicalized this type.
1035 // If a bound error occurred, mark the type as malbounded. 1049 if (!type.IsCanonical()) {
1036 // The bound error will be ignored in production mode. 1050 type.set_arguments(arguments);
1037 if (!bound_error.IsNull()) { 1051 // If a bound error occurred, mark the type as malbounded.
1038 // No compile-time error during finalization. 1052 // The bound error will be ignored in production mode.
1039 const String& type_name = String::Handle(type.UserVisibleName()); 1053 if (!bound_error.IsNull()) {
1040 FinalizeMalboundedType(bound_error, 1054 // No compile-time error during finalization.
1041 Script::Handle(cls.script()), 1055 const String& type_name = String::Handle(Z, type.UserVisibleName());
1042 type, 1056 FinalizeMalboundedType(bound_error,
1043 "type '%s' has an out of bound type argument", 1057 Script::Handle(Z, cls.script()),
1044 type_name.ToCString()); 1058 type,
1045 if (FLAG_trace_type_finalization) { 1059 "type '%s' has an out of bound type argument",
1046 THR_Print("Marking type '%s' as malbounded: %s\n", 1060 type_name.ToCString());
1047 String::Handle(type.Name()).ToCString(), 1061 if (FLAG_trace_type_finalization) {
1048 bound_error.ToCString()); 1062 THR_Print("Marking type '%s' as malbounded: %s\n",
1063 String::Handle(Z, type.Name()).ToCString(),
1064 bound_error.ToCString());
1065 }
1049 } 1066 }
1050 } 1067 }
1068 if (FLAG_trace_type_finalization) {
1069 THR_Print("Done checking bounds of type '%s': %s\n",
1070 String::Handle(Z, type.Name()).ToCString(),
1071 type.ToCString());
1072 }
1051 } 1073 }
1052 1074
1053 1075
1054 RawAbstractType* ClassFinalizer::FinalizeType( 1076 RawAbstractType* ClassFinalizer::FinalizeType(
1055 const Class& cls, 1077 const Class& cls,
1056 const AbstractType& type, 1078 const AbstractType& type,
1057 FinalizationKind finalization, 1079 FinalizationKind finalization,
1058 PendingTypes* pending_types) { 1080 PendingTypes* pending_types) {
1059 // Only the 'root' type of the graph can be canonicalized, after all depending 1081 // Only the 'root' type of the graph can be canonicalized, after all depending
1060 // types have been bound checked. 1082 // types have been bound checked.
1061 ASSERT((pending_types == NULL) || (finalization < kCanonicalize)); 1083 ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
1062 if (type.IsFinalized()) { 1084 if (type.IsFinalized()) {
1063 // Ensure type is canonical if canonicalization is requested, unless type is 1085 // Ensure type is canonical if canonicalization is requested, unless type is
1064 // malformed. 1086 // malformed.
1065 if ((finalization >= kCanonicalize) && !type.IsMalformed()) { 1087 if ((finalization >= kCanonicalize) &&
1088 !type.IsMalformed() &&
1089 !type.IsCanonical() &&
1090 (type.IsType() || type.IsFunctionType())) {
1091 CheckTypeBounds(cls, type);
1066 return type.Canonicalize(); 1092 return type.Canonicalize();
1067 } 1093 }
1068 return type.raw(); 1094 return type.raw();
1069 } 1095 }
1070 ASSERT(finalization >= kFinalize); 1096 ASSERT(finalization >= kFinalize);
1071 1097
1072 if (type.IsTypeRef()) { 1098 if (type.IsTypeRef()) {
1073 // The referenced type will be finalized later by the code that set the 1099 // The referenced type will be finalized later by the code that set the
1074 // is_being_finalized mark bit. 1100 // is_being_finalized mark bit.
1075 return type.raw(); 1101 return type.raw();
1076 } 1102 }
1077 1103
1078 // Recursive types must be processed in FinalizeTypeArguments() and cannot be 1104 // Recursive types must be processed in FinalizeTypeArguments() and cannot be
1079 // encountered here. 1105 // encountered here.
1080 ASSERT(!type.IsBeingFinalized()); 1106 ASSERT(!type.IsBeingFinalized());
1081 1107
1082 Zone* Z = Thread::Current()->zone(); 1108 Zone* Z = Thread::Current()->zone();
1083 const AbstractType& resolved_type = 1109 const AbstractType& resolved_type =
1084 AbstractType::Handle(Z, ResolveType(cls, type)); 1110 AbstractType::Handle(Z, ResolveType(cls, type));
1085 // A malformed type gets mapped to a finalized type. 1111 // A malformed type gets mapped to a finalized type.
1086 if (resolved_type.IsMalformed()) { 1112 if (resolved_type.IsMalformed()) {
1087 ASSERT(resolved_type.IsFinalized()); 1113 ASSERT(resolved_type.IsFinalized());
1088 return resolved_type.raw(); 1114 return resolved_type.raw();
1089 } 1115 }
1090 1116
1091 if (FLAG_trace_type_finalization) { 1117 if (FLAG_trace_type_finalization) {
1092 THR_Print("Finalizing type '%s' for class '%s'\n", 1118 THR_Print("Finalizing type '%s' for class '%s'\n",
1093 String::Handle(Z, resolved_type.Name()).ToCString(), 1119 String::Handle(Z, resolved_type.Name()).ToCString(),
1094 cls.ToCString()); 1120 String::Handle(Z, cls.Name()).ToCString());
1095 } 1121 }
1096 1122
1097 if (resolved_type.IsTypeParameter()) { 1123 if (resolved_type.IsTypeParameter()) {
1098 const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type); 1124 const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type);
1099 const Class& parameterized_class = 1125 const Class& parameterized_class =
1100 Class::Handle(Z, type_parameter.parameterized_class()); 1126 Class::Handle(Z, type_parameter.parameterized_class());
1101 ASSERT(!parameterized_class.IsNull()); 1127 ASSERT(!parameterized_class.IsNull());
1102 // The index must reflect the position of this type parameter in the type 1128 // The index must reflect the position of this type parameter in the type
1103 // arguments vector of its parameterized class. The offset to add is the 1129 // arguments vector of its parameterized class. The offset to add is the
1104 // number of type arguments in the super type, which is equal to the 1130 // number of type arguments in the super type, which is equal to the
(...skipping 30 matching lines...) Expand all
1135 pending_types = new PendingTypes(Z, 4); 1161 pending_types = new PendingTypes(Z, 4);
1136 } 1162 }
1137 1163
1138 const intptr_t num_expanded_type_arguments = 1164 const intptr_t num_expanded_type_arguments =
1139 ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types); 1165 ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types);
1140 1166
1141 // If we are done finalizing a graph of mutually recursive types, check their 1167 // If we are done finalizing a graph of mutually recursive types, check their
1142 // bounds. 1168 // bounds.
1143 if (is_root_type) { 1169 if (is_root_type) {
1144 for (intptr_t i = pending_types->length() - 1; i >= 0; i--) { 1170 for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
1145 CheckTypeBounds(cls, pending_types->At(i)); 1171 const AbstractType& type = pending_types->At(i);
1146 if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) { 1172 if (!type.IsMalformed() && !type.IsCanonical()) {
1147 THR_Print("Done finalizing recursive type '%s': %s\n", 1173 CheckTypeBounds(cls, type);
1148 String::Handle(Z, resolved_type.Name()).ToCString(),
1149 resolved_type.ToCString());
1150 } 1174 }
1151 } 1175 }
1152 } 1176 }
1153 1177
1154 // If the type is a FunctionType, we also need to finalize the types in its 1178 // If the type is a FunctionType, we also need to finalize the types in its
1155 // signature, i.e. finalize the result type and parameter types of the 1179 // signature, i.e. finalize the result type and parameter types of the
1156 // signature function of this function type. 1180 // signature function of this function type.
1157 // We do this after marking this type as finalized in order to allow a 1181 // We do this after marking this type as finalized in order to allow a
1158 // function type to refer to itself via its parameter types and result type. 1182 // function type to refer to itself via its parameter types and result type.
1159 // Note that we do not instantiate these types according to the type 1183 // Note that we do not instantiate these types according to the type
(...skipping 11 matching lines...) Expand all
1171 } 1195 }
1172 1196
1173 if (FLAG_trace_type_finalization) { 1197 if (FLAG_trace_type_finalization) {
1174 THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n", 1198 THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
1175 String::Handle(Z, resolved_type.Name()).ToCString(), 1199 String::Handle(Z, resolved_type.Name()).ToCString(),
1176 num_expanded_type_arguments, 1200 num_expanded_type_arguments,
1177 resolved_type.ToCString()); 1201 resolved_type.ToCString());
1178 } 1202 }
1179 1203
1180 if (finalization >= kCanonicalize) { 1204 if (finalization >= kCanonicalize) {
1181 if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) { 1205 if (FLAG_trace_type_finalization) {
1182 AbstractType& recursive_type = 1206 THR_Print("Canonicalizing type '%s'\n",
1207 String::Handle(Z, resolved_type.Name()).ToCString());
1208 AbstractType& canonical_type =
1183 AbstractType::Handle(Z, resolved_type.Canonicalize()); 1209 AbstractType::Handle(Z, resolved_type.Canonicalize());
1184 THR_Print("Done canonicalizing recursive type '%s': %s\n", 1210 THR_Print("Done canonicalizing type '%s'\n",
1185 String::Handle(Z, recursive_type.Name()).ToCString(), 1211 String::Handle(Z, canonical_type.Name()).ToCString());
1186 recursive_type.ToCString()); 1212 return canonical_type.raw();
1187 return recursive_type.raw();
1188 } 1213 }
1189 return resolved_type.Canonicalize(); 1214 return resolved_type.Canonicalize();
1190 } else { 1215 } else {
1191 return resolved_type.raw(); 1216 return resolved_type.raw();
1192 } 1217 }
1193 } 1218 }
1194 1219
1195 1220
1196 void ClassFinalizer::ResolveSignature(const Class& cls, 1221 void ClassFinalizer::ResolveSignature(const Class& cls,
1197 const Function& function) { 1222 const Function& function) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 for (intptr_t i = 0; i < num_type_params; i++) { 1326 for (intptr_t i = 0; i < num_type_params; i++) {
1302 type_param ^= type_params.TypeAt(i); 1327 type_param ^= type_params.TypeAt(i);
1303 bound = type_param.bound(); 1328 bound = type_param.bound();
1304 bound = ResolveType(cls, bound); 1329 bound = ResolveType(cls, bound);
1305 type_param.set_bound(bound); 1330 type_param.set_bound(bound);
1306 } 1331 }
1307 } 1332 }
1308 1333
1309 1334
1310 // Finalize the upper bounds of the type parameters of class cls. 1335 // Finalize the upper bounds of the type parameters of class cls.
1311 void ClassFinalizer::FinalizeUpperBounds(const Class& cls) { 1336 void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
1337 FinalizationKind finalization) {
1312 const intptr_t num_type_params = cls.NumTypeParameters(); 1338 const intptr_t num_type_params = cls.NumTypeParameters();
1313 TypeParameter& type_param = TypeParameter::Handle(); 1339 TypeParameter& type_param = TypeParameter::Handle();
1314 AbstractType& bound = AbstractType::Handle(); 1340 AbstractType& bound = AbstractType::Handle();
1315 const TypeArguments& type_params = 1341 const TypeArguments& type_params =
1316 TypeArguments::Handle(cls.type_parameters()); 1342 TypeArguments::Handle(cls.type_parameters());
1317 ASSERT((type_params.IsNull() && (num_type_params == 0)) || 1343 ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
1318 (type_params.Length() == num_type_params)); 1344 (type_params.Length() == num_type_params));
1319 for (intptr_t i = 0; i < num_type_params; i++) { 1345 for (intptr_t i = 0; i < num_type_params; i++) {
1320 type_param ^= type_params.TypeAt(i); 1346 type_param ^= type_params.TypeAt(i);
1321 bound = type_param.bound(); 1347 bound = type_param.bound();
1322 // Bound may be finalized, but not canonical yet. 1348 // Bound may be finalized, but not canonical yet.
1323 if (bound.IsCanonical() || bound.IsBeingFinalized()) { 1349 if (bound.IsCanonical() || bound.IsBeingFinalized()) {
1324 // A bound involved in F-bounded quantification may form a cycle. 1350 // A bound involved in F-bounded quantification may form a cycle.
1325 continue; 1351 continue;
1326 } 1352 }
1327 bound = FinalizeType(cls, bound, kCanonicalize); 1353 bound = FinalizeType(cls, bound, finalization);
1328 type_param.set_bound(bound); 1354 type_param.set_bound(bound);
1329 } 1355 }
1330 } 1356 }
1331 1357
1332 1358
1333 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { 1359 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
1334 // Note that getters and setters are explicitly listed as such in the list of 1360 // Note that getters and setters are explicitly listed as such in the list of
1335 // functions of a class, so we do not need to consider fields as implicitly 1361 // functions of a class, so we do not need to consider fields as implicitly
1336 // generating getters and setters. 1362 // generating getters and setters.
1337 // Most overriding conflicts are only static warnings, i.e. they are not 1363 // Most overriding conflicts are only static warnings, i.e. they are not
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1759 param_bound = param.bound(); 1785 param_bound = param.bound();
1760 if (!param_bound.IsInstantiated()) { 1786 if (!param_bound.IsInstantiated()) {
1761 // Make sure the bound is finalized before instantiating it. 1787 // Make sure the bound is finalized before instantiating it.
1762 if (!param_bound.IsFinalized() && 1788 if (!param_bound.IsFinalized() &&
1763 !param_bound.IsBeingFinalized()) { 1789 !param_bound.IsBeingFinalized()) {
1764 param_bound = 1790 param_bound =
1765 FinalizeType(mixin_app_class, param_bound, kCanonicalize); 1791 FinalizeType(mixin_app_class, param_bound, kCanonicalize);
1766 param.set_bound(param_bound); // In case part of recursive type. 1792 param.set_bound(param_bound); // In case part of recursive type.
1767 } 1793 }
1768 param_bound = param_bound.InstantiateFrom( 1794 param_bound = param_bound.InstantiateFrom(
1769 instantiator, &bound_error, NULL, Heap::kOld); 1795 instantiator, &bound_error, NULL, NULL, Heap::kOld);
1770 // The instantiator contains only TypeParameter objects and no 1796 // The instantiator contains only TypeParameter objects and no
1771 // BoundedType objects, so no bound error may occur. 1797 // BoundedType objects, so no bound error may occur.
1772 ASSERT(!param_bound.IsBoundedType()); 1798 ASSERT(!param_bound.IsBoundedType());
1773 ASSERT(bound_error.IsNull()); 1799 ASSERT(bound_error.IsNull());
1774 ASSERT(!param_bound.IsInstantiated()); 1800 ASSERT(!param_bound.IsInstantiated());
1775 param.set_bound(param_bound); 1801 param.set_bound(param_bound);
1776 } 1802 }
1777 } 1803 }
1778 } 1804 }
1779 1805
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 mixin_class_super_type_args.Length() - num_aliased_mixin_type_params; 2019 mixin_class_super_type_args.Length() - num_aliased_mixin_type_params;
1994 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { 2020 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) {
1995 type = mixin_class_super_type_args.TypeAt(offset + i); 2021 type = mixin_class_super_type_args.TypeAt(offset + i);
1996 if (!type.IsInstantiated()) { 2022 if (!type.IsInstantiated()) {
1997 // In the presence of bounds, the bounded type and the upper bound must 2023 // In the presence of bounds, the bounded type and the upper bound must
1998 // be instantiated separately. Instantiating a BoundedType would wrap 2024 // be instantiated separately. Instantiating a BoundedType would wrap
1999 // the BoundedType in another BoundedType. 2025 // the BoundedType in another BoundedType.
2000 if (type.IsBoundedType()) { 2026 if (type.IsBoundedType()) {
2001 bounded_type = BoundedType::Cast(type).type(); 2027 bounded_type = BoundedType::Cast(type).type();
2002 bounded_type = bounded_type.InstantiateFrom( 2028 bounded_type = bounded_type.InstantiateFrom(
2003 instantiator, &bound_error, NULL, Heap::kOld); 2029 instantiator, &bound_error, NULL, NULL, Heap::kOld);
2004 // The instantiator contains only TypeParameter objects and no 2030 // The instantiator contains only TypeParameter objects and no
2005 // BoundedType objects, so no bound error may occur. 2031 // BoundedType objects, so no bound error may occur.
2006 ASSERT(bound_error.IsNull()); 2032 ASSERT(bound_error.IsNull());
2007 upper_bound = BoundedType::Cast(type).bound(); 2033 upper_bound = BoundedType::Cast(type).bound();
2008 upper_bound = upper_bound.InstantiateFrom( 2034 upper_bound = upper_bound.InstantiateFrom(
2009 instantiator, &bound_error, NULL, Heap::kOld); 2035 instantiator, &bound_error, NULL, NULL, Heap::kOld);
2010 ASSERT(bound_error.IsNull()); 2036 ASSERT(bound_error.IsNull());
2011 type_parameter = BoundedType::Cast(type).type_parameter(); 2037 type_parameter = BoundedType::Cast(type).type_parameter();
2012 // The type parameter that declared the bound does not change. 2038 // The type parameter that declared the bound does not change.
2013 type = BoundedType::New(bounded_type, upper_bound, type_parameter); 2039 type = BoundedType::New(bounded_type, upper_bound, type_parameter);
2014 } else { 2040 } else {
2015 type = type.InstantiateFrom( 2041 type = type.InstantiateFrom(
2016 instantiator, &bound_error, NULL, Heap::kOld); 2042 instantiator, &bound_error, NULL, NULL, Heap::kOld);
2017 ASSERT(bound_error.IsNull()); 2043 ASSERT(bound_error.IsNull());
2018 } 2044 }
2019 } 2045 }
2020 new_mixin_type_args.SetTypeAt(i, type); 2046 new_mixin_type_args.SetTypeAt(i, type);
2021 } 2047 }
2022 } 2048 }
2023 TypeArguments& new_super_type_args = TypeArguments::Handle(zone); 2049 TypeArguments& new_super_type_args = TypeArguments::Handle(zone);
2024 if ((num_super_type_params + num_aliased_mixin_type_params) > 0) { 2050 if ((num_super_type_params + num_aliased_mixin_type_params) > 0) {
2025 new_super_type_args = TypeArguments::New(num_super_type_params + 2051 new_super_type_args = TypeArguments::New(num_super_type_params +
2026 num_aliased_mixin_type_params); 2052 num_aliased_mixin_type_params);
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
2305 } 2331 }
2306 // Finalize type parameters before finalizing the super type. 2332 // Finalize type parameters before finalizing the super type.
2307 FinalizeTypeParameters(cls); // May change super type. 2333 FinalizeTypeParameters(cls); // May change super type.
2308 super_class = cls.SuperClass(); 2334 super_class = cls.SuperClass();
2309 ASSERT(super_class.IsNull() || super_class.is_type_finalized()); 2335 ASSERT(super_class.IsNull() || super_class.is_type_finalized());
2310 // Only resolving rather than finalizing the upper bounds here would result in 2336 // Only resolving rather than finalizing the upper bounds here would result in
2311 // instantiated type parameters of the super type to temporarily have 2337 // instantiated type parameters of the super type to temporarily have
2312 // unfinalized bounds. It is more efficient to finalize them early. 2338 // unfinalized bounds. It is more efficient to finalize them early.
2313 // Finalize bounds even if running in production mode, so that a snapshot 2339 // Finalize bounds even if running in production mode, so that a snapshot
2314 // contains them. 2340 // contains them.
2315 FinalizeUpperBounds(cls); 2341 FinalizeUpperBounds(cls, kCanonicalizeWellFormed);
2316 // Finalize super type. 2342 // Finalize super type.
2317 AbstractType& super_type = AbstractType::Handle(cls.super_type()); 2343 AbstractType& super_type = AbstractType::Handle(cls.super_type());
2318 if (!super_type.IsNull()) { 2344 if (!super_type.IsNull()) {
2319 // In case of a bound error in the super type in production mode, the 2345 // In case of a bound error in the super type in production mode, the
2320 // finalized super type will have a BoundedType as type argument for the 2346 // finalized super type will have a BoundedType as type argument for the
2321 // out of bound type argument. 2347 // out of bound type argument.
2322 // It should not be a problem if the class is written to a snapshot and 2348 // It should not be a problem if the class is written to a snapshot and
2323 // later executed in checked mode. Note that the finalized type argument 2349 // later executed in checked mode. Note that the finalized type argument
2324 // vector of any type of the base class will contain a BoundedType for the 2350 // vector of any type of the base class will contain a BoundedType for the
2325 // out of bound type argument. 2351 // out of bound type argument.
(...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after
3293 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); 3319 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
3294 field ^= fields_array.At(0); 3320 field ^= fields_array.At(0);
3295 ASSERT(field.Offset() == ByteBuffer::data_offset()); 3321 ASSERT(field.Offset() == ByteBuffer::data_offset());
3296 name ^= field.name(); 3322 name ^= field.name();
3297 expected_name ^= String::New("_data"); 3323 expected_name ^= String::New("_data");
3298 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 3324 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
3299 #endif 3325 #endif
3300 } 3326 }
3301 3327
3302 } // namespace dart 3328 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698