OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |