| 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 |