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

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

Issue 10377095: Implement latest rules prohibiting some self referencing typedefs. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | 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) 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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698