Chromium Code Reviews| 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 1227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1238 !IsAliasCycleFree(type_class, visited)) { | 1238 !IsAliasCycleFree(type_class, visited)) { |
| 1239 return false; | 1239 return false; |
| 1240 } | 1240 } |
| 1241 } | 1241 } |
| 1242 } | 1242 } |
| 1243 visited->RemoveLast(); | 1243 visited->RemoveLast(); |
| 1244 return true; | 1244 return true; |
| 1245 } | 1245 } |
| 1246 | 1246 |
| 1247 | 1247 |
| 1248 void ClassFinalizer::ApplyMixin(const Class& cls, const Type& mixin) { | |
| 1249 ASSERT(mixin.HasResolvedTypeClass()); | |
| 1250 const Class& mixin_cls = Class::Handle(mixin.type_class()); | |
| 1251 | |
| 1252 // Check that the super class of the mixin class is extending | |
| 1253 // class Object. | |
| 1254 const Type& mixin_super_type = Type::Handle(mixin_cls.super_type()); | |
| 1255 ResolveType(mixin_cls, mixin_super_type, kCanonicalizeWellFormed); | |
| 1256 if (!mixin_super_type.IsObjectType()) { | |
| 1257 const Script& script = Script::Handle(cls.script()); | |
| 1258 const String& class_name = String::Handle(mixin_cls.Name()); | |
| 1259 ReportError(script, cls.token_pos(), | |
|
siva
2013/02/13 01:34:37
I am wondering if it would be more helpful if you
hausner
2013/02/13 19:58:14
I thought it makes more sense to report it where t
| |
| 1260 "mixin class %s must extend class Object", | |
| 1261 class_name.ToCString()); | |
| 1262 } | |
| 1263 | |
| 1264 const Array& functions = Array::Handle(mixin_cls.functions()); | |
| 1265 Function& func = Function::Handle(); | |
| 1266 const intptr_t num_functions = functions.Length(); | |
| 1267 for (int i = 0; i < num_functions; i++) { | |
| 1268 func ^= functions.At(i); | |
| 1269 if (func.IsConstructor()) { | |
| 1270 // A mixin class must not have explicit constructors. | |
| 1271 if (!func.IsImplicitConstructor()) { | |
| 1272 const Script& script = Script::Handle(cls.script()); | |
| 1273 ReportError(script, cls.token_pos(), | |
|
siva
2013/02/13 01:34:37
Ditto.
hausner
2013/02/13 19:58:14
Ditto.
| |
| 1274 "mixin class %s must not have constructors\n", | |
| 1275 String::Handle(mixin_cls.Name()).ToCString()); | |
| 1276 } | |
| 1277 continue; // Skip the implicit constructor. | |
| 1278 } | |
| 1279 // TODO(hausner): must check whether the function contains | |
| 1280 // super calls. If so, report error. | |
| 1281 if (!func.is_static()) { | |
| 1282 func = func.Clone(cls); | |
| 1283 cls.AddFunction(func); | |
|
siva
2013/02/13 01:34:37
Our AddFunction implementation is very inefficient
hausner
2013/02/13 19:58:14
I agree with what you suggest, but let me check it
| |
| 1284 } | |
| 1285 } | |
| 1286 Array& fields = Array::Handle(mixin_cls.fields()); | |
| 1287 Field& field = Field::Handle(); | |
| 1288 const GrowableObjectArray& cloned_fields = | |
| 1289 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
| 1290 const intptr_t num_fields = fields.Length(); | |
| 1291 for (int i = 0; i < num_fields; i++) { | |
| 1292 field ^= fields.At(i); | |
| 1293 if (!field.is_static()) { | |
| 1294 field = field.Clone(cls); | |
| 1295 cloned_fields.Add(field); | |
| 1296 } | |
| 1297 } | |
| 1298 fields = Array::MakeArray(cloned_fields); | |
|
siva
2013/02/13 01:34:37
Maybe we should assert here that
ASSERT(cls.fields
hausner
2013/02/13 19:58:14
Done.
| |
| 1299 cls.SetFields(fields); | |
| 1300 } | |
| 1301 | |
| 1302 | |
| 1248 // Recursively walks the graph of explicitly declared super type and | 1303 // Recursively walks the graph of explicitly declared super type and |
| 1249 // interfaces, resolving unresolved super types and interfaces. | 1304 // interfaces, resolving unresolved super types and interfaces. |
| 1250 // Reports an error if there is an interface reference that cannot be | 1305 // Reports an error if there is an interface reference that cannot be |
| 1251 // resolved, or if there is a cycle in the graph. We detect cycles by | 1306 // resolved, or if there is a cycle in the graph. We detect cycles by |
| 1252 // remembering interfaces we've visited in each path through the | 1307 // remembering interfaces we've visited in each path through the |
| 1253 // graph. If we visit an interface a second time on a given path, | 1308 // graph. If we visit an interface a second time on a given path, |
| 1254 // we found a loop. | 1309 // we found a loop. |
| 1255 void ClassFinalizer::ResolveSuperTypeAndInterfaces( | 1310 void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
| 1256 const Class& cls, GrowableArray<intptr_t>* visited) { | 1311 const Class& cls, GrowableArray<intptr_t>* visited) { |
| 1257 ASSERT(visited != NULL); | 1312 ASSERT(visited != NULL); |
| 1258 const intptr_t cls_index = cls.id(); | 1313 const intptr_t cls_index = cls.id(); |
| 1259 for (int i = 0; i < visited->length(); i++) { | 1314 for (int i = 0; i < visited->length(); i++) { |
| 1260 if ((*visited)[i] == cls_index) { | 1315 if ((*visited)[i] == cls_index) { |
| 1261 // We have already visited class 'cls'. We found a cycle. | 1316 // We have already visited class 'cls'. We found a cycle. |
| 1262 const String& class_name = String::Handle(cls.Name()); | 1317 const String& class_name = String::Handle(cls.Name()); |
| 1263 const Script& script = Script::Handle(cls.script()); | 1318 const Script& script = Script::Handle(cls.script()); |
| 1264 ReportError(script, cls.token_pos(), | 1319 ReportError(script, cls.token_pos(), |
| 1265 "cyclic reference found for class '%s'", | 1320 "cyclic reference found for class '%s'", |
| 1266 class_name.ToCString()); | 1321 class_name.ToCString()); |
| 1267 } | 1322 } |
| 1268 } | 1323 } |
| 1269 | 1324 |
| 1270 // If the class/interface has no explicit super class/interfaces, we are done. | 1325 // If the class/interface has no explicit super class/interfaces |
| 1326 // and is not a mixin application, we are done. | |
| 1271 Type& super_type = Type::Handle(cls.super_type()); | 1327 Type& super_type = Type::Handle(cls.super_type()); |
| 1328 Type& mixin_type = Type::Handle(cls.mixin()); | |
| 1272 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1329 Array& super_interfaces = Array::Handle(cls.interfaces()); |
| 1273 if ((super_type.IsNull() || super_type.IsObjectType()) && | 1330 if ((super_type.IsNull() || super_type.IsObjectType()) && |
| 1274 (super_interfaces.Length() == 0)) { | 1331 (super_interfaces.Length() == 0) && |
| 1332 (mixin_type.IsNull())) { | |
| 1275 return; | 1333 return; |
| 1276 } | 1334 } |
| 1277 | 1335 |
| 1278 // If cls belongs to core lib or to core lib's implementation, restrictions | 1336 if (!mixin_type.IsNull()) { |
| 1279 // about allowed interfaces are lifted. | 1337 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); |
| 1338 ApplyMixin(cls, mixin_type); | |
| 1339 } | |
| 1340 | |
| 1341 // If cls belongs to core lib, restrictions about allowed interfaces | |
| 1342 // are lifted. | |
| 1280 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); | 1343 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); |
| 1281 | 1344 |
| 1282 // Resolve and check the super type and interfaces of cls. | 1345 // Resolve and check the super type and interfaces of cls. |
| 1283 visited->Add(cls_index); | 1346 visited->Add(cls_index); |
| 1284 AbstractType& interface = AbstractType::Handle(); | 1347 AbstractType& interface = AbstractType::Handle(); |
| 1285 Class& interface_class = Class::Handle(); | 1348 Class& interface_class = Class::Handle(); |
| 1286 | 1349 |
| 1287 // Resolve super type. Failures lead to a longjmp. | 1350 // Resolve super type. Failures lead to a longjmp. |
| 1288 ResolveType(cls, super_type, kCanonicalizeWellFormed); | 1351 ResolveType(cls, super_type, kCanonicalizeWellFormed); |
| 1289 | 1352 |
| 1290 // If cls belongs to core lib or to core lib's implementation, restrictions | |
| 1291 interface_class = super_type.type_class(); | 1353 interface_class = super_type.type_class(); |
| 1292 // If cls belongs to core lib or to core lib's implementation, restrictions | 1354 // If cls belongs to core lib or to core lib's implementation, restrictions |
| 1293 // about allowed interfaces are lifted. | 1355 // about allowed interfaces are lifted. |
| 1294 if (!cls_belongs_to_core_lib) { | 1356 if (!cls_belongs_to_core_lib) { |
| 1295 // Prevent extending core implementation classes. | 1357 // Prevent extending core implementation classes. |
| 1296 bool is_error = false; | 1358 bool is_error = false; |
| 1297 switch (interface_class.id()) { | 1359 switch (interface_class.id()) { |
| 1298 case kNumberCid: | 1360 case kNumberCid: |
| 1299 case kIntegerCid: // Class Integer, not int. | 1361 case kIntegerCid: // Class Integer, not int. |
| 1300 case kSmiCid: | 1362 case kSmiCid: |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1582 void ClassFinalizer::ReportError(const char* format, ...) { | 1644 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1583 va_list args; | 1645 va_list args; |
| 1584 va_start(args, format); | 1646 va_start(args, format); |
| 1585 const Error& error = Error::Handle( | 1647 const Error& error = Error::Handle( |
| 1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1648 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1587 va_end(args); | 1649 va_end(args); |
| 1588 ReportError(error); | 1650 ReportError(error); |
| 1589 } | 1651 } |
| 1590 | 1652 |
| 1591 } // namespace dart | 1653 } // namespace dart |
| OLD | NEW |