OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/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 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 // FinalizeTypeArguments can modify 'full_arguments', | 745 // FinalizeTypeArguments can modify 'full_arguments', |
746 // canonicalize afterwards. | 746 // canonicalize afterwards. |
747 full_arguments ^= full_arguments.Canonicalize(); | 747 full_arguments ^= full_arguments.Canonicalize(); |
748 } | 748 } |
749 parameterized_type.set_arguments(full_arguments); | 749 parameterized_type.set_arguments(full_arguments); |
750 } else { | 750 } else { |
751 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. | 751 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. |
752 } | 752 } |
753 } | 753 } |
754 | 754 |
755 // Illegally self referencing types may get finalized indirectly. | 755 // Self referencing types may get finalized indirectly. |
756 if (parameterized_type.IsFinalized()) { | 756 if (!parameterized_type.IsFinalized()) { |
757 ASSERT(parameterized_type.IsMalformed()); | |
758 } else { | |
759 // Mark the type as finalized. | 757 // Mark the type as finalized. |
760 if (parameterized_type.IsInstantiated()) { | 758 if (parameterized_type.IsInstantiated()) { |
761 parameterized_type.set_is_finalized_instantiated(); | 759 parameterized_type.set_is_finalized_instantiated(); |
762 } else { | 760 } else { |
763 parameterized_type.set_is_finalized_uninstantiated(); | 761 parameterized_type.set_is_finalized_uninstantiated(); |
764 } | 762 } |
765 } | 763 } |
766 | 764 |
767 // Upper bounds of the finalized type arguments are only verified in checked | 765 // Upper bounds of the finalized type arguments are only verified in checked |
768 // mode, since bound errors are never reported by the vm in production mode. | 766 // mode, since bound errors are never reported by the vm in production mode. |
(...skipping 15 matching lines...) Expand all Loading... | |
784 // when finalizing the malformed type. | 782 // when finalizing the malformed type. |
785 FinalizeMalformedType( | 783 FinalizeMalformedType( |
786 malformed_error, | 784 malformed_error, |
787 cls, parameterized_type, kFinalize, | 785 cls, parameterized_type, kFinalize, |
788 "type arguments of type '%s' are not within bounds", | 786 "type arguments of type '%s' are not within bounds", |
789 String::Handle(parameterized_type.Name()).ToCString()); | 787 String::Handle(parameterized_type.Name()).ToCString()); |
790 return parameterized_type.raw(); | 788 return parameterized_type.raw(); |
791 } | 789 } |
792 } | 790 } |
793 | 791 |
794 // If the type class is a signature class, we also finalize its signature | 792 // If the type class is a signature class, we are currently finalizing a |
795 // type, thereby finalizing the result type and parameter types of its | 793 // signature type, i.e. finalizing the result type and parameter types of the |
796 // signature function. | 794 // signature function of this signature type. |
797 // We do this after marking this type as finalized in order to allow a | 795 // We do this after marking this type as finalized in order to allow a |
798 // function type to refer to itself via its parameter types and result type. | 796 // function type to refer to itself via its parameter types and result type. |
799 if (type_class.IsSignatureClass()) { | 797 if (type_class.IsSignatureClass()) { |
800 // Signature classes are finalized upon creation. | 798 // Signature classes are finalized upon creation, except function type |
801 ASSERT(type_class.is_finalized()); | 799 // aliases. |
802 // Resolve and finalize the result and parameter types of the signature | 800 if (type_class.IsCanonicalSignatureClass()) { |
803 // function of this signature class. | 801 ASSERT(type_class.is_finalized()); |
804 ResolveAndFinalizeSignature( | 802 // Resolve and finalize the result and parameter types of the signature |
805 type_class, Function::Handle(type_class.signature_function())); | 803 // function of this signature class. |
804 ASSERT(type_class.SignatureType() == type.raw()); | |
805 ResolveAndFinalizeSignature( | |
806 type_class, Function::Handle(type_class.signature_function())); | |
807 } else { | |
808 // This type is a function type alias. Its class may need to be finalized | |
809 // and checked for illegal self reference. | |
810 FinalizeClass(type_class, false); | |
811 // Finalizing the signature function here (as in the canonical case above) | |
812 // would not mark the canonical signature type as finalized. | |
813 const Type& signature_type = Type::Handle(type_class.SignatureType()); | |
814 FinalizeType(cls, signature_type, finalization); | |
815 } | |
806 } | 816 } |
807 | 817 |
808 return parameterized_type.Canonicalize(); | 818 return parameterized_type.Canonicalize(); |
809 } | 819 } |
810 | 820 |
811 | 821 |
812 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, | 822 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, |
813 const Function& function) { | 823 const Function& function) { |
814 // Resolve result type. | 824 // Resolve result type. |
815 AbstractType& type = AbstractType::Handle(function.result_type()); | 825 AbstractType& type = AbstractType::Handle(function.result_type()); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1052 } | 1062 } |
1053 | 1063 |
1054 | 1064 |
1055 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { | 1065 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { |
1056 if (cls.is_finalized()) { | 1066 if (cls.is_finalized()) { |
1057 return; | 1067 return; |
1058 } | 1068 } |
1059 if (FLAG_trace_class_finalization) { | 1069 if (FLAG_trace_class_finalization) { |
1060 OS::Print("Finalize %s\n", cls.ToCString()); | 1070 OS::Print("Finalize %s\n", cls.ToCString()); |
1061 } | 1071 } |
1062 // Signature classes are finalized upon creation. | |
1063 ASSERT(!cls.IsSignatureClass()); | |
1064 if (!IsSuperCycleFree(cls)) { | 1072 if (!IsSuperCycleFree(cls)) { |
1065 const String& name = String::Handle(cls.Name()); | 1073 const String& name = String::Handle(cls.Name()); |
1066 const Script& script = Script::Handle(cls.script()); | 1074 const Script& script = Script::Handle(cls.script()); |
1067 ReportError(script, cls.token_index(), | 1075 ReportError(script, cls.token_index(), |
1068 "class '%s' has a cycle in its superclass relationship", | 1076 "class '%s' has a cycle in its superclass relationship", |
1069 name.ToCString()); | 1077 name.ToCString()); |
1070 } | 1078 } |
1071 const GrowableObjectArray& visited = | 1079 const GrowableObjectArray& visited_interfaces = |
1072 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1080 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
1073 ResolveInterfaces(cls, visited); | 1081 ResolveInterfaces(cls, visited_interfaces); |
1074 // Finalize super class. | 1082 // Finalize super class. |
1075 const Class& super_class = Class::Handle(cls.SuperClass()); | 1083 const Class& super_class = Class::Handle(cls.SuperClass()); |
1076 if (!super_class.IsNull()) { | 1084 if (!super_class.IsNull()) { |
1077 FinalizeClass(super_class, generating_snapshot); | 1085 FinalizeClass(super_class, generating_snapshot); |
1078 } | 1086 } |
1079 // Finalize type parameters before finalizing the super type. | 1087 // Finalize type parameters before finalizing the super type. |
1080 FinalizeTypeParameters(cls); | 1088 FinalizeTypeParameters(cls); |
1081 // Finalize super type. | 1089 // Finalize super type. |
1082 Type& super_type = Type::Handle(cls.super_type()); | 1090 Type& super_type = Type::Handle(cls.super_type()); |
1083 if (!super_type.IsNull()) { | 1091 if (!super_type.IsNull()) { |
1084 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); | 1092 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); |
1085 cls.set_super_type(super_type); | 1093 cls.set_super_type(super_type); |
1086 } | 1094 } |
1095 // Signature classes are finalized upon creation, except function type | |
1096 // aliases. | |
1097 if (cls.IsSignatureClass()) { | |
1098 ASSERT(!cls.IsCanonicalSignatureClass()); | |
1099 // Check for illegal self references. | |
1100 const GrowableObjectArray& visited_aliases = | |
1101 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
1102 if (!IsAliasCycleFree(cls, visited_aliases)) { | |
1103 const String& name = String::Handle(cls.Name()); | |
1104 const Script& script = Script::Handle(cls.script()); | |
1105 ReportError(script, cls.token_index(), | |
1106 "typedef '%s' illegally refers to itself", | |
1107 name.ToCString()); | |
1108 } | |
1109 // TODO(regis): Also check this: "It is a compile-time error if any default | |
1110 // values are specified in the signature of a function type alias". | |
1111 cls.Finalize(); | |
1112 return; | |
1113 } | |
1087 // Finalize factory class, if any. | 1114 // Finalize factory class, if any. |
1088 if (cls.is_interface()) { | 1115 if (cls.is_interface()) { |
1089 if (cls.HasFactoryClass()) { | 1116 if (cls.HasFactoryClass()) { |
1090 const Class& factory_class = Class::Handle(cls.FactoryClass()); | 1117 const Class& factory_class = Class::Handle(cls.FactoryClass()); |
1091 if (!factory_class.is_finalized()) { | 1118 if (!factory_class.is_finalized()) { |
1092 FinalizeClass(factory_class, generating_snapshot); | 1119 FinalizeClass(factory_class, generating_snapshot); |
1093 // Finalizing the factory class may indirectly finalize this interface. | 1120 // Finalizing the factory class may indirectly finalize this interface. |
1094 if (cls.is_finalized()) { | 1121 if (cls.is_finalized()) { |
1095 return; | 1122 return; |
1096 } | 1123 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1146 test2 = test2.SuperClass(); | 1173 test2 = test2.SuperClass(); |
1147 if (!test2.IsNull()) { | 1174 if (!test2.IsNull()) { |
1148 test2 = test2.SuperClass(); | 1175 test2 = test2.SuperClass(); |
1149 } | 1176 } |
1150 } | 1177 } |
1151 // No cycles. | 1178 // No cycles. |
1152 return true; | 1179 return true; |
1153 } | 1180 } |
1154 | 1181 |
1155 | 1182 |
1183 // Returns false if the function type alias illegally refers to itself. | |
1184 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, | |
1185 const GrowableObjectArray& visited) { | |
srdjan
2012/05/10 22:28:21
You should be using class index instead of class f
regis
2012/05/10 22:56:00
Done. I have also done this in ResolveInterfaces.
| |
1186 ASSERT(cls.IsSignatureClass()); | |
1187 ASSERT(!cls.IsCanonicalSignatureClass()); | |
1188 ASSERT(!cls.is_finalized()); | |
1189 ASSERT(!visited.IsNull()); | |
1190 Class& visited_cls = Class::Handle(); | |
1191 for (int i = 0; i < visited.Length(); i++) { | |
1192 visited_cls ^= visited.At(i); | |
1193 if (visited_cls.raw() == cls.raw()) { | |
1194 // We have already visited alias 'cls'. We found a cycle. | |
1195 return false; | |
1196 } | |
1197 } | |
1198 | |
1199 // Visit the result type and parameter types of this signature type. | |
1200 visited.Add(cls); | |
1201 const Function& function = Function::Handle(cls.signature_function()); | |
1202 // Check class of result type. | |
1203 AbstractType& type = AbstractType::Handle(function.result_type()); | |
1204 ResolveType(cls, type, kFinalize); | |
1205 if (type.IsType() && !type.IsMalformed()) { | |
1206 const Class& type_class = Class::Handle(type.type_class()); | |
1207 if (!type_class.is_finalized() && | |
1208 type_class.IsSignatureClass() && | |
1209 !type_class.IsCanonicalSignatureClass()) { | |
1210 if (!IsAliasCycleFree(type_class, visited)) { | |
1211 return false; | |
1212 } | |
1213 } | |
1214 } | |
1215 // Check classes of formal parameter types. | |
1216 const intptr_t num_parameters = function.NumberOfParameters(); | |
1217 for (intptr_t i = 0; i < num_parameters; i++) { | |
1218 type = function.ParameterTypeAt(i); | |
1219 ResolveType(cls, type, kFinalize); | |
1220 if (type.IsType() && !type.IsMalformed()) { | |
1221 const Class& type_class = Class::Handle(type.type_class()); | |
1222 if (!type_class.is_finalized() && | |
1223 type_class.IsSignatureClass() && | |
1224 !type_class.IsCanonicalSignatureClass()) { | |
1225 if (!IsAliasCycleFree(type_class, visited)) { | |
1226 return false; | |
1227 } | |
1228 } | |
1229 } | |
1230 } | |
1231 visited.RemoveLast(); | |
1232 return true; | |
1233 } | |
1234 | |
1235 | |
1156 bool ClassFinalizer::AddInterfaceIfUnique( | 1236 bool ClassFinalizer::AddInterfaceIfUnique( |
1157 const GrowableObjectArray& interface_list, | 1237 const GrowableObjectArray& interface_list, |
1158 const AbstractType& interface, | 1238 const AbstractType& interface, |
1159 AbstractType* conflicting) { | 1239 AbstractType* conflicting) { |
1160 String& interface_class_name = String::Handle(interface.ClassName()); | 1240 String& interface_class_name = String::Handle(interface.ClassName()); |
1161 String& existing_interface_class_name = String::Handle(); | 1241 String& existing_interface_class_name = String::Handle(); |
1162 String& interface_name = String::Handle(); | 1242 String& interface_name = String::Handle(); |
1163 String& existing_interface_name = String::Handle(); | 1243 String& existing_interface_name = String::Handle(); |
1164 AbstractType& other_interface = AbstractType::Handle(); | 1244 AbstractType& other_interface = AbstractType::Handle(); |
1165 for (intptr_t i = 0; i < interface_list.Length(); i++) { | 1245 for (intptr_t i = 0; i < interface_list.Length(); i++) { |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1409 void ClassFinalizer::ReportError(const char* format, ...) { | 1489 void ClassFinalizer::ReportError(const char* format, ...) { |
1410 va_list args; | 1490 va_list args; |
1411 va_start(args, format); | 1491 va_start(args, format); |
1412 const Error& error = Error::Handle( | 1492 const Error& error = Error::Handle( |
1413 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1493 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1414 va_end(args); | 1494 va_end(args); |
1415 ReportError(error); | 1495 ReportError(error); |
1416 } | 1496 } |
1417 | 1497 |
1418 } // namespace dart | 1498 } // namespace dart |
OLD | NEW |