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

Side by Side Diff: runtime/vm/object.cc

Issue 203443012: Fix canonicalization of 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/reusable_handles.h » ('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 3233 matching lines...) Expand 10 before | Expand all | Expand 10 after
3244 RawObject* Class::canonical_types() const { 3244 RawObject* Class::canonical_types() const {
3245 return raw_ptr()->canonical_types_; 3245 return raw_ptr()->canonical_types_;
3246 } 3246 }
3247 3247
3248 void Class::set_canonical_types(const Object& value) const { 3248 void Class::set_canonical_types(const Object& value) const {
3249 ASSERT(!value.IsNull()); 3249 ASSERT(!value.IsNull());
3250 StorePointer(&raw_ptr()->canonical_types_, value.raw()); 3250 StorePointer(&raw_ptr()->canonical_types_, value.raw());
3251 } 3251 }
3252 3252
3253 3253
3254 intptr_t Class::NumCanonicalTypes() const {
3255 if (CanonicalType() != Type::null()) {
3256 return 1;
3257 }
3258 const Object& types = Object::Handle(canonical_types());
3259 if (types.IsNull()) {
3260 return 0;
3261 }
3262 intptr_t num_types = Array::Cast(types).Length();
3263 while ((num_types > 0) &&
3264 (Array::Cast(types).At(num_types - 1) == Type::null())) {
3265 num_types--;
3266 }
3267 return num_types;
3268 }
3269
3270
3271 intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
3272 Isolate* isolate = Isolate::Current();
3273 if (EnsureIsFinalized(isolate) != Error::null()) {
3274 return -1;
3275 }
3276 if (needle.raw() == CanonicalType()) {
3277 return 0;
3278 }
3279 REUSABLE_OBJECT_HANDLESCOPE(isolate);
3280 Object& types = isolate->ObjectHandle();
3281 types = canonical_types();
3282 if (types.IsNull()) {
3283 return -1;
3284 }
3285 const intptr_t len = Array::Cast(types).Length();
3286 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(isolate);
3287 AbstractType& type = isolate->AbstractTypeHandle();
3288 for (intptr_t i = 0; i < len; i++) {
3289 type ^= Array::Cast(types).At(i);
3290 if (needle.raw() == type.raw()) {
3291 return i;
3292 }
3293 }
3294 // No type found.
3295 return -1;
3296 }
3297
3298
3299 RawType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
3300 Type& type = Type::Handle();
3301 if (idx == 0) {
3302 type = CanonicalType();
3303 if (!type.IsNull()) {
3304 return type.raw();
3305 }
3306 }
3307 Object& types = Object::Handle(canonical_types());
3308 if (types.IsNull()) {
3309 return Type::null();
3310 }
3311 if ((idx < 0) || (idx >= Array::Cast(types).Length())) {
3312 return Type::null();
3313 }
3314 type ^= Array::Cast(types).At(idx);
3315 ASSERT(!type.IsNull());
3316 return type.raw();
3317 }
3318
3319
3254 void Class::set_allocation_stub(const Code& value) const { 3320 void Class::set_allocation_stub(const Code& value) const {
3255 ASSERT(!value.IsNull()); 3321 ASSERT(!value.IsNull());
3256 ASSERT(raw_ptr()->allocation_stub_ == Code::null()); 3322 ASSERT(raw_ptr()->allocation_stub_ == Code::null());
3257 StorePointer(&raw_ptr()->allocation_stub_, value.raw()); 3323 StorePointer(&raw_ptr()->allocation_stub_, value.raw());
3258 } 3324 }
3259 3325
3260 3326
3261 bool Class::IsFunctionClass() const { 3327 bool Class::IsFunctionClass() const {
3262 return raw() == Type::Handle(Type::Function()).type_class(); 3328 return raw() == Type::Handle(Type::Function()).type_class();
3263 } 3329 }
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 Isolate* isolate = Isolate::Current(); 3672 Isolate* isolate = Isolate::Current();
3607 if (EnsureIsFinalized(isolate) != Error::null()) { 3673 if (EnsureIsFinalized(isolate) != Error::null()) {
3608 return Function::null(); 3674 return Function::null();
3609 } 3675 }
3610 REUSABLE_ARRAY_HANDLESCOPE(isolate); 3676 REUSABLE_ARRAY_HANDLESCOPE(isolate);
3611 REUSABLE_FUNCTION_HANDLESCOPE(isolate); 3677 REUSABLE_FUNCTION_HANDLESCOPE(isolate);
3612 REUSABLE_STRING_HANDLESCOPE(isolate); 3678 REUSABLE_STRING_HANDLESCOPE(isolate);
3613 Array& funcs = isolate->ArrayHandle(); 3679 Array& funcs = isolate->ArrayHandle();
3614 funcs ^= functions(); 3680 funcs ^= functions();
3615 ASSERT(!funcs.IsNull()); 3681 ASSERT(!funcs.IsNull());
3616 intptr_t len = funcs.Length(); 3682 const intptr_t len = funcs.Length();
3617 Function& function = isolate->FunctionHandle(); 3683 Function& function = isolate->FunctionHandle();
3618 String& function_name = isolate->StringHandle(); 3684 String& function_name = isolate->StringHandle();
3619 for (intptr_t i = 0; i < len; i++) { 3685 for (intptr_t i = 0; i < len; i++) {
3620 function ^= funcs.At(i); 3686 function ^= funcs.At(i);
3621 function_name ^= function.name(); 3687 function_name ^= function.name();
3622 if (String::EqualsIgnoringPrivateKey(function_name, name)) { 3688 if (String::EqualsIgnoringPrivateKey(function_name, name)) {
3623 return CheckFunctionType(function, type); 3689 return CheckFunctionType(function, type);
3624 } 3690 }
3625 } 3691 }
3626 // No function found. 3692 // No function found.
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
3949 static intptr_t FinalizeHash(uword hash) { 4015 static intptr_t FinalizeHash(uword hash) {
3950 hash += hash << 3; 4016 hash += hash << 3;
3951 hash ^= hash >> 11; 4017 hash ^= hash >> 11;
3952 hash += hash << 15; 4018 hash += hash << 15;
3953 return hash; 4019 return hash;
3954 } 4020 }
3955 4021
3956 4022
3957 intptr_t TypeArguments::Hash() const { 4023 intptr_t TypeArguments::Hash() const {
3958 if (IsNull()) return 0; 4024 if (IsNull()) return 0;
3959 uword result = 0;
3960 const intptr_t num_types = Length(); 4025 const intptr_t num_types = Length();
4026 if (IsRaw(0, num_types)) return 0;
4027 intptr_t result = 0;
3961 AbstractType& type = AbstractType::Handle(); 4028 AbstractType& type = AbstractType::Handle();
3962 for (intptr_t i = 0; i < num_types; i++) { 4029 for (intptr_t i = 0; i < num_types; i++) {
3963 type = TypeAt(i); 4030 type = TypeAt(i);
3964 result += type.Hash(); 4031 result += type.Hash();
3965 result += result << 10; 4032 result += result << 10;
3966 result ^= result >> 6; 4033 result ^= result >> 6;
3967 } 4034 }
3968 return FinalizeHash(result); 4035 return FinalizeHash(result);
3969 } 4036 }
3970 4037
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
4066 } 4133 }
4067 return true; 4134 return true;
4068 } 4135 }
4069 4136
4070 4137
4071 void TypeArguments::PrintToJSONStream(JSONStream* stream, bool ref) const { 4138 void TypeArguments::PrintToJSONStream(JSONStream* stream, bool ref) const {
4072 JSONObject jsobj(stream); 4139 JSONObject jsobj(stream);
4073 } 4140 }
4074 4141
4075 4142
4143 bool TypeArguments::HasInstantiations() const {
4144 const Array& prior_instantiations = Array::Handle(instantiations());
4145 ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
4146 return prior_instantiations.Length() > 1;
4147 }
4148
4149
4150 intptr_t TypeArguments::NumInstantiations() const {
4151 const Array& prior_instantiations = Array::Handle(instantiations());
4152 ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
4153 intptr_t i = 0;
4154 while (prior_instantiations.At(i) != Smi::New(StubCode::kNoInstantiator)) {
4155 i += 2;
4156 }
4157 return i/2;
4158 }
4159
4160
4076 RawArray* TypeArguments::instantiations() const { 4161 RawArray* TypeArguments::instantiations() const {
4077 return raw_ptr()->instantiations_; 4162 return raw_ptr()->instantiations_;
4078 } 4163 }
4079 4164
4165
4080 void TypeArguments::set_instantiations(const Array& value) const { 4166 void TypeArguments::set_instantiations(const Array& value) const {
4081 ASSERT(!value.IsNull()); 4167 ASSERT(!value.IsNull());
4082 StorePointer(&raw_ptr()->instantiations_, value.raw()); 4168 StorePointer(&raw_ptr()->instantiations_, value.raw());
4083 } 4169 }
4084 4170
4085 4171
4086 intptr_t TypeArguments::Length() const { 4172 intptr_t TypeArguments::Length() const {
4087 ASSERT(!IsNull()); 4173 ASSERT(!IsNull());
4088 return Smi::Value(raw_ptr()->length_); 4174 return Smi::Value(raw_ptr()->length_);
4089 } 4175 }
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
4309 const TypeArguments& instantiator_type_arguments, 4395 const TypeArguments& instantiator_type_arguments,
4310 Error* bound_error) const { 4396 Error* bound_error) const {
4311 ASSERT(!IsInstantiated()); 4397 ASSERT(!IsInstantiated());
4312 ASSERT(instantiator_type_arguments.IsNull() || 4398 ASSERT(instantiator_type_arguments.IsNull() ||
4313 instantiator_type_arguments.IsCanonical()); 4399 instantiator_type_arguments.IsCanonical());
4314 // Lookup instantiator and, if found, return paired instantiated result. 4400 // Lookup instantiator and, if found, return paired instantiated result.
4315 Array& prior_instantiations = Array::Handle(instantiations()); 4401 Array& prior_instantiations = Array::Handle(instantiations());
4316 ASSERT(!prior_instantiations.IsNull() && prior_instantiations.IsArray()); 4402 ASSERT(!prior_instantiations.IsNull() && prior_instantiations.IsArray());
4317 // The instantiations cache is initialized with Object::zero_array() and is 4403 // The instantiations cache is initialized with Object::zero_array() and is
4318 // therefore guaranteed to contain kNoInstantiator. No length check needed. 4404 // therefore guaranteed to contain kNoInstantiator. No length check needed.
4319 ASSERT(prior_instantiations.Length() > 0); 4405 ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
4320 intptr_t index = 0; 4406 intptr_t index = 0;
4321 while (true) { 4407 while (true) {
4322 if (prior_instantiations.At(index) == instantiator_type_arguments.raw()) { 4408 if (prior_instantiations.At(index) == instantiator_type_arguments.raw()) {
4323 return TypeArguments::RawCast(prior_instantiations.At(index + 1)); 4409 return TypeArguments::RawCast(prior_instantiations.At(index + 1));
4324 } 4410 }
4325 if (prior_instantiations.At(index) == Smi::New(StubCode::kNoInstantiator)) { 4411 if (prior_instantiations.At(index) == Smi::New(StubCode::kNoInstantiator)) {
4326 break; 4412 break;
4327 } 4413 }
4328 index += 2; 4414 index += 2;
4329 } 4415 }
4330 // Cache lookup failed. Instantiate the type arguments. 4416 // Cache lookup failed. Instantiate the type arguments.
4331 TypeArguments& result = TypeArguments::Handle(); 4417 TypeArguments& result = TypeArguments::Handle();
4332 result = InstantiateFrom(instantiator_type_arguments, bound_error); 4418 result = InstantiateFrom(instantiator_type_arguments, bound_error);
4333 if ((bound_error != NULL) && !bound_error->IsNull()) { 4419 if ((bound_error != NULL) && !bound_error->IsNull()) {
4334 return result.raw(); 4420 return result.raw();
4335 } 4421 }
4336 // Instantiation did not result in bound error. Canonicalize type arguments. 4422 // Instantiation did not result in bound error. Canonicalize type arguments.
4337 result = result.Canonicalize(); 4423 result = result.Canonicalize();
4424 // InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
4425 // indirectly, so the prior_instantiations array cannot have grown.
4426 ASSERT(prior_instantiations.raw() == instantiations());
4338 // Add instantiator and result to instantiations array. 4427 // Add instantiator and result to instantiations array.
4339 intptr_t length = prior_instantiations.Length(); 4428 intptr_t length = prior_instantiations.Length();
4340 if ((index + 2) >= length) { 4429 if ((index + 2) >= length) {
4341 // Grow the instantiations array. 4430 // Grow the instantiations array.
4342 // The initial array is Object::zero_array() of length 1. 4431 // The initial array is Object::zero_array() of length 1.
4343 length = (length > 64) ? 4432 length = (length > 64) ?
4344 (length + 64) : 4433 (length + 64) :
4345 ((length == 1) ? 3 : ((length - 1) * 2 + 1)); 4434 ((length == 1) ? 3 : ((length - 1) * 2 + 1));
4346 prior_instantiations = 4435 prior_instantiations =
4347 Array::Grow(prior_instantiations, length, Heap::kOld); 4436 Array::Grow(prior_instantiations, length, Heap::kOld);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
4390 void TypeArguments::SetLength(intptr_t value) const { 4479 void TypeArguments::SetLength(intptr_t value) const {
4391 ASSERT(!IsCanonical()); 4480 ASSERT(!IsCanonical());
4392 // This is only safe because we create a new Smi, which does not cause 4481 // This is only safe because we create a new Smi, which does not cause
4393 // heap allocation. 4482 // heap allocation.
4394 raw_ptr()->length_ = Smi::New(value); 4483 raw_ptr()->length_ = Smi::New(value);
4395 } 4484 }
4396 4485
4397 4486
4398 static void GrowCanonicalTypeArguments(Isolate* isolate, const Array& table) { 4487 static void GrowCanonicalTypeArguments(Isolate* isolate, const Array& table) {
4399 // Last element of the array is the number of used elements. 4488 // Last element of the array is the number of used elements.
4400 intptr_t table_size = table.Length() - 1; 4489 const intptr_t table_size = table.Length() - 1;
4401 intptr_t new_table_size = table_size * 2; 4490 const intptr_t new_table_size = table_size * 2;
4402 Array& new_table = Array::Handle(isolate, Array::New(new_table_size + 1)); 4491 Array& new_table = Array::Handle(isolate, Array::New(new_table_size + 1));
4403 // Copy all elements from the original table to the newly allocated 4492 // Copy all elements from the original table to the newly allocated
4404 // array. 4493 // array.
4405 TypeArguments& element = TypeArguments::Handle(isolate); 4494 TypeArguments& element = TypeArguments::Handle(isolate);
4406 Object& new_element = Object::Handle(isolate); 4495 Object& new_element = Object::Handle(isolate);
4407 for (intptr_t i = 0; i < table_size; i++) { 4496 for (intptr_t i = 0; i < table_size; i++) {
4408 element ^= table.At(i); 4497 element ^= table.At(i);
4409 if (!element.IsNull()) { 4498 if (!element.IsNull()) {
4410 intptr_t hash = element.Hash(); 4499 intptr_t hash = element.Hash();
4411 ASSERT(Utils::IsPowerOfTwo(new_table_size)); 4500 ASSERT(Utils::IsPowerOfTwo(new_table_size));
(...skipping 15 matching lines...) Expand all
4427 4516
4428 4517
4429 static void InsertIntoCanonicalTypeArguments(Isolate* isolate, 4518 static void InsertIntoCanonicalTypeArguments(Isolate* isolate,
4430 const Array& table, 4519 const Array& table,
4431 const TypeArguments& arguments, 4520 const TypeArguments& arguments,
4432 intptr_t index) { 4521 intptr_t index) {
4433 arguments.SetCanonical(); // Mark object as being canonical. 4522 arguments.SetCanonical(); // Mark object as being canonical.
4434 table.SetAt(index, arguments); // Remember the new element. 4523 table.SetAt(index, arguments); // Remember the new element.
4435 // Update used count. 4524 // Update used count.
4436 // Last element of the array is the number of used elements. 4525 // Last element of the array is the number of used elements.
4437 intptr_t table_size = table.Length() - 1; 4526 const intptr_t table_size = table.Length() - 1;
4438 intptr_t used_elements = Smi::Value(Smi::RawCast(table.At(table_size))) + 1; 4527 const intptr_t used_elements =
4528 Smi::Value(Smi::RawCast(table.At(table_size))) + 1;
4439 const Smi& used = Smi::Handle(isolate, Smi::New(used_elements)); 4529 const Smi& used = Smi::Handle(isolate, Smi::New(used_elements));
4440 table.SetAt(table_size, used); 4530 table.SetAt(table_size, used);
4441 4531
4442 // Rehash if table is 75% full. 4532 // Rehash if table is 75% full.
4443 if (used_elements > ((table_size / 4) * 3)) { 4533 if (used_elements > ((table_size / 4) * 3)) {
4444 GrowCanonicalTypeArguments(isolate, table); 4534 GrowCanonicalTypeArguments(isolate, table);
4445 } 4535 }
4446 } 4536 }
4447 4537
4448 4538
4449 static intptr_t FindIndexInCanonicalTypeArguments( 4539 static intptr_t FindIndexInCanonicalTypeArguments(
4450 Isolate* isolate, 4540 Isolate* isolate,
4451 const Array& table, 4541 const Array& table,
4452 const TypeArguments& arguments, 4542 const TypeArguments& arguments,
4453 intptr_t hash) { 4543 intptr_t hash) {
4454 // Last element of the array is the number of used elements. 4544 // Last element of the array is the number of used elements.
4455 intptr_t table_size = table.Length() - 1; 4545 const intptr_t table_size = table.Length() - 1;
4456 ASSERT(Utils::IsPowerOfTwo(table_size)); 4546 ASSERT(Utils::IsPowerOfTwo(table_size));
4457 intptr_t index = hash & (table_size - 1); 4547 intptr_t index = hash & (table_size - 1);
4458 4548
4459 TypeArguments& current = TypeArguments::Handle(isolate); 4549 TypeArguments& current = TypeArguments::Handle(isolate);
4460 current ^= table.At(index); 4550 current ^= table.At(index);
4461 while (!current.IsNull() && !current.Equals(arguments)) { 4551 while (!current.IsNull() && !current.Equals(arguments)) {
4462 index = (index + 1) & (table_size - 1); // Move to next element. 4552 index = (index + 1) & (table_size - 1); // Move to next element.
4463 current ^= table.At(index); 4553 current ^= table.At(index);
4464 } 4554 }
4465 return index; // Index of element if found or slot into which to add it. 4555 return index; // Index of element if found or slot into which to add it.
(...skipping 18 matching lines...) Expand all
4484 return clone.raw(); 4574 return clone.raw();
4485 } 4575 }
4486 4576
4487 4577
4488 RawTypeArguments* TypeArguments::Canonicalize( 4578 RawTypeArguments* TypeArguments::Canonicalize(
4489 GrowableObjectArray* trail) const { 4579 GrowableObjectArray* trail) const {
4490 if (IsNull() || IsCanonical()) { 4580 if (IsNull() || IsCanonical()) {
4491 ASSERT(IsOld()); 4581 ASSERT(IsOld());
4492 return this->raw(); 4582 return this->raw();
4493 } 4583 }
4584 const intptr_t num_types = Length();
4585 if (IsRaw(0, num_types)) {
4586 return TypeArguments::null();
4587 }
4494 Isolate* isolate = Isolate::Current(); 4588 Isolate* isolate = Isolate::Current();
4495 ObjectStore* object_store = isolate->object_store(); 4589 ObjectStore* object_store = isolate->object_store();
4496 const Array& table = Array::Handle(isolate, 4590 Array& table = Array::Handle(isolate,
4497 object_store->canonical_type_arguments()); 4591 object_store->canonical_type_arguments());
4498 ASSERT(table.Length() > 0); 4592 // Last element of the array is the number of used elements.
4499 intptr_t index = FindIndexInCanonicalTypeArguments(isolate, 4593 const intptr_t used_elements =
4500 table, 4594 Smi::Value(Smi::RawCast(table.At(table.Length() - 1)));
4501 *this, 4595 const intptr_t hash = Hash();
4502 Hash()); 4596 intptr_t index =
4597 FindIndexInCanonicalTypeArguments(isolate, table, *this, hash);
4503 TypeArguments& result = TypeArguments::Handle(isolate); 4598 TypeArguments& result = TypeArguments::Handle(isolate);
4504 result ^= table.At(index); 4599 result ^= table.At(index);
4505 if (result.IsNull()) { 4600 if (result.IsNull()) {
4506 // Canonicalize each type argument. 4601 // Canonicalize each type argument.
4507 const intptr_t num_types = Length(); 4602 AbstractType& type_arg = AbstractType::Handle(isolate);
4508 AbstractType& type = AbstractType::Handle(isolate);
4509 for (intptr_t i = 0; i < num_types; i++) { 4603 for (intptr_t i = 0; i < num_types; i++) {
4510 type = TypeAt(i); 4604 type_arg = TypeAt(i);
4511 type = type.Canonicalize(trail); 4605 type_arg = type_arg.Canonicalize(trail);
4512 SetTypeAt(i, type); 4606 SetTypeAt(i, type_arg);
4513 } 4607 }
4514 // Make sure we have an old space object and add it to the table. 4608 // Canonicalization of a recursive type may change its hash.
4515 if (this->IsNew()) { 4609 const intptr_t new_hash = Hash();
4516 result ^= Object::Clone(*this, Heap::kOld); 4610 // Canonicalization of the type argument's own type arguments may add an
4517 } else { 4611 // entry to the table, or even grow the table, and thereby change the
4518 result ^= this->raw(); 4612 // previously calculated index.
4613 table = object_store->canonical_type_arguments();
4614 if ((new_hash != hash) ||
4615 (Smi::Value(Smi::RawCast(table.At(table.Length() - 1)))
4616 != used_elements)) {
4617 index =
4618 FindIndexInCanonicalTypeArguments(isolate, table, *this, new_hash);
4619 result ^= table.At(index);
4519 } 4620 }
4520 ASSERT(result.IsOld()); 4621 if (result.IsNull()) {
4521 InsertIntoCanonicalTypeArguments(isolate, table, result, index); 4622 // Make sure we have an old space object and add it to the table.
4623 if (this->IsNew()) {
4624 result ^= Object::Clone(*this, Heap::kOld);
4625 } else {
4626 result ^= this->raw();
4627 }
4628 ASSERT(result.IsOld());
4629 InsertIntoCanonicalTypeArguments(isolate, table, result, index);
4630 }
4522 } 4631 }
4523 ASSERT(result.Equals(*this)); 4632 ASSERT(result.Equals(*this));
4524 ASSERT(!result.IsNull()); 4633 ASSERT(!result.IsNull());
4525 ASSERT(result.IsTypeArguments()); 4634 ASSERT(result.IsTypeArguments());
4526 ASSERT(result.IsCanonical()); 4635 ASSERT(result.IsCanonical());
4527 return result.raw(); 4636 return result.raw();
4528 } 4637 }
4529 4638
4530 4639
4531 const char* TypeArguments::ToCString() const { 4640 const char* TypeArguments::ToCString() const {
(...skipping 3490 matching lines...) Expand 10 before | Expand all | Expand 10 after
8022 // Rehash all elements from the original dictionary 8131 // Rehash all elements from the original dictionary
8023 // to the newly allocated array. 8132 // to the newly allocated array.
8024 Object& entry = Class::Handle(); 8133 Object& entry = Class::Handle();
8025 String& entry_name = String::Handle(); 8134 String& entry_name = String::Handle();
8026 Object& new_entry = Object::Handle(); 8135 Object& new_entry = Object::Handle();
8027 for (intptr_t i = 0; i < dict_size; i++) { 8136 for (intptr_t i = 0; i < dict_size; i++) {
8028 entry = dict.At(i); 8137 entry = dict.At(i);
8029 if (!entry.IsNull()) { 8138 if (!entry.IsNull()) {
8030 entry_name = entry.DictionaryName(); 8139 entry_name = entry.DictionaryName();
8031 ASSERT(!entry_name.IsNull()); 8140 ASSERT(!entry_name.IsNull());
8032 intptr_t hash = entry_name.Hash(); 8141 const intptr_t hash = entry_name.Hash();
8033 intptr_t index = hash % new_dict_size; 8142 intptr_t index = hash % new_dict_size;
8034 new_entry = new_dict.At(index); 8143 new_entry = new_dict.At(index);
8035 while (!new_entry.IsNull()) { 8144 while (!new_entry.IsNull()) {
8036 index = (index + 1) % new_dict_size; // Move to next element. 8145 index = (index + 1) % new_dict_size; // Move to next element.
8037 new_entry = new_dict.At(index); 8146 new_entry = new_dict.At(index);
8038 } 8147 }
8039 new_dict.SetAt(index, entry); 8148 new_dict.SetAt(index, entry);
8040 } 8149 }
8041 } 8150 }
8042 // Copy used count. 8151 // Copy used count.
(...skipping 5085 matching lines...) Expand 10 before | Expand all | Expand 10 after
13128 } 13237 }
13129 ASSERT(this->Equals(type)); 13238 ASSERT(this->Equals(type));
13130 return type.raw(); 13239 return type.raw();
13131 } 13240 }
13132 13241
13133 Array& canonical_types = Array::Handle(isolate); 13242 Array& canonical_types = Array::Handle(isolate);
13134 canonical_types ^= cls.canonical_types(); 13243 canonical_types ^= cls.canonical_types();
13135 if (canonical_types.IsNull()) { 13244 if (canonical_types.IsNull()) {
13136 canonical_types = empty_array().raw(); 13245 canonical_types = empty_array().raw();
13137 } 13246 }
13138 const intptr_t length = canonical_types.Length(); 13247 intptr_t length = canonical_types.Length();
13139 // Linear search to see whether this type is already present in the 13248 // Linear search to see whether this type is already present in the
13140 // list of canonicalized types. 13249 // list of canonicalized types.
13141 // TODO(asiva): Try to re-factor this lookup code to make sharing 13250 // TODO(asiva): Try to re-factor this lookup code to make sharing
13142 // easy between the 4 versions of this loop. 13251 // easy between the 4 versions of this loop.
13143 intptr_t index = 0; 13252 intptr_t index = 0;
13144 while (index < length) { 13253 while (index < length) {
13145 type ^= canonical_types.At(index); 13254 type ^= canonical_types.At(index);
13146 if (type.IsNull()) { 13255 if (type.IsNull()) {
13147 break; 13256 break;
13148 } 13257 }
13149 ASSERT(type.IsFinalized()); 13258 ASSERT(type.IsFinalized());
13150 if (this->Equals(type)) { 13259 if (this->Equals(type)) {
13151 return type.raw(); 13260 return type.raw();
13152 } 13261 }
13153 index++; 13262 index++;
13154 } 13263 }
13264 // The type was not found in the table. It is not canonical yet.
13265
13155 // Canonicalize the type arguments. 13266 // Canonicalize the type arguments.
13156 TypeArguments& type_args = TypeArguments::Handle(isolate, arguments()); 13267 TypeArguments& type_args = TypeArguments::Handle(isolate, arguments());
13157 // In case the type is first canonicalized at runtime, its type argument 13268 // In case the type is first canonicalized at runtime, its type argument
13158 // vector may be longer than necessary. This is not an issue. 13269 // vector may be longer than necessary. This is not an issue.
13159 ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments())); 13270 ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
13160 type_args = type_args.Canonicalize(trail); 13271 type_args = type_args.Canonicalize(trail);
13161 set_arguments(type_args); 13272 set_arguments(type_args);
13273
13274 // Canonicalizing the type arguments may have changed the index, may have
13275 // grown the table, or may even have canonicalized this type.
13276 canonical_types ^= cls.canonical_types();
13277 if (canonical_types.IsNull()) {
13278 canonical_types = empty_array().raw();
13279 }
13280 length = canonical_types.Length();
13281 while (index < length) {
13282 type ^= canonical_types.At(index);
13283 if (type.IsNull()) {
13284 break;
13285 }
13286 ASSERT(type.IsFinalized());
13287 if (this->Equals(type)) {
13288 return type.raw();
13289 }
13290 index++;
13291 }
13292
13162 // The type needs to be added to the list. Grow the list if it is full. 13293 // The type needs to be added to the list. Grow the list if it is full.
13163 if (index == length) { 13294 if (index == length) {
13164 const intptr_t new_length = (length > 64) ? 13295 const intptr_t new_length = (length > 64) ?
13165 (length + 64) : 13296 (length + 64) :
13166 ((length == 0) ? 1 : (length * 2)); 13297 ((length == 0) ? 1 : (length * 2));
13167 const Array& new_canonical_types = Array::Handle( 13298 const Array& new_canonical_types = Array::Handle(
13168 isolate, Array::Grow(canonical_types, new_length, Heap::kOld)); 13299 isolate, Array::Grow(canonical_types, new_length, Heap::kOld));
13169 cls.set_canonical_types(new_canonical_types); 13300 cls.set_canonical_types(new_canonical_types);
13170 new_canonical_types.SetAt(index, *this); 13301 new_canonical_types.SetAt(index, *this);
13171 } else { 13302 } else {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
13263 const TypeArguments& type_arguments = TypeArguments::Handle(arguments()); 13394 const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
13264 const char* class_name; 13395 const char* class_name;
13265 if (HasResolvedTypeClass()) { 13396 if (HasResolvedTypeClass()) {
13266 class_name = String::Handle( 13397 class_name = String::Handle(
13267 Class::Handle(type_class()).Name()).ToCString(); 13398 Class::Handle(type_class()).Name()).ToCString();
13268 } else { 13399 } else {
13269 class_name = UnresolvedClass::Handle(unresolved_class()).ToCString(); 13400 class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
13270 } 13401 }
13271 if (type_arguments.IsNull()) { 13402 if (type_arguments.IsNull()) {
13272 const char* format = "Type: class '%s'"; 13403 const char* format = "Type: class '%s'";
13273 intptr_t len = OS::SNPrint(NULL, 0, format, class_name) + 1; 13404 const intptr_t len = OS::SNPrint(NULL, 0, format, class_name) + 1;
13274 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 13405 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
13275 OS::SNPrint(chars, len, format, class_name); 13406 OS::SNPrint(chars, len, format, class_name);
13276 return chars; 13407 return chars;
13277 } else { 13408 } else {
13278 const char* format = "Type: class '%s', args:[%s]"; 13409 const char* format = "Type: class '%s', args:[%s]";
13279 const char* args_cstr = TypeArguments::Handle(arguments()).ToCString(); 13410 const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
13280 intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1; 13411 intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1;
13281 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 13412 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
13282 OS::SNPrint(chars, len, format, class_name, args_cstr); 13413 OS::SNPrint(chars, len, format, class_name, args_cstr);
13283 return chars; 13414 return chars;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
13409 if (trail->At(i) == this->raw()) { 13540 if (trail->At(i) == this->raw()) {
13410 ASSERT(trail->At(i + 1) != Object::null()); 13541 ASSERT(trail->At(i + 1) != Object::null());
13411 return trail->At(i + 1); 13542 return trail->At(i + 1);
13412 } 13543 }
13413 } 13544 }
13414 return Object::null(); 13545 return Object::null();
13415 } 13546 }
13416 13547
13417 13548
13418 void TypeRef::AddOnlyBuddyToTrail(GrowableObjectArray** trail, 13549 void TypeRef::AddOnlyBuddyToTrail(GrowableObjectArray** trail,
13419 const Object& buddy) const { 13550 const Object& buddy) const {
13420 if (*trail == NULL) { 13551 if (*trail == NULL) {
13421 *trail = &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New()); 13552 *trail = &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New());
13422 } else { 13553 } else {
13423 ASSERT(OnlyBuddyInTrail(*trail) == Object::null()); 13554 ASSERT(OnlyBuddyInTrail(*trail) == Object::null());
13424 } 13555 }
13425 (*trail)->Add(*this); 13556 (*trail)->Add(*this);
13426 (*trail)->Add(buddy); 13557 (*trail)->Add(buddy);
13427 } 13558 }
13428 13559
13429 13560
(...skipping 4278 matching lines...) Expand 10 before | Expand all | Expand 10 after
17708 return "_MirrorReference"; 17839 return "_MirrorReference";
17709 } 17840 }
17710 17841
17711 17842
17712 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 17843 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
17713 Instance::PrintToJSONStream(stream, ref); 17844 Instance::PrintToJSONStream(stream, ref);
17714 } 17845 }
17715 17846
17716 17847
17717 } // namespace dart 17848 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/reusable_handles.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698