Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: runtime/vm/object.cc

Issue 1965493004: Canonicalize generic types in an isolate specific hash table (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: sync-tot Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698