Index: runtime/vm/class_finalizer.cc |
=================================================================== |
--- runtime/vm/class_finalizer.cc (revision 11113) |
+++ runtime/vm/class_finalizer.cc (working copy) |
@@ -17,8 +17,6 @@ |
DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
-DEFINE_FLAG(bool, verify_implements, false, |
- "Verify that all classes implement their interface."); |
DECLARE_FLAG(bool, enable_type_checks); |
@@ -30,10 +28,16 @@ |
} |
+bool ClassFinalizer::FinalizeAllClasses() { |
+ ClassFinalizer class_finalizer(kNotGeneratingSnapshot); |
+ return class_finalizer.FinalizePendingClasses(); |
+} |
+ |
+ |
// Class finalization occurs: |
// a) when bootstrap process completes (VerifyBootstrapClasses). |
// b) after the user classes are loaded (dart_api). |
-bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) { |
+bool ClassFinalizer::FinalizePendingClasses() const { |
bool retval = true; |
Isolate* isolate = Isolate::Current(); |
ASSERT(isolate != NULL); |
@@ -64,7 +68,7 @@ |
// Finalize all classes. |
for (intptr_t i = 0; i < class_array.Length(); i++) { |
cls ^= class_array.At(i); |
- FinalizeClass(cls, generating_snapshot); |
+ FinalizeClass(cls); |
} |
if (FLAG_print_classes) { |
for (intptr_t i = 0; i < class_array.Length(); i++) { |
@@ -72,14 +76,6 @@ |
PrintClassInformation(cls); |
} |
} |
- if (FLAG_verify_implements) { |
- for (intptr_t i = 0; i < class_array.Length(); i++) { |
- cls ^= class_array.At(i); |
- if (!cls.is_interface()) { |
- VerifyClassImplements(cls); |
- } |
- } |
- } |
// Clear pending classes array. |
class_array = GrowableObjectArray::New(); |
object_store->set_pending_classes(class_array); |
@@ -107,78 +103,6 @@ |
} |
-#if defined (DEBUG) |
-// Collect all interfaces of the class 'cls' and check that every function |
-// defined in each interface can be found in the class. |
-// No need to check instance fields since they have been turned into |
-// getters/setters. |
-void ClassFinalizer::VerifyClassImplements(const Class& cls) { |
- ASSERT(!cls.is_interface()); |
- const GrowableObjectArray& interfaces = |
- GrowableObjectArray::Handle(GrowableObjectArray::New()); |
- CollectInterfaces(cls, interfaces); |
- const String& class_name = String::Handle(cls.Name()); |
- Class& interface_class = Class::Handle(); |
- String& interface_name = String::Handle(); |
- Array& interface_functions = Array::Handle(); |
- for (int i = 0; i < interfaces.Length(); i++) { |
- interface_class ^= interfaces.At(i); |
- interface_name = interface_class.Name(); |
- interface_functions = interface_class.functions(); |
- for (intptr_t f = 0; f < interface_functions.Length(); f++) { |
- Function& interface_function = Function::Handle(); |
- interface_function ^= interface_functions.At(f); |
- const String& function_name = String::Handle(interface_function.name()); |
- // Check for constructor/factory. |
- if (function_name.StartsWith(interface_name)) { |
- // TODO(srdjan): convert 'InterfaceName.' to 'ClassName.' and check. |
- continue; |
- } |
- if (interface_function.kind() == RawFunction::kConstImplicitGetter) { |
- // This interface constants are not overridable. |
- continue; |
- } |
- // Lookup function in 'cls' and all its super classes. |
- Class& test_class = Class::Handle(cls.raw()); |
- Function& class_function = |
- Function::Handle(test_class.LookupDynamicFunction(function_name)); |
- while (class_function.IsNull()) { |
- test_class = test_class.SuperClass(); |
- if (test_class.IsNull()) break; |
- class_function = test_class.LookupDynamicFunction(function_name); |
- } |
- if (class_function.IsNull()) { |
- OS::PrintErr("%s implements '%s' missing: '%s'\n", |
- class_name.ToCString(), |
- interface_name.ToCString(), |
- function_name.ToCString()); |
- } else { |
- Error& malformed_error = Error::Handle(); |
- if (!class_function.IsSubtypeOf(TypeArguments::Handle(), |
- interface_function, |
- TypeArguments::Handle(), |
- &malformed_error)) { |
- if (!malformed_error.IsNull()) { |
- OS::PrintErr("%s\n", malformed_error.ToErrorCString()); |
- } |
- OS::PrintErr("The type of instance method '%s' in class '%s' is not " |
- "a subtype of the type of '%s' in interface '%s'\n", |
- function_name.ToCString(), |
- class_name.ToCString(), |
- function_name.ToCString(), |
- interface_name.ToCString()); |
- } |
- } |
- } |
- } |
-} |
-#else |
- |
-void ClassFinalizer::VerifyClassImplements(const Class& cls) {} |
- |
-#endif |
- |
- |
void ClassFinalizer::VerifyBootstrapClasses() { |
if (FLAG_trace_class_finalization) { |
OS::Print("VerifyBootstrapClasses START.\n"); |
@@ -273,7 +197,8 @@ |
} |
// Finalize classes that aren't pre-finalized by Object::Init(). |
- if (!FinalizePendingClasses()) { |
+ ClassFinalizer class_finalizer(kGeneratingSnapshot); |
+ if (!class_finalizer.FinalizePendingClasses()) { |
// TODO(srdjan): Exit like a real VM instead. |
const Error& err = Error::Handle(object_store->sticky_error()); |
OS::PrintErr("Could not verify bootstrap classes : %s\n", |
@@ -308,7 +233,7 @@ |
// Resolve unresolved supertype (String -> Class). |
-void ClassFinalizer::ResolveSuperType(const Class& cls) { |
+void ClassFinalizer::ResolveSuperType(const Class& cls) const { |
if (cls.is_finalized()) { |
return; |
} |
@@ -467,7 +392,7 @@ |
void ClassFinalizer::ResolveType(const Class& cls, |
const AbstractType& type, |
- FinalizationKind finalization) { |
+ FinalizationKind finalization) const { |
if (type.IsResolved() || type.IsFinalized()) { |
return; |
} |
@@ -518,7 +443,7 @@ |
} |
-void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { |
+void ClassFinalizer::FinalizeTypeParameters(const Class& cls) const { |
const TypeArguments& type_parameters = |
TypeArguments::Handle(cls.type_parameters()); |
if (!type_parameters.IsNull()) { |
@@ -552,7 +477,7 @@ |
void ClassFinalizer::FinalizeTypeArguments( |
const Class& cls, |
const AbstractTypeArguments& arguments, |
- FinalizationKind finalization) { |
+ FinalizationKind finalization) const { |
ASSERT(arguments.Length() >= cls.NumTypeArguments()); |
if (!cls.is_finalized()) { |
GrowableArray<intptr_t> visited_interfaces; |
@@ -606,9 +531,10 @@ |
} |
-RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, |
- const AbstractType& type, |
- FinalizationKind finalization) { |
+RawAbstractType* ClassFinalizer::FinalizeType( |
+ const Class& cls, |
+ const AbstractType& type, |
+ FinalizationKind finalization) const { |
if (type.IsFinalized()) { |
return type.raw(); |
} |
@@ -678,7 +604,7 @@ |
if (type_argument.IsMalformed()) { |
// In production mode, malformed type arguments are mapped to Dynamic. |
// In checked mode, a type with malformed type arguments is malformed. |
- if (FLAG_enable_type_checks) { |
+ if (FLAG_enable_type_checks || generating_snapshot_) { |
const Error& error = Error::Handle(type_argument.malformed_error()); |
const String& type_name = |
String::Handle(parameterized_type.UserVisibleName()); |
@@ -813,7 +739,7 @@ |
} else { |
// This type is a function type alias. Its class may need to be finalized |
// and checked for illegal self reference. |
- FinalizeClass(type_class, false); |
+ FinalizeClass(type_class); |
// Finalizing the signature function here (as in the canonical case above) |
// would not mark the canonical signature type as finalized. |
const Type& signature_type = Type::Handle(type_class.SignatureType()); |
@@ -829,8 +755,9 @@ |
} |
-void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, |
- const Function& function) { |
+void ClassFinalizer::ResolveAndFinalizeSignature( |
+ const Class& cls, |
+ const Function& function) const { |
// Resolve result type. |
AbstractType& type = AbstractType::Handle(function.result_type()); |
// In case of a factory, the parser sets the factory result type to a type |
@@ -899,7 +826,7 @@ |
// Resolve and finalize the upper bounds of the type parameters of class cls. |
-void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) { |
+void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) const { |
const intptr_t num_type_params = cls.NumTypeParameters(); |
TypeParameter& type_param = TypeParameter::Handle(); |
AbstractType& bound = AbstractType::Handle(); |
@@ -920,7 +847,7 @@ |
} |
-void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
+void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) const { |
// Note that getters and setters are explicitly listed as such in the list of |
// functions of a class, so we do not need to consider fields as implicitly |
// generating getters and setters. |
@@ -1079,7 +1006,7 @@ |
} |
-void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { |
+void ClassFinalizer::FinalizeClass(const Class& cls) const { |
if (cls.is_finalized()) { |
return; |
} |
@@ -1098,7 +1025,7 @@ |
// Finalize super class. |
const Class& super_class = Class::Handle(cls.SuperClass()); |
if (!super_class.IsNull()) { |
- FinalizeClass(super_class, generating_snapshot); |
+ FinalizeClass(super_class); |
} |
// Finalize type parameters before finalizing the super type. |
FinalizeTypeParameters(cls); |
@@ -1132,7 +1059,7 @@ |
if (cls.HasFactoryClass()) { |
const Class& factory_class = Class::Handle(cls.FactoryClass()); |
if (!factory_class.is_finalized()) { |
- FinalizeClass(factory_class, generating_snapshot); |
+ FinalizeClass(factory_class); |
// Finalizing the factory class may indirectly finalize this interface. |
if (cls.is_finalized()) { |
return; |
@@ -1159,7 +1086,7 @@ |
} |
// Check to ensure we don't have classes with native fields in libraries |
// which do not have a native resolver. |
- if (!generating_snapshot && cls.num_native_fields() != 0) { |
+ if (!generating_snapshot_ && cls.num_native_fields() != 0) { |
const Library& lib = Library::Handle(cls.library()); |
if (lib.native_entry_resolver() == NULL) { |
const String& cls_name = String::Handle(cls.Name()); |
@@ -1204,7 +1131,7 @@ |
// Returns false if the function type alias illegally refers to itself. |
bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
- GrowableArray<intptr_t>* visited) { |
+ GrowableArray<intptr_t>* visited) const { |
ASSERT(cls.IsSignatureClass()); |
ASSERT(!cls.IsCanonicalSignatureClass()); |
ASSERT(!cls.is_finalized()); |
@@ -1254,36 +1181,6 @@ |
} |
-bool ClassFinalizer::AddInterfaceIfUnique( |
- const GrowableObjectArray& interface_list, |
- const AbstractType& interface, |
- AbstractType* conflicting) { |
- String& interface_class_name = String::Handle(interface.ClassName()); |
- String& existing_interface_class_name = String::Handle(); |
- String& interface_name = String::Handle(); |
- String& existing_interface_name = String::Handle(); |
- AbstractType& other_interface = AbstractType::Handle(); |
- for (intptr_t i = 0; i < interface_list.Length(); i++) { |
- other_interface ^= interface_list.At(i); |
- existing_interface_class_name = other_interface.ClassName(); |
- if (interface_class_name.Equals(existing_interface_class_name)) { |
- // Same interface class name, now check names of type arguments. |
- interface_name = interface.Name(); |
- existing_interface_name = other_interface.Name(); |
- // TODO(regis): Revisit depending on the outcome of issue 4905685. |
- if (!interface_name.Equals(existing_interface_name)) { |
- *conflicting = other_interface.raw(); |
- return false; |
- } else { |
- return true; |
- } |
- } |
- } |
- interface_list.Add(interface); |
- return true; |
-} |
- |
- |
// Walks the graph of explicitly declared interfaces of classes and |
// interfaces recursively. Resolves unresolved interfaces. |
// Returns false if there is an interface reference that cannot be |
@@ -1292,7 +1189,7 @@ |
// graph. If we visit an interface a second time on a given path, |
// we found a loop. |
void ClassFinalizer::ResolveInterfaces(const Class& cls, |
- GrowableArray<intptr_t>* visited) { |
+ GrowableArray<intptr_t>* visited) const { |
ASSERT(visited != NULL); |
const intptr_t cls_index = cls.id(); |
for (int i = 0; i < visited->length(); i++) { |
@@ -1448,13 +1345,14 @@ |
const Class& cls, |
const Type& type, |
FinalizationKind finalization, |
- const char* format, ...) { |
+ const char* format, ...) const { |
va_list args; |
va_start(args, format); |
LanguageError& error = LanguageError::Handle(); |
if (FLAG_enable_type_checks || |
!type.HasResolvedTypeClass() || |
- (finalization == kCanonicalizeWellFormed)) { |
+ (finalization == kCanonicalizeWellFormed) || |
+ generating_snapshot_) { |
const Script& script = Script::Handle(cls.script()); |
if (prev_error.IsNull()) { |
error ^= Parser::FormatError( |
@@ -1463,7 +1361,7 @@ |
error ^= Parser::FormatErrorWithAppend( |
prev_error, script, type.token_pos(), "Error", format, args); |
} |
- if (finalization == kCanonicalizeWellFormed) { |
+ if ((finalization == kCanonicalizeWellFormed) || generating_snapshot_) { |
ReportError(error); |
} |
} |