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

Unified Diff: runtime/vm/object.cc

Issue 224793002: Simplify and fix instantiation of recursive types. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 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/raw_object_snapshot.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 34737)
+++ runtime/vm/object.cc (working copy)
@@ -4037,7 +4037,9 @@
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
- result = CombineHashes(result, type.Hash());
+ // The hash may be calculated during type finalization (for debugging
+ // purposes only) while a type argument is still temporarily null.
+ result = CombineHashes(result, type.IsNull() ? 0 : type.Hash());
}
return FinalizeHash(result);
}
@@ -4101,7 +4103,11 @@
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
- if (type.IsRecursive()) {
+ // If this type argument is null, the type parameterized with this type
+ // argument is still being finalized and is definitely recursive. The null
+ // type argument will be replaced by a non-null type before the type is
+ // marked as finalized.
+ if (type.IsNull() || type.IsRecursive()) {
return true;
}
}
@@ -4253,24 +4259,12 @@
}
-void TypeArguments::set_type_at(intptr_t index,
+void TypeArguments::SetTypeAt(intptr_t index,
const AbstractType& value) const {
StorePointer(TypeAddr(index), value.raw());
}
-void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
- const AbstractType& type_arg = AbstractType::Handle(TypeAt(index));
- if (type_arg.IsTypeRef()) {
- if (value.raw() != type_arg.raw()) {
- TypeRef::Cast(type_arg).set_type(value);
- }
- } else {
- set_type_at(index, value);
- }
-}
-
-
bool TypeArguments::IsResolved() const {
AbstractType& type = AbstractType::Handle();
const intptr_t num_types = Length();
@@ -4291,7 +4285,9 @@
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < len; i++) {
type = TypeAt(from_index + i);
- if (!type.IsInstantiated(trail)) {
+ // If the type argument is null, the type parameterized with this type
+ // argument is still being finalized. Skip this null type argument.
+ if (!type.IsNull() && !type.IsInstantiated(trail)) {
return false;
}
}
@@ -4455,7 +4451,13 @@
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
- if (!type.IsInstantiated()) {
+ // If this type argument T is null, the type A containing T in its flattened
+ // type argument vector V is recursive and is still being finalized.
+ // T is the type argument of a super type of A. T is being instantiated
+ // during finalization of V, which is also the instantiator. T depends
+ // solely on the type parameters of A and will be replaced by a non-null
+ // type before A is marked as finalized.
+ if (!type.IsNull() && !type.IsInstantiated()) {
type = type.InstantiateFrom(instantiator_type_arguments,
bound_error,
trail);
@@ -4698,14 +4700,19 @@
type_arg = type_arg.Canonicalize(trail);
SetTypeAt(i, type_arg);
}
- // Canonicalization of a type should not change its hash. Verify.
- ASSERT(Hash() == hash);
+ // Canonicalization of a recursive type may change its hash.
+ intptr_t canonical_hash = hash;
+ if (IsRecursive()) {
+ canonical_hash = Hash();
+ }
// Canonicalization of the type argument's own type arguments may add an
// entry to the table, or even grow the table, and thereby change the
// previously calculated index.
table = object_store->canonical_type_arguments();
- if (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used) {
- index = FindIndexInCanonicalTypeArguments(isolate, table, *this, hash);
+ if ((canonical_hash != hash) ||
+ (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used)) {
+ index = FindIndexInCanonicalTypeArguments(
+ isolate, table, *this, canonical_hash);
result ^= table.At(index);
}
if (result.IsNull()) {
@@ -13497,26 +13504,40 @@
if (IsMalformed()) {
return raw();
}
+ // Instantiating this type with its own type arguments as instantiator can
+ // occur during finalization and bounds checking. Return the type unchanged.
+ if (arguments() == instantiator_type_arguments.raw()) {
+ return raw();
+ }
+ // If this type is recursive, we may already be instantiating it.
+ Type& instantiated_type = Type::Handle();
+ instantiated_type ^= OnlyBuddyInTrail(trail);
+ if (!instantiated_type.IsNull()) {
+ ASSERT(IsRecursive());
+ return instantiated_type.raw();
+ }
// Note that the type class has to be resolved at this time, but not
// necessarily finalized yet. We may be checking bounds at compile time or
// finalizing the type argument vector of a recursive type.
const Class& cls = Class::Handle(type_class());
+
// This uninstantiated type is not modified, as it can be instantiated
- // with different instantiators.
- Type& instantiated_type = Type::Handle(
- Type::New(cls, TypeArguments::Handle(), token_pos()));
- if (arguments() != TypeArguments::null()) {
- TypeArguments& type_arguments = TypeArguments::Handle(arguments());
- ASSERT(type_arguments.Length() == cls.NumTypeArguments());
- if (type_arguments.IsRecursive()) {
- AddOnlyBuddyToTrail(&trail, instantiated_type);
- }
- type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
- bound_error,
- trail);
- instantiated_type.set_arguments(type_arguments);
+ // with different instantiators. Allocate a new instantiated version of it.
+ instantiated_type = Type::New(cls, TypeArguments::Handle(), token_pos());
+ TypeArguments& type_arguments = TypeArguments::Handle(arguments());
+ ASSERT(type_arguments.Length() == cls.NumTypeArguments());
+ if (type_arguments.IsRecursive()) {
+ AddOnlyBuddyToTrail(&trail, instantiated_type);
}
- instantiated_type.SetIsFinalized();
+ type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
+ bound_error,
+ trail);
+ instantiated_type.set_arguments(type_arguments);
+ if (IsFinalized()) {
+ instantiated_type.SetIsFinalized();
+ } else {
+ instantiated_type.set_is_resolved();
+ }
// Canonicalization is not part of instantiation.
return instantiated_type.raw();
}
@@ -13878,26 +13899,30 @@
}
-RawAbstractType* TypeRef::InstantiateFrom(
+RawTypeRef* TypeRef::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
GrowableObjectArray* trail) const {
+ TypeRef& instantiated_type_ref = TypeRef::Handle();
+ instantiated_type_ref ^= OnlyBuddyInTrail(trail);
+ if (!instantiated_type_ref.IsNull()) {
+ return instantiated_type_ref.raw();
+ }
AbstractType& ref_type = AbstractType::Handle(type());
ASSERT(!ref_type.IsTypeRef());
AbstractType& instantiated_ref_type = AbstractType::Handle();
- instantiated_ref_type ^= ref_type.OnlyBuddyInTrail(trail);
- if (instantiated_ref_type.IsNull()) {
- // The referenced type is first encountered here during instantiation.
- instantiated_ref_type = ref_type.InstantiateFrom(
+ instantiated_ref_type = ref_type.InstantiateFrom(
instantiator_type_arguments, bound_error, trail);
- }
ASSERT(!instantiated_ref_type.IsTypeRef());
- return TypeRef::New(instantiated_ref_type);
+ instantiated_type_ref = TypeRef::New(instantiated_ref_type);
+ AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
+ return instantiated_type_ref.raw();
}
void TypeRef::set_type(const AbstractType& value) const {
ASSERT(value.HasResolvedTypeClass());
+ ASSERT(!value.IsTypeRef());
StorePointer(&raw_ptr()->type_, value.raw());
}
@@ -13910,6 +13935,8 @@
if (TestAndAddToTrail(&trail)) {
return raw();
}
+ // TODO(regis): Try to reduce the number of nodes required to represent the
+ // referenced recursive type.
AbstractType& ref_type = AbstractType::Handle(type());
ref_type = ref_type.Canonicalize(trail);
set_type(ref_type);
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object_snapshot.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698