[VM/runtime] Decouple representation of function signatures from Function objects.

This fixes issue https://github.com/dart-lang/sdk/issues/43088

This CL improves on https://dart-review.googlesource.com/c/sdk/+/166920 by keeping the names of type parameters.

See go/dart-vm-signatures for motivation for this change.

TEST=existing suites

Change-Id: Ia82f1d322f72d07b2fb253cf914f9b868025c71e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176981
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Regis Crelier 2021-01-07 23:45:37 +00:00 committed by Régis Crelier
parent 5c174c8d8c
commit b3bca1821c
113 changed files with 3720 additions and 2982 deletions

View file

@ -248,8 +248,7 @@ DEFINE_NATIVE_ENTRY(Ffi_nativeCallbackFunction, 1, 2) {
arguments->NativeArgAt(1));
ASSERT(type_arg.IsInstantiated() && type_arg.IsFunctionType());
const Function& native_signature =
Function::Handle(zone, Type::Cast(type_arg).signature());
const FunctionType& native_signature = FunctionType::Cast(type_arg);
Function& func = Function::Handle(zone, closure.function());
// The FE verifies that the target of a 'fromFunction' is a static method, so

View file

@ -94,15 +94,16 @@ static void EnsureConstructorsAreCompiled(const Function& func) {
}
static InstancePtr CreateParameterMirrorList(const Function& func,
const FunctionType& signature,
const Instance& owner_mirror) {
HANDLESCOPE(Thread::Current());
const intptr_t implicit_param_count = func.NumImplicitParameters();
const intptr_t implicit_param_count = signature.num_implicit_parameters();
const intptr_t non_implicit_param_count =
func.NumParameters() - implicit_param_count;
signature.NumParameters() - implicit_param_count;
const intptr_t index_of_first_optional_param =
non_implicit_param_count - func.NumOptionalParameters();
non_implicit_param_count - signature.NumOptionalParameters();
const intptr_t index_of_first_named_param =
non_implicit_param_count - func.NumOptionalNamedParameters();
non_implicit_param_count - signature.NumOptionalNamedParameters();
const Array& results = Array::Handle(Array::New(non_implicit_param_count));
const Array& args = Array::Handle(Array::New(9));
@ -116,23 +117,18 @@ static InstancePtr CreateParameterMirrorList(const Function& func,
// We force compilation of constructors to ensure the types of initializing
// formals have been corrected. We do not force the compilation of all types
// of functions because some have no body, e.g. signature functions.
EnsureConstructorsAreCompiled(func);
if (!func.IsNull()) {
EnsureConstructorsAreCompiled(func);
}
bool has_extra_parameter_info = true;
if (non_implicit_param_count == 0) {
has_extra_parameter_info = false;
}
if (func.IsImplicitConstructor()) {
if (func.IsNull() || func.IsImplicitConstructor()) {
// This covers the default constructor and forwarding constructors.
has_extra_parameter_info = false;
}
if (func.IsSignatureFunction() &&
(func.token_pos() == TokenPosition::kNoSource)) {
// Signature functions (except those describing typedefs) get canonicalized,
// hence do not have a token position, and therefore cannot be reparsed.
has_extra_parameter_info = false;
}
Array& param_descriptor = Array::Handle();
if (has_extra_parameter_info) {
// Reparse the function for the following information:
@ -149,7 +145,7 @@ static InstancePtr CreateParameterMirrorList(const Function& func,
(Parser::kParameterEntrySize * non_implicit_param_count));
}
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(signature)));
args.SetAt(2, owner_mirror);
if (!has_extra_parameter_info) {
@ -160,7 +156,11 @@ static InstancePtr CreateParameterMirrorList(const Function& func,
for (intptr_t i = 0; i < non_implicit_param_count; i++) {
pos = Smi::New(i);
name = func.ParameterNameAt(implicit_param_count + i);
if (!func.IsNull()) {
name = func.ParameterNameAt(implicit_param_count + i);
} else {
name = signature.ParameterNameAt(implicit_param_count + i);
}
if (has_extra_parameter_info) {
is_final ^= param_descriptor.At(i * Parser::kParameterEntrySize +
Parser::kParameterIsFinalOffset);
@ -217,27 +217,14 @@ static InstancePtr CreateTypeVariableList(const Class& cls) {
return result.raw();
}
static InstancePtr CreateTypedefMirror(const Class& cls,
const AbstractType& type,
const Bool& is_declaration,
const Instance& owner_mirror) {
const Array& args = Array::Handle(Array::New(6));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
args.SetAt(2, String::Handle(cls.Name()));
args.SetAt(3, Bool::Get(cls.IsGeneric()));
args.SetAt(4, cls.IsGeneric() ? is_declaration : Bool::False());
args.SetAt(5, owner_mirror);
return CreateMirror(Symbols::_TypedefMirror(), args);
}
static InstancePtr CreateFunctionTypeMirror(const AbstractType& type) {
ASSERT(type.IsFunctionType());
const Class& cls = Class::Handle(Type::Cast(type).type_class());
const Function& func = Function::Handle(Type::Cast(type).signature());
const Class& closure_class =
Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
const FunctionType& sig = FunctionType::Cast(type);
const Array& args = Array::Handle(Array::New(3));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, MirrorReference::Handle(MirrorReference::New(func)));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(closure_class)));
args.SetAt(1, MirrorReference::Handle(MirrorReference::New(sig)));
args.SetAt(2, type);
return CreateMirror(Symbols::_FunctionTypeMirror(), args);
}
@ -318,11 +305,7 @@ static InstancePtr CreateClassMirror(const Class& cls,
ASSERT(!cls.IsNeverClass());
ASSERT(!type.IsNull());
ASSERT(type.IsFinalized());
if (cls.IsTypedefClass()) {
return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
}
ASSERT(type.IsCanonical());
const Array& args = Array::Handle(Array::New(9));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
@ -534,16 +517,10 @@ static InstancePtr CreateTypeMirror(const AbstractType& type) {
return CreateTypeMirror(ref_type);
}
ASSERT(type.IsFinalized());
ASSERT(type.IsCanonical() || type.IsTypeParameter());
ASSERT(type.IsCanonical());
if (type.IsFunctionType()) {
const Class& scope_class = Class::Handle(Type::Cast(type).type_class());
if (scope_class.IsTypedefClass()) {
return CreateTypedefMirror(scope_class, type, Bool::False(),
Object::null_instance());
} else {
return CreateFunctionTypeMirror(type);
}
return CreateFunctionTypeMirror(type);
}
if (type.HasTypeClass()) {
const Class& cls = Class::Handle(type.type_class());
@ -564,17 +541,19 @@ static InstancePtr CreateTypeMirror(const AbstractType& type) {
// TODO(regis): Until mirrors reflect nullability, force kLegacy, except for
// Null type, which should remain nullable.
if (!type.IsNullType()) {
const Type& legacy_type = Type::Handle(
Type& legacy_type = Type::Handle(
Type::Cast(type).ToNullability(Nullability::kLegacy, Heap::kOld));
legacy_type ^= legacy_type.Canonicalize(Thread::Current(), nullptr);
return CreateClassMirror(cls, legacy_type, Bool::False(),
Object::null_instance());
}
return CreateClassMirror(cls, type, Bool::False(), Object::null_instance());
} else if (type.IsTypeParameter()) {
// TODO(regis): Until mirrors reflect nullability, force kLegacy.
const TypeParameter& legacy_type =
TypeParameter& legacy_type =
TypeParameter::Handle(TypeParameter::Cast(type).ToNullability(
Nullability::kLegacy, Heap::kOld));
legacy_type ^= legacy_type.Canonicalize(Thread::Current(), nullptr);
return CreateTypeVariableMirror(legacy_type, Object::null_instance());
}
UNREACHABLE();
@ -631,13 +610,13 @@ static AbstractTypePtr InstantiateType(const AbstractType& type,
// Generic function type parameters are not reified, but mapped to dynamic,
// i.e. all function type parameters are free with a null vector.
ASSERT(type.IsFinalized());
ASSERT(type.IsCanonical() || type.IsTypeParameter());
ASSERT(type.IsCanonical());
if (type.IsInstantiated()) {
return type.Canonicalize(Thread::Current(), nullptr);
}
TypeArguments& instantiator_type_args = TypeArguments::Handle();
if (!instantiator.IsNull()) {
if (!instantiator.IsNull() && instantiator.IsType()) {
ASSERT(instantiator.IsFinalized());
instantiator_type_args = instantiator.arguments();
}
@ -763,11 +742,12 @@ DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 0, 1) {
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalClassMirror, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(type.IsFinalized());
ASSERT(type.HasTypeClass());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
ASSERT(!cls.IsNull());
if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsNeverClass() ||
cls.IsTypedefClass()) {
if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsNeverClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
@ -785,8 +765,10 @@ DEFINE_NATIVE_ENTRY(Mirrors_instantiateGenericType, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
ASSERT(type.HasTypeClass());
const Class& clz = Class::Handle(type.type_class());
const Class& clz = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
if (!clz.IsGeneric()) {
const Array& error_args = Array::Handle(Array::New(3));
error_args.SetAt(0, type);
@ -826,8 +808,7 @@ DEFINE_NATIVE_ENTRY(Mirrors_instantiateGenericType, 0, 2) {
type_args_obj.SetTypeAt(i, type_arg);
}
Type& instantiated_type =
Type::Handle(Type::New(clz, type_args_obj, TokenPosition::kNoSource));
Type& instantiated_type = Type::Handle(Type::New(clz, type_args_obj));
instantiated_type ^= ClassFinalizer::FinalizeType(instantiated_type);
return instantiated_type.raw();
}
@ -863,7 +844,7 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 0, 1) {
if (decl.IsClass()) {
klass ^= decl.raw();
library = klass.library();
} else if (decl.IsFunction() && !Function::Cast(decl).IsSignatureFunction()) {
} else if (decl.IsFunction()) {
klass = Function::Cast(decl).origin();
library = klass.library();
} else if (decl.IsField()) {
@ -872,12 +853,8 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 0, 1) {
} else if (decl.IsLibrary()) {
library ^= decl.raw();
} else if (decl.IsTypeParameter()) {
if (TypeParameter::Cast(decl).IsFunctionTypeParameter()) {
// TODO(regis): Fully support generic functions.
return Object::empty_array().raw();
}
klass = TypeParameter::Cast(decl).parameterized_class();
library = klass.library();
// There is no reference from a canonical type parameter to its declaration.
return Object::empty_array().raw();
} else {
return Object::empty_array().raw();
}
@ -892,26 +869,29 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 0, 1) {
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_call_method, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner_mirror,
arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
// TODO(rmacnak): Return get:call() method on class _Closure instead?
// This now returns the result of invoking that call getter.
const Function& func = Function::Handle(ref.GetFunctionReferent());
ASSERT(!func.IsNull());
return CreateMethodMirror(func, owner_mirror, AbstractType::Handle());
// Return get:call() method on class _Closure.
const auto& getter_name = Symbols::GetCall();
const Class& closure_class =
Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
const Function& get_call = Function::Handle(
Resolver::ResolveDynamicAnyArgs(zone, closure_class, getter_name,
/*allow_add=*/false));
ASSERT(!get_call.IsNull());
return CreateMethodMirror(get_call, owner_mirror, AbstractType::Handle());
}
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_parameters, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Function& func = Function::Handle(ref.GetFunctionReferent());
return CreateParameterMirrorList(func, owner);
const FunctionType& sig = FunctionType::Handle(ref.GetFunctionTypeReferent());
return CreateParameterMirrorList(Object::null_function(), sig, owner);
}
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Function& func = Function::Handle(ref.GetFunctionReferent());
ASSERT(!func.IsNull());
AbstractType& type = AbstractType::Handle(func.result_type());
const FunctionType& sig = FunctionType::Handle(ref.GetFunctionTypeReferent());
ASSERT(!sig.IsNull());
AbstractType& type = AbstractType::Handle(sig.result_type());
// Signatures of function types are instantiated, but not canonical.
return type.Canonicalize(thread, nullptr);
}
@ -927,7 +907,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_libraryUri, 0, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
ASSERT(super_type.IsNull() || super_type.IsFinalized());
return super_type.raw();
@ -936,7 +919,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 0, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
return InstantiateType(super_type, type);
}
@ -944,7 +930,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 0, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
@ -956,7 +945,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 0, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
@ -978,7 +970,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 0, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_mixin, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
AbstractType& mixin_type = AbstractType::Handle();
if (cls.is_transformed_mixin_application()) {
const Array& interfaces = Array::Handle(cls.interfaces());
@ -993,7 +988,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_mixin_instantiated, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, instantiator,
arguments->NativeArgAt(1));
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
AbstractType& mixin_type = AbstractType::Handle();
if (cls.is_transformed_mixin_application()) {
const Array& interfaces = Array::Handle(cls.interfaces());
@ -1157,7 +1155,10 @@ DEFINE_NATIVE_ENTRY(ClassMirror_type_variables, 0, 1) {
DEFINE_NATIVE_ENTRY(ClassMirror_type_arguments, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
const Class& cls = Class::Handle(type.type_class());
const Class& cls = Class::Handle(
type.IsFunctionType()
? IsolateGroup::Current()->object_store()->closure_class()
: type.type_class());
const intptr_t num_params = cls.NumTypeParameters();
if (num_params == 0) {
@ -1192,18 +1193,9 @@ DEFINE_NATIVE_ENTRY(ClassMirror_type_arguments, 0, 1) {
}
DEFINE_NATIVE_ENTRY(TypeVariableMirror_owner, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
Class& owner = Class::Handle(param.parameterized_class());
AbstractType& type = AbstractType::Handle();
if (owner.IsNull()) {
// TODO(regis): Fully support generic functions. For now, reify function
// type parameters to dynamic and map their function owner to Null class.
ASSERT(param.IsFunctionTypeParameter());
type = Type::NullType();
owner = type.type_class();
} else {
type = owner.DeclarationType();
}
// Type parameters do not have a reference to their owner anymore.
const AbstractType& type = AbstractType::Handle(Type::NullType());
Class& owner = Class::Handle(type.type_class());
return CreateClassMirror(owner, type,
Bool::True(), // is_declaration
Instance::null_instance());
@ -1214,16 +1206,6 @@ DEFINE_NATIVE_ENTRY(TypeVariableMirror_upper_bound, 0, 1) {
return param.bound();
}
DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
ASSERT(type.IsFunctionType());
const Class& cls = Class::Handle(type.type_class());
ASSERT(cls.IsTypedefClass());
return CreateTypedefMirror(cls, AbstractType::Handle(cls.DeclarationType()),
Bool::True(), // is_declaration
Object::null_instance());
}
DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 0, 5) {
// Argument 0 is the mirror, which is unused by the native. It exists
// because this native is an instance method in order to be polymorphic
@ -1292,7 +1274,7 @@ DEFINE_NATIVE_ENTRY(ClosureMirror_function, 0, 1) {
// function_type_arguments.
const Class& cls = Class::Handle(
IsolateGroup::Current()->object_store()->object_class());
instantiator = Type::New(cls, arguments, TokenPosition::kNoSource);
instantiator = Type::New(cls, arguments);
instantiator.SetIsFinalized();
}
return CreateMethodMirror(function, Instance::null_instance(),
@ -1533,7 +1515,8 @@ DEFINE_NATIVE_ENTRY(MethodMirror_parameters, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Function& func = Function::Handle(ref.GetFunctionReferent());
return CreateParameterMirrorList(func, owner);
const FunctionType& sig = FunctionType::Handle(func.signature());
return CreateParameterMirrorList(func, sig, owner);
}
DEFINE_NATIVE_ENTRY(MethodMirror_return_type, 0, 2) {
@ -1581,7 +1564,7 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_location, 0, 1) {
if (decl.IsFunction()) {
const Function& func = Function::Cast(decl);
if (func.IsImplicitConstructor() || func.IsSignatureFunction()) {
if (func.IsImplicitConstructor()) {
// These are synthetic methods; they have no source.
return Instance::null();
}
@ -1589,8 +1572,7 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_location, 0, 1) {
token_pos = func.token_pos();
} else if (decl.IsClass()) {
const Class& cls = Class::Cast(decl);
const bool is_typedef = cls.IsTypedefClass();
if (cls.is_synthesized_class() && !is_typedef && !cls.is_enum_class()) {
if (cls.is_synthesized_class() && !cls.is_enum_class()) {
return Instance::null(); // Synthetic.
}
script = cls.script();
@ -1600,14 +1582,7 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_location, 0, 1) {
script = field.Script();
token_pos = field.token_pos();
} else if (decl.IsTypeParameter()) {
const TypeParameter& type_var = TypeParameter::Cast(decl);
if (type_var.IsFunctionTypeParameter()) {
// TODO(regis): Support generic functions.
return Instance::null();
}
const Class& owner = Class::Handle(zone, type_var.parameterized_class());
script = owner.script();
token_pos = type_var.token_pos();
return Instance::null();
} else if (decl.IsLibrary()) {
const Library& lib = Library::Cast(decl);
if (lib.raw() == Library::NativeWrappersLibrary()) {
@ -1634,25 +1609,14 @@ DEFINE_NATIVE_ENTRY(DeclarationMirror_location, 0, 1) {
return CreateSourceLocation(uri, from_line, from_col);
}
DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
ASSERT(type.IsFunctionType());
const Class& cls = Class::Handle(type.type_class());
ASSERT(cls.IsTypedefClass());
const Function& sig_func = Function::Handle(cls.signature_function());
Type& referent_type = Type::Handle(sig_func.SignatureType());
ASSERT(cls.raw() == referent_type.type_class());
referent_type ^= InstantiateType(referent_type, type);
return CreateFunctionTypeMirror(referent_type);
}
DEFINE_NATIVE_ENTRY(ParameterMirror_type, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, pos, arguments->NativeArgAt(1));
GET_NATIVE_ARGUMENT(AbstractType, instantiator, arguments->NativeArgAt(2));
const Function& func = Function::Handle(ref.GetFunctionReferent());
AbstractType& type = AbstractType::Handle(
func.ParameterTypeAt(func.NumImplicitParameters() + pos.Value()));
const FunctionType& signature =
FunctionType::Handle(ref.GetFunctionTypeReferent());
AbstractType& type = AbstractType::Handle(signature.ParameterTypeAt(
signature.num_implicit_parameters() + pos.Value()));
type = type.Canonicalize(
thread, nullptr); // Instantiated signatures are not canonical.
return InstantiateType(type, instantiator);

View file

@ -81,6 +81,8 @@ DEFINE_NATIVE_ENTRY(Object_runtimeType, 0, 1) {
return Type::IntType();
} else if (instance.IsDouble()) {
return Type::Double();
} else if (instance.IsType() || instance.IsFunctionType()) {
return Type::DartTypeType();
}
return instance.GetType(Heap::kNew);
}
@ -97,8 +99,10 @@ DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
if (left_cid != right_cid) {
if (IsIntegerClassId(left_cid)) {
return Bool::Get(IsIntegerClassId(right_cid)).raw();
} else if (IsStringClassId(right_cid)) {
} else if (IsStringClassId(left_cid)) {
return Bool::Get(IsStringClassId(right_cid)).raw();
} else if (IsTypeClassId(left_cid)) {
return Bool::Get(IsTypeClassId(right_cid)).raw();
} else {
return Bool::False().raw();
}
@ -198,6 +202,26 @@ DEFINE_NATIVE_ENTRY(Type_equality, 0, 2) {
return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).raw();
}
DEFINE_NATIVE_ENTRY(FunctionType_getHashCode, 0, 1) {
const FunctionType& type =
FunctionType::CheckedHandle(zone, arguments->NativeArgAt(0));
intptr_t hash_val = type.Hash();
ASSERT(hash_val > 0);
ASSERT(Smi::IsValid(hash_val));
return Smi::New(hash_val);
}
DEFINE_NATIVE_ENTRY(FunctionType_equality, 0, 2) {
const FunctionType& type =
FunctionType::CheckedHandle(zone, arguments->NativeArgAt(0));
const Instance& other =
Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
if (type.raw() == other.raw()) {
return Bool::True().raw();
}
return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).raw();
}
DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 0, 1) {
const LibraryPrefix& prefix =
LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0));

View file

@ -424,8 +424,6 @@ class FunctionViewElement extends CustomElement implements Renderable {
return 'stub';
case M.FunctionKind.tag:
return 'tag';
case M.FunctionKind.signatureFunction:
return 'signature function';
case M.FunctionKind.dynamicInvocationForwarder:
return 'dynamic invocation forwarder';
}

View file

@ -125,6 +125,7 @@ class InstanceRefElement extends CustomElement implements Renderable {
_instance.valueAsString!, _instance.valueAsStringIsTruncated!)
];
case M.InstanceKind.type:
case M.InstanceKind.functionType:
case M.InstanceKind.typeRef:
case M.InstanceKind.typeParameter:
return [

View file

@ -15,7 +15,7 @@ abstract class FieldRef extends ObjectRef {
/// The declared type of this field.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
InstanceRef? get declaredType;
/// Is this field const?

View file

@ -24,7 +24,6 @@ enum FunctionKind {
ffiTrampoline,
stub,
tag,
signatureFunction,
dynamicInvocationForwarder
}

View file

@ -115,6 +115,9 @@ enum InstanceKind {
/// An instance of the Dart class Type.
type,
/// An instance of the Dart class FunctionType.
functionType,
/// An instance of the Dart class TypeParameter.
typeParameter,
@ -170,6 +173,7 @@ bool isAbstractType(InstanceKind? kind) {
}
switch (kind) {
case InstanceKind.type:
case InstanceKind.functionType:
case InstanceKind.typeRef:
case InstanceKind.typeParameter:
return true;
@ -387,7 +391,7 @@ abstract class Instance extends Object implements InstanceRef {
/// [optional] The referent of a TypeRef instance.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
///
/// Provided for instance kinds:
/// TypeRef
@ -396,7 +400,7 @@ abstract class Instance extends Object implements InstanceRef {
/// [optional] The bound of a TypeParameter.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
///
/// Provided for instance kinds:
/// TypeParameter

View file

@ -13,6 +13,6 @@ abstract class TypeArguments extends Object implements TypeArgumentsRef {
/// A list of types.
///
/// The value will always be one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
Iterable<InstanceRef>? get types;
}

View file

@ -2747,6 +2747,8 @@ M.InstanceKind stringToInstanceKind(String s) {
return M.InstanceKind.weakProperty;
case 'Type':
return M.InstanceKind.type;
case 'FunctionType':
return M.InstanceKind.functionType;
case 'TypeParameter':
return M.InstanceKind.typeParameter;
case 'TypeRef':
@ -3118,8 +3120,6 @@ M.FunctionKind stringToFunctionKind(String value) {
return M.FunctionKind.stub;
case 'Tag':
return M.FunctionKind.tag;
case 'SignatureFunction':
return M.FunctionKind.signatureFunction;
case 'DynamicInvocationForwarder':
return M.FunctionKind.dynamicInvocationForwarder;
}

View file

@ -422,8 +422,6 @@ class FunctionViewElement extends CustomElement implements Renderable {
return 'stub';
case M.FunctionKind.tag:
return 'tag';
case M.FunctionKind.signatureFunction:
return 'signature function';
case M.FunctionKind.dynamicInvocationForwarder:
return 'dynamic invocation forwarder';
}

View file

@ -124,6 +124,7 @@ class InstanceRefElement extends CustomElement implements Renderable {
_instance.valueAsString, _instance.valueAsStringIsTruncated)
];
case M.InstanceKind.type:
case M.InstanceKind.functionType:
case M.InstanceKind.typeRef:
case M.InstanceKind.typeParameter:
return [

View file

@ -15,7 +15,7 @@ abstract class FieldRef extends ObjectRef {
/// The declared type of this field.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
InstanceRef get declaredType;
/// Is this field const?

View file

@ -24,7 +24,6 @@ enum FunctionKind {
ffiTrampoline,
stub,
tag,
signatureFunction,
dynamicInvocationForwarder
}

View file

@ -115,6 +115,9 @@ enum InstanceKind {
/// An instance of the Dart class Type.
type,
/// An instance of the Dart class FunctionType.
functionType,
/// An instance of the Dart class TypeParameter.
typeParameter,
@ -161,6 +164,7 @@ bool isSimdValue(InstanceKind kind) {
bool isAbstractType(InstanceKind kind) {
switch (kind) {
case InstanceKind.type:
case InstanceKind.functionType:
case InstanceKind.typeRef:
case InstanceKind.typeParameter:
return true;
@ -378,7 +382,7 @@ abstract class Instance extends Object implements InstanceRef {
/// [optional] The referent of a TypeRef instance.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
///
/// Provided for instance kinds:
/// TypeRef
@ -387,7 +391,7 @@ abstract class Instance extends Object implements InstanceRef {
/// [optional] The bound of a TypeParameter.
///
/// The value will always be of one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
///
/// Provided for instance kinds:
/// TypeParameter

View file

@ -13,6 +13,6 @@ abstract class TypeArguments extends Object implements TypeArgumentsRef {
/// A list of types.
///
/// The value will always be one of the kinds:
/// Type, TypeRef, TypeParameter.
/// Type, FunctionType, TypeRef, TypeParameter.
Iterable<InstanceRef> get types;
}

View file

@ -2756,6 +2756,8 @@ M.InstanceKind stringToInstanceKind(String s) {
return M.InstanceKind.weakProperty;
case 'Type':
return M.InstanceKind.type;
case 'FunctionType':
return M.InstanceKind.functionType;
case 'TypeParameter':
return M.InstanceKind.typeParameter;
case 'TypeRef':
@ -3131,8 +3133,6 @@ M.FunctionKind stringToFunctionKind(String value) {
return M.FunctionKind.stub;
case 'Tag':
return M.FunctionKind.tag;
case 'SignatureFunction':
return M.FunctionKind.signatureFunction;
case 'DynamicInvocationForwarder':
return M.FunctionKind.dynamicInvocationForwarder;
}

View file

@ -22,7 +22,7 @@ main(args) async {
Expect.equals(
await caughtErrorCompleter.future,
"Invalid argument(s): Illegal argument in isolate message : "
"(function types are not supported yet)");
"(object is a FunctionType)");
}
Future<void> genericFunc<T>() async {
@ -36,7 +36,7 @@ main(args) async {
Expect.equals(
await caughtErrorCompleter.future,
"Invalid argument(s): Illegal argument in isolate message : "
"(function types are not supported yet)");
"(object is a FunctionType)");
}
await genericFunc<int>();

View file

@ -22,7 +22,7 @@ main(args) async {
Expect.equals(
await caughtErrorCompleter.future,
"Invalid argument(s): Illegal argument in isolate message : "
"(function types are not supported yet)");
"(object is a FunctionType)");
}
void genericFunc<T>() async {
@ -36,7 +36,7 @@ main(args) async {
Expect.equals(
await caughtErrorCompleter.future,
"Invalid argument(s): Illegal argument in isolate message : "
"(function types are not supported yet)");
"(object is a FunctionType)");
}
await genericFunc<int>();

View file

@ -30,6 +30,8 @@ namespace dart {
V(AbstractType_toString, 1) \
V(Type_getHashCode, 1) \
V(Type_equality, 2) \
V(FunctionType_getHashCode, 1) \
V(FunctionType_equality, 2) \
V(LibraryPrefix_isLoaded, 1) \
V(LibraryPrefix_setLoaded, 1) \
V(LibraryPrefix_loadingUnit, 1) \
@ -469,8 +471,6 @@ namespace dart {
V(MethodMirror_return_type, 2) \
V(MethodMirror_source, 1) \
V(ParameterMirror_type, 3) \
V(TypedefMirror_referent, 1) \
V(TypedefMirror_declaration, 1) \
V(VariableMirror_type, 2)
class BootstrapNatives : public AllStatic {

View file

@ -45,9 +45,12 @@ bool MetadataMapTraits::IsMatch(const Object& a, const Object& b) {
if (!name_a.Equals(name_b)) {
return false;
}
const Object& owner_a = Object::Handle(TypeParameter::Cast(a).Owner());
const Object& owner_b = Object::Handle(TypeParameter::Cast(b).Owner());
return IsMatch(owner_a, owner_b);
if (TypeParameter::Cast(a).index() != TypeParameter::Cast(b).index() ||
TypeParameter::Cast(a).base() != TypeParameter::Cast(b).base()) {
return false;
}
return TypeParameter::Cast(a).parameterized_class_id() ==
TypeParameter::Cast(b).parameterized_class_id();
}
return a.raw() == b.raw();
}

View file

@ -172,6 +172,45 @@ class CanonicalTypeTraits {
};
typedef UnorderedHashSet<CanonicalTypeTraits> CanonicalTypeSet;
class CanonicalFunctionTypeKey {
public:
explicit CanonicalFunctionTypeKey(const FunctionType& key) : key_(key) {}
bool Matches(const FunctionType& arg) const { return key_.Equals(arg); }
uword Hash() const { return key_.Hash(); }
const FunctionType& key_;
private:
DISALLOW_ALLOCATION();
};
// Traits for looking up Canonical FunctionType based on its hash.
class CanonicalFunctionTypeTraits {
public:
static const char* Name() { return "CanonicalFunctionTypeTraits"; }
static bool ReportStats() { return false; }
// Called when growing the table.
static bool IsMatch(const Object& a, const Object& b) {
ASSERT(a.IsFunctionType() && b.IsFunctionType());
const FunctionType& arg1 = FunctionType::Cast(a);
const FunctionType& arg2 = FunctionType::Cast(b);
return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
}
static bool IsMatch(const CanonicalFunctionTypeKey& a, const Object& b) {
ASSERT(b.IsFunctionType());
return a.Matches(FunctionType::Cast(b));
}
static uword Hash(const Object& key) {
ASSERT(key.IsFunctionType());
return FunctionType::Cast(key).Hash();
}
static uword Hash(const CanonicalFunctionTypeKey& key) { return key.Hash(); }
static ObjectPtr NewKey(const CanonicalFunctionTypeKey& obj) {
return obj.key_.raw();
}
};
typedef UnorderedHashSet<CanonicalFunctionTypeTraits> CanonicalFunctionTypeSet;
class CanonicalTypeParameterKey {
public:
explicit CanonicalTypeParameterKey(const TypeParameter& key) : key_(key) {}

View file

@ -288,30 +288,24 @@ void ClassFinalizer::VerifyBootstrapClasses() {
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
FinalizationKind finalization) {
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type parameters of '%s'\n",
String::Handle(cls.Name()).ToCString());
THR_Print("%s type parameters of '%s'\n",
String::Handle(cls.Name()).ToCString(),
finalization == kFinalize ? "Finalizing" : "Canonicalizing");
}
// The type parameter bounds are not finalized here.
const intptr_t offset = cls.NumTypeArguments() - cls.NumTypeParameters();
const TypeArguments& type_parameters =
const TypeArguments& type_params =
TypeArguments::Handle(cls.type_parameters());
if (!type_parameters.IsNull()) {
TypeParameter& type_parameter = TypeParameter::Handle();
const intptr_t num_types = type_parameters.Length();
for (intptr_t i = 0; i < num_types; i++) {
type_parameter ^= type_parameters.TypeAt(i);
if (!type_parameter.IsFinalized()) {
ASSERT(type_parameter.index() == i);
type_parameter.set_index(offset + i);
type_parameter.SetIsFinalized();
} else {
ASSERT(type_parameter.index() == offset + i);
if (!type_params.IsNull()) {
const intptr_t num_type_params = type_params.Length();
TypeParameter& type_param = TypeParameter::Handle();
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
if (!type_param.IsBeingFinalized()) {
type_param ^= FinalizeType(type_param, finalization);
type_params.SetTypeAt(i, type_param);
}
// The declaration of a type parameter is canonical.
ASSERT(type_parameter.IsDeclaration());
ASSERT(type_parameter.IsCanonical());
}
}
}
@ -328,6 +322,7 @@ void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
// pending finalization that are mutually recursive with the checked type.
void ClassFinalizer::CheckRecursiveType(const AbstractType& type,
PendingTypes* pending_types) {
ASSERT(!type.IsFunctionType());
ASSERT(pending_types != NULL);
Zone* zone = Thread::Current()->zone();
if (FLAG_trace_type_finalization) {
@ -338,13 +333,7 @@ void ClassFinalizer::CheckRecursiveType(const AbstractType& type,
const TypeArguments& arguments =
TypeArguments::Handle(zone, type.arguments());
// A type can only be recursive via its type arguments.
if (arguments.IsNull()) {
// However, Kernel does not keep the relation between a function type and
// its declaring typedef. Therefore, a typedef-declared function type may
// refer to the still unfinalized typedef via a type in its signature.
ASSERT(type.IsFunctionType());
return;
}
ASSERT(!arguments.IsNull());
const intptr_t num_type_args = arguments.Length();
ASSERT(num_type_args > 0);
ASSERT(num_type_args == type_cls.NumTypeArguments());
@ -416,9 +405,6 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
// Also, the type parameters of the type class must be finalized.
Class& type_class = Class::Handle(zone, type.type_class());
type_class.EnsureDeclarationLoaded();
if (!type_class.is_type_finalized()) {
FinalizeTypeParameters(type_class);
}
// The finalized type argument vector needs num_type_arguments types.
const intptr_t num_type_arguments = type_class.NumTypeArguments();
@ -430,13 +416,6 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
ASSERT(arguments.IsNull() || (arguments.Length() == num_type_parameters));
// Mark the type as being finalized in order to detect self reference and
// postpone bound checking (if required) until after all types in the graph of
// mutually recursive types are finalized.
type.SetIsBeingFinalized();
ASSERT(pending_types != NULL);
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.
@ -471,8 +450,12 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
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(type_arg, kFinalize, pending_types);
if (!type_arg.IsBeingFinalized()) {
type_arg = FinalizeType(type_arg, kFinalize, pending_types);
} else {
ASSERT(type_arg.IsTypeParameter());
// The bound of the type parameter is still being finalized.
}
full_arguments.SetTypeAt(offset + i, type_arg);
}
}
@ -537,7 +520,7 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
TrailPtr trail) {
ASSERT(arguments.Length() >= cls.NumTypeArguments());
if (!cls.is_type_finalized()) {
FinalizeTypeParameters(cls);
FinalizeTypeParameters(cls, kFinalize);
}
AbstractType& super_type = AbstractType::Handle(cls.super_type());
if (!super_type.IsNull()) {
@ -559,14 +542,25 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
super_type_arg = super_type_args.TypeAt(i);
if (!super_type_arg.IsTypeRef()) {
if (super_type_arg.IsBeingFinalized()) {
ASSERT(super_type_arg.IsType());
CheckRecursiveType(super_type_arg, pending_types);
if (FLAG_trace_type_finalization) {
THR_Print("Creating TypeRef '%s': '%s'\n",
String::Handle(super_type_arg.Name()).ToCString(),
super_type_arg.ToCString());
// A type parameter being finalized indicates an unfinalized bound,
// but the bound is not relevant here. Its index is finalized.
if (!super_type_arg.IsTypeParameter()) {
if (super_type_arg.IsType()) {
CheckRecursiveType(super_type_arg, pending_types);
} else {
// The spec prohibits a typedef-declared function type to refer
// to itself. However, self-reference can occur via type
// arguments of the base class,
// e.g. `class Derived extends Base<TypeDef<Derived>> {}`.
ASSERT(super_type_arg.IsFunctionType());
}
if (FLAG_trace_type_finalization) {
THR_Print("Creating TypeRef '%s': '%s'\n",
String::Handle(super_type_arg.Name()).ToCString(),
super_type_arg.ToCString());
}
super_type_arg = TypeRef::New(super_type_arg);
}
super_type_arg = TypeRef::New(super_type_arg);
super_type_args.SetTypeAt(i, super_type_arg);
} else {
if (!super_type_arg.IsFinalized()) {
@ -603,9 +597,11 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
super_type_arg = super_type_arg.InstantiateFrom(
arguments, Object::null_type_arguments(), kNoneFree, Heap::kOld,
trail);
if (super_type_arg.IsBeingFinalized()) {
if (super_type_arg.IsBeingFinalized() &&
!super_type_arg.IsTypeParameter()) {
// The super_type_arg was instantiated from a type being finalized.
// We need to finish finalizing its type arguments.
// We need to finish finalizing its type arguments, unless it is a
// type parameter, in which case there is nothing more to do.
AbstractType& unfinalized_type = AbstractType::Handle();
if (super_type_arg.IsTypeRef()) {
unfinalized_type = TypeRef::Cast(super_type_arg).type();
@ -618,8 +614,10 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
String::Handle(unfinalized_type.Name()).ToCString(),
unfinalized_type.ToCString());
}
CheckRecursiveType(unfinalized_type, pending_types);
pending_types->Add(unfinalized_type);
if (unfinalized_type.IsType()) {
CheckRecursiveType(unfinalized_type, pending_types);
pending_types->Add(unfinalized_type);
}
const Class& super_cls =
Class::Handle(unfinalized_type.type_class());
const TypeArguments& super_args =
@ -658,12 +656,12 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
if (type.IsFinalized()) {
// Ensure type is canonical if canonicalization is requested.
if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
if ((finalization >= kCanonicalize) && !type.IsCanonical() &&
!type.IsBeingFinalized()) {
return type.Canonicalize(Thread::Current(), nullptr);
}
return type.raw();
}
ASSERT(finalization >= kFinalize);
if (type.IsTypeRef()) {
// The referenced type will be finalized later by the code that set the
@ -671,11 +669,21 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
return type.raw();
}
if (type.IsTypeParameter() && type.IsBeingFinalized()) {
// The base and index have already been adjusted, but the bound referring
// back to the type parameter is still being finalized.
return type.raw();
}
// Recursive types must be processed in FinalizeTypeArguments() and cannot be
// encountered here.
ASSERT(!type.IsBeingFinalized());
Zone* zone = Thread::Current()->zone();
// Mark the type as being finalized in order to detect self reference.
type.SetIsBeingFinalized();
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type '%s'\n",
@ -686,100 +694,71 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
const TypeParameter& type_parameter = TypeParameter::Cast(type);
const Class& parameterized_class =
Class::Handle(zone, type_parameter.parameterized_class());
intptr_t offset;
// The base and index of a function type parameter are eagerly calculated
// upon loading and do not require adjustment here.
if (!parameterized_class.IsNull()) {
// The index must reflect the position of this type parameter in the type
// arguments vector of its parameterized class. The offset to add is the
// number of type arguments in the super type, which is equal to the
// difference in number of type arguments and type parameters of the
// parameterized class.
offset = parameterized_class.NumTypeArguments() -
parameterized_class.NumTypeParameters();
} else {
const Function& function =
Function::Handle(zone, type_parameter.parameterized_function());
ASSERT(!function.IsNull());
offset = function.NumParentTypeParameters();
const intptr_t offset = parameterized_class.NumTypeArguments() -
parameterized_class.NumTypeParameters();
type_parameter.set_base(offset); // Informative, but not needed.
type_parameter.set_index(type_parameter.index() + offset);
// Remove the reference to the parameterized class.
type_parameter.set_parameterized_class_id(kClassCid);
}
type_parameter.set_index(type_parameter.index() + offset);
AbstractType& t = AbstractType::Handle(zone);
t = type_parameter.bound();
if (!t.IsBeingFinalized()) {
t = FinalizeType(t, kFinalize);
type_parameter.set_bound(t);
}
t = type_parameter.default_argument();
// The default argument cannot create a cycle with the type parameter.
t = FinalizeType(t, kFinalize);
type_parameter.set_default_argument(t);
type_parameter.SetIsFinalized();
if (FLAG_trace_type_finalization) {
THR_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
String::Handle(zone, type_parameter.name()).ToCString(),
THR_Print("Done finalizing type parameter at index %" Pd "\n",
type_parameter.index());
}
if (type_parameter.IsDeclaration()) {
// The declaration of a type parameter is canonical.
ASSERT(type_parameter.IsCanonical());
return type_parameter.raw();
if (finalization >= kCanonicalize) {
return type_parameter.Canonicalize(thread, nullptr);
}
return type_parameter.Canonicalize(Thread::Current(), nullptr);
return type_parameter.raw();
}
// At this point, we can only have a Type.
ASSERT(type.IsType());
// If the type is a function type, 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.
if (type.IsFunctionType()) {
return FinalizeSignature(zone, FunctionType::Cast(type), finalization,
pending_types);
}
// This type is the root type of the type graph if no pending types queue is
// allocated yet.
// allocated yet. A function type is a collection of types, but not a root.
const bool is_root_type = pending_types == NULL;
if (is_root_type) {
pending_types = new PendingTypes(zone, 4);
}
// At this point, we can only have a Type.
ASSERT(type.IsType());
pending_types->Add(type);
const intptr_t num_expanded_type_arguments =
ExpandAndFinalizeTypeArguments(type, pending_types);
// Self referencing types may get finalized indirectly.
if (!type.IsFinalized()) {
// If the type is a function type, 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
// typedef function type to refer to itself via its parameter types and
// result type.
if (type.IsFunctionType()) {
const Type& fun_type = Type::Cast(type);
const Class& scope_class = Class::Handle(zone, fun_type.type_class());
if (scope_class.IsTypedefClass()) {
Function& signature =
Function::Handle(zone, scope_class.signature_function());
if (!scope_class.is_type_finalized()) {
FinalizeSignature(signature, finalization);
}
// If the function type is a generic typedef, instantiate its signature
// from its type arguments.
// Example: typedef F<T> = S Function<S>(T x) has uninstantiated
// signature (T x) => S.
// The instantiated signature of F(int) becomes (int x) => S.
// Note that after this step, the signature of the function type is not
// identical to the canonical signature of the typedef class anymore.
if (scope_class.IsGeneric() && !signature.HasInstantiatedSignature()) {
if (FLAG_trace_type_finalization) {
THR_Print("Instantiating signature '%s' of typedef '%s'\n",
String::Handle(zone, signature.Signature()).ToCString(),
String::Handle(zone, fun_type.Name()).ToCString());
}
const TypeArguments& instantiator_type_arguments =
TypeArguments::Handle(zone, fun_type.arguments());
signature = signature.InstantiateSignatureFrom(
instantiator_type_arguments, Object::null_type_arguments(),
kNoneFree, Heap::kOld);
// Note that if instantiator_type_arguments contains type parameters,
// as in F<K>, the signature is still uninstantiated (the typedef type
// parameters were substituted in the signature with typedef type
// arguments). Note also that the function type parameters were not
// modified.
FinalizeSignature(signature, finalization);
}
fun_type.set_signature(signature);
} else {
FinalizeSignature(Function::Handle(zone, fun_type.signature()),
finalization);
}
}
if (FLAG_trace_type_finalization) {
THR_Print("Marking type '%s' as finalized\n",
String::Handle(zone, type.Name()).ToCString());
@ -798,108 +777,73 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
if (FLAG_trace_type_finalization) {
THR_Print("Canonicalizing type '%s'\n",
String::Handle(zone, type.Name()).ToCString());
AbstractType& canonical_type = AbstractType::Handle(
zone, type.Canonicalize(Thread::Current(), nullptr));
AbstractType& canonical_type =
AbstractType::Handle(zone, type.Canonicalize(thread, nullptr));
THR_Print("Done canonicalizing type '%s'\n",
String::Handle(zone, canonical_type.Name()).ToCString());
return canonical_type.raw();
}
return type.Canonicalize(Thread::Current(), nullptr);
return type.Canonicalize(thread, nullptr);
} else {
return type.raw();
}
}
void ClassFinalizer::FinalizeSignature(const Function& function,
FinalizationKind finalization) {
AbstractType& type = AbstractType::Handle();
AbstractType& finalized_type = AbstractType::Handle();
// Finalize function type parameters, including their bounds and default args.
const intptr_t num_parent_type_params = function.NumParentTypeParameters();
const intptr_t num_type_params = function.NumTypeParameters();
AbstractTypePtr ClassFinalizer::FinalizeSignature(Zone* zone,
const FunctionType& signature,
FinalizationKind finalization,
PendingTypes* pending_types) {
AbstractType& type = AbstractType::Handle(zone);
AbstractType& finalized_type = AbstractType::Handle(zone);
// Finalize signature type parameters, their upper bounds and default args.
const intptr_t num_type_params = signature.NumTypeParameters();
if (num_type_params > 0) {
TypeParameter& type_param = TypeParameter::Handle();
TypeParameter& type_param = TypeParameter::Handle(zone);
const TypeArguments& type_params =
TypeArguments::Handle(function.type_parameters());
TypeArguments::Handle(zone, signature.type_parameters());
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
if (!type_param.IsFinalized()) {
ASSERT(type_param.index() == i);
type_param.set_index(num_parent_type_params + i);
type_param.SetIsFinalized();
} else {
ASSERT(type_param.index() == num_parent_type_params + i);
}
// The declaration of a type parameter is canonical.
ASSERT(type_param.IsDeclaration());
ASSERT(type_param.IsCanonical());
}
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
type = type_param.bound();
finalized_type = FinalizeType(type, finalization);
if (finalized_type.raw() != type.raw()) {
type_param.set_bound(finalized_type);
}
type = type_param.default_argument();
finalized_type = FinalizeType(type, finalization);
if (finalized_type.raw() != type.raw()) {
type_param.set_default_argument(finalized_type);
finalized_type ^= FinalizeType(type_param, kFinalize, pending_types);
if (type_param.raw() != finalized_type.raw()) {
type_params.SetTypeAt(i, TypeParameter::Cast(finalized_type));
}
}
function.UpdateCachedDefaultTypeArguments(Thread::Current());
}
// Finalize result type.
type = function.result_type();
finalized_type = FinalizeType(type, finalization);
type = signature.result_type();
finalized_type = FinalizeType(type, kFinalize, pending_types);
if (finalized_type.raw() != type.raw()) {
function.set_result_type(finalized_type);
signature.set_result_type(finalized_type);
}
// Finalize formal parameter types.
const intptr_t num_parameters = function.NumParameters();
const intptr_t num_parameters = signature.NumParameters();
for (intptr_t i = 0; i < num_parameters; i++) {
type = function.ParameterTypeAt(i);
finalized_type = FinalizeType(type, finalization);
type = signature.ParameterTypeAt(i);
finalized_type = FinalizeType(type, kFinalize, pending_types);
if (type.raw() != finalized_type.raw()) {
function.SetParameterTypeAt(i, finalized_type);
signature.SetParameterTypeAt(i, finalized_type);
}
}
}
// Finalize bounds and default arguments of the type parameters of class cls.
void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
FinalizationKind finalization) {
const intptr_t num_type_params = cls.NumTypeParameters();
TypeParameter& type_param = TypeParameter::Handle();
AbstractType& type = AbstractType::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);
// First, finalize the default argument (no cycles possible here).
type = type_param.default_argument();
type = FinalizeType(type, finalization);
type_param.set_default_argument(type);
// Next, finalize the bound.
type = type_param.bound();
// Bound may be finalized, but not canonical yet.
if (type.IsCanonical() || type.IsBeingFinalized()) {
// A bound involved in F-bounded quantification may form a cycle.
continue;
}
type = FinalizeType(type, finalization);
type_param.set_bound(type);
if (FLAG_trace_type_finalization) {
THR_Print("Marking function type '%s' as finalized\n",
String::Handle(zone, signature.Name()).ToCString());
}
signature.SetIsFinalized();
if (finalization >= kCanonicalize) {
return signature.Canonicalize(Thread::Current(), nullptr);
}
return signature.raw();
}
#if defined(TARGET_ARCH_X64)
static bool IsPotentialExactGeneric(const AbstractType& type) {
// TODO(dartbug.com/34170) Investigate supporting this for fields with types
// that depend on type parameters of the enclosing class.
if (type.IsType() && !type.IsFunctionType() && !type.IsDartFunctionType() &&
type.IsInstantiated() && !type.IsFutureOrType()) {
if (type.IsType() && !type.IsDartFunctionType() && type.IsInstantiated() &&
!type.IsFutureOrType()) {
const Class& cls = Class::Handle(type.type_class());
return cls.IsGeneric();
}
@ -939,6 +883,8 @@ void ClassFinalizer::FinalizeMemberTypes(const Class& cls) {
Array& array = Array::Handle(zone, cls.fields());
Field& field = Field::Handle(zone);
AbstractType& type = AbstractType::Handle(zone);
Function& function = Function::Handle(zone);
FunctionType& signature = FunctionType::Handle(zone);
const intptr_t num_fields = array.Length();
const bool track_exactness = isolate_group->use_field_guards();
for (intptr_t i = 0; i < num_fields; i++) {
@ -950,15 +896,24 @@ void ClassFinalizer::FinalizeMemberTypes(const Class& cls) {
field.set_static_type_exactness_state(
StaticTypeExactnessState::Uninitialized());
}
function = field.InitializerFunction();
if (!function.IsNull()) {
// TODO(regis): It looks like the initializer is never set at this point.
// Remove this finalization code?
signature = function.signature();
signature ^= FinalizeType(signature);
function.set_signature(signature);
}
}
// Finalize function signatures and check for conflicts in super classes and
// interfaces.
array = cls.current_functions();
Function& function = Function::Handle(zone);
const intptr_t num_functions = array.Length();
for (intptr_t i = 0; i < num_functions; i++) {
function ^= array.At(i);
FinalizeSignature(function);
signature = function.signature();
signature ^= FinalizeType(signature);
function.set_signature(signature);
if (function.IsSetterFunction() || function.IsImplicitSetterFunction()) {
continue;
}
@ -1011,45 +966,16 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
FinalizeTypesInClass(super_class);
}
// Finalize type parameters before finalizing the super type.
FinalizeTypeParameters(cls);
FinalizeTypeParameters(cls, kFinalize);
ASSERT(super_class.raw() == cls.SuperClass()); // Not modified.
ASSERT(super_class.IsNull() || super_class.is_type_finalized());
FinalizeUpperBounds(cls);
FinalizeTypeParameters(cls, kCanonicalize);
// Finalize super type.
AbstractType& super_type = AbstractType::Handle(cls.super_type());
if (!super_type.IsNull()) {
super_type = FinalizeType(super_type);
cls.set_super_type(super_type);
}
if (cls.IsTypedefClass()) {
Function& signature = Function::Handle(cls.signature_function());
Type& type = Type::Handle(signature.SignatureType());
ASSERT(type.signature() == signature.raw());
ASSERT(type.type_class() == cls.raw());
cls.set_is_type_finalized();
// Finalize the result and parameter types of the signature
// function of this typedef class.
FinalizeSignature(signature); // Does not modify signature type.
ASSERT(signature.SignatureType() == type.raw());
// Finalize the signature type of this typedef.
type ^= FinalizeType(type);
ASSERT(type.type_class() == cls.raw());
// If a different canonical signature type is returned, update the signature
// function of the typedef.
signature = type.signature();
signature.SetSignatureType(type);
cls.set_signature_function(signature);
// 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());
return;
}
// Finalize interface types (but not necessarily interface classes).
Array& interface_types = Array::Handle(cls.interfaces());
AbstractType& interface_type = AbstractType::Handle();
@ -1564,21 +1490,23 @@ void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
// In the Dart VM heap the following instances directly use cids for the
// computation of canonical hash codes:
//
// * RawType (due to TypeLayout::type_class_id_)
// * RawTypeParameter (due to TypeParameterLayout::parameterized_class_id_)
// * TypePtr (due to TypeLayout::type_class_id_)
// * TypeParameterPtr (due to TypeParameterLayout::parameterized_class_id_)
//
// The following instances use cids for the computation of canonical hash codes
// indirectly:
//
// * RawTypeRef (due to TypeRefLayout::type_->type_class_id)
// * RawType (due to TypeLayout::signature_'s result/parameter types)
// * RawTypeArguments (due to type references)
// * RawInstance (due to instance fields)
// * RawArray (due to type arguments & array entries)
// * TypeRefPtr (due to TypeRefLayout::type_->type_class_id)
// * TypePtr (due to type arguments)
// * FunctionTypePtr (due to the result and parameter types)
// * TypeArgumentsPtr (due to type references)
// * InstancePtr (due to instance fields)
// * ArrayPtr (due to type arguments & array entries)
//
// Caching of the canonical hash codes happens for:
//
// * TypeLayout::hash_
// * FunctionTypeLayout::hash_
// * TypeParameterLayout::hash_
// * TypeArgumentsLayout::hash_
// * RawInstance (weak table)
@ -1587,11 +1515,12 @@ void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
// No caching of canonical hash codes (i.e. it gets re-computed every time)
// happens for:
//
// * RawTypeRef (computed via TypeRefLayout::type_->type_class_id)
// * TypeRefPtr (computed via TypeRefLayout::type_->type_class_id)
//
// Usages of canonical hash codes are:
//
// * ObjectStore::canonical_types()
// * ObjectStore::canonical_function_types()
// * ObjectStore::canonical_type_parameters()
// * ObjectStore::canonical_type_arguments()
// * Class::constants()
@ -1601,6 +1530,7 @@ class ClearTypeHashVisitor : public ObjectVisitor {
explicit ClearTypeHashVisitor(Zone* zone)
: type_param_(TypeParameter::Handle(zone)),
type_(Type::Handle(zone)),
function_type_(FunctionType::Handle(zone)),
type_args_(TypeArguments::Handle(zone)) {}
void VisitObject(ObjectPtr obj) {
@ -1610,6 +1540,9 @@ class ClearTypeHashVisitor : public ObjectVisitor {
} else if (obj->IsType()) {
type_ ^= obj;
type_.SetHash(0);
} else if (obj->IsFunctionType()) {
function_type_ ^= obj;
function_type_.SetHash(0);
} else if (obj->IsTypeArguments()) {
type_args_ ^= obj;
type_args_.SetHash(0);
@ -1619,6 +1552,7 @@ class ClearTypeHashVisitor : public ObjectVisitor {
private:
TypeParameter& type_param_;
Type& type_;
FunctionType& function_type_;
TypeArguments& type_args_;
};
@ -1656,6 +1590,27 @@ void ClassFinalizer::RehashTypes() {
}
object_store->set_canonical_types(types_table.Release());
// Rehash the canonical FunctionTypes table.
Array& function_types = Array::Handle(Z);
FunctionType& function_type = FunctionType::Handle(Z);
{
CanonicalFunctionTypeSet function_types_table(
Z, object_store->canonical_function_types());
function_types = HashTables::ToArray(function_types_table, false);
function_types_table.Release();
}
dict_size = Utils::RoundUpToPowerOfTwo(function_types.Length() * 4 / 3);
CanonicalFunctionTypeSet function_types_table(
Z, HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld));
for (intptr_t i = 0; i < function_types.Length(); i++) {
function_type ^= function_types.At(i);
bool present = function_types_table.Insert(function_type);
// Two recursive types with different topology (and hashes) may be equal.
ASSERT(!present || function_type.IsRecursive());
}
object_store->set_canonical_function_types(function_types_table.Release());
// Rehash the canonical TypeParameters table.
Array& typeparams = Array::Handle(Z);
TypeParameter& typeparam = TypeParameter::Handle(Z);

View file

@ -31,10 +31,6 @@ class ClassFinalizer : public AllStatic {
FinalizationKind finalization = kCanonicalize,
PendingTypes* pending_types = NULL);
// Finalize the types in the functions's signature.
static void FinalizeSignature(const Function& function,
FinalizationKind finalization = kCanonicalize);
// Return false if we still have classes pending to be finalized.
static bool AllClassesFinalized();
@ -78,8 +74,17 @@ class ClassFinalizer : public AllStatic {
#endif // !defined(DART_PRECOMPILED_RUNTIME)
private:
// Finalize the types in the signature and the signature itself.
static AbstractTypePtr FinalizeSignature(
Zone* zone,
const FunctionType& signature,
FinalizationKind finalization = kCanonicalize,
PendingTypes* pending_types = NULL);
static void AllocateEnumValues(const Class& enum_cls);
static void FinalizeTypeParameters(const Class& cls);
static void FinalizeTypeParameters(
const Class& cls,
FinalizationKind finalization = kCanonicalize);
static intptr_t ExpandAndFinalizeTypeArguments(const AbstractType& type,
PendingTypes* pending_types);
static void FinalizeTypeArguments(const Class& cls,
@ -89,9 +94,6 @@ class ClassFinalizer : public AllStatic {
TrailPtr trail);
static void CheckRecursiveType(const AbstractType& type,
PendingTypes* pending_types);
static void FinalizeUpperBounds(
const Class& cls,
FinalizationKind finalization = kCanonicalize);
static void FinalizeMemberTypes(const Class& cls);
static void PrintClassInformation(const Class& cls);

View file

@ -22,7 +22,6 @@ typedef uint16_t ClassIdTagType;
V(PatchClass) \
V(Function) \
V(ClosureData) \
V(SignatureData) \
V(FfiTrampolineData) \
V(Field) \
V(Script) \
@ -58,6 +57,7 @@ typedef uint16_t ClassIdTagType;
V(TypeArguments) \
V(AbstractType) \
V(Type) \
V(FunctionType) \
V(TypeRef) \
V(TypeParameter) \
V(Closure) \
@ -230,6 +230,7 @@ bool IsOneByteStringClassId(intptr_t index);
bool IsTwoByteStringClassId(intptr_t index);
bool IsExternalStringClassId(intptr_t index);
bool IsBuiltinListClassId(intptr_t index);
bool IsTypeClassId(intptr_t index);
bool IsTypedDataBaseClassId(intptr_t index);
bool IsTypedDataClassId(intptr_t index);
bool IsTypedDataViewClassId(intptr_t index);
@ -315,6 +316,11 @@ inline bool IsBuiltinListClassId(intptr_t index) {
(index == kByteBufferCid));
}
inline bool IsTypeClassId(intptr_t index) {
// Only Type and FunctionType can be encountered as instance types at runtime.
return index == kTypeCid || index == kFunctionTypeCid;
}
inline bool IsTypedDataBaseClassId(intptr_t index) {
// Make sure this is updated when new TypedData types are added.
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);

View file

@ -776,7 +776,6 @@ class ClosureDataSerializationCluster : public SerializationCluster {
s->Push(data->ptr()->context_scope_);
}
s->Push(data->ptr()->parent_function_);
s->Push(data->ptr()->signature_type_);
s->Push(data->ptr()->closure_);
s->Push(data->ptr()->default_type_arguments_);
s->Push(data->ptr()->default_type_arguments_info_);
@ -801,7 +800,6 @@ class ClosureDataSerializationCluster : public SerializationCluster {
WriteField(data, context_scope_);
}
WriteField(data, parent_function_);
WriteField(data, signature_type_);
WriteField(data, closure_);
WriteField(data, default_type_arguments_);
WriteField(data, default_type_arguments_info_);
@ -841,7 +839,6 @@ class ClosureDataDeserializationCluster : public DeserializationCluster {
static_cast<ContextScopePtr>(d->ReadRef());
}
data->ptr()->parent_function_ = static_cast<FunctionPtr>(d->ReadRef());
data->ptr()->signature_type_ = static_cast<TypePtr>(d->ReadRef());
data->ptr()->closure_ = static_cast<InstancePtr>(d->ReadRef());
data->ptr()->default_type_arguments_ =
static_cast<TypeArgumentsPtr>(d->ReadRef());
@ -851,69 +848,6 @@ class ClosureDataDeserializationCluster : public DeserializationCluster {
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class SignatureDataSerializationCluster : public SerializationCluster {
public:
SignatureDataSerializationCluster() : SerializationCluster("SignatureData") {}
~SignatureDataSerializationCluster() {}
void Trace(Serializer* s, ObjectPtr object) {
SignatureDataPtr data = SignatureData::RawCast(object);
objects_.Add(data);
PushFromTo(data);
}
void WriteAlloc(Serializer* s) {
s->WriteCid(kSignatureDataCid);
const intptr_t count = objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
SignatureDataPtr data = objects_[i];
s->AssignRef(data);
}
}
void WriteFill(Serializer* s) {
const intptr_t count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
SignatureDataPtr data = objects_[i];
AutoTraceObject(data);
WriteFromTo(data);
}
}
private:
GrowableArray<SignatureDataPtr> objects_;
};
#endif // !DART_PRECOMPILED_RUNTIME
class SignatureDataDeserializationCluster : public DeserializationCluster {
public:
SignatureDataDeserializationCluster()
: DeserializationCluster("SignatureData") {}
~SignatureDataDeserializationCluster() {}
void ReadAlloc(Deserializer* d, bool is_canonical) {
start_index_ = d->next_index();
PageSpace* old_space = d->heap()->old_space();
const intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(
AllocateUninitialized(old_space, SignatureData::InstanceSize()));
}
stop_index_ = d->next_index();
}
void ReadFill(Deserializer* d, bool is_canonical) {
for (intptr_t id = start_index_; id < stop_index_; id++) {
SignatureDataPtr data = static_cast<SignatureDataPtr>(d->Ref(id));
Deserializer::InitializeHeader(data, kSignatureDataCid,
SignatureData::InstanceSize());
ReadFromTo(data);
}
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class FfiTrampolineDataSerializationCluster : public SerializationCluster {
public:
@ -3348,7 +3282,6 @@ class TypeSerializationCluster : public SerializationCluster {
void WriteType(Serializer* s, TypePtr type) {
AutoTraceObject(type);
WriteFromTo(type);
s->WriteTokenPosition(type->ptr()->token_pos_);
ASSERT(type->ptr()->type_state_ < (1 << TypeLayout::kTypeStateBitSize));
ASSERT(type->ptr()->nullability_ < (1 << kNullabilityBitSize));
static_assert(TypeLayout::kTypeStateBitSize + kNullabilityBitSize <=
@ -3386,7 +3319,6 @@ class TypeDeserializationCluster : public DeserializationCluster {
Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
is_canonical);
ReadFromTo(type);
type->ptr()->token_pos_ = d->ReadTokenPosition();
const uint8_t combined = d->Read<uint8_t>();
type->ptr()->type_state_ = combined >> kNullabilityBitSize;
type->ptr()->nullability_ = combined & kNullabilityBitMask;
@ -3428,6 +3360,124 @@ class TypeDeserializationCluster : public DeserializationCluster {
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class FunctionTypeSerializationCluster : public SerializationCluster {
public:
FunctionTypeSerializationCluster() : SerializationCluster("FunctionType") {}
~FunctionTypeSerializationCluster() {}
void Trace(Serializer* s, ObjectPtr object) {
FunctionTypePtr type = FunctionType::RawCast(object);
objects_.Add(type);
PushFromTo(type);
}
void WriteAlloc(Serializer* s) {
s->WriteCid(kFunctionTypeCid);
intptr_t count = objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
FunctionTypePtr type = objects_[i];
s->AssignRef(type);
}
}
void WriteFill(Serializer* s) {
intptr_t count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
WriteFunctionType(s, objects_[i]);
}
}
private:
void WriteFunctionType(Serializer* s, FunctionTypePtr type) {
AutoTraceObject(type);
WriteFromTo(type);
ASSERT(type->ptr()->type_state_ <
(1 << FunctionTypeLayout::kTypeStateBitSize));
ASSERT(type->ptr()->nullability_ < (1 << kNullabilityBitSize));
static_assert(FunctionTypeLayout::kTypeStateBitSize + kNullabilityBitSize <=
kBitsPerByte * sizeof(uint8_t),
"Cannot pack type_state_ and nullability_ into a uint8_t");
const uint8_t combined = (type->ptr()->type_state_ << kNullabilityBitSize) |
type->ptr()->nullability_;
ASSERT_EQUAL(type->ptr()->type_state_, combined >> kNullabilityBitSize);
ASSERT_EQUAL(type->ptr()->nullability_, combined & kNullabilityBitMask);
s->Write<uint8_t>(combined);
s->Write<uint32_t>(type->ptr()->packed_fields_);
}
GrowableArray<FunctionTypePtr> objects_;
};
#endif // !DART_PRECOMPILED_RUNTIME
class FunctionTypeDeserializationCluster : public DeserializationCluster {
public:
FunctionTypeDeserializationCluster()
: DeserializationCluster("FunctionType") {}
~FunctionTypeDeserializationCluster() {}
void ReadAlloc(Deserializer* d, bool is_canonical) {
start_index_ = d->next_index();
PageSpace* old_space = d->heap()->old_space();
const intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(
AllocateUninitialized(old_space, FunctionType::InstanceSize()));
}
stop_index_ = d->next_index();
}
void ReadFill(Deserializer* d, bool is_canonical) {
for (intptr_t id = start_index_; id < stop_index_; id++) {
FunctionTypePtr type = static_cast<FunctionTypePtr>(d->Ref(id));
Deserializer::InitializeHeader(
type, kFunctionTypeCid, FunctionType::InstanceSize(), is_canonical);
ReadFromTo(type);
const uint8_t combined = d->Read<uint8_t>();
type->ptr()->type_state_ = combined >> kNullabilityBitSize;
type->ptr()->nullability_ = combined & kNullabilityBitMask;
type->ptr()->packed_fields_ = d->Read<uint32_t>();
}
}
void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
CanonicalFunctionTypeSet table(
d->zone(),
d->isolate_group()->object_store()->canonical_function_types());
FunctionType& type = FunctionType::Handle(d->zone());
for (intptr_t i = start_index_; i < stop_index_; i++) {
type ^= refs.At(i);
ASSERT(type.IsCanonical());
bool present = table.Insert(type);
// Two recursive types with different topology (and hashes) may be
// equal.
ASSERT(!present || type.IsRecursive());
}
d->isolate_group()->object_store()->set_canonical_function_types(
table.Release());
}
FunctionType& type = FunctionType::Handle(d->zone());
Code& stub = Code::Handle(d->zone());
if (Snapshot::IncludesCode(d->kind())) {
for (intptr_t id = start_index_; id < stop_index_; id++) {
type ^= refs.At(id);
stub = type.type_test_stub();
type.SetTypeTestingStub(stub); // Update type_test_stub_entry_point_
}
} else {
for (intptr_t id = start_index_; id < stop_index_; id++) {
type ^= refs.At(id);
stub = TypeTestingStubGenerator::DefaultCodeForType(type);
type.SetTypeTestingStub(stub);
}
}
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class TypeRefSerializationCluster : public SerializationCluster {
public:
@ -3544,8 +3594,8 @@ class TypeParameterSerializationCluster : public SerializationCluster {
AutoTraceObject(type);
WriteFromTo(type);
s->Write<int32_t>(type->ptr()->parameterized_class_id_);
s->WriteTokenPosition(type->ptr()->token_pos_);
s->Write<int16_t>(type->ptr()->index_);
s->Write<uint16_t>(type->ptr()->base_);
s->Write<uint16_t>(type->ptr()->index_);
ASSERT(type->ptr()->flags_ < (1 << TypeParameterLayout::kFlagsBitSize));
ASSERT(type->ptr()->nullability_ < (1 << kNullabilityBitSize));
static_assert(TypeParameterLayout::kFlagsBitSize + kNullabilityBitSize <=
@ -3586,8 +3636,8 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical);
ReadFromTo(type);
type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
type->ptr()->token_pos_ = d->ReadTokenPosition();
type->ptr()->index_ = d->Read<int16_t>();
type->ptr()->base_ = d->Read<uint16_t>();
type->ptr()->index_ = d->Read<uint16_t>();
const uint8_t combined = d->Read<uint8_t>();
type->ptr()->flags_ = combined >> kNullabilityBitSize;
type->ptr()->nullability_ = combined & kNullabilityBitMask;
@ -3603,10 +3653,8 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
for (intptr_t i = start_index_; i < stop_index_; i++) {
type_param ^= refs.At(i);
ASSERT(type_param.IsCanonical());
if (!type_param.IsDeclaration()) {
bool present = table.Insert(type_param);
ASSERT(!present);
}
bool present = table.Insert(type_param);
ASSERT(!present);
}
d->isolate_group()->object_store()->set_canonical_type_parameters(
table.Release());
@ -4949,6 +4997,7 @@ class ProgramSerializationRoots : public SerializationRoots {
object_store_(object_store),
saved_symbol_table_(Array::Handle()),
saved_canonical_types_(Array::Handle()),
saved_canonical_function_types_(Array::Handle()),
saved_canonical_type_parameters_(Array::Handle()),
saved_canonical_type_arguments_(Array::Handle()),
dispatch_table_entries_(Array::Handle()) {
@ -4960,6 +5009,10 @@ class ProgramSerializationRoots : public SerializationRoots {
object_store->set_canonical_types(
Array::Handle(HashTables::New<CanonicalTypeSet>(4)));
saved_canonical_function_types_ = object_store->canonical_function_types();
object_store->set_canonical_function_types(
Array::Handle(HashTables::New<CanonicalFunctionTypeSet>(4)));
saved_canonical_type_parameters_ =
object_store->canonical_type_parameters();
object_store->set_canonical_type_parameters(
@ -4972,6 +5025,8 @@ class ProgramSerializationRoots : public SerializationRoots {
~ProgramSerializationRoots() {
object_store_->set_symbol_table(saved_symbol_table_);
object_store_->set_canonical_types(saved_canonical_types_);
object_store_->set_canonical_function_types(
saved_canonical_function_types_);
object_store_->set_canonical_type_parameters(
saved_canonical_type_parameters_);
object_store_->set_canonical_type_arguments(
@ -5033,6 +5088,7 @@ class ProgramSerializationRoots : public SerializationRoots {
ObjectStore* object_store_;
Array& saved_symbol_table_;
Array& saved_canonical_types_;
Array& saved_canonical_function_types_;
Array& saved_canonical_type_parameters_;
Array& saved_canonical_type_arguments_;
Array& dispatch_table_entries_;
@ -5494,8 +5550,6 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
return new (Z) FunctionSerializationCluster();
case kClosureDataCid:
return new (Z) ClosureDataSerializationCluster();
case kSignatureDataCid:
return new (Z) SignatureDataSerializationCluster();
case kFfiTrampolineDataCid:
return new (Z) FfiTrampolineDataSerializationCluster();
case kFieldCid:
@ -5538,6 +5592,8 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
return new (Z) LibraryPrefixSerializationCluster();
case kTypeCid:
return new (Z) TypeSerializationCluster();
case kFunctionTypeCid:
return new (Z) FunctionTypeSerializationCluster();
case kTypeRefCid:
return new (Z) TypeRefSerializationCluster();
case kTypeParameterCid:
@ -6194,8 +6250,6 @@ DeserializationCluster* Deserializer::ReadCluster() {
return new (Z) FunctionDeserializationCluster();
case kClosureDataCid:
return new (Z) ClosureDataDeserializationCluster();
case kSignatureDataCid:
return new (Z) SignatureDataDeserializationCluster();
case kFfiTrampolineDataCid:
return new (Z) FfiTrampolineDataDeserializationCluster();
case kFieldCid:
@ -6240,6 +6294,8 @@ DeserializationCluster* Deserializer::ReadCluster() {
return new (Z) LibraryPrefixDeserializationCluster();
case kTypeCid:
return new (Z) TypeDeserializationCluster();
case kFunctionTypeCid:
return new (Z) FunctionTypeDeserializationCluster();
case kTypeRefCid:
return new (Z) TypeRefDeserializationCluster();
case kTypeParameterCid:

View file

@ -28,9 +28,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
Library::Handle(), class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::Handle(Symbols::New(thread, "callerFunction"));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
const Function& function = Function::Handle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
const String& target_name = String::Handle(String::New("targetFunction"));
const intptr_t kTypeArgsLen = 0;

View file

@ -28,9 +28,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
Library::Handle(), class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::Handle(Symbols::New(thread, "callerFunction"));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
const Function& function = Function::Handle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
const String& target_name = String::Handle(String::New("targetFunction"));
const intptr_t kTypeArgsLen = 0;

View file

@ -28,9 +28,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
Library::Handle(), class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::Handle(Symbols::New(thread, "callerFunction"));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
const Function& function = Function::Handle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
const String& target_name = String::Handle(String::New("targetFunction"));
const intptr_t kTypeArgsLen = 0;

View file

@ -28,9 +28,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
Library::Handle(), class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::Handle(Symbols::New(thread, "callerFunction"));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
const Function& function = Function::Handle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
const String& target_name = String::Handle(String::New("targetFunction"));
const intptr_t kTypeArgsLen = 0;

View file

@ -168,7 +168,7 @@ bool AotCallSpecializer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) {
const Function& target = Function::ZoneHandle(Z, function.raw());
StaticCallInstr* static_call =
StaticCallInstr::FromCall(Z, call, target, call->CallCount());
static_call->SetResultType(Z, CompileType::FromCid(kTypeCid));
// Since the result is either a Type or a FunctionType, we cannot pin it.
call->ReplaceWith(static_call, current_iterator());
return true;
}

View file

@ -163,6 +163,8 @@ Precompiler::Precompiler(Thread* thread)
dropped_class_count_(0),
dropped_typearg_count_(0),
dropped_type_count_(0),
dropped_functiontype_count_(0),
dropped_typeparam_count_(0),
dropped_library_count_(0),
libraries_(GrowableObjectArray::Handle(
isolate_->group()->object_store()->libraries())),
@ -178,6 +180,7 @@ Precompiler::Precompiler(Thread* thread)
classes_to_retain_(),
typeargs_to_retain_(),
types_to_retain_(),
functiontypes_to_retain_(),
typeparams_to_retain_(),
consts_to_retain_(),
seen_table_selectors_(),
@ -400,6 +403,7 @@ void Precompiler::DoCompileAll() {
DropFields();
TraceTypesFromRetainedClasses();
DropTypes();
DropFunctionTypes();
DropTypeParameters();
DropTypeArguments();
@ -460,6 +464,8 @@ void Precompiler::DoCompileAll() {
THR_Print(" %" Pd " fields,", dropped_field_count_);
THR_Print(" %" Pd " symbols,", symbols_before - symbols_after);
THR_Print(" %" Pd " types,", dropped_type_count_);
THR_Print(" %" Pd " function types,", dropped_functiontype_count_);
THR_Print(" %" Pd " type parameters,", dropped_typeparam_count_);
THR_Print(" %" Pd " type arguments,", dropped_typearg_count_);
THR_Print(" %" Pd " classes,", dropped_class_count_);
THR_Print(" %" Pd " libraries.\n", dropped_library_count_);
@ -481,6 +487,7 @@ void Precompiler::PrecompileConstructors() {
if (FLAG_trace_precompiler) {
THR_Print("Precompiling constructor %s\n", function.ToCString());
}
ASSERT(Class::Handle(zone_, function.Owner()).is_finalized());
CompileFunction(precompiler_, Thread::Current(), zone_, function);
}
@ -558,7 +565,7 @@ void Precompiler::CollectCallbackFields() {
Class& subcls = Class::Handle(Z);
Array& fields = Array::Handle(Z);
Field& field = Field::Handle(Z);
Function& function = Function::Handle(Z);
FunctionType& signature = FunctionType::Handle(Z);
Function& dispatcher = Function::Handle(Z);
Array& args_desc = Array::Handle(Z);
AbstractType& field_type = AbstractType::Handle(Z);
@ -583,9 +590,9 @@ void Precompiler::CollectCallbackFields() {
if (!IsSent(field_name)) continue;
// Create arguments descriptor with fixed parameters from
// signature of field_type.
function = Type::Cast(field_type).signature();
if (function.IsGeneric()) continue;
if (function.HasOptionalParameters()) continue;
signature ^= field_type.raw();
if (signature.IsGeneric()) continue;
if (signature.HasOptionalParameters()) continue;
if (FLAG_trace_precompiler) {
THR_Print("Found callback field %s\n", field_name.ToCString());
}
@ -595,7 +602,7 @@ void Precompiler::CollectCallbackFields() {
// unboxed parameters.
args_desc =
ArgumentsDescriptor::NewBoxed(0, // No type argument vector.
function.num_fixed_parameters());
signature.num_fixed_parameters());
cids.Clear();
if (CHA::ConcreteSubclasses(cls, &cids)) {
for (intptr_t j = 0; j < cids.length(); ++j) {
@ -623,6 +630,9 @@ void Precompiler::ProcessFunction(const Function& function) {
FLAG_use_bare_instructions ? global_object_pool_builder()->CurrentLength()
: 0;
RELEASE_ASSERT(!function.HasCode());
// Ffi trampoline functions have no signature.
ASSERT(function.kind() == FunctionLayout::kFfiTrampoline ||
FunctionType::Handle(Z, function.signature()).IsFinalized());
TracingScope tracing_scope(this);
function_count_++;
@ -773,10 +783,6 @@ void Precompiler::AddTypesOf(const Class& cls) {
type = cls.super_type();
AddType(type);
if (cls.IsTypedefClass()) {
AddTypesOf(Function::Handle(Z, cls.signature_function()));
}
}
void Precompiler::AddTypesOf(const Function& function) {
@ -784,15 +790,10 @@ void Precompiler::AddTypesOf(const Function& function) {
if (functions_to_retain_.ContainsKey(function)) return;
functions_to_retain_.Insert(function);
AddTypeArguments(TypeArguments::Handle(Z, function.type_parameters()));
const FunctionType& signature = FunctionType::Handle(Z, function.signature());
AddType(signature);
AbstractType& type = AbstractType::Handle(Z);
type = function.result_type();
AddType(type);
for (intptr_t i = 0; i < function.NumParameters(); i++) {
type = function.ParameterTypeAt(i);
AddType(type);
}
// At this point, ensure any cached default type arguments are canonicalized.
function.UpdateCachedDefaultTypeArguments(thread());
if (function.CachesDefaultTypeArguments()) {
@ -802,19 +803,16 @@ void Precompiler::AddTypesOf(const Function& function) {
AddTypeArguments(defaults);
}
Code& code = Code::Handle(Z, function.CurrentCode());
if (code.IsNull()) {
ASSERT(function.kind() == FunctionLayout::kSignatureFunction);
} else {
const ExceptionHandlers& handlers =
ExceptionHandlers::Handle(Z, code.exception_handlers());
if (!handlers.IsNull()) {
Array& types = Array::Handle(Z);
for (intptr_t i = 0; i < handlers.num_entries(); i++) {
types = handlers.GetHandledTypes(i);
for (intptr_t j = 0; j < types.Length(); j++) {
type ^= types.At(j);
AddType(type);
}
ASSERT(!code.IsNull());
const ExceptionHandlers& handlers =
ExceptionHandlers::Handle(Z, code.exception_handlers());
if (!handlers.IsNull()) {
Array& types = Array::Handle(Z);
for (intptr_t i = 0; i < handlers.num_entries(); i++) {
types = handlers.GetHandledTypes(i);
for (intptr_t j = 0; j < types.Length(); j++) {
type ^= types.At(j);
AddType(type);
}
}
}
@ -824,12 +822,6 @@ void Precompiler::AddTypesOf(const Function& function) {
if (!parent.IsNull()) {
AddTypesOf(parent);
}
if (function.IsSignatureFunction() || function.IsClosureFunction()) {
type = function.ExistingSignatureType();
if (!type.IsNull()) {
AddType(type);
}
}
// A class may have all functions inlined except a local function.
const Class& owner = Class::Handle(Z, function.Owner());
AddTypesOf(owner);
@ -847,10 +839,24 @@ void Precompiler::AddType(const AbstractType& abstype) {
AddType(type);
type = param.default_argument();
AddType(type);
const auto& function = Function::Handle(Z, param.parameterized_function());
AddTypesOf(function);
const Class& cls = Class::Handle(Z, param.parameterized_class());
AddTypesOf(cls);
return;
}
if (abstype.IsFunctionType()) {
if (functiontypes_to_retain_.HasKey(&FunctionType::Cast(abstype))) return;
const FunctionType& signature =
FunctionType::ZoneHandle(Z, FunctionType::Cast(abstype).raw());
functiontypes_to_retain_.Insert(&signature);
AddTypeArguments(TypeArguments::Handle(Z, signature.type_parameters()));
AbstractType& type = AbstractType::Handle(Z);
type = signature.result_type();
AddType(type);
for (intptr_t i = 0; i < signature.NumParameters(); i++) {
type = signature.ParameterTypeAt(i);
AddType(type);
}
return;
}
@ -863,10 +869,6 @@ void Precompiler::AddType(const AbstractType& abstype) {
AddTypesOf(cls);
const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
AddTypeArguments(vector);
if (type.IsFunctionType()) {
const Function& func = Function::Handle(Z, type.signature());
AddTypesOf(func);
}
} else if (abstype.IsTypeRef()) {
AbstractType& type = AbstractType::Handle(Z);
type = TypeRef::Cast(abstype).type();
@ -1859,7 +1861,9 @@ void Precompiler::AttachOptimizedTypeTestingStub() {
: type_(AbstractType::Handle(zone)), types_(types) {}
void VisitObject(ObjectPtr obj) {
if (obj->GetClassId() == kTypeCid || obj->GetClassId() == kTypeRefCid) {
if (obj->GetClassId() == kTypeCid ||
obj->GetClassId() == kFunctionTypeCid ||
obj->GetClassId() == kTypeRefCid) {
type_ ^= obj;
types_->Add(type_);
}
@ -1948,6 +1952,45 @@ void Precompiler::DropTypes() {
object_store->set_canonical_types(types_table.Release());
}
void Precompiler::DropFunctionTypes() {
ObjectStore* object_store = IG->object_store();
GrowableObjectArray& retained_types =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
Array& types_array = Array::Handle(Z);
FunctionType& type = FunctionType::Handle(Z);
// First drop all the function types that are not referenced.
{
CanonicalFunctionTypeSet types_table(
Z, object_store->canonical_function_types());
types_array = HashTables::ToArray(types_table, false);
for (intptr_t i = 0; i < types_array.Length(); i++) {
type ^= types_array.At(i);
bool retain = functiontypes_to_retain_.HasKey(&type);
if (retain) {
retained_types.Add(type);
} else {
type.ClearCanonical();
dropped_functiontype_count_++;
}
}
types_table.Release();
}
// Now construct a new function type table and save in the object store.
const intptr_t dict_size =
Utils::RoundUpToPowerOfTwo(retained_types.Length() * 4 / 3);
types_array =
HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld);
CanonicalFunctionTypeSet types_table(Z, types_array.raw());
bool present;
for (intptr_t i = 0; i < retained_types.Length(); i++) {
type ^= retained_types.At(i);
present = types_table.Insert(type);
ASSERT(!present);
}
object_store->set_canonical_function_types(types_table.Release());
}
void Precompiler::DropTypeParameters() {
ObjectStore* object_store = IG->object_store();
GrowableObjectArray& retained_typeparams =

View file

@ -146,6 +146,26 @@ class AbstractTypeKeyValueTrait {
typedef DirectChainedHashMap<AbstractTypeKeyValueTrait> AbstractTypeSet;
class FunctionTypeKeyValueTrait {
public:
// Typedefs needed for the DirectChainedHashMap template.
typedef const FunctionType* Key;
typedef const FunctionType* Value;
typedef const FunctionType* Pair;
static Key KeyOf(Pair kv) { return kv; }
static Value ValueOf(Pair kv) { return kv; }
static inline intptr_t Hashcode(Key key) { return key->Hash(); }
static inline bool IsKeyEqual(Pair pair, Key key) {
return pair->raw() == key->raw();
}
};
typedef DirectChainedHashMap<FunctionTypeKeyValueTrait> FunctionTypeSet;
class TypeParameterKeyValueTrait {
public:
// Typedefs needed for the DirectChainedHashMap template.
@ -306,6 +326,7 @@ class Precompiler : public ValueObject {
void DropFields();
void TraceTypesFromRetainedClasses();
void DropTypes();
void DropFunctionTypes();
void DropTypeParameters();
void DropTypeArguments();
void DropMetadata();
@ -347,6 +368,7 @@ class Precompiler : public ValueObject {
intptr_t dropped_class_count_;
intptr_t dropped_typearg_count_;
intptr_t dropped_type_count_;
intptr_t dropped_functiontype_count_;
intptr_t dropped_typeparam_count_;
intptr_t dropped_library_count_;
@ -361,6 +383,7 @@ class Precompiler : public ValueObject {
ClassSet classes_to_retain_;
TypeArgumentsSet typeargs_to_retain_;
AbstractTypeSet types_to_retain_;
FunctionTypeSet functiontypes_to_retain_;
TypeParameterSet typeparams_to_retain_;
InstanceSet consts_to_retain_;
TableSelectorSet seen_table_selectors_;

View file

@ -1443,10 +1443,18 @@ static void JumpIfNotString(Assembler* assembler,
kIfNotInRange, target);
}
static void JumpIfNotType(Assembler* assembler,
Register cid,
Register tmp,
Label* target) {
RangeCheck(assembler, cid, tmp, kTypeCid, kFunctionTypeCid, kIfNotInRange,
target);
}
// Return type quickly for simple types (not parameterized and not signature).
void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
Label* normal_ir_body) {
Label use_declaration_type, not_double, not_integer;
Label use_declaration_type, not_double, not_integer, not_string;
__ ldr(R0, Address(SP, 0 * target::kWordSize));
__ LoadClassIdMayBeSmi(R1, R0);
@ -1472,12 +1480,19 @@ void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
__ Ret();
__ Bind(&not_integer);
JumpIfNotString(assembler, R1, R0, &use_declaration_type);
JumpIfNotString(assembler, R1, R0, &not_string);
__ LoadIsolate(R0);
__ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
__ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
__ Ret();
__ Bind(&not_string);
JumpIfNotType(assembler, R1, R0, &use_declaration_type);
__ LoadIsolate(R0);
__ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
__ LoadFromOffset(R0, R0, target::ObjectStore::type_type_offset());
__ Ret();
__ Bind(&use_declaration_type);
__ LoadClassById(R2, R1);
__ ldrh(R3, FieldAddress(R2, target::Class::num_type_arguments_offset()));
@ -1577,8 +1592,8 @@ void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
__ ldr(R0, Address(SP, 0 * target::kWordSize));
__ ldr(R0, FieldAddress(R0, target::String::hash_offset()));
__ cmp(R0, Operand(0));
READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE)); // Hash not yet computed.
__ Bind(normal_ir_body);
READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
__ Bind(normal_ir_body); // Hash not yet computed.
}
void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
@ -1586,8 +1601,8 @@ void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
__ ldr(R0, Address(SP, 0 * target::kWordSize));
__ ldr(R0, FieldAddress(R0, target::Type::hash_offset()));
__ cmp(R0, Operand(0));
READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE)); // Hash not yet computed.
__ Bind(normal_ir_body);
READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
__ Bind(normal_ir_body); // Hash not yet computed.
}
void AsmIntrinsifier::Type_equality(Assembler* assembler,
@ -1642,6 +1657,27 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
Label* normal_ir_body) {
__ ldr(R0, Address(SP, 0 * target::kWordSize));
__ ldr(R0, FieldAddress(R0, target::FunctionType::hash_offset()));
__ cmp(R0, Operand(0));
READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
__ Bind(normal_ir_body); // Hash not yet computed.
}
void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
Label* normal_ir_body) {
__ ldm(IA, SP, (1 << R1 | 1 << R2));
__ cmp(R1, Operand(R2));
__ b(normal_ir_body, NE);
__ LoadObject(R0, CastHandle<Object>(TrueObject()));
__ Ret();
__ Bind(normal_ir_body);
}
void GenerateSubstringMatchesSpecialization(Assembler* assembler,
intptr_t receiver_cid,
intptr_t other_cid,

View file

@ -1513,10 +1513,18 @@ static void JumpIfNotString(Assembler* assembler,
kIfNotInRange, target);
}
static void JumpIfNotType(Assembler* assembler,
Register cid,
Register tmp,
Label* target) {
RangeCheck(assembler, cid, tmp, kTypeCid, kFunctionTypeCid, kIfNotInRange,
target);
}
// Return type quickly for simple types (not parameterized and not signature).
void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
Label* normal_ir_body) {
Label use_declaration_type, not_double, not_integer;
Label use_declaration_type, not_double, not_integer, not_string;
__ ldr(R0, Address(SP, 0 * target::kWordSize));
__ LoadClassIdMayBeSmi(R1, R0);
@ -1542,12 +1550,19 @@ void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
__ ret();
__ Bind(&not_integer);
JumpIfNotString(assembler, R1, R0, &use_declaration_type);
JumpIfNotString(assembler, R1, R0, &not_string);
__ LoadIsolate(R0);
__ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
__ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
__ ret();
__ Bind(&not_string);
JumpIfNotType(assembler, R1, R0, &use_declaration_type);
__ LoadIsolate(R0);
__ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
__ LoadFromOffset(R0, R0, target::ObjectStore::type_type_offset());
__ ret();
__ Bind(&use_declaration_type);
__ LoadClassById(R2, R1);
__ ldr(
@ -1723,6 +1738,28 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
Label* normal_ir_body) {
__ ldr(R0, Address(SP, 0 * target::kWordSize));
__ ldr(R0, FieldAddress(R0, target::FunctionType::hash_offset()));
__ cbz(normal_ir_body, R0);
__ ret();
// Hash not yet computed.
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
Label* normal_ir_body) {
__ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
__ cmp(R1, Operand(R2));
__ b(normal_ir_body, NE);
__ LoadObject(R0, CastHandle<Object>(TrueObject()));
__ ret();
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::Object_getHash(Assembler* assembler,
Label* normal_ir_body) {
__ ldr(R0, Address(SP, 0 * target::kWordSize));

View file

@ -1538,10 +1538,14 @@ static void JumpIfNotString(Assembler* assembler, Register cid, Label* target) {
kIfNotInRange, target);
}
static void JumpIfNotType(Assembler* assembler, Register cid, Label* target) {
RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfNotInRange, target);
}
// Return type quickly for simple types (not parameterized and not signature).
void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
Label* normal_ir_body) {
Label use_declaration_type, not_double, not_integer;
Label use_declaration_type, not_double, not_integer, not_string;
__ movl(EAX, Address(ESP, +1 * target::kWordSize));
__ LoadClassIdMayBeSmi(EDI, EAX);
@ -1574,14 +1578,24 @@ void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
// If object is a string (one byte, two byte or external variants) return
// string type.
__ movl(EAX, EDI);
JumpIfNotString(assembler, EAX, &use_declaration_type);
JumpIfNotString(assembler, EAX, &not_string);
__ LoadIsolate(EAX);
__ movl(EAX, Address(EAX, target::Isolate::cached_object_store_offset()));
__ movl(EAX, Address(EAX, target::ObjectStore::string_type_offset()));
__ ret();
// Object is neither double, nor integer, nor string.
__ Bind(&not_string);
// If object is a type or function type, return Dart type.
__ movl(EAX, EDI);
JumpIfNotType(assembler, EAX, &use_declaration_type);
__ LoadIsolate(EAX);
__ movl(EAX, Address(EAX, target::Isolate::cached_object_store_offset()));
__ movl(EAX, Address(EAX, target::ObjectStore::type_type_offset()));
__ ret();
// Object is neither double, nor integer, nor string, nor type.
__ Bind(&use_declaration_type);
__ LoadClassById(EBX, EDI);
__ movzxw(EDI, FieldAddress(EBX, target::Class::num_type_arguments_offset()));
@ -1752,6 +1766,30 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
Label* normal_ir_body) {
__ movl(EAX, Address(ESP, +1 * target::kWordSize)); // FunctionType object.
__ movl(EAX, FieldAddress(EAX, target::FunctionType::hash_offset()));
__ testl(EAX, EAX);
__ j(EQUAL, normal_ir_body, Assembler::kNearJump);
__ ret();
__ Bind(normal_ir_body);
// Hash not yet computed.
}
void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
Label* normal_ir_body) {
__ movl(EDI, Address(ESP, +1 * target::kWordSize));
__ movl(EBX, Address(ESP, +2 * target::kWordSize));
__ cmpl(EDI, EBX);
__ j(NOT_EQUAL, normal_ir_body);
__ LoadObject(EAX, CastHandle<Object>(TrueObject()));
__ ret();
__ Bind(normal_ir_body);
}
// bool _substringMatches(int start, String other)
void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
Label* normal_ir_body) {

View file

@ -1444,10 +1444,13 @@ static void JumpIfNotString(Assembler* assembler, Register cid, Label* target) {
kIfNotInRange, target);
}
static void JumpIfNotType(Assembler* assembler, Register cid, Label* target) {
RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfNotInRange, target);
}
// Return type quickly for simple types (not parameterized and not signature).
void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
Label* normal_ir_body) {
Label use_declaration_type, not_integer, not_double;
Label use_declaration_type, not_integer, not_double, not_string;
__ movq(RAX, Address(RSP, +1 * target::kWordSize));
__ LoadClassIdMayBeSmi(RCX, RAX);
@ -1481,14 +1484,24 @@ void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
// If object is a string (one byte, two byte or external variants) return
// string type.
__ movq(RAX, RCX);
JumpIfNotString(assembler, RAX, &use_declaration_type);
JumpIfNotString(assembler, RAX, &not_string);
__ LoadIsolate(RAX);
__ movq(RAX, Address(RAX, target::Isolate::cached_object_store_offset()));
__ movq(RAX, Address(RAX, target::ObjectStore::string_type_offset()));
__ ret();
// Object is neither double, nor integer, nor string.
__ Bind(&not_string);
// If object is a type or function type, return Dart type.
__ movq(RAX, RCX);
JumpIfNotType(assembler, RAX, &use_declaration_type);
__ LoadIsolate(RAX);
__ movq(RAX, Address(RAX, target::Isolate::cached_object_store_offset()));
__ movq(RAX, Address(RAX, target::ObjectStore::type_type_offset()));
__ ret();
// Object is neither double, nor integer, nor string, nor type.
__ Bind(&use_declaration_type);
__ LoadClassById(RDI, RCX);
__ movzxw(RCX, FieldAddress(RDI, target::Class::num_type_arguments_offset()));
@ -1663,6 +1676,32 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
Label* normal_ir_body) {
__ movq(RAX, Address(RSP, +1 * target::kWordSize)); // FunctionType object.
__ movq(RAX, FieldAddress(RAX, target::FunctionType::hash_offset()));
ASSERT(kSmiTag == 0);
ASSERT(kSmiTagShift == 1);
__ testq(RAX, RAX);
__ j(ZERO, normal_ir_body, Assembler::kNearJump);
__ ret();
__ Bind(normal_ir_body);
// Hash not yet computed.
}
void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
Label* normal_ir_body) {
__ movq(RCX, Address(RSP, +1 * target::kWordSize));
__ movq(RDX, Address(RSP, +2 * target::kWordSize));
__ cmpq(RCX, RDX);
__ j(NOT_EQUAL, normal_ir_body);
__ LoadObject(RAX, CastHandle<Object>(TrueObject()));
__ ret();
__ Bind(normal_ir_body);
}
void AsmIntrinsifier::Object_getHash(Assembler* assembler,
Label* normal_ir_body) {
__ movq(RAX, Address(RSP, +1 * target::kWordSize)); // Object.

View file

@ -2480,8 +2480,7 @@ FlowGraphCompiler::GetTypeTestStubKindForTypeParameter(
AbstractType& bound = AbstractType::Handle(zone(), type_param.bound());
bound = bound.UnwrapFutureOr();
return !bound.IsTopTypeForSubtyping() && !bound.IsObjectType() &&
!bound.IsFunctionType() && !bound.IsDartFunctionType() &&
bound.IsType()
!bound.IsDartFunctionType() && bound.IsType()
? kTestTypeFiveArgs
: kTestTypeSevenArgs;
}
@ -3037,6 +3036,10 @@ void FlowGraphCompiler::GenerateCallerChecksForAssertAssignable(
return output_dst_type();
}
if (dst_type.IsFunctionType()) {
return output_dst_type();
}
if (auto const hi = thread()->hierarchy_info()) {
const Class& type_class = Class::Handle(zone(), dst_type.type_class());

View file

@ -354,8 +354,7 @@ void HierarchyInfo::BuildRangesForJIT(ClassTable* table,
bool HierarchyInfo::CanUseSubtypeRangeCheckFor(const AbstractType& type) {
ASSERT(type.IsFinalized());
if (!type.IsInstantiated() || !type.IsType() || type.IsFunctionType() ||
type.IsDartFunctionType()) {
if (!type.IsInstantiated() || !type.IsType() || type.IsDartFunctionType()) {
return false;
}
@ -398,7 +397,7 @@ bool HierarchyInfo::CanUseGenericSubtypeRangeCheckFor(
const AbstractType& type) {
ASSERT(type.IsFinalized());
if (!type.IsType() || type.IsFunctionType() || type.IsDartFunctionType()) {
if (!type.IsType() || type.IsDartFunctionType()) {
return false;
}
@ -2744,8 +2743,10 @@ bool LoadFieldInstr::IsImmutableLengthLoad() const {
case Slot::Kind::kFunction_kind_tag:
case Slot::Kind::kFunction_packed_fields:
case Slot::Kind::kFunction_parameter_names:
case Slot::Kind::kFunction_parameter_types:
case Slot::Kind::kFunction_type_parameters:
case Slot::Kind::kFunction_signature:
case Slot::Kind::kFunctionType_packed_fields:
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
case Slot::Kind::kPointerBase_data_field:
case Slot::Kind::kType_arguments:
case Slot::Kind::kTypeArgumentsIndex:
@ -5171,6 +5172,7 @@ TypePtr PolymorphicInstanceCallInstr::ComputeRuntimeType(
bool is_string = true;
bool is_integer = true;
bool is_double = true;
bool is_type = true;
const intptr_t num_checks = targets.length();
for (intptr_t i = 0; i < num_checks; i++) {
@ -5182,18 +5184,24 @@ TypePtr PolymorphicInstanceCallInstr::ComputeRuntimeType(
is_string = is_string && IsStringClassId(cid);
is_integer = is_integer && IsIntegerClassId(cid);
is_double = is_double && (cid == kDoubleCid);
is_type = is_type && IsTypeClassId(cid);
}
}
if (is_string) {
ASSERT(!is_integer);
ASSERT(!is_double);
ASSERT(!is_type);
return Type::StringType();
} else if (is_integer) {
ASSERT(!is_double);
ASSERT(!is_type);
return Type::IntType();
} else if (is_double) {
ASSERT(!is_type);
return Type::Double();
} else if (is_type) {
return Type::DartTypeType();
}
return Type::null();

View file

@ -1506,8 +1506,12 @@ bool FlowGraphDeserializer::ParseDartValue(SExpression* sexp, Object* out) {
return ParseField(list, out);
} else if (tag->Equals("Function")) {
return ParseFunction(list, out);
} else if (tag->Equals("FunctionType")) {
return ParseFunctionType(list, out);
} else if (tag->Equals("TypeParameter")) {
return ParseTypeParameter(list, out);
} else if (tag->Equals("Array")) {
return ParseArray(list, out);
} else if (tag->Equals("ImmutableList")) {
return ParseImmutableList(list, out);
} else if (tag->Equals("Instance")) {
@ -1661,7 +1665,43 @@ bool FlowGraphDeserializer::ParseFunction(SExpList* list, Object* out) {
return true;
}
bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
bool FlowGraphDeserializer::ParseFunctionType(SExpList* list, Object* out) {
ASSERT(out != nullptr);
if (list == nullptr) return false;
auto& type_params = TypeArguments::ZoneHandle(zone());
if (auto const type_params_sexp = Retrieve(list, "type_params")) {
if (!ParseTypeArguments(type_params_sexp, &type_params)) return false;
}
auto& result_type = AbstractType::ZoneHandle(zone());
if (auto const result_type_sexp = Retrieve(list, "result_type")) {
if (!ParseAbstractType(result_type_sexp, &result_type)) return false;
}
auto& parameter_types = Array::ZoneHandle(zone());
if (auto const parameter_types_sexp = Retrieve(list, "parameter_types")) {
if (!ParseDartValue(parameter_types_sexp, &parameter_types)) return false;
}
auto& parameter_names = Array::ZoneHandle(zone());
if (auto const parameter_names_sexp = Retrieve(list, "parameter_names")) {
if (!ParseDartValue(parameter_names_sexp, &parameter_names)) return false;
}
intptr_t packed_fields;
if (auto const packed_fields_sexp =
CheckInteger(list->ExtraLookupValue("packed_fields"))) {
packed_fields = packed_fields_sexp->value();
} else {
return false;
}
auto& sig = FunctionType::ZoneHandle(zone(), FunctionType::New());
sig.set_type_parameters(type_params);
sig.set_result_type(result_type);
sig.set_parameter_types(parameter_types);
sig.set_parameter_names(parameter_names);
sig.set_packed_fields(packed_fields);
*out = sig.raw();
return true;
}
bool FlowGraphDeserializer::ParseArray(SExpList* list, Object* out) {
ASSERT(out != nullptr);
if (list == nullptr) return false;
@ -1678,7 +1718,13 @@ bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
if (!ParseTypeArguments(type_args_sexp, &array_type_args_)) return false;
arr.SetTypeArguments(array_type_args_);
}
arr.MakeImmutable();
return true;
}
bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
if (!ParseArray(list, out)) return false;
Array::Cast(*out).MakeImmutable();
return CanonicalizeInstance(list, out);
}
@ -1852,13 +1898,8 @@ bool FlowGraphDeserializer::ParseType(SExpression* sexp, Object* out) {
if (!ParseClass(cls_sexp, &type_class_)) return false;
const Nullability nullability =
type_class_.IsNullClass() ? Nullability::kNullable : Nullability::kLegacy;
*out = Type::New(type_class_, *type_args_ptr, token_pos, nullability);
*out = Type::New(type_class_, *type_args_ptr, nullability);
auto& type = Type::Cast(*out);
if (auto const sig_sexp = list->ExtraLookupValue("signature")) {
auto& function = Function::Handle(zone());
if (!ParseDartValue(sig_sexp, &function)) return false;
type.set_signature(function);
}
if (is_recursive) {
while (!pending_typerefs->is_empty()) {
auto const ref = pending_typerefs->RemoveLast();
@ -1929,46 +1970,32 @@ bool FlowGraphDeserializer::ParseTypeParameter(SExpList* list, Object* out) {
ASSERT(out != nullptr);
if (list == nullptr) return false;
const Function* function = nullptr;
const Class* cls = nullptr;
if (auto const func_sexp = CheckSymbol(list->ExtraLookupValue("function"))) {
if (!ParseCanonicalName(func_sexp, &type_param_function_)) return false;
if (!type_param_function_.IsFunction() || type_param_function_.IsNull()) {
StoreError(func_sexp, "not a function name");
return false;
}
function = &type_param_function_;
} else if (auto const class_sexp =
CheckInteger(list->ExtraLookupValue("class"))) {
const intptr_t cid = class_sexp->value();
auto const table = thread()->isolate_group()->class_table();
Class& cls = Class::Handle();
if (auto const cid_sexp = CheckInteger(list->ExtraLookupValue("cid"))) {
const intptr_t cid = cid_sexp->value();
ClassTable* table = thread()->isolate_group()->class_table();
if (!table->HasValidClassAt(cid)) {
StoreError(class_sexp, "not a valid class id");
StoreError(cid_sexp, "no valid class found for cid");
return false;
}
type_param_class_ = table->At(cid);
cls = &type_param_class_;
cls = table->At(cid);
} else {
// If we weren't given an explicit source, check in the function for this
// flow graph.
ASSERT(parsed_function_ != nullptr);
function = &parsed_function_->function();
return false;
}
auto const base_sexp = CheckInteger(list->ExtraLookupValue("base"));
if (base_sexp == nullptr) return false;
intptr_t base = base_sexp->value();
auto const index_sexp = CheckInteger(list->ExtraLookupValue("index"));
if (index_sexp == nullptr) return false;
intptr_t index = index_sexp->value();
auto const name_sexp = CheckSymbol(Retrieve(list, 1));
if (name_sexp == nullptr) return false;
tmp_string_ = String::New(name_sexp->value());
*out = TypeParameter::null();
if (function != nullptr) {
*out = function->LookupTypeParameter(tmp_string_, nullptr);
} else if (cls != nullptr) {
*out = cls->LookupTypeParameter(tmp_string_);
}
if (out->IsNull()) {
StoreError(name_sexp, "no type parameter found for name");
return false;
}
*out =
TypeParameter::New(cls, base, index, tmp_string_, Object::dynamic_type(),
false, Nullability::kLegacy);
TypeParameter::Cast(*out).SetIsFinalized();
return CanonicalizeInstance(list, out);
}

View file

@ -67,7 +67,6 @@ class FlowGraphDeserializer : ValueObject {
name_library_(Library::Handle(zone)),
type_class_(Class::Handle(zone)),
type_param_class_(Class::Handle(zone)),
type_param_function_(Function::Handle(zone)),
tmp_string_(String::Handle(zone)) {
// See canonicalization comment in ParseDartValue as to why this is
// currently necessary.
@ -282,9 +281,12 @@ class FlowGraphDeserializer : ValueObject {
bool ParseClosure(SExpList* list, Object* out);
bool ParseField(SExpList* list, Object* out);
bool ParseFunction(SExpList* list, Object* out);
bool ParseSignature(SExpList* list, Object* out);
bool ParseArray(SExpList* list, Object* out);
bool ParseImmutableList(SExpList* list, Object* out);
bool ParseInstance(SExpList* list, Object* out);
bool ParseType(SExpression* sexp, Object* out);
bool ParseFunctionType(SExpList* list, Object* out);
bool ParseTypeParameter(SExpList* list, Object* out);
bool ParseTypeArguments(SExpression* sexp, Object* out);
bool ParseTypeRef(SExpList* list, Object* out);
@ -401,7 +403,6 @@ class FlowGraphDeserializer : ValueObject {
Library& name_library_; // ParseCanonicalName
Class& type_class_; // ParseType
Class& type_param_class_; // ParseTypeParameter
Function& type_param_function_; // ParseTypeParameter
// Uses of string handles tend to be immediate, so we only need one.
String& tmp_string_;

View file

@ -65,7 +65,7 @@ FlowGraphSerializer::FlowGraphSerializer(Zone* zone,
serialize_parent_(Function::Handle(zone_)),
type_arguments_elem_(AbstractType::Handle(zone_)),
type_class_(Class::Handle(zone_)),
type_function_(Function::Handle(zone_)),
type_signature_(FunctionType::Handle(zone_)),
type_ref_type_(AbstractType::Handle(zone_)) {
// Double-check that the zone in the flow graph is a parent of the
// zone we'll be using for serialization.
@ -389,20 +389,12 @@ SExpression* FlowGraphSerializer::AbstractTypeToSExp(const AbstractType& t) {
if (t.IsTypeParameter()) {
const auto& param = TypeParameter::Cast(t);
AddSymbol(sexp, "TypeParameter");
AddExtraInteger(sexp, "cid", param.parameterized_class_id());
AddExtraInteger(sexp, "base", param.base());
AddExtraInteger(sexp, "index", param.index());
tmp_string_ = param.name();
AddSymbol(sexp, tmp_string_.ToCString());
if (param.IsFunctionTypeParameter()) {
if (param.parameterized_function() != flow_graph_->function().raw()) {
type_function_ = param.parameterized_function();
sexp->AddExtra("function", CanonicalNameToSExp(type_function_));
} else if (FLAG_verbose_flow_graph_serialization) {
sexp->AddExtra("function",
CanonicalNameToSExp(flow_graph_->function()));
}
} else if (param.IsClassTypeParameter()) {
type_class_ = param.parameterized_class();
AddExtraInteger(sexp, "class", type_class_.id());
}
// TODO(regis): bound, default argument, flags, nullability, hash.
return sexp;
}
if (t.IsTypeRef()) {
@ -433,21 +425,37 @@ SExpression* FlowGraphSerializer::AbstractTypeToSExp(const AbstractType& t) {
}
return sexp;
}
// We want to check for the type being recursive before we may serialize
// any sub-parts that include possible TypeRefs to this type.
const bool is_recursive = t.IsRecursive();
intptr_t hash = 0;
if (is_recursive) {
hash = t.Hash();
AddExtraInteger(sexp, "hash", hash);
open_recursive_types_.Insert(hash, &t);
}
if (t.IsFunctionType()) {
const auto& sig = FunctionType::Handle(zone(), FunctionType::Cast(t).raw());
AddSymbol(sexp, "FunctionType");
function_type_args_ = sig.type_parameters();
if (auto const ta_sexp = NonEmptyTypeArgumentsToSExp(function_type_args_)) {
sexp->AddExtra("type_params", ta_sexp);
}
auto& type = AbstractType::Handle(zone(), sig.result_type());
sexp->AddExtra("result_type", AbstractTypeToSExp(type));
auto& parameter_types = Array::Handle(zone(), sig.parameter_types());
sexp->AddExtra("parameter_types", ArrayToSExp(parameter_types));
auto& parameter_names = Array::Handle(zone(), sig.parameter_names());
sexp->AddExtra("parameter_names", ArrayToSExp(parameter_names));
AddExtraInteger(sexp, "packed_fields", sig.packed_fields());
// If we were parsing a recursive type, we're now done building it, so
// remove it from the open recursive types.
if (is_recursive) open_recursive_types_.Remove(hash);
return sexp;
}
ASSERT(t.IsType());
AddSymbol(sexp, "Type");
const auto& type = Type::Cast(t);
if (!type.token_pos().IsNoSource()) {
AddExtraInteger(sexp, "token_pos", type.token_pos().Serialize());
}
// We want to check for the type being recursive before we may serialize
// any sub-parts that include possible TypeRefs to this type.
const bool is_recursive = type.IsRecursive();
intptr_t hash = 0;
if (is_recursive) {
hash = type.Hash();
AddExtraInteger(sexp, "hash", hash);
open_recursive_types_.Insert(hash, &type);
}
if (type.HasTypeClass()) {
type_class_ = type.type_class();
// This avoids re-entry as long as serializing a class doesn't involve
@ -458,10 +466,6 @@ SExpression* FlowGraphSerializer::AbstractTypeToSExp(const AbstractType& t) {
// just printing out this version.
AddExtraString(sexp, "name", type.ToCString());
}
if (type.IsFunctionType()) {
type_function_ = type.signature();
sexp->AddExtra("signature", DartValueToSExp(type_function_));
}
// Since type arguments may themselves be instantiations of generic
// types, we may call back into this function in the middle of printing
// the TypeArguments and so we must allocate a fresh handle here.
@ -591,7 +595,7 @@ SExpression* FlowGraphSerializer::FunctionToSExp(const Function& func) {
return sexp;
}
SExpression* FlowGraphSerializer::ArrayToSExp(const Array& arr) {
SExpression* FlowGraphSerializer::ImmutableListToSExp(const Array& arr) {
if (arr.IsNull()) return nullptr;
// We should only be getting immutable lists when serializing Dart values
// in flow graphs.
@ -612,6 +616,18 @@ SExpression* FlowGraphSerializer::ArrayToSExp(const Array& arr) {
return sexp;
}
SExpression* FlowGraphSerializer::ArrayToSExp(const Array& arr) {
if (arr.IsNull()) return nullptr;
auto sexp = new (zone()) SExpList(zone());
AddSymbol(sexp, "Array");
auto& array_elem = Object::Handle(zone());
for (intptr_t i = 0; i < arr.Length(); i++) {
array_elem = arr.At(i);
sexp->Add(DartValueToSExp(array_elem));
}
return sexp;
}
SExpression* FlowGraphSerializer::ClosureToSExp(const Closure& c) {
if (c.IsNull()) return nullptr;
auto sexp = new (zone()) SExpList(zone());
@ -691,7 +707,7 @@ SExpression* FlowGraphSerializer::ObjectToSExp(const Object& dartval) {
return CodeToSExp(Code::Cast(dartval));
}
if (dartval.IsArray()) {
return ArrayToSExp(Array::Cast(dartval));
return ImmutableListToSExp(Array::Cast(dartval));
}
if (dartval.IsFunction()) {
return FunctionToSExp(Function::Cast(dartval));

View file

@ -72,6 +72,7 @@ class FlowGraphSerializer : ValueObject {
// value is the null object, the null pointer is returned.
SExpression* AbstractTypeToSExp(const AbstractType& typ);
SExpression* ArrayToSExp(const Array& arr);
SExpression* ImmutableListToSExp(const Array& arr);
SExpression* ClassToSExp(const Class& cls);
SExpression* ClosureToSExp(const Closure& c);
SExpression* ContextToSExp(const Context& c);
@ -133,7 +134,7 @@ class FlowGraphSerializer : ValueObject {
// A map of currently open (being serialized) recursive types. We use this
// to determine whether to serialize the referred types in TypeRefs.
IntMap<const Type*> open_recursive_types_;
IntMap<const AbstractType*> open_recursive_types_;
// Used for --populate-llvm-constant-pool in ConstantPoolToSExp.
class LLVMPoolMapKeyEqualsTraits : public AllStatic {
@ -188,7 +189,7 @@ class FlowGraphSerializer : ValueObject {
Function& serialize_parent_; // SerializeCanonicalName
AbstractType& type_arguments_elem_; // TypeArgumentsToSExp
Class& type_class_; // AbstractTypeToSExp
Function& type_function_; // AbstractTypeToSExp
FunctionType& type_signature_; // AbstractTypeToSExp
AbstractType& type_ref_type_; // AbstractTypeToSExp
};

View file

@ -313,8 +313,10 @@ class FlowGraphBuilderHelper {
private:
static FlowGraph& MakeDummyGraph(Thread* thread) {
const FunctionType& signature =
FunctionType::ZoneHandle(FunctionType::New());
const Function& func = Function::ZoneHandle(Function::New(
String::Handle(Symbols::New(thread, "dummy")),
signature, String::Handle(Symbols::New(thread, "dummy")),
FunctionLayout::kRegularFunction,
/*is_static=*/true,
/*is_const=*/false,

View file

@ -2370,6 +2370,7 @@ intptr_t FlowGraphInliner::NextInlineId(const Function& function,
ASSERT(source.token_pos.IsReal() || source.token_pos.IsSynthetic() ||
source.token_pos.IsNoSource());
RELEASE_ASSERT(!function.IsNull());
ASSERT(FunctionType::Handle(function.signature()).IsFinalized());
inline_id_to_function_->Add(&function);
inline_id_to_token_pos_->Add(source.token_pos);
caller_inline_id_->Add(source.inlining_id);
@ -4128,6 +4129,8 @@ bool FlowGraphInliner::TryInlineRecognizedMethod(
type = Type::Double();
} else if (IsIntegerClassId(receiver_cid)) {
type = Type::IntType();
} else if (IsTypeClassId(receiver_cid)) {
type = Type::DartTypeType();
} else if (receiver_cid != kClosureCid) {
const Class& cls = Class::Handle(
Z, flow_graph->isolate_group()->class_table()->At(receiver_cid));

View file

@ -2725,9 +2725,10 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
case Slot::Kind::kClosure_instantiator_type_arguments:
case Slot::Kind::kClosureData_default_type_arguments:
case Slot::Kind::kFunction_data:
case Slot::Kind::kFunction_signature:
case Slot::Kind::kFunction_parameter_names:
case Slot::Kind::kFunction_parameter_types:
case Slot::Kind::kFunction_type_parameters:
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
case Slot::Kind::kPointerBase_data_field:
case Slot::Kind::kTypedDataView_data:
case Slot::Kind::kType_arguments:
@ -2753,6 +2754,7 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
*range = Range::Full(RepresentationToRangeSize(slot().representation()));
break;
case Slot::Kind::kFunctionType_packed_fields:
case Slot::Kind::kClosure_hash:
case Slot::Kind::kLinkedHashMap_hash_mask:
case Slot::Kind::kLinkedHashMap_used_data:

View file

@ -52,14 +52,15 @@ class ParsedFunction;
// (i.e. initialized once at construction time and does not change after
// that) or like a non-final field.
#define NULLABLE_BOXED_NATIVE_SLOTS_LIST(V) \
V(Function, FunctionLayout, signature, FunctionType, FINAL) \
V(Context, ContextLayout, parent, Context, FINAL) \
V(Closure, ClosureLayout, instantiator_type_arguments, TypeArguments, FINAL) \
V(Closure, ClosureLayout, delayed_type_arguments, TypeArguments, FINAL) \
V(Closure, ClosureLayout, function_type_arguments, TypeArguments, FINAL) \
V(ClosureData, ClosureDataLayout, default_type_arguments, TypeArguments, \
FINAL) \
V(Function, FunctionLayout, type_parameters, TypeArguments, FINAL) \
V(Type, TypeLayout, arguments, TypeArguments, FINAL) \
V(FunctionType, FunctionTypeLayout, type_parameters, TypeArguments, FINAL) \
V(WeakProperty, WeakPropertyLayout, key, Dynamic, VAR) \
V(WeakProperty, WeakPropertyLayout, value, Dynamic, VAR)
@ -84,7 +85,7 @@ class ParsedFunction;
V(ClosureData, ClosureDataLayout, default_type_arguments_info, Smi, FINAL) \
V(Function, FunctionLayout, data, Dynamic, FINAL) \
V(Function, FunctionLayout, parameter_names, Array, FINAL) \
V(Function, FunctionLayout, parameter_types, Array, FINAL) \
V(FunctionType, FunctionTypeLayout, parameter_types, Array, FINAL) \
V(GrowableObjectArray, GrowableObjectArrayLayout, length, Smi, VAR) \
V(GrowableObjectArray, GrowableObjectArrayLayout, data, Array, VAR) \
V(TypedDataBase, TypedDataBaseLayout, length, Smi, FINAL) \
@ -125,6 +126,7 @@ class ParsedFunction;
#define UNBOXED_NATIVE_SLOTS_LIST(V) \
V(Function, FunctionLayout, kind_tag, Uint32, FINAL) \
V(Function, FunctionLayout, packed_fields, Uint32, FINAL) \
V(FunctionType, FunctionTypeLayout, packed_fields, Uint32, FINAL) \
V(TypeParameter, TypeParameterLayout, flags, Uint8, FINAL)
// For uses that do not need the exact_type (boxed) or representation (unboxed)

View file

@ -46,8 +46,9 @@ TEST_CASE(SlotFromGuardedField) {
Script::Handle(), TokenPosition::kNoSource));
dummy_class.set_is_synthesized_class();
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
const Function& dummy_function = Function::ZoneHandle(
Function::New(String::Handle(Symbols::New(thread, "foo")),
Function::New(signature, String::Handle(Symbols::New(thread, "foo")),
FunctionLayout::kRegularFunction, false, false, false,
false, false, dummy_class, TokenPosition::kMinSource));

View file

@ -564,7 +564,8 @@ void CompileType::Union(CompileType* other) {
// Climb up the hierarchy to find a suitable supertype. Note that interface
// types are not considered, making the union potentially non-commutative
if (abstract_type->IsInstantiated() && !abstract_type->IsDynamicType()) {
if (abstract_type->IsInstantiated() && !abstract_type->IsDynamicType() &&
!abstract_type->IsFunctionType()) {
Class& cls = Class::Handle(abstract_type->type_class());
for (; !cls.IsNull() && !cls.IsGeneric(); cls = cls.SuperClass()) {
type_ = &AbstractType::ZoneHandle(cls.RareType());
@ -1357,8 +1358,8 @@ static CompileType ComputeListFactoryType(CompileType* inferred_type,
: TypeArguments::Cast(type_args_value->BoundConstant());
const Class& cls =
Class::Handle(IsolateGroup::Current()->class_table()->At(cid));
Type& type = Type::ZoneHandle(Type::New(
cls, type_args, TokenPosition::kNoSource, Nullability::kNonNullable));
Type& type =
Type::ZoneHandle(Type::New(cls, type_args, Nullability::kNonNullable));
ASSERT(type.IsInstantiated());
type.SetIsFinalized();
return CompileType(CompileType::kNonNullable, cid, &type);
@ -1480,8 +1481,9 @@ CompileType AllocateTypedDataInstr::ComputeType() const {
CompileType AllocateObjectInstr::ComputeType() const {
if (!closure_function().IsNull()) {
ASSERT(cls().id() == kClosureCid);
return CompileType(CompileType::kNonNullable, kClosureCid,
&Type::ZoneHandle(closure_function().SignatureType()));
const FunctionType& sig =
FunctionType::ZoneHandle(closure_function().signature());
return CompileType(CompileType::kNonNullable, kClosureCid, &sig);
}
// TODO(vegorov): Incorporate type arguments into the returned type.
return CompileType::FromCid(cls().id());

View file

@ -169,15 +169,16 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_Refinement) {
const Class& object_class =
Class::Handle(thread->isolate_group()->object_store()->object_class());
const FunctionType& signature = FunctionType::Handle(FunctionType::New());
const Function& target_func = Function::ZoneHandle(Function::New(
String::Handle(Symbols::New(thread, "dummy2")),
signature, String::Handle(Symbols::New(thread, "dummy2")),
FunctionLayout::kRegularFunction,
/*is_static=*/true,
/*is_const=*/false,
/*is_abstract=*/false,
/*is_external=*/false,
/*is_native=*/true, object_class, TokenPosition::kNoSource));
target_func.set_result_type(AbstractType::Handle(Type::IntType()));
signature.set_result_type(AbstractType::Handle(Type::IntType()));
const Field& field = Field::ZoneHandle(
Field::New(String::Handle(Symbols::New(thread, "dummy")),

View file

@ -84,8 +84,6 @@ bool CHA::ConcreteSubclasses(const Class& cls,
}
bool CHA::IsImplemented(const Class& cls) {
// Function type aliases have different type checking rules.
ASSERT(!cls.IsTypedefClass());
// Can't track dependencies for classes on the VM heap since those are
// read-only.
// TODO(fschneider): Enable tracking of CHA dependent code for VM heap

View file

@ -14,31 +14,32 @@ namespace compiler {
namespace ffi {
// TODO(dartbug.com/36607): Cache the trampolines.
FunctionPtr TrampolineFunction(const Function& dart_signature,
const Function& c_signature) {
FunctionPtr TrampolineFunction(const FunctionType& dart_signature,
const FunctionType& c_signature) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
String& name = String::Handle(zone, Symbols::New(thread, "FfiTrampoline"));
const Library& lib = Library::Handle(zone, Library::FfiLibrary());
const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
Function& function =
Function::Handle(zone, Function::New(name, FunctionLayout::kFfiTrampoline,
/*is_static=*/true,
/*is_const=*/false,
/*is_abstract=*/false,
/*is_external=*/false,
/*is_native=*/false, owner_class,
TokenPosition::kMinSource));
FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
Function& function = Function::Handle(
zone, Function::New(signature, name, FunctionLayout::kFfiTrampoline,
/*is_static=*/true,
/*is_const=*/false,
/*is_abstract=*/false,
/*is_external=*/false,
/*is_native=*/false, owner_class,
TokenPosition::kMinSource));
function.set_is_debuggable(false);
function.set_num_fixed_parameters(dart_signature.num_fixed_parameters());
function.set_result_type(
signature.set_result_type(
AbstractType::Handle(zone, dart_signature.result_type()));
function.set_parameter_types(
signature.set_parameter_types(
Array::Handle(zone, dart_signature.parameter_types()));
// The signature function won't have any names for the parameters. We need to
// assign unique names for scope building and error messages.
function.CreateNameArrayIncludingFlags(Heap::kNew);
signature.CreateNameArrayIncludingFlags(Heap::kOld);
const intptr_t num_params = dart_signature.num_fixed_parameters();
for (intptr_t i = 0; i < num_params; ++i) {
if (i == 0) {
@ -46,17 +47,12 @@ FunctionPtr TrampolineFunction(const Function& dart_signature,
} else {
name = Symbols::NewFormatted(thread, ":ffi_param%" Pd, i);
}
function.SetParameterNameAt(i, name);
signature.SetParameterNameAt(i, name);
}
function.TruncateUnusedParameterFlags();
signature.FinalizeNameArrays(function);
function.SetFfiCSignature(c_signature);
Type& type = Type::Handle(zone);
type ^= function.SignatureType(Nullability::kLegacy);
type ^= ClassFinalizer::FinalizeType(type);
function.SetSignatureType(type);
ASSERT(
Type::Handle(function.SignatureType(Nullability::kLegacy)).IsFinalized());
signature ^= ClassFinalizer::FinalizeType(signature);
function.set_signature(signature);
return function.raw();
}

View file

@ -19,8 +19,8 @@ namespace compiler {
namespace ffi {
FunctionPtr TrampolineFunction(const Function& dart_signature,
const Function& c_signature);
FunctionPtr TrampolineFunction(const FunctionType& dart_signature,
const FunctionType& c_signature);
} // namespace ffi

View file

@ -4,6 +4,7 @@
#include "vm/compiler/ffi/callback.h"
#include "vm/class_finalizer.h"
#include "vm/symbols.h"
namespace dart {
@ -12,7 +13,7 @@ namespace compiler {
namespace ffi {
FunctionPtr NativeCallbackFunction(const Function& c_signature,
FunctionPtr NativeCallbackFunction(const FunctionType& c_signature,
const Function& dart_target,
const Instance& exceptional_return) {
Thread* const thread = Thread::Current();
@ -20,7 +21,7 @@ FunctionPtr NativeCallbackFunction(const Function& c_signature,
// Create a new Function named '<target>_FfiCallback' and stick it in the
// 'dart:ffi' library. Note that these functions will never be invoked by
// Dart, so they have may have duplicate names.
// Dart, so they may have duplicate names.
Zone* const zone = thread->zone();
const auto& name = String::Handle(
zone, Symbols::FromConcat(thread, Symbols::FfiCallback(),
@ -28,7 +29,8 @@ FunctionPtr NativeCallbackFunction(const Function& c_signature,
const Library& lib = Library::Handle(zone, Library::FfiLibrary());
const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
const Function& function =
Function::Handle(zone, Function::New(name, FunctionLayout::kFfiTrampoline,
Function::Handle(zone, Function::New(Object::null_function_type(), name,
FunctionLayout::kFfiTrampoline,
/*is_static=*/true,
/*is_const=*/false,
/*is_abstract=*/false,

View file

@ -19,7 +19,7 @@ namespace compiler {
namespace ffi {
FunctionPtr NativeCallbackFunction(const Function& c_signature,
FunctionPtr NativeCallbackFunction(const FunctionType& c_signature,
const Function& dart_target,
const Instance& exceptional_return);

View file

@ -27,7 +27,7 @@ const intptr_t kNativeParamsStartAt = 1;
// Representations of the arguments and return value of a C signature function.
static const NativeFunctionType& NativeFunctionSignature(
Zone* zone,
const Function& c_signature) {
const FunctionType& c_signature) {
ASSERT(c_signature.NumOptionalParameters() == 0);
ASSERT(c_signature.NumOptionalPositionalParameters() == 0);
@ -55,7 +55,8 @@ static const NativeFunctionType& NativeFunctionSignature(
BaseMarshaller::BaseMarshaller(Zone* zone, const Function& dart_signature)
: zone_(zone),
dart_signature_(dart_signature),
c_signature_(Function::ZoneHandle(zone, dart_signature.FfiCSignature())),
c_signature_(
FunctionType::ZoneHandle(zone, dart_signature.FfiCSignature())),
native_calling_convention_(NativeCallingConvention::FromSignature(
zone,
NativeFunctionSignature(zone_, c_signature_))) {

View file

@ -135,7 +135,7 @@ class BaseMarshaller : public ZoneAllocated {
// Contains the function pointer as argument #0.
// The Dart signature is used for the function and argument names.
const Function& dart_signature_;
const Function& c_signature_;
const FunctionType& c_signature_;
const NativeCallingConvention& native_calling_convention_;
};

View file

@ -24,7 +24,7 @@ using NativeLocations = ZoneGrowableArray<const NativeLocation*>;
// Calculates native calling convention, is not aware of Dart calling
// convention constraints.
//
// This class is meant to beembedded in a class that is aware of Dart calling
// This class is meant to be embedded in a class that is aware of Dart calling
// convention constraints.
class NativeCallingConvention : public ZoneAllocated {
public:

View file

@ -1007,8 +1007,7 @@ Fragment BaseFlowGraphBuilder::BuildFfiAsFunctionInternalCall(
ASSERT(dart_type.IsFunctionType() && native_type.IsFunctionType());
const Function& target =
Function::ZoneHandle(compiler::ffi::TrampolineFunction(
Function::Handle(Z, Type::Cast(dart_type).signature()),
Function::Handle(Z, Type::Cast(native_type).signature())));
FunctionType::Cast(dart_type), FunctionType::Cast(native_type)));
Fragment code;
// Store the pointer in the context, we cannot load the untagged address

View file

@ -205,8 +205,8 @@ InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
AbstractType& type = type_translator.BuildType();
type_arguments.SetTypeAt(0, type);
// Instantiate class.
type = Type::New(list_class, type_arguments, TokenPosition::kNoSource);
type = ClassFinalizer::FinalizeType(type);
type = Type::New(list_class, type_arguments);
type = ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
type_arguments = type.arguments();
// Fill array with constant elements.
const intptr_t length = reader.ReadUInt();
@ -251,9 +251,9 @@ InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
type_arguments.SetTypeAt(j, type_translator.BuildType());
}
// Instantiate class.
auto& type = AbstractType::Handle(
Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
type = ClassFinalizer::FinalizeType(type);
auto& type = AbstractType::Handle(Z, Type::New(klass, type_arguments));
type =
ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
type_arguments = type.arguments();
instance.SetTypeArguments(type_arguments);
} else {

View file

@ -492,7 +492,7 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling(
Fragment prologue = B->BuildDefaultTypeHandling(dart_function);
if (dart_function.IsClosureFunction() &&
dart_function.NumParentTypeParameters() > 0) {
dart_function.NumParentTypeArguments() > 0) {
LocalVariable* closure = parsed_function()->ParameterVariable(0);
// Function with yield points can not be generic itself but the outer
@ -508,10 +508,9 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling(
prologue += LoadLocal(closure);
prologue += LoadNativeField(Slot::Closure_function_type_arguments());
prologue += IntConstant(dart_function.NumParentTypeParameters());
prologue += IntConstant(dart_function.NumParentTypeArguments());
prologue += IntConstant(dart_function.NumTypeParameters() +
dart_function.NumParentTypeParameters());
prologue += IntConstant(dart_function.NumTypeArguments());
const auto& prepend_function =
flow_graph_builder_->PrependTypeArgumentsFunction();
@ -1005,7 +1004,9 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraph() {
ActiveClassScope active_class_scope(active_class(), &klass);
ActiveMemberScope active_member(active_class(), &outermost_function);
ActiveTypeParametersScope active_type_params(active_class(), function, Z);
FunctionType& signature = FunctionType::Handle(Z, function.signature());
ActiveTypeParametersScope active_type_params(active_class(), function,
&signature, Z);
ParseKernelASTFunction();
@ -1043,7 +1044,6 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraph() {
return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(function);
case FunctionLayout::kFfiTrampoline:
return flow_graph_builder_->BuildGraphOfFfiTrampoline(function);
case FunctionLayout::kSignatureFunction:
case FunctionLayout::kIrregexpFunction:
break;
}
@ -1101,7 +1101,6 @@ void StreamingFlowGraphBuilder::ParseKernelASTFunction() {
SetupDefaultParameterValues();
}
break;
case FunctionLayout::kSignatureFunction:
case FunctionLayout::kIrregexpFunction:
UNREACHABLE();
break;
@ -4983,9 +4982,9 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
// Finalize function type.
Type& signature_type = Type::Handle(Z, function.SignatureType());
signature_type ^= ClassFinalizer::FinalizeType(signature_type);
function.SetSignatureType(signature_type);
FunctionType& signature = FunctionType::Handle(Z, function.signature());
signature ^= ClassFinalizer::FinalizeType(signature);
function.set_signature(signature);
ClosureFunctionsCache::AddClosureFunctionLocked(function);
break;
@ -5076,8 +5075,8 @@ Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction() {
const TypeArguments& type_arguments =
T.BuildTypeArguments(list_length); // read types.
ASSERT(type_arguments.Length() == 1 && type_arguments.IsInstantiated());
const Function& native_sig = Function::Handle(
Z, Type::CheckedHandle(Z, type_arguments.TypeAt(0)).signature());
const FunctionType& native_sig =
FunctionType::CheckedHandle(Z, type_arguments.TypeAt(0));
Fragment code;
const intptr_t positional_count =

View file

@ -792,13 +792,6 @@ uint32_t KernelFingerprintHelper::CalculateFunctionFingerprint() {
uint32_t KernelSourceFingerprintHelper::CalculateClassFingerprint(
const Class& klass) {
Zone* zone = Thread::Current()->zone();
// Handle typedefs.
if (klass.IsTypedefClass()) {
const Function& func = Function::Handle(zone, klass.signature_function());
return CalculateFunctionFingerprint(func);
}
String& name = String::Handle(zone, klass.Name());
const Array& fields = Array::Handle(zone, klass.fields());
const Array& functions = Array::Handle(zone, klass.current_functions());

View file

@ -2688,11 +2688,13 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks(
info.parameter_names = MakeTemporary("parameter_names");
body += LoadLocal(info.function);
body += LoadNativeField(Slot::Function_parameter_types());
body += LoadNativeField(Slot::Function_signature());
body += LoadNativeField(Slot::FunctionType_parameter_types());
info.parameter_types = MakeTemporary("parameter_types");
body += LoadLocal(info.function);
body += LoadNativeField(Slot::Function_type_parameters());
body += LoadNativeField(Slot::Function_signature());
body += LoadNativeField(Slot::FunctionType_type_parameters());
info.type_parameters = MakeTemporary("type_parameters");
body += LoadLocal(info.closure);
@ -3068,7 +3070,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
Function::ZoneHandle(Z, function.parent_function());
const Class& owner = Class::ZoneHandle(Z, parent.Owner());
AbstractType& type = AbstractType::ZoneHandle(Z);
type = Type::New(owner, TypeArguments::Handle(Z), owner.token_pos());
type = Type::New(owner, TypeArguments::Handle(Z));
type = ClassFinalizer::FinalizeType(type);
body += Constant(type);
} else {

View file

@ -713,8 +713,7 @@ Type& TranslationHelper::GetDeclarationType(const Class& klass) {
type = klass.DeclarationType();
} else {
// Note that the type argument vector is not yet extended.
type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
klass.token_pos());
type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()));
}
return type;
}
@ -727,23 +726,27 @@ void TranslationHelper::SetupFieldAccessorFunction(
bool is_method = !function.IsStaticFunction();
intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0);
const FunctionType& signature = FunctionType::Handle(Z, function.signature());
function.SetNumOptionalParameters(0, false);
function.set_num_fixed_parameters(parameter_count);
function.set_parameter_types(
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
function.CreateNameArrayIncludingFlags(Heap::kNew);
if (parameter_count > 0) {
signature.set_parameter_types(
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
}
signature.CreateNameArrayIncludingFlags(Heap::kOld);
intptr_t pos = 0;
if (is_method) {
function.SetParameterTypeAt(pos, GetDeclarationType(klass));
function.SetParameterNameAt(pos, Symbols::This());
signature.SetParameterTypeAt(pos, GetDeclarationType(klass));
signature.SetParameterNameAt(pos, Symbols::This());
pos++;
}
if (is_setter) {
function.SetParameterTypeAt(pos, field_type);
function.SetParameterNameAt(pos, Symbols::Value());
signature.SetParameterTypeAt(pos, field_type);
signature.SetParameterNameAt(pos, Symbols::Value());
pos++;
}
signature.FinalizeNameArrays(function);
}
void TranslationHelper::ReportError(const char* format, ...) {
@ -2855,11 +2858,13 @@ intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
}
}
ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
const Function& innermost,
Zone* Z)
ActiveTypeParametersScope::ActiveTypeParametersScope(
ActiveClass* active_class,
const Function& innermost,
const FunctionType* innermost_signature,
Zone* Z)
: active_class_(active_class), saved_(*active_class) {
active_class_->enclosing = &innermost;
active_class_->enclosing = innermost_signature;
intptr_t num_params = 0;
@ -2889,11 +2894,11 @@ ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
ActiveTypeParametersScope::ActiveTypeParametersScope(
ActiveClass* active_class,
const Function* function,
const FunctionType* innermost_signature,
const TypeArguments& new_params,
Zone* Z)
: active_class_(active_class), saved_(*active_class) {
active_class_->enclosing = function;
active_class_->enclosing = innermost_signature;
if (new_params.IsNull()) return;
@ -3022,8 +3027,7 @@ void TypeTranslator::BuildInterfaceType(bool simple) {
result_ = Type::Cast(result_).ToNullability(nullability, Heap::kOld);
} else {
// Note that the type argument vector is not yet extended.
result_ = Type::New(klass, Object::null_type_arguments(),
klass.token_pos(), nullability);
result_ = Type::New(klass, Object::null_type_arguments(), nullability);
}
return;
}
@ -3032,8 +3036,7 @@ void TypeTranslator::BuildInterfaceType(bool simple) {
helper_->ReadListLength(); // read type_arguments list length.
const TypeArguments& type_arguments =
BuildTypeArguments(length); // read type arguments.
result_ =
Type::New(klass, type_arguments, TokenPosition::kNoSource, nullability);
result_ = Type::New(klass, type_arguments, nullability);
result_ = result_.NormalizeFutureOrType(Heap::kOld);
if (finalize_) {
ASSERT(active_class_->klass != NULL);
@ -3042,17 +3045,16 @@ void TypeTranslator::BuildInterfaceType(bool simple) {
}
void TypeTranslator::BuildFunctionType(bool simple) {
Function& signature_function = Function::ZoneHandle(
Z, Function::NewSignatureFunction(*active_class_->klass,
active_class_->enclosing != NULL
? *active_class_->enclosing
: Function::Handle(Z),
TokenPosition::kNoSource));
const intptr_t num_enclosing_type_arguments =
active_class_->enclosing != NULL
? active_class_->enclosing->NumTypeArguments()
: 0;
Nullability nullability = helper_->ReadNullability();
if (apply_legacy_erasure_) {
nullability = Nullability::kLegacy;
}
FunctionType& signature = FunctionType::ZoneHandle(
Z, FunctionType::New(num_enclosing_type_arguments, nullability));
// Suspend finalization of types inside this one. They will be finalized after
// the whole function type is constructed.
@ -3063,13 +3065,14 @@ void TypeTranslator::BuildFunctionType(bool simple) {
finalize_ = false;
if (!simple) {
LoadAndSetupTypeParameters(active_class_, signature_function,
helper_->ReadListLength(), signature_function);
LoadAndSetupTypeParameters(
active_class_, Object::null_function(), Object::null_class(), signature,
helper_->ReadListLength(), active_class_->klass->nnbd_mode());
}
ActiveTypeParametersScope scope(
active_class_, &signature_function,
TypeArguments::Handle(Z, signature_function.type_parameters()), Z);
active_class_, &signature,
TypeArguments::Handle(Z, signature.type_parameters()), Z);
intptr_t required_count;
intptr_t all_count;
@ -3086,23 +3089,25 @@ void TypeTranslator::BuildFunctionType(bool simple) {
all_count = positional_count;
}
// The additional first parameter is the receiver type (set to dynamic).
signature_function.set_num_fixed_parameters(1 + required_count);
signature_function.SetNumOptionalParameters(
all_count - required_count, positional_count > required_count);
// The additional first parameter is the receiver (type set to dynamic).
const intptr_t kImplicitClosureParam = 1;
signature.set_num_implicit_parameters(kImplicitClosureParam);
signature.set_num_fixed_parameters(kImplicitClosureParam + required_count);
signature.SetNumOptionalParameters(all_count - required_count,
positional_count > required_count);
signature_function.set_parameter_types(
Array::Handle(Z, Array::New(1 + all_count, Heap::kOld)));
signature_function.CreateNameArrayIncludingFlags(Heap::kOld);
signature.set_parameter_types(Array::Handle(
Z, Array::New(kImplicitClosureParam + all_count, Heap::kOld)));
signature.CreateNameArrayIncludingFlags(Heap::kOld);
intptr_t pos = 0;
signature_function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
signature_function.SetParameterNameAt(pos, H.DartSymbolPlain("_receiver_"));
signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
signature.SetParameterNameAt(pos, H.DartSymbolPlain("_receiver_"));
++pos;
for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
BuildTypeInternal(); // read ith positional parameter.
signature_function.SetParameterTypeAt(pos, result_);
signature_function.SetParameterNameAt(pos, H.DartSymbolPlain("noname"));
signature.SetParameterTypeAt(pos, result_);
signature.SetParameterNameAt(pos, H.DartSymbolPlain("noname"));
}
if (!simple) {
@ -3113,36 +3118,30 @@ void TypeTranslator::BuildFunctionType(bool simple) {
String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
BuildTypeInternal(); // read named_parameters[i].type.
const uint8_t flags = helper_->ReadFlags(); // read flags
signature_function.SetParameterTypeAt(pos, result_);
signature_function.SetParameterNameAt(pos, name);
signature.SetParameterTypeAt(pos, result_);
signature.SetParameterNameAt(pos, name);
if (!apply_legacy_erasure_ &&
(flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) {
signature_function.SetIsRequiredAt(pos);
signature.SetIsRequiredAt(pos);
}
}
}
signature_function.TruncateUnusedParameterFlags();
signature.TruncateUnusedParameterFlags();
if (!simple) {
helper_->SkipOptionalDartType(); // read typedef type.
}
BuildTypeInternal(); // read return type.
signature_function.set_result_type(result_);
signature.set_result_type(result_);
finalize_ = finalize;
Type& signature_type =
Type::ZoneHandle(Z, signature_function.SignatureType(nullability));
if (finalize_) {
signature_type ^= ClassFinalizer::FinalizeType(signature_type);
// Do not refer to signature_function anymore, since it may have been
// replaced during canonicalization.
signature_function = Function::null();
signature ^= ClassFinalizer::FinalizeType(signature);
}
result_ = signature_type.raw();
result_ = signature.raw();
}
void TypeTranslator::BuildTypeParameterType() {
@ -3290,8 +3289,7 @@ const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments(
// We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
// finalize the argument types.
// (This can for example make the [type_arguments] vector larger)
Type& type = Type::Handle(
Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
Type& type = Type::Handle(Z, Type::New(receiver_class, type_arguments));
if (finalize_) {
type ^= ClassFinalizer::FinalizeType(type);
}
@ -3303,16 +3301,23 @@ const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments(
void TypeTranslator::LoadAndSetupTypeParameters(
ActiveClass* active_class,
const Object& set_on,
const Function& function,
const Class& parameterized_class,
const FunctionType& parameterized_signature,
intptr_t type_parameter_count,
const Function& parameterized_function) {
const NNBDMode nnbd_mode) {
ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
ASSERT(type_parameter_count >= 0);
if (type_parameter_count == 0) {
return;
}
ASSERT(set_on.IsClass() || set_on.IsFunction());
bool set_on_class = set_on.IsClass();
ASSERT(set_on_class == parameterized_function.IsNull());
// The finalized index of a type parameter can only be determined if the
// length of the flattened type argument vector is known, which in turn can
// only be determined after the super type and its class have been loaded.
// Due to the added complexity of loading classes out of order from the kernel
// file, class type parameter indices are not finalized during class loading.
// However, function type parameter indices can be immediately finalized.
// First setup the type parameters, so if any of the following code uses it
// (in a recursive way) we're fine.
@ -3320,15 +3325,27 @@ void TypeTranslator::LoadAndSetupTypeParameters(
TypeParameter& parameter = TypeParameter::Handle(Z);
const Type& null_bound = Type::Handle(Z);
const NNBDMode nnbd_mode = set_on.IsClass()
? Class::Cast(set_on).nnbd_mode()
: Function::Cast(set_on).nnbd_mode();
const Nullability nullability = (nnbd_mode == NNBDMode::kOptedInLib)
? Nullability::kNonNullable
: Nullability::kLegacy;
// Step a) Create array of [TypeParameter] objects (without bound).
// Step a)
// - Create array of [TypeParameter] objects (without bound).
// - Create array of [String] objects.
type_parameters = TypeArguments::New(type_parameter_count);
intptr_t offset = 0;
if (!parameterized_class.IsNull()) {
ASSERT(parameterized_class.type_parameters() == TypeArguments::null());
parameterized_class.set_type_parameters(type_parameters);
} else {
ASSERT(parameterized_signature.type_parameters() == TypeArguments::null());
parameterized_signature.set_type_parameters(type_parameters);
offset = parameterized_signature.NumParentTypeArguments();
if (!function.IsNull()) {
function.SetNumTypeParameters(type_parameter_count);
}
}
const Library& lib = Library::Handle(Z, active_class->klass->library());
{
AlternativeReadingScope alt(&helper_->reader_);
@ -3336,26 +3353,16 @@ void TypeTranslator::LoadAndSetupTypeParameters(
TypeParameterHelper helper(helper_);
helper.Finish();
parameter = TypeParameter::New(
set_on_class ? *active_class->klass : Class::Handle(Z),
parameterized_function, i,
H.DartIdentifier(lib, helper.name_index_), // read ith name index.
null_bound, helper.IsGenericCovariantImpl(), nullability,
TokenPosition::kNoSource);
parameter.SetCanonical();
parameter.SetDeclaration(true);
parameterized_class, offset, offset + i,
H.DartIdentifier(lib, helper.name_index_), null_bound,
helper.IsGenericCovariantImpl(), nullability);
type_parameters.SetTypeAt(i, parameter);
}
}
if (set_on.IsClass()) {
Class::Cast(set_on).set_type_parameters(type_parameters);
} else {
Function::Cast(set_on).set_type_parameters(type_parameters);
}
const Function* enclosing = NULL;
if (!parameterized_function.IsNull()) {
enclosing = &parameterized_function;
const FunctionType* enclosing = NULL;
if (!parameterized_signature.IsNull()) {
enclosing = &parameterized_signature;
}
ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
@ -3376,9 +3383,8 @@ void TypeTranslator::LoadAndSetupTypeParameters(
helper.Finish();
}
if (set_on.IsFunction()) {
Function::Cast(set_on).UpdateCachedDefaultTypeArguments(Thread::Current());
}
// Note that function.UpdateCachedDefaultTypeArguments() is called in
// function.set_signature() and is not required here.
// Fix bounds and default arguments in all derived type parameters (with
// different nullabilities).
@ -3389,10 +3395,13 @@ void TypeTranslator::LoadAndSetupTypeParameters(
i < n; ++i) {
derived ^= active_class->derived_type_parameters->At(i);
if (derived.bound() == AbstractType::null() &&
(derived.parameterized_class() == set_on.raw() ||
derived.parameterized_function() == set_on.raw())) {
ASSERT(!derived.IsFinalized());
parameter ^= type_parameters.TypeAt(derived.index());
((!parameterized_class.IsNull() &&
derived.parameterized_class() == parameterized_class.raw()) ||
(!parameterized_signature.IsNull() &&
derived.parameterized_class() == Class::null() &&
derived.index() >= offset &&
derived.index() < offset + type_parameter_count))) {
parameter ^= type_parameters.TypeAt(derived.index() - offset);
type = parameter.bound();
derived.set_bound(type);
type = parameter.default_argument();
@ -3404,7 +3413,6 @@ void TypeTranslator::LoadAndSetupTypeParameters(
const Type& TypeTranslator::ReceiverType(const Class& klass) {
ASSERT(!klass.IsNull());
ASSERT(!klass.IsTypedefClass());
// Note that if klass is _Closure, the returned type will be _Closure,
// and not the signature type.
Type& type = Type::ZoneHandle(Z);
@ -3412,7 +3420,7 @@ const Type& TypeTranslator::ReceiverType(const Class& klass) {
type = klass.DeclarationType();
} else {
type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
klass.token_pos(), Nullability::kNonNullable);
Nullability::kNonNullable);
}
return type;
}
@ -3524,13 +3532,16 @@ void TypeTranslator::SetupFunctionParameters(
bool is_factory = function.IsFactory();
intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;
const FunctionType& signature = FunctionType::Handle(Z, function.signature());
ASSERT(!signature.IsNull());
if (!is_factory) {
LoadAndSetupTypeParameters(active_class_, function,
helper_->ReadListLength(), function);
LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
signature, helper_->ReadListLength(),
function.nnbd_mode());
function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
}
ActiveTypeParametersScope scope(active_class_, function, Z);
ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
function_node_helper->ReadUntilExcluding(
FunctionNodeHelper::kPositionalParameters);
@ -3555,23 +3566,27 @@ void TypeTranslator::SetupFunctionParameters(
}
intptr_t parameter_count = extra_parameters + total_parameter_count;
function.set_parameter_types(
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
function.CreateNameArrayIncludingFlags(Heap::kOld);
intptr_t pos = 0;
if (is_method) {
ASSERT(!klass.IsNull());
function.SetParameterTypeAt(pos, H.GetDeclarationType(klass));
function.SetParameterNameAt(pos, Symbols::This());
pos++;
} else if (is_closure) {
function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
function.SetParameterNameAt(pos, Symbols::ClosureParameter());
pos++;
} else if (is_factory) {
function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
pos++;
if (parameter_count > 0) {
signature.set_parameter_types(
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
signature.CreateNameArrayIncludingFlags(Heap::kOld);
if (is_method) {
ASSERT(!klass.IsNull());
signature.SetParameterTypeAt(pos, H.GetDeclarationType(klass));
signature.SetParameterNameAt(pos, Symbols::This());
pos++;
} else if (is_closure) {
signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
signature.SetParameterNameAt(pos, Symbols::ClosureParameter());
pos++;
} else if (is_factory) {
signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
signature.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
pos++;
}
} else {
ASSERT(!is_method && !is_closure && !is_factory);
}
const Library& lib = Library::Handle(Z, active_class_->klass->library());
@ -3587,8 +3602,9 @@ void TypeTranslator::SetupFunctionParameters(
helper_->SkipExpression(); // read (actual) initializer.
}
function.SetParameterTypeAt(pos, type);
function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
signature.SetParameterTypeAt(pos, type);
signature.SetParameterNameAt(pos,
H.DartIdentifier(lib, helper.name_index_));
}
intptr_t named_parameter_count_check =
@ -3604,13 +3620,14 @@ void TypeTranslator::SetupFunctionParameters(
helper_->SkipExpression(); // read (actual) initializer.
}
function.SetParameterTypeAt(pos, type);
function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
signature.SetParameterTypeAt(pos, type);
signature.SetParameterNameAt(pos,
H.DartIdentifier(lib, helper.name_index_));
if (helper.IsRequired()) {
function.SetIsRequiredAt(pos);
signature.SetIsRequiredAt(pos);
}
}
function.TruncateUnusedParameterFlags();
signature.FinalizeNameArrays(function);
function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters);
@ -3618,7 +3635,7 @@ void TypeTranslator::SetupFunctionParameters(
if (!function.IsGenerativeConstructor()) {
const AbstractType& return_type =
BuildTypeWithoutFinalization(); // read return type.
function.set_result_type(return_type);
signature.set_result_type(return_type);
function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType);
}
}

View file

@ -1365,9 +1365,9 @@ class ActiveClass {
const Function* member;
// The innermost enclosing function. This is used for building types, as a
// The innermost enclosing signature. This is used for building types, as a
// parent for function types.
const Function* enclosing;
const FunctionType* enclosing;
const TypeArguments* local_type_parameters;
@ -1410,9 +1410,9 @@ class ActiveMemberScope {
class ActiveEnclosingFunctionScope {
public:
ActiveEnclosingFunctionScope(ActiveClass* active_class,
const Function* enclosing)
const FunctionType* enclosing_signature)
: active_class_(active_class), saved_(*active_class) {
active_class_->enclosing = enclosing;
active_class_->enclosing = enclosing_signature;
}
~ActiveEnclosingFunctionScope() { *active_class_ = saved_; }
@ -1430,16 +1430,17 @@ class ActiveTypeParametersScope {
// parameters defined by 'innermost' and any enclosing *closures* (but not
// enclosing methods/top-level functions/classes).
//
// Also, the enclosing function is set to 'innermost'.
// Also, the enclosing signature is set to innermost's signature.
ActiveTypeParametersScope(ActiveClass* active_class,
const Function& innermost,
const FunctionType* innermost_signature,
Zone* Z);
// Append the list of the local type parameters to the list in ActiveClass.
//
// Also, the enclosing function is set to 'function'.
// Also, the enclosing signature is set to 'signature'.
ActiveTypeParametersScope(ActiveClass* active_class,
const Function* function,
const FunctionType* innermost_signature,
const TypeArguments& new_params,
Zone* Z);
@ -1470,9 +1471,11 @@ class TypeTranslator {
intptr_t length);
void LoadAndSetupTypeParameters(ActiveClass* active_class,
const Object& set_on,
const Function& function,
const Class& parameterized_class,
const FunctionType& parameterized_signature,
intptr_t type_parameter_count,
const Function& parameterized_function);
const NNBDMode nnbd_mode);
const Type& ReceiverType(const Class& klass);

View file

@ -54,14 +54,16 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
// Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
// e.g. for type translation.
const Class& klass = Class::Handle(zone_, function.Owner());
const Class& klass = Class::Handle(Z, function.Owner());
Function& outermost_function =
Function::Handle(Z, function.GetOutermostFunction());
ActiveClassScope active_class_scope(&active_class_, &klass);
ActiveMemberScope active_member(&active_class_, &outermost_function);
ActiveTypeParametersScope active_type_params(&active_class_, function, Z);
FunctionType& signature = FunctionType::Handle(Z, function.signature());
ActiveTypeParametersScope active_type_params(&active_class_, function,
&signature, Z);
LocalScope* enclosing_scope = NULL;
if (function.IsImplicitClosureFunction() && !function.is_static()) {
@ -88,7 +90,7 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
scope_->set_end_token_pos(function.end_token_pos());
// Add function type arguments variable before current context variable.
if ((function.IsGeneric() || function.HasGenericParent())) {
if (function.IsGeneric() || function.HasGenericParent()) {
LocalVariable* type_args_var = MakeVariable(
TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
@ -419,7 +421,6 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
}
break;
}
case FunctionLayout::kSignatureFunction:
case FunctionLayout::kIrregexpFunction:
UNREACHABLE();
}

View file

@ -232,7 +232,7 @@ namespace dart {
V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0xd8114d5f) \
V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0xd0dd0025) \
V(Object, ==, ObjectEquals, 0xd3f5f95a) \
V(Object, get:runtimeType, ObjectRuntimeType, 0x8177627e) \
V(Object, get:runtimeType, ObjectRuntimeType, 0x81775ebd) \
V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, 0xe61da79f) \
V(_StringBase, get:hashCode, String_getHashCode, 0x4e27ab52) \
V(_StringBase, get:_identityHashCode, String_identityHash, 0x1fec4010) \
@ -246,6 +246,8 @@ namespace dart {
V(_TwoByteString, ==, TwoByteString_equality, 0x483ef8d2) \
V(_Type, get:hashCode, Type_getHashCode, 0x4e27ab52) \
V(_Type, ==, Type_equality, 0xd3f5f1d8) \
V(_FunctionType, get:hashCode, FunctionType_getHashCode, 0x4e27ab52) \
V(_FunctionType, ==, FunctionType_equality, 0xd3f5f1d8) \
V(::, _getHash, Object_getHash, 0x1d1372ac) \
V(::, _setHash, Object_setHash, 0x77e0bb27) \
@ -434,7 +436,7 @@ namespace dart {
V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x1b858d66) \
V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x9e2320c0) \
V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0xfa1f5cf1) \
V(Object, get:runtimeType, ObjectRuntimeType, 0x8177627e)
V(Object, get:runtimeType, ObjectRuntimeType, 0x81775ebd)
// List of recognized list factories:
// (factory-name-symbol, class-name-string, constructor-name-string,

View file

@ -823,12 +823,12 @@ const word Symbols::kNullCharCodeSymbolOffset =
const word String::kHashBits = dart::String::kHashBits;
const int8_t Nullability::kNullable =
static_cast<int8_t>(dart::Nullability::kNullable);
const int8_t Nullability::kNonNullable =
static_cast<int8_t>(dart::Nullability::kNonNullable);
const int8_t Nullability::kLegacy =
static_cast<int8_t>(dart::Nullability::kLegacy);
const uint8_t Nullability::kNullable =
static_cast<uint8_t>(dart::Nullability::kNullable);
const uint8_t Nullability::kNonNullable =
static_cast<uint8_t>(dart::Nullability::kNonNullable);
const uint8_t Nullability::kLegacy =
static_cast<uint8_t>(dart::Nullability::kLegacy);
bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
return dart::Heap::IsAllocatableInNewSpace(instance_size);
@ -920,10 +920,18 @@ word LinkedHashMap::NextFieldOffset() {
return -kWordSize;
}
word AbstractType::NextFieldOffset() {
return -kWordSize;
}
word Type::NextFieldOffset() {
return -kWordSize;
}
word FunctionType::NextFieldOffset() {
return -kWordSize;
}
word TypeRef::NextFieldOffset() {
return -kWordSize;
}
@ -980,10 +988,6 @@ word PatchClass::NextFieldOffset() {
return -kWordSize;
}
word SignatureData::NextFieldOffset() {
return -kWordSize;
}
word FfiTrampolineData::NextFieldOffset() {
return -kWordSize;
}

View file

@ -501,8 +501,7 @@ class Function : public AllStatic {
static word kind_tag_offset();
static word packed_fields_offset();
static word parameter_names_offset();
static word parameter_types_offset();
static word type_parameters_offset();
static word signature_offset();
static word usage_counter_offset();
static word InstanceSize();
static word NextFieldOffset();
@ -656,6 +655,8 @@ class Pointer : public PointerBase {
class AbstractType : public AllStatic {
public:
static word type_test_stub_entry_point_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Type : public AllStatic {
@ -663,13 +664,24 @@ class Type : public AllStatic {
static word hash_offset();
static word type_state_offset();
static word arguments_offset();
static word signature_offset();
static word type_class_id_offset();
static word nullability_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class FunctionType : public AllStatic {
public:
static word hash_offset();
static word type_state_offset();
static word packed_fields_offset();
static word parameter_types_offset();
static word type_parameters_offset();
static word nullability_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TypeRef : public AllStatic {
public:
static word type_offset();
@ -679,9 +691,9 @@ class TypeRef : public AllStatic {
class Nullability : public AllStatic {
public:
static const int8_t kNullable;
static const int8_t kNonNullable;
static const int8_t kLegacy;
static const uint8_t kNullable;
static const uint8_t kNonNullable;
static const uint8_t kLegacy;
};
class Double : public AllStatic {
@ -770,12 +782,6 @@ class PatchClass : public AllStatic {
static word NextFieldOffset();
};
class SignatureData : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class FfiTrampolineData : public AllStatic {
public:
static word InstanceSize();
@ -1125,6 +1131,7 @@ class ObjectStore : public AllStatic {
static word double_type_offset();
static word int_type_offset();
static word string_type_offset();
static word type_type_offset();
};
class Isolate : public AllStatic {

File diff suppressed because it is too large Load diff

View file

@ -112,8 +112,7 @@
FIELD(Function, kind_tag_offset) \
FIELD(Function, packed_fields_offset) \
FIELD(Function, parameter_names_offset) \
FIELD(Function, parameter_types_offset) \
FIELD(Function, type_parameters_offset) \
FIELD(Function, signature_offset) \
FIELD(FutureOr, type_arguments_offset) \
FIELD(GrowableObjectArray, data_offset) \
FIELD(GrowableObjectArray, length_offset) \
@ -153,6 +152,7 @@
FIELD(ObjectStore, double_type_offset) \
FIELD(ObjectStore, int_type_offset) \
FIELD(ObjectStore, string_type_offset) \
FIELD(ObjectStore, type_type_offset) \
FIELD(OneByteString, data_offset) \
FIELD(PointerBase, data_field_offset) \
FIELD(Pointer, type_arguments_offset) \
@ -261,10 +261,13 @@
FIELD(TwoByteString, data_offset) \
FIELD(Type, arguments_offset) \
FIELD(Type, hash_offset) \
FIELD(Type, signature_offset) \
FIELD(Type, type_class_id_offset) \
FIELD(Type, type_state_offset) \
FIELD(Type, nullability_offset) \
FIELD(FunctionType, hash_offset) \
FIELD(FunctionType, packed_fields_offset) \
FIELD(FunctionType, parameter_types_offset) \
FIELD(FunctionType, type_parameters_offset) \
FIELD(TypeParameter, parameterized_class_id_offset) \
FIELD(TypeParameter, index_offset) \
FIELD(TypeParameter, nullability_offset) \
@ -299,6 +302,7 @@
kNumberOfCpuRegisters - 1, \
[](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
\
SIZEOF(AbstractType, InstanceSize, AbstractTypeLayout) \
SIZEOF(ApiError, InstanceSize, ApiErrorLayout) \
SIZEOF(Array, InstanceSize, ArrayLayout) \
SIZEOF(Array, header_size, ArrayLayout) \
@ -324,6 +328,7 @@
SIZEOF(Float32x4, InstanceSize, Float32x4Layout) \
SIZEOF(Float64x2, InstanceSize, Float64x2Layout) \
SIZEOF(Function, InstanceSize, FunctionLayout) \
SIZEOF(FunctionType, InstanceSize, FunctionTypeLayout) \
SIZEOF(FutureOr, InstanceSize, FutureOrLayout) \
SIZEOF(GrowableObjectArray, InstanceSize, GrowableObjectArrayLayout) \
SIZEOF(ICData, InstanceSize, ICDataLayout) \
@ -355,7 +360,6 @@
SIZEOF(RegExp, InstanceSize, RegExpLayout) \
SIZEOF(Script, InstanceSize, ScriptLayout) \
SIZEOF(SendPort, InstanceSize, SendPortLayout) \
SIZEOF(SignatureData, InstanceSize, SignatureDataLayout) \
SIZEOF(SingleTargetCache, InstanceSize, SingleTargetCacheLayout) \
SIZEOF(Smi, InstanceSize, SmiLayout) \
SIZEOF(StackTrace, InstanceSize, StackTraceLayout) \

View file

@ -196,16 +196,21 @@ void StubCodeCompiler::GenerateInstanceOfStub(Assembler* assembler) {
// For use in GenerateTypeIsTopTypeForSubtyping and
// GenerateNullIsAssignableToType.
static void EnsureIsTypeOrTypeParameter(Assembler* assembler,
Register type_reg,
Register scratch_reg) {
static void EnsureIsTypeOrFunctionTypeOrTypeParameter(Assembler* assembler,
Register type_reg,
Register scratch_reg) {
#if defined(DEBUG)
compiler::Label is_type_param_or_type;
compiler::Label is_type_param_or_type_or_function_type;
__ LoadClassIdMayBeSmi(scratch_reg, type_reg);
__ CompareImmediate(scratch_reg, kTypeParameterCid);
__ BranchIf(EQUAL, &is_type_param_or_type, compiler::Assembler::kNearJump);
__ BranchIf(EQUAL, &is_type_param_or_type_or_function_type,
compiler::Assembler::kNearJump);
__ CompareImmediate(scratch_reg, kTypeCid);
__ BranchIf(EQUAL, &is_type_param_or_type, compiler::Assembler::kNearJump);
__ BranchIf(EQUAL, &is_type_param_or_type_or_function_type,
compiler::Assembler::kNearJump);
__ CompareImmediate(scratch_reg, kFunctionTypeCid);
__ BranchIf(EQUAL, &is_type_param_or_type_or_function_type,
compiler::Assembler::kNearJump);
// Type references show up in F-bounded polymorphism, which is limited
// to classes. Thus, TypeRefs only appear in places like class type
// arguments or the bounds of uninstantiated class type parameters.
@ -215,8 +220,8 @@ static void EnsureIsTypeOrTypeParameter(Assembler* assembler,
// a function type parameter or the type of a function parameter
// (respectively), we should never see a TypeRef here. This check is here
// in case this changes and we need to update this stub.
__ Stop("not a type or type parameter");
__ Bind(&is_type_param_or_type);
__ Stop("not a type or function type or type parameter");
__ Bind(&is_type_param_or_type_or_function_type);
#endif
}
@ -265,12 +270,14 @@ static void GenerateTypeIsTopTypeForSubtyping(Assembler* assembler,
__ MoveRegister(scratch1_reg, TypeTestABI::kDstTypeReg);
__ Bind(&check_top_type);
// scratch1_reg: Current type to check.
EnsureIsTypeOrTypeParameter(assembler, scratch1_reg, scratch2_reg);
EnsureIsTypeOrFunctionTypeOrTypeParameter(assembler, scratch1_reg,
scratch2_reg);
compiler::Label is_type_ref;
__ CompareClassId(scratch1_reg, kTypeParameterCid, scratch2_reg);
__ CompareClassId(scratch1_reg, kTypeCid, scratch2_reg);
// Type parameters can't be top types themselves, though a particular
// instantiation may result in a top type.
__ BranchIf(EQUAL, &done);
// Function types cannot be top types.
__ BranchIf(NOT_EQUAL, &done);
__ LoadField(
scratch2_reg,
compiler::FieldAddress(scratch1_reg,
@ -377,7 +384,8 @@ static void GenerateNullIsAssignableToType(Assembler* assembler,
__ BranchIf(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
__ Bind(&check_null_assignable);
// scratch1_reg: Current type to check.
EnsureIsTypeOrTypeParameter(assembler, scratch1_reg, scratch2_reg);
EnsureIsTypeOrFunctionTypeOrTypeParameter(assembler, scratch1_reg,
scratch2_reg);
compiler::Label is_not_type;
__ CompareClassId(scratch1_reg, kTypeCid, scratch2_reg);
__ BranchIf(NOT_EQUAL, &is_not_type, compiler::Assembler::kNearJump);
@ -614,12 +622,6 @@ void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
target::AbstractTypeLayout::kTypeStateFinalizedInstantiated);
__ BranchIf(NOT_EQUAL, &is_complex_case, Assembler::kNearJump);
// Check whether this [Type] is a function type.
__ LoadFieldFromOffset(TypeTestABI::kScratchReg, TypeTestABI::kDstTypeReg,
target::Type::signature_offset());
__ CompareObject(TypeTestABI::kScratchReg, NullObject());
__ BranchIf(NOT_EQUAL, &is_complex_case, Assembler::kNearJump);
// This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
__ BranchIfSmi(TypeTestABI::kInstanceReg, &is_complex_case);

View file

@ -119,11 +119,6 @@ class CheckFunctionTypesVisitor : public ObjectVisitor {
if (obj->IsFunction()) {
funcHandle_ ^= obj;
classHandle_ ^= funcHandle_.Owner();
// Signature functions get created, but not canonicalized, when function
// types get instantiated during run time type tests.
if (funcHandle_.IsSignatureFunction()) {
return;
}
// Verify that the result type of a function is canonical or a
// TypeParameter.
typeHandle_ ^= funcHandle_.result_type();
@ -2384,7 +2379,7 @@ DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(handle) == kTypeCid;
return IsTypeClassId(Api::ClassId(handle));
}
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
@ -5632,8 +5627,7 @@ static Dart_Handle GetTypeCommon(Dart_Handle library,
}
// Construct the type object, canonicalize it and return.
type ^=
Type::New(cls, type_args_obj, TokenPosition::kNoSource, nullability);
type ^= Type::New(cls, type_args_obj, nullability);
}
type ^= ClassFinalizer::FinalizeType(type);
return Api::NewHandle(T, type.raw());

View file

@ -1259,8 +1259,7 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
if ((function().IsGeneric() || function().HasGenericParent()) &&
type_arguments_available) {
intptr_t num_vars =
function().NumTypeParameters() + function().NumParentTypeParameters();
intptr_t num_vars = function().NumTypeArguments();
type_params_names.Grow(num_vars);
type_params_names.SetLength(num_vars);
TypeArguments& type_params = TypeArguments::Handle();
@ -1271,6 +1270,7 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
current = current.parent_function()) {
type_params = current.type_parameters();
intptr_t size = current.NumTypeParameters();
ASSERT(size == 0 || type_params.Length() == size);
ASSERT(mapping_offset >= size);
mapping_offset -= size;
for (intptr_t j = 0; j < size; ++j) {

View file

@ -2086,9 +2086,6 @@ void IsolateReloadContext::InvalidateFunctions(
Code& code = Code::Handle(zone);
for (intptr_t i = 0; i < functions.length(); i++) {
const Function& func = *functions[i];
if (func.IsSignatureFunction()) {
continue;
}
// Switch to unoptimized code or the lazy compilation stub.
func.SwitchToLazyCompiledUnoptimizedCode();

View file

@ -1418,8 +1418,9 @@ void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
// kImplementedClasses, [...].
// Set type parameters.
T.LoadAndSetupTypeParameters(&active_class_, *klass, type_parameter_count,
Function::Handle(Z));
T.LoadAndSetupTypeParameters(&active_class_, Object::null_function(), *klass,
Object::null_function_type(),
type_parameter_count, klass->nnbd_mode());
// Set super type. Some classes (e.g., Object) do not have one.
Tag type_tag = helper_.ReadTag(); // read super class type (part 1).
@ -1702,8 +1703,9 @@ void KernelLoader::FinishClassLoading(const Class& klass,
owner = &ClassForScriptAt(klass, source_uri_index);
}
Function& function = Function::ZoneHandle(
Z, Function::New(name, FunctionLayout::kConstructor,
FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
const Function& function = Function::ZoneHandle(
Z, Function::New(signature, name, FunctionLayout::kConstructor,
false, // is_static
constructor_helper.IsConst(),
false, // is_abstract
@ -1711,9 +1713,8 @@ void KernelLoader::FinishClassLoading(const Class& klass,
false, // is_native
*owner, constructor_helper.start_position_));
function.set_end_token_pos(constructor_helper.end_position_);
functions_.Add(&function);
function.set_kernel_offset(constructor_offset);
function.set_result_type(T.ReceiverType(klass));
signature.set_result_type(T.ReceiverType(klass));
function.set_has_pragma(has_pragma_annotation);
FunctionNodeHelper function_node_helper(&helper_);
@ -1738,6 +1739,16 @@ void KernelLoader::FinishClassLoading(const Class& klass,
constructor_helper.SetJustRead(ConstructorHelper::kFunction);
constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
if (klass.is_finalized()) {
// The owner class has already been marked as finalized (e.g. class
// 'NativeFieldWrapperClass1'), so the signature of this added constructor
// must be finalized here, since finalization of member types will not be
// called anymore.
signature ^= ClassFinalizer::FinalizeType(signature);
function.set_signature(signature);
}
functions_.Add(&function);
if ((FLAG_enable_mirrors || has_pragma_annotation) &&
annotation_count > 0) {
library.AddMetadata(function, constructor_offset);
@ -1981,8 +1992,9 @@ void KernelLoader::LoadProcedure(const Library& library,
// they are not reachable anymore and we never look them up by name.
const bool register_function = !name.Equals(Symbols::DebugProcedureName());
Function& function = Function::ZoneHandle(
Z, Function::New(name, kind,
const FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
const Function& function = Function::ZoneHandle(
Z, Function::New(signature, name, kind,
!is_method, // is_static
false, // is_const
is_abstract, is_external,
@ -2208,10 +2220,11 @@ InstancePtr KernelLoader::GenerateFieldAccessors(const Class& klass,
H.DartGetterName(field_helper->canonical_name_getter_);
const Object& script_class =
ClassForScriptAt(klass, field_helper->source_uri_index_);
const FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
Function& getter = Function::ZoneHandle(
Z,
Function::New(
getter_name,
signature, getter_name,
field_helper->IsStatic() ? FunctionLayout::kImplicitStaticGetter
: FunctionLayout::kImplicitGetter,
field_helper->IsStatic(),
@ -2228,7 +2241,7 @@ InstancePtr KernelLoader::GenerateFieldAccessors(const Class& klass,
getter.set_end_token_pos(field_helper->end_position_);
getter.set_kernel_offset(field.kernel_offset());
const AbstractType& field_type = AbstractType::Handle(Z, field.type());
getter.set_result_type(field_type);
signature.set_result_type(field_type);
getter.set_is_debuggable(false);
getter.set_accessor_field(field);
getter.set_is_extension_member(field.is_extension_member());
@ -2240,18 +2253,21 @@ InstancePtr KernelLoader::GenerateFieldAccessors(const Class& klass,
ASSERT(!field_helper->IsConst());
const String& setter_name =
H.DartSetterName(field_helper->canonical_name_setter_);
const FunctionType& signature =
FunctionType::Handle(Z, FunctionType::New());
Function& setter = Function::ZoneHandle(
Z, Function::New(setter_name, FunctionLayout::kImplicitSetter,
field_helper->IsStatic(),
false, // is_const
false, // is_abstract
false, // is_external
false, // is_native
script_class, field_helper->position_));
Z,
Function::New(signature, setter_name, FunctionLayout::kImplicitSetter,
field_helper->IsStatic(),
false, // is_const
false, // is_abstract
false, // is_external
false, // is_native
script_class, field_helper->position_));
functions_.Add(&setter);
setter.set_end_token_pos(field_helper->end_position_);
setter.set_kernel_offset(field.kernel_offset());
setter.set_result_type(Object::void_type());
signature.set_result_type(Object::void_type());
setter.set_is_debuggable(false);
setter.set_accessor_field(field);
setter.set_is_extension_member(field.is_extension_member());
@ -2400,25 +2416,27 @@ FunctionPtr CreateFieldInitializerFunction(Thread* thread,
initializer_owner.set_library_kernel_offset(lib.kernel_offset());
// Create a static initializer.
FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
const Function& initializer_fun = Function::Handle(
zone, Function::New(init_name, FunctionLayout::kFieldInitializer,
field.is_static(), // is_static
false, // is_const
false, // is_abstract
false, // is_external
false, // is_native
initializer_owner, TokenPosition::kNoSource));
zone,
Function::New(signature, init_name, FunctionLayout::kFieldInitializer,
field.is_static(), // is_static
false, // is_const
false, // is_abstract
false, // is_external
false, // is_native
initializer_owner, TokenPosition::kNoSource));
if (!field.is_static()) {
initializer_fun.set_num_fixed_parameters(1);
initializer_fun.set_parameter_types(
signature.set_parameter_types(
Array::Handle(zone, Array::New(1, Heap::kOld)));
initializer_fun.CreateNameArrayIncludingFlags(Heap::kOld);
initializer_fun.SetParameterTypeAt(
signature.CreateNameArrayIncludingFlags(Heap::kOld);
signature.SetParameterTypeAt(
0, AbstractType::Handle(zone, field_owner.DeclarationType()));
initializer_fun.SetParameterNameAt(0, Symbols::This());
initializer_fun.TruncateUnusedParameterFlags();
signature.SetParameterNameAt(0, Symbols::This());
signature.FinalizeNameArrays(initializer_fun);
}
initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
signature.set_result_type(AbstractType::Handle(zone, field.type()));
initializer_fun.set_is_reflectable(false);
initializer_fun.set_is_inlinable(false);
initializer_fun.set_token_pos(field.token_pos());
@ -2426,6 +2444,10 @@ FunctionPtr CreateFieldInitializerFunction(Thread* thread,
initializer_fun.set_accessor_field(field);
initializer_fun.InheritKernelOffsetFrom(field);
initializer_fun.set_is_extension_member(field.is_extension_member());
signature ^= ClassFinalizer::FinalizeType(signature);
initializer_fun.set_signature(signature);
field.SetInitializerFunction(initializer_fun);
return initializer_fun.raw();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -538,20 +538,6 @@ class EnumClassConflict : public ClassReasonForCancelling {
}
};
class TypedefClassConflict : public ClassReasonForCancelling {
public:
TypedefClassConflict(Zone* zone, const Class& from, const Class& to)
: ClassReasonForCancelling(zone, from, to) {}
StringPtr ToString() {
return String::NewFormatted(
from_.IsTypedefClass()
? "Typedef class cannot be redefined to be a non-typedef class: %s"
: "Class cannot be redefined to be a typedef class: %s",
from_.ToCString());
}
};
class EnsureFinalizedError : public ClassReasonForCancelling {
public:
EnsureFinalizedError(Zone* zone,
@ -699,14 +685,6 @@ void Class::CheckReload(const Class& replacement,
return;
}
// Class cannot change typedef property.
if (IsTypedefClass() != replacement.IsTypedefClass()) {
context->group_reload_context()->AddReasonForCancelling(
new (context->zone())
TypedefClassConflict(context->zone(), *this, replacement));
return;
}
if (is_finalized()) {
// Ensure the replacement class is also finalized.
const Error& error =

View file

@ -228,11 +228,7 @@ void PatchClass::PrintJSONImpl(JSONStream* stream, bool ref) const {
static void AddFunctionServiceId(const JSONObject& jsobj,
const Function& f,
const Class& cls) {
if (cls.IsNull()) {
ASSERT(f.IsSignatureFunction());
jsobj.AddServiceId(f);
return;
}
ASSERT(!cls.IsNull());
// Special kinds of functions use indices in their respective lists.
intptr_t id = -1;
const char* selector = NULL;
@ -283,13 +279,10 @@ static void AddFunctionServiceId(const JSONObject& jsobj,
void Function::PrintJSONImpl(JSONStream* stream, bool ref) const {
Class& cls = Class::Handle(Owner());
if (!cls.IsNull()) {
Error& err = Error::Handle();
err = cls.EnsureIsFinalized(Thread::Current());
ASSERT(err.IsNull());
} else {
ASSERT(IsSignatureFunction());
}
ASSERT(!cls.IsNull());
Error& err = Error::Handle();
err = cls.EnsureIsFinalized(Thread::Current());
ASSERT(err.IsNull());
JSONObject jsobj(stream);
AddCommonObjectProperties(&jsobj, "Function", ref);
AddFunctionServiceId(jsobj, *this, cls);
@ -1103,7 +1096,6 @@ void AbstractType::PrintJSONImpl(JSONStream* stream, bool ref) const {
}
void Type::PrintJSONImpl(JSONStream* stream, bool ref) const {
// TODO(regis): Function types are not handled properly.
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "Type");
@ -1127,6 +1119,13 @@ void Type::PrintJSONImpl(JSONStream* stream, bool ref) const {
}
}
void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "FunctionType");
// TODO(regis): Function types were not handled before, necessary now?
}
void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
@ -1149,6 +1148,7 @@ void TypeParameter::PrintJSONImpl(JSONStream* stream, bool ref) const {
const String& user_name = String::Handle(UserVisibleName());
const String& vm_name = String::Handle(Name());
AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
// TODO(regis): parameterizedClass is meaningless and always null.
const Class& param_cls = Class::Handle(parameterized_class());
jsobj.AddProperty("parameterizedClass", param_cls);
if (ref) {
@ -1472,10 +1472,6 @@ void ClosureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
Object::PrintJSONImpl(stream, ref);
}
void SignatureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
Object::PrintJSONImpl(stream, ref);
}
void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
Instance::PrintJSONImpl(stream, ref);
}

View file

@ -364,8 +364,7 @@ void ObjectStore::LazyInitFutureTypes() {
ASSERT(!type.IsNull());
type_args = TypeArguments::New(1);
type_args.SetTypeAt(0, type);
type = Type::New(cls, type_args, TokenPosition::kNoSource,
Nullability::kNonNullable);
type = Type::New(cls, type_args, Nullability::kNonNullable);
type.SetIsFinalized();
type ^= type.Canonicalize(thread, nullptr);
set_non_nullable_future_never_type(type);
@ -373,8 +372,7 @@ void ObjectStore::LazyInitFutureTypes() {
ASSERT(!type.IsNull());
type_args = TypeArguments::New(1);
type_args.SetTypeAt(0, type);
type = Type::New(cls, type_args, TokenPosition::kNoSource,
Nullability::kNullable);
type = Type::New(cls, type_args, Nullability::kNullable);
type.SetIsFinalized();
type ^= type.Canonicalize(thread, nullptr);
set_nullable_future_null_type(type);

View file

@ -132,6 +132,7 @@ class ObjectPointerVisitor;
RW(Class, weak_property_class) \
RW(Array, symbol_table) \
RW(Array, canonical_types) \
RW(Array, canonical_function_types) \
RW(Array, canonical_type_parameters) \
RW(Array, canonical_type_arguments) \
RW(Library, async_library) \

View file

@ -78,17 +78,20 @@ ISOLATE_UNIT_TEST_CASE(Class) {
// Create and populate the function arrays.
const Array& functions = Array::Handle(Array::New(6));
FunctionType& signature = FunctionType::Handle();
Function& function = Function::Handle();
String& function_name = String::Handle();
function_name = Symbols::New(thread, "foo");
function =
Function::New(function_name, FunctionLayout::kRegularFunction, false,
false, false, false, false, cls, TokenPosition::kMinSource);
signature = FunctionType::New();
function = Function::New(signature, function_name,
FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, function);
function_name = Symbols::New(thread, "bar");
function =
Function::New(function_name, FunctionLayout::kRegularFunction, false,
false, false, false, false, cls, TokenPosition::kMinSource);
signature = FunctionType::New();
function = Function::New(signature, function_name,
FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
const int kNumFixedParameters = 2;
const int kNumOptionalParameters = 3;
@ -99,26 +102,30 @@ ISOLATE_UNIT_TEST_CASE(Class) {
functions.SetAt(1, function);
function_name = Symbols::New(thread, "baz");
function =
Function::New(function_name, FunctionLayout::kRegularFunction, false,
false, false, false, false, cls, TokenPosition::kMinSource);
signature = FunctionType::New();
function = Function::New(signature, function_name,
FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
functions.SetAt(2, function);
function_name = Symbols::New(thread, "Foo");
function =
Function::New(function_name, FunctionLayout::kRegularFunction, true,
false, false, false, false, cls, TokenPosition::kMinSource);
signature = FunctionType::New();
function = Function::New(signature, function_name,
FunctionLayout::kRegularFunction, true, false, false,
false, false, cls, TokenPosition::kMinSource);
functions.SetAt(3, function);
function_name = Symbols::New(thread, "Bar");
function =
Function::New(function_name, FunctionLayout::kRegularFunction, true,
false, false, false, false, cls, TokenPosition::kMinSource);
signature = FunctionType::New();
function = Function::New(signature, function_name,
FunctionLayout::kRegularFunction, true, false, false,
false, false, cls, TokenPosition::kMinSource);
functions.SetAt(4, function);
function_name = Symbols::New(thread, "BaZ");
function =
Function::New(function_name, FunctionLayout::kRegularFunction, true,
false, false, false, false, cls, TokenPosition::kMinSource);
signature = FunctionType::New();
function = Function::New(signature, function_name,
FunctionLayout::kRegularFunction, true, false, false,
false, false, cls, TokenPosition::kMinSource);
functions.SetAt(5, function);
// Setup the functions in the class.
@ -2631,9 +2638,10 @@ ISOLATE_UNIT_TEST_CASE(Closure) {
const Context& context = Context::Handle(Context::New(0));
Function& parent = Function::Handle();
const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
parent =
Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
parent = Function::New(signature, parent_name,
FunctionLayout::kRegularFunction, false, false, false,
false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, parent);
{
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
@ -2708,9 +2716,10 @@ static FunctionPtr CreateFunction(const char* name) {
const Library& owner_library = Library::Handle(CreateDummyLibrary(lib_name));
owner_class.set_library(owner_library);
const String& function_name = String::ZoneHandle(Symbols::New(thread, name));
return Function::New(function_name, FunctionLayout::kRegularFunction, true,
false, false, false, false, owner_class,
TokenPosition::kMinSource);
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
return Function::New(signature, function_name,
FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kMinSource);
}
// Test for Code and Instruction object creation.
@ -3107,9 +3116,11 @@ static FunctionPtr GetDummyTarget(const char* name) {
const bool is_abstract = false;
const bool is_external = false;
const bool is_native = false;
return Function::New(function_name, FunctionLayout::kRegularFunction,
is_static, is_const, is_abstract, is_external, is_native,
cls, TokenPosition::kMinSource);
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
return Function::New(signature, function_name,
FunctionLayout::kRegularFunction, is_static, is_const,
is_abstract, is_external, is_native, cls,
TokenPosition::kMinSource);
}
ISOLATE_UNIT_TEST_CASE(ICData) {
@ -3948,9 +3959,10 @@ ISOLATE_UNIT_TEST_CASE(FindClosureIndex) {
Function& parent = Function::Handle();
const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
parent =
Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
parent = Function::New(signature, parent_name,
FunctionLayout::kRegularFunction, false, false, false,
false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, parent);
{
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
@ -3992,9 +4004,10 @@ ISOLATE_UNIT_TEST_CASE(FindInvocationDispatcherFunctionIndex) {
const Array& functions = Array::Handle(Array::New(1));
Function& parent = Function::Handle();
const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
parent =
Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
parent = Function::New(signature, parent_name,
FunctionLayout::kRegularFunction, false, false, false,
false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, parent);
{
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());

View file

@ -1023,7 +1023,7 @@ void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
explicit DedupListsVisitor(Zone* zone)
: Dedupper(zone),
list_(Array::Handle(zone)),
function_(Function::Handle(zone)) {}
field_(Field::Handle(zone)) {}
void VisitCode(const Code& code) {
if (!code.IsFunctionCode()) return;
@ -1042,36 +1042,34 @@ void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
}
void VisitFunction(const Function& function) {
list_ = PrepareParameterTypes(function);
list_ = Dedup(list_);
function.set_parameter_types(list_);
list_ = PrepareParameterNames(function);
list_ = Dedup(list_);
function.set_parameter_names(list_);
// No need to dedup parameter types, as they are stored in the
// canonicalized function type of the function.
// However, the function type of the function is only needed in case of
// recompilation or if available to mirrors, or for copied types
// to lazily generated tear offs. Also avoid attempting to change
// read-only VM objects for de-duplication.
// We cannot check precisely if a function is an entry point here,
// because the metadata has been dropped already. However, we use the
// has_pragma flag on the function as a conservative approximation.
// Resolution requires the number of parameters (no signature needed) and
// their names if any named parameter is required (signature needed).
if (FLAG_precompiled_mode && !function.InVMIsolateHeap() &&
!function.IsClosureFunction() && !function.IsFfiTrampoline() &&
function.name() != Symbols::Call().raw() && !function.is_native() &&
!function.HasRequiredNamedParameters() &&
!MayBeEntryPoint(function)) {
// Function type not needed for function type tests or resolution.
function.set_signature(Object::null_function_type());
}
}
private:
bool IsCorrectType(const Object& obj) const { return obj.IsArray(); }
ArrayPtr PrepareParameterTypes(const Function& function) {
list_ = function.parameter_types();
// Preserve parameter types in the JIT. Needed in case of recompilation
// in checked mode, or if available to mirrors, or for copied types to
// lazily generated tear offs. Also avoid attempting to change read-only
// VM objects for de-duplication.
if (FLAG_precompiled_mode && !list_.IsNull() &&
!list_.InVMIsolateHeap() && !function.IsSignatureFunction() &&
!function.IsClosureFunction() && !function.IsFfiTrampoline() &&
function.name() != Symbols::Call().raw()) {
// Parameter types not needed for function type tests.
for (intptr_t i = 0; i < list_.Length(); i++) {
list_.SetAt(i, Object::dynamic_type());
}
}
return list_.raw();
}
ArrayPtr PrepareParameterNames(const Function& function) {
list_ = function.parameter_names();
// Preserve parameter names in case of recompilation for the JIT. Also
@ -1087,8 +1085,23 @@ void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
return list_.raw();
}
bool MayBeEntryPoint(const Function& function) {
// Metadata has been dropped already.
// Use presence of pragma as conservative approximation.
if (function.has_pragma()) return true;
auto kind = function.kind();
if ((kind == FunctionLayout::kImplicitGetter) ||
(kind == FunctionLayout::kImplicitSetter) ||
(kind == FunctionLayout::kImplicitStaticGetter) ||
(kind == FunctionLayout::kFieldInitializer)) {
field_ = function.accessor_field();
if (!field_.IsNull() && field_.has_pragma()) return true;
}
return false;
}
Array& list_;
Function& function_;
Field& field_;
};
DedupListsVisitor visitor(zone);

View file

@ -500,13 +500,13 @@ bool ObjectLayout::FindObject(FindObjectVisitor* visitor) {
REGULAR_VISITOR(Class)
REGULAR_VISITOR(Type)
REGULAR_VISITOR(FunctionType)
REGULAR_VISITOR(TypeRef)
REGULAR_VISITOR(TypeParameter)
REGULAR_VISITOR(PatchClass)
REGULAR_VISITOR(Function)
COMPRESSED_VISITOR(Closure)
REGULAR_VISITOR(ClosureData)
REGULAR_VISITOR(SignatureData)
REGULAR_VISITOR(FfiTrampolineData)
REGULAR_VISITOR(Script)
REGULAR_VISITOR(Library)

View file

@ -819,8 +819,6 @@ class ClassLayout : public ObjectLayout {
POINTER_FIELD(LibraryPtr, library)
POINTER_FIELD(TypeArgumentsPtr, type_parameters) // Array of TypeParameter.
POINTER_FIELD(AbstractTypePtr, super_type)
POINTER_FIELD(FunctionPtr,
signature_function) // Associated function for typedef class.
POINTER_FIELD(ArrayPtr,
constants) // Canonicalized const instances of this class.
POINTER_FIELD(TypePtr, declaration_type) // Declaration type for this class.
@ -944,8 +942,6 @@ class FunctionLayout : public ObjectLayout {
/* an implicit closure (i.e., tear-off) */ \
V(ImplicitClosureFunction) \
/* a signature only without actual code */ \
V(SignatureFunction) \
/* getter functions e.g: get foo() { .. } */ \
V(GetterFunction) \
/* setter functions e.g: set foo(..) { .. } */ \
V(SetterFunction) \
@ -1076,9 +1072,6 @@ class FunctionLayout : public ObjectLayout {
uint64_t bitmap_;
};
static constexpr intptr_t kMaxFixedParametersBits = 14;
static constexpr intptr_t kMaxOptionalParametersBits = 13;
private:
friend class Class;
friend class UnitDeserializationRoots;
@ -1092,10 +1085,8 @@ class FunctionLayout : public ObjectLayout {
POINTER_FIELD(StringPtr, name)
POINTER_FIELD(ObjectPtr, owner) // Class or patch class or mixin class
// where this function is defined.
POINTER_FIELD(AbstractTypePtr, result_type)
POINTER_FIELD(ArrayPtr, parameter_types)
POINTER_FIELD(ArrayPtr, parameter_names)
POINTER_FIELD(TypeArgumentsPtr, type_parameters) // Array of TypeParameter.
POINTER_FIELD(FunctionTypePtr, signature)
POINTER_FIELD(ObjectPtr,
data) // Additional data specific to the function kind. See
// Function::set_data() for details.
@ -1135,17 +1126,35 @@ class FunctionLayout : public ObjectLayout {
uint32_t kind_tag_; // See Function::KindTagBits.
uint32_t packed_fields_;
typedef BitField<uint32_t, bool, 0, 1> PackedHasNamedOptionalParameters;
// TODO(regis): Split packed_fields_ in 2 uint32_t if max values are too low.
// Keep in sync with corresponding constants in FunctionTypeLayout.
static constexpr intptr_t kMaxOptimizableBits = 1;
static constexpr intptr_t kMaxBackgroundOptimizableBits = 1;
static constexpr intptr_t kMaxTypeParametersBits = 7;
static constexpr intptr_t kMaxHasNamedOptionalParametersBits = 1;
static constexpr intptr_t kMaxFixedParametersBits = 10;
static constexpr intptr_t kMaxOptionalParametersBits = 10;
typedef BitField<uint32_t, bool, 0, kMaxOptimizableBits> PackedOptimizable;
typedef BitField<uint32_t,
bool,
PackedHasNamedOptionalParameters::kNextBit,
1>
OptimizableBit;
typedef BitField<uint32_t, bool, OptimizableBit::kNextBit, 1>
BackgroundOptimizableBit;
PackedOptimizable::kNextBit,
kMaxBackgroundOptimizableBits>
PackedBackgroundOptimizable;
typedef BitField<uint32_t,
uint8_t,
PackedBackgroundOptimizable::kNextBit,
kMaxTypeParametersBits>
PackedNumTypeParameters;
typedef BitField<uint32_t,
bool,
PackedNumTypeParameters::kNextBit,
kMaxHasNamedOptionalParametersBits>
PackedHasNamedOptionalParameters;
typedef BitField<uint32_t,
uint16_t,
BackgroundOptimizableBit::kNextBit,
PackedHasNamedOptionalParameters::kNextBit,
kMaxFixedParametersBits>
PackedNumFixedParameters;
typedef BitField<uint32_t,
@ -1154,8 +1163,8 @@ class FunctionLayout : public ObjectLayout {
kMaxOptionalParametersBits>
PackedNumOptionalParameters;
static_assert(PackedNumOptionalParameters::kNextBit <=
kBitsPerWord * sizeof(decltype(packed_fields_)),
"FunctionLayout::packed_fields_ bitfields don't align.");
kBitsPerByte * sizeof(decltype(packed_fields_)),
"FunctionLayout::packed_fields_ bitfields don't fit.");
static_assert(PackedNumOptionalParameters::kNextBit <=
compiler::target::kSmiBits,
"In-place mask for number of optional parameters cannot fit in "
@ -1187,7 +1196,6 @@ class ClosureDataLayout : public ObjectLayout {
POINTER_FIELD(ContextScopePtr, context_scope)
POINTER_FIELD(FunctionPtr,
parent_function) // Enclosing function of this local function.
POINTER_FIELD(TypePtr, signature_type)
POINTER_FIELD(InstancePtr,
closure) // Closure object for static implicit closures.
// Instantiate-to-bounds TAV for use when no TAV is provided.
@ -1199,27 +1207,13 @@ class ClosureDataLayout : public ObjectLayout {
friend class Function;
};
class SignatureDataLayout : public ObjectLayout {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(SignatureData);
VISIT_FROM(ObjectPtr, parent_function)
POINTER_FIELD(FunctionPtr,
parent_function); // Enclosing function of this sig. function.
POINTER_FIELD(TypePtr, signature_type)
VISIT_TO(ObjectPtr, signature_type)
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class Function;
};
class FfiTrampolineDataLayout : public ObjectLayout {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData);
VISIT_FROM(ObjectPtr, signature_type)
POINTER_FIELD(TypePtr, signature_type)
POINTER_FIELD(FunctionPtr, c_signature)
POINTER_FIELD(FunctionTypePtr, c_signature)
// Target Dart method for callbacks, otherwise null.
POINTER_FIELD(FunctionPtr, callback_target)
@ -2292,14 +2286,9 @@ class TypeLayout : public AbstractTypeLayout {
POINTER_FIELD(SmiPtr, type_class_id)
POINTER_FIELD(TypeArgumentsPtr, arguments)
POINTER_FIELD(SmiPtr, hash)
// This type object represents a function type if its signature field is a
// non-null function object.
POINTER_FIELD(FunctionPtr,
signature) // If not null, this type is a function type.
VISIT_TO(ObjectPtr, signature)
TokenPosition token_pos_;
int8_t type_state_;
int8_t nullability_;
VISIT_TO(ObjectPtr, hash)
uint8_t type_state_;
uint8_t nullability_;
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
@ -2307,6 +2296,59 @@ class TypeLayout : public AbstractTypeLayout {
friend class TypeArgumentsLayout;
};
class FunctionTypeLayout : public AbstractTypeLayout {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
VISIT_FROM(ObjectPtr, type_test_stub)
POINTER_FIELD(TypeArgumentsPtr, type_parameters) // Array of TypeParameter.
POINTER_FIELD(AbstractTypePtr, result_type)
POINTER_FIELD(ArrayPtr, parameter_types)
POINTER_FIELD(ArrayPtr, parameter_names);
POINTER_FIELD(SmiPtr, hash)
VISIT_TO(ObjectPtr, hash)
uint32_t packed_fields_; // Number of parent type args and own parameters.
uint8_t type_state_;
uint8_t nullability_;
// Keep in sync with corresponding constants in FunctionLayout.
static constexpr intptr_t kMaxParentTypeArgumentsBits = 8;
static constexpr intptr_t kMaxHasNamedOptionalParametersBits = 1;
static constexpr intptr_t kMaxImplicitParametersBits = 1;
static constexpr intptr_t kMaxFixedParametersBits = 10;
static constexpr intptr_t kMaxOptionalParametersBits = 10;
typedef BitField<uint32_t, uint8_t, 0, kMaxParentTypeArgumentsBits>
PackedNumParentTypeArguments;
typedef BitField<uint32_t,
bool,
PackedNumParentTypeArguments::kNextBit,
kMaxHasNamedOptionalParametersBits>
PackedHasNamedOptionalParameters;
typedef BitField<uint32_t,
uint8_t,
PackedHasNamedOptionalParameters::kNextBit,
kMaxImplicitParametersBits>
PackedNumImplicitParameters;
typedef BitField<uint32_t,
uint16_t,
PackedNumImplicitParameters::kNextBit,
kMaxFixedParametersBits>
PackedNumFixedParameters;
typedef BitField<uint32_t,
uint16_t,
PackedNumFixedParameters::kNextBit,
kMaxOptionalParametersBits>
PackedNumOptionalParameters;
static_assert(PackedNumOptionalParameters::kNextBit <=
kBitsPerByte * sizeof(decltype(packed_fields_)),
"FunctionTypeLayout::packed_fields_ bitfields don't fit.");
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class Function;
};
class TypeRefLayout : public AbstractTypeLayout {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(TypeRef);
@ -2331,21 +2373,22 @@ class TypeParameterLayout : public AbstractTypeLayout {
// TODO(dartbug.com/43901): Once a separate TypeParameters class has been
// added, move these there and remove them from TypeParameter objects.
POINTER_FIELD(AbstractTypePtr, default_argument)
POINTER_FIELD(FunctionPtr, parameterized_function)
VISIT_TO(ObjectPtr, parameterized_function)
ClassIdTagType parameterized_class_id_;
TokenPosition token_pos_;
int16_t index_;
VISIT_TO(ObjectPtr, default_argument)
ClassIdTagType parameterized_class_id_; // Or kFunctionCid for function tp.
// TODO(regis): Can we use uint8_t twice below? Or keep uint16_t?
// Warning: BuildTypeParameterTypeTestStub assumes uint16_t.
uint16_t base_; // Number of enclosing function type parameters.
uint16_t index_;
uint8_t flags_;
int8_t nullability_;
uint8_t nullability_;
public:
using FinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
using BeingFinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
using FinalizedBit =
BitField<decltype(flags_), bool, BeingFinalizedBit::kNextBit, 1>;
using GenericCovariantImplBit =
BitField<decltype(flags_), bool, FinalizedBit::kNextBit, 1>;
using DeclarationBit =
BitField<decltype(flags_), bool, GenericCovariantImplBit::kNextBit, 1>;
static constexpr intptr_t kFlagsBitSize = DeclarationBit::kNextBit;
static constexpr intptr_t kFlagsBitSize = GenericCovariantImplBit::kNextBit;
private:
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }

View file

@ -20,7 +20,6 @@ namespace dart {
F(Class, library_) \
F(Class, type_parameters_) \
F(Class, super_type_) \
F(Class, signature_function_) \
F(Class, constants_) \
F(Class, declaration_type_) \
F(Class, invocation_dispatcher_cache_) \
@ -34,19 +33,12 @@ namespace dart {
F(PatchClass, library_kernel_data_) \
F(Function, name_) \
F(Function, owner_) \
F(Function, result_type_) \
F(Function, parameter_types_) \
F(Function, parameter_names_) \
F(Function, type_parameters_) \
F(Function, data_) \
F(Function, ic_data_array_) \
F(Function, code_) \
F(ClosureData, context_scope_) \
F(ClosureData, parent_function_) \
F(ClosureData, signature_type_) \
F(ClosureData, closure_) \
F(SignatureData, parent_function_) \
F(SignatureData, signature_type_) \
F(Field, name_) \
F(Field, owner_) \
F(Field, type_) \
@ -137,14 +129,18 @@ namespace dart {
F(Type, type_class_id_) \
F(Type, arguments_) \
F(Type, hash_) \
F(Type, signature_) \
F(FunctionType, type_test_stub_) \
F(FunctionType, hash_) \
F(FunctionType, result_type_) \
F(FunctionType, parameter_types_) \
F(FunctionType, parameter_names_) \
F(FunctionType, type_parameters_) \
F(TypeRef, type_test_stub_) \
F(TypeRef, type_) \
F(TypeParameter, type_test_stub_) \
F(TypeParameter, name_) \
F(TypeParameter, hash_) \
F(TypeParameter, bound_) \
F(TypeParameter, parameterized_function_) \
F(Closure, instantiator_type_arguments_) \
F(Closure, function_type_arguments_) \
F(Closure, delayed_type_arguments_) \
@ -188,7 +184,6 @@ namespace dart {
F(PointerBase, data_) \
F(Pointer, type_arguments_) \
F(DynamicLibrary, handle_) \
F(FfiTrampolineData, signature_type_) \
F(FfiTrampolineData, c_signature_) \
F(FfiTrampolineData, callback_target_) \
F(FfiTrampolineData, callback_exceptional_return_) \

View file

@ -87,7 +87,6 @@ TypePtr Type::ReadFrom(SnapshotReader* reader,
reader->AddBackRef(object_id, &type, kIsDeserialized);
// Set all non object fields.
type.set_token_pos(TokenPosition::Deserialize(reader->Read<int32_t>()));
const uint8_t combined = reader->Read<uint8_t>();
type.set_type_state(combined >> 4);
type.set_nullability(static_cast<Nullability>(combined & 0xf));
@ -122,13 +121,6 @@ void TypeLayout::WriteTo(SnapshotWriter* writer,
bool as_reference) {
ASSERT(writer != NULL);
if (signature() != Function::null()) {
writer->SetWriteException(Exceptions::kArgument,
"Illegal argument in isolate message"
" : (function types are not supported yet)");
UNREACHABLE();
}
// Only resolved and finalized types should be written to a snapshot.
ASSERT((type_state_ == TypeLayout::kFinalizedInstantiated) ||
(type_state_ == TypeLayout::kFinalizedUninstantiated));
@ -160,7 +152,6 @@ void TypeLayout::WriteTo(SnapshotWriter* writer,
writer->Write<bool>(typeclass_is_in_fullsnapshot);
// Write out all the non object pointer fields.
writer->Write<int32_t>(token_pos_.Serialize());
const uint8_t combined = (type_state_ << 4) | nullability_;
ASSERT(type_state_ == (combined >> 4));
ASSERT(nullability_ == (combined & 0xf));
@ -233,9 +224,6 @@ TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
// Set all non object fields.
type_parameter.set_token_pos(
TokenPosition::Deserialize(reader->Read<int32_t>()));
type_parameter.set_index(reader->Read<int16_t>());
const uint8_t combined = reader->Read<uint8_t>();
type_parameter.set_flags(combined >> 4);
type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
@ -247,11 +235,10 @@ TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
READ_OBJECT_FIELDS(type_parameter, type_parameter.raw()->ptr()->from(),
type_parameter.raw()->ptr()->to(), kAsReference);
if (type_parameter.parameterized_function() == Function::null()) {
// Read in the parameterized class.
(*reader->ClassHandle()) =
Class::RawCast(reader->ReadObjectImpl(kAsReference));
} else {
// Read in the parameterized class.
(*reader->ClassHandle()) =
Class::RawCast(reader->ReadObjectImpl(kAsReference));
if (reader->ClassHandle()->id() == kFunctionCid) {
(*reader->ClassHandle()) = Class::null();
}
type_parameter.set_parameterized_class(*reader->ClassHandle());
@ -285,8 +272,8 @@ void TypeParameterLayout::WriteTo(SnapshotWriter* writer,
writer->WriteTags(writer->GetObjectTags(this));
// Write out all the non object pointer fields.
writer->Write<int32_t>(token_pos_.Serialize());
writer->Write<int16_t>(index_);
writer->Write<uint16_t>(base_);
writer->Write<uint16_t>(index_);
const uint8_t combined = (flags_ << 4) | nullability_;
ASSERT(flags_ == (combined >> 4));
ASSERT(nullability_ == (combined & 0xf));
@ -296,15 +283,10 @@ void TypeParameterLayout::WriteTo(SnapshotWriter* writer,
SnapshotWriterVisitor visitor(writer, kAsReference);
visitor.VisitPointers(from(), to());
if (parameterized_class_id_ != kFunctionCid) {
ASSERT(parameterized_function() == Function::null());
// Write out the parameterized class.
ClassPtr param_class =
writer->isolate_group()->class_table()->At(parameterized_class_id_);
writer->WriteObjectImpl(param_class, kAsReference);
} else {
ASSERT(parameterized_function() != Function::null());
}
// Write out the parameterized class (or Function if cid == kFunctionCid).
ClassPtr param_class =
writer->isolate_group()->class_table()->At(parameterized_class_id_);
writer->WriteObjectImpl(param_class, kAsReference);
}
TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
@ -568,7 +550,6 @@ MESSAGE_SNAPSHOT_UNREACHABLE(ObjectPool);
MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
MESSAGE_SNAPSHOT_UNREACHABLE(Script);
MESSAGE_SNAPSHOT_UNREACHABLE(SignatureData);
MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
MESSAGE_SNAPSHOT_UNREACHABLE(String);
MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
@ -580,6 +561,7 @@ MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError);
MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr);
MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference);
MESSAGE_SNAPSHOT_ILLEGAL(FunctionType)
MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
MESSAGE_SNAPSHOT_ILLEGAL(Pointer);

View file

@ -5513,8 +5513,10 @@ static void CreateSpecializedFunction(Thread* thread,
const Object& owner) {
const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
const FunctionType& signature =
FunctionType::Handle(zone, FunctionType::New());
Function& fn =
Function::Handle(zone, Function::New(Symbols::ColonMatcher(),
Function::Handle(zone, Function::New(signature, Symbols::ColonMatcher(),
FunctionLayout::kIrregexpFunction,
true, // Static.
false, // Not const.
@ -5524,24 +5526,25 @@ static void CreateSpecializedFunction(Thread* thread,
owner, TokenPosition::kMinSource));
// TODO(zerny): Share these arrays between all irregexp functions.
// TODO(regis): Better, share a common signature.
fn.set_num_fixed_parameters(kParamCount);
fn.set_parameter_types(
signature.set_parameter_types(
Array::Handle(zone, Array::New(kParamCount, Heap::kOld)));
fn.CreateNameArrayIncludingFlags(Heap::kOld);
fn.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
Object::dynamic_type());
fn.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
Symbols::This());
fn.SetParameterTypeAt(RegExpMacroAssembler::kParamStringIndex,
Object::dynamic_type());
fn.SetParameterNameAt(RegExpMacroAssembler::kParamStringIndex,
Symbols::string_param());
fn.SetParameterTypeAt(RegExpMacroAssembler::kParamStartOffsetIndex,
Object::dynamic_type());
fn.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
Symbols::start_index_param());
fn.set_result_type(Type::Handle(zone, Type::ArrayType()));
fn.TruncateUnusedParameterFlags();
signature.CreateNameArrayIncludingFlags(Heap::kOld);
signature.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
Object::dynamic_type());
signature.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
Symbols::This());
signature.SetParameterTypeAt(RegExpMacroAssembler::kParamStringIndex,
Object::dynamic_type());
signature.SetParameterNameAt(RegExpMacroAssembler::kParamStringIndex,
Symbols::string_param());
signature.SetParameterTypeAt(RegExpMacroAssembler::kParamStartOffsetIndex,
Object::dynamic_type());
signature.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
Symbols::start_index_param());
signature.set_result_type(Type::Handle(zone, Type::ArrayType()));
signature.FinalizeNameArrays(fn);
// Cache the result.
regexp.set_function(specialization_cid, sticky, fn);

View file

@ -481,6 +481,9 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) {
// we can't guarantee the supertype isn't the top type.
if (supertype.IsTopTypeForSubtyping()) return;
// TODO(regis): Support for FLAG_trace_type_checks is missing here. Is it
// still useful or should we remove it everywhere?
// The supertype or subtype may not be instantiated.
if (AbstractType::InstantiateAndTestSubtype(
&subtype, &supertype, instantiator_type_args, function_type_args)) {
@ -537,12 +540,12 @@ static void PrintTypeCheck(const char* message,
ASSERT(instance_type.IsInstantiated() ||
(instance.IsClosure() && instance_type.IsInstantiated(kCurrentClass)));
if (type.IsInstantiated()) {
OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", message,
OS::PrintErr("%s: '%s' %d %s '%s' %d (pc: %#" Px ").\n", message,
String::Handle(instance_type.Name()).ToCString(),
Class::Handle(instance_type.type_class()).id(),
instance_type.type_class_id(),
(result.raw() == Bool::True().raw()) ? "is" : "is !",
String::Handle(type.Name()).ToCString(),
Class::Handle(type.type_class()).id(), caller_frame->pc());
String::Handle(type.Name()).ToCString(), type.type_class_id(),
caller_frame->pc());
} else {
// Instantiate type before printing.
const AbstractType& instantiated_type = AbstractType::Handle(

View file

@ -155,6 +155,8 @@ static intptr_t GetTypeIndex(ObjectStore* object_store,
const ObjectPtr raw_type) {
if (raw_type == object_store->legacy_object_type()) {
return kLegacyObjectType;
} else if (raw_type == object_store->nullable_object_type()) {
return kNullableObjectType;
} else if (raw_type == object_store->null_type()) {
return kNullType;
} else if (raw_type == object_store->never_type()) {

View file

@ -401,10 +401,10 @@ class SnapshotReader : public BaseReader {
friend class PatchClass;
friend class RegExp;
friend class Script;
friend class SignatureData;
friend class SubtypeTestCache;
friend class TransferableTypedData;
friend class Type;
friend class FunctionType;
friend class TypedDataView;
friend class TypeArguments;
friend class TypeParameter;
@ -685,6 +685,7 @@ class SnapshotWriter : public BaseWriter {
friend class SubtypeTestCacheLayout;
friend class TransferableTypedDataLayout;
friend class TypeLayout;
friend class FunctionTypeLayout;
friend class TypeArgumentsLayout;
friend class TypeParameterLayout;
friend class TypeRefLayout;

View file

@ -28,9 +28,10 @@ static Function* CreateFunction(const char* name) {
Class::New(lib, class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::ZoneHandle(Symbols::New(Thread::Current(), name));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
Function& function = Function::ZoneHandle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
return &function;
}

View file

@ -28,9 +28,10 @@ static Function* CreateFunction(const char* name) {
Class::New(lib, class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::ZoneHandle(Symbols::New(Thread::Current(), name));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
Function& function = Function::ZoneHandle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
return &function;
}

View file

@ -28,9 +28,10 @@ static Function* CreateFunction(const char* name) {
Class::New(lib, class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::ZoneHandle(Symbols::New(Thread::Current(), name));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
Function& function = Function::ZoneHandle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kMinSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kMinSource));
return &function;
}

View file

@ -18,9 +18,10 @@ const Function& RegisterFakeFunction(const char* name, const Code& code) {
const Class& owner_class = Class::Handle(
Class::New(lib, class_name, script, TokenPosition::kNoSource));
const String& function_name = String::ZoneHandle(Symbols::New(thread, name));
const Function& function = Function::ZoneHandle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kMinSource));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
Function& function = Function::ZoneHandle(Function::New(
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
const Array& functions = Array::Handle(Array::New(1));
functions.SetAt(0, function);
{

View file

@ -28,9 +28,10 @@ static Function* CreateFunction(const char* name) {
Class::New(lib, class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::ZoneHandle(Symbols::New(Thread::Current(), name));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
Function& function = Function::ZoneHandle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
return &function;
}

View file

@ -247,7 +247,6 @@ class ObjectPointerVisitor;
V(SecondArg, "y") \
V(Set, "set") \
V(SetterPrefix, "set:") \
V(SignatureData, "SignatureData") \
V(SingleTargetCache, "SingleTargetCache") \
V(SizeOfStructField, "#sizeOf") \
V(SpaceExtendsSpace, " extends ") \
@ -401,11 +400,12 @@ class ObjectPointerVisitor;
V(_SyncIterableConstructor, "_SyncIterable.") \
V(_SyncIterator, "_SyncIterator") \
V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl") \
V(_AbstractType, "_AbstractType") \
V(_Type, "_Type") \
V(_FunctionType, "_FunctionType") \
V(_TypeParameter, "_TypeParameter") \
V(_TypeRef, "_TypeRef") \
V(_TypeVariableMirror, "_TypeVariableMirror") \
V(_TypedefMirror, "_TypedefMirror") \
V(_Uint16ArrayFactory, "Uint16List.") \
V(_Uint16ArrayView, "_Uint16ArrayView") \
V(_Uint16List, "_Uint16List") \

View file

@ -233,7 +233,6 @@ DEFINE_TAGGED_POINTER(Class, Object)
DEFINE_TAGGED_POINTER(PatchClass, Object)
DEFINE_TAGGED_POINTER(Function, Object)
DEFINE_TAGGED_POINTER(ClosureData, Object)
DEFINE_TAGGED_POINTER(SignatureData, Object)
DEFINE_TAGGED_POINTER(FfiTrampolineData, Object)
DEFINE_TAGGED_POINTER(Field, Object)
DEFINE_TAGGED_POINTER(Script, Object)
@ -270,6 +269,7 @@ DEFINE_TAGGED_POINTER(LibraryPrefix, Instance)
DEFINE_TAGGED_POINTER(TypeArguments, Instance)
DEFINE_TAGGED_POINTER(AbstractType, Instance)
DEFINE_TAGGED_POINTER(Type, AbstractType)
DEFINE_TAGGED_POINTER(FunctionType, AbstractType)
DEFINE_TAGGED_POINTER(TypeRef, AbstractType)
DEFINE_TAGGED_POINTER(TypeParameter, AbstractType)
DEFINE_TAGGED_POINTER(Closure, Instance)

View file

@ -431,9 +431,10 @@ static Function* CreateFunction(const char* name) {
Class::New(lib, class_name, script, TokenPosition::kNoSource));
const String& function_name =
String::ZoneHandle(Symbols::New(Thread::Current(), name));
const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
Function& function = Function::ZoneHandle(Function::New(
function_name, FunctionLayout::kRegularFunction, true, false, false,
false, false, owner_class, TokenPosition::kNoSource));
signature, function_name, FunctionLayout::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
return &function;
}

Some files were not shown because too many files have changed in this diff Show more