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 22 matching lines...) Expand all Loading... | |
33 #include "vm/profiler.h" | 33 #include "vm/profiler.h" |
34 #include "vm/reusable_handles.h" | 34 #include "vm/reusable_handles.h" |
35 #include "vm/runtime_entry.h" | 35 #include "vm/runtime_entry.h" |
36 #include "vm/scopes.h" | 36 #include "vm/scopes.h" |
37 #include "vm/stack_frame.h" | 37 #include "vm/stack_frame.h" |
38 #include "vm/symbols.h" | 38 #include "vm/symbols.h" |
39 #include "vm/tags.h" | 39 #include "vm/tags.h" |
40 #include "vm/thread_registry.h" | 40 #include "vm/thread_registry.h" |
41 #include "vm/timeline.h" | 41 #include "vm/timeline.h" |
42 #include "vm/timer.h" | 42 #include "vm/timer.h" |
43 #include "vm/type_table.h" | |
43 #include "vm/unicode.h" | 44 #include "vm/unicode.h" |
44 #include "vm/verified_memory.h" | 45 #include "vm/verified_memory.h" |
45 #include "vm/weak_code.h" | 46 #include "vm/weak_code.h" |
46 | 47 |
47 namespace dart { | 48 namespace dart { |
48 | 49 |
49 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, | 50 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
50 "Huge method cutoff in unoptimized code size (in bytes)."); | 51 "Huge method cutoff in unoptimized code size (in bytes)."); |
51 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, | 52 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, |
52 "Huge method cutoff in tokens: Disables optimizations for huge methods."); | 53 "Huge method cutoff in tokens: Disables optimizations for huge methods."); |
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 cls.set_num_type_arguments(1); | 1134 cls.set_num_type_arguments(1); |
1134 | 1135 |
1135 // Set up the growable object array class (Has to be done after the array | 1136 // Set up the growable object array class (Has to be done after the array |
1136 // class is setup as one of its field is an array object). | 1137 // class is setup as one of its field is an array object). |
1137 cls = Class::New<GrowableObjectArray>(); | 1138 cls = Class::New<GrowableObjectArray>(); |
1138 object_store->set_growable_object_array_class(cls); | 1139 object_store->set_growable_object_array_class(cls); |
1139 cls.set_type_arguments_field_offset( | 1140 cls.set_type_arguments_field_offset( |
1140 GrowableObjectArray::type_arguments_offset()); | 1141 GrowableObjectArray::type_arguments_offset()); |
1141 cls.set_num_type_arguments(1); | 1142 cls.set_num_type_arguments(1); |
1142 | 1143 |
1143 // canonical_type_arguments_ are Smi terminated. | 1144 // Initialize hash set for canonical_type_. |
1144 // Last element contains the count of used slots. | 1145 const intptr_t kInitialCanonicalTypeSize = 16; |
1146 array = HashTables::New<CanonicalTypeSet>( | |
1147 kInitialCanonicalTypeSize, Heap::kOld); | |
1148 object_store->set_canonical_types(array); | |
1149 | |
1150 // Initialize hash set for canonical_type_arguments_. | |
1145 const intptr_t kInitialCanonicalTypeArgumentsSize = 4; | 1151 const intptr_t kInitialCanonicalTypeArgumentsSize = 4; |
1146 array = Array::New(kInitialCanonicalTypeArgumentsSize + 1); | 1152 array = HashTables::New<CanonicalTypeArgumentsSet>( |
1147 array.SetAt(kInitialCanonicalTypeArgumentsSize, | 1153 kInitialCanonicalTypeArgumentsSize, Heap::kOld); |
1148 Smi::Handle(zone, Smi::New(0))); | |
1149 object_store->set_canonical_type_arguments(array); | 1154 object_store->set_canonical_type_arguments(array); |
1150 | 1155 |
1151 // Setup type class early in the process. | 1156 // Setup type class early in the process. |
1152 const Class& type_cls = Class::Handle(zone, Class::New<Type>()); | 1157 const Class& type_cls = Class::Handle(zone, Class::New<Type>()); |
1153 const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>()); | 1158 const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>()); |
1154 const Class& type_parameter_cls = Class::Handle(zone, | 1159 const Class& type_parameter_cls = Class::Handle(zone, |
1155 Class::New<TypeParameter>()); | 1160 Class::New<TypeParameter>()); |
1156 const Class& bounded_type_cls = Class::Handle(zone, | 1161 const Class& bounded_type_cls = Class::Handle(zone, |
1157 Class::New<BoundedType>()); | 1162 Class::New<BoundedType>()); |
1158 const Class& mixin_app_type_cls = Class::Handle(zone, | 1163 const Class& mixin_app_type_cls = Class::Handle(zone, |
(...skipping 2445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3604 RawArray* Class::constants() const { | 3609 RawArray* Class::constants() const { |
3605 return raw_ptr()->constants_; | 3610 return raw_ptr()->constants_; |
3606 } | 3611 } |
3607 | 3612 |
3608 void Class::set_constants(const Array& value) const { | 3613 void Class::set_constants(const Array& value) const { |
3609 ASSERT(!value.IsNull()); | 3614 ASSERT(!value.IsNull()); |
3610 StorePointer(&raw_ptr()->constants_, value.raw()); | 3615 StorePointer(&raw_ptr()->constants_, value.raw()); |
3611 } | 3616 } |
3612 | 3617 |
3613 | 3618 |
3614 RawObject* Class::canonical_types() const { | 3619 RawType* Class::canonical_type() const { |
3615 return raw_ptr()->canonical_types_; | 3620 return raw_ptr()->canonical_type_; |
3616 } | 3621 } |
3617 | 3622 |
3618 | 3623 |
3619 void Class::set_canonical_types(const Object& value) const { | 3624 void Class::set_canonical_type(const Type& value) const { |
3620 ASSERT(!value.IsNull()); | 3625 ASSERT(!value.IsNull()); |
3621 StorePointer(&raw_ptr()->canonical_types_, value.raw()); | 3626 StorePointer(&raw_ptr()->canonical_type_, value.raw()); |
3622 } | 3627 } |
3623 | 3628 |
3624 | 3629 |
3625 RawType* Class::CanonicalType() const { | 3630 RawType* Class::CanonicalType() const { |
3626 if (!IsGeneric() && !IsClosureClass()) { | 3631 return raw_ptr()->canonical_type_; |
3627 return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_); | |
3628 } | |
3629 Array& types = Array::Handle(); | |
3630 types ^= canonical_types(); | |
3631 if (!types.IsNull() && (types.Length() > 0)) { | |
3632 return reinterpret_cast<RawType*>(types.At(0)); | |
3633 } | |
3634 return reinterpret_cast<RawType*>(Object::null()); | |
3635 } | 3632 } |
3636 | 3633 |
3637 | 3634 |
3638 void Class::SetCanonicalType(const Type& type) const { | 3635 void Class::SetCanonicalType(const Type& type) const { |
3639 ASSERT(type.IsCanonical()); | 3636 ASSERT((canonical_type() == Object::null()) || |
3640 if (!IsGeneric() && !IsClosureClass()) { | 3637 (canonical_type() == type.raw())); // Set during own finalization. |
3641 ASSERT((canonical_types() == Object::null()) || | 3638 set_canonical_type(type); |
3642 (canonical_types() == type.raw())); // Set during own finalization. | |
3643 set_canonical_types(type); | |
3644 } else { | |
3645 Array& types = Array::Handle(); | |
3646 types ^= canonical_types(); | |
3647 ASSERT(!types.IsNull() && (types.Length() > 1)); | |
3648 ASSERT((types.At(0) == Object::null()) || (types.At(0) == type.raw())); | |
3649 types.SetAt(0, type); | |
3650 // Makes sure that 'canonical_types' has not changed. | |
3651 ASSERT(types.raw() == canonical_types()); | |
3652 } | |
3653 } | 3639 } |
3654 | 3640 |
3655 | 3641 |
3656 intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const { | |
3657 Thread* thread = Thread::Current(); | |
3658 if (EnsureIsFinalized(thread) != Error::null()) { | |
3659 return -1; | |
3660 } | |
3661 if (needle.raw() == CanonicalType()) { | |
3662 // For a generic type or signature type, there exists another index with the | |
3663 // same type. It will never be returned by this function. | |
3664 return 0; | |
3665 } | |
3666 REUSABLE_OBJECT_HANDLESCOPE(thread); | |
3667 Object& types = thread->ObjectHandle(); | |
3668 types = canonical_types(); | |
3669 if (types.IsNull()) { | |
3670 return -1; | |
3671 } | |
3672 const intptr_t len = Array::Cast(types).Length(); | |
3673 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread); | |
3674 AbstractType& type = thread->AbstractTypeHandle(); | |
3675 for (intptr_t i = 0; i < len; i++) { | |
3676 type ^= Array::Cast(types).At(i); | |
3677 if (needle.raw() == type.raw()) { | |
3678 return i; | |
3679 } | |
3680 } | |
3681 // No type found. | |
3682 return -1; | |
3683 } | |
3684 | |
3685 | |
3686 RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const { | |
3687 AbstractType& type = AbstractType::Handle(); | |
3688 if (idx == 0) { | |
3689 type = CanonicalType(); | |
3690 if (!type.IsNull()) { | |
3691 return type.raw(); | |
3692 } | |
3693 } | |
3694 Object& types = Object::Handle(canonical_types()); | |
3695 if (types.IsNull() || !types.IsArray()) { | |
3696 return Type::null(); | |
3697 } | |
3698 if ((idx < 0) || (idx >= Array::Cast(types).Length())) { | |
3699 return Type::null(); | |
3700 } | |
3701 type ^= Array::Cast(types).At(idx); | |
3702 ASSERT(!type.IsNull()); | |
3703 return type.raw(); | |
3704 } | |
3705 | |
3706 | |
3707 void Class::set_allocation_stub(const Code& value) const { | 3642 void Class::set_allocation_stub(const Code& value) const { |
3708 // Never clear the stub as it may still be a target, but will be GC-d if | 3643 // Never clear the stub as it may still be a target, but will be GC-d if |
3709 // not referenced. | 3644 // not referenced. |
3710 ASSERT(!value.IsNull()); | 3645 ASSERT(!value.IsNull()); |
3711 ASSERT(raw_ptr()->allocation_stub_ == Code::null()); | 3646 ASSERT(raw_ptr()->allocation_stub_ == Code::null()); |
3712 StorePointer(&raw_ptr()->allocation_stub_, value.raw()); | 3647 StorePointer(&raw_ptr()->allocation_stub_, value.raw()); |
3713 } | 3648 } |
3714 | 3649 |
3715 | 3650 |
3716 void Class::DisableAllocationStub() const { | 3651 void Class::DisableAllocationStub() const { |
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4265 Zone* zone = Thread::Current()->zone(); | 4200 Zone* zone = Thread::Current()->zone(); |
4266 const Library& lib = Library::Handle(zone, library()); | 4201 const Library& lib = Library::Handle(zone, library()); |
4267 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); | 4202 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); |
4268 if (!obj.IsNull() && obj.IsLibraryPrefix()) { | 4203 if (!obj.IsNull() && obj.IsLibraryPrefix()) { |
4269 return LibraryPrefix::Cast(obj).raw(); | 4204 return LibraryPrefix::Cast(obj).raw(); |
4270 } | 4205 } |
4271 return LibraryPrefix::null(); | 4206 return LibraryPrefix::null(); |
4272 } | 4207 } |
4273 | 4208 |
4274 | 4209 |
4275 // Returns AbstractType::null() if type not found. Modifies index to the last | |
4276 // position looked up. | |
4277 RawAbstractType* Class::LookupCanonicalType( | |
4278 Zone* zone, const AbstractType& lookup_type, intptr_t* index) const { | |
4279 Array& canonical_types = Array::Handle(zone); | |
4280 canonical_types ^= this->canonical_types(); | |
4281 if (canonical_types.IsNull()) { | |
4282 return AbstractType::null(); | |
4283 } | |
4284 AbstractType& type = Type::Handle(zone); | |
4285 const intptr_t length = canonical_types.Length(); | |
4286 while (*index < length) { | |
4287 type ^= canonical_types.At(*index); | |
4288 if (type.IsNull()) { | |
4289 break; | |
4290 } | |
4291 ASSERT(type.IsFinalized()); | |
4292 if (lookup_type.Equals(type)) { | |
4293 ASSERT(type.IsCanonical()); | |
4294 return type.raw(); | |
4295 } | |
4296 *index = *index + 1; | |
4297 } | |
4298 return AbstractType::null(); | |
4299 } | |
4300 | |
4301 | |
4302 // Canonicalizing the type arguments may have changed the index, may have | |
4303 // grown the table, or may even have canonicalized this type. Therefore | |
4304 // conrtinue search for canonical type at the last index visited. | |
4305 RawAbstractType* Class::LookupOrAddCanonicalType( | |
4306 const AbstractType& lookup_type, intptr_t start_index) const { | |
4307 Thread* thread = Thread::Current(); | |
4308 Zone* zone = thread->zone(); | |
4309 Isolate* isolate = thread->isolate(); | |
4310 AbstractType& type = Type::Handle(zone); | |
4311 intptr_t index = start_index; | |
4312 type ^= LookupCanonicalType(zone, lookup_type, &index); | |
4313 | |
4314 if (!type.IsNull()) { | |
4315 return type.raw(); | |
4316 } | |
4317 { | |
4318 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); | |
4319 // Lookup again, in case the canonicalization array changed. | |
4320 Array& canonical_types = Array::Handle(zone); | |
4321 canonical_types ^= this->canonical_types(); | |
4322 if (canonical_types.IsNull()) { | |
4323 canonical_types = empty_array().raw(); | |
4324 } | |
4325 const intptr_t length = canonical_types.Length(); | |
4326 // Start looking after previously looked up last position ('length'). | |
4327 type ^= LookupCanonicalType(zone, lookup_type, &index); | |
4328 if (!type.IsNull()) { | |
4329 return type.raw(); | |
4330 } | |
4331 | |
4332 // 'lookup_type' is not canonicalized yet. | |
4333 lookup_type.SetCanonical(); | |
4334 | |
4335 // The type needs to be added to the list. Grow the list if it is full. | |
4336 if (index >= length) { | |
4337 ASSERT((index == length) || ((index == 1) && (length == 0))); | |
4338 const intptr_t new_length = (length > 64) ? | |
4339 (length + 64) : | |
4340 ((length == 0) ? 2 : (length * 2)); | |
4341 const Array& new_canonical_types = Array::Handle( | |
4342 zone, Array::Grow(canonical_types, new_length, Heap::kOld)); | |
4343 new_canonical_types.SetAt(index, lookup_type); | |
4344 this->set_canonical_types(new_canonical_types); | |
4345 } else { | |
4346 canonical_types.SetAt(index, lookup_type); | |
4347 } | |
4348 } | |
4349 return lookup_type.raw(); | |
4350 } | |
4351 | |
4352 | |
4353 const char* Class::ToCString() const { | 4210 const char* Class::ToCString() const { |
4354 const Library& lib = Library::Handle(library()); | 4211 const Library& lib = Library::Handle(library()); |
4355 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); | 4212 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); |
4356 const char* patch_prefix = is_patch() ? "Patch " : ""; | 4213 const char* patch_prefix = is_patch() ? "Patch " : ""; |
4357 const char* class_name = String::Handle(Name()).ToCString(); | 4214 const char* class_name = String::Handle(Name()).ToCString(); |
4358 return OS::SCreate(Thread::Current()->zone(), | 4215 return OS::SCreate(Thread::Current()->zone(), |
4359 "%s %sClass: %s", library_name, patch_prefix, class_name); | 4216 "%s %sClass: %s", library_name, patch_prefix, class_name); |
4360 } | 4217 } |
4361 | 4218 |
4362 | 4219 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4620 | 4477 |
4621 | 4478 |
4622 static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) { | 4479 static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) { |
4623 hash += other_hash; | 4480 hash += other_hash; |
4624 hash += hash << 10; | 4481 hash += hash << 10; |
4625 hash ^= hash >> 6; // Logical shift, unsigned hash. | 4482 hash ^= hash >> 6; // Logical shift, unsigned hash. |
4626 return hash; | 4483 return hash; |
4627 } | 4484 } |
4628 | 4485 |
4629 | 4486 |
4630 static uint32_t FinalizeHash(uint32_t hash) { | 4487 static uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits) { |
4631 hash += hash << 3; | 4488 hash += hash << 3; |
4632 hash ^= hash >> 11; // Logical shift, unsigned hash. | 4489 hash ^= hash >> 11; // Logical shift, unsigned hash. |
4633 hash += hash << 15; | 4490 hash += hash << 15; |
4634 return hash; | 4491 hash &= ((static_cast<intptr_t>(1) << hashbits) - 1); |
4492 return (hash == 0) ? 1 : hash; | |
4635 } | 4493 } |
4636 | 4494 |
4637 | 4495 |
4638 intptr_t TypeArguments::Hash() const { | 4496 intptr_t TypeArguments::ComputeHash() const { |
4639 if (IsNull()) return 0; | 4497 if (IsNull()) return 0; |
4640 const intptr_t num_types = Length(); | 4498 const intptr_t num_types = Length(); |
4641 if (IsRaw(0, num_types)) return 0; | 4499 if (IsRaw(0, num_types)) return 0; |
4642 uint32_t result = 0; | 4500 uint32_t result = 0; |
4643 AbstractType& type = AbstractType::Handle(); | 4501 AbstractType& type = AbstractType::Handle(); |
4644 for (intptr_t i = 0; i < num_types; i++) { | 4502 for (intptr_t i = 0; i < num_types; i++) { |
4645 type = TypeAt(i); | 4503 type = TypeAt(i); |
4646 // The hash may be calculated during type finalization (for debugging | 4504 // The hash may be calculated during type finalization (for debugging |
4647 // purposes only) while a type argument is still temporarily null. | 4505 // purposes only) while a type argument is still temporarily null. |
4648 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); | 4506 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); |
4649 } | 4507 } |
4650 return FinalizeHash(result); | 4508 result = FinalizeHash(result, kHashBits); |
4509 SetHash(result); | |
4510 return result; | |
4651 } | 4511 } |
4652 | 4512 |
4653 | 4513 |
4654 RawString* TypeArguments::SubvectorName(intptr_t from_index, | 4514 RawString* TypeArguments::SubvectorName(intptr_t from_index, |
4655 intptr_t len, | 4515 intptr_t len, |
4656 NameVisibility name_visibility) const { | 4516 NameVisibility name_visibility) const { |
4657 Thread* thread = Thread::Current(); | 4517 Thread* thread = Thread::Current(); |
4658 Zone* zone = thread->zone(); | 4518 Zone* zone = thread->zone(); |
4659 ASSERT(from_index + len <= Length()); | 4519 ASSERT(from_index + len <= Length()); |
4660 String& name = String::Handle(zone); | 4520 String& name = String::Handle(zone); |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5091 } | 4951 } |
5092 TypeArguments& result = TypeArguments::Handle(); | 4952 TypeArguments& result = TypeArguments::Handle(); |
5093 { | 4953 { |
5094 RawObject* raw = Object::Allocate(TypeArguments::kClassId, | 4954 RawObject* raw = Object::Allocate(TypeArguments::kClassId, |
5095 TypeArguments::InstanceSize(len), | 4955 TypeArguments::InstanceSize(len), |
5096 space); | 4956 space); |
5097 NoSafepointScope no_safepoint; | 4957 NoSafepointScope no_safepoint; |
5098 result ^= raw; | 4958 result ^= raw; |
5099 // Length must be set before we start storing into the array. | 4959 // Length must be set before we start storing into the array. |
5100 result.SetLength(len); | 4960 result.SetLength(len); |
4961 result.SetHash(0); | |
5101 } | 4962 } |
5102 // The zero array should have been initialized. | 4963 // The zero array should have been initialized. |
5103 ASSERT(Object::zero_array().raw() != Array::null()); | 4964 ASSERT(Object::zero_array().raw() != Array::null()); |
5104 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); | 4965 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); |
5105 result.set_instantiations(Object::zero_array()); | 4966 result.set_instantiations(Object::zero_array()); |
5106 return result.raw(); | 4967 return result.raw(); |
5107 } | 4968 } |
5108 | 4969 |
5109 | 4970 |
5110 | 4971 |
5111 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { | 4972 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { |
5112 // TODO(iposva): Determine if we should throw an exception here. | 4973 // TODO(iposva): Determine if we should throw an exception here. |
5113 ASSERT((index >= 0) && (index < Length())); | 4974 ASSERT((index >= 0) && (index < Length())); |
5114 return &raw_ptr()->types()[index]; | 4975 return &raw_ptr()->types()[index]; |
5115 } | 4976 } |
5116 | 4977 |
5117 | 4978 |
5118 void TypeArguments::SetLength(intptr_t value) const { | 4979 void TypeArguments::SetLength(intptr_t value) const { |
5119 ASSERT(!IsCanonical()); | 4980 ASSERT(!IsCanonical()); |
5120 // This is only safe because we create a new Smi, which does not cause | 4981 // This is only safe because we create a new Smi, which does not cause |
5121 // heap allocation. | 4982 // heap allocation. |
5122 StoreSmi(&raw_ptr()->length_, Smi::New(value)); | 4983 StoreSmi(&raw_ptr()->length_, Smi::New(value)); |
5123 } | 4984 } |
5124 | 4985 |
5125 | 4986 |
5126 static void GrowCanonicalTypeArguments(Thread* thread, const Array& table) { | |
5127 Isolate* isolate = thread->isolate(); | |
5128 Zone* zone = thread->zone(); | |
5129 // Last element of the array is the number of used elements. | |
5130 const intptr_t table_size = table.Length() - 1; | |
5131 const intptr_t new_table_size = table_size * 2; | |
5132 Array& new_table = Array::Handle(zone, Array::New(new_table_size + 1)); | |
5133 // Copy all elements from the original table to the newly allocated | |
5134 // array. | |
5135 TypeArguments& element = TypeArguments::Handle(zone); | |
5136 Object& new_element = Object::Handle(zone); | |
5137 for (intptr_t i = 0; i < table_size; i++) { | |
5138 element ^= table.At(i); | |
5139 if (!element.IsNull()) { | |
5140 const intptr_t hash = element.Hash(); | |
5141 ASSERT(Utils::IsPowerOfTwo(new_table_size)); | |
5142 intptr_t index = hash & (new_table_size - 1); | |
5143 new_element = new_table.At(index); | |
5144 while (!new_element.IsNull()) { | |
5145 index = (index + 1) & (new_table_size - 1); // Move to next element. | |
5146 new_element = new_table.At(index); | |
5147 } | |
5148 new_table.SetAt(index, element); | |
5149 } | |
5150 } | |
5151 // Copy used count. | |
5152 new_element = table.At(table_size); | |
5153 new_table.SetAt(new_table_size, new_element); | |
5154 // Remember the new table now. | |
5155 isolate->object_store()->set_canonical_type_arguments(new_table); | |
5156 } | |
5157 | |
5158 | |
5159 static void InsertIntoCanonicalTypeArguments(Thread* thread, | |
5160 const Array& table, | |
5161 const TypeArguments& arguments, | |
5162 intptr_t index) { | |
5163 Zone* zone = thread->zone(); | |
5164 arguments.SetCanonical(); // Mark object as being canonical. | |
5165 table.SetAt(index, arguments); // Remember the new element. | |
5166 // Update used count. | |
5167 // Last element of the array is the number of used elements. | |
5168 const intptr_t table_size = table.Length() - 1; | |
5169 const intptr_t used_elements = | |
5170 Smi::Value(Smi::RawCast(table.At(table_size))) + 1; | |
5171 const Smi& used = Smi::Handle(zone, Smi::New(used_elements)); | |
5172 table.SetAt(table_size, used); | |
5173 | |
5174 #ifdef DEBUG | |
5175 // Verify that there are no duplicates. | |
5176 // Duplicates could appear if hash values are not kept constant across | |
5177 // snapshots, e.g. if class ids are not preserved by the snapshots. | |
5178 TypeArguments& other_arguments = TypeArguments::Handle(); | |
5179 for (intptr_t i = 0; i < table_size; i++) { | |
5180 if ((i != index) && (table.At(i) != TypeArguments::null())) { | |
5181 other_arguments ^= table.At(i); | |
5182 if (arguments.Equals(other_arguments)) { | |
5183 // Recursive types may be equal, but have different hashes. | |
5184 ASSERT(arguments.IsRecursive()); | |
5185 ASSERT(other_arguments.IsRecursive()); | |
5186 ASSERT(arguments.Hash() != other_arguments.Hash()); | |
5187 } | |
5188 } | |
5189 } | |
5190 #endif | |
5191 | |
5192 // Rehash if table is 75% full. | |
5193 if (used_elements > ((table_size / 4) * 3)) { | |
5194 GrowCanonicalTypeArguments(thread, table); | |
5195 } | |
5196 } | |
5197 | |
5198 | |
5199 static intptr_t FindIndexInCanonicalTypeArguments( | |
5200 Zone* zone, | |
5201 const Array& table, | |
5202 const TypeArguments& arguments, | |
5203 intptr_t hash) { | |
5204 // Last element of the array is the number of used elements. | |
5205 const intptr_t table_size = table.Length() - 1; | |
5206 ASSERT(Utils::IsPowerOfTwo(table_size)); | |
5207 intptr_t index = hash & (table_size - 1); | |
5208 | |
5209 TypeArguments& current = TypeArguments::Handle(zone); | |
5210 current ^= table.At(index); | |
5211 while (!current.IsNull() && !current.Equals(arguments)) { | |
5212 index = (index + 1) & (table_size - 1); // Move to next element. | |
5213 current ^= table.At(index); | |
5214 } | |
5215 return index; // Index of element if found or slot into which to add it. | |
5216 } | |
5217 | |
5218 | |
5219 RawTypeArguments* TypeArguments::CloneUnfinalized() const { | 4987 RawTypeArguments* TypeArguments::CloneUnfinalized() const { |
5220 if (IsNull() || IsFinalized()) { | 4988 if (IsNull() || IsFinalized()) { |
5221 return raw(); | 4989 return raw(); |
5222 } | 4990 } |
5223 ASSERT(IsResolved()); | 4991 ASSERT(IsResolved()); |
5224 AbstractType& type = AbstractType::Handle(); | 4992 AbstractType& type = AbstractType::Handle(); |
5225 const intptr_t num_types = Length(); | 4993 const intptr_t num_types = Length(); |
5226 const TypeArguments& clone = TypeArguments::Handle( | 4994 const TypeArguments& clone = TypeArguments::Handle( |
5227 TypeArguments::New(num_types)); | 4995 TypeArguments::New(num_types)); |
5228 for (intptr_t i = 0; i < num_types; i++) { | 4996 for (intptr_t i = 0; i < num_types; i++) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5263 return this->raw(); | 5031 return this->raw(); |
5264 } | 5032 } |
5265 const intptr_t num_types = Length(); | 5033 const intptr_t num_types = Length(); |
5266 if (IsRaw(0, num_types)) { | 5034 if (IsRaw(0, num_types)) { |
5267 return TypeArguments::null(); | 5035 return TypeArguments::null(); |
5268 } | 5036 } |
5269 Thread* thread = Thread::Current(); | 5037 Thread* thread = Thread::Current(); |
5270 Zone* zone = thread->zone(); | 5038 Zone* zone = thread->zone(); |
5271 Isolate* isolate = thread->isolate(); | 5039 Isolate* isolate = thread->isolate(); |
5272 ObjectStore* object_store = isolate->object_store(); | 5040 ObjectStore* object_store = isolate->object_store(); |
5273 Array& table = Array::Handle(zone, | |
5274 object_store->canonical_type_arguments()); | |
5275 // Last element of the array is the number of used elements. | |
5276 const intptr_t num_used = | |
5277 Smi::Value(Smi::RawCast(table.At(table.Length() - 1))); | |
5278 const intptr_t hash = Hash(); | |
5279 intptr_t index = FindIndexInCanonicalTypeArguments(zone, table, *this, hash); | |
5280 TypeArguments& result = TypeArguments::Handle(zone); | 5041 TypeArguments& result = TypeArguments::Handle(zone); |
5281 result ^= table.At(index); | 5042 { |
5043 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); | |
5044 CanonicalTypeArgumentsSet table(zone, | |
5045 object_store->canonical_type_arguments()); | |
5046 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this)); | |
5047 object_store->set_canonical_type_arguments(table.Release()); | |
5048 } | |
5282 if (result.IsNull()) { | 5049 if (result.IsNull()) { |
5283 // Canonicalize each type argument. | 5050 // Canonicalize each type argument. |
5284 AbstractType& type_arg = AbstractType::Handle(zone); | 5051 AbstractType& type_arg = AbstractType::Handle(zone); |
5285 for (intptr_t i = 0; i < num_types; i++) { | 5052 for (intptr_t i = 0; i < num_types; i++) { |
5286 type_arg = TypeAt(i); | 5053 type_arg = TypeAt(i); |
5287 type_arg = type_arg.Canonicalize(trail); | 5054 type_arg = type_arg.Canonicalize(trail); |
5288 if (IsCanonical()) { | 5055 if (IsCanonical()) { |
5289 // Canonicalizing this type_arg canonicalized this type. | 5056 // Canonicalizing this type_arg canonicalized this type. |
5290 ASSERT(IsRecursive()); | 5057 ASSERT(IsRecursive()); |
5291 return this->raw(); | 5058 return this->raw(); |
5292 } | 5059 } |
5293 SetTypeAt(i, type_arg); | 5060 SetTypeAt(i, type_arg); |
5294 } | 5061 } |
5295 // Canonicalization of a recursive type may change its hash. | 5062 // Canonicalization of a type argument of a recursive type argument vector |
5296 intptr_t canonical_hash = hash; | 5063 // may change the hash of the vector, so recompute. |
5297 if (IsRecursive()) { | 5064 if (IsRecursive()) { |
5298 canonical_hash = Hash(); | 5065 ComputeHash(); |
5299 } | 5066 } |
5300 // Canonicalization of the type argument's own type arguments may add an | 5067 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
5301 // entry to the table, or even grow the table, and thereby change the | 5068 CanonicalTypeArgumentsSet table( |
5302 // previously calculated index. | 5069 zone, object_store->canonical_type_arguments()); |
5303 table = object_store->canonical_type_arguments(); | 5070 // Since we canonicalized some type arguments above we need to lookup |
5304 if ((canonical_hash != hash) || | 5071 // in the table again to make sure we don't already have an equivalent |
5305 (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used)) { | 5072 // canonical entry. |
5306 index = FindIndexInCanonicalTypeArguments( | 5073 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this)); |
5307 zone, table, *this, canonical_hash); | |
5308 result ^= table.At(index); | |
5309 } | |
5310 if (result.IsNull()) { | 5074 if (result.IsNull()) { |
5311 // Make sure we have an old space object and add it to the table. | 5075 // Make sure we have an old space object and add it to the table. |
5312 if (this->IsNew()) { | 5076 if (this->IsNew()) { |
5313 result ^= Object::Clone(*this, Heap::kOld); | 5077 result ^= Object::Clone(*this, Heap::kOld); |
5314 } else { | 5078 } else { |
5315 result ^= this->raw(); | 5079 result ^= this->raw(); |
5316 } | 5080 } |
5317 ASSERT(result.IsOld()); | 5081 ASSERT(result.IsOld()); |
5318 InsertIntoCanonicalTypeArguments(thread, table, result, index); | 5082 result.SetCanonical(); // Mark object as being canonical. |
5083 // Now add this TypeArgument into the canonical list of type arguments. | |
5084 bool present = table.Insert(result); | |
5085 ASSERT(!present); | |
5319 } | 5086 } |
5087 object_store->set_canonical_type_arguments(table.Release()); | |
5320 } | 5088 } |
5321 ASSERT(result.Equals(*this)); | 5089 ASSERT(result.Equals(*this)); |
5322 ASSERT(!result.IsNull()); | 5090 ASSERT(!result.IsNull()); |
5323 ASSERT(result.IsTypeArguments()); | 5091 ASSERT(result.IsTypeArguments()); |
5324 ASSERT(result.IsCanonical()); | 5092 ASSERT(result.IsCanonical()); |
5325 return result.raw(); | 5093 return result.raw(); |
5326 } | 5094 } |
5327 | 5095 |
5328 | 5096 |
5329 RawString* TypeArguments::EnumerateURIs() const { | 5097 RawString* TypeArguments::EnumerateURIs() const { |
(...skipping 10 matching lines...) Expand all Loading... | |
5340 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); | 5108 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); |
5341 } | 5109 } |
5342 return String::ConcatAll(pieces); | 5110 return String::ConcatAll(pieces); |
5343 } | 5111 } |
5344 | 5112 |
5345 | 5113 |
5346 const char* TypeArguments::ToCString() const { | 5114 const char* TypeArguments::ToCString() const { |
5347 if (IsNull()) { | 5115 if (IsNull()) { |
5348 return "NULL TypeArguments"; | 5116 return "NULL TypeArguments"; |
5349 } | 5117 } |
5350 const char* prev_cstr = "TypeArguments:"; | 5118 Zone* zone = Thread::Current()->zone(); |
5119 const char* prev_cstr = OS::SCreate( | |
5120 zone, "TypeArguments: (%" Pd ")", Smi::Value(raw_ptr()->hash_)); | |
5351 for (int i = 0; i < Length(); i++) { | 5121 for (int i = 0; i < Length(); i++) { |
5352 const AbstractType& type_at = AbstractType::Handle(TypeAt(i)); | 5122 const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i)); |
5353 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); | 5123 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); |
5354 char* chars = OS::SCreate(Thread::Current()->zone(), | 5124 char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr); |
5355 "%s [%s]", prev_cstr, type_cstr); | |
5356 prev_cstr = chars; | 5125 prev_cstr = chars; |
5357 } | 5126 } |
5358 return prev_cstr; | 5127 return prev_cstr; |
5359 } | 5128 } |
5360 | 5129 |
5361 | 5130 |
5362 const char* PatchClass::ToCString() const { | 5131 const char* PatchClass::ToCString() const { |
5363 const Class& cls = Class::Handle(patched_class()); | 5132 const Class& cls = Class::Handle(patched_class()); |
5364 const char* cls_name = cls.ToCString(); | 5133 const char* cls_name = cls.ToCString(); |
5365 return OS::SCreate(Thread::Current()->zone(), | 5134 return OS::SCreate(Thread::Current()->zone(), |
(...skipping 4001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9367 // Called when growing the table. | 9136 // Called when growing the table. |
9368 static bool IsMatch(const Object& a, const Object& b) { | 9137 static bool IsMatch(const Object& a, const Object& b) { |
9369 ASSERT(a.IsLibrary() && b.IsLibrary()); | 9138 ASSERT(a.IsLibrary() && b.IsLibrary()); |
9370 // Library objects are always canonical. | 9139 // Library objects are always canonical. |
9371 return a.raw() == b.raw(); | 9140 return a.raw() == b.raw(); |
9372 } | 9141 } |
9373 static uword Hash(const Object& key) { | 9142 static uword Hash(const Object& key) { |
9374 return Library::Cast(key).UrlHash(); | 9143 return Library::Cast(key).UrlHash(); |
9375 } | 9144 } |
9376 }; | 9145 }; |
9377 | |
9378 | |
9379 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; | 9146 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; |
9380 | 9147 |
9381 | 9148 |
9382 RawInstance* Library::TransitiveLoadError() const { | 9149 RawInstance* Library::TransitiveLoadError() const { |
9383 if (LoadError() != Instance::null()) { | 9150 if (LoadError() != Instance::null()) { |
9384 return LoadError(); | 9151 return LoadError(); |
9385 } | 9152 } |
9386 Thread* thread = Thread::Current(); | 9153 Thread* thread = Thread::Current(); |
9387 Isolate* isolate = thread->isolate(); | 9154 Isolate* isolate = thread->isolate(); |
9388 Zone* zone = thread->zone(); | 9155 Zone* zone = thread->zone(); |
(...skipping 5718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15107 ASSERT(instance_size != 0); | 14874 ASSERT(instance_size != 0); |
15108 uword hash = instance_size; | 14875 uword hash = instance_size; |
15109 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | 14876 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
15110 for (intptr_t offset = Instance::NextFieldOffset(); | 14877 for (intptr_t offset = Instance::NextFieldOffset(); |
15111 offset < instance_size; | 14878 offset < instance_size; |
15112 offset += kWordSize) { | 14879 offset += kWordSize) { |
15113 uword value = reinterpret_cast<uword>( | 14880 uword value = reinterpret_cast<uword>( |
15114 *reinterpret_cast<RawObject**>(this_addr + offset)); | 14881 *reinterpret_cast<RawObject**>(this_addr + offset)); |
15115 hash = CombineHashes(hash, value); | 14882 hash = CombineHashes(hash, value); |
15116 } | 14883 } |
15117 return FinalizeHash(hash); | 14884 return FinalizeHash(hash, (kBitsPerWord - 1)); |
15118 } | 14885 } |
15119 | 14886 |
15120 | 14887 |
15121 #if defined(DEBUG) | 14888 #if defined(DEBUG) |
15122 class CheckForPointers : public ObjectPointerVisitor { | 14889 class CheckForPointers : public ObjectPointerVisitor { |
15123 public: | 14890 public: |
15124 explicit CheckForPointers(Isolate* isolate) | 14891 explicit CheckForPointers(Isolate* isolate) |
15125 : ObjectPointerVisitor(isolate), has_pointers_(false) {} | 14892 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
15126 | 14893 |
15127 bool has_pointers() const { return has_pointers_; } | 14894 bool has_pointers() const { return has_pointers_; } |
(...skipping 1753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16881 | 16648 |
16882 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { | 16649 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { |
16883 ASSERT(IsFinalized()); | 16650 ASSERT(IsFinalized()); |
16884 if (IsCanonical() || IsMalformed()) { | 16651 if (IsCanonical() || IsMalformed()) { |
16885 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); | 16652 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); |
16886 return this->raw(); | 16653 return this->raw(); |
16887 } | 16654 } |
16888 Thread* thread = Thread::Current(); | 16655 Thread* thread = Thread::Current(); |
16889 Zone* zone = thread->zone(); | 16656 Zone* zone = thread->zone(); |
16890 Isolate* isolate = thread->isolate(); | 16657 Isolate* isolate = thread->isolate(); |
16891 AbstractType& type = Type::Handle(zone); | 16658 |
16892 const Class& cls = Class::Handle(zone, type_class()); | |
16893 // Since void is a keyword, we never have to canonicalize the void type after | 16659 // Since void is a keyword, we never have to canonicalize the void type after |
16894 // it is canonicalized once by the vm isolate. The parser does the mapping. | 16660 // it is canonicalized once by the vm isolate. The parser does the mapping. |
16895 ASSERT((cls.raw() != Object::void_class()) || | 16661 ASSERT((type_class() != Object::void_class()) || |
16896 (isolate == Dart::vm_isolate())); | 16662 (isolate == Dart::vm_isolate())); |
16663 | |
16897 // Since dynamic is not a keyword, the parser builds a type that requires | 16664 // Since dynamic is not a keyword, the parser builds a type that requires |
16898 // canonicalization. | 16665 // canonicalization. |
16899 if ((cls.raw() == Object::dynamic_class()) && | 16666 if ((type_class() == Object::dynamic_class()) && |
16900 (isolate != Dart::vm_isolate())) { | 16667 (isolate != Dart::vm_isolate())) { |
16901 ASSERT(Object::dynamic_type().IsCanonical()); | 16668 ASSERT(Object::dynamic_type().IsCanonical()); |
16902 return Object::dynamic_type().raw(); | 16669 return Object::dynamic_type().raw(); |
16903 } | 16670 } |
16671 | |
16672 AbstractType& type = Type::Handle(zone); | |
16673 const Class& cls = Class::Handle(zone, type_class()); | |
16674 | |
16904 // Fast canonical lookup/registry for simple types. | 16675 // Fast canonical lookup/registry for simple types. |
16905 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { | 16676 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { |
16906 ASSERT(!IsFunctionType()); | 16677 ASSERT(!IsFunctionType()); |
16907 type = cls.CanonicalType(); | 16678 type = cls.CanonicalType(); |
16908 if (type.IsNull()) { | 16679 if (type.IsNull()) { |
16909 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); | 16680 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); |
16910 // Canonicalize the type arguments of the supertype, if any. | 16681 // Canonicalize the type arguments of the supertype, if any. |
16911 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 16682 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
16912 type_args = type_args.Canonicalize(trail); | 16683 type_args = type_args.Canonicalize(trail); |
16913 if (IsCanonical()) { | 16684 if (IsCanonical()) { |
16914 // Canonicalizing type_args canonicalized this type. | 16685 // Canonicalizing type_args canonicalized this type. |
16915 ASSERT(IsRecursive()); | 16686 ASSERT(IsRecursive()); |
16916 return this->raw(); | 16687 return this->raw(); |
16917 } | 16688 } |
16918 set_arguments(type_args); | 16689 set_arguments(type_args); |
16919 type = cls.CanonicalType(); // May be set while canonicalizing type args. | 16690 type = cls.CanonicalType(); // May be set while canonicalizing type args. |
16920 if (type.IsNull()) { | 16691 if (type.IsNull()) { |
16921 MutexLocker ml(isolate->type_canonicalization_mutex()); | 16692 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
16922 // Recheck if type exists. | 16693 // Recheck if type exists. |
16923 type = cls.CanonicalType(); | 16694 type = cls.CanonicalType(); |
16924 if (type.IsNull()) { | 16695 if (type.IsNull()) { |
16696 ComputeHash(); | |
16925 SetCanonical(); | 16697 SetCanonical(); |
16926 cls.set_canonical_types(*this); | 16698 cls.set_canonical_type(*this); |
16927 return this->raw(); | 16699 return this->raw(); |
16928 } | 16700 } |
16929 } | 16701 } |
16930 } | 16702 } |
16931 ASSERT(this->Equals(type)); | 16703 ASSERT(this->Equals(type)); |
16932 ASSERT(type.IsCanonical()); | 16704 ASSERT(type.IsCanonical()); |
16933 return type.raw(); | 16705 return type.raw(); |
16934 } | 16706 } |
16935 | 16707 |
16936 Array& canonical_types = Array::Handle(zone); | 16708 ObjectStore* object_store = isolate->object_store(); |
16937 canonical_types ^= cls.canonical_types(); | 16709 { |
16938 if (canonical_types.IsNull()) { | 16710 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
16939 canonical_types = empty_array().raw(); | 16711 CanonicalTypeSet table(zone, object_store->canonical_types()); |
16712 type ^= table.GetOrNull(CanonicalTypeKey(*this)); | |
16713 object_store->set_canonical_types(table.Release()); | |
16940 } | 16714 } |
16941 intptr_t length = canonical_types.Length(); | 16715 if (type.IsNull()) { |
16942 // Linear search to see whether this type is already present in the | 16716 // The type was not found in the table. It is not canonical yet. |
16943 // list of canonicalized types. | 16717 |
16944 // TODO(asiva): Try to re-factor this lookup code to make sharing | 16718 // Canonicalize the type arguments. |
16945 // easy between the 4 versions of this loop. | 16719 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
16946 intptr_t index = 1; // Slot 0 is reserved for CanonicalType(). | 16720 // In case the type is first canonicalized at runtime, its type argument |
16947 while (index < length) { | 16721 // vector may be longer than necessary. This is not an issue. |
16948 type ^= canonical_types.At(index); | 16722 ASSERT(type_args.IsNull() || |
16723 (type_args.Length() >= cls.NumTypeArguments())); | |
16724 type_args = type_args.Canonicalize(trail); | |
16725 if (IsCanonical()) { | |
16726 // Canonicalizing type_args canonicalized this type as a side effect. | |
16727 ASSERT(IsRecursive()); | |
16728 // Cycles via typedefs are detected and disallowed, but a function type | |
16729 // can be recursive due to a cycle in its type arguments. | |
16730 return this->raw(); | |
16731 } | |
16732 set_arguments(type_args); | |
16733 ASSERT(type_args.IsNull() || type_args.IsOld()); | |
16734 | |
16735 // In case of a function type, replace the actual function by a signature | |
16736 // function. | |
16737 if (IsFunctionType()) { | |
16738 const Function& fun = Function::Handle(zone, signature()); | |
16739 if (!fun.IsSignatureFunction()) { | |
16740 Function& sig_fun = Function::Handle( | |
16741 zone, | |
16742 Function::NewSignatureFunction(cls, TokenPosition::kNoSource)); | |
16743 type = fun.result_type(); | |
16744 type = type.Canonicalize(trail); | |
16745 sig_fun.set_result_type(type); | |
16746 const intptr_t num_params = fun.NumParameters(); | |
16747 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters()); | |
16748 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(), | |
16749 fun.HasOptionalPositionalParameters()); | |
16750 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params, | |
16751 Heap::kOld))); | |
16752 for (intptr_t i = 0; i < num_params; i++) { | |
16753 type = fun.ParameterTypeAt(i); | |
16754 type = type.Canonicalize(trail); | |
16755 sig_fun.SetParameterTypeAt(i, type); | |
16756 } | |
16757 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names())); | |
16758 set_signature(sig_fun); | |
16759 } | |
16760 } | |
16761 | |
16762 // Check to see if the type got added to canonical list as part of the | |
16763 // type arguments canonicalization. | |
16764 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); | |
16765 CanonicalTypeSet table(zone, object_store->canonical_types()); | |
16766 type ^= table.GetOrNull(CanonicalTypeKey(*this)); | |
16949 if (type.IsNull()) { | 16767 if (type.IsNull()) { |
16950 break; | 16768 // Add this Type into the canonical list of types. |
16769 type ^= raw(); | |
16770 ASSERT(type.IsOld()); | |
16771 type.SetCanonical(); // Mark object as being canonical. | |
16772 bool present = table.Insert(type); | |
16773 ASSERT(!present); | |
16951 } | 16774 } |
16952 ASSERT(type.IsFinalized()); | 16775 object_store->set_canonical_types(table.Release()); |
16953 if (this->Equals(type)) { | |
16954 ASSERT(type.IsCanonical()); | |
16955 return type.raw(); | |
16956 } | |
16957 index++; | |
16958 } | 16776 } |
16959 // The type was not found in the table. It is not canonical yet. | 16777 return type.raw(); |
16960 | |
16961 // Canonicalize the type arguments. | |
16962 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | |
16963 // In case the type is first canonicalized at runtime, its type argument | |
16964 // vector may be longer than necessary. This is not an issue. | |
16965 ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments())); | |
16966 type_args = type_args.Canonicalize(trail); | |
16967 if (IsCanonical()) { | |
16968 // Canonicalizing type_args canonicalized this type as a side effect. | |
16969 ASSERT(IsRecursive()); | |
16970 // Cycles via typedefs are detected and disallowed, but a function type can | |
16971 // be recursive due to a cycle in its type arguments. | |
16972 return this->raw(); | |
16973 } | |
16974 set_arguments(type_args); | |
16975 ASSERT(type_args.IsNull() || type_args.IsOld()); | |
16976 | |
16977 // In case of a function type, replace the actual function by a signature | |
16978 // function. | |
16979 if (IsFunctionType()) { | |
16980 const Function& fun = Function::Handle(zone, signature()); | |
16981 if (!fun.IsSignatureFunction()) { | |
16982 Function& sig_fun = Function::Handle(zone, | |
16983 Function::NewSignatureFunction(cls, TokenPosition::kNoSource)); | |
16984 type = fun.result_type(); | |
16985 type = type.Canonicalize(trail); | |
16986 sig_fun.set_result_type(type); | |
16987 const intptr_t num_params = fun.NumParameters(); | |
16988 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters()); | |
16989 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(), | |
16990 fun.HasOptionalPositionalParameters()); | |
16991 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params, | |
16992 Heap::kOld))); | |
16993 for (intptr_t i = 0; i < num_params; i++) { | |
16994 type = fun.ParameterTypeAt(i); | |
16995 type = type.Canonicalize(trail); | |
16996 sig_fun.SetParameterTypeAt(i, type); | |
16997 } | |
16998 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names())); | |
16999 set_signature(sig_fun); | |
17000 } | |
17001 } | |
17002 return cls.LookupOrAddCanonicalType(*this, index); | |
17003 } | 16778 } |
17004 | 16779 |
17005 | 16780 |
17006 RawString* Type::EnumerateURIs() const { | 16781 RawString* Type::EnumerateURIs() const { |
17007 if (IsDynamicType() || IsVoidType()) { | 16782 if (IsDynamicType() || IsVoidType()) { |
17008 return Symbols::Empty().raw(); | 16783 return Symbols::Empty().raw(); |
17009 } | 16784 } |
17010 Thread* thread = Thread::Current(); | 16785 Thread* thread = Thread::Current(); |
17011 Zone* zone = thread->zone(); | 16786 Zone* zone = thread->zone(); |
17012 GrowableHandlePtrArray<const String> pieces(zone, 6); | 16787 GrowableHandlePtrArray<const String> pieces(zone, 6); |
(...skipping 20 matching lines...) Expand all Loading... | |
17033 const Library& library = Library::Handle(zone, cls.library()); | 16808 const Library& library = Library::Handle(zone, cls.library()); |
17034 pieces.Add(String::Handle(zone, library.url())); | 16809 pieces.Add(String::Handle(zone, library.url())); |
17035 pieces.Add(Symbols::NewLine()); | 16810 pieces.Add(Symbols::NewLine()); |
17036 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 16811 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
17037 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); | 16812 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); |
17038 } | 16813 } |
17039 return Symbols::FromConcatAll(thread, pieces); | 16814 return Symbols::FromConcatAll(thread, pieces); |
17040 } | 16815 } |
17041 | 16816 |
17042 | 16817 |
17043 intptr_t Type::Hash() const { | 16818 intptr_t Type::ComputeHash() const { |
17044 ASSERT(IsFinalized()); | 16819 ASSERT(IsFinalized()); |
17045 uint32_t result = 1; | 16820 uint32_t result = 1; |
17046 if (IsMalformed()) return result; | 16821 if (IsMalformed()) return result; |
17047 result = CombineHashes(result, Class::Handle(type_class()).id()); | 16822 result = CombineHashes(result, Class::Handle(type_class()).id()); |
17048 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); | 16823 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); |
17049 if (IsFunctionType()) { | 16824 if (IsFunctionType()) { |
17050 const Function& sig_fun = Function::Handle(signature()); | 16825 const Function& sig_fun = Function::Handle(signature()); |
17051 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); | 16826 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); |
17052 result = CombineHashes(result, type.Hash()); | 16827 result = CombineHashes(result, type.Hash()); |
17053 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); | 16828 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); |
17054 const intptr_t num_params = sig_fun.NumParameters(); | 16829 const intptr_t num_params = sig_fun.NumParameters(); |
17055 for (intptr_t i = 0; i < num_params; i++) { | 16830 for (intptr_t i = 0; i < num_params; i++) { |
17056 type = sig_fun.ParameterTypeAt(i); | 16831 type = sig_fun.ParameterTypeAt(i); |
17057 result = CombineHashes(result, type.Hash()); | 16832 result = CombineHashes(result, type.Hash()); |
17058 } | 16833 } |
17059 if (sig_fun.NumOptionalNamedParameters() > 0) { | 16834 if (sig_fun.NumOptionalNamedParameters() > 0) { |
17060 String& param_name = String::Handle(); | 16835 String& param_name = String::Handle(); |
17061 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { | 16836 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { |
17062 param_name = sig_fun.ParameterNameAt(i); | 16837 param_name = sig_fun.ParameterNameAt(i); |
17063 result = CombineHashes(result, param_name.Hash()); | 16838 result = CombineHashes(result, param_name.Hash()); |
17064 } | 16839 } |
17065 } | 16840 } |
17066 } | 16841 } |
17067 return FinalizeHash(result); | 16842 result = FinalizeHash(result, kHashBits); |
16843 SetHash(result); | |
16844 return result; | |
17068 } | 16845 } |
17069 | 16846 |
17070 | 16847 |
17071 void Type::set_type_class(const Object& value) const { | 16848 void Type::set_type_class(const Object& value) const { |
17072 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); | 16849 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); |
17073 StorePointer(&raw_ptr()->type_class_, value.raw()); | 16850 StorePointer(&raw_ptr()->type_class_, value.raw()); |
17074 } | 16851 } |
17075 | 16852 |
17076 | 16853 |
17077 void Type::set_arguments(const TypeArguments& value) const { | 16854 void Type::set_arguments(const TypeArguments& value) const { |
(...skipping 10 matching lines...) Expand all Loading... | |
17088 } | 16865 } |
17089 | 16866 |
17090 | 16867 |
17091 RawType* Type::New(const Object& clazz, | 16868 RawType* Type::New(const Object& clazz, |
17092 const TypeArguments& arguments, | 16869 const TypeArguments& arguments, |
17093 TokenPosition token_pos, | 16870 TokenPosition token_pos, |
17094 Heap::Space space) { | 16871 Heap::Space space) { |
17095 const Type& result = Type::Handle(Type::New(space)); | 16872 const Type& result = Type::Handle(Type::New(space)); |
17096 result.set_type_class(clazz); | 16873 result.set_type_class(clazz); |
17097 result.set_arguments(arguments); | 16874 result.set_arguments(arguments); |
16875 result.SetHash(0); | |
17098 result.set_token_pos(token_pos); | 16876 result.set_token_pos(token_pos); |
17099 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); | 16877 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); |
17100 return result.raw(); | 16878 return result.raw(); |
17101 } | 16879 } |
17102 | 16880 |
17103 | 16881 |
17104 void Type::set_token_pos(TokenPosition token_pos) const { | 16882 void Type::set_token_pos(TokenPosition token_pos) const { |
17105 ASSERT(!token_pos.IsClassifying()); | 16883 ASSERT(!token_pos.IsClassifying()); |
17106 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 16884 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
17107 } | 16885 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17267 pieces.Add(String::Handle(zone, library.url())); | 17045 pieces.Add(String::Handle(zone, library.url())); |
17268 pieces.Add(Symbols::NewLine()); | 17046 pieces.Add(Symbols::NewLine()); |
17269 return Symbols::FromConcatAll(thread, pieces); | 17047 return Symbols::FromConcatAll(thread, pieces); |
17270 } | 17048 } |
17271 | 17049 |
17272 | 17050 |
17273 intptr_t TypeRef::Hash() const { | 17051 intptr_t TypeRef::Hash() const { |
17274 // Do not calculate the hash of the referenced type to avoid divergence. | 17052 // Do not calculate the hash of the referenced type to avoid divergence. |
17275 const uint32_t result = | 17053 const uint32_t result = |
17276 Class::Handle(AbstractType::Handle(type()).type_class()).id(); | 17054 Class::Handle(AbstractType::Handle(type()).type_class()).id(); |
17277 return FinalizeHash(result); | 17055 return FinalizeHash(result, Type::kHashBits); |
regis
2016/05/17 16:55:30
This is the only place where you qualify kHashBits
siva
2016/05/17 21:25:53
Moved kHashBits to AbstractType as discussed offli
| |
17278 } | 17056 } |
17279 | 17057 |
17280 | 17058 |
17281 RawTypeRef* TypeRef::New() { | 17059 RawTypeRef* TypeRef::New() { |
17282 RawObject* raw = Object::Allocate(TypeRef::kClassId, | 17060 RawObject* raw = Object::Allocate(TypeRef::kClassId, |
17283 TypeRef::InstanceSize(), | 17061 TypeRef::InstanceSize(), |
17284 Heap::kOld); | 17062 Heap::kOld); |
17285 return reinterpret_cast<RawTypeRef*>(raw); | 17063 return reinterpret_cast<RawTypeRef*>(raw); |
17286 } | 17064 } |
17287 | 17065 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17497 const Class& cls = Class::Handle(zone, parameterized_class()); | 17275 const Class& cls = Class::Handle(zone, parameterized_class()); |
17498 pieces.Add(String::Handle(zone, cls.UserVisibleName())); | 17276 pieces.Add(String::Handle(zone, cls.UserVisibleName())); |
17499 pieces.Add(Symbols::SpaceIsFromSpace()); | 17277 pieces.Add(Symbols::SpaceIsFromSpace()); |
17500 const Library& library = Library::Handle(zone, cls.library()); | 17278 const Library& library = Library::Handle(zone, cls.library()); |
17501 pieces.Add(String::Handle(zone, library.url())); | 17279 pieces.Add(String::Handle(zone, library.url())); |
17502 pieces.Add(Symbols::NewLine()); | 17280 pieces.Add(Symbols::NewLine()); |
17503 return Symbols::FromConcatAll(thread, pieces); | 17281 return Symbols::FromConcatAll(thread, pieces); |
17504 } | 17282 } |
17505 | 17283 |
17506 | 17284 |
17507 intptr_t TypeParameter::Hash() const { | 17285 intptr_t TypeParameter::ComputeHash() const { |
17508 ASSERT(IsFinalized()); | 17286 ASSERT(IsFinalized()); |
17509 uint32_t result = Class::Handle(parameterized_class()).id(); | 17287 uint32_t result = Class::Handle(parameterized_class()).id(); |
17510 // No need to include the hash of the bound, since the type parameter is fully | 17288 // No need to include the hash of the bound, since the type parameter is fully |
17511 // identified by its class and index. | 17289 // identified by its class and index. |
17512 result = CombineHashes(result, index()); | 17290 result = CombineHashes(result, index()); |
17513 return FinalizeHash(result); | 17291 result = FinalizeHash(result, kHashBits); |
17292 SetHash(result); | |
17293 return result; | |
17514 } | 17294 } |
17515 | 17295 |
17516 | 17296 |
17517 RawTypeParameter* TypeParameter::New() { | 17297 RawTypeParameter* TypeParameter::New() { |
17518 RawObject* raw = Object::Allocate(TypeParameter::kClassId, | 17298 RawObject* raw = Object::Allocate(TypeParameter::kClassId, |
17519 TypeParameter::InstanceSize(), | 17299 TypeParameter::InstanceSize(), |
17520 Heap::kOld); | 17300 Heap::kOld); |
17521 return reinterpret_cast<RawTypeParameter*>(raw); | 17301 return reinterpret_cast<RawTypeParameter*>(raw); |
17522 } | 17302 } |
17523 | 17303 |
17524 | 17304 |
17525 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, | 17305 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, |
17526 intptr_t index, | 17306 intptr_t index, |
17527 const String& name, | 17307 const String& name, |
17528 const AbstractType& bound, | 17308 const AbstractType& bound, |
17529 TokenPosition token_pos) { | 17309 TokenPosition token_pos) { |
17530 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); | 17310 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); |
17531 result.set_parameterized_class(parameterized_class); | 17311 result.set_parameterized_class(parameterized_class); |
17532 result.set_index(index); | 17312 result.set_index(index); |
17533 result.set_name(name); | 17313 result.set_name(name); |
17534 result.set_bound(bound); | 17314 result.set_bound(bound); |
17315 result.SetHash(0); | |
17535 result.set_token_pos(token_pos); | 17316 result.set_token_pos(token_pos); |
17536 result.StoreNonPointer(&result.raw_ptr()->type_state_, | 17317 result.StoreNonPointer(&result.raw_ptr()->type_state_, |
17537 RawTypeParameter::kAllocated); | 17318 RawTypeParameter::kAllocated); |
17538 return result.raw(); | 17319 return result.raw(); |
17539 } | 17320 } |
17540 | 17321 |
17541 | 17322 |
17542 void TypeParameter::set_token_pos(TokenPosition token_pos) const { | 17323 void TypeParameter::set_token_pos(TokenPosition token_pos) const { |
17543 ASSERT(!token_pos.IsClassifying()); | 17324 ASSERT(!token_pos.IsClassifying()); |
17544 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 17325 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17761 return BoundedType::New(bounded_type, upper_bound, type_param); | 17542 return BoundedType::New(bounded_type, upper_bound, type_param); |
17762 } | 17543 } |
17763 | 17544 |
17764 | 17545 |
17765 RawString* BoundedType::EnumerateURIs() const { | 17546 RawString* BoundedType::EnumerateURIs() const { |
17766 // The bound does not appear in the user visible name. | 17547 // The bound does not appear in the user visible name. |
17767 return AbstractType::Handle(type()).EnumerateURIs(); | 17548 return AbstractType::Handle(type()).EnumerateURIs(); |
17768 } | 17549 } |
17769 | 17550 |
17770 | 17551 |
17771 intptr_t BoundedType::Hash() const { | 17552 intptr_t BoundedType::ComputeHash() const { |
17772 uint32_t result = AbstractType::Handle(type()).Hash(); | 17553 uint32_t result = AbstractType::Handle(type()).Hash(); |
17773 // No need to include the hash of the bound, since the bound is defined by the | 17554 // No need to include the hash of the bound, since the bound is defined by the |
17774 // type parameter (modulo instantiation state). | 17555 // type parameter (modulo instantiation state). |
17775 result = CombineHashes(result, | 17556 result = CombineHashes(result, |
17776 TypeParameter::Handle(type_parameter()).Hash()); | 17557 TypeParameter::Handle(type_parameter()).Hash()); |
17777 return FinalizeHash(result); | 17558 result = FinalizeHash(result, kHashBits); |
17559 SetHash(result); | |
17560 return result; | |
17778 } | 17561 } |
17779 | 17562 |
17780 | 17563 |
17781 RawBoundedType* BoundedType::New() { | 17564 RawBoundedType* BoundedType::New() { |
17782 RawObject* raw = Object::Allocate(BoundedType::kClassId, | 17565 RawObject* raw = Object::Allocate(BoundedType::kClassId, |
17783 BoundedType::InstanceSize(), | 17566 BoundedType::InstanceSize(), |
17784 Heap::kOld); | 17567 Heap::kOld); |
17785 return reinterpret_cast<RawBoundedType*>(raw); | 17568 return reinterpret_cast<RawBoundedType*>(raw); |
17786 } | 17569 } |
17787 | 17570 |
17788 | 17571 |
17789 RawBoundedType* BoundedType::New(const AbstractType& type, | 17572 RawBoundedType* BoundedType::New(const AbstractType& type, |
17790 const AbstractType& bound, | 17573 const AbstractType& bound, |
17791 const TypeParameter& type_parameter) { | 17574 const TypeParameter& type_parameter) { |
17792 const BoundedType& result = BoundedType::Handle(BoundedType::New()); | 17575 const BoundedType& result = BoundedType::Handle(BoundedType::New()); |
17793 result.set_type(type); | 17576 result.set_type(type); |
17794 result.set_bound(bound); | 17577 result.set_bound(bound); |
17578 result.SetHash(0); | |
17795 result.set_type_parameter(type_parameter); | 17579 result.set_type_parameter(type_parameter); |
17796 return result.raw(); | 17580 return result.raw(); |
17797 } | 17581 } |
17798 | 17582 |
17799 | 17583 |
17800 const char* BoundedType::ToCString() const { | 17584 const char* BoundedType::ToCString() const { |
17801 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; | 17585 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; |
17802 const char* type_cstr = String::Handle(AbstractType::Handle( | 17586 const char* type_cstr = String::Handle(AbstractType::Handle( |
17803 type()).Name()).ToCString(); | 17587 type()).Name()).ToCString(); |
17804 const char* bound_cstr = String::Handle(AbstractType::Handle( | 17588 const char* bound_cstr = String::Handle(AbstractType::Handle( |
(...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
19322 public: | 19106 public: |
19323 StringHasher() : hash_(0) {} | 19107 StringHasher() : hash_(0) {} |
19324 void Add(int32_t ch) { | 19108 void Add(int32_t ch) { |
19325 hash_ = CombineHashes(hash_, ch); | 19109 hash_ = CombineHashes(hash_, ch); |
19326 } | 19110 } |
19327 void Add(const String& str, intptr_t begin_index, intptr_t len); | 19111 void Add(const String& str, intptr_t begin_index, intptr_t len); |
19328 | 19112 |
19329 // Return a non-zero hash of at most 'bits' bits. | 19113 // Return a non-zero hash of at most 'bits' bits. |
19330 intptr_t Finalize(int bits) { | 19114 intptr_t Finalize(int bits) { |
19331 ASSERT(1 <= bits && bits <= (kBitsPerWord - 1)); | 19115 ASSERT(1 <= bits && bits <= (kBitsPerWord - 1)); |
19332 hash_ = FinalizeHash(hash_); | 19116 hash_ = FinalizeHash(hash_, bits); |
19333 hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); | |
19334 ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32)); | 19117 ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32)); |
19335 return hash_ == 0 ? 1 : hash_; | 19118 return hash_; |
19336 } | 19119 } |
19337 private: | 19120 private: |
19338 uint32_t hash_; | 19121 uint32_t hash_; |
19339 }; | 19122 }; |
19340 | 19123 |
19341 | 19124 |
19342 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) { | 19125 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) { |
19343 ASSERT(begin_index >= 0); | 19126 ASSERT(begin_index >= 0); |
19344 ASSERT(len >= 0); | 19127 ASSERT(len >= 0); |
19345 ASSERT((begin_index + len) <= str.Length()); | 19128 ASSERT((begin_index + len) <= str.Length()); |
(...skipping 1756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
21102 uword Array::ComputeCanonicalTableHash() const { | 20885 uword Array::ComputeCanonicalTableHash() const { |
21103 ASSERT(!IsNull()); | 20886 ASSERT(!IsNull()); |
21104 intptr_t len = Length(); | 20887 intptr_t len = Length(); |
21105 uword hash = len; | 20888 uword hash = len; |
21106 uword value = reinterpret_cast<uword>(GetTypeArguments()); | 20889 uword value = reinterpret_cast<uword>(GetTypeArguments()); |
21107 hash = CombineHashes(hash, value); | 20890 hash = CombineHashes(hash, value); |
21108 for (intptr_t i = 0; i < len; i++) { | 20891 for (intptr_t i = 0; i < len; i++) { |
21109 value = reinterpret_cast<uword>(At(i)); | 20892 value = reinterpret_cast<uword>(At(i)); |
21110 hash = CombineHashes(hash, value); | 20893 hash = CombineHashes(hash, value); |
21111 } | 20894 } |
21112 return FinalizeHash(hash); | 20895 return FinalizeHash(hash, kHashBits); |
21113 } | 20896 } |
21114 | 20897 |
21115 | 20898 |
21116 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20899 RawArray* Array::New(intptr_t len, Heap::Space space) { |
21117 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20900 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
21118 return New(kClassId, len, space); | 20901 return New(kClassId, len, space); |
21119 } | 20902 } |
21120 | 20903 |
21121 | 20904 |
21122 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 20905 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... | |
21759 } | 21542 } |
21760 | 21543 |
21761 | 21544 |
21762 uword TypedData::ComputeCanonicalTableHash() const { | 21545 uword TypedData::ComputeCanonicalTableHash() const { |
21763 const intptr_t len = this->LengthInBytes(); | 21546 const intptr_t len = this->LengthInBytes(); |
21764 ASSERT(len != 0); | 21547 ASSERT(len != 0); |
21765 uword hash = len; | 21548 uword hash = len; |
21766 for (intptr_t i = 0; i < len; i++) { | 21549 for (intptr_t i = 0; i < len; i++) { |
21767 hash = CombineHashes(len, GetUint8(i)); | 21550 hash = CombineHashes(len, GetUint8(i)); |
21768 } | 21551 } |
21769 return FinalizeHash(hash); | 21552 return FinalizeHash(hash, kHashBits); |
21770 } | 21553 } |
21771 | 21554 |
21772 | 21555 |
21773 RawTypedData* TypedData::New(intptr_t class_id, | 21556 RawTypedData* TypedData::New(intptr_t class_id, |
21774 intptr_t len, | 21557 intptr_t len, |
21775 Heap::Space space) { | 21558 Heap::Space space) { |
21776 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21559 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
21777 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21560 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
21778 } | 21561 } |
21779 TypedData& result = TypedData::Handle(); | 21562 TypedData& result = TypedData::Handle(); |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
22457 return UserTag::null(); | 22240 return UserTag::null(); |
22458 } | 22241 } |
22459 | 22242 |
22460 | 22243 |
22461 const char* UserTag::ToCString() const { | 22244 const char* UserTag::ToCString() const { |
22462 const String& tag_label = String::Handle(label()); | 22245 const String& tag_label = String::Handle(label()); |
22463 return tag_label.ToCString(); | 22246 return tag_label.ToCString(); |
22464 } | 22247 } |
22465 | 22248 |
22466 } // namespace dart | 22249 } // namespace dart |
OLD | NEW |