Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: runtime/vm/class_finalizer.cc

Issue 20503003: Delay resolution of redirecting factory targets in order to avoid class (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698