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

Unified Diff: runtime/vm/class_finalizer.cc

Issue 1584223006: Remove signature classes from the VM. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: sync Created 4 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/class_finalizer.cc
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index ace3016cc7194b7b6d850720f829ece352f0e8c6..184772653046a9864fa61350381d2103eb188b76 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -440,7 +440,8 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
if (!target_type.IsInstantiated()) {
const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
Error& bound_error = Error::Handle();
- target_type ^= target_type.InstantiateFrom(type_args, &bound_error);
+ target_type ^= target_type.InstantiateFrom(
+ type_args, &bound_error, NULL, Heap::kOld);
if (bound_error.IsNull()) {
target_type ^= FinalizeType(cls, target_type, kCanonicalize);
} else {
@@ -457,10 +458,10 @@ void ClassFinalizer::ResolveRedirectingFactoryTarget(
}
-void ClassFinalizer::ResolveTypeClass(const Class& cls,
- const AbstractType& type) {
- if (type.IsFinalized() || type.HasResolvedTypeClass()) {
- return;
+RawAbstractType* ClassFinalizer::ResolveTypeClass(const Class& cls,
+ const Type& type) {
+ if (type.IsFinalized()) {
+ return type.raw();
}
if (FLAG_trace_type_finalization) {
THR_Print("Resolve type class of '%s'\n",
@@ -473,55 +474,77 @@ void ClassFinalizer::ResolveTypeClass(const Class& cls,
// that the type parameter appeared in a static scope. Leaving the type as
// unresolved is the correct thing to do.
- // Lookup the type class.
- const UnresolvedClass& unresolved_class =
- UnresolvedClass::Handle(type.unresolved_class());
- const Class& type_class =
- Class::Handle(ResolveClass(cls, unresolved_class));
-
- // Replace unresolved class with resolved type class.
- const Type& parameterized_type = Type::Cast(type);
- if (type_class.IsNull()) {
- // The type class could not be resolved. The type is malformed.
- FinalizeMalformedType(
- Error::Handle(), // No previous error.
- Script::Handle(cls.script()),
- parameterized_type,
- "cannot resolve class '%s' from '%s'",
- String::Handle(unresolved_class.Name()).ToCString(),
- String::Handle(cls.Name()).ToCString());
- return;
+ // Lookup the type class if necessary.
+ Class& type_class = Class::Handle();
+ if (type.HasResolvedTypeClass()) {
+ type_class = type.type_class();
+ } else {
+ const UnresolvedClass& unresolved_class =
+ UnresolvedClass::Handle(type.unresolved_class());
+ type_class = ResolveClass(cls, unresolved_class);
+ if (type_class.IsNull()) {
+ // The type class could not be resolved. The type is malformed.
+ FinalizeMalformedType(
+ Error::Handle(), // No previous error.
+ Script::Handle(cls.script()),
+ type,
+ "cannot resolve class '%s' from '%s'",
+ String::Handle(unresolved_class.Name()).ToCString(),
+ String::Handle(cls.Name()).ToCString());
+ return type.raw();
+ }
+ }
+ // Promote the Type to a FunctionType in case its type class is a typedef.
+ if (type_class.IsTypedefClass()) {
+ return FunctionType::New(type_class,
+ TypeArguments::Handle(type.arguments()),
+ Function::Handle(type_class.signature_function()),
+ type.token_pos());
}
- parameterized_type.set_type_class(type_class);
+ // Replace unresolved class with resolved type class.
+ type.set_type_class(type_class);
+ return type.raw();
}
-void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
+RawAbstractType* ClassFinalizer::ResolveType(const Class& cls,
+ const AbstractType& type) {
if (type.IsResolved()) {
- return;
+ return type.raw();
}
- ASSERT(type.IsType());
if (FLAG_trace_type_finalization) {
THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
}
- ResolveTypeClass(cls, type);
- if (type.IsMalformed()) {
- ASSERT(type.IsResolved());
- return;
+ AbstractType& resolved_type = AbstractType::Handle();
+ if (type.IsType()) {
+ resolved_type = ResolveTypeClass(cls, Type::Cast(type));
+ if (resolved_type.IsMalformed()) {
+ ASSERT(resolved_type.IsResolved());
+ return resolved_type.raw();
+ }
+ } else {
+ ASSERT(type.IsFunctionType());
+ const Function& signature =
+ Function::Handle(FunctionType::Cast(type).signature());
+ ResolveSignature(cls, signature);
+ resolved_type = type.raw();
}
// Mark type as resolved before resolving its type arguments in order to avoid
// repeating resolution of recursive types.
- Type::Cast(type).set_is_resolved();
+ resolved_type.SetIsResolved();
// Resolve type arguments, if any.
- const TypeArguments& arguments = TypeArguments::Handle(type.arguments());
+ const TypeArguments& arguments =
+ TypeArguments::Handle(resolved_type.arguments());
if (!arguments.IsNull()) {
const intptr_t num_arguments = arguments.Length();
AbstractType& type_argument = AbstractType::Handle();
for (intptr_t i = 0; i < num_arguments; i++) {
type_argument = arguments.TypeAt(i);
- ResolveType(cls, type_argument);
+ type_argument = ResolveType(cls, type_argument);
+ arguments.SetTypeAt(i, type_argument);
}
}
+ return resolved_type.raw();
}
@@ -564,7 +587,7 @@ void ClassFinalizer::FinalizeTypeParameters(
// A non-contractive type can be detected by looking at the queue of types
// pending finalization that are mutually recursive with the checked type.
void ClassFinalizer::CheckRecursiveType(const Class& cls,
- const Type& type,
+ const AbstractType& type,
PendingTypes* pending_types) {
Zone* zone = Thread::Current()->zone();
if (FLAG_trace_type_finalization) {
@@ -620,6 +643,127 @@ void ClassFinalizer::CheckRecursiveType(const Class& cls,
}
+// Expand the type arguments of the given type and finalize its full type
+// argument vector. Return the number of type arguments (0 for a raw type).
+intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
+ const Class& cls,
+ const AbstractType& type,
+ PendingTypes* pending_types) {
+ Zone* Z = Thread::Current()->zone();
+ // 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, a precondition to calling FinalizeType).
+ // Also, the interfaces of the type class must be resolved and the type
+ // parameters of the type class must be finalized.
+ Class& type_class = Class::Handle(Z, type.type_class());
+ if (!type_class.is_type_finalized()) {
+ FinalizeTypeParameters(type_class, pending_types);
+ ResolveUpperBounds(type_class);
+ }
+
+ // The finalized type argument vector needs num_type_arguments types.
+ const intptr_t num_type_arguments = type_class.NumTypeArguments();
+ // The class has num_type_parameters type parameters.
+ const intptr_t num_type_parameters = type_class.NumTypeParameters();
+
+ // Initialize the type argument vector.
+ // Check the number of parsed type arguments, if any.
+ // Specifying no type arguments indicates a raw type, which is not an error.
+ // However, type parameter bounds are checked below, even for a raw type.
+ TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
+ if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
+ // Wrong number of type arguments. The type is mapped to the raw type.
+ if (Isolate::Current()->flags().error_on_bad_type()) {
+ const String& type_class_name = String::Handle(Z, type_class.Name());
+ ReportError(cls, type.token_pos(),
+ "wrong number of type arguments for class '%s'",
+ type_class_name.ToCString());
+ }
+ // Make the type raw and continue without reporting any error.
+ // A static warning should have been reported.
+ arguments = TypeArguments::null();
+ type.set_arguments(arguments);
+ }
+
+ // Mark the type as being finalized in order to detect self reference and
+ // postpone bound checking until after all types in the graph of
+ // mutually recursive types are finalized.
+ type.SetIsBeingFinalized();
+ pending_types->Add(type);
+
+ // The full type argument vector consists of the type arguments of the
+ // super types of type_class, which are initialized from the parsed
+ // type arguments, followed by the parsed type arguments.
+ TypeArguments& full_arguments = TypeArguments::Handle(Z);
+ if (num_type_arguments > 0) {
+ // If no type arguments were parsed and if the super types do not prepend
+ // type arguments to the vector, we can leave the vector as null.
+ if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
+ full_arguments = TypeArguments::New(num_type_arguments);
+ // Copy the parsed type arguments at the correct offset in the full type
+ // argument vector.
+ const intptr_t offset = num_type_arguments - num_type_parameters;
+ AbstractType& type_arg =
+ AbstractType::Handle(Z, Type::DynamicType());
+ // Leave the temporary type arguments at indices [0..offset[ as null.
+ for (intptr_t i = 0; i < num_type_parameters; i++) {
+ // If no type parameters were provided, a raw type is desired, so we
+ // create a vector of dynamic.
+ if (!arguments.IsNull()) {
+ type_arg = arguments.TypeAt(i);
+ // The parsed type_arg may or may not be finalized.
+ }
+ full_arguments.SetTypeAt(offset + i, type_arg);
+ }
+ // Replace the compile-time argument vector (of length zero or
+ // num_type_parameters) of this type being finalized with the still
+ // unfinalized run-time argument vector (of length num_type_arguments).
+ // This type being finalized may be recursively reached via bounds
+ // checking or type arguments of its super type.
+ type.set_arguments(full_arguments);
+ // Finalize the current type arguments of the type, which are still the
+ // parsed type arguments.
+ if (!arguments.IsNull()) {
+ for (intptr_t i = 0; i < num_type_parameters; i++) {
+ type_arg = full_arguments.TypeAt(offset + i);
+ ASSERT(!type_arg.IsBeingFinalized());
+ type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
+ if (type_arg.IsMalformed()) {
+ // Malformed type arguments are mapped to dynamic.
+ type_arg = Type::DynamicType();
+ }
+ full_arguments.SetTypeAt(offset + i, type_arg);
+ }
+ }
+ if (offset > 0) {
+ TrailPtr trail = new Trail(Z, 4);
+ Error& bound_error = Error::Handle();
+ FinalizeTypeArguments(type_class, full_arguments, offset,
+ &bound_error, pending_types, trail);
+ }
+ if (full_arguments.IsRaw(0, num_type_arguments)) {
+ // The parameterized_type is raw. Set its argument vector to null, which
+ // is more efficient in type tests.
+ full_arguments = TypeArguments::null();
+ }
+ type.set_arguments(full_arguments);
+ } else {
+ ASSERT(full_arguments.IsNull()); // Use null vector for raw type.
+ }
+ }
+
+ // Self referencing types may get finalized indirectly.
+ if (!type.IsFinalized()) {
+ ASSERT(full_arguments.IsNull() ||
+ !full_arguments.IsRaw(0, num_type_arguments));
+ // Mark the type as finalized.
+ type.SetIsFinalized();
+ // Do not yet remove the type from the pending_types array.
+ }
+ return full_arguments.IsNull() ? 0 : full_arguments.Length();
+}
+
+
// Finalize the type argument vector 'arguments' of the type defined by the
// class 'cls' parameterized with the type arguments 'cls_args'.
// The vector 'cls_args' is already initialized as a subvector at the correct
@@ -687,8 +831,8 @@ void ClassFinalizer::FinalizeTypeArguments(
super_type_arg = super_type_args.TypeAt(i);
if (!super_type_arg.IsTypeRef()) {
if (super_type_arg.IsBeingFinalized()) {
- ASSERT(super_type_arg.IsType());
- CheckRecursiveType(cls, Type::Cast(super_type_arg), pending_types);
+ ASSERT(super_type_arg.IsType() || super_type_arg.IsFunctionType());
+ CheckRecursiveType(cls, super_type_arg, pending_types);
if (FLAG_trace_type_finalization) {
THR_Print("Creating TypeRef '%s': '%s'\n",
String::Handle(super_type_arg.Name()).ToCString(),
@@ -737,7 +881,7 @@ void ClassFinalizer::FinalizeTypeArguments(
if (super_type_arg.IsTypeRef()) {
super_type_arg = TypeRef::Cast(super_type_arg).type();
}
- Type::Cast(super_type_arg).set_is_being_finalized();
+ Type::Cast(super_type_arg).SetIsBeingFinalized();
pending_types->Add(super_type_arg);
const Class& cls = Class::Handle(super_type_arg.type_class());
FinalizeTypeArguments(
@@ -844,9 +988,10 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
if (type_arg.IsTypeParameter()) {
const Class& type_arg_cls = Class::Handle(
TypeParameter::Cast(type_arg).parameterized_class());
- const AbstractType& bound = AbstractType::Handle(
+ AbstractType& bound = AbstractType::Handle(
TypeParameter::Cast(type_arg).bound());
- ResolveType(type_arg_cls, bound);
+ bound = ResolveType(type_arg_cls, bound);
+ TypeParameter::Cast(type_arg).set_bound(bound);
}
// This may be called only if type needs to be finalized, therefore
// seems OK to allocate finalized types in old space.
@@ -870,24 +1015,17 @@ void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
}
-void ClassFinalizer::CheckTypeBounds(const Class& cls, const Type& type) {
+void ClassFinalizer::CheckTypeBounds(const Class& cls,
+ const AbstractType& type) {
+ ASSERT(type.IsType() || type.IsFunctionType());
ASSERT(type.IsFinalized());
TypeArguments& arguments = TypeArguments::Handle(type.arguments());
if (arguments.IsNull()) {
return;
}
- Class& owner_class = Class::Handle();
- Class& type_class = Class::Handle(type.type_class());
- if (type_class.IsSignatureClass()) {
- const Function& signature_fun =
- Function::Handle(type_class.signature_function());
- ASSERT(!signature_fun.is_static());
- owner_class = signature_fun.Owner();
- } else {
- owner_class = type_class.raw();
- }
+ const Class& type_class = Class::Handle(type.type_class());
Error& bound_error = Error::Handle();
- CheckTypeArgumentBounds(owner_class, arguments, &bound_error);
+ CheckTypeArgumentBounds(type_class, arguments, &bound_error);
type.set_arguments(arguments);
// If a bound error occurred, mark the type as malbounded.
// The bound error will be ignored in production mode.
@@ -936,22 +1074,23 @@ RawAbstractType* ClassFinalizer::FinalizeType(
// encountered here.
ASSERT(!type.IsBeingFinalized());
+ Zone* Z = Thread::Current()->zone();
+ const AbstractType& resolved_type =
+ AbstractType::Handle(Z, ResolveType(cls, type));
// A malformed type gets mapped to a finalized type.
- ResolveType(cls, type);
- if (type.IsMalformed()) {
- ASSERT(type.IsFinalized());
- return type.raw();
+ if (resolved_type.IsMalformed()) {
+ ASSERT(resolved_type.IsFinalized());
+ return resolved_type.raw();
}
- Zone* Z = Thread::Current()->zone();
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type '%s' for class '%s'\n",
- String::Handle(Z, type.Name()).ToCString(),
+ String::Handle(Z, resolved_type.Name()).ToCString(),
cls.ToCString());
}
- if (type.IsTypeParameter()) {
- const TypeParameter& type_parameter = TypeParameter::Cast(type);
+ if (resolved_type.IsTypeParameter()) {
+ const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type);
const Class& parameterized_class =
Class::Handle(Z, type_parameter.parameterized_class());
ASSERT(!parameterized_class.IsNull());
@@ -966,7 +1105,7 @@ RawAbstractType* ClassFinalizer::FinalizeType(
// belongs to a mixin application class.
if (!type_parameter.IsFinalized()) {
type_parameter.set_index(type_parameter.index() + offset);
- type_parameter.set_is_finalized();
+ type_parameter.SetIsFinalized();
} else {
ASSERT(cls.IsMixinApplication());
}
@@ -981,8 +1120,8 @@ RawAbstractType* ClassFinalizer::FinalizeType(
return type_parameter.raw();
}
- // At this point, we can only have a parameterized_type.
- const Type& parameterized_type = Type::Cast(type);
+ // At this point, we can only have a Type or a FunctionType.
+ ASSERT(resolved_type.IsType() || resolved_type.IsFunctionType());
// This type is the root type of the type graph if no pending types queue is
// allocated yet.
@@ -991,197 +1130,93 @@ RawAbstractType* ClassFinalizer::FinalizeType(
pending_types = new PendingTypes(Z, 4);
}
- // 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, a precondition to calling FinalizeType).
- // Also, the interfaces of the type class must be resolved and the type
- // parameters of the type class must be finalized.
- Class& type_class = Class::Handle(Z, parameterized_type.type_class());
- if (!type_class.is_type_finalized()) {
- FinalizeTypeParameters(type_class, pending_types);
- ResolveUpperBounds(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.
- const intptr_t num_type_parameters = type_class.NumTypeParameters();
-
- // Initialize the type argument vector.
- // Check the number of parsed type arguments, if any.
- // Specifying no type arguments indicates a raw type, which is not an error.
- // However, type parameter bounds are checked below, even for a raw type.
- TypeArguments& arguments =
- TypeArguments::Handle(Z, parameterized_type.arguments());
- if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
- // Wrong number of type arguments. The type is mapped to the raw type.
- if (Isolate::Current()->flags().error_on_bad_type()) {
- const String& type_class_name =
- String::Handle(Z, type_class.Name());
- ReportError(cls, parameterized_type.token_pos(),
- "wrong number of type arguments for class '%s'",
- type_class_name.ToCString());
- }
- // Make the type raw and continue without reporting any error.
- // A static warning should have been reported.
- arguments = TypeArguments::null();
- parameterized_type.set_arguments(arguments);
- }
-
- // Mark the type as being finalized in order to detect self reference and
- // postpone bound checking until after all types in the graph of
- // mutually recursive types are finalized.
- parameterized_type.set_is_being_finalized();
- pending_types->Add(parameterized_type);
-
- // The full type argument vector consists of the type arguments of the
- // super types of type_class, which are initialized from the parsed
- // type arguments, followed by the parsed type arguments.
- TypeArguments& full_arguments = TypeArguments::Handle(Z);
- Error& bound_error = Error::Handle(Z);
- if (num_type_arguments > 0) {
- // If no type arguments were parsed and if the super types do not prepend
- // type arguments to the vector, we can leave the vector as null.
- if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
- full_arguments = TypeArguments::New(num_type_arguments);
- // Copy the parsed type arguments at the correct offset in the full type
- // argument vector.
- const intptr_t offset = num_type_arguments - num_type_parameters;
- AbstractType& type_arg =
- AbstractType::Handle(Z, Type::DynamicType());
- // Leave the temporary type arguments at indices [0..offset[ as null.
- for (intptr_t i = 0; i < num_type_parameters; i++) {
- // If no type parameters were provided, a raw type is desired, so we
- // create a vector of dynamic.
- if (!arguments.IsNull()) {
- type_arg = arguments.TypeAt(i);
- // The parsed type_arg may or may not be finalized.
- }
- full_arguments.SetTypeAt(offset + i, type_arg);
- }
- // Replace the compile-time argument vector (of length zero or
- // num_type_parameters) of this type being finalized with the still
- // unfinalized run-time argument vector (of length num_type_arguments).
- // This type being finalized may be recursively reached via bounds
- // checking or type arguments of its super type.
- parameterized_type.set_arguments(full_arguments);
- // Finalize the current type arguments of the type, which are still the
- // parsed type arguments.
- if (!arguments.IsNull()) {
- for (intptr_t i = 0; i < num_type_parameters; i++) {
- type_arg = full_arguments.TypeAt(offset + i);
- ASSERT(!type_arg.IsBeingFinalized());
- type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
- if (type_arg.IsMalformed()) {
- // Malformed type arguments are mapped to dynamic.
- type_arg = Type::DynamicType();
- }
- full_arguments.SetTypeAt(offset + i, type_arg);
- }
- }
- // If the type class is a signature class, the full argument vector
- // must include the argument vector of the super type.
- // If the signature class is a function type alias, it is also the owner
- // of its signature function and no super type is involved.
- // If the signature class is canonical (not an alias), the owner of its
- // signature function may either be an alias or the enclosing class of a
- // local function, in which case the super type of the enclosing class is
- // also considered when filling up the argument vector.
- Class& owner_class = Class::Handle(Z);
- if (type_class.IsSignatureClass()) {
- const Function& signature_fun =
- Function::Handle(Z, type_class.signature_function());
- ASSERT(!signature_fun.is_static());
- owner_class = signature_fun.Owner();
- } else {
- owner_class = type_class.raw();
- }
- if (offset > 0) {
- TrailPtr trail = new Trail(Z, 4);
- FinalizeTypeArguments(owner_class, full_arguments, offset,
- &bound_error, pending_types, trail);
- }
- if (full_arguments.IsRaw(0, num_type_arguments)) {
- // The parameterized_type is raw. Set its argument vector to null, which
- // is more efficient in type tests.
- full_arguments = TypeArguments::null();
- }
- parameterized_type.set_arguments(full_arguments);
- } else {
- ASSERT(full_arguments.IsNull()); // Use null vector for raw type.
- }
- }
-
- // Self referencing types may get finalized indirectly.
- if (!parameterized_type.IsFinalized()) {
- ASSERT(full_arguments.IsNull() ||
- !full_arguments.IsRaw(0, num_type_arguments));
- // Mark the type as finalized.
- parameterized_type.SetIsFinalized();
- // Do not yet remove the type from the pending_types array.
- }
+ const intptr_t num_expanded_type_arguments =
+ ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types);
// If we are done finalizing a graph of mutually recursive types, check their
// bounds.
if (is_root_type) {
for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
- CheckTypeBounds(cls, Type::Cast(pending_types->At(i)));
- if (FLAG_trace_type_finalization && type.IsRecursive()) {
+ CheckTypeBounds(cls, pending_types->At(i));
+ if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) {
THR_Print("Done finalizing recursive type '%s': %s\n",
- String::Handle(Z, type.Name()).ToCString(),
- type.ToCString());
+ String::Handle(Z, resolved_type.Name()).ToCString(),
+ resolved_type.ToCString());
}
}
}
- // If the type class is a signature class, we are currently finalizing a
- // signature type, i.e. finalizing the result type and parameter types of the
- // signature function of this signature type.
+ // If the type is a FunctionType, we also need to finalize the types in its
+ // signature, i.e. finalize the result type and parameter types of the
+ // signature function of this function type.
// We do this after marking this type as finalized in order to allow a
// function type to refer to itself via its parameter types and result type.
- if (type_class.IsSignatureClass()) {
- // The class may be created while parsing a function body, after all
- // pending classes have already been finalized.
- FinalizeTypesInClass(type_class);
+ // Note that we do not instantiate these types according to the type
+ // arguments. This will happen on demand when executing a type test.
+ if (resolved_type.IsFunctionType()) {
+ const Function& signature =
+ Function::Handle(Z, FunctionType::Cast(resolved_type).signature());
+ FinalizeSignature(cls, signature);
}
if (FLAG_trace_type_finalization) {
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
- String::Handle(Z, parameterized_type.Name()).ToCString(),
- parameterized_type.arguments() == TypeArguments::null() ?
- 0 : num_type_arguments,
- parameterized_type.ToCString());
+ String::Handle(Z, resolved_type.Name()).ToCString(),
+ num_expanded_type_arguments,
+ resolved_type.ToCString());
}
if (finalization >= kCanonicalize) {
- if (FLAG_trace_type_finalization && parameterized_type.IsRecursive()) {
- AbstractType& type = Type::Handle(Z);
- type = parameterized_type.Canonicalize();
+ if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) {
+ AbstractType& recursive_type =
+ AbstractType::Handle(Z, resolved_type.Canonicalize());
THR_Print("Done canonicalizing recursive type '%s': %s\n",
- String::Handle(Z, type.Name()).ToCString(),
- type.ToCString());
- return type.raw();
+ String::Handle(Z, recursive_type.Name()).ToCString(),
+ recursive_type.ToCString());
+ return recursive_type.raw();
}
- return parameterized_type.Canonicalize();
+ return resolved_type.Canonicalize();
} else {
- return parameterized_type.raw();
+ return resolved_type.raw();
}
}
-void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls,
- const Function& function) {
+void ClassFinalizer::ResolveSignature(const Class& cls,
+ const Function& function) {
// Resolve result type.
AbstractType& type = AbstractType::Handle(function.result_type());
// It is not a compile time error if this name does not resolve to a class or
// interface.
+ AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
+ if (resolved_type.raw() != type.raw()) {
+ function.set_result_type(resolved_type);
+ }
+ // Resolve formal parameter types.
+ const intptr_t num_parameters = function.NumParameters();
+ for (intptr_t i = 0; i < num_parameters; i++) {
+ type = function.ParameterTypeAt(i);
+ resolved_type = ResolveType(cls, type);
+ if (resolved_type.raw() != type.raw()) {
+ function.SetParameterTypeAt(i, resolved_type);
+ }
+ }
+}
+
+
+void ClassFinalizer::FinalizeSignature(const Class& cls,
+ const Function& function) {
+ // Finalize result type.
+ AbstractType& type = AbstractType::Handle(function.result_type());
+ // It is not a compile time error if this name does not resolve to a class or
+ // interface.
AbstractType& finalized_type =
AbstractType::Handle(FinalizeType(cls, type, kCanonicalize));
// The result type may be malformed or malbounded.
- if (type.raw() != finalized_type.raw()) {
+ if (finalized_type.raw() != type.raw()) {
function.set_result_type(finalized_type);
}
- // Resolve formal parameter types.
+ // Finalize formal parameter types.
const intptr_t num_parameters = function.NumParameters();
for (intptr_t i = 0; i < num_parameters; i++) {
type = function.ParameterTypeAt(i);
@@ -1255,7 +1290,8 @@ void ClassFinalizer::ResolveUpperBounds(const Class& cls) {
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
bound = type_param.bound();
- ResolveType(cls, bound);
+ bound = ResolveType(cls, bound);
+ type_param.set_bound(bound);
}
}
@@ -1445,7 +1481,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
Error& error = Error::Handle(Z);
for (intptr_t i = 0; i < num_functions; i++) {
function ^= array.At(i);
- ResolveAndFinalizeSignature(cls, function);
+ FinalizeSignature(cls, function);
name = function.name();
// Report signature conflicts only.
if (Isolate::Current()->flags().error_on_bad_override() &&
@@ -1718,8 +1754,8 @@ void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) {
FinalizeType(mixin_app_class, param_bound, kCanonicalize);
param.set_bound(param_bound); // In case part of recursive type.
}
- param_bound = param_bound.InstantiateFrom(instantiator,
- &bound_error);
+ param_bound = param_bound.InstantiateFrom(
+ instantiator, &bound_error, NULL, Heap::kOld);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
ASSERT(!param_bound.IsBoundedType());
@@ -1947,19 +1983,21 @@ void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class,
// the BoundedType in another BoundedType.
if (type.IsBoundedType()) {
bounded_type = BoundedType::Cast(type).type();
- bounded_type = bounded_type.InstantiateFrom(instantiator,
- &bound_error);
+ bounded_type = bounded_type.InstantiateFrom(
+ instantiator, &bound_error, NULL, Heap::kOld);
// The instantiator contains only TypeParameter objects and no
// BoundedType objects, so no bound error may occur.
ASSERT(bound_error.IsNull());
upper_bound = BoundedType::Cast(type).bound();
- upper_bound = upper_bound.InstantiateFrom(instantiator, &bound_error);
+ upper_bound = upper_bound.InstantiateFrom(
+ instantiator, &bound_error, NULL, Heap::kOld);
ASSERT(bound_error.IsNull());
type_parameter = BoundedType::Cast(type).type_parameter();
// The type parameter that declared the bound does not change.
type = BoundedType::New(bounded_type, upper_bound, type_parameter);
} else {
- type = type.InstantiateFrom(instantiator, &bound_error);
+ type = type.InstantiateFrom(
+ instantiator, &bound_error, NULL, Heap::kOld);
ASSERT(bound_error.IsNull());
}
}
@@ -2245,6 +2283,8 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
// Only resolving rather than finalizing the upper bounds here would result in
// instantiated type parameters of the super type to temporarily have
// unfinalized bounds. It is more efficient to finalize them early.
+ // Finalize bounds even if running in production mode, so that a snapshot
+ // contains them.
FinalizeUpperBounds(cls);
// Finalize super type.
AbstractType& super_type = AbstractType::Handle(cls.super_type());
@@ -2265,10 +2305,13 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
mixin_type ^= FinalizeType(cls, mixin_type, kCanonicalizeWellFormed);
cls.set_mixin(mixin_type);
}
- if (cls.IsSignatureClass()) {
+ if (cls.IsTypedefClass()) {
+ const Function& signature = Function::Handle(cls.signature_function());
+ FunctionType& type = FunctionType::Handle(signature.SignatureType());
+
// Check for illegal self references.
GrowableArray<intptr_t> visited_aliases;
- if (!IsAliasCycleFree(cls, &visited_aliases)) {
+ if (!IsTypedefCycleFree(cls, type, &visited_aliases)) {
const String& name = String::Handle(cls.Name());
ReportError(cls, cls.token_pos(),
"typedef '%s' illegally refers to itself",
@@ -2276,26 +2319,22 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
}
cls.set_is_type_finalized();
- // The type parameters of signature classes may have bounds.
- FinalizeUpperBounds(cls);
-
// Resolve and finalize the result and parameter types of the signature
- // function of this signature class.
- const Function& sig_function = Function::Handle(cls.signature_function());
- ResolveAndFinalizeSignature(cls, sig_function);
+ // function of this typedef class.
+ FinalizeSignature(cls, signature); // Does not modify signature type.
+ ASSERT(signature.SignatureType() == type.raw());
- // Resolve and finalize the signature type of this signature class.
- const Type& sig_type = Type::Handle(cls.SignatureType());
- FinalizeType(cls, sig_type, kCanonicalizeWellFormed);
+ // Resolve and finalize the signature type of this typedef.
+ type ^= FinalizeType(cls, type, kCanonicalizeWellFormed);
+ signature.SetSignatureType(type);
+
+ // Closure instances do not refer to this typedef as their class, so there
+ // is no need to add this typedef class to the subclasses of _Closure.
+ ASSERT(super_type.IsNull() || super_type.IsObjectType());
- // Add this class to the subclasses of the superclass (_FunctionImpl).
- if (!super_type.IsNull()) {
- ASSERT(!super_type.IsObjectType());
- ASSERT(!super_class.IsNull());
- super_class.AddDirectSubclass(cls);
- }
return;
}
+
// Finalize interface types (but not necessarily interface classes).
Array& interface_types = Array::Handle(cls.interfaces());
AbstractType& interface_type = AbstractType::Handle();
@@ -2332,9 +2371,6 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
// Mark as type finalized before resolving type parameter upper bounds
// in order to break cycles.
cls.set_is_type_finalized();
- // Finalize bounds even if running in production mode, so that a snapshot
- // contains them.
- FinalizeUpperBounds(cls);
// Add this class to the direct subclasses of the superclass, unless the
// superclass is Object.
if (!super_type.IsNull() && !super_type.IsObjectType()) {
@@ -2401,9 +2437,9 @@ void ClassFinalizer::FinalizeClass(const Class& cls) {
cls.SetFunctions(functions);
}
// Every class should have at least a constructor, unless it is a top level
- // class or a signature class.
+ // class or a typedef class.
ASSERT(cls.IsTopLevel() ||
- cls.IsSignatureClass() ||
+ cls.IsTypedefClass() ||
(Array::Handle(cls.functions()).Length() > 0));
// Resolve and finalize all member types.
ResolveAndFinalizeMemberTypes(cls);
@@ -2494,82 +2530,74 @@ bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
}
-// Helper function called by IsAliasCycleFree.
-bool ClassFinalizer::IsTypeCycleFree(
- const Class& cls,
- const AbstractType& type,
- GrowableArray<intptr_t>* visited) {
+// Returns false if a function type alias illegally refers to itself.
+bool ClassFinalizer::IsTypedefCycleFree(const Class& cls,
+ const AbstractType& type,
+ GrowableArray<intptr_t>* visited) {
ASSERT(visited != NULL);
- ResolveType(cls, type);
- if (type.IsType() && !type.IsMalformed()) {
- const Class& type_class = Class::Handle(type.type_class());
- if (!type_class.is_type_finalized() &&
- type_class.IsSignatureClass() &&
- !IsAliasCycleFree(type_class, visited)) {
- return false;
+ AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
+ bool checking_typedef = false;
+ if ((resolved_type.IsType() || resolved_type.IsFunctionType()) &&
+ !resolved_type.IsMalformed()) {
+ AbstractType& other_type = AbstractType::Handle();
+ if (resolved_type.IsFunctionType()) {
+ const Class& scope_class = Class::Handle(resolved_type.type_class());
+ if (!scope_class.is_type_finalized() && scope_class.IsTypedefClass()) {
+ checking_typedef = true;
+ const intptr_t scope_class_id = scope_class.id();
+ ASSERT(visited != NULL);
+ for (intptr_t i = 0; i < visited->length(); i++) {
+ if ((*visited)[i] == scope_class_id) {
+ // We have already visited alias 'scope_class'. We found a cycle.
+ return false;
+ }
+ }
+ visited->Add(scope_class_id);
+ }
+ // Check the bounds of this function type.
+ const intptr_t num_type_params = scope_class.NumTypeParameters();
+ TypeParameter& type_param = TypeParameter::Handle();
+ const TypeArguments& type_params =
+ TypeArguments::Handle(scope_class.type_parameters());
+ ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
+ (type_params.Length() == num_type_params));
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ other_type = type_param.bound();
+ if (!IsTypedefCycleFree(cls, other_type, visited)) {
+ return false;
+ }
+ }
+ // Check the result type of the signature of this function type.
+ const Function& function =
+ Function::Handle(FunctionType::Cast(resolved_type).signature());
+ other_type = function.result_type();
+ if (!IsTypedefCycleFree(cls, other_type, visited)) {
+ return false;
+ }
+ // Check the parameter types of the signature of this function type.
+ const intptr_t num_parameters = function.NumParameters();
+ for (intptr_t i = 0; i < num_parameters; i++) {
+ other_type = function.ParameterTypeAt(i);
+ if (!IsTypedefCycleFree(cls, other_type, visited)) {
+ return false;
+ }
+ }
}
- const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
+ const TypeArguments& type_args =
+ TypeArguments::Handle(resolved_type.arguments());
if (!type_args.IsNull()) {
- AbstractType& type_arg = AbstractType::Handle();
for (intptr_t i = 0; i < type_args.Length(); i++) {
- type_arg = type_args.TypeAt(i);
- if (!IsTypeCycleFree(cls, type_arg, visited)) {
+ other_type = type_args.TypeAt(i);
+ if (!IsTypedefCycleFree(cls, other_type, visited)) {
return false;
}
}
}
- }
- return true;
-}
-
-
-// Returns false if the function type alias illegally refers to itself.
-bool ClassFinalizer::IsAliasCycleFree(const Class& cls,
- GrowableArray<intptr_t>* visited) {
- ASSERT(cls.IsSignatureClass());
- ASSERT(!cls.is_type_finalized());
- ASSERT(visited != NULL);
- const intptr_t cls_index = cls.id();
- for (intptr_t i = 0; i < visited->length(); i++) {
- if ((*visited)[i] == cls_index) {
- // We have already visited alias 'cls'. We found a cycle.
- return false;
- }
- }
-
- // Visit the bounds, result type, and parameter types of this signature type.
- visited->Add(cls.id());
- AbstractType& type = AbstractType::Handle();
-
- // Check the bounds of this signature type.
- const intptr_t num_type_params = cls.NumTypeParameters();
- TypeParameter& type_param = TypeParameter::Handle();
- const TypeArguments& type_params =
- TypeArguments::Handle(cls.type_parameters());
- ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
- (type_params.Length() == num_type_params));
- for (intptr_t i = 0; i < num_type_params; i++) {
- type_param ^= type_params.TypeAt(i);
- type = type_param.bound();
- if (!IsTypeCycleFree(cls, type, visited)) {
- return false;
- }
- }
- // Check the result type of the function of this signature type.
- const Function& function = Function::Handle(cls.signature_function());
- type = function.result_type();
- if (!IsTypeCycleFree(cls, type, visited)) {
- return false;
- }
- // Check the formal parameter types of the function of this signature type.
- const intptr_t num_parameters = function.NumParameters();
- for (intptr_t i = 0; i < num_parameters; i++) {
- type = function.ParameterTypeAt(i);
- if (!IsTypeCycleFree(cls, type, visited)) {
- return false;
+ if (checking_typedef) {
+ visited->RemoveLast();
}
}
- visited->RemoveLast();
return true;
}
@@ -2657,7 +2685,7 @@ RawType* ClassFinalizer::ResolveMixinAppType(
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
AbstractType& mixin_super_type =
AbstractType::Handle(zone, mixin_app_type.super_type());
- ResolveType(cls, mixin_super_type);
+ mixin_super_type = ResolveType(cls, mixin_super_type);
ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed.
if (mixin_super_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, mixin_super_type.error()));
@@ -2681,7 +2709,7 @@ RawType* ClassFinalizer::ResolveMixinAppType(
for (intptr_t i = 0; i < depth; i++) {
mixin_type = mixin_app_type.MixinTypeAt(i);
ASSERT(!mixin_type.IsNull());
- ResolveType(cls, mixin_type);
+ mixin_type = ResolveType(cls, mixin_type);
ASSERT(mixin_type.HasResolvedTypeClass()); // Even if malformed.
ASSERT(mixin_type.IsType());
const intptr_t num_super_type_args = type_args.Length();
@@ -2842,7 +2870,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces(
Class& interface_class = Class::Handle(zone);
// Resolve super type. Failures lead to a longjmp.
- ResolveType(cls, super_type);
+ super_type = ResolveType(cls, super_type);
if (super_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, super_type.error()));
}
@@ -2852,7 +2880,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces(
String::Handle(zone, cls.Name()).ToCString());
}
interface_class = super_type.type_class();
- if (interface_class.IsSignatureClass()) {
+ if (interface_class.IsTypedefClass()) {
ReportError(cls, cls.token_pos(),
"class '%s' may not extend function type alias '%s'",
String::Handle(zone, cls.Name()).ToCString(),
@@ -2922,7 +2950,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces(
// Resolve interfaces. Failures lead to a longjmp.
for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
interface ^= super_interfaces.At(i);
- ResolveType(cls, interface);
+ interface = ResolveType(cls, interface);
ASSERT(!interface.IsTypeParameter()); // Should be detected by parser.
// A malbounded interface is only reported when involved in a type test.
if (interface.IsMalformed()) {
@@ -2933,7 +2961,7 @@ void ClassFinalizer::ResolveSuperTypeAndInterfaces(
"'dynamic' may not be used as interface");
}
interface_class = interface.type_class();
- if (interface_class.IsSignatureClass()) {
+ if (interface_class.IsTypedefClass()) {
const String& interface_name = String::Handle(zone,
interface_class.Name());
ReportError(cls, cls.token_pos(),
@@ -3069,7 +3097,7 @@ void ClassFinalizer::MarkTypeMalformed(const Error& prev_error,
type.set_arguments(Object::null_type_arguments());
if (!type.IsFinalized()) {
type.SetIsFinalized();
- // Do not canonicalize malformed types, since they may not be resolved.
+ // Do not canonicalize malformed types, since they contain an error field.
} else {
// The only case where the malformed type was already finalized is when its
// type arguments are not within bounds. In that case, we have a prev_error.
@@ -3111,7 +3139,7 @@ void ClassFinalizer::FinalizeMalformedType(const Error& prev_error,
void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error,
const Script& script,
- const Type& type,
+ const AbstractType& type,
const char* format, ...) {
va_list args;
va_start(args, format);
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698