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

Unified Diff: runtime/vm/object.cc

Issue 2979763002: [VM generic function types] Properly set the scope function after parsing a (Closed)
Patch Set: work in progress Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index fdb2ddf1663b67cc1df6d84919644f31753c07d6..7c254845a2f57bc37568bdedb161586aeba6cd69 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4777,6 +4777,19 @@ bool TypeArguments::IsRecursive() const {
}
+void TypeArguments::SetScopeFunction(const Function& function) const {
+ if (IsNull()) return;
+ const intptr_t num_types = Length();
+ AbstractType& type = AbstractType::Handle();
+ for (intptr_t i = 0; i < num_types; i++) {
+ type = TypeAt(i);
+ if (!type.IsNull()) {
+ type.SetScopeFunction(function);
+ }
+ }
+}
+
+
bool TypeArguments::IsDynamicTypes(bool raw_instantiated,
intptr_t from_index,
intptr_t len) const {
@@ -5733,44 +5746,6 @@ RawType* Function::ExistingSignatureType() const {
}
-RawFunction* Function::CanonicalSignatureFunction(TrailPtr trail) const {
- ASSERT(!IsSignatureFunction());
- Zone* zone = Thread::Current()->zone();
- Function& parent = Function::Handle(zone, parent_function());
- if (!parent.IsNull() && !parent.IsSignatureFunction()) {
- // Make sure the parent function is also a signature function.
- parent = parent.CanonicalSignatureFunction(trail);
- }
- const Class& owner = Class::Handle(zone, Owner());
- const Function& sig_fun = Function::Handle(
- zone,
- Function::NewSignatureFunction(owner, parent, TokenPosition::kNoSource));
- // In case of a generic function, the function type parameters in the
- // signature will still refer to the original function. This should not
- // be a problem, since once finalized the indices will be identical.
- sig_fun.set_type_parameters(TypeArguments::Handle(zone, type_parameters()));
- ASSERT(HasGenericParent() == sig_fun.HasGenericParent());
- ASSERT(IsGeneric() == sig_fun.IsGeneric());
- AbstractType& type = AbstractType::Handle(zone);
- type = result_type();
- type = type.Canonicalize(trail);
- sig_fun.set_result_type(type);
- const intptr_t num_params = NumParameters();
- sig_fun.set_num_fixed_parameters(num_fixed_parameters());
- sig_fun.SetNumOptionalParameters(NumOptionalParameters(),
- HasOptionalPositionalParameters());
- sig_fun.set_parameter_types(
- Array::Handle(Array::New(num_params, Heap::kOld)));
- for (intptr_t i = 0; i < num_params; i++) {
- type = ParameterTypeAt(i);
- type = type.Canonicalize(trail);
- sig_fun.SetParameterTypeAt(i, type);
- }
- sig_fun.set_parameter_names(Array::Handle(zone, parameter_names()));
- return sig_fun.raw();
-}
-
-
RawType* Function::SignatureType() const {
Type& type = Type::Handle(ExistingSignatureType());
if (type.IsNull()) {
@@ -6045,13 +6020,6 @@ void Function::set_native_name(const String& value) const {
void Function::set_result_type(const AbstractType& value) const {
ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->result_type_, value.raw());
- if (value.IsFunctionType()) {
- // The function result type may refer to this function's type parameters.
- // Change its parent function.
- const Function& result_signature_function =
- Function::Handle(Type::Cast(value).signature());
- result_signature_function.set_parent_function(*this);
- }
}
@@ -6121,12 +6089,26 @@ intptr_t Function::NumParentTypeParameters() const {
intptr_t num_parent_type_params = 0;
while (!parent.IsNull()) {
num_parent_type_params += parent.NumTypeParameters(thread);
+ if (parent.IsImplicitClosureFunction()) break;
parent ^= parent.parent_function();
}
return num_parent_type_params;
}
+void Function::PrintSignatureTypes() const {
+ Function& sig_fun = Function::Handle(raw());
+ Type& sig_type = Type::Handle();
+ while (!sig_fun.IsNull()) {
+ sig_type = sig_fun.SignatureType();
+ THR_Print("%s%s\n",
+ sig_fun.IsImplicitClosureFunction() ? "implicit closure: " : "",
+ sig_type.ToCString());
+ sig_fun ^= sig_fun.parent_function();
+ }
+}
+
+
RawTypeParameter* Function::LookupTypeParameter(
const String& type_name,
intptr_t* function_level) const {
@@ -6603,6 +6585,8 @@ RawFunction* Function::InstantiateSignatureFrom(
Heap::Space space) const {
Zone* zone = Thread::Current()->zone();
const Object& owner = Object::Handle(zone, RawOwner());
+ // Note that parent pointers in newly instantiated signatures still points to
+ // the original uninstantiated parent signatures. That is not a problem.
const Function& parent = Function::Handle(zone, parent_function());
ASSERT(!HasInstantiatedSignature());
Function& sig = Function::Handle(
@@ -7298,12 +7282,22 @@ bool Function::HasInstantiatedSignature(Genericity genericity,
intptr_t num_free_fun_type_params,
TrailPtr trail) const {
if (genericity != kCurrentClass) {
- // We only consider the function type parameters declared by the parents of
- // this signature function.
- const int num_parent_type_params = NumParentTypeParameters();
- if (num_parent_type_params < num_free_fun_type_params) {
- num_free_fun_type_params = num_parent_type_params;
+ // A generic typedef may declare a non-generic function type and get
+ // instantiated with unrelated function type parameters. In that case, its
+ // signature is still uninstantiated, because these type parameters are
+ // free (they are not declared by the typedef).
+ // For that reason, we only adjust num_free_fun_type_params is this
rmacnak 2017/07/19 19:56:39 if
regis 2017/07/19 20:14:23 Done.
+ // signature is generic or has a generic parent.
+ if (IsGeneric() || HasGenericParent()) {
+ // We only consider the function type parameters declared by the parents
+ // of this signature function as free.
+ const int num_parent_type_params = NumParentTypeParameters();
+ if (num_parent_type_params < num_free_fun_type_params) {
+ num_free_fun_type_params = num_parent_type_params;
+ }
}
+ // TODO(regis): Should we check the owners of the function type parameters
+ // in addition to their indexes to decide if they are free or not?
}
AbstractType& type = AbstractType::Handle(result_type());
if (!type.IsInstantiated(genericity, num_free_fun_type_params, trail)) {
@@ -16433,6 +16427,12 @@ bool AbstractType::IsRecursive() const {
}
+void AbstractType::SetScopeFunction(const Function& function) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+}
+
+
RawAbstractType* AbstractType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
@@ -16860,7 +16860,6 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
if (type_param.Equals(other_type_param)) {
return true;
}
- // TODO(regis): Should we update TypeParameter::IsEquivalent() instead?
if (type_param.IsFunctionTypeParameter() &&
other_type_param.IsFunctionTypeParameter() &&
type_param.IsFinalized() && other_type_param.IsFinalized()) {
@@ -17483,6 +17482,17 @@ bool Type::IsRecursive() const {
}
+void Type::SetScopeFunction(const Function& function) const {
+ TypeArguments::Handle(arguments()).SetScopeFunction(function);
+ if (IsFunctionType()) {
+ const Function& sig_fun = Function::Handle(signature());
+ sig_fun.set_parent_function(function);
+ // No need to traverse result type and parameter types (and bounds, in case
+ // sig_fun is generic), since they have sig_fun as scope function.
+ }
+}
+
+
RawAbstractType* Type::CloneUnfinalized() const {
ASSERT(IsResolved());
if (IsFinalized()) {
@@ -17723,19 +17733,11 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
set_arguments(type_args);
ASSERT(type_args.IsNull() || type_args.IsOld());
- // In case of a function type, replace the actual function by a signature
- // function.
- if (IsFunctionType()) {
- Function& sig_fun = Function::Handle(zone, signature());
- if (!sig_fun.IsSignatureFunction()) {
- sig_fun = sig_fun.CanonicalSignatureFunction(trail);
- set_signature(sig_fun);
- // Note that the signature type of the signature function may be
- // different than the type being canonicalized.
- // Consider F<int> being canonicalized, with F being a typedef and F<T>
- // being its signature type.
- }
- }
+ // In case of a function type, the signature has already been canonicalized
+ // when finalizing the type and passing kCanonicalize as finalization.
+ // Therefore, we do not canonicalize the signature here, which would have no
+ // effect on selecting the canonical type anyway, because the function
+ // object is not replaced when canonicalizing the signature.
// Check to see if the type got added to canonical list as part of the
// type arguments canonicalization.
@@ -17983,6 +17985,13 @@ bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
}
+void TypeRef::SetScopeFunction(const Function& function) const {
+ // TypeRefs are created during finalization, when scope functions have
+ // already been adjusted.
+ UNREACHABLE();
+}
+
+
RawTypeRef* TypeRef::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
@@ -18543,6 +18552,12 @@ bool BoundedType::IsRecursive() const {
}
+void BoundedType::SetScopeFunction(const Function& function) const {
+ AbstractType::Handle(type()).SetScopeFunction(function);
+ AbstractType::Handle(bound()).SetScopeFunction(function);
+}
+
+
void BoundedType::set_type(const AbstractType& value) const {
ASSERT(value.IsFinalized() || value.IsBeingFinalized() ||
value.IsTypeParameter());

Powered by Google App Engine
This is Rietveld 408576698