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 { | 3642 intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const { |
regis
2016/05/16 20:17:48
This function should not be required anymore.
siva
2016/05/16 23:24:25
This function is not required anymore, removed it.
| |
3657 Thread* thread = Thread::Current(); | 3643 Thread* thread = Thread::Current(); |
3658 if (EnsureIsFinalized(thread) != Error::null()) { | 3644 if (EnsureIsFinalized(thread) != Error::null()) { |
3659 return -1; | 3645 return -1; |
3660 } | 3646 } |
3661 if (needle.raw() == CanonicalType()) { | 3647 if (needle.raw() == CanonicalType()) { |
3662 // For a generic type or signature type, there exists another index with the | 3648 // For a generic type or signature type, there exists another index with the |
3663 // same type. It will never be returned by this function. | 3649 // same type. It will never be returned by this function. |
3664 return 0; | 3650 return 0; |
3665 } | 3651 } |
3666 REUSABLE_OBJECT_HANDLESCOPE(thread); | 3652 REUSABLE_OBJECT_HANDLESCOPE(thread); |
3667 Object& types = thread->ObjectHandle(); | 3653 Object& types = thread->ObjectHandle(); |
3668 types = canonical_types(); | 3654 types = canonical_type(); |
Cutch
2016/05/16 17:01:57
Maybe rename variable to "type" to match the acces
siva
2016/05/16 23:24:24
This function is not used anymore and has been rem
| |
3669 if (types.IsNull()) { | 3655 if (types.IsNull()) { |
3670 return -1; | 3656 return -1; |
3671 } | 3657 } |
3672 const intptr_t len = Array::Cast(types).Length(); | 3658 const intptr_t len = Array::Cast(types).Length(); |
regis
2016/05/16 20:17:48
I thought the point of this cl was to remove the a
siva
2016/05/16 23:24:25
Yes, this function has been removed.
| |
3673 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread); | 3659 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread); |
3674 AbstractType& type = thread->AbstractTypeHandle(); | 3660 AbstractType& type = thread->AbstractTypeHandle(); |
3675 for (intptr_t i = 0; i < len; i++) { | 3661 for (intptr_t i = 0; i < len; i++) { |
3676 type ^= Array::Cast(types).At(i); | 3662 type ^= Array::Cast(types).At(i); |
3677 if (needle.raw() == type.raw()) { | 3663 if (needle.raw() == type.raw()) { |
3678 return i; | 3664 return i; |
3679 } | 3665 } |
3680 } | 3666 } |
3681 // No type found. | 3667 // No type found. |
3682 return -1; | 3668 return -1; |
3683 } | 3669 } |
3684 | 3670 |
3685 | 3671 |
3686 RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const { | 3672 RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const { |
regis
2016/05/16 20:17:48
Still required?
siva
2016/05/16 23:24:24
This function is also not required and has been re
| |
3687 AbstractType& type = AbstractType::Handle(); | 3673 AbstractType& type = AbstractType::Handle(); |
3688 if (idx == 0) { | 3674 if (idx == 0) { |
3689 type = CanonicalType(); | 3675 type = CanonicalType(); |
3690 if (!type.IsNull()) { | 3676 if (!type.IsNull()) { |
3691 return type.raw(); | 3677 return type.raw(); |
3692 } | 3678 } |
3693 } | 3679 } |
3694 Object& types = Object::Handle(canonical_types()); | 3680 Object& types = Object::Handle(canonical_type()); |
3695 if (types.IsNull() || !types.IsArray()) { | 3681 if (types.IsNull() || !types.IsArray()) { |
rmacnak
2016/05/16 19:37:02
Never an array anymore.
siva
2016/05/16 23:24:24
This function has been removed.
| |
3696 return Type::null(); | 3682 return Type::null(); |
3697 } | 3683 } |
3698 if ((idx < 0) || (idx >= Array::Cast(types).Length())) { | 3684 if ((idx < 0) || (idx >= Array::Cast(types).Length())) { |
3699 return Type::null(); | 3685 return Type::null(); |
3700 } | 3686 } |
3701 type ^= Array::Cast(types).At(idx); | 3687 type ^= Array::Cast(types).At(idx); |
3702 ASSERT(!type.IsNull()); | 3688 ASSERT(!type.IsNull()); |
3703 return type.raw(); | 3689 return type.raw(); |
3704 } | 3690 } |
3705 | 3691 |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4265 Zone* zone = Thread::Current()->zone(); | 4251 Zone* zone = Thread::Current()->zone(); |
4266 const Library& lib = Library::Handle(zone, library()); | 4252 const Library& lib = Library::Handle(zone, library()); |
4267 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); | 4253 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); |
4268 if (!obj.IsNull() && obj.IsLibraryPrefix()) { | 4254 if (!obj.IsNull() && obj.IsLibraryPrefix()) { |
4269 return LibraryPrefix::Cast(obj).raw(); | 4255 return LibraryPrefix::Cast(obj).raw(); |
4270 } | 4256 } |
4271 return LibraryPrefix::null(); | 4257 return LibraryPrefix::null(); |
4272 } | 4258 } |
4273 | 4259 |
4274 | 4260 |
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 { | 4261 const char* Class::ToCString() const { |
4354 const Library& lib = Library::Handle(library()); | 4262 const Library& lib = Library::Handle(library()); |
4355 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); | 4263 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); |
4356 const char* patch_prefix = is_patch() ? "Patch " : ""; | 4264 const char* patch_prefix = is_patch() ? "Patch " : ""; |
4357 const char* class_name = String::Handle(Name()).ToCString(); | 4265 const char* class_name = String::Handle(Name()).ToCString(); |
4358 return OS::SCreate(Thread::Current()->zone(), | 4266 return OS::SCreate(Thread::Current()->zone(), |
4359 "%s %sClass: %s", library_name, patch_prefix, class_name); | 4267 "%s %sClass: %s", library_name, patch_prefix, class_name); |
4360 } | 4268 } |
4361 | 4269 |
4362 | 4270 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4628 | 4536 |
4629 | 4537 |
4630 static uint32_t FinalizeHash(uint32_t hash) { | 4538 static uint32_t FinalizeHash(uint32_t hash) { |
4631 hash += hash << 3; | 4539 hash += hash << 3; |
4632 hash ^= hash >> 11; // Logical shift, unsigned hash. | 4540 hash ^= hash >> 11; // Logical shift, unsigned hash. |
4633 hash += hash << 15; | 4541 hash += hash << 15; |
4634 return hash; | 4542 return hash; |
4635 } | 4543 } |
4636 | 4544 |
4637 | 4545 |
4638 intptr_t TypeArguments::Hash() const { | 4546 intptr_t TypeArguments::ComputeHash() const { |
4639 if (IsNull()) return 0; | 4547 if (IsNull()) return 0; |
4640 const intptr_t num_types = Length(); | 4548 const intptr_t num_types = Length(); |
4641 if (IsRaw(0, num_types)) return 0; | 4549 if (IsRaw(0, num_types)) return 0; |
4642 uint32_t result = 0; | 4550 uint32_t result = 0; |
4643 AbstractType& type = AbstractType::Handle(); | 4551 AbstractType& type = AbstractType::Handle(); |
4644 for (intptr_t i = 0; i < num_types; i++) { | 4552 for (intptr_t i = 0; i < num_types; i++) { |
4645 type = TypeAt(i); | 4553 type = TypeAt(i); |
4646 // The hash may be calculated during type finalization (for debugging | 4554 // The hash may be calculated during type finalization (for debugging |
4647 // purposes only) while a type argument is still temporarily null. | 4555 // purposes only) while a type argument is still temporarily null. |
4648 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); | 4556 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); |
4649 } | 4557 } |
4650 return FinalizeHash(result); | 4558 result = FinalizeHash(result) & ((static_cast<intptr_t>(1) << kHashBits) - 1); |
4559 result = (result == 0) ? 1 : result; | |
4560 SetHash(result); | |
4561 return result; | |
4651 } | 4562 } |
4652 | 4563 |
4653 | 4564 |
4654 RawString* TypeArguments::SubvectorName(intptr_t from_index, | 4565 RawString* TypeArguments::SubvectorName(intptr_t from_index, |
4655 intptr_t len, | 4566 intptr_t len, |
4656 NameVisibility name_visibility) const { | 4567 NameVisibility name_visibility) const { |
4657 Thread* thread = Thread::Current(); | 4568 Thread* thread = Thread::Current(); |
4658 Zone* zone = thread->zone(); | 4569 Zone* zone = thread->zone(); |
4659 ASSERT(from_index + len <= Length()); | 4570 ASSERT(from_index + len <= Length()); |
4660 String& name = String::Handle(zone); | 4571 String& name = String::Handle(zone); |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5091 } | 5002 } |
5092 TypeArguments& result = TypeArguments::Handle(); | 5003 TypeArguments& result = TypeArguments::Handle(); |
5093 { | 5004 { |
5094 RawObject* raw = Object::Allocate(TypeArguments::kClassId, | 5005 RawObject* raw = Object::Allocate(TypeArguments::kClassId, |
5095 TypeArguments::InstanceSize(len), | 5006 TypeArguments::InstanceSize(len), |
5096 space); | 5007 space); |
5097 NoSafepointScope no_safepoint; | 5008 NoSafepointScope no_safepoint; |
5098 result ^= raw; | 5009 result ^= raw; |
5099 // Length must be set before we start storing into the array. | 5010 // Length must be set before we start storing into the array. |
5100 result.SetLength(len); | 5011 result.SetLength(len); |
5012 result.SetHash(0); | |
5101 } | 5013 } |
5102 // The zero array should have been initialized. | 5014 // The zero array should have been initialized. |
5103 ASSERT(Object::zero_array().raw() != Array::null()); | 5015 ASSERT(Object::zero_array().raw() != Array::null()); |
5104 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); | 5016 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); |
5105 result.set_instantiations(Object::zero_array()); | 5017 result.set_instantiations(Object::zero_array()); |
5106 return result.raw(); | 5018 return result.raw(); |
5107 } | 5019 } |
5108 | 5020 |
5109 | 5021 |
5110 | 5022 |
5111 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { | 5023 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { |
5112 // TODO(iposva): Determine if we should throw an exception here. | 5024 // TODO(iposva): Determine if we should throw an exception here. |
5113 ASSERT((index >= 0) && (index < Length())); | 5025 ASSERT((index >= 0) && (index < Length())); |
5114 return &raw_ptr()->types()[index]; | 5026 return &raw_ptr()->types()[index]; |
5115 } | 5027 } |
5116 | 5028 |
5117 | 5029 |
5118 void TypeArguments::SetLength(intptr_t value) const { | 5030 void TypeArguments::SetLength(intptr_t value) const { |
5119 ASSERT(!IsCanonical()); | 5031 ASSERT(!IsCanonical()); |
5120 // This is only safe because we create a new Smi, which does not cause | 5032 // This is only safe because we create a new Smi, which does not cause |
5121 // heap allocation. | 5033 // heap allocation. |
5122 StoreSmi(&raw_ptr()->length_, Smi::New(value)); | 5034 StoreSmi(&raw_ptr()->length_, Smi::New(value)); |
5123 } | 5035 } |
5124 | 5036 |
5125 | 5037 |
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 { | 5038 RawTypeArguments* TypeArguments::CloneUnfinalized() const { |
5220 if (IsNull() || IsFinalized()) { | 5039 if (IsNull() || IsFinalized()) { |
5221 return raw(); | 5040 return raw(); |
5222 } | 5041 } |
5223 ASSERT(IsResolved()); | 5042 ASSERT(IsResolved()); |
5224 AbstractType& type = AbstractType::Handle(); | 5043 AbstractType& type = AbstractType::Handle(); |
5225 const intptr_t num_types = Length(); | 5044 const intptr_t num_types = Length(); |
5226 const TypeArguments& clone = TypeArguments::Handle( | 5045 const TypeArguments& clone = TypeArguments::Handle( |
5227 TypeArguments::New(num_types)); | 5046 TypeArguments::New(num_types)); |
5228 for (intptr_t i = 0; i < num_types; i++) { | 5047 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(); | 5082 return this->raw(); |
5264 } | 5083 } |
5265 const intptr_t num_types = Length(); | 5084 const intptr_t num_types = Length(); |
5266 if (IsRaw(0, num_types)) { | 5085 if (IsRaw(0, num_types)) { |
5267 return TypeArguments::null(); | 5086 return TypeArguments::null(); |
5268 } | 5087 } |
5269 Thread* thread = Thread::Current(); | 5088 Thread* thread = Thread::Current(); |
5270 Zone* zone = thread->zone(); | 5089 Zone* zone = thread->zone(); |
5271 Isolate* isolate = thread->isolate(); | 5090 Isolate* isolate = thread->isolate(); |
5272 ObjectStore* object_store = isolate->object_store(); | 5091 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); | 5092 TypeArguments& result = TypeArguments::Handle(zone); |
5281 result ^= table.At(index); | 5093 { |
5094 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); | |
5095 CanonicalTypeArgumentsSet table(zone, | |
5096 object_store->canonical_type_arguments()); | |
5097 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this)); | |
5098 object_store->set_canonical_type_arguments(table.Release()); | |
5099 } | |
5282 if (result.IsNull()) { | 5100 if (result.IsNull()) { |
5283 // Canonicalize each type argument. | 5101 // Canonicalize each type argument. |
5284 AbstractType& type_arg = AbstractType::Handle(zone); | 5102 AbstractType& type_arg = AbstractType::Handle(zone); |
5285 for (intptr_t i = 0; i < num_types; i++) { | 5103 for (intptr_t i = 0; i < num_types; i++) { |
5286 type_arg = TypeAt(i); | 5104 type_arg = TypeAt(i); |
5287 type_arg = type_arg.Canonicalize(trail); | 5105 type_arg = type_arg.Canonicalize(trail); |
5288 if (IsCanonical()) { | 5106 if (IsCanonical()) { |
5289 // Canonicalizing this type_arg canonicalized this type. | 5107 // Canonicalizing this type_arg canonicalized this type. |
5290 ASSERT(IsRecursive()); | 5108 ASSERT(IsRecursive()); |
5291 return this->raw(); | 5109 return this->raw(); |
5292 } | 5110 } |
5293 SetTypeAt(i, type_arg); | 5111 SetTypeAt(i, type_arg); |
5294 } | 5112 } |
5295 // Canonicalization of a recursive type may change its hash. | 5113 // Canonicalization of a recursive type may change its hash, so recompute. |
regis
2016/05/16 20:17:48
To be exact, the comment should say:
Canonicalizat
siva
2016/05/16 23:24:24
Done.
| |
5296 intptr_t canonical_hash = hash; | |
5297 if (IsRecursive()) { | 5114 if (IsRecursive()) { |
5298 canonical_hash = Hash(); | 5115 ComputeHash(); |
5299 } | 5116 } |
5300 // Canonicalization of the type argument's own type arguments may add an | 5117 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
5301 // entry to the table, or even grow the table, and thereby change the | 5118 CanonicalTypeArgumentsSet table( |
5302 // previously calculated index. | 5119 zone, object_store->canonical_type_arguments()); |
5303 table = object_store->canonical_type_arguments(); | 5120 // Since we canonicalized some type arguments above we need to lookup |
5304 if ((canonical_hash != hash) || | 5121 // 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)) { | 5122 // canonical entry. |
5306 index = FindIndexInCanonicalTypeArguments( | 5123 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this)); |
5307 zone, table, *this, canonical_hash); | |
5308 result ^= table.At(index); | |
5309 } | |
5310 if (result.IsNull()) { | 5124 if (result.IsNull()) { |
5311 // Make sure we have an old space object and add it to the table. | 5125 // Make sure we have an old space object and add it to the table. |
5312 if (this->IsNew()) { | 5126 if (this->IsNew()) { |
5313 result ^= Object::Clone(*this, Heap::kOld); | 5127 result ^= Object::Clone(*this, Heap::kOld); |
5314 } else { | 5128 } else { |
5315 result ^= this->raw(); | 5129 result ^= this->raw(); |
5316 } | 5130 } |
5317 ASSERT(result.IsOld()); | 5131 ASSERT(result.IsOld()); |
5318 InsertIntoCanonicalTypeArguments(thread, table, result, index); | 5132 result.SetCanonical(); // Mark object as being canonical. |
5133 // Now add this TypeArgument into the canonical list of type arguments. | |
5134 bool present = table.Insert(result); | |
5135 ASSERT(!present); | |
5319 } | 5136 } |
5137 object_store->set_canonical_type_arguments(table.Release()); | |
5320 } | 5138 } |
5321 ASSERT(result.Equals(*this)); | 5139 ASSERT(result.Equals(*this)); |
5322 ASSERT(!result.IsNull()); | 5140 ASSERT(!result.IsNull()); |
5323 ASSERT(result.IsTypeArguments()); | 5141 ASSERT(result.IsTypeArguments()); |
5324 ASSERT(result.IsCanonical()); | 5142 ASSERT(result.IsCanonical()); |
5325 return result.raw(); | 5143 return result.raw(); |
5326 } | 5144 } |
5327 | 5145 |
5328 | 5146 |
5329 RawString* TypeArguments::EnumerateURIs() const { | 5147 RawString* TypeArguments::EnumerateURIs() const { |
(...skipping 10 matching lines...) Expand all Loading... | |
5340 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); | 5158 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); |
5341 } | 5159 } |
5342 return String::ConcatAll(pieces); | 5160 return String::ConcatAll(pieces); |
5343 } | 5161 } |
5344 | 5162 |
5345 | 5163 |
5346 const char* TypeArguments::ToCString() const { | 5164 const char* TypeArguments::ToCString() const { |
5347 if (IsNull()) { | 5165 if (IsNull()) { |
5348 return "NULL TypeArguments"; | 5166 return "NULL TypeArguments"; |
5349 } | 5167 } |
5350 const char* prev_cstr = "TypeArguments:"; | 5168 Zone* zone = Thread::Current()->zone(); |
5169 const char* prev_cstr = OS::SCreate( | |
5170 zone, "TypeArguments: (%" Pd ")", Smi::Value(raw_ptr()->hash_)); | |
5351 for (int i = 0; i < Length(); i++) { | 5171 for (int i = 0; i < Length(); i++) { |
5352 const AbstractType& type_at = AbstractType::Handle(TypeAt(i)); | 5172 const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i)); |
5353 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); | 5173 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); |
5354 char* chars = OS::SCreate(Thread::Current()->zone(), | 5174 char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr); |
5355 "%s [%s]", prev_cstr, type_cstr); | |
5356 prev_cstr = chars; | 5175 prev_cstr = chars; |
5357 } | 5176 } |
5358 return prev_cstr; | 5177 return prev_cstr; |
5359 } | 5178 } |
5360 | 5179 |
5361 | 5180 |
5362 const char* PatchClass::ToCString() const { | 5181 const char* PatchClass::ToCString() const { |
5363 const Class& cls = Class::Handle(patched_class()); | 5182 const Class& cls = Class::Handle(patched_class()); |
5364 const char* cls_name = cls.ToCString(); | 5183 const char* cls_name = cls.ToCString(); |
5365 return OS::SCreate(Thread::Current()->zone(), | 5184 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. | 9186 // Called when growing the table. |
9368 static bool IsMatch(const Object& a, const Object& b) { | 9187 static bool IsMatch(const Object& a, const Object& b) { |
9369 ASSERT(a.IsLibrary() && b.IsLibrary()); | 9188 ASSERT(a.IsLibrary() && b.IsLibrary()); |
9370 // Library objects are always canonical. | 9189 // Library objects are always canonical. |
9371 return a.raw() == b.raw(); | 9190 return a.raw() == b.raw(); |
9372 } | 9191 } |
9373 static uword Hash(const Object& key) { | 9192 static uword Hash(const Object& key) { |
9374 return Library::Cast(key).UrlHash(); | 9193 return Library::Cast(key).UrlHash(); |
9375 } | 9194 } |
9376 }; | 9195 }; |
9377 | |
9378 | |
9379 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; | 9196 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; |
9380 | 9197 |
9381 | 9198 |
9382 RawInstance* Library::TransitiveLoadError() const { | 9199 RawInstance* Library::TransitiveLoadError() const { |
9383 if (LoadError() != Instance::null()) { | 9200 if (LoadError() != Instance::null()) { |
9384 return LoadError(); | 9201 return LoadError(); |
9385 } | 9202 } |
9386 Thread* thread = Thread::Current(); | 9203 Thread* thread = Thread::Current(); |
9387 Isolate* isolate = thread->isolate(); | 9204 Isolate* isolate = thread->isolate(); |
9388 Zone* zone = thread->zone(); | 9205 Zone* zone = thread->zone(); |
(...skipping 7492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16881 | 16698 |
16882 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { | 16699 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { |
16883 ASSERT(IsFinalized()); | 16700 ASSERT(IsFinalized()); |
16884 if (IsCanonical() || IsMalformed()) { | 16701 if (IsCanonical() || IsMalformed()) { |
16885 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); | 16702 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); |
16886 return this->raw(); | 16703 return this->raw(); |
16887 } | 16704 } |
16888 Thread* thread = Thread::Current(); | 16705 Thread* thread = Thread::Current(); |
16889 Zone* zone = thread->zone(); | 16706 Zone* zone = thread->zone(); |
16890 Isolate* isolate = thread->isolate(); | 16707 Isolate* isolate = thread->isolate(); |
16891 AbstractType& type = Type::Handle(zone); | 16708 |
16892 const Class& cls = Class::Handle(zone, type_class()); | |
16893 // Since void is a keyword, we never have to canonicalize the void type after | 16709 // 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. | 16710 // it is canonicalized once by the vm isolate. The parser does the mapping. |
16895 ASSERT((cls.raw() != Object::void_class()) || | 16711 ASSERT((type_class() != Object::void_class()) || |
16896 (isolate == Dart::vm_isolate())); | 16712 (isolate == Dart::vm_isolate())); |
16713 | |
16897 // Since dynamic is not a keyword, the parser builds a type that requires | 16714 // Since dynamic is not a keyword, the parser builds a type that requires |
16898 // canonicalization. | 16715 // canonicalization. |
16899 if ((cls.raw() == Object::dynamic_class()) && | 16716 if ((type_class() == Object::dynamic_class()) && |
16900 (isolate != Dart::vm_isolate())) { | 16717 (isolate != Dart::vm_isolate())) { |
16901 ASSERT(Object::dynamic_type().IsCanonical()); | 16718 ASSERT(Object::dynamic_type().IsCanonical()); |
16902 return Object::dynamic_type().raw(); | 16719 return Object::dynamic_type().raw(); |
16903 } | 16720 } |
16721 | |
16722 AbstractType& type = Type::Handle(zone); | |
16723 const Class& cls = Class::Handle(zone, type_class()); | |
16724 | |
16904 // Fast canonical lookup/registry for simple types. | 16725 // Fast canonical lookup/registry for simple types. |
16905 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { | 16726 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { |
16906 ASSERT(!IsFunctionType()); | 16727 ASSERT(!IsFunctionType()); |
16907 type = cls.CanonicalType(); | 16728 type = cls.CanonicalType(); |
16908 if (type.IsNull()) { | 16729 if (type.IsNull()) { |
16909 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); | 16730 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); |
16910 // Canonicalize the type arguments of the supertype, if any. | 16731 // Canonicalize the type arguments of the supertype, if any. |
16911 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 16732 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
16912 type_args = type_args.Canonicalize(trail); | 16733 type_args = type_args.Canonicalize(trail); |
16913 if (IsCanonical()) { | 16734 if (IsCanonical()) { |
16914 // Canonicalizing type_args canonicalized this type. | 16735 // Canonicalizing type_args canonicalized this type. |
16915 ASSERT(IsRecursive()); | 16736 ASSERT(IsRecursive()); |
16916 return this->raw(); | 16737 return this->raw(); |
16917 } | 16738 } |
16918 set_arguments(type_args); | 16739 set_arguments(type_args); |
16919 type = cls.CanonicalType(); // May be set while canonicalizing type args. | 16740 type = cls.CanonicalType(); // May be set while canonicalizing type args. |
16920 if (type.IsNull()) { | 16741 if (type.IsNull()) { |
16921 MutexLocker ml(isolate->type_canonicalization_mutex()); | 16742 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
16922 // Recheck if type exists. | 16743 // Recheck if type exists. |
16923 type = cls.CanonicalType(); | 16744 type = cls.CanonicalType(); |
16924 if (type.IsNull()) { | 16745 if (type.IsNull()) { |
16746 ComputeHash(); | |
16925 SetCanonical(); | 16747 SetCanonical(); |
16926 cls.set_canonical_types(*this); | 16748 cls.set_canonical_type(*this); |
16927 return this->raw(); | 16749 return this->raw(); |
16928 } | 16750 } |
16929 } | 16751 } |
16930 } | 16752 } |
16931 ASSERT(this->Equals(type)); | 16753 ASSERT(this->Equals(type)); |
16932 ASSERT(type.IsCanonical()); | 16754 ASSERT(type.IsCanonical()); |
16933 return type.raw(); | 16755 return type.raw(); |
16934 } | 16756 } |
16935 | 16757 |
16936 Array& canonical_types = Array::Handle(zone); | 16758 ObjectStore* object_store = isolate->object_store(); |
16937 canonical_types ^= cls.canonical_types(); | 16759 { |
16938 if (canonical_types.IsNull()) { | 16760 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); |
16939 canonical_types = empty_array().raw(); | 16761 CanonicalTypeSet table(zone, object_store->canonical_types()); |
16762 type ^= table.GetOrNull(CanonicalTypeKey(*this)); | |
16763 object_store->set_canonical_types(table.Release()); | |
16940 } | 16764 } |
16941 intptr_t length = canonical_types.Length(); | 16765 if (type.IsNull()) { |
16942 // Linear search to see whether this type is already present in the | 16766 // The type was not found in the table. It is not canonical yet. |
16943 // list of canonicalized types. | 16767 |
16944 // TODO(asiva): Try to re-factor this lookup code to make sharing | 16768 // Canonicalize the type arguments. |
16945 // easy between the 4 versions of this loop. | 16769 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
16946 intptr_t index = 1; // Slot 0 is reserved for CanonicalType(). | 16770 // In case the type is first canonicalized at runtime, its type argument |
16947 while (index < length) { | 16771 // vector may be longer than necessary. This is not an issue. |
16948 type ^= canonical_types.At(index); | 16772 ASSERT(type_args.IsNull() || |
16773 (type_args.Length() >= cls.NumTypeArguments())); | |
16774 type_args = type_args.Canonicalize(trail); | |
16775 if (IsCanonical()) { | |
16776 // Canonicalizing type_args canonicalized this type as a side effect. | |
16777 ASSERT(IsRecursive()); | |
16778 // Cycles via typedefs are detected and disallowed, but a function type | |
16779 // can be recursive due to a cycle in its type arguments. | |
16780 return this->raw(); | |
16781 } | |
16782 set_arguments(type_args); | |
16783 ASSERT(type_args.IsNull() || type_args.IsOld()); | |
16784 | |
16785 // In case of a function type, replace the actual function by a signature | |
16786 // function. | |
16787 if (IsFunctionType()) { | |
16788 const Function& fun = Function::Handle(zone, signature()); | |
16789 if (!fun.IsSignatureFunction()) { | |
16790 Function& sig_fun = Function::Handle( | |
16791 zone, | |
16792 Function::NewSignatureFunction(cls, TokenPosition::kNoSource)); | |
16793 type = fun.result_type(); | |
16794 type = type.Canonicalize(trail); | |
16795 sig_fun.set_result_type(type); | |
16796 const intptr_t num_params = fun.NumParameters(); | |
16797 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters()); | |
16798 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(), | |
16799 fun.HasOptionalPositionalParameters()); | |
16800 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params, | |
16801 Heap::kOld))); | |
16802 for (intptr_t i = 0; i < num_params; i++) { | |
16803 type = fun.ParameterTypeAt(i); | |
16804 type = type.Canonicalize(trail); | |
16805 sig_fun.SetParameterTypeAt(i, type); | |
16806 } | |
16807 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names())); | |
16808 set_signature(sig_fun); | |
16809 } | |
16810 } | |
16811 | |
16812 // Check to see if the type got added to canonical list as part of the | |
16813 // type arguments canonicalization. | |
16814 SafepointMutexLocker ml(isolate->type_canonicalization_mutex()); | |
16815 CanonicalTypeSet table(zone, object_store->canonical_types()); | |
16816 type ^= table.GetOrNull(CanonicalTypeKey(*this)); | |
16949 if (type.IsNull()) { | 16817 if (type.IsNull()) { |
16950 break; | 16818 // Add this Type into the canonical list of types. |
16819 type ^= raw(); | |
16820 ASSERT(type.IsOld()); | |
16821 type.SetCanonical(); // Mark object as being canonical. | |
16822 bool present = table.Insert(type); | |
16823 ASSERT(!present); | |
16951 } | 16824 } |
16952 ASSERT(type.IsFinalized()); | 16825 object_store->set_canonical_types(table.Release()); |
16953 if (this->Equals(type)) { | |
16954 ASSERT(type.IsCanonical()); | |
16955 return type.raw(); | |
16956 } | |
16957 index++; | |
16958 } | 16826 } |
16959 // The type was not found in the table. It is not canonical yet. | 16827 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 } | 16828 } |
17004 | 16829 |
17005 | 16830 |
17006 RawString* Type::EnumerateURIs() const { | 16831 RawString* Type::EnumerateURIs() const { |
17007 if (IsDynamicType() || IsVoidType()) { | 16832 if (IsDynamicType() || IsVoidType()) { |
17008 return Symbols::Empty().raw(); | 16833 return Symbols::Empty().raw(); |
17009 } | 16834 } |
17010 Thread* thread = Thread::Current(); | 16835 Thread* thread = Thread::Current(); |
17011 Zone* zone = thread->zone(); | 16836 Zone* zone = thread->zone(); |
17012 GrowableHandlePtrArray<const String> pieces(zone, 6); | 16837 GrowableHandlePtrArray<const String> pieces(zone, 6); |
(...skipping 20 matching lines...) Expand all Loading... | |
17033 const Library& library = Library::Handle(zone, cls.library()); | 16858 const Library& library = Library::Handle(zone, cls.library()); |
17034 pieces.Add(String::Handle(zone, library.url())); | 16859 pieces.Add(String::Handle(zone, library.url())); |
17035 pieces.Add(Symbols::NewLine()); | 16860 pieces.Add(Symbols::NewLine()); |
17036 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 16861 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
17037 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); | 16862 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); |
17038 } | 16863 } |
17039 return Symbols::FromConcatAll(thread, pieces); | 16864 return Symbols::FromConcatAll(thread, pieces); |
17040 } | 16865 } |
17041 | 16866 |
17042 | 16867 |
17043 intptr_t Type::Hash() const { | 16868 intptr_t Type::ComputeHash() const { |
17044 ASSERT(IsFinalized()); | 16869 ASSERT(IsFinalized()); |
17045 uint32_t result = 1; | 16870 uint32_t result = 1; |
17046 if (IsMalformed()) return result; | 16871 if (IsMalformed()) return result; |
17047 result = CombineHashes(result, Class::Handle(type_class()).id()); | 16872 result = CombineHashes(result, Class::Handle(type_class()).id()); |
17048 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); | 16873 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); |
17049 if (IsFunctionType()) { | 16874 if (IsFunctionType()) { |
17050 const Function& sig_fun = Function::Handle(signature()); | 16875 const Function& sig_fun = Function::Handle(signature()); |
17051 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); | 16876 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); |
17052 result = CombineHashes(result, type.Hash()); | 16877 result = CombineHashes(result, type.Hash()); |
17053 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); | 16878 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); |
17054 const intptr_t num_params = sig_fun.NumParameters(); | 16879 const intptr_t num_params = sig_fun.NumParameters(); |
17055 for (intptr_t i = 0; i < num_params; i++) { | 16880 for (intptr_t i = 0; i < num_params; i++) { |
17056 type = sig_fun.ParameterTypeAt(i); | 16881 type = sig_fun.ParameterTypeAt(i); |
17057 result = CombineHashes(result, type.Hash()); | 16882 result = CombineHashes(result, type.Hash()); |
17058 } | 16883 } |
17059 if (sig_fun.NumOptionalNamedParameters() > 0) { | 16884 if (sig_fun.NumOptionalNamedParameters() > 0) { |
17060 String& param_name = String::Handle(); | 16885 String& param_name = String::Handle(); |
17061 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { | 16886 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { |
17062 param_name = sig_fun.ParameterNameAt(i); | 16887 param_name = sig_fun.ParameterNameAt(i); |
17063 result = CombineHashes(result, param_name.Hash()); | 16888 result = CombineHashes(result, param_name.Hash()); |
17064 } | 16889 } |
17065 } | 16890 } |
17066 } | 16891 } |
17067 return FinalizeHash(result); | 16892 result = FinalizeHash(result) & ((static_cast<intptr_t>(1) << kHashBits) - 1); |
16893 result = (result == 0) ? 1 : result; | |
16894 SetHash(result); | |
16895 return result; | |
17068 } | 16896 } |
17069 | 16897 |
17070 | 16898 |
17071 void Type::set_type_class(const Object& value) const { | 16899 void Type::set_type_class(const Object& value) const { |
17072 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); | 16900 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); |
17073 StorePointer(&raw_ptr()->type_class_, value.raw()); | 16901 StorePointer(&raw_ptr()->type_class_, value.raw()); |
17074 } | 16902 } |
17075 | 16903 |
17076 | 16904 |
17077 void Type::set_arguments(const TypeArguments& value) const { | 16905 void Type::set_arguments(const TypeArguments& value) const { |
(...skipping 10 matching lines...) Expand all Loading... | |
17088 } | 16916 } |
17089 | 16917 |
17090 | 16918 |
17091 RawType* Type::New(const Object& clazz, | 16919 RawType* Type::New(const Object& clazz, |
17092 const TypeArguments& arguments, | 16920 const TypeArguments& arguments, |
17093 TokenPosition token_pos, | 16921 TokenPosition token_pos, |
17094 Heap::Space space) { | 16922 Heap::Space space) { |
17095 const Type& result = Type::Handle(Type::New(space)); | 16923 const Type& result = Type::Handle(Type::New(space)); |
17096 result.set_type_class(clazz); | 16924 result.set_type_class(clazz); |
17097 result.set_arguments(arguments); | 16925 result.set_arguments(arguments); |
16926 result.SetHash(0); | |
17098 result.set_token_pos(token_pos); | 16927 result.set_token_pos(token_pos); |
17099 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); | 16928 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); |
17100 return result.raw(); | 16929 return result.raw(); |
17101 } | 16930 } |
17102 | 16931 |
17103 | 16932 |
17104 void Type::set_token_pos(TokenPosition token_pos) const { | 16933 void Type::set_token_pos(TokenPosition token_pos) const { |
17105 ASSERT(!token_pos.IsClassifying()); | 16934 ASSERT(!token_pos.IsClassifying()); |
17106 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 16935 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
17107 } | 16936 } |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17497 const Class& cls = Class::Handle(zone, parameterized_class()); | 17326 const Class& cls = Class::Handle(zone, parameterized_class()); |
17498 pieces.Add(String::Handle(zone, cls.UserVisibleName())); | 17327 pieces.Add(String::Handle(zone, cls.UserVisibleName())); |
17499 pieces.Add(Symbols::SpaceIsFromSpace()); | 17328 pieces.Add(Symbols::SpaceIsFromSpace()); |
17500 const Library& library = Library::Handle(zone, cls.library()); | 17329 const Library& library = Library::Handle(zone, cls.library()); |
17501 pieces.Add(String::Handle(zone, library.url())); | 17330 pieces.Add(String::Handle(zone, library.url())); |
17502 pieces.Add(Symbols::NewLine()); | 17331 pieces.Add(Symbols::NewLine()); |
17503 return Symbols::FromConcatAll(thread, pieces); | 17332 return Symbols::FromConcatAll(thread, pieces); |
17504 } | 17333 } |
17505 | 17334 |
17506 | 17335 |
17507 intptr_t TypeParameter::Hash() const { | 17336 intptr_t TypeParameter::ComputeHash() const { |
17508 ASSERT(IsFinalized()); | 17337 ASSERT(IsFinalized()); |
17509 uint32_t result = Class::Handle(parameterized_class()).id(); | 17338 uint32_t result = Class::Handle(parameterized_class()).id(); |
17510 // No need to include the hash of the bound, since the type parameter is fully | 17339 // No need to include the hash of the bound, since the type parameter is fully |
17511 // identified by its class and index. | 17340 // identified by its class and index. |
17512 result = CombineHashes(result, index()); | 17341 result = CombineHashes(result, index()); |
17513 return FinalizeHash(result); | 17342 result = FinalizeHash(result) & ((static_cast<intptr_t>(1) << kHashBits) - 1); |
17343 result = (result == 0) ? 1 : result; | |
17344 SetHash(result); | |
17345 return result; | |
17514 } | 17346 } |
17515 | 17347 |
17516 | 17348 |
17517 RawTypeParameter* TypeParameter::New() { | 17349 RawTypeParameter* TypeParameter::New() { |
17518 RawObject* raw = Object::Allocate(TypeParameter::kClassId, | 17350 RawObject* raw = Object::Allocate(TypeParameter::kClassId, |
17519 TypeParameter::InstanceSize(), | 17351 TypeParameter::InstanceSize(), |
17520 Heap::kOld); | 17352 Heap::kOld); |
17521 return reinterpret_cast<RawTypeParameter*>(raw); | 17353 return reinterpret_cast<RawTypeParameter*>(raw); |
17522 } | 17354 } |
17523 | 17355 |
17524 | 17356 |
17525 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, | 17357 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, |
17526 intptr_t index, | 17358 intptr_t index, |
17527 const String& name, | 17359 const String& name, |
17528 const AbstractType& bound, | 17360 const AbstractType& bound, |
17529 TokenPosition token_pos) { | 17361 TokenPosition token_pos) { |
17530 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); | 17362 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); |
17531 result.set_parameterized_class(parameterized_class); | 17363 result.set_parameterized_class(parameterized_class); |
17532 result.set_index(index); | 17364 result.set_index(index); |
17533 result.set_name(name); | 17365 result.set_name(name); |
17534 result.set_bound(bound); | 17366 result.set_bound(bound); |
17367 result.SetHash(0); | |
17535 result.set_token_pos(token_pos); | 17368 result.set_token_pos(token_pos); |
17536 result.StoreNonPointer(&result.raw_ptr()->type_state_, | 17369 result.StoreNonPointer(&result.raw_ptr()->type_state_, |
17537 RawTypeParameter::kAllocated); | 17370 RawTypeParameter::kAllocated); |
17538 return result.raw(); | 17371 return result.raw(); |
17539 } | 17372 } |
17540 | 17373 |
17541 | 17374 |
17542 void TypeParameter::set_token_pos(TokenPosition token_pos) const { | 17375 void TypeParameter::set_token_pos(TokenPosition token_pos) const { |
17543 ASSERT(!token_pos.IsClassifying()); | 17376 ASSERT(!token_pos.IsClassifying()); |
17544 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 17377 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); | 17594 return BoundedType::New(bounded_type, upper_bound, type_param); |
17762 } | 17595 } |
17763 | 17596 |
17764 | 17597 |
17765 RawString* BoundedType::EnumerateURIs() const { | 17598 RawString* BoundedType::EnumerateURIs() const { |
17766 // The bound does not appear in the user visible name. | 17599 // The bound does not appear in the user visible name. |
17767 return AbstractType::Handle(type()).EnumerateURIs(); | 17600 return AbstractType::Handle(type()).EnumerateURIs(); |
17768 } | 17601 } |
17769 | 17602 |
17770 | 17603 |
17771 intptr_t BoundedType::Hash() const { | 17604 intptr_t BoundedType::ComputeHash() const { |
17772 uint32_t result = AbstractType::Handle(type()).Hash(); | 17605 uint32_t result = AbstractType::Handle(type()).Hash(); |
17773 // No need to include the hash of the bound, since the bound is defined by the | 17606 // No need to include the hash of the bound, since the bound is defined by the |
17774 // type parameter (modulo instantiation state). | 17607 // type parameter (modulo instantiation state). |
17775 result = CombineHashes(result, | 17608 result = CombineHashes(result, |
17776 TypeParameter::Handle(type_parameter()).Hash()); | 17609 TypeParameter::Handle(type_parameter()).Hash()); |
17777 return FinalizeHash(result); | 17610 result = FinalizeHash(result) & ((static_cast<intptr_t>(1) << kHashBits) - 1); |
17611 result = (result == 0) ? 1 : result; | |
17612 SetHash(result); | |
17613 return result; | |
17778 } | 17614 } |
17779 | 17615 |
17780 | 17616 |
17781 RawBoundedType* BoundedType::New() { | 17617 RawBoundedType* BoundedType::New() { |
17782 RawObject* raw = Object::Allocate(BoundedType::kClassId, | 17618 RawObject* raw = Object::Allocate(BoundedType::kClassId, |
17783 BoundedType::InstanceSize(), | 17619 BoundedType::InstanceSize(), |
17784 Heap::kOld); | 17620 Heap::kOld); |
17785 return reinterpret_cast<RawBoundedType*>(raw); | 17621 return reinterpret_cast<RawBoundedType*>(raw); |
17786 } | 17622 } |
17787 | 17623 |
17788 | 17624 |
17789 RawBoundedType* BoundedType::New(const AbstractType& type, | 17625 RawBoundedType* BoundedType::New(const AbstractType& type, |
17790 const AbstractType& bound, | 17626 const AbstractType& bound, |
17791 const TypeParameter& type_parameter) { | 17627 const TypeParameter& type_parameter) { |
17792 const BoundedType& result = BoundedType::Handle(BoundedType::New()); | 17628 const BoundedType& result = BoundedType::Handle(BoundedType::New()); |
17793 result.set_type(type); | 17629 result.set_type(type); |
17794 result.set_bound(bound); | 17630 result.set_bound(bound); |
17631 result.SetHash(0); | |
17795 result.set_type_parameter(type_parameter); | 17632 result.set_type_parameter(type_parameter); |
17796 return result.raw(); | 17633 return result.raw(); |
17797 } | 17634 } |
17798 | 17635 |
17799 | 17636 |
17800 const char* BoundedType::ToCString() const { | 17637 const char* BoundedType::ToCString() const { |
17801 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; | 17638 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; |
17802 const char* type_cstr = String::Handle(AbstractType::Handle( | 17639 const char* type_cstr = String::Handle(AbstractType::Handle( |
17803 type()).Name()).ToCString(); | 17640 type()).Name()).ToCString(); |
17804 const char* bound_cstr = String::Handle(AbstractType::Handle( | 17641 const char* bound_cstr = String::Handle(AbstractType::Handle( |
(...skipping 3297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
21102 uword Array::ComputeCanonicalTableHash() const { | 20939 uword Array::ComputeCanonicalTableHash() const { |
21103 ASSERT(!IsNull()); | 20940 ASSERT(!IsNull()); |
21104 intptr_t len = Length(); | 20941 intptr_t len = Length(); |
21105 uword hash = len; | 20942 uword hash = len; |
21106 uword value = reinterpret_cast<uword>(GetTypeArguments()); | 20943 uword value = reinterpret_cast<uword>(GetTypeArguments()); |
21107 hash = CombineHashes(hash, value); | 20944 hash = CombineHashes(hash, value); |
21108 for (intptr_t i = 0; i < len; i++) { | 20945 for (intptr_t i = 0; i < len; i++) { |
21109 value = reinterpret_cast<uword>(At(i)); | 20946 value = reinterpret_cast<uword>(At(i)); |
21110 hash = CombineHashes(hash, value); | 20947 hash = CombineHashes(hash, value); |
21111 } | 20948 } |
21112 return FinalizeHash(hash); | 20949 hash = FinalizeHash(hash) & ((static_cast<intptr_t>(1) << kHashBits) - 1); |
20950 return (hash == 0) ? 1 : hash; | |
Cutch
2016/05/16 17:01:57
Couldn't the masking off of high bits and handling
siva
2016/05/16 23:24:24
Done.
| |
21113 } | 20951 } |
21114 | 20952 |
21115 | 20953 |
21116 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20954 RawArray* Array::New(intptr_t len, Heap::Space space) { |
21117 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20955 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
21118 return New(kClassId, len, space); | 20956 return New(kClassId, len, space); |
21119 } | 20957 } |
21120 | 20958 |
21121 | 20959 |
21122 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 20960 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 } | 21597 } |
21760 | 21598 |
21761 | 21599 |
21762 uword TypedData::ComputeCanonicalTableHash() const { | 21600 uword TypedData::ComputeCanonicalTableHash() const { |
21763 const intptr_t len = this->LengthInBytes(); | 21601 const intptr_t len = this->LengthInBytes(); |
21764 ASSERT(len != 0); | 21602 ASSERT(len != 0); |
21765 uword hash = len; | 21603 uword hash = len; |
21766 for (intptr_t i = 0; i < len; i++) { | 21604 for (intptr_t i = 0; i < len; i++) { |
21767 hash = CombineHashes(len, GetUint8(i)); | 21605 hash = CombineHashes(len, GetUint8(i)); |
21768 } | 21606 } |
21769 return FinalizeHash(hash); | 21607 hash = FinalizeHash(hash) & ((static_cast<intptr_t>(1) << kHashBits) - 1); |
21608 return (hash == 0) ? 1 : hash; | |
21770 } | 21609 } |
21771 | 21610 |
21772 | 21611 |
21773 RawTypedData* TypedData::New(intptr_t class_id, | 21612 RawTypedData* TypedData::New(intptr_t class_id, |
21774 intptr_t len, | 21613 intptr_t len, |
21775 Heap::Space space) { | 21614 Heap::Space space) { |
21776 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21615 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
21777 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21616 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
21778 } | 21617 } |
21779 TypedData& result = TypedData::Handle(); | 21618 TypedData& result = TypedData::Handle(); |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
22457 return UserTag::null(); | 22296 return UserTag::null(); |
22458 } | 22297 } |
22459 | 22298 |
22460 | 22299 |
22461 const char* UserTag::ToCString() const { | 22300 const char* UserTag::ToCString() const { |
22462 const String& tag_label = String::Handle(label()); | 22301 const String& tag_label = String::Handle(label()); |
22463 return tag_label.ToCString(); | 22302 return tag_label.ToCString(); |
22464 } | 22303 } |
22465 | 22304 |
22466 } // namespace dart | 22305 } // namespace dart |
OLD | NEW |