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 respective type parameters of the mixin application |
| 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()); |
| 1196 ASSERT(super_type.IsResolved()); |
| 1197 const Class& super_class = Class::Handle(super_type.type_class()); |
| 1198 const Type& mixin_type = Type::Handle(mixapp_class.mixin()); |
| 1199 const Class& mixin_class = Class::Handle(mixin_type.type_class()); |
| 1200 const int num_super_parameters = super_class.NumTypeParameters(); |
| 1201 const int num_mixin_parameters = mixin_class.NumTypeParameters(); |
| 1202 if ((num_super_parameters + num_mixin_parameters) == 0) { |
| 1203 return; |
| 1204 } |
| 1205 |
| 1206 // First, clone the super class type parameters. Rename them so that |
| 1207 // there can be no name conflict between the parameters of the super |
| 1208 // class and the mixin class. |
| 1209 const TypeArguments& cloned_type_params = TypeArguments::Handle( |
| 1210 TypeArguments::New(num_super_parameters + num_mixin_parameters)); |
| 1211 TypeParameter& param = TypeParameter::Handle(); |
| 1212 TypeParameter& cloned_param = TypeParameter::Handle(); |
| 1213 String& param_name = String::Handle(); |
| 1214 AbstractType& param_bound = AbstractType::Handle(); |
| 1215 int cloned_index = 0; |
| 1216 if (num_super_parameters > 0) { |
| 1217 const TypeArguments& super_params = |
| 1218 TypeArguments::Handle(super_class.type_parameters()); |
| 1219 const TypeArguments& super_type_args = |
| 1220 TypeArguments::Handle(TypeArguments::New(num_super_parameters)); |
| 1221 for (int i = 0; i < num_super_parameters; i++) { |
| 1222 param ^= super_params.TypeAt(i); |
| 1223 param_name = param.name(); |
| 1224 param_bound = param.bound(); |
| 1225 // TODO(hausner): handle type bounds. |
| 1226 if (!param_bound.IsObjectType()) { |
| 1227 const Script& script = Script::Handle(mixapp_class.script()); |
| 1228 ReportError(script, param.token_pos(), |
| 1229 "type parameter '%s': type bounds not yet" |
| 1230 " implemented for mixins\n", |
| 1231 param_name.ToCString()); |
| 1232 } |
| 1233 param_name = String::Concat(param_name, Symbols::Backtick()); |
| 1234 param_name = Symbols::New(param_name); |
| 1235 cloned_param = TypeParameter::New(mixapp_class, |
| 1236 cloned_index, |
| 1237 param_name, |
| 1238 param_bound, |
| 1239 param.token_pos()); |
| 1240 cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
| 1241 // Change the type arguments of the super type to refer to the |
| 1242 // cloned type parameters of the mixin application class. |
| 1243 super_type_args.SetTypeAt(cloned_index, cloned_param); |
| 1244 cloned_index++; |
| 1245 } |
| 1246 // TODO(hausner): May need to handle BoundedType here. |
| 1247 ASSERT(super_type.IsType()); |
| 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::CollectTypeArguments(const Class& cls, |
| 1539 const Type& type, |
| 1540 const GrowableObjectArray& collected_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 collected_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 collected_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 // TODO(hausner): May need to handle BoundedType here. |
| 1579 ASSERT(type.IsType()); |
| 1580 CollectTypeArguments(cls, Type::Cast(type), type_args); |
| 1581 const Array& mixins = Array::Handle(mixin_app.mixin_types()); |
| 1582 for (int i = 0; i < mixins.Length(); i++) { |
| 1583 type ^= mixins.At(i); |
| 1584 ASSERT(type.HasResolvedTypeClass()); // Newly created class in parser. |
| 1585 const Class& mixin_app_class = Class::Handle(type.type_class()); |
| 1586 type = mixin_app_class.mixin(); |
| 1587 ASSERT(!type.IsNull()); |
| 1588 ResolveType(cls, type, kCanonicalizeWellFormed); |
| 1589 ASSERT(type.HasResolvedTypeClass()); |
| 1590 ASSERT(type.IsType()); |
| 1591 CollectTypeArguments(cls, Type::Cast(type), type_args); |
| 1592 } |
| 1593 const TypeArguments& mixin_app_args = |
| 1594 TypeArguments::Handle(TypeArguments::New(type_args.Length())); |
| 1595 for (int i = 0; i < type_args.Length(); i++) { |
| 1596 type ^= type_args.At(i); |
| 1597 mixin_app_args.SetTypeAt(i, type); |
| 1598 } |
| 1599 if (FLAG_trace_class_finalization) { |
| 1600 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n", |
| 1601 mixin_app_args.ToCString()); |
| 1602 } |
| 1603 // The last element in the mixins array is the lowest mixin application |
| 1604 // type in the mixin chain. Build a new super type with its type class |
| 1605 // and the collected type arguments from the super type and all |
| 1606 // mixin types. This super type replaces the MixinAppType object |
| 1607 // in the class that extends the mixin application. |
| 1608 type ^= mixins.At(mixins.Length() - 1); |
| 1609 const Class& resolved_mixin_app_class = Class::Handle(type.type_class()); |
| 1610 Type& resolved_mixin_app_type = Type::Handle(); |
| 1611 resolved_mixin_app_type = Type::New(resolved_mixin_app_class, |
| 1612 mixin_app_args, |
| 1613 mixin_app.token_pos()); |
| 1614 return resolved_mixin_app_type.raw(); |
| 1615 } |
| 1616 |
| 1617 |
1454 // Recursively walks the graph of explicitly declared super type and | 1618 // Recursively walks the graph of explicitly declared super type and |
1455 // interfaces, resolving unresolved super types and interfaces. | 1619 // interfaces, resolving unresolved super types and interfaces. |
1456 // Reports an error if there is an interface reference that cannot be | 1620 // 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 | 1621 // 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 | 1622 // remembering interfaces we've visited in each path through the |
1459 // graph. If we visit an interface a second time on a given path, | 1623 // graph. If we visit an interface a second time on a given path, |
1460 // we found a loop. | 1624 // we found a loop. |
1461 void ClassFinalizer::ResolveSuperTypeAndInterfaces( | 1625 void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
1462 const Class& cls, GrowableArray<intptr_t>* visited) { | 1626 const Class& cls, GrowableArray<intptr_t>* visited) { |
1463 ASSERT(visited != NULL); | 1627 ASSERT(visited != NULL); |
1464 const intptr_t cls_index = cls.id(); | 1628 const intptr_t cls_index = cls.id(); |
1465 for (int i = 0; i < visited->length(); i++) { | 1629 for (int i = 0; i < visited->length(); i++) { |
1466 if ((*visited)[i] == cls_index) { | 1630 if ((*visited)[i] == cls_index) { |
1467 // We have already visited class 'cls'. We found a cycle. | 1631 // We have already visited class 'cls'. We found a cycle. |
1468 const String& class_name = String::Handle(cls.Name()); | 1632 const String& class_name = String::Handle(cls.Name()); |
1469 const Script& script = Script::Handle(cls.script()); | 1633 const Script& script = Script::Handle(cls.script()); |
1470 ReportError(script, cls.token_pos(), | 1634 ReportError(script, cls.token_pos(), |
1471 "cyclic reference found for class '%s'", | 1635 "cyclic reference found for class '%s'", |
1472 class_name.ToCString()); | 1636 class_name.ToCString()); |
1473 } | 1637 } |
1474 } | 1638 } |
1475 | 1639 |
1476 // If the class/interface has no explicit super class/interfaces | 1640 // If the class/interface has no explicit super class/interfaces |
1477 // and is not a mixin application, we are done. | 1641 // and is not a mixin application, we are done. |
1478 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 1642 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
1479 Type& mixin_type = Type::Handle(cls.mixin()); | |
1480 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1643 Array& super_interfaces = Array::Handle(cls.interfaces()); |
1481 if ((super_type.IsNull() || super_type.IsObjectType()) && | 1644 if ((super_type.IsNull() || super_type.IsObjectType()) && |
1482 (super_interfaces.Length() == 0) && | 1645 (super_interfaces.Length() == 0)) { |
1483 (mixin_type.IsNull())) { | |
1484 return; | 1646 return; |
1485 } | 1647 } |
1486 | 1648 |
1487 if (!mixin_type.IsNull()) { | 1649 if (super_type.IsMixinAppType()) { |
1488 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); | 1650 const MixinAppType& mixin_app_type = MixinAppType::Cast(super_type); |
| 1651 super_type = ResolveMixinAppType(cls, mixin_app_type); |
| 1652 cls.set_super_type(super_type); |
1489 } | 1653 } |
1490 | 1654 |
1491 // If cls belongs to core lib, restrictions about allowed interfaces | 1655 // If cls belongs to core lib, restrictions about allowed interfaces |
1492 // are lifted. | 1656 // are lifted. |
1493 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); | 1657 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); |
1494 | 1658 |
1495 // Resolve and check the super type and interfaces of cls. | 1659 // Resolve and check the super type and interfaces of cls. |
1496 visited->Add(cls_index); | 1660 visited->Add(cls_index); |
1497 AbstractType& interface = AbstractType::Handle(); | 1661 AbstractType& interface = AbstractType::Handle(); |
1498 Class& interface_class = Class::Handle(); | 1662 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, ...) { | 1958 void ClassFinalizer::ReportError(const char* format, ...) { |
1795 va_list args; | 1959 va_list args; |
1796 va_start(args, format); | 1960 va_start(args, format); |
1797 const Error& error = Error::Handle( | 1961 const Error& error = Error::Handle( |
1798 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1962 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1799 va_end(args); | 1963 va_end(args); |
1800 ReportError(error); | 1964 ReportError(error); |
1801 } | 1965 } |
1802 | 1966 |
1803 } // namespace dart | 1967 } // namespace dart |
OLD | NEW |