| Index: runtime/vm/object.cc
|
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
|
| index 38913816fb130fba099d91114347aad5d0f25e9f..69a752ec90addcfc13c121db7dc694da6f7998c1 100644
|
| --- a/runtime/vm/object.cc
|
| +++ b/runtime/vm/object.cc
|
| @@ -1122,6 +1122,8 @@ RawError* Object::Init(Isolate* isolate) {
|
|
|
| // Setup type class early in the process.
|
| const Class& type_cls = Class::Handle(zone, Class::New<Type>());
|
| + const Class& function_type_cls = Class::Handle(zone,
|
| + Class::New<FunctionType>());
|
| const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
|
| const Class& type_parameter_cls = Class::Handle(zone,
|
| Class::New<TypeParameter>());
|
| @@ -1284,6 +1286,9 @@ RawError* Object::Init(Isolate* isolate) {
|
| RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
|
| pending_classes.Add(type_cls);
|
|
|
| + RegisterPrivateClass(function_type_cls, Symbols::FunctionType(), core_lib);
|
| + pending_classes.Add(function_type_cls);
|
| +
|
| RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
|
| pending_classes.Add(type_ref_cls);
|
|
|
| @@ -1321,15 +1326,14 @@ RawError* Object::Init(Isolate* isolate) {
|
| RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
|
| pending_classes.Add(cls);
|
|
|
| - // Abstract super class for all signature classes.
|
| - cls = Class::New<Instance>(kIllegalCid);
|
| - cls.set_num_type_arguments(0);
|
| + // Class that represents the Dart class _Closure and C++ class Closure.
|
| + cls = Class::New<Closure>();
|
| + cls.set_type_arguments_field_offset(Closure::type_arguments_offset());
|
| + cls.set_num_type_arguments(0); // Although a closure has type_arguments_.
|
| cls.set_num_own_type_arguments(0);
|
| - cls.set_is_prefinalized();
|
| - RegisterPrivateClass(cls, Symbols::FunctionImpl(), core_lib);
|
| + RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
|
| pending_classes.Add(cls);
|
| - type = Type::NewNonParameterizedType(cls);
|
| - object_store->set_function_impl_type(type);
|
| + object_store->set_closure_class(cls);
|
|
|
| cls = Class::New<WeakProperty>();
|
| object_store->set_weak_property_class(cls);
|
| @@ -1606,6 +1610,7 @@ RawError* Object::Init(Isolate* isolate) {
|
|
|
| cls = Class::New<LibraryPrefix>();
|
| cls = Class::New<Type>();
|
| + cls = Class::New<FunctionType>();
|
| cls = Class::New<TypeRef>();
|
| cls = Class::New<TypeParameter>();
|
| cls = Class::New<BoundedType>();
|
| @@ -1660,6 +1665,9 @@ RawError* Object::Init(Isolate* isolate) {
|
| cls = Class::New<Double>();
|
| object_store->set_double_class(cls);
|
|
|
| + cls = Class::New<Closure>();
|
| + object_store->set_closure_class(cls);
|
| +
|
| cls = Class::New<Bigint>();
|
| object_store->set_bigint_class(cls);
|
|
|
| @@ -1953,36 +1961,6 @@ bool Class::IsInFullSnapshot() const {
|
| }
|
|
|
|
|
| -RawType* Class::SignatureType() const {
|
| - ASSERT(IsSignatureClass());
|
| - Zone* zone = Thread::Current()->zone();
|
| - const Function& function = Function::Handle(zone, signature_function());
|
| - ASSERT(!function.IsNull());
|
| - if (function.signature_class() != raw()) {
|
| - // This class is a function type alias. Return the canonical signature type.
|
| - const Class& canonical_signature_class =
|
| - Class::Handle(zone, function.signature_class());
|
| - return canonical_signature_class.SignatureType();
|
| - }
|
| - const Type& signature_type = Type::Handle(zone, CanonicalType());
|
| - if (!signature_type.IsNull()) {
|
| - return signature_type.raw();
|
| - }
|
| - // A signature class extends class Instance and is parameterized in the same
|
| - // way as the owner class of its non-static signature function.
|
| - // It is not type parameterized if its signature function is static.
|
| - // See Class::NewSignatureClass() for the setup of its type parameters.
|
| - // During type finalization, the type arguments of the super class of the
|
| - // owner class of its signature function will be prepended to the type
|
| - // argument vector. Therefore, we only need to set the type arguments
|
| - // matching the type parameters here.
|
| - const TypeArguments& signature_type_arguments =
|
| - TypeArguments::Handle(zone, type_parameters());
|
| - // Return the still unfinalized signature type.
|
| - return Type::New(*this, signature_type_arguments, token_pos());
|
| -}
|
| -
|
| -
|
| RawAbstractType* Class::RareType() const {
|
| const Type& type = Type::Handle(Type::New(
|
| *this,
|
| @@ -2458,14 +2436,6 @@ intptr_t Class::NumTypeArguments() const {
|
| cls = raw();
|
| intptr_t num_type_args = 0;
|
| do {
|
| - if (cls.IsSignatureClass()) {
|
| - Function& signature_fun = Function::Handle(zone);
|
| - signature_fun ^= cls.signature_function();
|
| - if (!signature_fun.is_static() &&
|
| - !signature_fun.HasInstantiatedSignature()) {
|
| - cls = signature_fun.Owner();
|
| - }
|
| - }
|
| // Calling NumOwnTypeArguments() on a mixin application class will setup the
|
| // type parameters if not already done.
|
| num_type_args += cls.NumOwnTypeArguments();
|
| @@ -2475,8 +2445,12 @@ intptr_t Class::NumTypeArguments() const {
|
| break;
|
| }
|
| sup_type = cls.super_type();
|
| - ClassFinalizer::ResolveTypeClass(cls, sup_type);
|
| + // A BoundedType, TypeRef, or FunctionType can appear as type argument of
|
| + // sup_type, but not as sup_type itself.
|
| + ASSERT(sup_type.IsType());
|
| + sup_type = ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
|
| cls = sup_type.type_class();
|
| + ASSERT(!cls.IsTypedefClass());
|
| } while (true);
|
| set_num_type_arguments(num_type_args);
|
| return num_type_args;
|
| @@ -2528,6 +2502,7 @@ RawTypeParameter* Class::LookupTypeParameter(const String& type_name) const {
|
|
|
|
|
| void Class::CalculateFieldOffsets() const {
|
| + ASSERT(id() != kClosureCid); // Class _Closure is prefinalized.
|
| Array& flds = Array::Handle(fields());
|
| const Class& super = Class::Handle(SuperClass());
|
| intptr_t offset = 0;
|
| @@ -2741,9 +2716,7 @@ void Class::set_invocation_dispatcher_cache(const Array& cache) const {
|
|
|
| void Class::Finalize() const {
|
| ASSERT(Thread::Current()->IsMutatorThread());
|
| - // Even if all regular classes are prefinalized (precompilation), signature
|
| - // classes may be added later when we encounter local functions.
|
| - ASSERT(IsSignatureClass() || !Isolate::Current()->all_classes_finalized());
|
| + ASSERT(!Isolate::Current()->all_classes_finalized());
|
| ASSERT(!is_finalized());
|
| // Prefinalized classes have a VM internal representation and no Dart fields.
|
| // Their instance size is precomputed and field offsets are known.
|
| @@ -3128,73 +3101,6 @@ RawClass* Class::New(const String& name,
|
| }
|
|
|
|
|
| -RawClass* Class::NewSignatureClass(const String& name,
|
| - const Function& signature_function,
|
| - const Script& script,
|
| - intptr_t token_pos) {
|
| - const Class& result = Class::Handle(New(name, script, token_pos));
|
| - // Instances of a signature class can only be closures.
|
| - result.set_instance_size(Closure::InstanceSize());
|
| - result.set_next_field_offset(Closure::NextFieldOffset());
|
| - // Signature classes extend the _FunctionImpl class.
|
| - result.set_super_type(Type::Handle(
|
| - Isolate::Current()->object_store()->function_impl_type()));
|
| - result.set_is_synthesized_class();
|
| - result.set_type_arguments_field_offset(Closure::type_arguments_offset());
|
| - if (!signature_function.IsNull()) {
|
| - result.PatchSignatureFunction(signature_function);
|
| - }
|
| - return result.raw();
|
| -}
|
| -
|
| -
|
| -void Class::PatchSignatureFunction(const Function& signature_function) const {
|
| - ASSERT(!signature_function.IsNull());
|
| - set_signature_function(signature_function);
|
| - const Class& owner_class = Class::Handle(signature_function.Owner());
|
| - ASSERT(!owner_class.IsNull());
|
| - // A signature class extends class Instance and is either not parameterized or
|
| - // parameterized with exactly the same list of type parameters as the owner
|
| - // class of its function.
|
| - // In case of a function type alias, the function owner is the alias class,
|
| - // which is also the signature class. The signature class is therefore
|
| - // parameterized according to the alias class declaration, even if the
|
| - // function type is not generic.
|
| - // Otherwise, if the function is static or if its signature type is
|
| - // non-generic, i.e. it does not depend on any type parameter of the owner
|
| - // class, then the signature class is not parameterized, although the owner
|
| - // class may be.
|
| - if (owner_class.raw() == raw()) {
|
| - // This signature class is an alias, which cannot be the canonical
|
| - // signature class for this signature function.
|
| - ASSERT(!IsCanonicalSignatureClass());
|
| - // Do not modify the declared type parameters of the alias, even if unused.
|
| - } else {
|
| - // Copy the type parameters only for an instance function type that is not
|
| - // instantiated, i.e. that depends on the type parameters of the owner
|
| - // class.
|
| - // TODO(regis): Verify that it is not a problem for the copied type
|
| - // parameters to refer to the owner class rather than to the signature
|
| - // class. In other words, uninstantiated function types should only get
|
| - // instantiated by the owner class as instantiator and never by the
|
| - // signature class itself.
|
| - TypeArguments& type_parameters = TypeArguments::Handle();
|
| - if (!signature_function.is_static() &&
|
| - (owner_class.NumTypeParameters() > 0) &&
|
| - !signature_function.HasInstantiatedSignature()) {
|
| - type_parameters = owner_class.type_parameters();
|
| - }
|
| - set_type_parameters(type_parameters);
|
| - if (signature_function.signature_class() == Object::null()) {
|
| - // Make this signature class the canonical signature class.
|
| - signature_function.set_signature_class(*this);
|
| - ASSERT(IsCanonicalSignatureClass());
|
| - }
|
| - }
|
| - set_is_prefinalized();
|
| -}
|
| -
|
| -
|
| RawClass* Class::NewNativeWrapper(const Library& library,
|
| const String& name,
|
| int field_count) {
|
| @@ -3292,12 +3198,8 @@ void Class::set_user_name(const String& value) const {
|
|
|
|
|
| RawString* Class::GeneratePrettyName() const {
|
| - if (!IsCanonicalSignatureClass()) {
|
| - const String& name = String::Handle(Name());
|
| - return String::IdentifierPrettyName(name);
|
| - } else {
|
| - return Name();
|
| - }
|
| + const String& name = String::Handle(Name());
|
| + return String::IdentifierPrettyName(name);
|
| }
|
|
|
|
|
| @@ -3435,12 +3337,8 @@ RawString* Class::GenerateUserVisibleName() const {
|
| case kExternalTypedDataFloat64ArrayCid:
|
| return Symbols::Float64List().raw();
|
| default:
|
| - if (!IsCanonicalSignatureClass()) {
|
| - const String& name = String::Handle(Name());
|
| - return String::IdentifierPrettyName(name);
|
| - } else {
|
| - return Name();
|
| - }
|
| + const String& name = String::Handle(Name());
|
| + return String::IdentifierPrettyName(name);
|
| }
|
| UNREACHABLE();
|
| }
|
| @@ -3459,7 +3357,7 @@ void Class::set_token_pos(intptr_t token_pos) const {
|
|
|
| intptr_t Class::ComputeEndTokenPos() const {
|
| // Return the begin token for synthetic classes.
|
| - if (IsSignatureClass() || IsMixinApplication() || IsTopLevel()) {
|
| + if (IsMixinApplication() || IsTopLevel()) {
|
| return token_pos();
|
| }
|
| const Script& scr = Script::Handle(script());
|
| @@ -3642,7 +3540,7 @@ void Class::set_canonical_types(const Object& value) const {
|
|
|
|
|
| RawType* Class::CanonicalType() const {
|
| - if (!IsGeneric()) {
|
| + if (!IsGeneric() && !IsClosureClass()) {
|
| return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
|
| }
|
| Array& types = Array::Handle();
|
| @@ -3656,7 +3554,7 @@ RawType* Class::CanonicalType() const {
|
|
|
| void Class::SetCanonicalType(const Type& type) const {
|
| ASSERT(type.IsCanonical());
|
| - if (!IsGeneric()) {
|
| + if (!IsGeneric() && !IsClosureClass()) {
|
| ASSERT((canonical_types() == Object::null()) ||
|
| (canonical_types() == type.raw())); // Set during own finalization.
|
| set_canonical_types(type);
|
| @@ -3670,7 +3568,7 @@ void Class::SetCanonicalType(const Type& type) const {
|
| }
|
|
|
|
|
| -intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
|
| +intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const {
|
| Thread* thread = Thread::Current();
|
| if (EnsureIsFinalized(thread) != Error::null()) {
|
| return -1;
|
| @@ -3700,8 +3598,8 @@ intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
|
| }
|
|
|
|
|
| -RawType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
|
| - Type& type = Type::Handle();
|
| +RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
|
| + AbstractType& type = AbstractType::Handle();
|
| if (idx == 0) {
|
| type = CanonicalType();
|
| if (!type.IsNull()) {
|
| @@ -3748,12 +3646,6 @@ bool Class::IsFunctionClass() const {
|
| }
|
|
|
|
|
| -bool Class::IsCanonicalSignatureClass() const {
|
| - const Function& function = Function::Handle(signature_function());
|
| - return (!function.IsNull() && (function.signature_class() == raw()));
|
| -}
|
| -
|
| -
|
| // If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T.
|
| // If test_kind == kIsMoreSpecificThan, checks if S is more specific than T.
|
| // Type S is specified by this class parameterized with 'type_arguments', and
|
| @@ -3826,25 +3718,8 @@ bool Class::TypeTestNonRecursive(const Class& cls,
|
| bound_error,
|
| space);
|
| }
|
| - const bool other_is_function_class = other.IsFunctionClass();
|
| - if (other.IsSignatureClass() || other_is_function_class) {
|
| - const Function& other_fun = Function::Handle(zone,
|
| - other.signature_function());
|
| - if (thsi.IsSignatureClass()) {
|
| - if (other_is_function_class) {
|
| - return true;
|
| - }
|
| - // Check for two function types.
|
| - const Function& fun =
|
| - Function::Handle(zone, thsi.signature_function());
|
| - return fun.TypeTest(test_kind,
|
| - type_arguments,
|
| - other_fun,
|
| - other_type_arguments,
|
| - bound_error,
|
| - space);
|
| - }
|
| - // Check if type S has a call() method of function type T.
|
| + if (other.IsFunctionClass()) {
|
| + // Check if type S has a call() method.
|
| Function& function =
|
| Function::Handle(zone, thsi.LookupDynamicFunction(Symbols::Call()));
|
| if (function.IsNull()) {
|
| @@ -3856,15 +3731,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
|
| }
|
| }
|
| if (!function.IsNull()) {
|
| - if (other_is_function_class ||
|
| - function.TypeTest(test_kind,
|
| - type_arguments,
|
| - other_fun,
|
| - other_type_arguments,
|
| - bound_error,
|
| - space)) {
|
| - return true;
|
| - }
|
| + return true;
|
| }
|
| }
|
| // Check for 'direct super type' specified in the implements clause
|
| @@ -4904,7 +4771,8 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
|
| }
|
| // Cache lookup failed. Instantiate the type arguments.
|
| TypeArguments& result = TypeArguments::Handle();
|
| - result = InstantiateFrom(instantiator_type_arguments, bound_error);
|
| + result = InstantiateFrom(
|
| + instantiator_type_arguments, bound_error, NULL, Heap::kOld);
|
| if ((bound_error != NULL) && !bound_error->IsNull()) {
|
| return result.raw();
|
| }
|
| @@ -5496,33 +5364,67 @@ void Function::set_implicit_closure_function(const Function& value) const {
|
| }
|
|
|
|
|
| -RawClass* Function::signature_class() const {
|
| +RawFunctionType* Function::SignatureType() const {
|
| + FunctionType& type = FunctionType::Handle();
|
| + const Object& obj = Object::Handle(raw_ptr()->data_);
|
| if (IsSignatureFunction()) {
|
| - const Object& obj = Object::Handle(raw_ptr()->data_);
|
| - ASSERT(obj.IsNull() || obj.IsClass());
|
| - return (obj.IsNull()) ? Class::null() : Class::Cast(obj).raw();
|
| - }
|
| - if (IsClosureFunction()) {
|
| - const Object& obj = Object::Handle(raw_ptr()->data_);
|
| + ASSERT(obj.IsNull() || obj.IsFunctionType());
|
| + type = obj.IsNull() ? FunctionType::null() : FunctionType::Cast(obj).raw();
|
| + } else {
|
| + ASSERT(IsClosureFunction());
|
| ASSERT(!obj.IsNull());
|
| - return ClosureData::Cast(obj).signature_class();
|
| + type = ClosureData::Cast(obj).signature_type();
|
| }
|
| - return Class::null();
|
| + if (type.IsNull()) {
|
| + // A function type is parameterized in the same way as the owner class of
|
| + // its non-static signature function.
|
| + // It is not type parameterized if its signature function is static.
|
| + // During type finalization, the type arguments of the super class of the
|
| + // owner class of its signature function will be prepended to the type
|
| + // argument vector. Therefore, we only need to set the type arguments
|
| + // matching the type parameters here.
|
| + // In case of a function type alias, the function owner is the alias class,
|
| + // i.e. the typedef. The signature type is therefore parameterized according
|
| + // to the alias class declaration, even if the function type is not generic.
|
| + // Otherwise, if the function is static or if its signature type is
|
| + // non-generic, i.e. it does not depend on any type parameter of the owner
|
| + // class, then the signature type is not parameterized, although the owner
|
| + // class may be. In this case, the scope class of the function type is reset
|
| + // to _Closure class as well as the owner of the signature function.
|
| + Class& scope_class = Class::Handle(Owner());
|
| + if (!scope_class.IsTypedefClass() &&
|
| + (is_static() ||
|
| + !scope_class.IsGeneric() ||
|
| + HasInstantiatedSignature())) {
|
| + scope_class = Isolate::Current()->object_store()->closure_class();
|
| + if (IsSignatureFunction()) {
|
| + set_owner(scope_class);
|
| + set_token_pos(Token::kNoSourcePos);
|
| + }
|
| + }
|
| + const TypeArguments& signature_type_arguments =
|
| + TypeArguments::Handle(scope_class.type_parameters());
|
| + // Return the still unfinalized signature type.
|
| + type = FunctionType::New(scope_class,
|
| + signature_type_arguments,
|
| + *this,
|
| + token_pos());
|
| +
|
| + SetSignatureType(type);
|
| + }
|
| + return type.raw();
|
| }
|
|
|
|
|
| -void Function::set_signature_class(const Class& value) const {
|
| +void Function::SetSignatureType(const FunctionType& value) const {
|
| if (IsSignatureFunction()) {
|
| set_data(value);
|
| - return;
|
| - }
|
| - if (IsClosureFunction()) {
|
| + } else {
|
| + ASSERT(IsClosureFunction());
|
| const Object& obj = Object::Handle(raw_ptr()->data_);
|
| ASSERT(!obj.IsNull());
|
| - ClosureData::Cast(obj).set_signature_class(value);
|
| - return;
|
| + ClosureData::Cast(obj).set_signature_type(value);
|
| }
|
| - UNREACHABLE();
|
| }
|
|
|
|
|
| @@ -5643,7 +5545,7 @@ void Function::SetRedirectionTarget(const Function& target) const {
|
|
|
| // This field is heavily overloaded:
|
| // eval function: Script expression source
|
| -// signature function: Class signature class
|
| +// signature function: Function type
|
| // method extractor: Function extracted closure function
|
| // noSuchMethod dispatcher: Array arguments descriptor
|
| // invoke-field dispatcher: Array arguments descriptor
|
| @@ -6509,6 +6411,25 @@ RawFunction* Function::NewClosureFunction(const String& name,
|
| }
|
|
|
|
|
| +RawFunction* Function::NewSignatureFunction(const Class& owner,
|
| + intptr_t token_pos) {
|
| + const Function& result = Function::Handle(Function::New(
|
| + Symbols::AnonymousSignature(),
|
| + RawFunction::kSignatureFunction,
|
| + /* is_static = */ false,
|
| + /* is_const = */ false,
|
| + /* is_abstract = */ false,
|
| + /* is_external = */ false,
|
| + /* is_native = */ false,
|
| + owner, // Same as function type scope class.
|
| + token_pos));
|
| + result.set_is_reflectable(false);
|
| + result.set_is_visible(false);
|
| + result.set_is_debuggable(false);
|
| + return result.raw();
|
| +}
|
| +
|
| +
|
| RawFunction* Function::NewEvalFunction(const Class& owner,
|
| const Script& script,
|
| bool is_static) {
|
| @@ -6587,35 +6508,12 @@ RawFunction* Function::ImplicitClosureFunction() const {
|
| param_name = ParameterNameAt(has_receiver - kClosure + i);
|
| closure_function.SetParameterNameAt(i, param_name);
|
| }
|
| -
|
| - // Lookup or create a new signature class for the closure function in the
|
| - // library of the owner class.
|
| - const Class& owner_class = Class::Handle(Owner());
|
| - ASSERT(!owner_class.IsNull() && (Owner() == closure_function.Owner()));
|
| - const Library& library = Library::Handle(owner_class.library());
|
| - ASSERT(!library.IsNull());
|
| - const String& signature = String::Handle(closure_function.Signature());
|
| - Class& signature_class = Class::ZoneHandle(
|
| - library.LookupLocalClass(signature));
|
| - if (signature_class.IsNull()) {
|
| - const Script& script = Script::Handle(this->script());
|
| - signature_class = Class::NewSignatureClass(signature,
|
| - closure_function,
|
| - script,
|
| - closure_function.token_pos());
|
| - library.AddClass(signature_class);
|
| - } else {
|
| - closure_function.set_signature_class(signature_class);
|
| - }
|
| - // Finalize types in signature class here, so that the
|
| - // signature type is not computed twice.
|
| - ClassFinalizer::FinalizeTypesInClass(signature_class);
|
| - const Type& signature_type = Type::Handle(signature_class.SignatureType());
|
| + const FunctionType& signature_type =
|
| + FunctionType::Handle(closure_function.SignatureType());
|
| if (!signature_type.IsFinalized()) {
|
| ClassFinalizer::FinalizeType(
|
| - signature_class, signature_type, ClassFinalizer::kCanonicalize);
|
| + Class::Handle(Owner()), signature_type, ClassFinalizer::kCanonicalize);
|
| }
|
| - ASSERT(closure_function.signature_class() == signature_class.raw());
|
| set_implicit_closure_function(closure_function);
|
| ASSERT(closure_function.IsImplicitClosureFunction());
|
| return closure_function.raw();
|
| @@ -6720,9 +6618,6 @@ RawInstance* Function::ImplicitStaticClosure() const {
|
| Context::Handle(zone, object_store->empty_context());
|
| Instance& closure =
|
| Instance::Handle(zone, Closure::New(*this, context, Heap::kOld));
|
| - const char* error_str = NULL;
|
| - closure ^= closure.CheckAndCanonicalize(&error_str);
|
| - ASSERT(!closure.IsNull());
|
| set_implicit_static_closure(closure);
|
| }
|
| return implicit_static_closure();
|
| @@ -6731,11 +6626,12 @@ RawInstance* Function::ImplicitStaticClosure() const {
|
|
|
| RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const {
|
| ASSERT(IsImplicitClosureFunction());
|
| - const Class& cls = Class::Handle(signature_class());
|
| + const FunctionType& signature_type = FunctionType::Handle(SignatureType());
|
| + const Class& cls = Class::Handle(signature_type.type_class());
|
| const Context& context = Context::Handle(Context::New(1));
|
| context.SetAt(0, receiver);
|
| const Instance& result = Instance::Handle(Closure::New(*this, context));
|
| - if (cls.NumTypeArguments() > 0) {
|
| + if (cls.IsGeneric()) {
|
| const TypeArguments& type_arguments =
|
| TypeArguments::Handle(receiver.GetTypeArguments());
|
| result.SetTypeArguments(type_arguments);
|
| @@ -6752,18 +6648,17 @@ RawString* Function::BuildSignature(bool instantiate,
|
| GrowableHandlePtrArray<const String> pieces(zone, 4);
|
| String& name = String::Handle(zone);
|
| if (!instantiate && !is_static() && (name_visibility == kInternalName)) {
|
| - // Prefix the signature with its signature class and type parameters, if any
|
| + // Prefix the signature with its scope class and type parameters, if any
|
| // (e.g. "Map<K, V>(K) => bool"). In case of a function type alias, the
|
| - // signature class name is the alias name.
|
| + // scope class name is the alias name.
|
| // The signature of static functions cannot be type parameterized.
|
| - const Class& function_class = Class::Handle(zone, Owner());
|
| - ASSERT(!function_class.IsNull());
|
| - const TypeArguments& type_parameters = TypeArguments::Handle(
|
| - zone, function_class.type_parameters());
|
| - if (!type_parameters.IsNull()) {
|
| - const String& function_class_name =
|
| - String::Handle(zone, function_class.Name());
|
| - pieces.Add(function_class_name);
|
| + const Class& scope_class = Class::Handle(zone, Owner());
|
| + ASSERT(!scope_class.IsNull());
|
| + if (scope_class.IsGeneric()) {
|
| + const TypeArguments& type_parameters = TypeArguments::Handle(
|
| + zone, scope_class.type_parameters());
|
| + const String& scope_class_name = String::Handle(zone, scope_class.Name());
|
| + pieces.Add(scope_class_name);
|
| const intptr_t num_type_parameters = type_parameters.Length();
|
| pieces.Add(Symbols::LAngleBracket());
|
| TypeParameter& type_parameter = TypeParameter::Handle(zone);
|
| @@ -7275,8 +7170,8 @@ void ClosureData::set_parent_function(const Function& value) const {
|
| }
|
|
|
|
|
| -void ClosureData::set_signature_class(const Class& value) const {
|
| - StorePointer(&raw_ptr()->signature_class_, value.raw());
|
| +void ClosureData::set_signature_type(const FunctionType& value) const {
|
| + StorePointer(&raw_ptr()->signature_type_, value.raw());
|
| }
|
|
|
|
|
| @@ -10528,8 +10423,7 @@ void Library::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| Class& klass = Class::Handle();
|
| while (class_iter.HasNext()) {
|
| klass = class_iter.GetNextClass();
|
| - if (!klass.IsCanonicalSignatureClass() &&
|
| - !klass.IsMixinApplication()) {
|
| + if (!klass.IsMixinApplication()) {
|
| jsarr.AddValue(klass);
|
| }
|
| }
|
| @@ -14395,7 +14289,7 @@ intptr_t SubtypeTestCache::NumberOfChecks() const {
|
|
|
|
|
| void SubtypeTestCache::AddCheck(
|
| - intptr_t instance_class_id,
|
| + const Object& instance_class_id_or_function,
|
| const TypeArguments& instance_type_arguments,
|
| const TypeArguments& instantiator_type_arguments,
|
| const Bool& test_result) const {
|
| @@ -14405,24 +14299,24 @@ void SubtypeTestCache::AddCheck(
|
| data = Array::Grow(data, new_len);
|
| set_cache(data);
|
| intptr_t data_pos = old_num * kTestEntryLength;
|
| - data.SetAt(data_pos + kInstanceClassId,
|
| - Smi::Handle(Smi::New(instance_class_id)));
|
| + data.SetAt(data_pos + kInstanceClassIdOrFunction,
|
| + instance_class_id_or_function);
|
| data.SetAt(data_pos + kInstanceTypeArguments, instance_type_arguments);
|
| data.SetAt(data_pos + kInstantiatorTypeArguments,
|
| - instantiator_type_arguments);
|
| + instantiator_type_arguments);
|
| data.SetAt(data_pos + kTestResult, test_result);
|
| }
|
|
|
|
|
| void SubtypeTestCache::GetCheck(intptr_t ix,
|
| - intptr_t* instance_class_id,
|
| + Object* instance_class_id_or_function,
|
| TypeArguments* instance_type_arguments,
|
| TypeArguments* instantiator_type_arguments,
|
| Bool* test_result) const {
|
| Array& data = Array::Handle(cache());
|
| intptr_t data_pos = ix * kTestEntryLength;
|
| - *instance_class_id =
|
| - Smi::Value(Smi::RawCast(data.At(data_pos + kInstanceClassId)));
|
| + *instance_class_id_or_function =
|
| + data.At(data_pos + kInstanceClassIdOrFunction);
|
| *instance_type_arguments ^= data.At(data_pos + kInstanceTypeArguments);
|
| *instantiator_type_arguments ^=
|
| data.At(data_pos + kInstantiatorTypeArguments);
|
| @@ -14981,11 +14875,32 @@ RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
|
| }
|
|
|
|
|
| -RawType* Instance::GetType() const {
|
| +RawAbstractType* Instance::GetType() const {
|
| if (IsNull()) {
|
| return Type::NullType();
|
| }
|
| const Class& cls = Class::Handle(clazz());
|
| + if (cls.IsClosureClass()) {
|
| + const Function& signature =
|
| + Function::Handle(Closure::Cast(*this).function());
|
| + FunctionType& type = FunctionType::Handle(signature.SignatureType());
|
| + if (type.scope_class() == cls.raw()) {
|
| + // Type is not parameterized.
|
| + if (!type.IsCanonical()) {
|
| + type ^= type.Canonicalize();
|
| + signature.SetSignatureType(type);
|
| + }
|
| + return type.raw();
|
| + }
|
| + const Class& scope_cls = Class::Handle(type.scope_class());
|
| + ASSERT(scope_cls.NumTypeArguments() > 0);
|
| + TypeArguments& type_arguments = TypeArguments::Handle(GetTypeArguments());
|
| + type = FunctionType::New(
|
| + scope_cls, type_arguments, signature, Token::kNoSourcePos);
|
| + type.SetIsFinalized();
|
| + type ^= type.Canonicalize();
|
| + return type.raw();
|
| + }
|
| Type& type = Type::Handle();
|
| if (!cls.IsGeneric()) {
|
| type = cls.CanonicalType();
|
| @@ -15034,6 +14949,47 @@ bool Instance::IsInstanceOf(const AbstractType& other,
|
| }
|
| Zone* zone = Thread::Current()->zone();
|
| const Class& cls = Class::Handle(zone, clazz());
|
| + if (cls.IsClosureClass()) {
|
| + if (other.IsObjectType() || other.IsDartFunctionType()) {
|
| + return true;
|
| + }
|
| + Function& other_signature = Function::Handle(zone);
|
| + TypeArguments& other_type_arguments = TypeArguments::Handle(zone);
|
| + // Note that we may encounter a bound error in checked mode.
|
| + if (!other.IsInstantiated()) {
|
| + const AbstractType& instantiated_other = AbstractType::Handle(
|
| + zone, other.InstantiateFrom(other_instantiator, bound_error));
|
| + if ((bound_error != NULL) && !bound_error->IsNull()) {
|
| + ASSERT(Isolate::Current()->flags().type_checks());
|
| + return false;
|
| + }
|
| + if (instantiated_other.IsDynamicType() ||
|
| + instantiated_other.IsObjectType() ||
|
| + instantiated_other.IsDartFunctionType()) {
|
| + return true;
|
| + }
|
| + if (!instantiated_other.IsFunctionType()) {
|
| + return false;
|
| + }
|
| + other_signature = FunctionType::Cast(instantiated_other).signature();
|
| + other_type_arguments = instantiated_other.arguments();
|
| + } else {
|
| + if (!other.IsFunctionType()) {
|
| + return false;
|
| + }
|
| + other_signature = FunctionType::Cast(other).signature();
|
| + other_type_arguments = other.arguments();
|
| + }
|
| + const Function& signature =
|
| + Function::Handle(zone, Closure::Cast(*this).function());
|
| + const TypeArguments& type_arguments =
|
| + TypeArguments::Handle(zone, GetTypeArguments());
|
| + return signature.IsSubtypeOf(type_arguments,
|
| + other_signature,
|
| + other_type_arguments,
|
| + bound_error,
|
| + Heap::kOld);
|
| + }
|
| TypeArguments& type_arguments = TypeArguments::Handle(zone);
|
| if (cls.NumTypeArguments() > 0) {
|
| type_arguments = GetTypeArguments();
|
| @@ -15051,20 +15007,54 @@ bool Instance::IsInstanceOf(const AbstractType& other,
|
| }
|
| Class& other_class = Class::Handle(zone);
|
| TypeArguments& other_type_arguments = TypeArguments::Handle(zone);
|
| + AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
|
| // Note that we may encounter a bound error in checked mode.
|
| if (!other.IsInstantiated()) {
|
| - const AbstractType& instantiated_other = AbstractType::Handle(
|
| - zone, other.InstantiateFrom(other_instantiator, bound_error));
|
| + instantiated_other = other.InstantiateFrom(other_instantiator, bound_error);
|
| if ((bound_error != NULL) && !bound_error->IsNull()) {
|
| ASSERT(Isolate::Current()->flags().type_checks());
|
| return false;
|
| }
|
| - other_class = instantiated_other.type_class();
|
| - other_type_arguments = instantiated_other.arguments();
|
| - } else {
|
| - other_class = other.type_class();
|
| - other_type_arguments = other.arguments();
|
| + if (instantiated_other.IsTypeRef()) {
|
| + instantiated_other = TypeRef::Cast(instantiated_other).type();
|
| + }
|
| + if (instantiated_other.IsDynamicType()) {
|
| + return true;
|
| + }
|
| + }
|
| + other_type_arguments = instantiated_other.arguments();
|
| + const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
|
| + if (other_is_dart_function || instantiated_other.IsFunctionType()) {
|
| + // Check if this instance understands a call() method of a compatible type.
|
| + Function& call =
|
| + Function::Handle(zone, cls.LookupDynamicFunction(Symbols::Call()));
|
| + if (call.IsNull()) {
|
| + // Walk up the super_class chain.
|
| + Class& super_cls = Class::Handle(zone, cls.SuperClass());
|
| + while (!super_cls.IsNull() && call.IsNull()) {
|
| + call = super_cls.LookupDynamicFunction(Symbols::Call());
|
| + super_cls = super_cls.SuperClass();
|
| + }
|
| + }
|
| + if (!call.IsNull()) {
|
| + if (other_is_dart_function) {
|
| + return true;
|
| + }
|
| + const Function& other_signature = Function::Handle(
|
| + zone, FunctionType::Cast(instantiated_other).signature());
|
| + if (call.IsSubtypeOf(type_arguments,
|
| + other_signature,
|
| + other_type_arguments,
|
| + bound_error,
|
| + Heap::kOld)) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + if (!instantiated_other.IsType()) {
|
| + return false;
|
| }
|
| + other_class = instantiated_other.type_class();
|
| return cls.IsSubtypeOf(type_arguments, other_class, other_type_arguments,
|
| bound_error, Heap::kOld);
|
| }
|
| @@ -15130,17 +15120,11 @@ void Instance::SetNativeFields(uint16_t num_native_fields,
|
| }
|
|
|
|
|
| -bool Instance::IsClosure() const {
|
| - const Class& cls = Class::Handle(clazz());
|
| - return cls.IsSignatureClass();
|
| -}
|
| -
|
| -
|
| bool Instance::IsCallable(Function* function) const {
|
| Class& cls = Class::Handle(clazz());
|
| - if (cls.IsSignatureClass()) {
|
| + if (cls.IsClosureClass()) {
|
| if (function != NULL) {
|
| - *function = Closure::function(*this);
|
| + *function = Closure::Cast(*this).function();
|
| }
|
| return true;
|
| }
|
| @@ -15245,7 +15229,7 @@ const char* Instance::ToCString() const {
|
| return "Instance";
|
| } else {
|
| if (IsClosure()) {
|
| - return Closure::ToCString(*this);
|
| + return Closure::Cast(*this).ToCString();
|
| }
|
| const Class& cls = Class::Handle(clazz());
|
| TypeArguments& type_arguments = TypeArguments::Handle();
|
| @@ -15330,9 +15314,9 @@ void Instance::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| jsobj.AddServiceId(*this);
|
| if (IsClosure()) {
|
| jsobj.AddProperty("closureFunction",
|
| - Function::Handle(Closure::function(*this)));
|
| + Function::Handle(Closure::Cast(*this).function()));
|
| jsobj.AddProperty("closureContext",
|
| - Context::Handle(Closure::context(*this)));
|
| + Context::Handle(Closure::Cast(*this).context()));
|
| }
|
| if (ref) {
|
| return;
|
| @@ -15354,6 +15338,12 @@ bool AbstractType::IsResolved() const {
|
| }
|
|
|
|
|
| +void AbstractType::SetIsResolved() const {
|
| + // AbstractType is an abstract class.
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| bool AbstractType::HasResolvedTypeClass() const {
|
| // AbstractType is an abstract class.
|
| UNREACHABLE();
|
| @@ -15382,6 +15372,11 @@ RawTypeArguments* AbstractType::arguments() const {
|
| }
|
|
|
|
|
| +void AbstractType::set_arguments(const TypeArguments& value) const {
|
| + // AbstractType is an abstract class.
|
| + UNREACHABLE();
|
| +}
|
| +
|
| intptr_t AbstractType::token_pos() const {
|
| // AbstractType is an abstract class.
|
| UNREACHABLE();
|
| @@ -15403,6 +15398,12 @@ bool AbstractType::IsFinalized() const {
|
| }
|
|
|
|
|
| +void AbstractType::SetIsFinalized() const {
|
| + // AbstractType is an abstract class.
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| bool AbstractType::IsBeingFinalized() const {
|
| // AbstractType is an abstract class.
|
| UNREACHABLE();
|
| @@ -15410,6 +15411,12 @@ bool AbstractType::IsBeingFinalized() const {
|
| }
|
|
|
|
|
| +void AbstractType::SetIsBeingFinalized() const {
|
| + // AbstractType is an abstract class.
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| bool AbstractType::IsMalformed() const {
|
| // AbstractType is an abstract class.
|
| UNREACHABLE();
|
| @@ -15564,8 +15571,29 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
|
| String& class_name = String::Handle(zone);
|
| intptr_t first_type_param_index;
|
| intptr_t num_type_params; // Number of type parameters to print.
|
| - if (HasResolvedTypeClass()) {
|
| - const Class& cls = Class::Handle(zone, type_class());
|
| + Class& cls = Class::Handle(zone);
|
| + if (IsFunctionType()) {
|
| + cls = type_class();
|
| + if (!cls.IsTypedefClass()) {
|
| + const Function& signature_function = Function::Handle(
|
| + zone, FunctionType::Cast(*this).signature());
|
| + if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
|
| + return signature_function.UserVisibleSignature();
|
| + }
|
| + return signature_function.InstantiatedSignatureFrom(args,
|
| + name_visibility);
|
| + }
|
| + class_name = cls.Name(); // Typedef name.
|
| + // We may be reporting an error about a malformed function type. In that
|
| + // case, avoid instantiating the signature, since it may cause divergence.
|
| + if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
|
| + return class_name.raw();
|
| + }
|
| + // Print the name of a typedef as a regular, possibly parameterized, class.
|
| + } else if (HasResolvedTypeClass()) {
|
| + cls = type_class();
|
| + }
|
| + if (!cls.IsNull()) {
|
| if (IsResolved() || !cls.IsMixinApplication()) {
|
| // Do not print the full vector, but only the declared type parameters.
|
| num_type_params = cls.NumTypeParameters();
|
| @@ -15603,29 +15631,8 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
|
| first_type_param_index = num_args - num_type_params;
|
| }
|
| }
|
| - if (cls.IsSignatureClass()) {
|
| - // We may be reporting an error about a malformed function type. In that
|
| - // case, avoid instantiating the signature, since it may cause divergence.
|
| - if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
|
| - return class_name.raw();
|
| - }
|
| - // To avoid divergence, print the name of a typedef (non-canonical
|
| - // signature class) as a regular, possibly parameterized, class.
|
| - if (cls.IsCanonicalSignatureClass()) {
|
| - const Function& signature_function = Function::Handle(
|
| - zone, cls.signature_function());
|
| - // Signature classes have no super type, however, they take as many
|
| - // type arguments as the owner class of their signature function (if it
|
| - // is non static and generic, see Class::NumTypeArguments()). Therefore,
|
| - // first_type_param_index may be greater than 0 here.
|
| - return signature_function.InstantiatedSignatureFrom(args,
|
| - name_visibility);
|
| - }
|
| - }
|
| } else {
|
| - const UnresolvedClass& cls =
|
| - UnresolvedClass::Handle(zone, unresolved_class());
|
| - class_name = cls.Name();
|
| + class_name = UnresolvedClass::Handle(zone, unresolved_class()).Name();
|
| num_type_params = num_args;
|
| first_type_param_index = 0;
|
| }
|
| @@ -15717,7 +15724,7 @@ bool AbstractType::IsStringType() const {
|
| }
|
|
|
|
|
| -bool AbstractType::IsFunctionType() const {
|
| +bool AbstractType::IsDartFunctionType() const {
|
| return HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::Function()).type_class());
|
| }
|
| @@ -15755,6 +15762,9 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| }
|
| return false;
|
| }
|
| + if (other.IsObjectType() || other.IsDynamicType()) {
|
| + return true;
|
| + }
|
| if (IsBoundedType() || other.IsBoundedType()) {
|
| if (Equals(other)) {
|
| return true;
|
| @@ -15766,6 +15776,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| }
|
| return false; // TODO(regis): We should return "maybe after instantiation".
|
| }
|
| + Zone* zone = Thread::Current()->zone();
|
| // Type parameters cannot be handled by Class::TypeTest().
|
| // When comparing two uninstantiated function types, one returning type
|
| // parameter K, the other returning type parameter V, we cannot assume that K
|
| @@ -15774,7 +15785,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| // The same rule applies when checking the upper bound of a still
|
| // uninstantiated type at compile time. Returning false will defer the test
|
| // to run time.
|
| - // There are however some cases can be decided at compile time.
|
| + // There are however some cases that can be decided at compile time.
|
| // For example, with class A<K, V extends K>, new A<T, T> called from within
|
| // a class B<T> will never require a run time bound check, even if T is
|
| // uninstantiated at compile time.
|
| @@ -15786,7 +15797,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| return true;
|
| }
|
| }
|
| - const AbstractType& bound = AbstractType::Handle(type_param.bound());
|
| + const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
|
| // We may be checking bounds at finalization time and can encounter
|
| // a still unfinalized bound. Finalizing the bound here may lead to cycles.
|
| if (!bound.IsFinalized()) {
|
| @@ -15800,13 +15811,59 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| if (other.IsTypeParameter()) {
|
| return false; // TODO(regis): We should return "maybe after instantiation".
|
| }
|
| - const Class& cls = Class::Handle(type_class());
|
| - return cls.TypeTest(test_kind,
|
| - TypeArguments::Handle(arguments()),
|
| - Class::Handle(other.type_class()),
|
| - TypeArguments::Handle(other.arguments()),
|
| - bound_error,
|
| - space);
|
| + const Class& type_cls = Class::Handle(zone, type_class());
|
| + // Function types cannot be handled by Class::TypeTest().
|
| + const bool other_is_dart_function_type = other.IsDartFunctionType();
|
| + if (other_is_dart_function_type || other.IsFunctionType()) {
|
| + if (IsFunctionType()) {
|
| + if (other_is_dart_function_type) {
|
| + return true;
|
| + }
|
| + const Function& other_fun =
|
| + Function::Handle(zone, FunctionType::Cast(other).signature());
|
| + // Check for two function types.
|
| + const Function& fun =
|
| + Function::Handle(zone, FunctionType::Cast(*this).signature());
|
| + return fun.TypeTest(test_kind,
|
| + TypeArguments::Handle(zone, arguments()),
|
| + other_fun,
|
| + TypeArguments::Handle(zone, other.arguments()),
|
| + bound_error,
|
| + space);
|
| + }
|
| + // Check if type S has a call() method of function type T.
|
| + Function& function =
|
| + Function::Handle(zone, type_cls.LookupDynamicFunction(Symbols::Call()));
|
| + if (function.IsNull()) {
|
| + // Walk up the super_class chain.
|
| + Class& cls = Class::Handle(zone, type_cls.SuperClass());
|
| + while (!cls.IsNull() && function.IsNull()) {
|
| + function = cls.LookupDynamicFunction(Symbols::Call());
|
| + cls = cls.SuperClass();
|
| + }
|
| + }
|
| + if (!function.IsNull()) {
|
| + if (other_is_dart_function_type ||
|
| + function.TypeTest(test_kind,
|
| + TypeArguments::Handle(zone, arguments()),
|
| + Function::Handle(
|
| + zone, FunctionType::Cast(other).signature()),
|
| + TypeArguments::Handle(zone, other.arguments()),
|
| + bound_error,
|
| + space)) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + if (IsFunctionType()) {
|
| + return false;
|
| + }
|
| + return type_cls.TypeTest(test_kind,
|
| + TypeArguments::Handle(zone, arguments()),
|
| + Class::Handle(zone, other.type_class()),
|
| + TypeArguments::Handle(zone, other.arguments()),
|
| + bound_error,
|
| + space);
|
| }
|
|
|
|
|
| @@ -15936,14 +15993,7 @@ void Type::SetIsFinalized() const {
|
| }
|
|
|
|
|
| -void Type::ResetIsFinalized() const {
|
| - ASSERT(IsFinalized());
|
| - set_type_state(RawType::kBeingFinalized);
|
| - SetIsFinalized();
|
| -}
|
| -
|
| -
|
| -void Type::set_is_being_finalized() const {
|
| +void Type::SetIsBeingFinalized() const {
|
| ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
|
| set_type_state(RawType::kBeingFinalized);
|
| }
|
| @@ -15988,8 +16038,10 @@ void Type::set_error(const LanguageError& value) const {
|
| }
|
|
|
|
|
| -void Type::set_is_resolved() const {
|
| +void Type::SetIsResolved() const {
|
| ASSERT(!IsResolved());
|
| + // A Typedef is a FunctionType, not a type.
|
| + ASSERT(!Class::Handle(type_class()).IsTypedefClass());
|
| set_type_state(RawType::kResolved);
|
| }
|
|
|
| @@ -16027,11 +16079,6 @@ RawUnresolvedClass* Type::unresolved_class() const {
|
| }
|
|
|
|
|
| -RawTypeArguments* Type::arguments() const {
|
| - return raw_ptr()->arguments_;
|
| -}
|
| -
|
| -
|
| bool Type::IsInstantiated(TrailPtr trail) const {
|
| if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) {
|
| return true;
|
| @@ -16047,7 +16094,6 @@ bool Type::IsInstantiated(TrailPtr trail) const {
|
| intptr_t len = num_type_args; // Check the full vector of type args.
|
| ASSERT(num_type_args > 0);
|
| // This type is not instantiated if it refers to type parameters.
|
| - // This IsInstantiated() call may be invoked on an unresolved signature type.
|
| // Although this type may still be unresolved, the type parameters it may
|
| // refer to are resolved by definition. We can therefore return the correct
|
| // result even for an unresolved type. We just need to look at all type
|
| @@ -16094,7 +16140,8 @@ RawAbstractType* Type::InstantiateFrom(
|
|
|
| // This uninstantiated type is not modified, as it can be instantiated
|
| // with different instantiators. Allocate a new instantiated version of it.
|
| - instantiated_type = Type::New(cls, TypeArguments::Handle(zone), token_pos());
|
| + instantiated_type =
|
| + Type::New(cls, TypeArguments::Handle(zone), token_pos(), space);
|
| TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
|
| ASSERT(type_arguments.Length() == cls.NumTypeArguments());
|
| if (type_arguments.IsRecursive()) {
|
| @@ -16108,7 +16155,7 @@ RawAbstractType* Type::InstantiateFrom(
|
| if (IsFinalized()) {
|
| instantiated_type.SetIsFinalized();
|
| } else {
|
| - instantiated_type.set_is_resolved();
|
| + instantiated_type.SetIsResolved();
|
| }
|
| // Canonicalization is not part of instantiation.
|
| return instantiated_type.raw();
|
| @@ -16210,9 +16257,9 @@ RawAbstractType* Type::CloneUnfinalized() const {
|
| ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
|
| TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| type_args = type_args.CloneUnfinalized();
|
| - const Class& type_cls = Class::Handle(type_class());
|
| - const Type& clone = Type::Handle(Type::New(type_cls, type_args, token_pos()));
|
| - clone.set_is_resolved();
|
| + const Type& clone = Type::Handle(
|
| + Type::New(Class::Handle(type_class()), type_args, token_pos()));
|
| + clone.SetIsResolved();
|
| return clone.raw();
|
| }
|
|
|
| @@ -16254,13 +16301,14 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
|
| Thread* thread = Thread::Current();
|
| Zone* zone = thread->zone();
|
| Isolate* isolate = thread->isolate();
|
| - Type& type = Type::Handle(zone);
|
| + AbstractType& type = Type::Handle(zone);
|
| const Class& cls = Class::Handle(zone, type_class());
|
| + ASSERT(!cls.IsTypedefClass()); // This type should be a FunctionType.
|
| if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
|
| return Object::dynamic_type().raw();
|
| }
|
| // Fast canonical lookup/registry for simple types.
|
| - if (!cls.IsGeneric()) {
|
| + if (!cls.IsGeneric() && !cls.IsClosureClass()) {
|
| type = cls.CanonicalType();
|
| if (type.IsNull()) {
|
| ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
|
| @@ -16345,36 +16393,6 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
|
| canonical_types = new_canonical_types.raw();
|
| }
|
| canonical_types.SetAt(index, *this);
|
| - if ((index == 1) && cls.IsCanonicalSignatureClass()) {
|
| - canonical_types.SetAt(0, *this); // Also set canonical signature type at 0.
|
| -#ifdef DEBUG
|
| - // Verify that the first canonical type is the signature type by checking
|
| - // that the type argument vector of the canonical type ends with the
|
| - // uninstantiated type parameters of the signature class. Note that these
|
| - // type parameters may be bounded if the super class of the owner class
|
| - // declares bounds.
|
| - // The signature type is finalized during class finalization, before the
|
| - // optimizer may canonicalize instantiated function types of the same
|
| - // signature class.
|
| - // Although the signature class extends class Instance, the type arguments
|
| - // of the super class of the owner class of its signature function will be
|
| - // prepended to the type argument vector during class finalization.
|
| - const TypeArguments& type_params =
|
| - TypeArguments::Handle(zone, cls.type_parameters());
|
| - const intptr_t num_type_params = cls.NumTypeParameters();
|
| - const intptr_t num_type_args = cls.NumTypeArguments();
|
| - AbstractType& type_arg = AbstractType::Handle(zone);
|
| - TypeParameter& type_param = TypeParameter::Handle(zone);
|
| - for (intptr_t i = 0; i < num_type_params; i++) {
|
| - type_arg = type_args.TypeAt(num_type_args - num_type_params + i);
|
| - while (type_arg.IsBoundedType()) {
|
| - type_arg = BoundedType::Cast(type_arg).type();
|
| - }
|
| - type_param ^= type_params.TypeAt(i);
|
| - ASSERT(type_arg.Equals(type_param));
|
| - }
|
| -#endif
|
| - }
|
| ASSERT(IsOld());
|
| ASSERT(type_args.IsNull() || type_args.IsOld());
|
| SetCanonical();
|
| @@ -16491,39 +16509,585 @@ void Type::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| }
|
|
|
|
|
| -bool TypeRef::IsInstantiated(TrailPtr trail) const {
|
| - if (TestAndAddToTrail(&trail)) {
|
| +void FunctionType::SetIsFinalized() const {
|
| + ASSERT(!IsFinalized());
|
| + if (IsInstantiated()) {
|
| + set_type_state(RawFunctionType::kFinalizedInstantiated);
|
| + } else {
|
| + set_type_state(RawFunctionType::kFinalizedUninstantiated);
|
| + }
|
| +}
|
| +
|
| +
|
| +void FunctionType::ResetIsFinalized() const {
|
| + ASSERT(IsFinalized());
|
| + set_type_state(RawFunctionType::kBeingFinalized);
|
| + SetIsFinalized();
|
| +}
|
| +
|
| +
|
| +void FunctionType::SetIsBeingFinalized() const {
|
| + ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
|
| + set_type_state(RawFunctionType::kBeingFinalized);
|
| +}
|
| +
|
| +
|
| +bool FunctionType::IsMalformed() const {
|
| + if (raw_ptr()->error_ == LanguageError::null()) {
|
| + return false;
|
| + }
|
| + const LanguageError& type_error = LanguageError::Handle(error());
|
| + return type_error.kind() == Report::kMalformedType;
|
| +}
|
| +
|
| +
|
| +bool FunctionType::IsMalbounded() const {
|
| + if (!Isolate::Current()->flags().type_checks()) {
|
| + return false;
|
| + }
|
| + if (raw_ptr()->error_ == LanguageError::null()) {
|
| + return false;
|
| + }
|
| + const LanguageError& type_error = LanguageError::Handle(error());
|
| + return type_error.kind() == Report::kMalboundedType;
|
| +}
|
| +
|
| +
|
| +bool FunctionType::IsMalformedOrMalbounded() const {
|
| + if (raw_ptr()->error_ == LanguageError::null()) {
|
| + return false;
|
| + }
|
| + const LanguageError& type_error = LanguageError::Handle(error());
|
| + if (type_error.kind() == Report::kMalformedType) {
|
| return true;
|
| }
|
| - return AbstractType::Handle(type()).IsInstantiated(trail);
|
| + ASSERT(type_error.kind() == Report::kMalboundedType);
|
| + return Isolate::Current()->flags().type_checks();
|
| }
|
|
|
|
|
| -bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| - if (raw() == other.raw()) {
|
| +void FunctionType::set_error(const LanguageError& value) const {
|
| + StorePointer(&raw_ptr()->error_, value.raw());
|
| +}
|
| +
|
| +
|
| +void FunctionType::SetIsResolved() const {
|
| + ASSERT(!IsResolved());
|
| + set_type_state(RawFunctionType::kResolved);
|
| +}
|
| +
|
| +
|
| +bool FunctionType::IsInstantiated(TrailPtr trail) const {
|
| + if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) {
|
| return true;
|
| }
|
| - if (!other.IsAbstractType()) {
|
| + if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated) {
|
| return false;
|
| }
|
| - if (TestAndAddBuddyToTrail(&trail, AbstractType::Cast(other))) {
|
| + if (arguments() == TypeArguments::null()) {
|
| return true;
|
| }
|
| - return AbstractType::Handle(type()).IsEquivalent(other, trail);
|
| + const Class& scope_cls = Class::Handle(scope_class());
|
| + if (!scope_cls.IsGeneric()) {
|
| + ASSERT(scope_cls.IsClosureClass() || scope_cls.IsTypedefClass());
|
| + ASSERT(arguments() == TypeArguments::null());
|
| + return true;
|
| + }
|
| + const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
|
| + const intptr_t num_type_args = scope_cls.NumTypeArguments();
|
| + const intptr_t num_type_params = scope_cls.NumTypeParameters();
|
| + // The vector may be longer than necessary. An empty vector is handled above.
|
| + ASSERT(type_arguments.Length() >= num_type_args);
|
| + return
|
| + (num_type_params == 0) ||
|
| + type_arguments.IsSubvectorInstantiated(num_type_args - num_type_params,
|
| + num_type_params);
|
| }
|
|
|
|
|
| -RawTypeRef* TypeRef::InstantiateFrom(
|
| +RawAbstractType* FunctionType::InstantiateFrom(
|
| const TypeArguments& instantiator_type_arguments,
|
| Error* bound_error,
|
| TrailPtr trail,
|
| Heap::Space space) const {
|
| - TypeRef& instantiated_type_ref = TypeRef::Handle();
|
| - instantiated_type_ref ^= OnlyBuddyInTrail(trail);
|
| - if (!instantiated_type_ref.IsNull()) {
|
| - return instantiated_type_ref.raw();
|
| - }
|
| - AbstractType& ref_type = AbstractType::Handle(type());
|
| + Zone* zone = Thread::Current()->zone();
|
| + ASSERT(IsFinalized() || IsBeingFinalized());
|
| + ASSERT(!IsInstantiated());
|
| + ASSERT(!IsMalformed()); // FunctionType cannot be malformed.
|
| + // Instantiating this type with its own type arguments as instantiator can
|
| + // occur during finalization and bounds checking. Return the type unchanged.
|
| + if (arguments() == instantiator_type_arguments.raw()) {
|
| + return raw();
|
| + }
|
| + // If this type is recursive, we may already be instantiating it.
|
| + FunctionType& instantiated_type = FunctionType::Handle(zone);
|
| + instantiated_type ^= OnlyBuddyInTrail(trail);
|
| + if (!instantiated_type.IsNull()) {
|
| + ASSERT(IsRecursive());
|
| + return instantiated_type.raw();
|
| + }
|
| + // Note that the scope class has to be resolved at this time, but not
|
| + // necessarily finalized yet. We may be checking bounds at compile time or
|
| + // finalizing the type argument vector of a recursive type.
|
| + const Class& cls = Class::Handle(zone, scope_class());
|
| +
|
| + // This uninstantiated type is not modified, as it can be instantiated
|
| + // with different instantiators. Allocate a new instantiated version of it.
|
| + instantiated_type =
|
| + FunctionType::New(cls,
|
| + TypeArguments::Handle(zone),
|
| + Function::Handle(zone, signature()),
|
| + token_pos(),
|
| + space);
|
| + TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
|
| + ASSERT(type_arguments.Length() == cls.NumTypeArguments());
|
| + if (type_arguments.IsRecursive()) {
|
| + AddOnlyBuddyToTrail(&trail, instantiated_type);
|
| + }
|
| + type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
|
| + bound_error,
|
| + trail,
|
| + space);
|
| + instantiated_type.set_arguments(type_arguments);
|
| + if (IsFinalized()) {
|
| + instantiated_type.SetIsFinalized();
|
| + } else {
|
| + instantiated_type.SetIsResolved();
|
| + }
|
| + // Canonicalization is not part of instantiation.
|
| + return instantiated_type.raw();
|
| +}
|
| +
|
| +
|
| +bool FunctionType::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| + ASSERT(!IsNull());
|
| + if (raw() == other.raw()) {
|
| + return true;
|
| + }
|
| + if (!other.IsFunctionType()) {
|
| + return false;
|
| + }
|
| + const FunctionType& other_type = FunctionType::Cast(other);
|
| + ASSERT(IsResolved() && other_type.IsResolved());
|
| + if (IsMalformed() || other_type.IsMalformed()) {
|
| + return false;
|
| + }
|
| + if (scope_class() != other_type.scope_class()) {
|
| + return false;
|
| + }
|
| + if ((arguments() == other_type.arguments()) &&
|
| + (signature() == other_type.signature())) {
|
| + return true;
|
| + }
|
| + if (!IsFinalized() || !other_type.IsFinalized()) {
|
| + return false;
|
| + }
|
| +
|
| + // We do not instantiate the types of the signature. This happens on demand
|
| + // at runtime during a type test.
|
| + // Therefore, equal function types must have equal type arguments.
|
| + Thread* thread = Thread::Current();
|
| + Zone* zone = thread->zone();
|
| + const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| + const TypeArguments& other_type_args = TypeArguments::Handle(
|
| + zone, other_type.arguments());
|
| + if (!type_args.Equals(other_type_args)) {
|
| + return false;
|
| + }
|
| +
|
| + // Type arguments are equal.
|
| + // Equal function types must have equal signature types and equal optional
|
| + // named arguments.
|
| + if (signature() == other_type.signature()) {
|
| + return true;
|
| + }
|
| + const Function& sig_fun = Function::Handle(zone, signature());
|
| + const Function& other_sig_fun = Function::Handle(
|
| + zone, other_type.signature());
|
| +
|
| + // Compare number of function parameters.
|
| + const intptr_t num_fixed_params = sig_fun.num_fixed_parameters();
|
| + const intptr_t other_num_fixed_params = other_sig_fun.num_fixed_parameters();
|
| + if (num_fixed_params != other_num_fixed_params) {
|
| + return false;
|
| + }
|
| + const intptr_t num_opt_pos_params = sig_fun.NumOptionalPositionalParameters();
|
| + const intptr_t other_num_opt_pos_params =
|
| + other_sig_fun.NumOptionalPositionalParameters();
|
| + if (num_opt_pos_params != other_num_opt_pos_params) {
|
| + return false;
|
| + }
|
| + const intptr_t num_opt_named_params = sig_fun.NumOptionalNamedParameters();
|
| + const intptr_t other_num_opt_named_params =
|
| + other_sig_fun.NumOptionalNamedParameters();
|
| + if (num_opt_named_params != other_num_opt_named_params) {
|
| + return false;
|
| + }
|
| + const intptr_t num_ignored_params = sig_fun.NumImplicitParameters();
|
| + const intptr_t other_num_ignored_params =
|
| + other_sig_fun.NumImplicitParameters();
|
| + if (num_ignored_params != other_num_ignored_params) {
|
| + return false;
|
| + }
|
| + AbstractType& param_type = Type::Handle(zone);
|
| + AbstractType& other_param_type = Type::Handle(zone);
|
| + // Check the result type.
|
| + param_type = sig_fun.result_type();
|
| + other_param_type = other_sig_fun.result_type();
|
| + if (!param_type.Equals(other_param_type)) {
|
| + return false;
|
| + }
|
| + // Check the types of all parameters.
|
| + const intptr_t num_params = sig_fun.NumParameters();
|
| + ASSERT(other_sig_fun.NumParameters() == num_params);
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + param_type = sig_fun.ParameterTypeAt(i);
|
| + other_param_type = other_sig_fun.ParameterTypeAt(i);
|
| + if (!param_type.Equals(other_param_type)) {
|
| + return false;
|
| + }
|
| + }
|
| + // Check the names and types of optional named parameters.
|
| + if (num_opt_named_params == 0) {
|
| + return true;
|
| + }
|
| + for (intptr_t i = num_fixed_params; i < num_params; i++) {
|
| + if (sig_fun.ParameterNameAt(i) != other_sig_fun.ParameterNameAt(i)) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool FunctionType::IsRecursive() const {
|
| + return TypeArguments::Handle(arguments()).IsRecursive();
|
| +}
|
| +
|
| +
|
| +RawAbstractType* FunctionType::CloneUnfinalized() const {
|
| + ASSERT(IsResolved());
|
| + if (IsFinalized()) {
|
| + return raw();
|
| + }
|
| + ASSERT(!IsMalformed()); // Malformed types are finalized.
|
| + ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
|
| + TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| + type_args = type_args.CloneUnfinalized();
|
| + const FunctionType& clone = FunctionType::Handle(
|
| + FunctionType::New(Class::Handle(scope_class()),
|
| + type_args,
|
| + Function::Handle(signature()),
|
| + token_pos()));
|
| + clone.SetIsResolved();
|
| + return clone.raw();
|
| +}
|
| +
|
| +
|
| +RawAbstractType* FunctionType::CloneUninstantiated(const Class& new_owner,
|
| + TrailPtr trail) const {
|
| + ASSERT(IsFinalized());
|
| + ASSERT(!IsMalformed());
|
| + if (IsInstantiated()) {
|
| + return raw();
|
| + }
|
| + // We may recursively encounter a type already being cloned, because we clone
|
| + // the upper bounds of its uninstantiated type arguments in the same pass.
|
| + FunctionType& clone = FunctionType::Handle();
|
| + clone ^= OnlyBuddyInTrail(trail);
|
| + if (!clone.IsNull()) {
|
| + return clone.raw();
|
| + }
|
| + clone = FunctionType::New(Class::Handle(scope_class()),
|
| + TypeArguments::Handle(),
|
| + Function::Handle(signature()),
|
| + token_pos());
|
| + TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| + // Upper bounds of uninstantiated type arguments may form a cycle.
|
| + if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
|
| + AddOnlyBuddyToTrail(&trail, clone);
|
| + }
|
| + type_args = type_args.CloneUninstantiated(new_owner, trail);
|
| + clone.set_arguments(type_args);
|
| + clone.SetIsFinalized();
|
| + return clone.raw();
|
| +}
|
| +
|
| +
|
| +RawAbstractType* FunctionType::Canonicalize(TrailPtr trail) const {
|
| + ASSERT(IsFinalized());
|
| + if (IsCanonical() || IsMalformed()) {
|
| + ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
|
| + return this->raw();
|
| + }
|
| + Thread* thread = Thread::Current();
|
| + Zone* zone = thread->zone();
|
| + AbstractType& type = Type::Handle(zone);
|
| + const Class& scope_cls = Class::Handle(zone, type_class());
|
| + Array& canonical_types = Array::Handle(zone);
|
| + canonical_types ^= scope_cls.canonical_types();
|
| + if (canonical_types.IsNull()) {
|
| + canonical_types = empty_array().raw();
|
| + }
|
| + intptr_t length = canonical_types.Length();
|
| + // Linear search to see whether this type is already present in the
|
| + // list of canonicalized types.
|
| + // TODO(asiva): Try to re-factor this lookup code to make sharing
|
| + // easy between the 4 versions of this loop.
|
| + intptr_t index = 1; // Slot 0 is reserved for CanonicalType().
|
| + while (index < length) {
|
| + type ^= canonical_types.At(index);
|
| + if (type.IsNull()) {
|
| + break;
|
| + }
|
| + ASSERT(type.IsFinalized());
|
| + if (this->Equals(type)) {
|
| + ASSERT(type.IsCanonical());
|
| + return type.raw();
|
| + }
|
| + index++;
|
| + }
|
| + // The type was not found in the table. It is not canonical yet.
|
| +
|
| + // Canonicalize the type arguments.
|
| + TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| + // In case the type is first canonicalized at runtime, its type argument
|
| + // vector may be longer than necessary. This is not an issue.
|
| + ASSERT(type_args.IsNull() ||
|
| + (type_args.Length() >= scope_cls.NumTypeArguments()));
|
| + type_args = type_args.Canonicalize(trail);
|
| + set_arguments(type_args);
|
| +
|
| + // Replace the actual function by a signature function.
|
| + const Function& fun = Function::Handle(zone, signature());
|
| + if (!fun.IsSignatureFunction()) {
|
| + Function& sig_fun =
|
| + Function::Handle(zone,
|
| + Function::NewSignatureFunction(scope_cls,
|
| + Token::kNoSourcePos));
|
| + type = fun.result_type();
|
| + type = type.Canonicalize(trail);
|
| + sig_fun.set_result_type(type);
|
| + const intptr_t num_params = fun.NumParameters();
|
| + sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
|
| + sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
|
| + fun.HasOptionalPositionalParameters());
|
| + sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
|
| + Heap::kOld)));
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = fun.ParameterTypeAt(i);
|
| + type = type.Canonicalize(trail);
|
| + sig_fun.SetParameterTypeAt(i, type);
|
| + }
|
| + sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
|
| + set_signature(sig_fun);
|
| + }
|
| +
|
| + // Canonicalizing the type arguments and the signature may have changed the
|
| + // index, may have grown the table, or may even have canonicalized this type.
|
| + canonical_types ^= scope_cls.canonical_types();
|
| + if (canonical_types.IsNull()) {
|
| + canonical_types = empty_array().raw();
|
| + }
|
| + length = canonical_types.Length();
|
| + while (index < length) {
|
| + type ^= canonical_types.At(index);
|
| + if (type.IsNull()) {
|
| + break;
|
| + }
|
| + ASSERT(type.IsFinalized());
|
| + if (this->Equals(type)) {
|
| + ASSERT(type.IsCanonical());
|
| + return type.raw();
|
| + }
|
| + index++;
|
| + }
|
| +
|
| + // The type needs to be added to the list. Grow the list if it is full.
|
| + if (index >= length) {
|
| + ASSERT((index == length) || ((index == 1) && (length == 0)));
|
| + const intptr_t new_length = (length > 64) ?
|
| + (length + 64) :
|
| + ((length == 0) ? 2 : (length * 2));
|
| + const Array& new_canonical_types = Array::Handle(
|
| + zone, Array::Grow(canonical_types, new_length, Heap::kOld));
|
| + scope_cls.set_canonical_types(new_canonical_types);
|
| + canonical_types = new_canonical_types.raw();
|
| + }
|
| + canonical_types.SetAt(index, *this);
|
| + ASSERT(IsOld());
|
| + ASSERT(type_args.IsNull() || type_args.IsOld());
|
| + SetCanonical();
|
| + return this->raw();
|
| +}
|
| +
|
| +
|
| +intptr_t FunctionType::Hash() const {
|
| + ASSERT(IsFinalized());
|
| + uint32_t result = 1;
|
| + if (IsMalformed()) return result;
|
| + result = CombineHashes(result, Class::Handle(scope_class()).id());
|
| + result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
|
| + const Function& sig_fun = Function::Handle(signature());
|
| + AbstractType& type = AbstractType::Handle(sig_fun.result_type());
|
| + result = CombineHashes(result, type.Hash());
|
| + result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
|
| + const intptr_t num_params = sig_fun.NumParameters();
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = sig_fun.ParameterTypeAt(i);
|
| + result = CombineHashes(result, type.Hash());
|
| + }
|
| + if (sig_fun.NumOptionalNamedParameters() > 0) {
|
| + String& param_name = String::Handle();
|
| + for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
|
| + param_name = sig_fun.ParameterNameAt(i);
|
| + result = CombineHashes(result, param_name.Hash());
|
| + }
|
| + }
|
| + return FinalizeHash(result);
|
| +}
|
| +
|
| +
|
| +void FunctionType::set_scope_class(const Class& value) const {
|
| + ASSERT(!value.IsNull());
|
| + StorePointer(&raw_ptr()->scope_class_, value.raw());
|
| +}
|
| +
|
| +
|
| +void FunctionType::set_arguments(const TypeArguments& value) const {
|
| + StorePointer(&raw_ptr()->arguments_, value.raw());
|
| +}
|
| +
|
| +
|
| +void FunctionType::set_signature(const Function& value) const {
|
| + StorePointer(&raw_ptr()->signature_, value.raw());
|
| +}
|
| +
|
| +
|
| +RawFunctionType* FunctionType::New(Heap::Space space) {
|
| + RawObject* raw = Object::Allocate(FunctionType::kClassId,
|
| + FunctionType::InstanceSize(),
|
| + space);
|
| + return reinterpret_cast<RawFunctionType*>(raw);
|
| +}
|
| +
|
| +
|
| +RawFunctionType* FunctionType::New(const Class& clazz,
|
| + const TypeArguments& arguments,
|
| + const Function& signature,
|
| + intptr_t token_pos,
|
| + Heap::Space space) {
|
| + const FunctionType& result = FunctionType::Handle(FunctionType::New(space));
|
| + result.set_scope_class(clazz);
|
| + result.set_arguments(arguments);
|
| + result.set_signature(signature);
|
| + result.set_token_pos(token_pos);
|
| + result.StoreNonPointer(&result.raw_ptr()->type_state_,
|
| + RawFunctionType::kAllocated);
|
| + return result.raw();
|
| +}
|
| +
|
| +
|
| +void FunctionType::set_token_pos(intptr_t token_pos) const {
|
| + ASSERT(!Token::IsClassifying(token_pos));
|
| + StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
|
| +}
|
| +
|
| +
|
| +void FunctionType::set_type_state(int8_t state) const {
|
| + ASSERT((state >= RawFunctionType::kAllocated) &&
|
| + (state <= RawFunctionType::kFinalizedUninstantiated));
|
| + StoreNonPointer(&raw_ptr()->type_state_, state);
|
| +}
|
| +
|
| +
|
| +const char* FunctionType::ToCString() const {
|
| + const char* unresolved = IsResolved() ? "" : "Unresolved ";
|
| + const Class& scope_cls = Class::Handle(scope_class());
|
| + const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
|
| + const Function& signature_function = Function::Handle(signature());
|
| + const String& signature_string = String::Handle(
|
| + signature_function.InstantiatedSignatureFrom(type_arguments,
|
| + kInternalName));
|
| + if (scope_cls.IsClosureClass()) {
|
| + ASSERT(arguments() == TypeArguments::null());
|
| + return OS::SCreate(
|
| + Thread::Current()->zone(),
|
| + "%sFunctionType: %s", unresolved, signature_string.ToCString());
|
| + }
|
| + const char* class_name = String::Handle(scope_cls.Name()).ToCString();
|
| + const char* args_cstr =
|
| + type_arguments.IsNull() ? "null" : type_arguments.ToCString();
|
| + return OS::SCreate(
|
| + Thread::Current()->zone(),
|
| + "%s FunctionType: %s (scope_cls: %s, args: %s)",
|
| + unresolved,
|
| + signature_string.ToCString(),
|
| + class_name,
|
| + args_cstr);
|
| +}
|
| +
|
| +
|
| +void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + JSONObject jsobj(stream);
|
| + PrintSharedInstanceJSON(&jsobj, ref);
|
| + jsobj.AddProperty("kind", "FunctionType");
|
| + if (IsCanonical()) {
|
| + const Class& scope_cls = Class::Handle(scope_class());
|
| + intptr_t id = scope_cls.FindCanonicalTypeIndex(*this);
|
| + ASSERT(id >= 0);
|
| + intptr_t cid = scope_cls.id();
|
| + jsobj.AddFixedServiceId("classes/%" Pd "/types/%" Pd "", cid, id);
|
| + jsobj.AddProperty("scopeClass", scope_cls);
|
| + } else {
|
| + jsobj.AddServiceId(*this);
|
| + }
|
| + const String& user_name = String::Handle(PrettyName());
|
| + const String& vm_name = String::Handle(Name());
|
| + AddNameProperties(&jsobj, user_name, vm_name);
|
| + if (ref) {
|
| + return;
|
| + }
|
| + const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
|
| + if (!typeArgs.IsNull()) {
|
| + jsobj.AddProperty("typeArguments", typeArgs);
|
| + }
|
| +}
|
| +
|
| +
|
| +bool TypeRef::IsInstantiated(TrailPtr trail) const {
|
| + if (TestAndAddToTrail(&trail)) {
|
| + return true;
|
| + }
|
| + return AbstractType::Handle(type()).IsInstantiated(trail);
|
| +}
|
| +
|
| +
|
| +bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| + if (raw() == other.raw()) {
|
| + return true;
|
| + }
|
| + if (!other.IsAbstractType()) {
|
| + return false;
|
| + }
|
| + if (TestAndAddBuddyToTrail(&trail, AbstractType::Cast(other))) {
|
| + return true;
|
| + }
|
| + return AbstractType::Handle(type()).IsEquivalent(other, trail);
|
| +}
|
| +
|
| +
|
| +RawTypeRef* TypeRef::InstantiateFrom(
|
| + const TypeArguments& instantiator_type_arguments,
|
| + Error* bound_error,
|
| + TrailPtr trail,
|
| + Heap::Space space) const {
|
| + TypeRef& instantiated_type_ref = TypeRef::Handle();
|
| + instantiated_type_ref ^= OnlyBuddyInTrail(trail);
|
| + if (!instantiated_type_ref.IsNull()) {
|
| + return instantiated_type_ref.raw();
|
| + }
|
| + AbstractType& ref_type = AbstractType::Handle(type());
|
| ASSERT(!ref_type.IsTypeRef());
|
| AbstractType& instantiated_ref_type = AbstractType::Handle();
|
| instantiated_ref_type = ref_type.InstantiateFrom(
|
| @@ -16554,7 +17118,7 @@ RawTypeRef* TypeRef::CloneUninstantiated(const Class& new_owner,
|
|
|
|
|
| void TypeRef::set_type(const AbstractType& value) const {
|
| - ASSERT(value.HasResolvedTypeClass());
|
| + ASSERT(value.IsFunctionType() || value.HasResolvedTypeClass());
|
| ASSERT(!value.IsTypeRef());
|
| StorePointer(&raw_ptr()->type_, value.raw());
|
| }
|
| @@ -16666,7 +17230,7 @@ void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| }
|
|
|
|
|
| -void TypeParameter::set_is_finalized() const {
|
| +void TypeParameter::SetIsFinalized() const {
|
| ASSERT(!IsFinalized());
|
| set_type_state(RawTypeParameter::kFinalizedUninstantiated);
|
| }
|
| @@ -16816,7 +17380,7 @@ RawAbstractType* TypeParameter::CloneUninstantiated(
|
| String::Handle(name()),
|
| upper_bound,
|
| token_pos()));
|
| - clone.set_is_finalized();
|
| + clone.SetIsFinalized();
|
| return clone.raw();
|
| }
|
|
|
| @@ -21493,8 +22057,8 @@ void SendPort::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| }
|
|
|
|
|
| -const char* Closure::ToCString(const Instance& closure) {
|
| - const Function& fun = Function::Handle(Closure::function(closure));
|
| +const char* Closure::ToCString() const {
|
| + const Function& fun = Function::Handle(function());
|
| const bool is_implicit_closure = fun.IsImplicitClosureFunction();
|
| const char* fun_sig = String::Handle(fun.UserVisibleSignature()).ToCString();
|
| const char* from = is_implicit_closure ? " from " : "";
|
| @@ -21504,23 +22068,36 @@ const char* Closure::ToCString(const Instance& closure) {
|
| }
|
|
|
|
|
| -RawInstance* Closure::New(const Function& function,
|
| - const Context& context,
|
| - Heap::Space space) {
|
| - const Class& cls = Class::Handle(function.signature_class());
|
| - ASSERT(cls.instance_size() == Closure::InstanceSize());
|
| - Instance& result = Instance::Handle();
|
| +void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| + Instance::PrintJSONImpl(stream, ref);
|
| +}
|
| +
|
| +
|
| +RawClosure* Closure::New(const Function& function,
|
| + const Context& context,
|
| + Heap::Space space) {
|
| + Closure& result = Closure::Handle();
|
| {
|
| - RawObject* raw = Object::Allocate(cls.id(), Closure::InstanceSize(), space);
|
| + RawObject* raw = Object::Allocate(Closure::kClassId,
|
| + Closure::InstanceSize(),
|
| + space);
|
| NoSafepointScope no_safepoint;
|
| result ^= raw;
|
| + result.StorePointer(&result.raw_ptr()->function_, function.raw());
|
| + result.StorePointer(&result.raw_ptr()->context_, context.raw());
|
| }
|
| - Closure::set_function(result, function);
|
| - Closure::set_context(result, context);
|
| return result.raw();
|
| }
|
|
|
|
|
| +RawClosure* Closure::New() {
|
| + RawObject* raw = Object::Allocate(Closure::kClassId,
|
| + Closure::InstanceSize(),
|
| + Heap::kOld);
|
| + return reinterpret_cast<RawClosure*>(raw);
|
| +}
|
| +
|
| +
|
| intptr_t Stacktrace::Length() const {
|
| const Array& code_array = Array::Handle(raw_ptr()->code_array_);
|
| return code_array.Length();
|
|
|