Index: runtime/vm/class_finalizer.cc |
=================================================================== |
--- runtime/vm/class_finalizer.cc (revision 25531) |
+++ runtime/vm/class_finalizer.cc (working copy) |
@@ -282,6 +282,21 @@ |
} |
+ |
+void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, |
+ const Function& factory) { |
+ const Function& target = Function::Handle(factory.RedirectionTarget()); |
+ if (target.IsNull()) { |
+ const Type& type = Type::Handle(factory.RedirectionType()); |
+ if (!type.IsMalformed()) { |
+ const GrowableObjectArray& visited_factories = |
+ GrowableObjectArray::Handle(GrowableObjectArray::New()); |
+ ResolveRedirectingFactoryTarget(cls, factory, visited_factories); |
+ } |
+ } |
+} |
+ |
+ |
void ClassFinalizer::ResolveRedirectingFactoryTarget( |
const Class& cls, |
const Function& factory, |
@@ -385,7 +400,7 @@ |
return; |
} |
- // Verify that the target is const if the the redirecting factory is const. |
+ // Verify that the target is const if the redirecting factory is const. |
if (factory.is_const() && !target.is_const()) { |
const Script& script = Script::Handle(cls.script()); |
ReportError(script, factory.token_pos(), |
@@ -1159,11 +1174,8 @@ |
function_name.ToCString(), |
super_class_name.ToCString()); |
} |
- if (function.IsRedirectingFactory()) { |
- const GrowableObjectArray& redirecting_factories = |
- GrowableObjectArray::Handle(GrowableObjectArray::New()); |
- ResolveRedirectingFactoryTarget(cls, function, redirecting_factories); |
- } |
+ // The function may be a still unresolved redirecting factory. Do not yet |
+ // try to resolve it in order to avoid cycles in class finalization. |
} else { |
for (int i = 0; i < interfaces.Length(); i++) { |
super_class ^= interfaces.At(i); |
@@ -1505,7 +1517,7 @@ |
return; |
} |
if (FLAG_trace_class_finalization) { |
- OS::Print("Finalize %s\n", cls.ToCString()); |
+ OS::Print("Finalize types in %s\n", cls.ToCString()); |
} |
if (!IsSuperCycleFree(cls)) { |
const String& name = String::Handle(cls.Name()); |
@@ -1614,7 +1626,7 @@ |
} |
// Top level classes are parsed eagerly so just finalize it. |
if (cls.IsTopLevel()) { |
- ClassFinalizer::FinalizeClass(cls); |
+ FinalizeClass(cls); |
} |
} |
@@ -1624,12 +1636,20 @@ |
if (cls.is_finalized()) { |
return; |
} |
+ if (FLAG_trace_class_finalization) { |
+ OS::Print("Finalize %s\n", cls.ToCString()); |
+ } |
if (cls.mixin() != Type::null()) { |
// Copy instance methods and fields from the mixin class. |
// This has to happen before the check whether the methods of |
// the class conflict with inherited methods. |
ApplyMixin(cls); |
} |
+ // Ensure super class is finalized. |
+ const Class& super = Class::Handle(cls.SuperClass()); |
+ if (!super.IsNull()) { |
+ FinalizeClass(super); |
+ } |
// Mark as parsed and finalized. |
cls.Finalize(); |
// Resolve and finalize all member types. |