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 |