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 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1177 function_name.ToCString(), | 1177 function_name.ToCString(), |
1178 class_name.ToCString(), | 1178 class_name.ToCString(), |
1179 function_name.ToCString(), | 1179 function_name.ToCString(), |
1180 super_class_name.ToCString()); | 1180 super_class_name.ToCString()); |
1181 } | 1181 } |
1182 } | 1182 } |
1183 } | 1183 } |
1184 } | 1184 } |
1185 | 1185 |
1186 | 1186 |
1187 // Copy the type parameters of the super and mixin classes to the | |
1188 // mixin application class. Change type arguments of super type to | |
1189 // refer to the respecive type parameters of the mixin application | |
regis
2013/03/14 23:40:34
respective
hausner
2013/03/15 00:36:32
Done.
| |
1190 // class. | |
1191 void ClassFinalizer::CloneTypeParameters(const Class& mixapp_class) { | |
1192 ASSERT(mixapp_class.NumTypeParameters() == 0); | |
1193 | |
1194 const AbstractType& super_type = | |
1195 AbstractType::Handle(mixapp_class.super_type()); | |
regis
2013/03/14 23:40:34
I would assert that the super type is not a MixinA
hausner
2013/03/15 00:36:32
Done.
| |
1196 const Class& super_class = Class::Handle(super_type.type_class()); | |
1197 | |
1198 const Type& mixin_type = Type::Handle(mixapp_class.mixin()); | |
1199 const Class& mixin_class = Class::Handle(mixin_type.type_class()); | |
1200 | |
1201 const int num_super_parameters = super_class.NumTypeParameters(); | |
1202 const int num_mixin_parameters = mixin_class.NumTypeParameters(); | |
1203 if ((num_super_parameters + num_mixin_parameters) == 0) { | |
1204 return; | |
1205 } | |
1206 | |
1207 // First, clone the super class type parameters. Rename them so that | |
1208 // there can be no name conflict between the parameters of the super | |
1209 // class and the mixin class. | |
1210 const TypeArguments& cloned_type_params = TypeArguments::Handle( | |
1211 TypeArguments::New(num_super_parameters + num_mixin_parameters)); | |
1212 TypeParameter& param = TypeParameter::Handle(); | |
1213 TypeParameter& cloned_param = TypeParameter::Handle(); | |
1214 String& param_name = String::Handle(); | |
1215 AbstractType& param_bound = AbstractType::Handle(); | |
1216 int cloned_index = 0; | |
1217 if (num_super_parameters > 0) { | |
1218 const TypeArguments& super_params = | |
1219 TypeArguments::Handle(super_class.type_parameters()); | |
1220 const TypeArguments& super_type_args = | |
1221 TypeArguments::Handle(TypeArguments::New(num_super_parameters)); | |
1222 for (int i = 0; i < num_super_parameters; i++) { | |
1223 param ^= super_params.TypeAt(i); | |
1224 param_name = param.name(); | |
1225 param_bound = param.bound(); | |
1226 // TODO(hausner): handle type bounds. | |
1227 if (!param_bound.IsObjectType()) { | |
1228 const Script& script = Script::Handle(mixapp_class.script()); | |
1229 ReportError(script, param.token_pos(), | |
1230 "type parameter '%s': type bounds not yet" | |
1231 " implemented for mixins\n", | |
1232 param_name.ToCString()); | |
1233 } | |
1234 param_name = String::Concat(param_name, Symbols::Backtick()); | |
1235 param_name = Symbols::New(param_name); | |
1236 cloned_param = TypeParameter::New(mixapp_class, | |
1237 cloned_index, | |
1238 param_name, | |
1239 param_bound, | |
1240 param.token_pos()); | |
1241 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | |
1242 // Change the type arguments of the super type to refer to the | |
1243 // cloned type parameters of the mixin application class. | |
1244 super_type_args.SetTypeAt(cloned_index, cloned_param); | |
1245 cloned_index++; | |
1246 } | |
1247 ASSERT(super_type.IsType()); | |
regis
2013/03/14 23:40:34
This may fail if the super type is a BoundedType.
hausner
2013/03/15 00:36:32
Added a todo that I need to handle BoundedType her
| |
1248 Type::Cast(super_type).set_arguments(super_type_args); | |
1249 } | |
1250 | |
1251 // Second, clone the type parameters of the mixin class. | |
1252 // We need to retain the parameter names of the mixin class | |
1253 // since the code that will be compiled in the context of the | |
1254 // mixin application class may refer to the type parameters | |
1255 // with that name. | |
1256 if (num_mixin_parameters > 0) { | |
1257 const TypeArguments& mixin_params = | |
1258 TypeArguments::Handle(mixin_class.type_parameters()); | |
1259 for (int i = 0; i < num_mixin_parameters; i++) { | |
1260 param ^= mixin_params.TypeAt(i); | |
1261 param_name = param.name(); | |
1262 param_bound = param.bound(); | |
1263 | |
1264 // TODO(hausner): handle type bounds. | |
1265 if (!param_bound.IsObjectType()) { | |
1266 const Script& script = Script::Handle(mixapp_class.script()); | |
1267 ReportError(script, param.token_pos(), | |
1268 "type parameter '%s': type bounds not yet" | |
1269 " implemented for mixins\n", | |
1270 param_name.ToCString()); | |
1271 } | |
1272 cloned_param = TypeParameter::New(mixapp_class, | |
1273 cloned_index, | |
1274 param_name, | |
1275 param_bound, | |
1276 param.token_pos()); | |
1277 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | |
1278 cloned_index++; | |
1279 } | |
1280 } | |
1281 mixapp_class.set_type_parameters(cloned_type_params); | |
1282 } | |
1283 | |
1284 | |
1187 void ClassFinalizer::ApplyMixin(const Class& cls) { | 1285 void ClassFinalizer::ApplyMixin(const Class& cls) { |
1188 const Type& mixin_type = Type::Handle(cls.mixin()); | 1286 const Type& mixin_type = Type::Handle(cls.mixin()); |
1189 ASSERT(!mixin_type.IsNull()); | 1287 ASSERT(!mixin_type.IsNull()); |
1190 ASSERT(mixin_type.HasResolvedTypeClass()); | 1288 ASSERT(mixin_type.HasResolvedTypeClass()); |
1191 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); | 1289 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); |
1192 | 1290 |
1193 if (FLAG_trace_class_finalization) { | 1291 if (FLAG_trace_class_finalization) { |
1194 OS::Print("Applying mixin '%s' to '%s'\n", | 1292 OS::Print("Applying mixin '%s' to '%s' at pos %"Pd"\n", |
1195 String::Handle(mixin_cls.Name()).ToCString(), | 1293 String::Handle(mixin_cls.Name()).ToCString(), |
1196 cls.ToCString()); | 1294 cls.ToCString(), |
1295 cls.token_pos()); | |
1197 } | 1296 } |
1198 | 1297 |
1199 // Check that the super class of the mixin class is extending | 1298 // Check that the super class of the mixin class is extending |
1200 // class Object. | 1299 // class Object. |
1201 const AbstractType& mixin_super_type = | 1300 const AbstractType& mixin_super_type = |
1202 AbstractType::Handle(mixin_cls.super_type()); | 1301 AbstractType::Handle(mixin_cls.super_type()); |
1203 if (!mixin_super_type.IsObjectType()) { | 1302 if (!mixin_super_type.IsObjectType()) { |
1204 const Script& script = Script::Handle(cls.script()); | 1303 const Script& script = Script::Handle(cls.script()); |
1205 const String& class_name = String::Handle(mixin_cls.Name()); | 1304 const String& class_name = String::Handle(mixin_cls.Name()); |
1206 ReportError(script, cls.token_pos(), | 1305 ReportError(script, cls.token_pos(), |
1207 "mixin class %s must extend class Object", | 1306 "mixin class %s must extend class Object", |
1208 class_name.ToCString()); | 1307 class_name.ToCString()); |
1209 } | 1308 } |
1210 | 1309 |
1211 // Copy the type parameters of the mixin class to the mixin | 1310 // Copy type parameters to mixin application class. |
1212 // application class. | 1311 CloneTypeParameters(cls); |
1213 const int num_type_parameters = mixin_cls.NumTypeParameters(); | |
1214 if (num_type_parameters > 0) { | |
1215 ASSERT(cls.NumTypeParameters() == 0); | |
1216 const TypeArguments& type_params = | |
1217 TypeArguments::Handle(mixin_cls.type_parameters()); | |
1218 const TypeArguments& cloned_type_params = | |
1219 TypeArguments::Handle(TypeArguments::New(num_type_parameters)); | |
1220 ASSERT(!type_params.IsNull()); | |
1221 TypeParameter& param = TypeParameter::Handle(); | |
1222 TypeParameter& cloned_param = TypeParameter::Handle(); | |
1223 String& param_name = String::Handle(); | |
1224 AbstractType& param_bound = AbstractType::Handle(); | |
1225 for (int i = 0; i < num_type_parameters; i++) { | |
1226 param ^= type_params.TypeAt(i); | |
1227 param_name = param.name(); | |
1228 param_bound = param.bound(); | |
1229 cloned_param = TypeParameter::New( | |
1230 cls, i, param_name, param_bound, param.token_pos()); | |
1231 cloned_type_params.SetTypeAt(i, cloned_param); | |
1232 } | |
1233 cls.set_type_parameters(cloned_type_params); | |
1234 } | |
1235 | 1312 |
1236 const GrowableObjectArray& cloned_funcs = | 1313 const GrowableObjectArray& cloned_funcs = |
1237 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1314 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
1238 Array& functions = Array::Handle(); | 1315 Array& functions = Array::Handle(); |
1239 Function& func = Function::Handle(); | 1316 Function& func = Function::Handle(); |
1240 // The parser creates the mixin application class and adds just | 1317 // The parser creates the mixin application class and adds just |
1241 // one function, the implicit constructor. | 1318 // one function, the implicit constructor. |
1242 functions = cls.functions(); | 1319 functions = cls.functions(); |
1243 ASSERT(functions.Length() == 1); | 1320 ASSERT(functions.Length() == 1); |
1244 func ^= functions.At(0); | 1321 func ^= functions.At(0); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1277 const intptr_t num_fields = fields.Length(); | 1354 const intptr_t num_fields = fields.Length(); |
1278 for (int i = 0; i < num_fields; i++) { | 1355 for (int i = 0; i < num_fields; i++) { |
1279 field ^= fields.At(i); | 1356 field ^= fields.At(i); |
1280 if (!field.is_static()) { | 1357 if (!field.is_static()) { |
1281 field = field.Clone(cls); | 1358 field = field.Clone(cls); |
1282 cloned_fields.Add(field); | 1359 cloned_fields.Add(field); |
1283 } | 1360 } |
1284 } | 1361 } |
1285 fields = Array::MakeArray(cloned_fields); | 1362 fields = Array::MakeArray(cloned_fields); |
1286 cls.SetFields(fields); | 1363 cls.SetFields(fields); |
1364 | |
1365 if (FLAG_trace_class_finalization) { | |
1366 OS::Print("done mixin appl %s %s extending %s\n", | |
1367 String::Handle(cls.Name()).ToCString(), | |
1368 TypeArguments::Handle(cls.type_parameters()).ToCString(), | |
1369 AbstractType::Handle(cls.super_type()).ToCString()); | |
1370 } | |
1287 } | 1371 } |
1288 | 1372 |
1289 | 1373 |
1290 void ClassFinalizer::FinalizeClass(const Class& cls) { | 1374 void ClassFinalizer::FinalizeClass(const Class& cls) { |
1291 if (cls.is_finalized()) { | 1375 if (cls.is_finalized()) { |
1292 return; | 1376 return; |
1293 } | 1377 } |
1294 if (FLAG_trace_class_finalization) { | 1378 if (FLAG_trace_class_finalization) { |
1295 OS::Print("Finalize %s\n", cls.ToCString()); | 1379 OS::Print("Finalize %s\n", cls.ToCString()); |
1296 } | 1380 } |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1444 !IsAliasCycleFree(type_class, visited)) { | 1528 !IsAliasCycleFree(type_class, visited)) { |
1445 return false; | 1529 return false; |
1446 } | 1530 } |
1447 } | 1531 } |
1448 } | 1532 } |
1449 visited->RemoveLast(); | 1533 visited->RemoveLast(); |
1450 return true; | 1534 return true; |
1451 } | 1535 } |
1452 | 1536 |
1453 | 1537 |
1538 void ClassFinalizer::CopyArgs(const Class& cls, | |
regis
2013/03/14 23:40:34
I would pick more meaningful names. What args are
hausner
2013/03/15 00:36:32
Done.
| |
1539 const Type& type, | |
1540 const GrowableObjectArray& args) { | |
1541 ASSERT(type.HasResolvedTypeClass()); | |
1542 Class& type_class = Class::Handle(type.type_class()); | |
1543 AbstractTypeArguments& type_args = | |
1544 AbstractTypeArguments::Handle(type.arguments()); | |
1545 intptr_t num_type_parameters = type_class.NumTypeParameters(); | |
1546 intptr_t num_type_arguments = type_args.IsNull() ? 0 : type_args.Length(); | |
1547 AbstractType& arg = AbstractType::Handle(); | |
1548 if (num_type_arguments > 0) { | |
1549 if (num_type_arguments != num_type_parameters) { | |
1550 const Script& script = Script::Handle(cls.script()); | |
1551 const String& type_class_name = String::Handle(type_class.Name()); | |
1552 ReportError(script, type.token_pos(), | |
1553 "wrong number of type arguments for class '%s'", | |
1554 type_class_name.ToCString()); | |
1555 } | |
1556 for (int i = 0; i < num_type_arguments; i++) { | |
1557 arg = type_args.TypeAt(i); | |
1558 args.Add(arg); | |
1559 } | |
1560 } else { | |
1561 // Fill arguments with type dynamic. | |
1562 for (int i = 0; i < num_type_parameters; i++) { | |
1563 arg = Type::DynamicType(); | |
1564 args.Add(arg); | |
1565 } | |
1566 } | |
1567 } | |
1568 | |
1569 | |
1570 RawType* ClassFinalizer::ResolveMixinAppType(const Class& cls, | |
1571 const MixinAppType& mixin_app) { | |
1572 // Resolve super type and all mixin types. | |
1573 const GrowableObjectArray& type_args = | |
1574 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
1575 AbstractType& type = AbstractType::Handle(mixin_app.super_type()); | |
1576 ResolveType(cls, type, kCanonicalizeWellFormed); | |
1577 ASSERT(type.HasResolvedTypeClass()); | |
1578 ASSERT(type.IsType()); | |
regis
2013/03/14 23:40:34
Not necessarily. It could be a BoundedType. Add a
hausner
2013/03/15 00:36:32
Same reasoning as above: the parser does not put a
| |
1579 CopyArgs(cls, Type::Cast(type), type_args); | |
1580 const Array& mixins = Array::Handle(mixin_app.mixin_types()); | |
1581 for (int i = 0; i < mixins.Length(); i++) { | |
1582 type ^= mixins.At(i); | |
1583 ASSERT(type.HasResolvedTypeClass()); // Newly created class in parser. | |
1584 const Class& mixin_app_class = Class::Handle(type.type_class()); | |
1585 type = mixin_app_class.mixin(); | |
1586 ASSERT(!type.IsNull()); | |
1587 ResolveType(cls, type, kCanonicalizeWellFormed); | |
1588 ASSERT(type.HasResolvedTypeClass()); | |
1589 ASSERT(type.IsType()); | |
1590 CopyArgs(cls, Type::Cast(type), type_args); | |
1591 } | |
1592 const TypeArguments& mixin_app_args = | |
1593 TypeArguments::Handle(TypeArguments::New(type_args.Length())); | |
1594 for (int i = 0; i < type_args.Length(); i++) { | |
1595 type ^= type_args.At(i); | |
1596 mixin_app_args.SetTypeAt(i, type); | |
1597 } | |
1598 if (FLAG_trace_class_finalization) { | |
1599 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n", | |
1600 mixin_app_args.ToCString()); | |
1601 } | |
1602 type ^= mixins.At(mixins.Length() - 1); | |
regis
2013/03/14 23:40:34
Can you explain in a comment that the last type in
hausner
2013/03/15 00:36:32
Actually, all elements in the mixins array are mix
| |
1603 const Class& resolved_mixin_app_class = Class::Handle(type.type_class()); | |
1604 Type& resolved_mixin_app_type = Type::Handle(); | |
1605 resolved_mixin_app_type = Type::New(resolved_mixin_app_class, | |
1606 mixin_app_args, | |
1607 mixin_app.token_pos()); | |
1608 return resolved_mixin_app_type.raw(); | |
1609 } | |
1610 | |
1611 | |
1454 // Recursively walks the graph of explicitly declared super type and | 1612 // Recursively walks the graph of explicitly declared super type and |
1455 // interfaces, resolving unresolved super types and interfaces. | 1613 // interfaces, resolving unresolved super types and interfaces. |
1456 // Reports an error if there is an interface reference that cannot be | 1614 // Reports an error if there is an interface reference that cannot be |
1457 // resolved, or if there is a cycle in the graph. We detect cycles by | 1615 // resolved, or if there is a cycle in the graph. We detect cycles by |
1458 // remembering interfaces we've visited in each path through the | 1616 // remembering interfaces we've visited in each path through the |
1459 // graph. If we visit an interface a second time on a given path, | 1617 // graph. If we visit an interface a second time on a given path, |
1460 // we found a loop. | 1618 // we found a loop. |
1461 void ClassFinalizer::ResolveSuperTypeAndInterfaces( | 1619 void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
1462 const Class& cls, GrowableArray<intptr_t>* visited) { | 1620 const Class& cls, GrowableArray<intptr_t>* visited) { |
1463 ASSERT(visited != NULL); | 1621 ASSERT(visited != NULL); |
1464 const intptr_t cls_index = cls.id(); | 1622 const intptr_t cls_index = cls.id(); |
1465 for (int i = 0; i < visited->length(); i++) { | 1623 for (int i = 0; i < visited->length(); i++) { |
1466 if ((*visited)[i] == cls_index) { | 1624 if ((*visited)[i] == cls_index) { |
1467 // We have already visited class 'cls'. We found a cycle. | 1625 // We have already visited class 'cls'. We found a cycle. |
1468 const String& class_name = String::Handle(cls.Name()); | 1626 const String& class_name = String::Handle(cls.Name()); |
1469 const Script& script = Script::Handle(cls.script()); | 1627 const Script& script = Script::Handle(cls.script()); |
1470 ReportError(script, cls.token_pos(), | 1628 ReportError(script, cls.token_pos(), |
1471 "cyclic reference found for class '%s'", | 1629 "cyclic reference found for class '%s'", |
1472 class_name.ToCString()); | 1630 class_name.ToCString()); |
1473 } | 1631 } |
1474 } | 1632 } |
1475 | 1633 |
1476 // If the class/interface has no explicit super class/interfaces | 1634 // If the class/interface has no explicit super class/interfaces |
1477 // and is not a mixin application, we are done. | 1635 // and is not a mixin application, we are done. |
1478 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 1636 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
1479 Type& mixin_type = Type::Handle(cls.mixin()); | |
1480 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1637 Array& super_interfaces = Array::Handle(cls.interfaces()); |
1481 if ((super_type.IsNull() || super_type.IsObjectType()) && | 1638 if ((super_type.IsNull() || super_type.IsObjectType()) && |
1482 (super_interfaces.Length() == 0) && | 1639 (super_interfaces.Length() == 0)) { |
1483 (mixin_type.IsNull())) { | |
1484 return; | 1640 return; |
1485 } | 1641 } |
1486 | 1642 |
1487 if (!mixin_type.IsNull()) { | 1643 if (super_type.IsMixinAppType()) { |
1488 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); | 1644 const MixinAppType& mixin_app_type = MixinAppType::Cast(super_type); |
1645 super_type = ResolveMixinAppType(cls, mixin_app_type); | |
1646 cls.set_super_type(super_type); | |
1489 } | 1647 } |
1490 | 1648 |
1491 // If cls belongs to core lib, restrictions about allowed interfaces | 1649 // If cls belongs to core lib, restrictions about allowed interfaces |
1492 // are lifted. | 1650 // are lifted. |
1493 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); | 1651 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); |
1494 | 1652 |
1495 // Resolve and check the super type and interfaces of cls. | 1653 // Resolve and check the super type and interfaces of cls. |
1496 visited->Add(cls_index); | 1654 visited->Add(cls_index); |
1497 AbstractType& interface = AbstractType::Handle(); | 1655 AbstractType& interface = AbstractType::Handle(); |
1498 Class& interface_class = Class::Handle(); | 1656 Class& interface_class = Class::Handle(); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1794 void ClassFinalizer::ReportError(const char* format, ...) { | 1952 void ClassFinalizer::ReportError(const char* format, ...) { |
1795 va_list args; | 1953 va_list args; |
1796 va_start(args, format); | 1954 va_start(args, format); |
1797 const Error& error = Error::Handle( | 1955 const Error& error = Error::Handle( |
1798 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1956 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1799 va_end(args); | 1957 va_end(args); |
1800 ReportError(error); | 1958 ReportError(error); |
1801 } | 1959 } |
1802 | 1960 |
1803 } // namespace dart | 1961 } // namespace dart |
OLD | NEW |