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

Unified Diff: runtime/vm/class_finalizer.cc

Issue 8506001: Finalize all classes (fix issue 364). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/class_finalizer.cc
===================================================================
--- runtime/vm/class_finalizer.cc (revision 1336)
+++ runtime/vm/class_finalizer.cc (working copy)
@@ -18,8 +18,22 @@
"Verify that all classes implement their interface.");
DECLARE_FLAG(bool, enable_type_checks);
+void ClassFinalizer::ExpectPendingClasses() {
srdjan 2011/11/09 21:22:43 Do you want to allow ExpectPendingClasses several
regis 2011/11/09 23:31:01 Good question! Currently, there may be several cal
+ if (AllClassesFinalized()) {
+ ObjectStore* object_store = Isolate::Current()->object_store();
+ object_store->set_pending_classes(Array::Handle(Array::Empty()));
+ ASSERT(!AllClassesFinalized());
+ }
+}
+
+
void ClassFinalizer::AddPendingClasses(
const GrowableArray<const Class*>& classes) {
+ // ExpectPendingClasses() must be called prior to calling AddPendingClasses().
+ if (AllClassesFinalized()) { // TODO(regis): DEBUG.
+ ASSERT(false);
+ }
srdjan 2011/11/09 21:22:43 Why the code above?
regis 2011/11/09 23:31:01 Left over debugging code. Removed.
+ ASSERT(!AllClassesFinalized());
if (!classes.is_empty()) {
ObjectStore* object_store = Isolate::Current()->object_store();
const Array& old_array = Array::Handle(object_store->pending_classes());
@@ -38,7 +52,7 @@
bool ClassFinalizer::AllClassesFinalized() {
ObjectStore* object_store = Isolate::Current()->object_store();
const Array& classes = Array::Handle(object_store->pending_classes());
- return classes.Length() == 0;
+ return classes.IsNull();
}
@@ -59,10 +73,11 @@
isolate->set_long_jump_base(&jump);
if (setjmp(*jump.Set()) == 0) {
const Array& class_array = Array::Handle(object_store->pending_classes());
- ASSERT(!class_array.IsNull());
+ const intptr_t num_pending_classes =
+ class_array.IsNull() ? 0 : class_array.Length();
Class& cls = Class::Handle();
// First resolve all superclasses.
- for (intptr_t i = 0; i < class_array.Length(); i++) {
+ for (intptr_t i = 0; i < num_pending_classes; i++) {
cls ^= class_array.At(i);
if (FLAG_trace_class_finalization) {
OS::Print("Resolving super and default: %s\n", cls.ToCString());
@@ -73,18 +88,18 @@
}
}
// Finalize all classes.
- for (intptr_t i = 0; i < class_array.Length(); i++) {
+ for (intptr_t i = 0; i < num_pending_classes; i++) {
cls ^= class_array.At(i);
FinalizeClass(cls);
}
if (FLAG_print_classes) {
- for (intptr_t i = 0; i < class_array.Length(); i++) {
+ for (intptr_t i = 0; i < num_pending_classes; i++) {
cls ^= class_array.At(i);
PrintClassInformation(cls);
}
}
if (FLAG_verify_implements) {
- for (intptr_t i = 0; i < class_array.Length(); i++) {
+ for (intptr_t i = 0; i < num_pending_classes; i++) {
cls ^= class_array.At(i);
if (!cls.is_interface()) {
VerifyClassImplements(cls);
@@ -92,7 +107,8 @@
}
}
// Clear pending classes array.
- object_store->set_pending_classes(Array::Handle(Array::Empty()));
+ object_store->set_pending_classes(Array::Handle());
+ ASSERT(AllClassesFinalized());
// Check to ensure there are no duplicate definitions in the library
// hierarchy.
@@ -242,6 +258,38 @@
}
+// Resolve unresolved_class in the library of cls.
+RawClass* ClassFinalizer::ResolveClass(
+ const Class& cls, const UnresolvedClass& unresolved_class) {
+ Library& lib = Library::Handle();
+ if (unresolved_class.qualifier() == String::null()) {
+ lib = cls.library();
+ } else {
+ const String& qualifier = String::Handle(unresolved_class.qualifier());
+ LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
+ lib_prefix = cls.LookupLibraryPrefix(qualifier);
+ if (lib_prefix.IsNull()) {
+ const Script& script = Script::Handle(cls.script());
+ ReportError(script, unresolved_class.token_index(),
+ "cannot resolve name '%s'\n",
srdjan 2011/11/09 21:22:43 Maybe be more specific -> cannot resolve library p
regis 2011/11/09 23:31:01 Done.
+ String::Handle(unresolved_class.Name()).ToCString());
+ }
+ lib = lib_prefix.library();
+ }
+ ASSERT(!lib.IsNull());
+ const String& class_name = String::Handle(unresolved_class.ident());
+ const Class& resolved_class = Class::Handle(lib.LookupClass(class_name));
+ if (resolved_class.IsNull()) {
+ const Script& script = Script::Handle(cls.script());
+ ReportError(script, unresolved_class.token_index(),
+ "cannot resolve class name '%s' from '%s'\n",
+ String::Handle(unresolved_class.Name()).ToCString(),
+ String::Handle(cls.Name()).ToCString());
+ }
+ return resolved_class.raw();
+}
+
+
// Resolve unresolved superclasses (String -> Class).
void ClassFinalizer::ResolveSuperClass(const Class& cls) {
if (cls.is_finalized()) {
@@ -253,6 +301,13 @@
}
// Resolve failures lead to a longjmp.
super_type = ResolveType(cls, super_type);
+ if (super_type.IsTypeParameter()) {
+ String& class_name = String::Handle(cls.Name());
+ String& type_parameter_name = String::Handle(super_type.Name());
+ ReportError("'%s' cannot extend or implement type parameter '%s'.\n",
+ class_name.ToCString(),
+ type_parameter_name.ToCString());
+ }
cls.set_super_type(super_type);
const Class& super_class = Class::Handle(super_type.type_class());
if (cls.is_interface() != super_class.is_interface()) {
@@ -354,31 +409,9 @@
}
// Lookup the type class.
- Class& type_class = Class::Handle();
- Library& lib = Library::Handle();
- if (unresolved_class.qualifier() == String::null()) {
- lib = cls.library();
- } else {
- const String& qualifier = String::Handle(unresolved_class.qualifier());
- LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
- lib_prefix = cls.LookupLibraryPrefix(qualifier);
- if (lib_prefix.IsNull()) {
- const Script& script = Script::Handle(cls.script());
- ReportError(script, unresolved_class.token_index(),
- "cannot resolve name '%s'\n",
- String::Handle(unresolved_class.Name()).ToCString());
- }
- lib = lib_prefix.library();
- }
- ASSERT(!lib.IsNull());
- type_class = lib.LookupClass(type_class_name);
- if (type_class.IsNull()) {
- const Script& script = Script::Handle(cls.script());
- ReportError(script, unresolved_class.token_index(),
- "cannot resolve class name '%s' from '%s'\n",
- String::Handle(unresolved_class.Name()).ToCString(),
- String::Handle(cls.Name()).ToCString());
- }
+ const Class& type_class =
+ Class::Handle(ResolveClass(cls, unresolved_class));
+
// Replace unresolved class with resolved type class.
ASSERT(type.IsParameterizedType());
ParameterizedType& parameterized_type = ParameterizedType::Handle();
@@ -506,10 +539,18 @@
}
// The type class does not need to be finalized in order to finalize the type,
- // however, it must at least be resolved. This was done as part of resolving
- // the type itself.
+ // however, it must at least be resolved (this was done as part of resolving
+ // the type itself, a precondition to calling FinalizeType) and the upper
+ // bounds of its type parameters must be finalized (done here).
Class& type_class = Class::Handle(parameterized_type.type_class());
+ // If the type class is a signature class, finalize it, thereby finalizing the
+ // result and parameter types of its signature function.
+ // Do this before marking this type as finalized in order to detect cycles.
+ if (type_class.IsSignatureClass()) {
+ FinalizeClass(type_class);
+ }
+
// The finalized type argument vector needs num_type_arguments types.
const intptr_t num_type_arguments = type_class.NumTypeArguments();
// The type class has num_type_parameters type parameters.
@@ -545,14 +586,11 @@
FinalizeTypeArguments(type_class, full_arguments);
parameterized_type.set_arguments(full_arguments);
}
+ // Mark the type as finalized before finalizing the upper bounds, because
+ // cycles via upper bounds are legal at compile time.
+ parameterized_type.set_is_finalized();
+ ResolveAndFinalizeUpperBounds(type_class);
- // If the type is a function type, finalize the result and parameter types.
- if (type_class.IsSignatureClass()) {
- ResolveAndFinalizeSignature(
- type_class, Function::Handle(type_class.signature_function()));
- }
-
- parameterized_type.set_is_finalized();
return parameterized_type.Canonicalize();
}
@@ -565,7 +603,15 @@
LongJump jump;
isolate->set_long_jump_base(&jump);
if (setjmp(*jump.Set()) == 0) {
- const Type& canonical_type = Type::Handle(FinalizeType(type));
+ Type& canonical_type = Type::Handle();
+ if (type.IsSignatureType() && !AllClassesFinalized()) {
srdjan 2011/11/09 21:22:43 Maybe have a interim method: CollectingClassesToFi
regis 2011/11/09 23:31:01 Done. Renamed these calls to: ExpectClassesToFinal
+ // Postpone the finalization of this signature type and class.
+ GrowableArray<const Class*> classes;
+ classes.Add(&Class::ZoneHandle(type.type_class()));
+ ClassFinalizer::AddPendingClasses(classes);
+ } else {
+ canonical_type = FinalizeType(type);
+ }
isolate->set_long_jump_base(base);
*errmsg = String::null();
return canonical_type.raw();
@@ -580,11 +626,6 @@
}
-// Top level function signatures are canonicalized, added to the library class
-// dictionary, and finalized with other library classes and interfaces.
-// Function signatures used as type of a local variable or of a local function
-// are canonicalized and finalized upon creation, since all the types they
-// reference are already resolved.
void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls,
const Function& function) {
// Resolve result type.
@@ -644,6 +685,23 @@
}
+void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) {
+ const intptr_t num_type_params = cls.NumTypeParameters();
+ Type& type_extends = Type::Handle();
+ const TypeArguments& extends_array =
+ TypeArguments::Handle(cls.type_parameter_extends());
+ ASSERT((extends_array.IsNull() && (num_type_params == 0)) ||
+ (extends_array.Length() == num_type_params));
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_extends = extends_array.TypeAt(i);
+ type_extends = ResolveType(cls, type_extends);
+ extends_array.SetTypeAt(i, type_extends);
+ type_extends = FinalizeType(type_extends);
+ extends_array.SetTypeAt(i, type_extends);
+ }
+}
+
+
void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
// 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
@@ -777,13 +835,6 @@
}
}
}
- // Resolve the signature type if this class is a signature class.
- if (cls.IsSignatureClass()) {
- Type& signature_type = Type::Handle(cls.SignatureType());
- signature_type = FinalizeType(signature_type);
- // Signature types are canonicalized by default.
- ASSERT(signature_type.raw() == cls.SignatureType());
- }
}
@@ -833,9 +884,25 @@
interface_type = FinalizeType(interface_type);
interface_types.SetAt(i, interface_type);
}
- // Mark as finalized before resolving member types in order to break cycles.
+ // Mark as finalized before resolving type parameter upper bounds and member
+ // types in order to break cycles.
cls.Finalize();
+ ResolveAndFinalizeUpperBounds(cls);
ResolveAndFinalizeMemberTypes(cls);
+
+ if (cls.IsSignatureClass()) {
+ // Finalize the signature type of this signature class.
+ Type& signature_type = Type::Handle(cls.SignatureType());
+ signature_type = FinalizeType(signature_type);
+ // Signature types are canonicalized by default.
+ ASSERT(signature_type.raw() == cls.SignatureType());
+
+ // Resolve and finalize the result and parameter types of the signature
+ // function of this signature class.
+ ResolveAndFinalizeSignature(cls,
+ Function::Handle(cls.signature_function()));
+ }
+
// Run additional checks after all types are finalized.
if (cls.is_const()) {
CheckForLegalConstClass(cls);
@@ -964,8 +1031,6 @@
String::Handle(cls.Name()).ToCString(),
String::Handle(interface_class.Name()).ToCString());
}
- // TODO(regis): We also need to prevent extending classes Smi, Mint,
- // BigInt, Double, OneByteString, TwoByteString, FourByteString.
}
// Now resolve the super interfaces.
ResolveInterfaces(interface_class, visited);

Powered by Google App Engine
This is Rietveld 408576698