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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 if (resolved_class.IsNull() && !ambiguity_error_msg.IsNull()) { | 275 if (resolved_class.IsNull() && !ambiguity_error_msg.IsNull()) { |
276 const Script& script = Script::Handle(cls.script()); | 276 const Script& script = Script::Handle(cls.script()); |
277 *ambiguity_error = Parser::FormatErrorMsg( | 277 *ambiguity_error = Parser::FormatErrorMsg( |
278 script, unresolved_class.token_pos(), "Error", | 278 script, unresolved_class.token_pos(), "Error", |
279 "%s", ambiguity_error_msg.ToCString()); | 279 "%s", ambiguity_error_msg.ToCString()); |
280 } | 280 } |
281 return resolved_class.raw(); | 281 return resolved_class.raw(); |
282 } | 282 } |
283 | 283 |
284 | 284 |
| 285 |
| 286 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, |
| 287 const Function& factory) { |
| 288 const Function& target = Function::Handle(factory.RedirectionTarget()); |
| 289 if (target.IsNull()) { |
| 290 const Type& type = Type::Handle(factory.RedirectionType()); |
| 291 if (!type.IsMalformed()) { |
| 292 const GrowableObjectArray& visited_factories = |
| 293 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 294 ResolveRedirectingFactoryTarget(cls, factory, visited_factories); |
| 295 } |
| 296 } |
| 297 } |
| 298 |
| 299 |
285 void ClassFinalizer::ResolveRedirectingFactoryTarget( | 300 void ClassFinalizer::ResolveRedirectingFactoryTarget( |
286 const Class& cls, | 301 const Class& cls, |
287 const Function& factory, | 302 const Function& factory, |
288 const GrowableObjectArray& visited_factories) { | 303 const GrowableObjectArray& visited_factories) { |
289 ASSERT(factory.IsRedirectingFactory()); | 304 ASSERT(factory.IsRedirectingFactory()); |
290 | 305 |
291 // Check for redirection cycle. | 306 // Check for redirection cycle. |
292 for (int i = 0; i < visited_factories.Length(); i++) { | 307 for (int i = 0; i < visited_factories.Length(); i++) { |
293 if (visited_factories.At(i) == factory.raw()) { | 308 if (visited_factories.At(i) == factory.raw()) { |
294 // A redirection cycle is reported as a compile-time error. | 309 // A redirection cycle is reported as a compile-time error. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 kResolveTypeParameters, // No compile-time error. | 393 kResolveTypeParameters, // No compile-time error. |
379 "constructor '%s' has incompatible parameters with " | 394 "constructor '%s' has incompatible parameters with " |
380 "redirecting factory '%s'", | 395 "redirecting factory '%s'", |
381 String::Handle(target.name()).ToCString(), | 396 String::Handle(target.name()).ToCString(), |
382 String::Handle(factory.name()).ToCString()); | 397 String::Handle(factory.name()).ToCString()); |
383 factory.SetRedirectionType(type); | 398 factory.SetRedirectionType(type); |
384 ASSERT(factory.RedirectionTarget() == Function::null()); | 399 ASSERT(factory.RedirectionTarget() == Function::null()); |
385 return; | 400 return; |
386 } | 401 } |
387 | 402 |
388 // Verify that the target is const if the the redirecting factory is const. | 403 // Verify that the target is const if the redirecting factory is const. |
389 if (factory.is_const() && !target.is_const()) { | 404 if (factory.is_const() && !target.is_const()) { |
390 const Script& script = Script::Handle(cls.script()); | 405 const Script& script = Script::Handle(cls.script()); |
391 ReportError(script, factory.token_pos(), | 406 ReportError(script, factory.token_pos(), |
392 "constructor '%s' must be const as required by redirecting" | 407 "constructor '%s' must be const as required by redirecting" |
393 "const factory '%s'", | 408 "const factory '%s'", |
394 String::Handle(target.name()).ToCString(), | 409 String::Handle(target.name()).ToCString(), |
395 String::Handle(factory.name()).ToCString()); | 410 String::Handle(factory.name()).ToCString()); |
396 } | 411 } |
397 | 412 |
398 // Update redirection data with resolved target. | 413 // Update redirection data with resolved target. |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 const String& super_class_name = String::Handle(super_class.Name()); | 1167 const String& super_class_name = String::Handle(super_class.Name()); |
1153 const Script& script = Script::Handle(cls.script()); | 1168 const Script& script = Script::Handle(cls.script()); |
1154 ReportError(script, function.token_pos(), | 1169 ReportError(script, function.token_pos(), |
1155 "static function '%s' of class '%s' conflicts with " | 1170 "static function '%s' of class '%s' conflicts with " |
1156 "instance member '%s' of super class '%s'", | 1171 "instance member '%s' of super class '%s'", |
1157 function_name.ToCString(), | 1172 function_name.ToCString(), |
1158 class_name.ToCString(), | 1173 class_name.ToCString(), |
1159 function_name.ToCString(), | 1174 function_name.ToCString(), |
1160 super_class_name.ToCString()); | 1175 super_class_name.ToCString()); |
1161 } | 1176 } |
1162 if (function.IsRedirectingFactory()) { | 1177 // The function may be a still unresolved redirecting factory. Do not yet |
1163 const GrowableObjectArray& redirecting_factories = | 1178 // try to resolve it in order to avoid cycles in class finalization. |
1164 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
1165 ResolveRedirectingFactoryTarget(cls, function, redirecting_factories); | |
1166 } | |
1167 } else { | 1179 } else { |
1168 for (int i = 0; i < interfaces.Length(); i++) { | 1180 for (int i = 0; i < interfaces.Length(); i++) { |
1169 super_class ^= interfaces.At(i); | 1181 super_class ^= interfaces.At(i); |
1170 overridden_function = super_class.LookupDynamicFunction(function_name); | 1182 overridden_function = super_class.LookupDynamicFunction(function_name); |
1171 if (!overridden_function.IsNull() && | 1183 if (!overridden_function.IsNull() && |
1172 !function.HasCompatibleParametersWith(overridden_function)) { | 1184 !function.HasCompatibleParametersWith(overridden_function)) { |
1173 // Function types are purposely not checked for subtyping. | 1185 // Function types are purposely not checked for subtyping. |
1174 const String& class_name = String::Handle(cls.Name()); | 1186 const String& class_name = String::Handle(cls.Name()); |
1175 const String& super_class_name = String::Handle(super_class.Name()); | 1187 const String& super_class_name = String::Handle(super_class.Name()); |
1176 const Script& script = Script::Handle(cls.script()); | 1188 const Script& script = Script::Handle(cls.script()); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1498 } | 1510 } |
1499 } | 1511 } |
1500 | 1512 |
1501 | 1513 |
1502 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { | 1514 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
1503 HANDLESCOPE(Isolate::Current()); | 1515 HANDLESCOPE(Isolate::Current()); |
1504 if (cls.is_type_finalized()) { | 1516 if (cls.is_type_finalized()) { |
1505 return; | 1517 return; |
1506 } | 1518 } |
1507 if (FLAG_trace_class_finalization) { | 1519 if (FLAG_trace_class_finalization) { |
1508 OS::Print("Finalize %s\n", cls.ToCString()); | 1520 OS::Print("Finalize types in %s\n", cls.ToCString()); |
1509 } | 1521 } |
1510 if (!IsSuperCycleFree(cls)) { | 1522 if (!IsSuperCycleFree(cls)) { |
1511 const String& name = String::Handle(cls.Name()); | 1523 const String& name = String::Handle(cls.Name()); |
1512 const Script& script = Script::Handle(cls.script()); | 1524 const Script& script = Script::Handle(cls.script()); |
1513 ReportError(script, cls.token_pos(), | 1525 ReportError(script, cls.token_pos(), |
1514 "class '%s' has a cycle in its superclass relationship", | 1526 "class '%s' has a cycle in its superclass relationship", |
1515 name.ToCString()); | 1527 name.ToCString()); |
1516 } | 1528 } |
1517 // Finalize super class. | 1529 // Finalize super class. |
1518 const Class& super_class = Class::Handle(cls.SuperClass()); | 1530 const Class& super_class = Class::Handle(cls.SuperClass()); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1607 // contains them. | 1619 // contains them. |
1608 FinalizeUpperBounds(cls); | 1620 FinalizeUpperBounds(cls); |
1609 // Add this class to the direct subclasses of the superclass, unless the | 1621 // Add this class to the direct subclasses of the superclass, unless the |
1610 // superclass is Object. | 1622 // superclass is Object. |
1611 if (!super_type.IsNull() && !super_type.IsObjectType()) { | 1623 if (!super_type.IsNull() && !super_type.IsObjectType()) { |
1612 ASSERT(!super_class.IsNull()); | 1624 ASSERT(!super_class.IsNull()); |
1613 super_class.AddDirectSubclass(cls); | 1625 super_class.AddDirectSubclass(cls); |
1614 } | 1626 } |
1615 // Top level classes are parsed eagerly so just finalize it. | 1627 // Top level classes are parsed eagerly so just finalize it. |
1616 if (cls.IsTopLevel()) { | 1628 if (cls.IsTopLevel()) { |
1617 ClassFinalizer::FinalizeClass(cls); | 1629 FinalizeClass(cls); |
1618 } | 1630 } |
1619 } | 1631 } |
1620 | 1632 |
1621 | 1633 |
1622 void ClassFinalizer::FinalizeClass(const Class& cls) { | 1634 void ClassFinalizer::FinalizeClass(const Class& cls) { |
1623 HANDLESCOPE(Isolate::Current()); | 1635 HANDLESCOPE(Isolate::Current()); |
1624 if (cls.is_finalized()) { | 1636 if (cls.is_finalized()) { |
1625 return; | 1637 return; |
1626 } | 1638 } |
| 1639 if (FLAG_trace_class_finalization) { |
| 1640 OS::Print("Finalize %s\n", cls.ToCString()); |
| 1641 } |
1627 if (cls.mixin() != Type::null()) { | 1642 if (cls.mixin() != Type::null()) { |
1628 // Copy instance methods and fields from the mixin class. | 1643 // Copy instance methods and fields from the mixin class. |
1629 // This has to happen before the check whether the methods of | 1644 // This has to happen before the check whether the methods of |
1630 // the class conflict with inherited methods. | 1645 // the class conflict with inherited methods. |
1631 ApplyMixin(cls); | 1646 ApplyMixin(cls); |
1632 } | 1647 } |
| 1648 // Ensure super class is finalized. |
| 1649 const Class& super = Class::Handle(cls.SuperClass()); |
| 1650 if (!super.IsNull()) { |
| 1651 FinalizeClass(super); |
| 1652 } |
1633 // Mark as parsed and finalized. | 1653 // Mark as parsed and finalized. |
1634 cls.Finalize(); | 1654 cls.Finalize(); |
1635 // Resolve and finalize all member types. | 1655 // Resolve and finalize all member types. |
1636 ResolveAndFinalizeMemberTypes(cls); | 1656 ResolveAndFinalizeMemberTypes(cls); |
1637 // Run additional checks after all types are finalized. | 1657 // Run additional checks after all types are finalized. |
1638 if (cls.is_const()) { | 1658 if (cls.is_const()) { |
1639 CheckForLegalConstClass(cls); | 1659 CheckForLegalConstClass(cls); |
1640 } | 1660 } |
1641 } | 1661 } |
1642 | 1662 |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2187 expected_name ^= String::New("_offset"); | 2207 expected_name ^= String::New("_offset"); |
2188 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2208 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
2189 field ^= fields_array.At(2); | 2209 field ^= fields_array.At(2); |
2190 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2210 ASSERT(field.Offset() == TypedDataView::length_offset()); |
2191 name ^= field.name(); | 2211 name ^= field.name(); |
2192 ASSERT(name.Equals("length")); | 2212 ASSERT(name.Equals("length")); |
2193 #endif | 2213 #endif |
2194 } | 2214 } |
2195 | 2215 |
2196 } // namespace dart | 2216 } // namespace dart |
OLD | NEW |