mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:51:19 +00:00
[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:
parent
5c174c8d8c
commit
b3bca1821c
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -24,7 +24,6 @@ enum FunctionKind {
|
|||
ffiTrampoline,
|
||||
stub,
|
||||
tag,
|
||||
signatureFunction,
|
||||
dynamicInvocationForwarder
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -24,7 +24,6 @@ enum FunctionKind {
|
|||
ffiTrampoline,
|
||||
stub,
|
||||
tag,
|
||||
signatureFunction,
|
||||
dynamicInvocationForwarder
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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(¬_integer);
|
||||
JumpIfNotString(assembler, R1, R0, &use_declaration_type);
|
||||
JumpIfNotString(assembler, R1, R0, ¬_string);
|
||||
__ LoadIsolate(R0);
|
||||
__ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
|
||||
__ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
|
||||
__ Ret();
|
||||
|
||||
__ Bind(¬_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,
|
||||
|
|
|
@ -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(¬_integer);
|
||||
JumpIfNotString(assembler, R1, R0, &use_declaration_type);
|
||||
JumpIfNotString(assembler, R1, R0, ¬_string);
|
||||
__ LoadIsolate(R0);
|
||||
__ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
|
||||
__ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
|
||||
__ ret();
|
||||
|
||||
__ Bind(¬_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));
|
||||
|
|
|
@ -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, ¬_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(¬_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) {
|
||||
|
|
|
@ -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, ¬_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(¬_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.
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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, ¶meter_types)) return false;
|
||||
}
|
||||
auto& parameter_names = Array::ZoneHandle(zone());
|
||||
if (auto const parameter_names_sexp = Retrieve(list, "parameter_names")) {
|
||||
if (!ParseDartValue(parameter_names_sexp, ¶meter_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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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")),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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_))) {
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 = ¶meterized_function;
|
||||
const FunctionType* enclosing = NULL;
|
||||
if (!parameterized_signature.IsNull()) {
|
||||
enclosing = ¶meterized_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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
2200
runtime/vm/object.cc
2200
runtime/vm/object.cc
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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_) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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") \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue