| 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 24 matching lines...) Expand all Loading... |
| 35 #include "vm/resolver.h" | 35 #include "vm/resolver.h" |
| 36 #include "vm/reusable_handles.h" | 36 #include "vm/reusable_handles.h" |
| 37 #include "vm/runtime_entry.h" | 37 #include "vm/runtime_entry.h" |
| 38 #include "vm/scopes.h" | 38 #include "vm/scopes.h" |
| 39 #include "vm/stack_frame.h" | 39 #include "vm/stack_frame.h" |
| 40 #include "vm/symbols.h" | 40 #include "vm/symbols.h" |
| 41 #include "vm/tags.h" | 41 #include "vm/tags.h" |
| 42 #include "vm/thread_registry.h" | 42 #include "vm/thread_registry.h" |
| 43 #include "vm/timeline.h" | 43 #include "vm/timeline.h" |
| 44 #include "vm/timer.h" | 44 #include "vm/timer.h" |
| 45 #include "vm/type_table.h" |
| 45 #include "vm/unicode.h" | 46 #include "vm/unicode.h" |
| 46 #include "vm/verified_memory.h" | 47 #include "vm/verified_memory.h" |
| 47 #include "vm/weak_code.h" | 48 #include "vm/weak_code.h" |
| 48 | 49 |
| 49 namespace dart { | 50 namespace dart { |
| 50 | 51 |
| 51 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, | 52 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
| 52 "Huge method cutoff in unoptimized code size (in bytes)."); | 53 "Huge method cutoff in unoptimized code size (in bytes)."); |
| 53 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, | 54 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, |
| 54 "Huge method cutoff in tokens: Disables optimizations for huge methods."); | 55 "Huge method cutoff in tokens: Disables optimizations for huge methods."); |
| (...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 cls.set_num_type_arguments(1); | 1140 cls.set_num_type_arguments(1); |
| 1140 | 1141 |
| 1141 // Set up the growable object array class (Has to be done after the array | 1142 // Set up the growable object array class (Has to be done after the array |
| 1142 // class is setup as one of its field is an array object). | 1143 // class is setup as one of its field is an array object). |
| 1143 cls = Class::New<GrowableObjectArray>(); | 1144 cls = Class::New<GrowableObjectArray>(); |
| 1144 object_store->set_growable_object_array_class(cls); | 1145 object_store->set_growable_object_array_class(cls); |
| 1145 cls.set_type_arguments_field_offset( | 1146 cls.set_type_arguments_field_offset( |
| 1146 GrowableObjectArray::type_arguments_offset()); | 1147 GrowableObjectArray::type_arguments_offset()); |
| 1147 cls.set_num_type_arguments(1); | 1148 cls.set_num_type_arguments(1); |
| 1148 | 1149 |
| 1149 // canonical_type_arguments_ are Smi terminated. | 1150 // Initialize hash set for canonical_type_. |
| 1150 // Last element contains the count of used slots. | 1151 const intptr_t kInitialCanonicalTypeSize = 16; |
| 1152 array = HashTables::New<CanonicalTypeSet>( |
| 1153 kInitialCanonicalTypeSize, Heap::kOld); |
| 1154 object_store->set_canonical_types(array); |
| 1155 |
| 1156 // Initialize hash set for canonical_type_arguments_. |
| 1151 const intptr_t kInitialCanonicalTypeArgumentsSize = 4; | 1157 const intptr_t kInitialCanonicalTypeArgumentsSize = 4; |
| 1152 array = Array::New(kInitialCanonicalTypeArgumentsSize + 1); | 1158 array = HashTables::New<CanonicalTypeArgumentsSet>( |
| 1153 array.SetAt(kInitialCanonicalTypeArgumentsSize, | 1159 kInitialCanonicalTypeArgumentsSize, Heap::kOld); |
| 1154 Smi::Handle(zone, Smi::New(0))); | |
| 1155 object_store->set_canonical_type_arguments(array); | 1160 object_store->set_canonical_type_arguments(array); |
| 1156 | 1161 |
| 1157 // Setup type class early in the process. | 1162 // Setup type class early in the process. |
| 1158 const Class& type_cls = Class::Handle(zone, Class::New<Type>()); | 1163 const Class& type_cls = Class::Handle(zone, Class::New<Type>()); |
| 1159 const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>()); | 1164 const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>()); |
| 1160 const Class& type_parameter_cls = Class::Handle(zone, | 1165 const Class& type_parameter_cls = Class::Handle(zone, |
| 1161 Class::New<TypeParameter>()); | 1166 Class::New<TypeParameter>()); |
| 1162 const Class& bounded_type_cls = Class::Handle(zone, | 1167 const Class& bounded_type_cls = Class::Handle(zone, |
| 1163 Class::New<BoundedType>()); | 1168 Class::New<BoundedType>()); |
| 1164 const Class& mixin_app_type_cls = Class::Handle(zone, | 1169 const Class& mixin_app_type_cls = Class::Handle(zone, |
| (...skipping 2460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3625 RawArray* Class::constants() const { | 3630 RawArray* Class::constants() const { |
| 3626 return raw_ptr()->constants_; | 3631 return raw_ptr()->constants_; |
| 3627 } | 3632 } |
| 3628 | 3633 |
| 3629 void Class::set_constants(const Array& value) const { | 3634 void Class::set_constants(const Array& value) const { |
| 3630 ASSERT(!value.IsNull()); | 3635 ASSERT(!value.IsNull()); |
| 3631 StorePointer(&raw_ptr()->constants_, value.raw()); | 3636 StorePointer(&raw_ptr()->constants_, value.raw()); |
| 3632 } | 3637 } |
| 3633 | 3638 |
| 3634 | 3639 |
| 3635 RawObject* Class::canonical_types() const { | 3640 RawType* Class::canonical_type() const { |
| 3636 return raw_ptr()->canonical_types_; | 3641 return raw_ptr()->canonical_type_; |
| 3637 } | 3642 } |
| 3638 | 3643 |
| 3639 | 3644 |
| 3640 void Class::set_canonical_types(const Object& value) const { | 3645 void Class::set_canonical_type(const Type& value) const { |
| 3641 ASSERT(!value.IsNull()); | 3646 ASSERT(!value.IsNull()); |
| 3642 StorePointer(&raw_ptr()->canonical_types_, value.raw()); | 3647 StorePointer(&raw_ptr()->canonical_type_, value.raw()); |
| 3643 } | 3648 } |
| 3644 | 3649 |
| 3645 | 3650 |
| 3646 RawType* Class::CanonicalType() const { | 3651 RawType* Class::CanonicalType() const { |
| 3647 if (!IsGeneric() && !IsClosureClass()) { | 3652 return raw_ptr()->canonical_type_; |
| 3648 return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_); | |
| 3649 } | |
| 3650 Array& types = Array::Handle(); | |
| 3651 types ^= canonical_types(); | |
| 3652 if (!types.IsNull() && (types.Length() > 0)) { | |
| 3653 return reinterpret_cast<RawType*>(types.At(0)); | |
| 3654 } | |
| 3655 return reinterpret_cast<RawType*>(Object::null()); | |
| 3656 } | 3653 } |
| 3657 | 3654 |
| 3658 | 3655 |
| 3659 void Class::SetCanonicalType(const Type& type) const { | 3656 void Class::SetCanonicalType(const Type& type) const { |
| 3660 ASSERT(type.IsCanonical()); | 3657 ASSERT((canonical_type() == Object::null()) || |
| 3661 if (!IsGeneric() && !IsClosureClass()) { | 3658 (canonical_type() == type.raw())); // Set during own finalization. |
| 3662 ASSERT((canonical_types() == Object::null()) || | 3659 set_canonical_type(type); |
| 3663 (canonical_types() == type.raw())); // Set during own finalization. | |
| 3664 set_canonical_types(type); | |
| 3665 } else { | |
| 3666 Array& types = Array::Handle(); | |
| 3667 types ^= canonical_types(); | |
| 3668 ASSERT(!types.IsNull() && (types.Length() > 1)); | |
| 3669 ASSERT((types.At(0) == Object::null()) || (types.At(0) == type.raw())); | |
| 3670 types.SetAt(0, type); | |
| 3671 // Makes sure that 'canonical_types' has not changed. | |
| 3672 ASSERT(types.raw() == canonical_types()); | |
| 3673 } | |
| 3674 } | 3660 } |
| 3675 | 3661 |
| 3676 | 3662 |
| 3677 intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const { | |
| 3678 Thread* thread = Thread::Current(); | |
| 3679 if (EnsureIsFinalized(thread) != Error::null()) { | |
| 3680 return -1; | |
| 3681 } | |
| 3682 if (needle.raw() == CanonicalType()) { | |
| 3683 // For a generic type or signature type, there exists another index with the | |
| 3684 // same type. It will never be returned by this function. | |
| 3685 return 0; | |
| 3686 } | |
| 3687 REUSABLE_OBJECT_HANDLESCOPE(thread); | |
| 3688 Object& types = thread->ObjectHandle(); | |
| 3689 types = canonical_types(); | |
| 3690 if (types.IsNull()) { | |
| 3691 return -1; | |
| 3692 } | |
| 3693 const intptr_t len = Array::Cast(types).Length(); | |
| 3694 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread); | |
| 3695 AbstractType& type = thread->AbstractTypeHandle(); | |
| 3696 for (intptr_t i = 0; i < len; i++) { | |
| 3697 type ^= Array::Cast(types).At(i); | |
| 3698 if (needle.raw() == type.raw()) { | |
| 3699 return i; | |
| 3700 } | |
| 3701 } | |
| 3702 // No type found. | |
| 3703 return -1; | |
| 3704 } | |
| 3705 | |
| 3706 | |
| 3707 RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const { | |
| 3708 AbstractType& type = AbstractType::Handle(); | |
| 3709 if (idx == 0) { | |
| 3710 type = CanonicalType(); | |
| 3711 if (!type.IsNull()) { | |
| 3712 return type.raw(); | |
| 3713 } | |
| 3714 } | |
| 3715 Object& types = Object::Handle(canonical_types()); | |
| 3716 if (types.IsNull() || !types.IsArray()) { | |
| 3717 return Type::null(); | |
| 3718 } | |
| 3719 if ((idx < 0) || (idx >= Array::Cast(types).Length())) { | |
| 3720 return Type::null(); | |
| 3721 } | |
| 3722 type ^= Array::Cast(types).At(idx); | |
| 3723 ASSERT(!type.IsNull()); | |
| 3724 return type.raw(); | |
| 3725 } | |
| 3726 | |
| 3727 | |
| 3728 void Class::set_allocation_stub(const Code& value) const { | 3663 void Class::set_allocation_stub(const Code& value) const { |
| 3729 // Never clear the stub as it may still be a target, but will be GC-d if | 3664 // Never clear the stub as it may still be a target, but will be GC-d if |
| 3730 // not referenced. | 3665 // not referenced. |
| 3731 ASSERT(!value.IsNull()); | 3666 ASSERT(!value.IsNull()); |
| 3732 ASSERT(raw_ptr()->allocation_stub_ == Code::null()); | 3667 ASSERT(raw_ptr()->allocation_stub_ == Code::null()); |
| 3733 StorePointer(&raw_ptr()->allocation_stub_, value.raw()); | 3668 StorePointer(&raw_ptr()->allocation_stub_, value.raw()); |
| 3734 } | 3669 } |
| 3735 | 3670 |
| 3736 | 3671 |
| 3737 void Class::DisableAllocationStub() const { | 3672 void Class::DisableAllocationStub() const { |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4286 Zone* zone = Thread::Current()->zone(); | 4221 Zone* zone = Thread::Current()->zone(); |
| 4287 const Library& lib = Library::Handle(zone, library()); | 4222 const Library& lib = Library::Handle(zone, library()); |
| 4288 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); | 4223 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); |
| 4289 if (!obj.IsNull() && obj.IsLibraryPrefix()) { | 4224 if (!obj.IsNull() && obj.IsLibraryPrefix()) { |
| 4290 return LibraryPrefix::Cast(obj).raw(); | 4225 return LibraryPrefix::Cast(obj).raw(); |
| 4291 } | 4226 } |
| 4292 return LibraryPrefix::null(); | 4227 return LibraryPrefix::null(); |
| 4293 } | 4228 } |
| 4294 | 4229 |
| 4295 | 4230 |
| 4296 // Returns AbstractType::null() if type not found. Modifies index to the last | |
| 4297 // position looked up. | |
| 4298 RawAbstractType* Class::LookupCanonicalType( | |
| 4299 Zone* zone, const AbstractType& lookup_type, intptr_t* index) const { | |
| 4300 Array& canonical_types = Array::Handle(zone); | |
| 4301 canonical_types ^= this->canonical_types(); | |
| 4302 if (canonical_types.IsNull()) { | |
| 4303 return AbstractType::null(); | |
| 4304 } | |
| 4305 AbstractType& type = Type::Handle(zone); | |
| 4306 const intptr_t length = canonical_types.Length(); | |
| 4307 while (*index < length) { | |
| 4308 type ^= canonical_types.At(*index); | |
| 4309 if (type.IsNull()) { | |
| 4310 break; | |
| 4311 } | |
| 4312 ASSERT(type.IsFinalized()); | |
| 4313 if (lookup_type.Equals(type)) { | |
| 4314 ASSERT(type.IsCanonical()); | |
| 4315 return type.raw(); | |
| 4316 } | |
| 4317 *index = *index + 1; | |
| 4318 } | |
| 4319 return AbstractType::null(); | |
| 4320 } | |
| 4321 | |
| 4322 | |
| 4323 // Canonicalizing the type arguments may have changed the index, may have | |
| 4324 // grown the table, or may even have canonicalized this type. Therefore | |
| 4325 // conrtinue search for canonical type at the last index visited. | |
| 4326 RawAbstractType* Class::LookupOrAddCanonicalType( | |
| 4327 const AbstractType& lookup_type, intptr_t start_index) const { | |
| 4328 Thread* thread = Thread::Current(); | |
| 4329 Zone* zone = thread->zone(); | |
| 4330 Isolate* isolate = thread->isolate(); | |
| 4331 AbstractType& type = Type::Handle(zone); | |
| 4332 intptr_t index = start_index; | |
| 4333 type ^= LookupCanonicalType(zone, lookup_type, &index); | |
| 4334 | |
| 4335 if (!type.IsNull()) { | |
| 4336 return type.raw(); | |
| 4337 } | |
| 4338 { | |
| 4339 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); | |
| 4340 // Lookup again, in case the canonicalization array changed. | |
| 4341 Array& canonical_types = Array::Handle(zone); | |
| 4342 canonical_types ^= this->canonical_types(); | |
| 4343 if (canonical_types.IsNull()) { | |
| 4344 canonical_types = empty_array().raw(); | |
| 4345 } | |
| 4346 const intptr_t length = canonical_types.Length(); | |
| 4347 // Start looking after previously looked up last position ('length'). | |
| 4348 type ^= LookupCanonicalType(zone, lookup_type, &index); | |
| 4349 if (!type.IsNull()) { | |
| 4350 return type.raw(); | |
| 4351 } | |
| 4352 | |
| 4353 // 'lookup_type' is not canonicalized yet. | |
| 4354 lookup_type.SetCanonical(); | |
| 4355 | |
| 4356 // The type needs to be added to the list. Grow the list if it is full. | |
| 4357 if (index >= length) { | |
| 4358 ASSERT((index == length) || ((index == 1) && (length == 0))); | |
| 4359 const intptr_t new_length = (length > 64) ? | |
| 4360 (length + 64) : | |
| 4361 ((length == 0) ? 2 : (length * 2)); | |
| 4362 const Array& new_canonical_types = Array::Handle( | |
| 4363 zone, Array::Grow(canonical_types, new_length, Heap::kOld)); | |
| 4364 new_canonical_types.SetAt(index, lookup_type); | |
| 4365 this->set_canonical_types(new_canonical_types); | |
| 4366 } else { | |
| 4367 canonical_types.SetAt(index, lookup_type); | |
| 4368 } | |
| 4369 } | |
| 4370 return lookup_type.raw(); | |
| 4371 } | |
| 4372 | |
| 4373 | |
| 4374 const char* Class::ToCString() const { | 4231 const char* Class::ToCString() const { |
| 4375 const Library& lib = Library::Handle(library()); | 4232 const Library& lib = Library::Handle(library()); |
| 4376 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); | 4233 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); |
| 4377 const char* patch_prefix = is_patch() ? "Patch " : ""; | 4234 const char* patch_prefix = is_patch() ? "Patch " : ""; |
| 4378 const char* class_name = String::Handle(Name()).ToCString(); | 4235 const char* class_name = String::Handle(Name()).ToCString(); |
| 4379 return OS::SCreate(Thread::Current()->zone(), | 4236 return OS::SCreate(Thread::Current()->zone(), |
| 4380 "%s %sClass: %s", library_name, patch_prefix, class_name); | 4237 "%s %sClass: %s", library_name, patch_prefix, class_name); |
| 4381 } | 4238 } |
| 4382 | 4239 |
| 4383 | 4240 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4641 | 4498 |
| 4642 | 4499 |
| 4643 static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) { | 4500 static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) { |
| 4644 hash += other_hash; | 4501 hash += other_hash; |
| 4645 hash += hash << 10; | 4502 hash += hash << 10; |
| 4646 hash ^= hash >> 6; // Logical shift, unsigned hash. | 4503 hash ^= hash >> 6; // Logical shift, unsigned hash. |
| 4647 return hash; | 4504 return hash; |
| 4648 } | 4505 } |
| 4649 | 4506 |
| 4650 | 4507 |
| 4651 static uint32_t FinalizeHash(uint32_t hash) { | 4508 static uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits) { |
| 4652 hash += hash << 3; | 4509 hash += hash << 3; |
| 4653 hash ^= hash >> 11; // Logical shift, unsigned hash. | 4510 hash ^= hash >> 11; // Logical shift, unsigned hash. |
| 4654 hash += hash << 15; | 4511 hash += hash << 15; |
| 4655 return hash; | 4512 hash &= ((static_cast<intptr_t>(1) << hashbits) - 1); |
| 4513 return (hash == 0) ? 1 : hash; |
| 4656 } | 4514 } |
| 4657 | 4515 |
| 4658 | 4516 |
| 4659 intptr_t TypeArguments::Hash() const { | 4517 intptr_t TypeArguments::ComputeHash() const { |
| 4660 if (IsNull()) return 0; | 4518 if (IsNull()) return 0; |
| 4661 const intptr_t num_types = Length(); | 4519 const intptr_t num_types = Length(); |
| 4662 if (IsRaw(0, num_types)) return 0; | 4520 if (IsRaw(0, num_types)) return 0; |
| 4663 uint32_t result = 0; | 4521 uint32_t result = 0; |
| 4664 AbstractType& type = AbstractType::Handle(); | 4522 AbstractType& type = AbstractType::Handle(); |
| 4665 for (intptr_t i = 0; i < num_types; i++) { | 4523 for (intptr_t i = 0; i < num_types; i++) { |
| 4666 type = TypeAt(i); | 4524 type = TypeAt(i); |
| 4667 // The hash may be calculated during type finalization (for debugging | 4525 // The hash may be calculated during type finalization (for debugging |
| 4668 // purposes only) while a type argument is still temporarily null. | 4526 // purposes only) while a type argument is still temporarily null. |
| 4669 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); | 4527 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); |
| 4670 } | 4528 } |
| 4671 return FinalizeHash(result); | 4529 result = FinalizeHash(result, kHashBits); |
| 4530 SetHash(result); |
| 4531 return result; |
| 4672 } | 4532 } |
| 4673 | 4533 |
| 4674 | 4534 |
| 4675 RawString* TypeArguments::SubvectorName(intptr_t from_index, | 4535 RawString* TypeArguments::SubvectorName(intptr_t from_index, |
| 4676 intptr_t len, | 4536 intptr_t len, |
| 4677 NameVisibility name_visibility) const { | 4537 NameVisibility name_visibility) const { |
| 4678 Thread* thread = Thread::Current(); | 4538 Thread* thread = Thread::Current(); |
| 4679 Zone* zone = thread->zone(); | 4539 Zone* zone = thread->zone(); |
| 4680 ASSERT(from_index + len <= Length()); | 4540 ASSERT(from_index + len <= Length()); |
| 4681 String& name = String::Handle(zone); | 4541 String& name = String::Handle(zone); |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5112 } | 4972 } |
| 5113 TypeArguments& result = TypeArguments::Handle(); | 4973 TypeArguments& result = TypeArguments::Handle(); |
| 5114 { | 4974 { |
| 5115 RawObject* raw = Object::Allocate(TypeArguments::kClassId, | 4975 RawObject* raw = Object::Allocate(TypeArguments::kClassId, |
| 5116 TypeArguments::InstanceSize(len), | 4976 TypeArguments::InstanceSize(len), |
| 5117 space); | 4977 space); |
| 5118 NoSafepointScope no_safepoint; | 4978 NoSafepointScope no_safepoint; |
| 5119 result ^= raw; | 4979 result ^= raw; |
| 5120 // Length must be set before we start storing into the array. | 4980 // Length must be set before we start storing into the array. |
| 5121 result.SetLength(len); | 4981 result.SetLength(len); |
| 4982 result.SetHash(0); |
| 5122 } | 4983 } |
| 5123 // The zero array should have been initialized. | 4984 // The zero array should have been initialized. |
| 5124 ASSERT(Object::zero_array().raw() != Array::null()); | 4985 ASSERT(Object::zero_array().raw() != Array::null()); |
| 5125 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); | 4986 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); |
| 5126 result.set_instantiations(Object::zero_array()); | 4987 result.set_instantiations(Object::zero_array()); |
| 5127 return result.raw(); | 4988 return result.raw(); |
| 5128 } | 4989 } |
| 5129 | 4990 |
| 5130 | 4991 |
| 5131 | 4992 |
| 5132 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { | 4993 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { |
| 5133 // TODO(iposva): Determine if we should throw an exception here. | 4994 // TODO(iposva): Determine if we should throw an exception here. |
| 5134 ASSERT((index >= 0) && (index < Length())); | 4995 ASSERT((index >= 0) && (index < Length())); |
| 5135 return &raw_ptr()->types()[index]; | 4996 return &raw_ptr()->types()[index]; |
| 5136 } | 4997 } |
| 5137 | 4998 |
| 5138 | 4999 |
| 5139 void TypeArguments::SetLength(intptr_t value) const { | 5000 void TypeArguments::SetLength(intptr_t value) const { |
| 5140 ASSERT(!IsCanonical()); | 5001 ASSERT(!IsCanonical()); |
| 5141 // This is only safe because we create a new Smi, which does not cause | 5002 // This is only safe because we create a new Smi, which does not cause |
| 5142 // heap allocation. | 5003 // heap allocation. |
| 5143 StoreSmi(&raw_ptr()->length_, Smi::New(value)); | 5004 StoreSmi(&raw_ptr()->length_, Smi::New(value)); |
| 5144 } | 5005 } |
| 5145 | 5006 |
| 5146 | 5007 |
| 5147 static void GrowCanonicalTypeArguments(Thread* thread, const Array& table) { | |
| 5148 Isolate* isolate = thread->isolate(); | |
| 5149 Zone* zone = thread->zone(); | |
| 5150 // Last element of the array is the number of used elements. | |
| 5151 const intptr_t table_size = table.Length() - 1; | |
| 5152 const intptr_t new_table_size = table_size * 2; | |
| 5153 Array& new_table = Array::Handle(zone, Array::New(new_table_size + 1)); | |
| 5154 // Copy all elements from the original table to the newly allocated | |
| 5155 // array. | |
| 5156 TypeArguments& element = TypeArguments::Handle(zone); | |
| 5157 Object& new_element = Object::Handle(zone); | |
| 5158 for (intptr_t i = 0; i < table_size; i++) { | |
| 5159 element ^= table.At(i); | |
| 5160 if (!element.IsNull()) { | |
| 5161 const intptr_t hash = element.Hash(); | |
| 5162 ASSERT(Utils::IsPowerOfTwo(new_table_size)); | |
| 5163 intptr_t index = hash & (new_table_size - 1); | |
| 5164 new_element = new_table.At(index); | |
| 5165 while (!new_element.IsNull()) { | |
| 5166 index = (index + 1) & (new_table_size - 1); // Move to next element. | |
| 5167 new_element = new_table.At(index); | |
| 5168 } | |
| 5169 new_table.SetAt(index, element); | |
| 5170 } | |
| 5171 } | |
| 5172 // Copy used count. | |
| 5173 new_element = table.At(table_size); | |
| 5174 new_table.SetAt(new_table_size, new_element); | |
| 5175 // Remember the new table now. | |
| 5176 isolate->object_store()->set_canonical_type_arguments(new_table); | |
| 5177 } | |
| 5178 | |
| 5179 | |
| 5180 static void InsertIntoCanonicalTypeArguments(Thread* thread, | |
| 5181 const Array& table, | |
| 5182 const TypeArguments& arguments, | |
| 5183 intptr_t index) { | |
| 5184 Zone* zone = thread->zone(); | |
| 5185 arguments.SetCanonical(); // Mark object as being canonical. | |
| 5186 table.SetAt(index, arguments); // Remember the new element. | |
| 5187 // Update used count. | |
| 5188 // Last element of the array is the number of used elements. | |
| 5189 const intptr_t table_size = table.Length() - 1; | |
| 5190 const intptr_t used_elements = | |
| 5191 Smi::Value(Smi::RawCast(table.At(table_size))) + 1; | |
| 5192 const Smi& used = Smi::Handle(zone, Smi::New(used_elements)); | |
| 5193 table.SetAt(table_size, used); | |
| 5194 | |
| 5195 #ifdef DEBUG | |
| 5196 // Verify that there are no duplicates. | |
| 5197 // Duplicates could appear if hash values are not kept constant across | |
| 5198 // snapshots, e.g. if class ids are not preserved by the snapshots. | |
| 5199 TypeArguments& other_arguments = TypeArguments::Handle(); | |
| 5200 for (intptr_t i = 0; i < table_size; i++) { | |
| 5201 if ((i != index) && (table.At(i) != TypeArguments::null())) { | |
| 5202 other_arguments ^= table.At(i); | |
| 5203 if (arguments.Equals(other_arguments)) { | |
| 5204 // Recursive types may be equal, but have different hashes. | |
| 5205 ASSERT(arguments.IsRecursive()); | |
| 5206 ASSERT(other_arguments.IsRecursive()); | |
| 5207 ASSERT(arguments.Hash() != other_arguments.Hash()); | |
| 5208 } | |
| 5209 } | |
| 5210 } | |
| 5211 #endif | |
| 5212 | |
| 5213 // Rehash if table is 75% full. | |
| 5214 if (used_elements > ((table_size / 4) * 3)) { | |
| 5215 GrowCanonicalTypeArguments(thread, table); | |
| 5216 } | |
| 5217 } | |
| 5218 | |
| 5219 | |
| 5220 static intptr_t FindIndexInCanonicalTypeArguments( | |
| 5221 Zone* zone, | |
| 5222 const Array& table, | |
| 5223 const TypeArguments& arguments, | |
| 5224 intptr_t hash) { | |
| 5225 // Last element of the array is the number of used elements. | |
| 5226 const intptr_t table_size = table.Length() - 1; | |
| 5227 ASSERT(Utils::IsPowerOfTwo(table_size)); | |
| 5228 intptr_t index = hash & (table_size - 1); | |
| 5229 | |
| 5230 TypeArguments& current = TypeArguments::Handle(zone); | |
| 5231 current ^= table.At(index); | |
| 5232 while (!current.IsNull() && !current.Equals(arguments)) { | |
| 5233 index = (index + 1) & (table_size - 1); // Move to next element. | |
| 5234 current ^= table.At(index); | |
| 5235 } | |
| 5236 return index; // Index of element if found or slot into which to add it. | |
| 5237 } | |
| 5238 | |
| 5239 | |
| 5240 RawTypeArguments* TypeArguments::CloneUnfinalized() const { | 5008 RawTypeArguments* TypeArguments::CloneUnfinalized() const { |
| 5241 if (IsNull() || IsFinalized()) { | 5009 if (IsNull() || IsFinalized()) { |
| 5242 return raw(); | 5010 return raw(); |
| 5243 } | 5011 } |
| 5244 ASSERT(IsResolved()); | 5012 ASSERT(IsResolved()); |
| 5245 AbstractType& type = AbstractType::Handle(); | 5013 AbstractType& type = AbstractType::Handle(); |
| 5246 const intptr_t num_types = Length(); | 5014 const intptr_t num_types = Length(); |
| 5247 const TypeArguments& clone = TypeArguments::Handle( | 5015 const TypeArguments& clone = TypeArguments::Handle( |
| 5248 TypeArguments::New(num_types)); | 5016 TypeArguments::New(num_types)); |
| 5249 for (intptr_t i = 0; i < num_types; i++) { | 5017 for (intptr_t i = 0; i < num_types; i++) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5284 return this->raw(); | 5052 return this->raw(); |
| 5285 } | 5053 } |
| 5286 const intptr_t num_types = Length(); | 5054 const intptr_t num_types = Length(); |
| 5287 if (IsRaw(0, num_types)) { | 5055 if (IsRaw(0, num_types)) { |
| 5288 return TypeArguments::null(); | 5056 return TypeArguments::null(); |
| 5289 } | 5057 } |
| 5290 Thread* thread = Thread::Current(); | 5058 Thread* thread = Thread::Current(); |
| 5291 Zone* zone = thread->zone(); | 5059 Zone* zone = thread->zone(); |
| 5292 Isolate* isolate = thread->isolate(); | 5060 Isolate* isolate = thread->isolate(); |
| 5293 ObjectStore* object_store = isolate->object_store(); | 5061 ObjectStore* object_store = isolate->object_store(); |
| 5294 Array& table = Array::Handle(zone, | |
| 5295 object_store->canonical_type_arguments()); | |
| 5296 // Last element of the array is the number of used elements. | |
| 5297 const intptr_t num_used = | |
| 5298 Smi::Value(Smi::RawCast(table.At(table.Length() - 1))); | |
| 5299 const intptr_t hash = Hash(); | |
| 5300 intptr_t index = FindIndexInCanonicalTypeArguments(zone, table, *this, hash); | |
| 5301 TypeArguments& result = TypeArguments::Handle(zone); | 5062 TypeArguments& result = TypeArguments::Handle(zone); |
| 5302 result ^= table.At(index); | 5063 { |
| 5064 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
| 5065 CanonicalTypeArgumentsSet table(zone, |
| 5066 object_store->canonical_type_arguments()); |
| 5067 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this)); |
| 5068 object_store->set_canonical_type_arguments(table.Release()); |
| 5069 } |
| 5303 if (result.IsNull()) { | 5070 if (result.IsNull()) { |
| 5304 // Canonicalize each type argument. | 5071 // Canonicalize each type argument. |
| 5305 AbstractType& type_arg = AbstractType::Handle(zone); | 5072 AbstractType& type_arg = AbstractType::Handle(zone); |
| 5306 for (intptr_t i = 0; i < num_types; i++) { | 5073 for (intptr_t i = 0; i < num_types; i++) { |
| 5307 type_arg = TypeAt(i); | 5074 type_arg = TypeAt(i); |
| 5308 type_arg = type_arg.Canonicalize(trail); | 5075 type_arg = type_arg.Canonicalize(trail); |
| 5309 if (IsCanonical()) { | 5076 if (IsCanonical()) { |
| 5310 // Canonicalizing this type_arg canonicalized this type. | 5077 // Canonicalizing this type_arg canonicalized this type. |
| 5311 ASSERT(IsRecursive()); | 5078 ASSERT(IsRecursive()); |
| 5312 return this->raw(); | 5079 return this->raw(); |
| 5313 } | 5080 } |
| 5314 SetTypeAt(i, type_arg); | 5081 SetTypeAt(i, type_arg); |
| 5315 } | 5082 } |
| 5316 // Canonicalization of a recursive type may change its hash. | 5083 // Canonicalization of a type argument of a recursive type argument vector |
| 5317 intptr_t canonical_hash = hash; | 5084 // may change the hash of the vector, so recompute. |
| 5318 if (IsRecursive()) { | 5085 if (IsRecursive()) { |
| 5319 canonical_hash = Hash(); | 5086 ComputeHash(); |
| 5320 } | 5087 } |
| 5321 // Canonicalization of the type argument's own type arguments may add an | 5088 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
| 5322 // entry to the table, or even grow the table, and thereby change the | 5089 CanonicalTypeArgumentsSet table( |
| 5323 // previously calculated index. | 5090 zone, object_store->canonical_type_arguments()); |
| 5324 table = object_store->canonical_type_arguments(); | 5091 // Since we canonicalized some type arguments above we need to lookup |
| 5325 if ((canonical_hash != hash) || | 5092 // in the table again to make sure we don't already have an equivalent |
| 5326 (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used)) { | 5093 // canonical entry. |
| 5327 index = FindIndexInCanonicalTypeArguments( | 5094 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this)); |
| 5328 zone, table, *this, canonical_hash); | |
| 5329 result ^= table.At(index); | |
| 5330 } | |
| 5331 if (result.IsNull()) { | 5095 if (result.IsNull()) { |
| 5332 // Make sure we have an old space object and add it to the table. | 5096 // Make sure we have an old space object and add it to the table. |
| 5333 if (this->IsNew()) { | 5097 if (this->IsNew()) { |
| 5334 result ^= Object::Clone(*this, Heap::kOld); | 5098 result ^= Object::Clone(*this, Heap::kOld); |
| 5335 } else { | 5099 } else { |
| 5336 result ^= this->raw(); | 5100 result ^= this->raw(); |
| 5337 } | 5101 } |
| 5338 ASSERT(result.IsOld()); | 5102 ASSERT(result.IsOld()); |
| 5339 InsertIntoCanonicalTypeArguments(thread, table, result, index); | 5103 result.SetCanonical(); // Mark object as being canonical. |
| 5104 // Now add this TypeArgument into the canonical list of type arguments. |
| 5105 bool present = table.Insert(result); |
| 5106 ASSERT(!present); |
| 5340 } | 5107 } |
| 5108 object_store->set_canonical_type_arguments(table.Release()); |
| 5341 } | 5109 } |
| 5342 ASSERT(result.Equals(*this)); | 5110 ASSERT(result.Equals(*this)); |
| 5343 ASSERT(!result.IsNull()); | 5111 ASSERT(!result.IsNull()); |
| 5344 ASSERT(result.IsTypeArguments()); | 5112 ASSERT(result.IsTypeArguments()); |
| 5345 ASSERT(result.IsCanonical()); | 5113 ASSERT(result.IsCanonical()); |
| 5346 return result.raw(); | 5114 return result.raw(); |
| 5347 } | 5115 } |
| 5348 | 5116 |
| 5349 | 5117 |
| 5350 RawString* TypeArguments::EnumerateURIs() const { | 5118 RawString* TypeArguments::EnumerateURIs() const { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5361 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); | 5129 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); |
| 5362 } | 5130 } |
| 5363 return String::ConcatAll(pieces); | 5131 return String::ConcatAll(pieces); |
| 5364 } | 5132 } |
| 5365 | 5133 |
| 5366 | 5134 |
| 5367 const char* TypeArguments::ToCString() const { | 5135 const char* TypeArguments::ToCString() const { |
| 5368 if (IsNull()) { | 5136 if (IsNull()) { |
| 5369 return "NULL TypeArguments"; | 5137 return "NULL TypeArguments"; |
| 5370 } | 5138 } |
| 5371 const char* prev_cstr = "TypeArguments:"; | 5139 Zone* zone = Thread::Current()->zone(); |
| 5140 const char* prev_cstr = OS::SCreate( |
| 5141 zone, "TypeArguments: (%" Pd ")", Smi::Value(raw_ptr()->hash_)); |
| 5372 for (int i = 0; i < Length(); i++) { | 5142 for (int i = 0; i < Length(); i++) { |
| 5373 const AbstractType& type_at = AbstractType::Handle(TypeAt(i)); | 5143 const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i)); |
| 5374 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); | 5144 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); |
| 5375 char* chars = OS::SCreate(Thread::Current()->zone(), | 5145 char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr); |
| 5376 "%s [%s]", prev_cstr, type_cstr); | |
| 5377 prev_cstr = chars; | 5146 prev_cstr = chars; |
| 5378 } | 5147 } |
| 5379 return prev_cstr; | 5148 return prev_cstr; |
| 5380 } | 5149 } |
| 5381 | 5150 |
| 5382 | 5151 |
| 5383 const char* PatchClass::ToCString() const { | 5152 const char* PatchClass::ToCString() const { |
| 5384 const Class& cls = Class::Handle(patched_class()); | 5153 const Class& cls = Class::Handle(patched_class()); |
| 5385 const char* cls_name = cls.ToCString(); | 5154 const char* cls_name = cls.ToCString(); |
| 5386 return OS::SCreate(Thread::Current()->zone(), | 5155 return OS::SCreate(Thread::Current()->zone(), |
| (...skipping 4081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9468 // Called when growing the table. | 9237 // Called when growing the table. |
| 9469 static bool IsMatch(const Object& a, const Object& b) { | 9238 static bool IsMatch(const Object& a, const Object& b) { |
| 9470 ASSERT(a.IsLibrary() && b.IsLibrary()); | 9239 ASSERT(a.IsLibrary() && b.IsLibrary()); |
| 9471 // Library objects are always canonical. | 9240 // Library objects are always canonical. |
| 9472 return a.raw() == b.raw(); | 9241 return a.raw() == b.raw(); |
| 9473 } | 9242 } |
| 9474 static uword Hash(const Object& key) { | 9243 static uword Hash(const Object& key) { |
| 9475 return Library::Cast(key).UrlHash(); | 9244 return Library::Cast(key).UrlHash(); |
| 9476 } | 9245 } |
| 9477 }; | 9246 }; |
| 9478 | |
| 9479 | |
| 9480 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; | 9247 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; |
| 9481 | 9248 |
| 9482 | 9249 |
| 9483 RawInstance* Library::TransitiveLoadError() const { | 9250 RawInstance* Library::TransitiveLoadError() const { |
| 9484 if (LoadError() != Instance::null()) { | 9251 if (LoadError() != Instance::null()) { |
| 9485 return LoadError(); | 9252 return LoadError(); |
| 9486 } | 9253 } |
| 9487 Thread* thread = Thread::Current(); | 9254 Thread* thread = Thread::Current(); |
| 9488 Isolate* isolate = thread->isolate(); | 9255 Isolate* isolate = thread->isolate(); |
| 9489 Zone* zone = thread->zone(); | 9256 Zone* zone = thread->zone(); |
| (...skipping 5947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15437 ASSERT(instance_size != 0); | 15204 ASSERT(instance_size != 0); |
| 15438 uword hash = instance_size; | 15205 uword hash = instance_size; |
| 15439 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | 15206 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
| 15440 for (intptr_t offset = Instance::NextFieldOffset(); | 15207 for (intptr_t offset = Instance::NextFieldOffset(); |
| 15441 offset < instance_size; | 15208 offset < instance_size; |
| 15442 offset += kWordSize) { | 15209 offset += kWordSize) { |
| 15443 uword value = reinterpret_cast<uword>( | 15210 uword value = reinterpret_cast<uword>( |
| 15444 *reinterpret_cast<RawObject**>(this_addr + offset)); | 15211 *reinterpret_cast<RawObject**>(this_addr + offset)); |
| 15445 hash = CombineHashes(hash, value); | 15212 hash = CombineHashes(hash, value); |
| 15446 } | 15213 } |
| 15447 return FinalizeHash(hash); | 15214 return FinalizeHash(hash, (kBitsPerWord - 1)); |
| 15448 } | 15215 } |
| 15449 | 15216 |
| 15450 | 15217 |
| 15451 #if defined(DEBUG) | 15218 #if defined(DEBUG) |
| 15452 class CheckForPointers : public ObjectPointerVisitor { | 15219 class CheckForPointers : public ObjectPointerVisitor { |
| 15453 public: | 15220 public: |
| 15454 explicit CheckForPointers(Isolate* isolate) | 15221 explicit CheckForPointers(Isolate* isolate) |
| 15455 : ObjectPointerVisitor(isolate), has_pointers_(false) {} | 15222 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
| 15456 | 15223 |
| 15457 bool has_pointers() const { return has_pointers_; } | 15224 bool has_pointers() const { return has_pointers_; } |
| (...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17217 | 16984 |
| 17218 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { | 16985 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { |
| 17219 ASSERT(IsFinalized()); | 16986 ASSERT(IsFinalized()); |
| 17220 if (IsCanonical() || IsMalformed()) { | 16987 if (IsCanonical() || IsMalformed()) { |
| 17221 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); | 16988 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); |
| 17222 return this->raw(); | 16989 return this->raw(); |
| 17223 } | 16990 } |
| 17224 Thread* thread = Thread::Current(); | 16991 Thread* thread = Thread::Current(); |
| 17225 Zone* zone = thread->zone(); | 16992 Zone* zone = thread->zone(); |
| 17226 Isolate* isolate = thread->isolate(); | 16993 Isolate* isolate = thread->isolate(); |
| 17227 AbstractType& type = Type::Handle(zone); | 16994 |
| 17228 const Class& cls = Class::Handle(zone, type_class()); | |
| 17229 // Since void is a keyword, we never have to canonicalize the void type after | 16995 // Since void is a keyword, we never have to canonicalize the void type after |
| 17230 // it is canonicalized once by the vm isolate. The parser does the mapping. | 16996 // it is canonicalized once by the vm isolate. The parser does the mapping. |
| 17231 ASSERT((cls.raw() != Object::void_class()) || | 16997 ASSERT((type_class() != Object::void_class()) || |
| 17232 (isolate == Dart::vm_isolate())); | 16998 (isolate == Dart::vm_isolate())); |
| 16999 |
| 17233 // Since dynamic is not a keyword, the parser builds a type that requires | 17000 // Since dynamic is not a keyword, the parser builds a type that requires |
| 17234 // canonicalization. | 17001 // canonicalization. |
| 17235 if ((cls.raw() == Object::dynamic_class()) && | 17002 if ((type_class() == Object::dynamic_class()) && |
| 17236 (isolate != Dart::vm_isolate())) { | 17003 (isolate != Dart::vm_isolate())) { |
| 17237 ASSERT(Object::dynamic_type().IsCanonical()); | 17004 ASSERT(Object::dynamic_type().IsCanonical()); |
| 17238 return Object::dynamic_type().raw(); | 17005 return Object::dynamic_type().raw(); |
| 17239 } | 17006 } |
| 17007 |
| 17008 AbstractType& type = Type::Handle(zone); |
| 17009 const Class& cls = Class::Handle(zone, type_class()); |
| 17010 |
| 17240 // Fast canonical lookup/registry for simple types. | 17011 // Fast canonical lookup/registry for simple types. |
| 17241 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { | 17012 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { |
| 17242 ASSERT(!IsFunctionType()); | 17013 ASSERT(!IsFunctionType()); |
| 17243 type = cls.CanonicalType(); | 17014 type = cls.CanonicalType(); |
| 17244 if (type.IsNull()) { | 17015 if (type.IsNull()) { |
| 17245 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); | 17016 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); |
| 17246 // Canonicalize the type arguments of the supertype, if any. | 17017 // Canonicalize the type arguments of the supertype, if any. |
| 17247 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 17018 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
| 17248 type_args = type_args.Canonicalize(trail); | 17019 type_args = type_args.Canonicalize(trail); |
| 17249 if (IsCanonical()) { | 17020 if (IsCanonical()) { |
| 17250 // Canonicalizing type_args canonicalized this type. | 17021 // Canonicalizing type_args canonicalized this type. |
| 17251 ASSERT(IsRecursive()); | 17022 ASSERT(IsRecursive()); |
| 17252 return this->raw(); | 17023 return this->raw(); |
| 17253 } | 17024 } |
| 17254 set_arguments(type_args); | 17025 set_arguments(type_args); |
| 17255 type = cls.CanonicalType(); // May be set while canonicalizing type args. | 17026 type = cls.CanonicalType(); // May be set while canonicalizing type args. |
| 17256 if (type.IsNull()) { | 17027 if (type.IsNull()) { |
| 17257 MutexLocker ml(isolate->type_canonicalization_mutex()); | 17028 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
| 17258 // Recheck if type exists. | 17029 // Recheck if type exists. |
| 17259 type = cls.CanonicalType(); | 17030 type = cls.CanonicalType(); |
| 17260 if (type.IsNull()) { | 17031 if (type.IsNull()) { |
| 17032 ComputeHash(); |
| 17261 SetCanonical(); | 17033 SetCanonical(); |
| 17262 cls.set_canonical_types(*this); | 17034 cls.set_canonical_type(*this); |
| 17263 return this->raw(); | 17035 return this->raw(); |
| 17264 } | 17036 } |
| 17265 } | 17037 } |
| 17266 } | 17038 } |
| 17267 ASSERT(this->Equals(type)); | 17039 ASSERT(this->Equals(type)); |
| 17268 ASSERT(type.IsCanonical()); | 17040 ASSERT(type.IsCanonical()); |
| 17269 return type.raw(); | 17041 return type.raw(); |
| 17270 } | 17042 } |
| 17271 | 17043 |
| 17272 Array& canonical_types = Array::Handle(zone); | 17044 ObjectStore* object_store = isolate->object_store(); |
| 17273 canonical_types ^= cls.canonical_types(); | 17045 { |
| 17274 if (canonical_types.IsNull()) { | 17046 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
| 17275 canonical_types = empty_array().raw(); | 17047 CanonicalTypeSet table(zone, object_store->canonical_types()); |
| 17048 type ^= table.GetOrNull(CanonicalTypeKey(*this)); |
| 17049 object_store->set_canonical_types(table.Release()); |
| 17276 } | 17050 } |
| 17277 intptr_t length = canonical_types.Length(); | 17051 if (type.IsNull()) { |
| 17278 // Linear search to see whether this type is already present in the | 17052 // The type was not found in the table. It is not canonical yet. |
| 17279 // list of canonicalized types. | 17053 |
| 17280 // TODO(asiva): Try to re-factor this lookup code to make sharing | 17054 // Canonicalize the type arguments. |
| 17281 // easy between the 4 versions of this loop. | 17055 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
| 17282 intptr_t index = 1; // Slot 0 is reserved for CanonicalType(). | 17056 // In case the type is first canonicalized at runtime, its type argument |
| 17283 while (index < length) { | 17057 // vector may be longer than necessary. This is not an issue. |
| 17284 type ^= canonical_types.At(index); | 17058 ASSERT(type_args.IsNull() || |
| 17059 (type_args.Length() >= cls.NumTypeArguments())); |
| 17060 type_args = type_args.Canonicalize(trail); |
| 17061 if (IsCanonical()) { |
| 17062 // Canonicalizing type_args canonicalized this type as a side effect. |
| 17063 ASSERT(IsRecursive()); |
| 17064 // Cycles via typedefs are detected and disallowed, but a function type |
| 17065 // can be recursive due to a cycle in its type arguments. |
| 17066 return this->raw(); |
| 17067 } |
| 17068 set_arguments(type_args); |
| 17069 ASSERT(type_args.IsNull() || type_args.IsOld()); |
| 17070 |
| 17071 // In case of a function type, replace the actual function by a signature |
| 17072 // function. |
| 17073 if (IsFunctionType()) { |
| 17074 const Function& fun = Function::Handle(zone, signature()); |
| 17075 if (!fun.IsSignatureFunction()) { |
| 17076 Function& sig_fun = Function::Handle( |
| 17077 zone, |
| 17078 Function::NewSignatureFunction(cls, TokenPosition::kNoSource)); |
| 17079 type = fun.result_type(); |
| 17080 type = type.Canonicalize(trail); |
| 17081 sig_fun.set_result_type(type); |
| 17082 const intptr_t num_params = fun.NumParameters(); |
| 17083 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters()); |
| 17084 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(), |
| 17085 fun.HasOptionalPositionalParameters()); |
| 17086 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params, |
| 17087 Heap::kOld))); |
| 17088 for (intptr_t i = 0; i < num_params; i++) { |
| 17089 type = fun.ParameterTypeAt(i); |
| 17090 type = type.Canonicalize(trail); |
| 17091 sig_fun.SetParameterTypeAt(i, type); |
| 17092 } |
| 17093 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names())); |
| 17094 set_signature(sig_fun); |
| 17095 } |
| 17096 } |
| 17097 |
| 17098 // Check to see if the type got added to canonical list as part of the |
| 17099 // type arguments canonicalization. |
| 17100 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
| 17101 CanonicalTypeSet table(zone, object_store->canonical_types()); |
| 17102 type ^= table.GetOrNull(CanonicalTypeKey(*this)); |
| 17285 if (type.IsNull()) { | 17103 if (type.IsNull()) { |
| 17286 break; | 17104 // Add this Type into the canonical list of types. |
| 17105 type ^= raw(); |
| 17106 ASSERT(type.IsOld()); |
| 17107 type.SetCanonical(); // Mark object as being canonical. |
| 17108 bool present = table.Insert(type); |
| 17109 ASSERT(!present); |
| 17287 } | 17110 } |
| 17288 ASSERT(type.IsFinalized()); | 17111 object_store->set_canonical_types(table.Release()); |
| 17289 if (this->Equals(type)) { | |
| 17290 ASSERT(type.IsCanonical()); | |
| 17291 return type.raw(); | |
| 17292 } | |
| 17293 index++; | |
| 17294 } | 17112 } |
| 17295 // The type was not found in the table. It is not canonical yet. | 17113 return type.raw(); |
| 17296 | |
| 17297 // Canonicalize the type arguments. | |
| 17298 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | |
| 17299 // In case the type is first canonicalized at runtime, its type argument | |
| 17300 // vector may be longer than necessary. This is not an issue. | |
| 17301 ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments())); | |
| 17302 type_args = type_args.Canonicalize(trail); | |
| 17303 if (IsCanonical()) { | |
| 17304 // Canonicalizing type_args canonicalized this type as a side effect. | |
| 17305 ASSERT(IsRecursive()); | |
| 17306 // Cycles via typedefs are detected and disallowed, but a function type can | |
| 17307 // be recursive due to a cycle in its type arguments. | |
| 17308 return this->raw(); | |
| 17309 } | |
| 17310 set_arguments(type_args); | |
| 17311 ASSERT(type_args.IsNull() || type_args.IsOld()); | |
| 17312 | |
| 17313 // In case of a function type, replace the actual function by a signature | |
| 17314 // function. | |
| 17315 if (IsFunctionType()) { | |
| 17316 const Function& fun = Function::Handle(zone, signature()); | |
| 17317 if (!fun.IsSignatureFunction()) { | |
| 17318 Function& sig_fun = Function::Handle(zone, | |
| 17319 Function::NewSignatureFunction(cls, TokenPosition::kNoSource)); | |
| 17320 type = fun.result_type(); | |
| 17321 type = type.Canonicalize(trail); | |
| 17322 sig_fun.set_result_type(type); | |
| 17323 const intptr_t num_params = fun.NumParameters(); | |
| 17324 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters()); | |
| 17325 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(), | |
| 17326 fun.HasOptionalPositionalParameters()); | |
| 17327 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params, | |
| 17328 Heap::kOld))); | |
| 17329 for (intptr_t i = 0; i < num_params; i++) { | |
| 17330 type = fun.ParameterTypeAt(i); | |
| 17331 type = type.Canonicalize(trail); | |
| 17332 sig_fun.SetParameterTypeAt(i, type); | |
| 17333 } | |
| 17334 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names())); | |
| 17335 set_signature(sig_fun); | |
| 17336 } | |
| 17337 } | |
| 17338 return cls.LookupOrAddCanonicalType(*this, index); | |
| 17339 } | 17114 } |
| 17340 | 17115 |
| 17341 | 17116 |
| 17342 RawString* Type::EnumerateURIs() const { | 17117 RawString* Type::EnumerateURIs() const { |
| 17343 if (IsDynamicType() || IsVoidType()) { | 17118 if (IsDynamicType() || IsVoidType()) { |
| 17344 return Symbols::Empty().raw(); | 17119 return Symbols::Empty().raw(); |
| 17345 } | 17120 } |
| 17346 Thread* thread = Thread::Current(); | 17121 Thread* thread = Thread::Current(); |
| 17347 Zone* zone = thread->zone(); | 17122 Zone* zone = thread->zone(); |
| 17348 GrowableHandlePtrArray<const String> pieces(zone, 6); | 17123 GrowableHandlePtrArray<const String> pieces(zone, 6); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 17369 const Library& library = Library::Handle(zone, cls.library()); | 17144 const Library& library = Library::Handle(zone, cls.library()); |
| 17370 pieces.Add(String::Handle(zone, library.url())); | 17145 pieces.Add(String::Handle(zone, library.url())); |
| 17371 pieces.Add(Symbols::NewLine()); | 17146 pieces.Add(Symbols::NewLine()); |
| 17372 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 17147 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
| 17373 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); | 17148 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); |
| 17374 } | 17149 } |
| 17375 return Symbols::FromConcatAll(thread, pieces); | 17150 return Symbols::FromConcatAll(thread, pieces); |
| 17376 } | 17151 } |
| 17377 | 17152 |
| 17378 | 17153 |
| 17379 intptr_t Type::Hash() const { | 17154 intptr_t Type::ComputeHash() const { |
| 17380 ASSERT(IsFinalized()); | 17155 ASSERT(IsFinalized()); |
| 17381 uint32_t result = 1; | 17156 uint32_t result = 1; |
| 17382 if (IsMalformed()) return result; | 17157 if (IsMalformed()) return result; |
| 17383 result = CombineHashes(result, Class::Handle(type_class()).id()); | 17158 result = CombineHashes(result, Class::Handle(type_class()).id()); |
| 17384 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); | 17159 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); |
| 17385 if (IsFunctionType()) { | 17160 if (IsFunctionType()) { |
| 17386 const Function& sig_fun = Function::Handle(signature()); | 17161 const Function& sig_fun = Function::Handle(signature()); |
| 17387 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); | 17162 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); |
| 17388 result = CombineHashes(result, type.Hash()); | 17163 result = CombineHashes(result, type.Hash()); |
| 17389 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); | 17164 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); |
| 17390 const intptr_t num_params = sig_fun.NumParameters(); | 17165 const intptr_t num_params = sig_fun.NumParameters(); |
| 17391 for (intptr_t i = 0; i < num_params; i++) { | 17166 for (intptr_t i = 0; i < num_params; i++) { |
| 17392 type = sig_fun.ParameterTypeAt(i); | 17167 type = sig_fun.ParameterTypeAt(i); |
| 17393 result = CombineHashes(result, type.Hash()); | 17168 result = CombineHashes(result, type.Hash()); |
| 17394 } | 17169 } |
| 17395 if (sig_fun.NumOptionalNamedParameters() > 0) { | 17170 if (sig_fun.NumOptionalNamedParameters() > 0) { |
| 17396 String& param_name = String::Handle(); | 17171 String& param_name = String::Handle(); |
| 17397 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { | 17172 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { |
| 17398 param_name = sig_fun.ParameterNameAt(i); | 17173 param_name = sig_fun.ParameterNameAt(i); |
| 17399 result = CombineHashes(result, param_name.Hash()); | 17174 result = CombineHashes(result, param_name.Hash()); |
| 17400 } | 17175 } |
| 17401 } | 17176 } |
| 17402 } | 17177 } |
| 17403 return FinalizeHash(result); | 17178 result = FinalizeHash(result, kHashBits); |
| 17179 SetHash(result); |
| 17180 return result; |
| 17404 } | 17181 } |
| 17405 | 17182 |
| 17406 | 17183 |
| 17407 void Type::set_type_class(const Class& value) const { | 17184 void Type::set_type_class(const Class& value) const { |
| 17408 ASSERT(!value.IsNull()); | 17185 ASSERT(!value.IsNull()); |
| 17409 StorePointer(&raw_ptr()->type_class_id_, | 17186 StorePointer(&raw_ptr()->type_class_id_, |
| 17410 reinterpret_cast<RawObject*>(Smi::New(value.id()))); | 17187 reinterpret_cast<RawObject*>(Smi::New(value.id()))); |
| 17411 } | 17188 } |
| 17412 | 17189 |
| 17413 | 17190 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 17435 const TypeArguments& arguments, | 17212 const TypeArguments& arguments, |
| 17436 TokenPosition token_pos, | 17213 TokenPosition token_pos, |
| 17437 Heap::Space space) { | 17214 Heap::Space space) { |
| 17438 const Type& result = Type::Handle(Type::New(space)); | 17215 const Type& result = Type::Handle(Type::New(space)); |
| 17439 if (clazz.IsClass()) { | 17216 if (clazz.IsClass()) { |
| 17440 result.set_type_class(Class::Cast(clazz)); | 17217 result.set_type_class(Class::Cast(clazz)); |
| 17441 } else { | 17218 } else { |
| 17442 result.set_unresolved_class(clazz); | 17219 result.set_unresolved_class(clazz); |
| 17443 } | 17220 } |
| 17444 result.set_arguments(arguments); | 17221 result.set_arguments(arguments); |
| 17222 result.SetHash(0); |
| 17445 result.set_token_pos(token_pos); | 17223 result.set_token_pos(token_pos); |
| 17446 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); | 17224 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); |
| 17447 return result.raw(); | 17225 return result.raw(); |
| 17448 } | 17226 } |
| 17449 | 17227 |
| 17450 | 17228 |
| 17451 void Type::set_token_pos(TokenPosition token_pos) const { | 17229 void Type::set_token_pos(TokenPosition token_pos) const { |
| 17452 ASSERT(!token_pos.IsClassifying()); | 17230 ASSERT(!token_pos.IsClassifying()); |
| 17453 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 17231 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
| 17454 } | 17232 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17614 pieces.Add(String::Handle(zone, library.url())); | 17392 pieces.Add(String::Handle(zone, library.url())); |
| 17615 pieces.Add(Symbols::NewLine()); | 17393 pieces.Add(Symbols::NewLine()); |
| 17616 return Symbols::FromConcatAll(thread, pieces); | 17394 return Symbols::FromConcatAll(thread, pieces); |
| 17617 } | 17395 } |
| 17618 | 17396 |
| 17619 | 17397 |
| 17620 intptr_t TypeRef::Hash() const { | 17398 intptr_t TypeRef::Hash() const { |
| 17621 // Do not calculate the hash of the referenced type to avoid divergence. | 17399 // Do not calculate the hash of the referenced type to avoid divergence. |
| 17622 const uint32_t result = | 17400 const uint32_t result = |
| 17623 Class::Handle(AbstractType::Handle(type()).type_class()).id(); | 17401 Class::Handle(AbstractType::Handle(type()).type_class()).id(); |
| 17624 return FinalizeHash(result); | 17402 return FinalizeHash(result, kHashBits); |
| 17625 } | 17403 } |
| 17626 | 17404 |
| 17627 | 17405 |
| 17628 RawTypeRef* TypeRef::New() { | 17406 RawTypeRef* TypeRef::New() { |
| 17629 RawObject* raw = Object::Allocate(TypeRef::kClassId, | 17407 RawObject* raw = Object::Allocate(TypeRef::kClassId, |
| 17630 TypeRef::InstanceSize(), | 17408 TypeRef::InstanceSize(), |
| 17631 Heap::kOld); | 17409 Heap::kOld); |
| 17632 return reinterpret_cast<RawTypeRef*>(raw); | 17410 return reinterpret_cast<RawTypeRef*>(raw); |
| 17633 } | 17411 } |
| 17634 | 17412 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17862 const Class& cls = Class::Handle(zone, parameterized_class()); | 17640 const Class& cls = Class::Handle(zone, parameterized_class()); |
| 17863 pieces.Add(String::Handle(zone, cls.UserVisibleName())); | 17641 pieces.Add(String::Handle(zone, cls.UserVisibleName())); |
| 17864 pieces.Add(Symbols::SpaceIsFromSpace()); | 17642 pieces.Add(Symbols::SpaceIsFromSpace()); |
| 17865 const Library& library = Library::Handle(zone, cls.library()); | 17643 const Library& library = Library::Handle(zone, cls.library()); |
| 17866 pieces.Add(String::Handle(zone, library.url())); | 17644 pieces.Add(String::Handle(zone, library.url())); |
| 17867 pieces.Add(Symbols::NewLine()); | 17645 pieces.Add(Symbols::NewLine()); |
| 17868 return Symbols::FromConcatAll(thread, pieces); | 17646 return Symbols::FromConcatAll(thread, pieces); |
| 17869 } | 17647 } |
| 17870 | 17648 |
| 17871 | 17649 |
| 17872 intptr_t TypeParameter::Hash() const { | 17650 intptr_t TypeParameter::ComputeHash() const { |
| 17873 ASSERT(IsFinalized()); | 17651 ASSERT(IsFinalized()); |
| 17874 uint32_t result = Class::Handle(parameterized_class()).id(); | 17652 uint32_t result = Class::Handle(parameterized_class()).id(); |
| 17875 // No need to include the hash of the bound, since the type parameter is fully | 17653 // No need to include the hash of the bound, since the type parameter is fully |
| 17876 // identified by its class and index. | 17654 // identified by its class and index. |
| 17877 result = CombineHashes(result, index()); | 17655 result = CombineHashes(result, index()); |
| 17878 return FinalizeHash(result); | 17656 result = FinalizeHash(result, kHashBits); |
| 17657 SetHash(result); |
| 17658 return result; |
| 17879 } | 17659 } |
| 17880 | 17660 |
| 17881 | 17661 |
| 17882 RawTypeParameter* TypeParameter::New() { | 17662 RawTypeParameter* TypeParameter::New() { |
| 17883 RawObject* raw = Object::Allocate(TypeParameter::kClassId, | 17663 RawObject* raw = Object::Allocate(TypeParameter::kClassId, |
| 17884 TypeParameter::InstanceSize(), | 17664 TypeParameter::InstanceSize(), |
| 17885 Heap::kOld); | 17665 Heap::kOld); |
| 17886 return reinterpret_cast<RawTypeParameter*>(raw); | 17666 return reinterpret_cast<RawTypeParameter*>(raw); |
| 17887 } | 17667 } |
| 17888 | 17668 |
| 17889 | 17669 |
| 17890 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, | 17670 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, |
| 17891 intptr_t index, | 17671 intptr_t index, |
| 17892 const String& name, | 17672 const String& name, |
| 17893 const AbstractType& bound, | 17673 const AbstractType& bound, |
| 17894 TokenPosition token_pos) { | 17674 TokenPosition token_pos) { |
| 17895 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); | 17675 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); |
| 17896 result.set_parameterized_class(parameterized_class); | 17676 result.set_parameterized_class(parameterized_class); |
| 17897 result.set_index(index); | 17677 result.set_index(index); |
| 17898 result.set_name(name); | 17678 result.set_name(name); |
| 17899 result.set_bound(bound); | 17679 result.set_bound(bound); |
| 17680 result.SetHash(0); |
| 17900 result.set_token_pos(token_pos); | 17681 result.set_token_pos(token_pos); |
| 17901 result.StoreNonPointer(&result.raw_ptr()->type_state_, | 17682 result.StoreNonPointer(&result.raw_ptr()->type_state_, |
| 17902 RawTypeParameter::kAllocated); | 17683 RawTypeParameter::kAllocated); |
| 17903 return result.raw(); | 17684 return result.raw(); |
| 17904 } | 17685 } |
| 17905 | 17686 |
| 17906 | 17687 |
| 17907 void TypeParameter::set_token_pos(TokenPosition token_pos) const { | 17688 void TypeParameter::set_token_pos(TokenPosition token_pos) const { |
| 17908 ASSERT(!token_pos.IsClassifying()); | 17689 ASSERT(!token_pos.IsClassifying()); |
| 17909 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 17690 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 18126 return BoundedType::New(bounded_type, upper_bound, type_param); | 17907 return BoundedType::New(bounded_type, upper_bound, type_param); |
| 18127 } | 17908 } |
| 18128 | 17909 |
| 18129 | 17910 |
| 18130 RawString* BoundedType::EnumerateURIs() const { | 17911 RawString* BoundedType::EnumerateURIs() const { |
| 18131 // The bound does not appear in the user visible name. | 17912 // The bound does not appear in the user visible name. |
| 18132 return AbstractType::Handle(type()).EnumerateURIs(); | 17913 return AbstractType::Handle(type()).EnumerateURIs(); |
| 18133 } | 17914 } |
| 18134 | 17915 |
| 18135 | 17916 |
| 18136 intptr_t BoundedType::Hash() const { | 17917 intptr_t BoundedType::ComputeHash() const { |
| 18137 uint32_t result = AbstractType::Handle(type()).Hash(); | 17918 uint32_t result = AbstractType::Handle(type()).Hash(); |
| 18138 // No need to include the hash of the bound, since the bound is defined by the | 17919 // No need to include the hash of the bound, since the bound is defined by the |
| 18139 // type parameter (modulo instantiation state). | 17920 // type parameter (modulo instantiation state). |
| 18140 result = CombineHashes(result, | 17921 result = CombineHashes(result, |
| 18141 TypeParameter::Handle(type_parameter()).Hash()); | 17922 TypeParameter::Handle(type_parameter()).Hash()); |
| 18142 return FinalizeHash(result); | 17923 result = FinalizeHash(result, kHashBits); |
| 17924 SetHash(result); |
| 17925 return result; |
| 18143 } | 17926 } |
| 18144 | 17927 |
| 18145 | 17928 |
| 18146 RawBoundedType* BoundedType::New() { | 17929 RawBoundedType* BoundedType::New() { |
| 18147 RawObject* raw = Object::Allocate(BoundedType::kClassId, | 17930 RawObject* raw = Object::Allocate(BoundedType::kClassId, |
| 18148 BoundedType::InstanceSize(), | 17931 BoundedType::InstanceSize(), |
| 18149 Heap::kOld); | 17932 Heap::kOld); |
| 18150 return reinterpret_cast<RawBoundedType*>(raw); | 17933 return reinterpret_cast<RawBoundedType*>(raw); |
| 18151 } | 17934 } |
| 18152 | 17935 |
| 18153 | 17936 |
| 18154 RawBoundedType* BoundedType::New(const AbstractType& type, | 17937 RawBoundedType* BoundedType::New(const AbstractType& type, |
| 18155 const AbstractType& bound, | 17938 const AbstractType& bound, |
| 18156 const TypeParameter& type_parameter) { | 17939 const TypeParameter& type_parameter) { |
| 18157 const BoundedType& result = BoundedType::Handle(BoundedType::New()); | 17940 const BoundedType& result = BoundedType::Handle(BoundedType::New()); |
| 18158 result.set_type(type); | 17941 result.set_type(type); |
| 18159 result.set_bound(bound); | 17942 result.set_bound(bound); |
| 17943 result.SetHash(0); |
| 18160 result.set_type_parameter(type_parameter); | 17944 result.set_type_parameter(type_parameter); |
| 18161 return result.raw(); | 17945 return result.raw(); |
| 18162 } | 17946 } |
| 18163 | 17947 |
| 18164 | 17948 |
| 18165 const char* BoundedType::ToCString() const { | 17949 const char* BoundedType::ToCString() const { |
| 18166 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; | 17950 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; |
| 18167 const char* type_cstr = String::Handle(AbstractType::Handle( | 17951 const char* type_cstr = String::Handle(AbstractType::Handle( |
| 18168 type()).Name()).ToCString(); | 17952 type()).Name()).ToCString(); |
| 18169 const char* bound_cstr = String::Handle(AbstractType::Handle( | 17953 const char* bound_cstr = String::Handle(AbstractType::Handle( |
| (...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19687 public: | 19471 public: |
| 19688 StringHasher() : hash_(0) {} | 19472 StringHasher() : hash_(0) {} |
| 19689 void Add(int32_t ch) { | 19473 void Add(int32_t ch) { |
| 19690 hash_ = CombineHashes(hash_, ch); | 19474 hash_ = CombineHashes(hash_, ch); |
| 19691 } | 19475 } |
| 19692 void Add(const String& str, intptr_t begin_index, intptr_t len); | 19476 void Add(const String& str, intptr_t begin_index, intptr_t len); |
| 19693 | 19477 |
| 19694 // Return a non-zero hash of at most 'bits' bits. | 19478 // Return a non-zero hash of at most 'bits' bits. |
| 19695 intptr_t Finalize(int bits) { | 19479 intptr_t Finalize(int bits) { |
| 19696 ASSERT(1 <= bits && bits <= (kBitsPerWord - 1)); | 19480 ASSERT(1 <= bits && bits <= (kBitsPerWord - 1)); |
| 19697 hash_ = FinalizeHash(hash_); | 19481 hash_ = FinalizeHash(hash_, bits); |
| 19698 hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); | |
| 19699 ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32)); | 19482 ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32)); |
| 19700 return hash_ == 0 ? 1 : hash_; | 19483 return hash_; |
| 19701 } | 19484 } |
| 19702 private: | 19485 private: |
| 19703 uint32_t hash_; | 19486 uint32_t hash_; |
| 19704 }; | 19487 }; |
| 19705 | 19488 |
| 19706 | 19489 |
| 19707 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) { | 19490 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) { |
| 19708 ASSERT(begin_index >= 0); | 19491 ASSERT(begin_index >= 0); |
| 19709 ASSERT(len >= 0); | 19492 ASSERT(len >= 0); |
| 19710 ASSERT((begin_index + len) <= str.Length()); | 19493 ASSERT((begin_index + len) <= str.Length()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 19723 while (it.Next()) { | 19506 while (it.Next()) { |
| 19724 Add(it.Current()); | 19507 Add(it.Current()); |
| 19725 } | 19508 } |
| 19726 } | 19509 } |
| 19727 } | 19510 } |
| 19728 | 19511 |
| 19729 | 19512 |
| 19730 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) { | 19513 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) { |
| 19731 StringHasher hasher; | 19514 StringHasher hasher; |
| 19732 hasher.Add(str, begin_index, len); | 19515 hasher.Add(str, begin_index, len); |
| 19733 return hasher.Finalize(String::kHashBits); | 19516 return hasher.Finalize(kHashBits); |
| 19734 } | 19517 } |
| 19735 | 19518 |
| 19736 | 19519 |
| 19737 intptr_t String::HashConcat(const String& str1, const String& str2) { | 19520 intptr_t String::HashConcat(const String& str1, const String& str2) { |
| 19738 intptr_t len1 = str1.Length(); | 19521 intptr_t len1 = str1.Length(); |
| 19739 // Since String::Hash works at the code point (rune) level, a surrogate pair | 19522 // Since String::Hash works at the code point (rune) level, a surrogate pair |
| 19740 // that crosses the boundary between str1 and str2 must be composed. | 19523 // that crosses the boundary between str1 and str2 must be composed. |
| 19741 if (str1.IsTwoByteString() && Utf16::IsLeadSurrogate(str1.CharAt(len1 - 1))) { | 19524 if (str1.IsTwoByteString() && Utf16::IsLeadSurrogate(str1.CharAt(len1 - 1))) { |
| 19742 const String& temp = String::Handle(String::Concat(str1, str2)); | 19525 const String& temp = String::Handle(String::Concat(str1, str2)); |
| 19743 return temp.Hash(); | 19526 return temp.Hash(); |
| 19744 } else { | 19527 } else { |
| 19745 StringHasher hasher; | 19528 StringHasher hasher; |
| 19746 hasher.Add(str1, 0, len1); | 19529 hasher.Add(str1, 0, len1); |
| 19747 hasher.Add(str2, 0, str2.Length()); | 19530 hasher.Add(str2, 0, str2.Length()); |
| 19748 return hasher.Finalize(String::kHashBits); | 19531 return hasher.Finalize(kHashBits); |
| 19749 } | 19532 } |
| 19750 } | 19533 } |
| 19751 | 19534 |
| 19752 | 19535 |
| 19753 template<typename T> | 19536 template<typename T> |
| 19754 static intptr_t HashImpl(const T* characters, intptr_t len) { | 19537 static intptr_t HashImpl(const T* characters, intptr_t len) { |
| 19755 ASSERT(len >= 0); | 19538 ASSERT(len >= 0); |
| 19756 StringHasher hasher; | 19539 StringHasher hasher; |
| 19757 for (intptr_t i = 0; i < len; i++) { | 19540 for (intptr_t i = 0; i < len; i++) { |
| 19758 hasher.Add(characters[i]); | 19541 hasher.Add(characters[i]); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 19770 return HashImpl(characters, len); | 19553 return HashImpl(characters, len); |
| 19771 } | 19554 } |
| 19772 | 19555 |
| 19773 | 19556 |
| 19774 intptr_t String::Hash(const uint16_t* characters, intptr_t len) { | 19557 intptr_t String::Hash(const uint16_t* characters, intptr_t len) { |
| 19775 StringHasher hasher; | 19558 StringHasher hasher; |
| 19776 intptr_t i = 0; | 19559 intptr_t i = 0; |
| 19777 while (i < len) { | 19560 while (i < len) { |
| 19778 hasher.Add(Utf16::Next(characters, &i, len)); | 19561 hasher.Add(Utf16::Next(characters, &i, len)); |
| 19779 } | 19562 } |
| 19780 return hasher.Finalize(String::kHashBits); | 19563 return hasher.Finalize(kHashBits); |
| 19781 } | 19564 } |
| 19782 | 19565 |
| 19783 | 19566 |
| 19784 intptr_t String::Hash(const int32_t* characters, intptr_t len) { | 19567 intptr_t String::Hash(const int32_t* characters, intptr_t len) { |
| 19785 return HashImpl(characters, len); | 19568 return HashImpl(characters, len); |
| 19786 } | 19569 } |
| 19787 | 19570 |
| 19788 | 19571 |
| 19789 uint16_t String::CharAt(intptr_t index) const { | 19572 uint16_t String::CharAt(intptr_t index) const { |
| 19790 intptr_t class_id = raw()->GetClassId(); | 19573 intptr_t class_id = raw()->GetClassId(); |
| (...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21467 uword Array::ComputeCanonicalTableHash() const { | 21250 uword Array::ComputeCanonicalTableHash() const { |
| 21468 ASSERT(!IsNull()); | 21251 ASSERT(!IsNull()); |
| 21469 intptr_t len = Length(); | 21252 intptr_t len = Length(); |
| 21470 uword hash = len; | 21253 uword hash = len; |
| 21471 uword value = reinterpret_cast<uword>(GetTypeArguments()); | 21254 uword value = reinterpret_cast<uword>(GetTypeArguments()); |
| 21472 hash = CombineHashes(hash, value); | 21255 hash = CombineHashes(hash, value); |
| 21473 for (intptr_t i = 0; i < len; i++) { | 21256 for (intptr_t i = 0; i < len; i++) { |
| 21474 value = reinterpret_cast<uword>(At(i)); | 21257 value = reinterpret_cast<uword>(At(i)); |
| 21475 hash = CombineHashes(hash, value); | 21258 hash = CombineHashes(hash, value); |
| 21476 } | 21259 } |
| 21477 return FinalizeHash(hash); | 21260 return FinalizeHash(hash, kHashBits); |
| 21478 } | 21261 } |
| 21479 | 21262 |
| 21480 | 21263 |
| 21481 RawArray* Array::New(intptr_t len, Heap::Space space) { | 21264 RawArray* Array::New(intptr_t len, Heap::Space space) { |
| 21482 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 21265 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
| 21483 return New(kClassId, len, space); | 21266 return New(kClassId, len, space); |
| 21484 } | 21267 } |
| 21485 | 21268 |
| 21486 | 21269 |
| 21487 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 21270 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22124 } | 21907 } |
| 22125 | 21908 |
| 22126 | 21909 |
| 22127 uword TypedData::ComputeCanonicalTableHash() const { | 21910 uword TypedData::ComputeCanonicalTableHash() const { |
| 22128 const intptr_t len = this->LengthInBytes(); | 21911 const intptr_t len = this->LengthInBytes(); |
| 22129 ASSERT(len != 0); | 21912 ASSERT(len != 0); |
| 22130 uword hash = len; | 21913 uword hash = len; |
| 22131 for (intptr_t i = 0; i < len; i++) { | 21914 for (intptr_t i = 0; i < len; i++) { |
| 22132 hash = CombineHashes(len, GetUint8(i)); | 21915 hash = CombineHashes(len, GetUint8(i)); |
| 22133 } | 21916 } |
| 22134 return FinalizeHash(hash); | 21917 return FinalizeHash(hash, kHashBits); |
| 22135 } | 21918 } |
| 22136 | 21919 |
| 22137 | 21920 |
| 22138 RawTypedData* TypedData::New(intptr_t class_id, | 21921 RawTypedData* TypedData::New(intptr_t class_id, |
| 22139 intptr_t len, | 21922 intptr_t len, |
| 22140 Heap::Space space) { | 21923 Heap::Space space) { |
| 22141 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21924 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
| 22142 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21925 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
| 22143 } | 21926 } |
| 22144 TypedData& result = TypedData::Handle(); | 21927 TypedData& result = TypedData::Handle(); |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22822 return UserTag::null(); | 22605 return UserTag::null(); |
| 22823 } | 22606 } |
| 22824 | 22607 |
| 22825 | 22608 |
| 22826 const char* UserTag::ToCString() const { | 22609 const char* UserTag::ToCString() const { |
| 22827 const String& tag_label = String::Handle(label()); | 22610 const String& tag_label = String::Handle(label()); |
| 22828 return tag_label.ToCString(); | 22611 return tag_label.ToCString(); |
| 22829 } | 22612 } |
| 22830 | 22613 |
| 22831 } // namespace dart | 22614 } // namespace dart |
| OLD | NEW |