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

Unified Diff: runtime/vm/object.cc

Issue 2818273002: Remove parent_level field of function type parameters. (Closed)
Patch Set: address comments 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 | « runtime/vm/object.h ('k') | runtime/vm/object_service.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 b012e5a80fe6bba680491c37853f7619fb627382..eb563e30ad530f193de7565062449f58dba4455e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -111,6 +111,7 @@ Array* Object::null_array_ = NULL;
String* Object::null_string_ = NULL;
Instance* Object::null_instance_ = NULL;
TypeArguments* Object::null_type_arguments_ = NULL;
+TypeArguments* Object::empty_type_arguments_ = NULL;
Array* Object::empty_array_ = NULL;
Array* Object::zero_array_ = NULL;
Context* Object::empty_context_ = NULL;
@@ -515,6 +516,7 @@ void Object::InitOnce(Isolate* isolate) {
null_string_ = String::ReadOnlyHandle();
null_instance_ = Instance::ReadOnlyHandle();
null_type_arguments_ = TypeArguments::ReadOnlyHandle();
+ empty_type_arguments_ = TypeArguments::ReadOnlyHandle();
empty_array_ = Array::ReadOnlyHandle();
zero_array_ = Array::ReadOnlyHandle();
empty_context_ = Context::ReadOnlyHandle();
@@ -756,6 +758,22 @@ void Object::InitOnce(Isolate* isolate) {
// Needed for object pools of VM isolate stubs.
Class::NewTypedDataClass(kTypedDataInt8ArrayCid);
+ // Allocate and initialize the empty_type_arguments instance.
+ {
+ uword address = heap->Allocate(TypeArguments::InstanceSize(0), Heap::kOld);
+ InitializeObject(address, TypeArguments::kClassId,
+ TypeArguments::InstanceSize(0), true);
+ TypeArguments::initializeHandle(
+ empty_type_arguments_,
+ reinterpret_cast<RawTypeArguments*>(address + kHeapObjectTag));
+ empty_type_arguments_->StoreSmi(&empty_type_arguments_->raw_ptr()->length_,
+ Smi::New(0));
+ empty_type_arguments_->StoreSmi(&empty_type_arguments_->raw_ptr()->hash_,
+ Smi::New(0));
+ // instantiations_ field is initialized to null and should not be used.
+ empty_type_arguments_->SetCanonical();
+ }
+
// Allocate and initialize the empty_array instance.
{
uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld);
@@ -931,6 +949,8 @@ void Object::InitOnce(Isolate* isolate) {
ASSERT(null_instance_->IsInstance());
ASSERT(!null_type_arguments_->IsSmi());
ASSERT(null_type_arguments_->IsTypeArguments());
+ ASSERT(!empty_type_arguments_->IsSmi());
+ ASSERT(empty_type_arguments_->IsTypeArguments());
ASSERT(!empty_array_->IsSmi());
ASSERT(empty_array_->IsArray());
ASSERT(!zero_array_->IsSmi());
@@ -4717,14 +4737,9 @@ bool TypeArguments::IsDynamicTypes(bool raw_instantiated,
type = TypeAt(from_index + i);
if (!type.HasResolvedTypeClass()) {
if (raw_instantiated && type.IsTypeParameter()) {
- const TypeParameter& type_param = TypeParameter::Cast(type);
- if (type_param.IsClassTypeParameter() ||
- (type_param.IsFunctionTypeParameter() &&
- type_param.parent_level() == 0)) {
- // An uninstantiated type parameter is equivalent to dynamic (even in
- // the presence of a malformed bound in checked mode).
- continue;
- }
+ // An uninstantiated type parameter is equivalent to dynamic (even in
+ // the presence of a malformed bound in checked mode).
+ continue;
}
return false;
}
@@ -5028,6 +5043,9 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
ASSERT(!IsInstantiated());
ASSERT(instantiator_type_arguments.IsNull() ||
instantiator_type_arguments.IsCanonical());
+ // TODO(regis): It is not clear yet whether we will canonicalize the result
+ // of the concatenation of function_type_arguments in a nested generic
+ // function. Leave the assert for now to be safe, but plan on revisiting.
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.IsCanonical());
// Lookup instantiator and, if found, return paired instantiated result.
@@ -5059,11 +5077,6 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
// InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
// indirectly, so the prior_instantiations array cannot have grown.
ASSERT(prior_instantiations.raw() == instantiations());
- // Do not cache result if the context is required to instantiate the
- // type arguments, i.e. they refer to the type parameters of parent functions.
- if (!IsInstantiated(kParentFunctions)) {
- return result.raw();
- }
// Add instantiator and function type args and result to instantiations array.
intptr_t length = prior_instantiations.Length();
if ((index + StubCode::kInstantiationSizeInWords) >= length) {
@@ -5989,6 +6002,18 @@ intptr_t Function::NumTypeParameters(Thread* thread) const {
}
+intptr_t Function::NumParentTypeParameters() const {
+ Thread* thread = Thread::Current();
+ Function& parent = Function::Handle(parent_function());
+ intptr_t num_parent_type_params = 0;
+ while (!parent.IsNull()) {
+ num_parent_type_params += parent.NumTypeParameters(thread);
+ parent ^= parent.parent_function();
+ }
+ return num_parent_type_params;
+}
+
+
RawTypeParameter* Function::LookupTypeParameter(
const String& type_name,
intptr_t* function_level) const {
@@ -6004,7 +6029,6 @@ RawTypeParameter* Function::LookupTypeParameter(
Function& function = thread->FunctionHandle();
function ^= this->raw();
- intptr_t parent_level = 0;
while (!function.IsNull()) {
type_params ^= function.type_parameters();
if (!type_params.IsNull()) {
@@ -6013,20 +6037,11 @@ RawTypeParameter* Function::LookupTypeParameter(
type_param ^= type_params.TypeAt(i);
type_param_name = type_param.name();
if (type_param_name.Equals(type_name)) {
- if (parent_level > 0) {
- // Clone type parameter and set parent_level.
- type_param = TypeParameter::New(
- Class::Handle(), function, type_param.index(), parent_level,
- type_param_name, AbstractType::Handle(type_param.bound()),
- TokenPosition::kNoSource);
- type_param.SetIsFinalized();
- }
return type_param.raw();
}
}
}
function ^= function.parent_function();
- parent_level++;
if (function_level != NULL) {
(*function_level)--;
}
@@ -6550,6 +6565,9 @@ 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.
+
// Check the result type.
const AbstractType& other_res_type =
AbstractType::Handle(other.result_type());
@@ -6969,9 +6987,14 @@ RawInstance* Function::ImplicitStaticClosure() const {
if (implicit_static_closure() == Instance::null()) {
Zone* zone = Thread::Current()->zone();
const Context& context = Object::empty_context();
- const TypeArguments& instantiator = TypeArguments::Handle(zone);
- Instance& closure = Instance::Handle(
- zone, Closure::New(instantiator, *this, context, Heap::kOld));
+ TypeArguments& function_type_arguments = TypeArguments::Handle(zone);
+ if (!HasInstantiatedSignature(kFunctions)) {
+ function_type_arguments = Object::empty_type_arguments().raw();
+ }
+ Instance& closure =
+ Instance::Handle(zone, Closure::New(Object::null_type_arguments(),
+ function_type_arguments, *this,
+ context, Heap::kOld));
set_implicit_static_closure(closure);
}
return implicit_static_closure();
@@ -6983,11 +7006,16 @@ RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const {
Zone* zone = Thread::Current()->zone();
const Context& context = Context::Handle(zone, Context::New(1));
context.SetAt(0, receiver);
- TypeArguments& instantiator = TypeArguments::Handle(zone);
+ TypeArguments& instantiator_type_arguments = TypeArguments::Handle(zone);
+ TypeArguments& function_type_arguments = TypeArguments::Handle(zone);
if (!HasInstantiatedSignature(kCurrentClass)) {
- instantiator = receiver.GetTypeArguments();
+ instantiator_type_arguments = receiver.GetTypeArguments();
+ }
+ if (!HasInstantiatedSignature(kFunctions)) {
+ function_type_arguments = Object::empty_type_arguments().raw();
}
- return Closure::New(instantiator, *this, context);
+ return Closure::New(instantiator_type_arguments, function_type_arguments,
+ *this, context);
}
@@ -15655,11 +15683,10 @@ RawAbstractType* Instance::GetType(Heap::Space space) const {
Function::Handle(Closure::Cast(*this).function());
Type& type = Type::Handle(signature.SignatureType());
if (!type.IsInstantiated()) {
- TypeArguments& instantiator_type_arguments =
- TypeArguments::Handle(Closure::Cast(*this).instantiator());
+ const TypeArguments& instantiator_type_arguments = TypeArguments::Handle(
+ Closure::Cast(*this).instantiator_type_arguments());
const TypeArguments& function_type_arguments =
- TypeArguments::Handle(signature.type_parameters());
- // TODO(regis): Pass the closure context to InstantiateSignatureFrom().
+ TypeArguments::Handle(Closure::Cast(*this).function_type_arguments());
// No bound error possible, since the instance exists.
type ^= type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments, NULL, NULL, NULL,
@@ -15750,11 +15777,10 @@ bool Instance::IsInstanceOf(
Function::Handle(zone, Type::Cast(instantiated_other).signature());
Function& sig_fun = Function::Handle(zone, Closure::Cast(*this).function());
if (!sig_fun.HasInstantiatedSignature()) {
- const TypeArguments& instantiator_type_arguments =
- TypeArguments::Handle(zone, Closure::Cast(*this).instantiator());
- const TypeArguments& function_type_arguments =
- TypeArguments::Handle(zone, sig_fun.type_parameters());
- // TODO(regis): Pass the closure context to InstantiateSignatureFrom().
+ const TypeArguments& instantiator_type_arguments = TypeArguments::Handle(
+ zone, Closure::Cast(*this).instantiator_type_arguments());
+ const TypeArguments& function_type_arguments = TypeArguments::Handle(
+ zone, Closure::Cast(*this).function_type_arguments());
sig_fun = sig_fun.InstantiateSignatureFrom(
instantiator_type_arguments, function_type_arguments, Heap::kOld);
}
@@ -16585,6 +16611,13 @@ 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() &&
+ (type_param.index() == other_type_param.index())) {
+ return true;
+ }
}
const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
// We may be checking bounds at finalization time and can encounter
@@ -17796,10 +17829,6 @@ bool TypeParameter::IsInstantiated(Genericity genericity,
return IsFunctionTypeParameter();
case kFunctions:
return IsClassTypeParameter();
- case kCurrentFunction:
- return IsClassTypeParameter() || (parent_level() > 0);
- case kParentFunctions:
- return IsClassTypeParameter() || (parent_level() == 0);
default:
UNREACHABLE();
}
@@ -17825,12 +17854,12 @@ bool TypeParameter::IsEquivalent(const Instance& other, TrailPtr trail) const {
if (parameterized_class_id() != other_type_param.parameterized_class_id()) {
return false;
}
+ // The function doesn't matter in type tests, but it does in canonicalization.
if (parameterized_function() != other_type_param.parameterized_function()) {
return false;
}
if (IsFinalized() == other_type_param.IsFinalized()) {
- return (index() == other_type_param.index()) &&
- (parent_level() == other_type_param.parent_level());
+ return (index() == other_type_param.index());
}
return name() == other_type_param.name();
}
@@ -17892,15 +17921,17 @@ RawAbstractType* TypeParameter::InstantiateFrom(
Heap::Space space) const {
ASSERT(IsFinalized());
if (IsFunctionTypeParameter()) {
- if (parent_level() == 0) {
- if (function_type_arguments.IsNull()) {
- return Type::DynamicType();
- }
- return function_type_arguments.TypeAt(index());
+ // We make the distinction between a null function_type_arguments vector,
+ // which instantiates every function type parameter to dynamic, and a
+ // (possibly empty) function_type_arguments vector of length N, which only
+ // instantiates function type parameters with indices below N.
+ if (function_type_arguments.IsNull()) {
+ return Type::DynamicType();
+ }
+ if (index() >= function_type_arguments.Length()) {
+ // Return uninstantiated type parameter unchanged.
+ return raw();
}
- // We need to find the type argument vector of the parent function at
- // parent_level() in the context.
- UNIMPLEMENTED();
return function_type_arguments.TypeAt(index());
}
ASSERT(IsClassTypeParameter());
@@ -17918,6 +17949,10 @@ RawAbstractType* TypeParameter::InstantiateFrom(
// time (i.e. compile time).
// Indeed, the instantiator (type arguments of an instance) is always
// instantiated at run time and any bounds were checked during allocation.
+ // Similarly, function type arguments are always instantiated before being
+ // passed to a function at run time and bounds are checked as part of the
+ // signature compatibility check (during call resolution or in the function
+ // prolog).
}
@@ -17991,7 +18026,7 @@ RawAbstractType* TypeParameter::CloneUnfinalized() const {
// No need to clone bound, as it is not part of the finalization state.
return TypeParameter::New(Class::Handle(parameterized_class()),
Function::Handle(parameterized_function()), index(),
- parent_level(), String::Handle(name()),
+ String::Handle(name()),
AbstractType::Handle(bound()), token_pos());
}
@@ -18014,7 +18049,7 @@ RawAbstractType* TypeParameter::CloneUninstantiated(const Class& new_owner,
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, 0,
+ clone = TypeParameter::New(new_owner, Function::Handle(), new_index,
String::Handle(name()),
upper_bound, // Not cloned yet.
token_pos());
@@ -18032,12 +18067,21 @@ RawString* TypeParameter::EnumerateURIs() const {
GrowableHandlePtrArray<const String> pieces(zone, 4);
pieces.Add(Symbols::TwoSpaces());
pieces.Add(String::Handle(zone, name()));
- pieces.Add(Symbols::SpaceOfSpace());
- const Class& cls = Class::Handle(zone, parameterized_class());
- pieces.Add(String::Handle(zone, cls.UserVisibleName()));
- pieces.Add(Symbols::SpaceIsFromSpace());
- const Library& library = Library::Handle(zone, cls.library());
- pieces.Add(String::Handle(zone, library.url()));
+ Class& cls = Class::Handle(zone, parameterized_class());
+ if (cls.IsNull()) {
+ const Function& fun = Function::Handle(zone, parameterized_function());
+ pieces.Add(Symbols::SpaceOfSpace());
+ pieces.Add(String::Handle(zone, fun.UserVisibleName()));
+ cls = fun.Owner(); // May be null.
+ // TODO(regis): Should we keep the function owner for better error messages?
+ }
+ if (!cls.IsNull()) {
+ pieces.Add(Symbols::SpaceOfSpace());
+ pieces.Add(String::Handle(zone, cls.UserVisibleName()));
+ pieces.Add(Symbols::SpaceIsFromSpace());
+ const Library& library = Library::Handle(zone, cls.library());
+ pieces.Add(String::Handle(zone, library.url()));
+ }
pieces.Add(Symbols::NewLine());
return Symbols::FromConcatAll(thread, pieces);
}
@@ -18050,7 +18094,6 @@ intptr_t TypeParameter::ComputeHash() const {
result = parameterized_class_id();
} else {
result = Function::Handle(parameterized_function()).Hash();
- result = CombineHashes(result, parent_level());
}
// No need to include the hash of the bound, since the type parameter is fully
// identified by its class and index.
@@ -18071,7 +18114,6 @@ RawTypeParameter* TypeParameter::New() {
RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
const Function& parameterized_function,
intptr_t index,
- intptr_t parent_level,
const String& name,
const AbstractType& bound,
TokenPosition token_pos) {
@@ -18080,7 +18122,6 @@ RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
result.set_parameterized_class(parameterized_class);
result.set_parameterized_function(parameterized_function);
result.set_index(index);
- result.set_parent_level(parent_level);
result.set_name(name);
result.set_bound(bound);
result.SetHash(0);
@@ -18097,13 +18138,6 @@ void TypeParameter::set_token_pos(TokenPosition token_pos) const {
}
-void TypeParameter::set_parent_level(intptr_t value) const {
- // TODO(regis): Report error in caller if not uint8.
- ASSERT(Utils::IsUint(8, value));
- StoreNonPointer(&raw_ptr()->parent_level_, value);
-}
-
-
void TypeParameter::set_type_state(int8_t state) const {
ASSERT((state == RawTypeParameter::kAllocated) ||
(state == RawTypeParameter::kBeingFinalized) ||
@@ -18118,16 +18152,14 @@ const char* TypeParameter::ToCString() const {
const char* bound_cstr = String::Handle(upper_bound.Name()).ToCString();
if (IsFunctionTypeParameter()) {
const char* format =
- "TypeParameter: name %s; index: %d; parent_level: %d, "
- "function: %s; bound: %s";
+ "TypeParameter: name %s; index: %d; function: %s; bound: %s";
const Function& function = Function::Handle(parameterized_function());
const char* fun_cstr = String::Handle(function.name()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, name_cstr, index(),
- parent_level(), fun_cstr, bound_cstr) +
- 1;
+ intptr_t len =
+ OS::SNPrint(NULL, 0, format, name_cstr, index(), fun_cstr, bound_cstr) +
+ 1;
char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, name_cstr, index(), parent_level(),
- fun_cstr, bound_cstr);
+ OS::SNPrint(chars, len, format, name_cstr, index(), fun_cstr, bound_cstr);
return chars;
} else {
const char* format =
@@ -22528,7 +22560,8 @@ const char* Closure::ToCString() const {
}
-RawClosure* Closure::New(const TypeArguments& instantiator,
+RawClosure* Closure::New(const TypeArguments& instantiator_type_arguments,
+ const TypeArguments& function_type_arguments,
const Function& function,
const Context& context,
Heap::Space space) {
@@ -22538,7 +22571,10 @@ RawClosure* Closure::New(const TypeArguments& instantiator,
Object::Allocate(Closure::kClassId, Closure::InstanceSize(), space);
NoSafepointScope no_safepoint;
result ^= raw;
- result.StorePointer(&result.raw_ptr()->instantiator_, instantiator.raw());
+ result.StorePointer(&result.raw_ptr()->instantiator_type_arguments_,
+ instantiator_type_arguments.raw());
+ result.StorePointer(&result.raw_ptr()->function_type_arguments_,
+ function_type_arguments.raw());
result.StorePointer(&result.raw_ptr()->function_, function.raw());
result.StorePointer(&result.raw_ptr()->context_, context.raw());
}
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698