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

Side by Side 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, 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object_snapshot.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 4019 matching lines...) Expand 10 before | Expand all | Expand 10 after
4030 4030
4031 4031
4032 intptr_t TypeArguments::Hash() const { 4032 intptr_t TypeArguments::Hash() const {
4033 if (IsNull()) return 0; 4033 if (IsNull()) return 0;
4034 const intptr_t num_types = Length(); 4034 const intptr_t num_types = Length();
4035 if (IsRaw(0, num_types)) return 0; 4035 if (IsRaw(0, num_types)) return 0;
4036 uint32_t result = 0; 4036 uint32_t result = 0;
4037 AbstractType& type = AbstractType::Handle(); 4037 AbstractType& type = AbstractType::Handle();
4038 for (intptr_t i = 0; i < num_types; i++) { 4038 for (intptr_t i = 0; i < num_types; i++) {
4039 type = TypeAt(i); 4039 type = TypeAt(i);
4040 result = CombineHashes(result, type.Hash()); 4040 // The hash may be calculated during type finalization (for debugging
4041 // purposes only) while a type argument is still temporarily null.
4042 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash());
4041 } 4043 }
4042 return FinalizeHash(result); 4044 return FinalizeHash(result);
4043 } 4045 }
4044 4046
4045 4047
4046 RawString* TypeArguments::SubvectorName(intptr_t from_index, 4048 RawString* TypeArguments::SubvectorName(intptr_t from_index,
4047 intptr_t len, 4049 intptr_t len,
4048 NameVisibility name_visibility) const { 4050 NameVisibility name_visibility) const {
4049 ASSERT(from_index + len <= Length()); 4051 ASSERT(from_index + len <= Length());
4050 String& name = String::Handle(); 4052 String& name = String::Handle();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4094 return true; 4096 return true;
4095 } 4097 }
4096 4098
4097 4099
4098 bool TypeArguments::IsRecursive() const { 4100 bool TypeArguments::IsRecursive() const {
4099 if (IsNull()) return false; 4101 if (IsNull()) return false;
4100 const intptr_t num_types = Length(); 4102 const intptr_t num_types = Length();
4101 AbstractType& type = AbstractType::Handle(); 4103 AbstractType& type = AbstractType::Handle();
4102 for (intptr_t i = 0; i < num_types; i++) { 4104 for (intptr_t i = 0; i < num_types; i++) {
4103 type = TypeAt(i); 4105 type = TypeAt(i);
4104 if (type.IsRecursive()) { 4106 // If this type argument is null, the type parameterized with this type
4107 // argument is still being finalized and is definitely recursive. The null
4108 // type argument will be replaced by a non-null type before the type is
4109 // marked as finalized.
4110 if (type.IsNull() || type.IsRecursive()) {
4105 return true; 4111 return true;
4106 } 4112 }
4107 } 4113 }
4108 return false; 4114 return false;
4109 } 4115 }
4110 4116
4111 4117
4112 bool TypeArguments::IsDynamicTypes(bool raw_instantiated, 4118 bool TypeArguments::IsDynamicTypes(bool raw_instantiated,
4113 intptr_t from_index, 4119 intptr_t from_index,
4114 intptr_t len) const { 4120 intptr_t len) const {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
4246 ASSERT(!IsNull()); 4252 ASSERT(!IsNull());
4247 return Smi::Value(raw_ptr()->length_); 4253 return Smi::Value(raw_ptr()->length_);
4248 } 4254 }
4249 4255
4250 4256
4251 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const { 4257 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
4252 return *TypeAddr(index); 4258 return *TypeAddr(index);
4253 } 4259 }
4254 4260
4255 4261
4256 void TypeArguments::set_type_at(intptr_t index, 4262 void TypeArguments::SetTypeAt(intptr_t index,
4257 const AbstractType& value) const { 4263 const AbstractType& value) const {
4258 StorePointer(TypeAddr(index), value.raw()); 4264 StorePointer(TypeAddr(index), value.raw());
4259 } 4265 }
4260 4266
4261 4267
4262 void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
4263 const AbstractType& type_arg = AbstractType::Handle(TypeAt(index));
4264 if (type_arg.IsTypeRef()) {
4265 if (value.raw() != type_arg.raw()) {
4266 TypeRef::Cast(type_arg).set_type(value);
4267 }
4268 } else {
4269 set_type_at(index, value);
4270 }
4271 }
4272
4273
4274 bool TypeArguments::IsResolved() const { 4268 bool TypeArguments::IsResolved() const {
4275 AbstractType& type = AbstractType::Handle(); 4269 AbstractType& type = AbstractType::Handle();
4276 const intptr_t num_types = Length(); 4270 const intptr_t num_types = Length();
4277 for (intptr_t i = 0; i < num_types; i++) { 4271 for (intptr_t i = 0; i < num_types; i++) {
4278 type = TypeAt(i); 4272 type = TypeAt(i);
4279 if (!type.IsResolved()) { 4273 if (!type.IsResolved()) {
4280 return false; 4274 return false;
4281 } 4275 }
4282 } 4276 }
4283 return true; 4277 return true;
4284 } 4278 }
4285 4279
4286 4280
4287 bool TypeArguments::IsSubvectorInstantiated(intptr_t from_index, 4281 bool TypeArguments::IsSubvectorInstantiated(intptr_t from_index,
4288 intptr_t len, 4282 intptr_t len,
4289 GrowableObjectArray* trail) const { 4283 GrowableObjectArray* trail) const {
4290 ASSERT(!IsNull()); 4284 ASSERT(!IsNull());
4291 AbstractType& type = AbstractType::Handle(); 4285 AbstractType& type = AbstractType::Handle();
4292 for (intptr_t i = 0; i < len; i++) { 4286 for (intptr_t i = 0; i < len; i++) {
4293 type = TypeAt(from_index + i); 4287 type = TypeAt(from_index + i);
4294 if (!type.IsInstantiated(trail)) { 4288 // If the type argument is null, the type parameterized with this type
4289 // argument is still being finalized. Skip this null type argument.
4290 if (!type.IsNull() && !type.IsInstantiated(trail)) {
4295 return false; 4291 return false;
4296 } 4292 }
4297 } 4293 }
4298 return true; 4294 return true;
4299 } 4295 }
4300 4296
4301 4297
4302 bool TypeArguments::IsUninstantiatedIdentity() const { 4298 bool TypeArguments::IsUninstantiatedIdentity() const {
4303 ASSERT(!IsInstantiated()); 4299 ASSERT(!IsInstantiated());
4304 AbstractType& type = AbstractType::Handle(); 4300 AbstractType& type = AbstractType::Handle();
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
4448 IsUninstantiatedIdentity() && 4444 IsUninstantiatedIdentity() &&
4449 (instantiator_type_arguments.Length() == Length())) { 4445 (instantiator_type_arguments.Length() == Length())) {
4450 return instantiator_type_arguments.raw(); 4446 return instantiator_type_arguments.raw();
4451 } 4447 }
4452 const intptr_t num_types = Length(); 4448 const intptr_t num_types = Length();
4453 TypeArguments& instantiated_array = 4449 TypeArguments& instantiated_array =
4454 TypeArguments::Handle(TypeArguments::New(num_types, Heap::kNew)); 4450 TypeArguments::Handle(TypeArguments::New(num_types, Heap::kNew));
4455 AbstractType& type = AbstractType::Handle(); 4451 AbstractType& type = AbstractType::Handle();
4456 for (intptr_t i = 0; i < num_types; i++) { 4452 for (intptr_t i = 0; i < num_types; i++) {
4457 type = TypeAt(i); 4453 type = TypeAt(i);
4458 if (!type.IsInstantiated()) { 4454 // If this type argument T is null, the type A containing T in its flattened
4455 // type argument vector V is recursive and is still being finalized.
4456 // T is the type argument of a super type of A. T is being instantiated
4457 // during finalization of V, which is also the instantiator. T depends
4458 // solely on the type parameters of A and will be replaced by a non-null
4459 // type before A is marked as finalized.
4460 if (!type.IsNull() && !type.IsInstantiated()) {
4459 type = type.InstantiateFrom(instantiator_type_arguments, 4461 type = type.InstantiateFrom(instantiator_type_arguments,
4460 bound_error, 4462 bound_error,
4461 trail); 4463 trail);
4462 } 4464 }
4463 instantiated_array.SetTypeAt(i, type); 4465 instantiated_array.SetTypeAt(i, type);
4464 } 4466 }
4465 return instantiated_array.raw(); 4467 return instantiated_array.raw();
4466 } 4468 }
4467 4469
4468 4470
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
4691 TypeArguments& result = TypeArguments::Handle(isolate); 4693 TypeArguments& result = TypeArguments::Handle(isolate);
4692 result ^= table.At(index); 4694 result ^= table.At(index);
4693 if (result.IsNull()) { 4695 if (result.IsNull()) {
4694 // Canonicalize each type argument. 4696 // Canonicalize each type argument.
4695 AbstractType& type_arg = AbstractType::Handle(isolate); 4697 AbstractType& type_arg = AbstractType::Handle(isolate);
4696 for (intptr_t i = 0; i < num_types; i++) { 4698 for (intptr_t i = 0; i < num_types; i++) {
4697 type_arg = TypeAt(i); 4699 type_arg = TypeAt(i);
4698 type_arg = type_arg.Canonicalize(trail); 4700 type_arg = type_arg.Canonicalize(trail);
4699 SetTypeAt(i, type_arg); 4701 SetTypeAt(i, type_arg);
4700 } 4702 }
4701 // Canonicalization of a type should not change its hash. Verify. 4703 // Canonicalization of a recursive type may change its hash.
4702 ASSERT(Hash() == hash); 4704 intptr_t canonical_hash = hash;
4705 if (IsRecursive()) {
4706 canonical_hash = Hash();
4707 }
4703 // Canonicalization of the type argument's own type arguments may add an 4708 // Canonicalization of the type argument's own type arguments may add an
4704 // entry to the table, or even grow the table, and thereby change the 4709 // entry to the table, or even grow the table, and thereby change the
4705 // previously calculated index. 4710 // previously calculated index.
4706 table = object_store->canonical_type_arguments(); 4711 table = object_store->canonical_type_arguments();
4707 if (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used) { 4712 if ((canonical_hash != hash) ||
4708 index = FindIndexInCanonicalTypeArguments(isolate, table, *this, hash); 4713 (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used)) {
4714 index = FindIndexInCanonicalTypeArguments(
4715 isolate, table, *this, canonical_hash);
4709 result ^= table.At(index); 4716 result ^= table.At(index);
4710 } 4717 }
4711 if (result.IsNull()) { 4718 if (result.IsNull()) {
4712 // Make sure we have an old space object and add it to the table. 4719 // Make sure we have an old space object and add it to the table.
4713 if (this->IsNew()) { 4720 if (this->IsNew()) {
4714 result ^= Object::Clone(*this, Heap::kOld); 4721 result ^= Object::Clone(*this, Heap::kOld);
4715 } else { 4722 } else {
4716 result ^= this->raw(); 4723 result ^= this->raw();
4717 } 4724 }
4718 ASSERT(result.IsOld()); 4725 ASSERT(result.IsOld());
(...skipping 8771 matching lines...) Expand 10 before | Expand all | Expand 10 after
13490 RawAbstractType* Type::InstantiateFrom( 13497 RawAbstractType* Type::InstantiateFrom(
13491 const TypeArguments& instantiator_type_arguments, 13498 const TypeArguments& instantiator_type_arguments,
13492 Error* bound_error, 13499 Error* bound_error,
13493 GrowableObjectArray* trail) const { 13500 GrowableObjectArray* trail) const {
13494 ASSERT(IsFinalized() || IsBeingFinalized()); 13501 ASSERT(IsFinalized() || IsBeingFinalized());
13495 ASSERT(!IsInstantiated()); 13502 ASSERT(!IsInstantiated());
13496 // Return the uninstantiated type unchanged if malformed. No copy needed. 13503 // Return the uninstantiated type unchanged if malformed. No copy needed.
13497 if (IsMalformed()) { 13504 if (IsMalformed()) {
13498 return raw(); 13505 return raw();
13499 } 13506 }
13507 // Instantiating this type with its own type arguments as instantiator can
13508 // occur during finalization and bounds checking. Return the type unchanged.
13509 if (arguments() == instantiator_type_arguments.raw()) {
13510 return raw();
13511 }
13512 // If this type is recursive, we may already be instantiating it.
13513 Type& instantiated_type = Type::Handle();
13514 instantiated_type ^= OnlyBuddyInTrail(trail);
13515 if (!instantiated_type.IsNull()) {
13516 ASSERT(IsRecursive());
13517 return instantiated_type.raw();
13518 }
13500 // Note that the type class has to be resolved at this time, but not 13519 // Note that the type class has to be resolved at this time, but not
13501 // necessarily finalized yet. We may be checking bounds at compile time or 13520 // necessarily finalized yet. We may be checking bounds at compile time or
13502 // finalizing the type argument vector of a recursive type. 13521 // finalizing the type argument vector of a recursive type.
13503 const Class& cls = Class::Handle(type_class()); 13522 const Class& cls = Class::Handle(type_class());
13523
13504 // This uninstantiated type is not modified, as it can be instantiated 13524 // This uninstantiated type is not modified, as it can be instantiated
13505 // with different instantiators. 13525 // with different instantiators. Allocate a new instantiated version of it.
13506 Type& instantiated_type = Type::Handle( 13526 instantiated_type = Type::New(cls, TypeArguments::Handle(), token_pos());
13507 Type::New(cls, TypeArguments::Handle(), token_pos())); 13527 TypeArguments& type_arguments = TypeArguments::Handle(arguments());
13508 if (arguments() != TypeArguments::null()) { 13528 ASSERT(type_arguments.Length() == cls.NumTypeArguments());
13509 TypeArguments& type_arguments = TypeArguments::Handle(arguments()); 13529 if (type_arguments.IsRecursive()) {
13510 ASSERT(type_arguments.Length() == cls.NumTypeArguments()); 13530 AddOnlyBuddyToTrail(&trail, instantiated_type);
13511 if (type_arguments.IsRecursive()) {
13512 AddOnlyBuddyToTrail(&trail, instantiated_type);
13513 }
13514 type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
13515 bound_error,
13516 trail);
13517 instantiated_type.set_arguments(type_arguments);
13518 } 13531 }
13519 instantiated_type.SetIsFinalized(); 13532 type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
13533 bound_error,
13534 trail);
13535 instantiated_type.set_arguments(type_arguments);
13536 if (IsFinalized()) {
13537 instantiated_type.SetIsFinalized();
13538 } else {
13539 instantiated_type.set_is_resolved();
13540 }
13520 // Canonicalization is not part of instantiation. 13541 // Canonicalization is not part of instantiation.
13521 return instantiated_type.raw(); 13542 return instantiated_type.raw();
13522 } 13543 }
13523 13544
13524 13545
13525 bool Type::IsEquivalent(const Instance& other, 13546 bool Type::IsEquivalent(const Instance& other,
13526 GrowableObjectArray* trail) const { 13547 GrowableObjectArray* trail) const {
13527 ASSERT(!IsNull()); 13548 ASSERT(!IsNull());
13528 if (raw() == other.raw()) { 13549 if (raw() == other.raw()) {
13529 return true; 13550 return true;
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
13871 if (raw() == other.raw()) { 13892 if (raw() == other.raw()) {
13872 return true; 13893 return true;
13873 } 13894 }
13874 if (TestAndAddBuddyToTrail(&trail, other)) { 13895 if (TestAndAddBuddyToTrail(&trail, other)) {
13875 return true; 13896 return true;
13876 } 13897 }
13877 return AbstractType::Handle(type()).IsEquivalent(other, trail); 13898 return AbstractType::Handle(type()).IsEquivalent(other, trail);
13878 } 13899 }
13879 13900
13880 13901
13881 RawAbstractType* TypeRef::InstantiateFrom( 13902 RawTypeRef* TypeRef::InstantiateFrom(
13882 const TypeArguments& instantiator_type_arguments, 13903 const TypeArguments& instantiator_type_arguments,
13883 Error* bound_error, 13904 Error* bound_error,
13884 GrowableObjectArray* trail) const { 13905 GrowableObjectArray* trail) const {
13906 TypeRef& instantiated_type_ref = TypeRef::Handle();
13907 instantiated_type_ref ^= OnlyBuddyInTrail(trail);
13908 if (!instantiated_type_ref.IsNull()) {
13909 return instantiated_type_ref.raw();
13910 }
13885 AbstractType& ref_type = AbstractType::Handle(type()); 13911 AbstractType& ref_type = AbstractType::Handle(type());
13886 ASSERT(!ref_type.IsTypeRef()); 13912 ASSERT(!ref_type.IsTypeRef());
13887 AbstractType& instantiated_ref_type = AbstractType::Handle(); 13913 AbstractType& instantiated_ref_type = AbstractType::Handle();
13888 instantiated_ref_type ^= ref_type.OnlyBuddyInTrail(trail); 13914 instantiated_ref_type = ref_type.InstantiateFrom(
13889 if (instantiated_ref_type.IsNull()) {
13890 // The referenced type is first encountered here during instantiation.
13891 instantiated_ref_type = ref_type.InstantiateFrom(
13892 instantiator_type_arguments, bound_error, trail); 13915 instantiator_type_arguments, bound_error, trail);
13893 }
13894 ASSERT(!instantiated_ref_type.IsTypeRef()); 13916 ASSERT(!instantiated_ref_type.IsTypeRef());
13895 return TypeRef::New(instantiated_ref_type); 13917 instantiated_type_ref = TypeRef::New(instantiated_ref_type);
13918 AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
13919 return instantiated_type_ref.raw();
13896 } 13920 }
13897 13921
13898 13922
13899 void TypeRef::set_type(const AbstractType& value) const { 13923 void TypeRef::set_type(const AbstractType& value) const {
13900 ASSERT(value.HasResolvedTypeClass()); 13924 ASSERT(value.HasResolvedTypeClass());
13925 ASSERT(!value.IsTypeRef());
13901 StorePointer(&raw_ptr()->type_, value.raw()); 13926 StorePointer(&raw_ptr()->type_, value.raw());
13902 } 13927 }
13903 13928
13904 13929
13905 // A TypeRef cannot be canonical by definition. Only its referenced type can be. 13930 // A TypeRef cannot be canonical by definition. Only its referenced type can be.
13906 // Consider the type Derived, where class Derived extends Base<Derived>. 13931 // Consider the type Derived, where class Derived extends Base<Derived>.
13907 // The first type argument of its flattened type argument vector is Derived, 13932 // The first type argument of its flattened type argument vector is Derived,
13908 // represented by a TypeRef pointing to itself. 13933 // represented by a TypeRef pointing to itself.
13909 RawAbstractType* TypeRef::Canonicalize(GrowableObjectArray* trail) const { 13934 RawAbstractType* TypeRef::Canonicalize(GrowableObjectArray* trail) const {
13910 if (TestAndAddToTrail(&trail)) { 13935 if (TestAndAddToTrail(&trail)) {
13911 return raw(); 13936 return raw();
13912 } 13937 }
13938 // TODO(regis): Try to reduce the number of nodes required to represent the
13939 // referenced recursive type.
13913 AbstractType& ref_type = AbstractType::Handle(type()); 13940 AbstractType& ref_type = AbstractType::Handle(type());
13914 ref_type = ref_type.Canonicalize(trail); 13941 ref_type = ref_type.Canonicalize(trail);
13915 set_type(ref_type); 13942 set_type(ref_type);
13916 return raw(); 13943 return raw();
13917 } 13944 }
13918 13945
13919 13946
13920 intptr_t TypeRef::Hash() const { 13947 intptr_t TypeRef::Hash() const {
13921 // Do not calculate the hash of the referenced type to avoid divergence. 13948 // Do not calculate the hash of the referenced type to avoid divergence.
13922 const uint32_t result = 13949 const uint32_t result =
(...skipping 4310 matching lines...) Expand 10 before | Expand all | Expand 10 after
18233 return "_MirrorReference"; 18260 return "_MirrorReference";
18234 } 18261 }
18235 18262
18236 18263
18237 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 18264 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
18238 Instance::PrintToJSONStream(stream, ref); 18265 Instance::PrintToJSONStream(stream, ref);
18239 } 18266 }
18240 18267
18241 18268
18242 } // namespace dart 18269 } // namespace dart
OLDNEW
« 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