Index: runtime/vm/object.cc |
=================================================================== |
--- runtime/vm/object.cc (revision 478) |
+++ runtime/vm/object.cc (working copy) |
@@ -696,6 +696,39 @@ |
} |
+RawType* Class::SignatureType() const { |
+ // Return the cached signature type if any. |
+ if (raw_ptr()->signature_type_ != Type::null()) { |
+ return raw_ptr()->signature_type_; |
+ } |
+ ASSERT(IsSignatureClass()); |
+ TypeArguments& signature_type_arguments = TypeArguments::Handle(); |
+ const intptr_t num_type_params = NumTypeParameters(); |
+ // If the signature class extends a parameterized class, the type arguments of |
+ // the super class will be prepended to the type argument vector during type |
+ // finalization. We only need to provide the type parameters of the signature |
+ // class here. |
+ if (num_type_params > 0) { |
+ const Array& type_params = Array::Handle(type_parameters()); |
+ signature_type_arguments = TypeArguments::NewTypeArray(num_type_params); |
+ String& type_param_name = String::Handle(); |
+ Type& type_param = Type::Handle(); |
+ for (int i = 0; i < num_type_params; i++) { |
+ type_param_name ^= type_params.At(i); |
+ type_param = Type::NewTypeParameter(i, type_param_name); |
+ signature_type_arguments.SetTypeAt(i, type_param); |
+ } |
+ } |
+ const ParameterizedType& signature_type = ParameterizedType::Handle( |
+ ParameterizedType::New(*this, signature_type_arguments)); |
+ |
+ // Cache and return the still unfinalized signature type. |
+ ASSERT(!signature_type.IsFinalized()); |
+ set_signature_type(signature_type); |
+ return signature_type.raw(); |
+} |
+ |
+ |
template <class FakeObject> |
RawClass* Class::New() { |
Class& class_class = Class::Handle(Object::class_class()); |
@@ -766,6 +799,11 @@ |
} |
+void Class::set_signature_type(const Type& value) const { |
+ StorePointer(&raw_ptr()->signature_type_, value.raw()); |
+} |
+ |
+ |
void Class::set_class_state(int8_t state) const { |
ASSERT(state == RawClass::kAllocated || |
state == RawClass::kPreFinalized || |
@@ -802,7 +840,8 @@ |
intptr_t Class::NumTypeArguments() const { |
intptr_t num_type_args = NumTypeParameters(); |
const Class& superclass = Class::Handle(SuperClass()); |
- if (!superclass.IsNull()) { |
+ // Object is its own super class during bootstrap. |
+ if (!superclass.IsNull() && (superclass.raw() != raw())) { |
num_type_args += superclass.NumTypeArguments(); |
} |
return num_type_args; |
@@ -977,19 +1016,21 @@ |
intptr_t token_index) { |
ASSERT(!signature_function.IsNull()); |
Type& super_type = Type::Handle(Type::ObjectType()); |
+ const Class& owner_class = Class::Handle(signature_function.owner()); |
+ ASSERT(!owner_class.IsNull()); |
Array& type_parameters = Array::Handle(); |
TypeArray& type_parameter_extends = TypeArray::Handle(); |
if (!signature_function.is_static()) { |
- const Class& owner_class = Class::Handle(signature_function.owner()); |
- ASSERT(!owner_class.IsNull()); |
- ASSERT(!owner_class.is_interface()); |
- if (owner_class.IsParameterized()) { |
+ if (owner_class.IsParameterized() && |
+ !signature_function.HasInstantiatedSignature()) { |
// Share the function owner super class as the super class of the |
// signature class, so that the type argument vector of the closure at |
// run time matches the type argument vector of the closure instantiator. |
type_parameters = owner_class.type_parameters(); |
type_parameter_extends = owner_class.type_parameter_extends(); |
- super_type = owner_class.super_type(); |
+ if (!owner_class.is_interface()) { |
+ super_type = owner_class.super_type(); |
+ } |
} |
} |
Class& result = Class::Handle(New<Closure>(name, script)); |
@@ -1586,6 +1627,13 @@ |
} |
+bool Type::IsBeingFinalized() const { |
+ // Type is an abstract class. |
+ UNREACHABLE(); |
+ return false; |
+} |
+ |
+ |
RawType* Type::InstantiateFrom( |
const TypeArguments& instantiator_type_arguments, |
intptr_t offset) const { |
@@ -1606,12 +1654,23 @@ |
class_name = cls.Name(); |
num_type_params = cls.NumTypeParameters(); // Do not print the full vector. |
if (num_type_params > num_args) { |
- ASSERT(!IsFinalized()); |
+ ASSERT(num_args == 0); // Type is raw. |
// We fill up with "var". |
first_type_param_index = 0; |
} else { |
first_type_param_index = num_args - num_type_params; |
} |
+ if (cls.IsSignatureClass()) { |
+ const Function& signature_function = Function::Handle( |
+ cls.signature_function()); |
+ // We may be reporting an error about an illformed function type. In that |
+ // case, avoid instantiating the signature, since it may lead to cycles. |
+ if (IsBeingFinalized()) { |
+ return class_name.raw(); |
+ } |
+ return signature_function.InstantiatedSignatureFrom( |
+ args, first_type_param_index); |
+ } |
} else { |
const UnresolvedClass& type = UnresolvedClass::Handle(unresolved_class()); |
class_name = type.Name(); |
@@ -1645,7 +1704,7 @@ |
ASSERT(s == num_strings); |
type_name = String::ConcatAll(strings); |
} |
- // The name is only used for naming function types and for debugging purposes. |
+ // The name is only used for type checking and debugging purposes. |
// Unless profiling data shows otherwise, it is not worth caching the name in |
// the type. |
return String::NewSymbol(type_name); |
@@ -1842,7 +1901,7 @@ |
void ParameterizedType::set_is_being_finalized() const { |
- ASSERT(!IsFinalized() && !is_being_finalized()); |
+ ASSERT(!IsFinalized() && !IsBeingFinalized()); |
set_type_state(RawParameterizedType::kBeingFinalized); |
} |
@@ -1901,8 +1960,11 @@ |
type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments, |
offset); |
} |
+ const Class& cls = Class::Handle(type_class()); |
ParameterizedType& instantiated_type = ParameterizedType::Handle( |
- ParameterizedType::New(Object::Handle(type_class()), type_arguments)); |
+ ParameterizedType::New(cls, type_arguments)); |
+ ASSERT(type_arguments.IsNull() || |
+ (type_arguments.Length() == cls.NumTypeArguments())); |
instantiated_type.set_is_finalized(); |
return instantiated_type.raw(); |
} |
@@ -2910,21 +2972,21 @@ |
} |
-// Build a string of the form '<T>(A, [b: B, c: C]) => R)' representing the |
-// signature of the given function. |
-RawString* Function::Signature() const { |
+RawString* Function::BuildSignature(bool instantiate, |
+ const TypeArguments& instantiator, |
+ intptr_t offset) const { |
GrowableArray<const String*> pieces; |
- const String& kSpaceExtendsSpace = |
- String::Handle(String::NewSymbol(" extends ")); |
const String& kCommaSpace = String::Handle(String::NewSymbol(", ")); |
const String& kColonSpace = String::Handle(String::NewSymbol(": ")); |
- const String& kLAngleBracket = String::Handle(String::NewSymbol("<")); |
- const String& kRAngleBracket = String::Handle(String::NewSymbol(">")); |
const String& kLParen = String::Handle(String::NewSymbol("(")); |
const String& kRParen = String::Handle(String::NewSymbol(") => ")); |
const String& kLBracket = String::Handle(String::NewSymbol("[")); |
const String& kRBracket = String::Handle(String::NewSymbol("]")); |
- if (!is_static()) { |
+ if (!instantiate && !is_static()) { |
+ const String& kSpaceExtendsSpace = |
+ String::Handle(String::NewSymbol(" extends ")); |
+ const String& kLAngleBracket = String::Handle(String::NewSymbol("<")); |
+ const String& kRAngleBracket = String::Handle(String::NewSymbol(">")); |
const Class& function_class = Class::Handle(owner()); |
ASSERT(!function_class.IsNull()); |
const Array& type_parameters = Array::Handle( |
@@ -2960,6 +3022,9 @@ |
for (intptr_t i = 0; i < num_fixed_params; i++) { |
param_type = ParameterTypeAt(i); |
ASSERT(!param_type.IsNull()); |
+ if (instantiate && !param_type.IsInstantiated()) { |
+ param_type = param_type.InstantiateFrom(instantiator, offset); |
+ } |
pieces.Add(&String::ZoneHandle(param_type.Name())); |
if (i != (num_params - 1)) { |
pieces.Add(&kCommaSpace); |
@@ -2971,6 +3036,9 @@ |
pieces.Add(&String::ZoneHandle(ParameterNameAt(i))); |
pieces.Add(&kColonSpace); |
param_type = ParameterTypeAt(i); |
+ if (instantiate && !param_type.IsInstantiated()) { |
+ param_type = param_type.InstantiateFrom(instantiator, offset); |
+ } |
ASSERT(!param_type.IsNull()); |
pieces.Add(&String::ZoneHandle(param_type.Name())); |
if (i != (num_params - 1)) { |
@@ -2980,13 +3048,32 @@ |
pieces.Add(&kRBracket); |
} |
pieces.Add(&kRParen); |
- const Type& res_type = Type::Handle(result_type()); |
+ Type& res_type = Type::Handle(result_type()); |
+ if (instantiate && !res_type.IsInstantiated()) { |
+ res_type = res_type.InstantiateFrom(instantiator, offset); |
+ } |
pieces.Add(&String::Handle(res_type.Name())); |
const Array& strings = Array::Handle(NewArray<const String>(pieces)); |
return String::NewSymbol(String::Handle(String::ConcatAll(strings))); |
} |
+bool Function::HasInstantiatedSignature() const { |
+ Type& type = Type::Handle(result_type()); |
+ if (!type.IsInstantiated()) { |
+ return false; |
+ } |
+ const intptr_t num_parameters = NumberOfParameters(); |
+ for (intptr_t i = 0; i < num_parameters; i++) { |
+ type = ParameterTypeAt(i); |
+ if (!type.IsInstantiated()) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+ |
const char* Function::ToCString() const { |
const char* f0 = is_static() ? " static" : ""; |
const char* f1 = NULL; |