| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 function_name.ToCString(), | 1091 function_name.ToCString(), |
| 1092 class_name.ToCString(), | 1092 class_name.ToCString(), |
| 1093 function_name.ToCString(), | 1093 function_name.ToCString(), |
| 1094 super_class_name.ToCString()); | 1094 super_class_name.ToCString()); |
| 1095 } | 1095 } |
| 1096 } | 1096 } |
| 1097 } | 1097 } |
| 1098 } | 1098 } |
| 1099 | 1099 |
| 1100 | 1100 |
| 1101 void ClassFinalizer::ApplyMixin(const Class& cls) { |
| 1102 const Type& mixin_type = Type::Handle(cls.mixin()); |
| 1103 ASSERT(!mixin_type.IsNull()); |
| 1104 ASSERT(mixin_type.HasResolvedTypeClass()); |
| 1105 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); |
| 1106 |
| 1107 if (FLAG_trace_class_finalization) { |
| 1108 OS::Print("Applying mixin '%s' to '%s'\n", |
| 1109 String::Handle(mixin_cls.Name()).ToCString(), |
| 1110 cls.ToCString()); |
| 1111 } |
| 1112 |
| 1113 // Check that the super class of the mixin class is extending |
| 1114 // class Object. |
| 1115 const Type& mixin_super_type = Type::Handle(mixin_cls.super_type()); |
| 1116 if (!mixin_super_type.IsObjectType()) { |
| 1117 const Script& script = Script::Handle(cls.script()); |
| 1118 const String& class_name = String::Handle(mixin_cls.Name()); |
| 1119 ReportError(script, cls.token_pos(), |
| 1120 "mixin class %s must extend class Object", |
| 1121 class_name.ToCString()); |
| 1122 } |
| 1123 |
| 1124 const Array& functions = Array::Handle(mixin_cls.functions()); |
| 1125 Function& func = Function::Handle(); |
| 1126 const intptr_t num_functions = functions.Length(); |
| 1127 for (int i = 0; i < num_functions; i++) { |
| 1128 func ^= functions.At(i); |
| 1129 if (func.IsConstructor()) { |
| 1130 // A mixin class must not have explicit constructors. |
| 1131 if (!func.IsImplicitConstructor()) { |
| 1132 const Script& script = Script::Handle(cls.script()); |
| 1133 ReportError(script, cls.token_pos(), |
| 1134 "mixin class %s must not have constructors\n", |
| 1135 String::Handle(mixin_cls.Name()).ToCString()); |
| 1136 } |
| 1137 continue; // Skip the implicit constructor. |
| 1138 } |
| 1139 if (!func.is_static()) { |
| 1140 func = func.Clone(cls); |
| 1141 cls.AddFunction(func); |
| 1142 } |
| 1143 } |
| 1144 Array& fields = Array::Handle(mixin_cls.fields()); |
| 1145 Field& field = Field::Handle(); |
| 1146 const GrowableObjectArray& cloned_fields = |
| 1147 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1148 const intptr_t num_fields = fields.Length(); |
| 1149 for (int i = 0; i < num_fields; i++) { |
| 1150 field ^= fields.At(i); |
| 1151 if (!field.is_static()) { |
| 1152 field = field.Clone(cls); |
| 1153 cloned_fields.Add(field); |
| 1154 } |
| 1155 } |
| 1156 fields = Array::MakeArray(cloned_fields); |
| 1157 ASSERT(Array::Handle(cls.fields()).Length() == 0); |
| 1158 cls.SetFields(fields); |
| 1159 } |
| 1160 |
| 1161 |
| 1101 void ClassFinalizer::FinalizeClass(const Class& cls) { | 1162 void ClassFinalizer::FinalizeClass(const Class& cls) { |
| 1102 if (cls.is_finalized()) { | 1163 if (cls.is_finalized()) { |
| 1103 return; | 1164 return; |
| 1104 } | 1165 } |
| 1105 if (FLAG_trace_class_finalization) { | 1166 if (FLAG_trace_class_finalization) { |
| 1106 OS::Print("Finalize %s\n", cls.ToCString()); | 1167 OS::Print("Finalize %s\n", cls.ToCString()); |
| 1107 } | 1168 } |
| 1108 if (!IsSuperCycleFree(cls)) { | 1169 if (!IsSuperCycleFree(cls)) { |
| 1109 const String& name = String::Handle(cls.Name()); | 1170 const String& name = String::Handle(cls.Name()); |
| 1110 const Script& script = Script::Handle(cls.script()); | 1171 const Script& script = Script::Handle(cls.script()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 // Resolve and finalize the result and parameter types of the signature | 1204 // Resolve and finalize the result and parameter types of the signature |
| 1144 // function of this signature class. | 1205 // function of this signature class. |
| 1145 const Function& sig_function = Function::Handle(cls.signature_function()); | 1206 const Function& sig_function = Function::Handle(cls.signature_function()); |
| 1146 ResolveAndFinalizeSignature(cls, sig_function); | 1207 ResolveAndFinalizeSignature(cls, sig_function); |
| 1147 | 1208 |
| 1148 // Resolve and finalize the signature type of this signature class. | 1209 // Resolve and finalize the signature type of this signature class. |
| 1149 const Type& sig_type = Type::Handle(cls.SignatureType()); | 1210 const Type& sig_type = Type::Handle(cls.SignatureType()); |
| 1150 FinalizeType(cls, sig_type, kCanonicalizeWellFormed); | 1211 FinalizeType(cls, sig_type, kCanonicalizeWellFormed); |
| 1151 return; | 1212 return; |
| 1152 } | 1213 } |
| 1214 if (cls.mixin() != Type::null()) { |
| 1215 // Copy instance methods and fields from the mixin class. |
| 1216 // This has to happen before the check whether the methods of |
| 1217 // the class conflict with inherited methods. |
| 1218 ApplyMixin(cls); |
| 1219 } |
| 1153 // Finalize interface types (but not necessarily interface classes). | 1220 // Finalize interface types (but not necessarily interface classes). |
| 1154 Array& interface_types = Array::Handle(cls.interfaces()); | 1221 Array& interface_types = Array::Handle(cls.interfaces()); |
| 1155 AbstractType& interface_type = AbstractType::Handle(); | 1222 AbstractType& interface_type = AbstractType::Handle(); |
| 1156 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 1223 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
| 1157 interface_type ^= interface_types.At(i); | 1224 interface_type ^= interface_types.At(i); |
| 1158 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1225 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
| 1159 interface_types.SetAt(i, interface_type); | 1226 interface_types.SetAt(i, interface_type); |
| 1160 } | 1227 } |
| 1161 // Mark as finalized before resolving type parameter upper bounds and member | 1228 // Mark as finalized before resolving type parameter upper bounds and member |
| 1162 // types in order to break cycles. | 1229 // types in order to break cycles. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 if ((*visited)[i] == cls_index) { | 1327 if ((*visited)[i] == cls_index) { |
| 1261 // We have already visited class 'cls'. We found a cycle. | 1328 // We have already visited class 'cls'. We found a cycle. |
| 1262 const String& class_name = String::Handle(cls.Name()); | 1329 const String& class_name = String::Handle(cls.Name()); |
| 1263 const Script& script = Script::Handle(cls.script()); | 1330 const Script& script = Script::Handle(cls.script()); |
| 1264 ReportError(script, cls.token_pos(), | 1331 ReportError(script, cls.token_pos(), |
| 1265 "cyclic reference found for class '%s'", | 1332 "cyclic reference found for class '%s'", |
| 1266 class_name.ToCString()); | 1333 class_name.ToCString()); |
| 1267 } | 1334 } |
| 1268 } | 1335 } |
| 1269 | 1336 |
| 1270 // If the class/interface has no explicit super class/interfaces, we are done. | 1337 // If the class/interface has no explicit super class/interfaces |
| 1338 // and is not a mixin application, we are done. |
| 1271 Type& super_type = Type::Handle(cls.super_type()); | 1339 Type& super_type = Type::Handle(cls.super_type()); |
| 1340 Type& mixin_type = Type::Handle(cls.mixin()); |
| 1272 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1341 Array& super_interfaces = Array::Handle(cls.interfaces()); |
| 1273 if ((super_type.IsNull() || super_type.IsObjectType()) && | 1342 if ((super_type.IsNull() || super_type.IsObjectType()) && |
| 1274 (super_interfaces.Length() == 0)) { | 1343 (super_interfaces.Length() == 0) && |
| 1344 (mixin_type.IsNull())) { |
| 1275 return; | 1345 return; |
| 1276 } | 1346 } |
| 1277 | 1347 |
| 1278 // If cls belongs to core lib or to core lib's implementation, restrictions | 1348 if (!mixin_type.IsNull()) { |
| 1279 // about allowed interfaces are lifted. | 1349 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); |
| 1350 } |
| 1351 |
| 1352 // If cls belongs to core lib, restrictions about allowed interfaces |
| 1353 // are lifted. |
| 1280 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); | 1354 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); |
| 1281 | 1355 |
| 1282 // Resolve and check the super type and interfaces of cls. | 1356 // Resolve and check the super type and interfaces of cls. |
| 1283 visited->Add(cls_index); | 1357 visited->Add(cls_index); |
| 1284 AbstractType& interface = AbstractType::Handle(); | 1358 AbstractType& interface = AbstractType::Handle(); |
| 1285 Class& interface_class = Class::Handle(); | 1359 Class& interface_class = Class::Handle(); |
| 1286 | 1360 |
| 1287 // Resolve super type. Failures lead to a longjmp. | 1361 // Resolve super type. Failures lead to a longjmp. |
| 1288 ResolveType(cls, super_type, kCanonicalizeWellFormed); | 1362 ResolveType(cls, super_type, kCanonicalizeWellFormed); |
| 1289 | 1363 |
| 1290 // If cls belongs to core lib or to core lib's implementation, restrictions | |
| 1291 interface_class = super_type.type_class(); | 1364 interface_class = super_type.type_class(); |
| 1292 // If cls belongs to core lib or to core lib's implementation, restrictions | 1365 // If cls belongs to core lib or to core lib's implementation, restrictions |
| 1293 // about allowed interfaces are lifted. | 1366 // about allowed interfaces are lifted. |
| 1294 if (!cls_belongs_to_core_lib) { | 1367 if (!cls_belongs_to_core_lib) { |
| 1295 // Prevent extending core implementation classes. | 1368 // Prevent extending core implementation classes. |
| 1296 bool is_error = false; | 1369 bool is_error = false; |
| 1297 switch (interface_class.id()) { | 1370 switch (interface_class.id()) { |
| 1298 case kNumberCid: | 1371 case kNumberCid: |
| 1299 case kIntegerCid: // Class Integer, not int. | 1372 case kIntegerCid: // Class Integer, not int. |
| 1300 case kSmiCid: | 1373 case kSmiCid: |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 void ClassFinalizer::ReportError(const char* format, ...) { | 1655 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1583 va_list args; | 1656 va_list args; |
| 1584 va_start(args, format); | 1657 va_start(args, format); |
| 1585 const Error& error = Error::Handle( | 1658 const Error& error = Error::Handle( |
| 1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1659 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1587 va_end(args); | 1660 va_end(args); |
| 1588 ReportError(error); | 1661 ReportError(error); |
| 1589 } | 1662 } |
| 1590 | 1663 |
| 1591 } // namespace dart | 1664 } // namespace dart |
| OLD | NEW |