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

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

Powered by Google App Engine
This is Rietveld 408576698