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