Chromium Code Reviews| 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 |