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

Unified Diff: runtime/vm/object.cc

Issue 2835513002: Process generic function type arguments in more places (function type tests, (Closed)
Patch Set: Created 3 years, 8 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
« no previous file with comments | « no previous file | runtime/vm/parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 79b65d0679b5c3706861573a2cb8b45e7dbaf684..4e70608fde575ffaca700d6cc7193c61880d15bc 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -52,6 +52,10 @@
namespace dart {
+DEFINE_FLAG(bool,
zra 2017/04/20 19:22:09 Should we put this in flag_list.h?
regis 2017/04/20 20:23:30 Done.
+ reify_generic_functions,
+ false,
+ "Enable reification of generic functions (not yet supported).");
DEFINE_FLAG(int,
huge_method_cutoff_in_code_size,
200000,
@@ -6432,19 +6436,17 @@ bool Function::HasCompatibleParametersWith(const Function& other,
ASSERT((bound_error != NULL) && bound_error->IsNull());
// Check that this function's signature type is a subtype of the other
// function's signature type.
- // Map type parameters in the signature to dynamic before the test.
+ // Map type parameters referred to by formal parameter types and result type
+ // in the signature to dynamic before the test.
+ // Note that type parameters declared by a generic signature are preserved.
Function& this_fun = Function::Handle(raw());
if (!this_fun.HasInstantiatedSignature()) {
- // TODO(regis): Should we pass the context explicitly here (i.e. null) once
- // we support generic functions?
this_fun = this_fun.InstantiateSignatureFrom(Object::null_type_arguments(),
Object::null_type_arguments(),
Heap::kOld);
}
Function& other_fun = Function::Handle(other.raw());
if (!other_fun.HasInstantiatedSignature()) {
- // TODO(regis): Should we pass the context explicitly here (i.e. null) once
- // we support generic functions?
other_fun = other_fun.InstantiateSignatureFrom(
Object::null_type_arguments(), Object::null_type_arguments(),
Heap::kOld);
@@ -6484,8 +6486,6 @@ RawFunction* Function::InstantiateSignatureFrom(
Function& sig = Function::Handle(
zone,
Function::NewSignatureFunction(owner, TokenPosition::kNoSource, space));
- // TODO(regis): If type parameter bounds are not IsInstantiated(kFunctions),
- // clone finalized type parameters and instantiate bounds.
sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters()));
AbstractType& type = AbstractType::Handle(zone, result_type());
if (!type.IsInstantiated()) {
@@ -6577,14 +6577,41 @@ bool Function::TypeTest(TypeTestKind test_kind,
(num_opt_named_params < other_num_opt_named_params)) {
return false;
}
-
- // TODO(regis): Check the type parameters and bounds of a generic function.
-
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ if (FLAG_reify_generic_functions) {
+ // Check the type parameters and bounds of a generic function.
+ const intptr_t num_type_params = NumTypeParameters(thread);
+ if (num_type_params != other.NumTypeParameters(thread)) {
+ return false;
+ }
+ if (num_type_params > 0) {
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, type_parameters());
+ ASSERT(!type_params.IsNull());
+ const TypeArguments& other_type_params =
+ TypeArguments::Handle(zone, other.type_parameters());
+ ASSERT(!other_type_params.IsNull());
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ TypeParameter& other_type_param = TypeParameter::Handle(zone);
+ AbstractType& bound = AbstractType::Handle(zone);
+ AbstractType& other_bound = AbstractType::Handle(zone);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ other_type_param ^= other_type_params.TypeAt(i);
+ bound = type_param.bound();
+ other_bound = other_type_param.bound();
siva 2017/04/20 20:32:08 Should we assert here that the two types are final
regis 2017/04/20 21:18:26 The Equals call should do the right thing in case
+ if (!bound.Equals(other_bound)) {
+ return false;
+ }
+ }
+ }
+ }
// Check the result type.
const AbstractType& other_res_type =
- AbstractType::Handle(other.result_type());
+ AbstractType::Handle(zone, other.result_type());
if (!other_res_type.IsDynamicType() && !other_res_type.IsVoidType()) {
- const AbstractType& res_type = AbstractType::Handle(result_type());
+ const AbstractType& res_type = AbstractType::Handle(zone, result_type());
if (res_type.IsVoidType()) {
return false;
}
@@ -6626,13 +6653,13 @@ bool Function::TypeTest(TypeTestKind test_kind,
const int other_num_params =
other_num_fixed_params + other_num_opt_named_params;
bool found_param_name;
- String& other_param_name = String::Handle();
+ String& other_param_name = String::Handle(zone);
for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) {
other_param_name = other.ParameterNameAt(i);
ASSERT(other_param_name.IsSymbol());
found_param_name = false;
for (intptr_t j = num_fixed_params; j < num_params; j++) {
- ASSERT(String::Handle(ParameterNameAt(j)).IsSymbol());
+ ASSERT(String::Handle(zone, ParameterNameAt(j)).IsSymbol());
if (ParameterNameAt(j) == other_param_name.raw()) {
found_param_name = true;
if (!TestParameterType(test_kind, j, i, other, bound_error, space)) {
@@ -6762,11 +6789,13 @@ RawFunction* Function::New(const String& name,
RawFunction* Function::Clone(const Class& new_owner) const {
ASSERT(!IsGenerativeConstructor());
- Function& clone = Function::Handle();
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Function& clone = Function::Handle(zone);
clone ^= Object::Clone(*this, Heap::kOld);
- const Class& origin = Class::Handle(this->origin());
+ const Class& origin = Class::Handle(zone, this->origin());
const PatchClass& clone_owner =
- PatchClass::Handle(PatchClass::New(new_owner, origin));
+ PatchClass::Handle(zone, PatchClass::New(new_owner, origin));
clone.set_owner(clone_owner);
clone.ClearICDataArray();
clone.ClearCode();
@@ -6775,14 +6804,27 @@ RawFunction* Function::Clone(const Class& new_owner) const {
clone.set_optimized_instruction_count(0);
clone.set_optimized_call_site_count(0);
clone.set_kernel_function(kernel_function());
- // TODO(regis): Clone function type parameters (their bounds may change).
if (new_owner.NumTypeParameters() > 0) {
// Adjust uninstantiated types to refer to type parameters of the new owner.
- AbstractType& type = AbstractType::Handle(clone.result_type());
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, type_parameters());
+ if (!type_params.IsNull()) {
+ const intptr_t num_type_params = type_params.Length();
+ const TypeArguments& type_params_clone =
+ TypeArguments::Handle(zone, TypeArguments::New(num_type_params));
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ type_param ^= type_param.CloneUninstantiated(new_owner);
+ type_params_clone.SetTypeAt(i, type_param);
+ }
+ clone.set_type_parameters(type_params_clone);
+ }
+ AbstractType& type = AbstractType::Handle(zone, clone.result_type());
type ^= type.CloneUninstantiated(new_owner);
clone.set_result_type(type);
const intptr_t num_params = clone.NumParameters();
- Array& array = Array::Handle(clone.parameter_types());
+ Array& array = Array::Handle(zone, clone.parameter_types());
array ^= Object::Clone(array, Heap::kOld);
clone.set_parameter_types(array);
for (intptr_t i = 0; i < num_params; i++) {
@@ -6873,6 +6915,10 @@ RawFunction* Function::ImplicitClosureFunction() const {
closure_function.set_context_scope(context_scope);
}
+ // Set closure function's type parameters.
+ closure_function.set_type_parameters(
+ TypeArguments::Handle(type_parameters()));
+
// Set closure function's result type to this result type.
closure_function.set_result_type(AbstractType::Handle(result_type()));
@@ -7065,12 +7111,37 @@ RawString* Function::BuildSignature(NameVisibility name_visibility) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
GrowableHandlePtrArray<const String> pieces(zone, 4);
+ String& name = String::Handle(zone);
+ if (FLAG_reify_generic_functions) {
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, type_parameters());
+ if (!type_params.IsNull()) {
+ const intptr_t num_type_params = type_params.Length();
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ AbstractType& bound = AbstractType::Handle(zone);
+ pieces.Add(Symbols::LAngleBracket());
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ name = type_param.name();
+ pieces.Add(name);
+ bound = type_param.bound();
+ if (!bound.IsNull() && !bound.IsObjectType()) {
+ pieces.Add(Symbols::SpaceExtendsSpace());
+ name = bound.BuildName(name_visibility);
+ pieces.Add(name);
+ }
+ if (i < num_type_params - 1) {
+ pieces.Add(Symbols::CommaSpace());
+ }
+ }
+ pieces.Add(Symbols::RAngleBracket());
siva 2017/04/20 20:32:08 Do we still want '<>' if num_type_params is 0? or
regis 2017/04/20 21:18:26 Yes, we should never see an empty array. I added a
+ }
+ }
pieces.Add(Symbols::LParen());
BuildSignatureParameters(thread, zone, name_visibility, &pieces);
pieces.Add(Symbols::RParenArrow());
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
- const String& name =
- String::Handle(zone, res_type.BuildName(name_visibility));
+ name = res_type.BuildName(name_visibility);
pieces.Add(name);
return Symbols::FromConcatAll(thread, pieces);
}
@@ -15814,7 +15885,6 @@ bool Instance::IsInstanceOf(
if (!sig_fun.HasInstantiatedSignature()) {
const TypeArguments& function_type_arguments =
TypeArguments::Handle(zone, sig_fun.type_parameters());
- // TODO(regis): Pass the closure context to InstantiateSignatureFrom().
// No bound error possible, since the instance exists.
sig_fun = sig_fun.InstantiateSignatureFrom(
type_arguments, function_type_arguments, Heap::kOld);
@@ -17123,6 +17193,35 @@ bool Type::IsEquivalent(const Instance& other, TrailPtr trail) const {
const Function& other_sig_fun =
Function::Handle(zone, other_type.signature());
+ if (FLAG_reify_generic_functions) {
+ // Compare function type parameters and their bounds.
+ const intptr_t num_type_params = sig_fun.NumTypeParameters(thread);
+ if (num_type_params != other_sig_fun.NumTypeParameters(thread)) {
+ return false;
+ }
+ if (num_type_params > 0) {
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, sig_fun.type_parameters());
+ ASSERT(!type_params.IsNull());
+ const TypeArguments& other_type_params =
+ TypeArguments::Handle(zone, other_sig_fun.type_parameters());
+ ASSERT(!other_type_params.IsNull());
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ TypeParameter& other_type_param = TypeParameter::Handle(zone);
+ AbstractType& bound = AbstractType::Handle(zone);
+ AbstractType& other_bound = AbstractType::Handle(zone);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ other_type_param ^= other_type_params.TypeAt(i);
+ bound = type_param.bound();
+ other_bound = other_type_param.bound();
+ if (!bound.Equals(other_bound)) {
+ return false;
+ }
+ }
+ }
siva 2017/04/20 20:32:08 This code here is very similar to the one in Funct
regis 2017/04/20 21:18:26 That was bugging me too, and then I forgot :-) I a
+ }
+
// Compare number of function parameters.
const intptr_t num_fixed_params = sig_fun.num_fixed_parameters();
const intptr_t other_num_fixed_params = other_sig_fun.num_fixed_parameters();
@@ -17211,7 +17310,20 @@ RawAbstractType* Type::CloneUnfinalized() const {
const Class& owner = Class::Handle(zone, fun.Owner());
Function& fun_clone = Function::Handle(
zone, Function::NewSignatureFunction(owner, TokenPosition::kNoSource));
- // TODO(regis): Handle cloning of a generic function type.
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, fun.type_parameters());
+ if (!type_params.IsNull()) {
+ const intptr_t num_type_params = type_params.Length();
+ const TypeArguments& type_params_clone =
+ TypeArguments::Handle(zone, TypeArguments::New(num_type_params));
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ type_param ^= type_param.CloneUnfinalized();
+ type_params_clone.SetTypeAt(i, type_param);
+ }
+ fun_clone.set_type_parameters(type_params_clone);
+ }
siva 2017/04/20 20:32:08 ditto comment about this matching up with the one
regis 2017/04/20 21:18:25 This one cannot easily be factored out. One is cal
AbstractType& type = AbstractType::Handle(zone, fun.result_type());
type = type.CloneUnfinalized();
fun_clone.set_result_type(type);
@@ -17267,6 +17379,20 @@ RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
Function& fun_clone = Function::Handle(
zone,
Function::NewSignatureFunction(new_owner, TokenPosition::kNoSource));
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, fun.type_parameters());
+ if (!type_params.IsNull()) {
+ const intptr_t num_type_params = type_params.Length();
+ const TypeArguments& type_params_clone =
+ TypeArguments::Handle(zone, TypeArguments::New(num_type_params));
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ type_param ^= type_param.CloneUninstantiated(new_owner, trail);
+ type_params_clone.SetTypeAt(i, type_param);
+ }
+ fun_clone.set_type_parameters(type_params_clone);
+ }
AbstractType& type = AbstractType::Handle(zone, fun.result_type());
type = type.CloneUninstantiated(new_owner, trail);
fun_clone.set_result_type(type);
@@ -17393,6 +17519,8 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
Function& sig_fun = Function::Handle(
zone,
Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
+ sig_fun.set_type_parameters(
+ TypeArguments::Handle(zone, fun.type_parameters()));
type = fun.result_type();
type = type.Canonicalize(trail);
sig_fun.set_result_type(type);
@@ -18025,18 +18153,19 @@ RawAbstractType* TypeParameter::CloneUninstantiated(const Class& new_owner,
if (!clone.IsNull()) {
return clone.raw();
}
- const Class& old_owner = Class::Handle(parameterized_class());
- if (old_owner.IsNull()) {
+ intptr_t new_index = index();
+ AbstractType& upper_bound = AbstractType::Handle(bound());
+ const Function& fun = Function::Handle(parameterized_function());
+ Class& cls = Class::Handle(parameterized_class());
+ if (!cls.IsNull()) {
+ ASSERT(fun.IsNull());
+ new_index += new_owner.NumTypeArguments() - cls.NumTypeArguments();
+ cls = new_owner.raw();
+ } else {
ASSERT(IsFunctionTypeParameter());
- // Function type parameters do not need cloning.
- return raw();
+ // Only the bounds of function type parameters need cloning.
}
- const intptr_t new_index =
- index() + new_owner.NumTypeArguments() - old_owner.NumTypeArguments();
- AbstractType& upper_bound = AbstractType::Handle(bound());
- ASSERT(parameterized_function() == Function::null());
- clone = TypeParameter::New(new_owner, Function::Handle(), new_index,
- String::Handle(name()),
+ clone = TypeParameter::New(cls, fun, new_index, String::Handle(name()),
upper_bound, // Not cloned yet.
token_pos());
clone.SetIsFinalized();
« no previous file with comments | « no previous file | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698