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

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-merge-conflicts 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_reload.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 24 matching lines...) Expand all
35 #include "vm/resolver.h" 35 #include "vm/resolver.h"
36 #include "vm/reusable_handles.h" 36 #include "vm/reusable_handles.h"
37 #include "vm/runtime_entry.h" 37 #include "vm/runtime_entry.h"
38 #include "vm/scopes.h" 38 #include "vm/scopes.h"
39 #include "vm/stack_frame.h" 39 #include "vm/stack_frame.h"
40 #include "vm/symbols.h" 40 #include "vm/symbols.h"
41 #include "vm/tags.h" 41 #include "vm/tags.h"
42 #include "vm/thread_registry.h" 42 #include "vm/thread_registry.h"
43 #include "vm/timeline.h" 43 #include "vm/timeline.h"
44 #include "vm/timer.h" 44 #include "vm/timer.h"
45 #include "vm/type_table.h"
45 #include "vm/unicode.h" 46 #include "vm/unicode.h"
46 #include "vm/verified_memory.h" 47 #include "vm/verified_memory.h"
47 #include "vm/weak_code.h" 48 #include "vm/weak_code.h"
48 49
49 namespace dart { 50 namespace dart {
50 51
51 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, 52 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000,
52 "Huge method cutoff in unoptimized code size (in bytes)."); 53 "Huge method cutoff in unoptimized code size (in bytes).");
53 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, 54 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000,
54 "Huge method cutoff in tokens: Disables optimizations for huge methods."); 55 "Huge method cutoff in tokens: Disables optimizations for huge methods.");
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 cls.set_num_type_arguments(1); 1140 cls.set_num_type_arguments(1);
1140 1141
1141 // Set up the growable object array class (Has to be done after the array 1142 // Set up the growable object array class (Has to be done after the array
1142 // class is setup as one of its field is an array object). 1143 // class is setup as one of its field is an array object).
1143 cls = Class::New<GrowableObjectArray>(); 1144 cls = Class::New<GrowableObjectArray>();
1144 object_store->set_growable_object_array_class(cls); 1145 object_store->set_growable_object_array_class(cls);
1145 cls.set_type_arguments_field_offset( 1146 cls.set_type_arguments_field_offset(
1146 GrowableObjectArray::type_arguments_offset()); 1147 GrowableObjectArray::type_arguments_offset());
1147 cls.set_num_type_arguments(1); 1148 cls.set_num_type_arguments(1);
1148 1149
1149 // canonical_type_arguments_ are Smi terminated. 1150 // Initialize hash set for canonical_type_.
1150 // Last element contains the count of used slots. 1151 const intptr_t kInitialCanonicalTypeSize = 16;
1152 array = HashTables::New<CanonicalTypeSet>(
1153 kInitialCanonicalTypeSize, Heap::kOld);
1154 object_store->set_canonical_types(array);
1155
1156 // Initialize hash set for canonical_type_arguments_.
1151 const intptr_t kInitialCanonicalTypeArgumentsSize = 4; 1157 const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
1152 array = Array::New(kInitialCanonicalTypeArgumentsSize + 1); 1158 array = HashTables::New<CanonicalTypeArgumentsSet>(
1153 array.SetAt(kInitialCanonicalTypeArgumentsSize, 1159 kInitialCanonicalTypeArgumentsSize, Heap::kOld);
1154 Smi::Handle(zone, Smi::New(0)));
1155 object_store->set_canonical_type_arguments(array); 1160 object_store->set_canonical_type_arguments(array);
1156 1161
1157 // Setup type class early in the process. 1162 // Setup type class early in the process.
1158 const Class& type_cls = Class::Handle(zone, Class::New<Type>()); 1163 const Class& type_cls = Class::Handle(zone, Class::New<Type>());
1159 const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>()); 1164 const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
1160 const Class& type_parameter_cls = Class::Handle(zone, 1165 const Class& type_parameter_cls = Class::Handle(zone,
1161 Class::New<TypeParameter>()); 1166 Class::New<TypeParameter>());
1162 const Class& bounded_type_cls = Class::Handle(zone, 1167 const Class& bounded_type_cls = Class::Handle(zone,
1163 Class::New<BoundedType>()); 1168 Class::New<BoundedType>());
1164 const Class& mixin_app_type_cls = Class::Handle(zone, 1169 const Class& mixin_app_type_cls = Class::Handle(zone,
(...skipping 2460 matching lines...) Expand 10 before | Expand all | Expand 10 after
3625 RawArray* Class::constants() const { 3630 RawArray* Class::constants() const {
3626 return raw_ptr()->constants_; 3631 return raw_ptr()->constants_;
3627 } 3632 }
3628 3633
3629 void Class::set_constants(const Array& value) const { 3634 void Class::set_constants(const Array& value) const {
3630 ASSERT(!value.IsNull()); 3635 ASSERT(!value.IsNull());
3631 StorePointer(&raw_ptr()->constants_, value.raw()); 3636 StorePointer(&raw_ptr()->constants_, value.raw());
3632 } 3637 }
3633 3638
3634 3639
3635 RawObject* Class::canonical_types() const { 3640 RawType* Class::canonical_type() const {
3636 return raw_ptr()->canonical_types_; 3641 return raw_ptr()->canonical_type_;
3637 } 3642 }
3638 3643
3639 3644
3640 void Class::set_canonical_types(const Object& value) const { 3645 void Class::set_canonical_type(const Type& value) const {
3641 ASSERT(!value.IsNull()); 3646 ASSERT(!value.IsNull());
3642 StorePointer(&raw_ptr()->canonical_types_, value.raw()); 3647 StorePointer(&raw_ptr()->canonical_type_, value.raw());
3643 } 3648 }
3644 3649
3645 3650
3646 RawType* Class::CanonicalType() const { 3651 RawType* Class::CanonicalType() const {
3647 if (!IsGeneric() && !IsClosureClass()) { 3652 return raw_ptr()->canonical_type_;
3648 return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
3649 }
3650 Array& types = Array::Handle();
3651 types ^= canonical_types();
3652 if (!types.IsNull() && (types.Length() > 0)) {
3653 return reinterpret_cast<RawType*>(types.At(0));
3654 }
3655 return reinterpret_cast<RawType*>(Object::null());
3656 } 3653 }
3657 3654
3658 3655
3659 void Class::SetCanonicalType(const Type& type) const { 3656 void Class::SetCanonicalType(const Type& type) const {
3660 ASSERT(type.IsCanonical()); 3657 ASSERT((canonical_type() == Object::null()) ||
3661 if (!IsGeneric() && !IsClosureClass()) { 3658 (canonical_type() == type.raw())); // Set during own finalization.
3662 ASSERT((canonical_types() == Object::null()) || 3659 set_canonical_type(type);
3663 (canonical_types() == type.raw())); // Set during own finalization.
3664 set_canonical_types(type);
3665 } else {
3666 Array& types = Array::Handle();
3667 types ^= canonical_types();
3668 ASSERT(!types.IsNull() && (types.Length() > 1));
3669 ASSERT((types.At(0) == Object::null()) || (types.At(0) == type.raw()));
3670 types.SetAt(0, type);
3671 // Makes sure that 'canonical_types' has not changed.
3672 ASSERT(types.raw() == canonical_types());
3673 }
3674 } 3660 }
3675 3661
3676 3662
3677 intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const {
3678 Thread* thread = Thread::Current();
3679 if (EnsureIsFinalized(thread) != Error::null()) {
3680 return -1;
3681 }
3682 if (needle.raw() == CanonicalType()) {
3683 // For a generic type or signature type, there exists another index with the
3684 // same type. It will never be returned by this function.
3685 return 0;
3686 }
3687 REUSABLE_OBJECT_HANDLESCOPE(thread);
3688 Object& types = thread->ObjectHandle();
3689 types = canonical_types();
3690 if (types.IsNull()) {
3691 return -1;
3692 }
3693 const intptr_t len = Array::Cast(types).Length();
3694 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread);
3695 AbstractType& type = thread->AbstractTypeHandle();
3696 for (intptr_t i = 0; i < len; i++) {
3697 type ^= Array::Cast(types).At(i);
3698 if (needle.raw() == type.raw()) {
3699 return i;
3700 }
3701 }
3702 // No type found.
3703 return -1;
3704 }
3705
3706
3707 RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
3708 AbstractType& type = AbstractType::Handle();
3709 if (idx == 0) {
3710 type = CanonicalType();
3711 if (!type.IsNull()) {
3712 return type.raw();
3713 }
3714 }
3715 Object& types = Object::Handle(canonical_types());
3716 if (types.IsNull() || !types.IsArray()) {
3717 return Type::null();
3718 }
3719 if ((idx < 0) || (idx >= Array::Cast(types).Length())) {
3720 return Type::null();
3721 }
3722 type ^= Array::Cast(types).At(idx);
3723 ASSERT(!type.IsNull());
3724 return type.raw();
3725 }
3726
3727
3728 void Class::set_allocation_stub(const Code& value) const { 3663 void Class::set_allocation_stub(const Code& value) const {
3729 // Never clear the stub as it may still be a target, but will be GC-d if 3664 // Never clear the stub as it may still be a target, but will be GC-d if
3730 // not referenced. 3665 // not referenced.
3731 ASSERT(!value.IsNull()); 3666 ASSERT(!value.IsNull());
3732 ASSERT(raw_ptr()->allocation_stub_ == Code::null()); 3667 ASSERT(raw_ptr()->allocation_stub_ == Code::null());
3733 StorePointer(&raw_ptr()->allocation_stub_, value.raw()); 3668 StorePointer(&raw_ptr()->allocation_stub_, value.raw());
3734 } 3669 }
3735 3670
3736 3671
3737 void Class::DisableAllocationStub() const { 3672 void Class::DisableAllocationStub() const {
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
4286 Zone* zone = Thread::Current()->zone(); 4221 Zone* zone = Thread::Current()->zone();
4287 const Library& lib = Library::Handle(zone, library()); 4222 const Library& lib = Library::Handle(zone, library());
4288 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name)); 4223 const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name));
4289 if (!obj.IsNull() && obj.IsLibraryPrefix()) { 4224 if (!obj.IsNull() && obj.IsLibraryPrefix()) {
4290 return LibraryPrefix::Cast(obj).raw(); 4225 return LibraryPrefix::Cast(obj).raw();
4291 } 4226 }
4292 return LibraryPrefix::null(); 4227 return LibraryPrefix::null();
4293 } 4228 }
4294 4229
4295 4230
4296 // Returns AbstractType::null() if type not found. Modifies index to the last
4297 // position looked up.
4298 RawAbstractType* Class::LookupCanonicalType(
4299 Zone* zone, const AbstractType& lookup_type, intptr_t* index) const {
4300 Array& canonical_types = Array::Handle(zone);
4301 canonical_types ^= this->canonical_types();
4302 if (canonical_types.IsNull()) {
4303 return AbstractType::null();
4304 }
4305 AbstractType& type = Type::Handle(zone);
4306 const intptr_t length = canonical_types.Length();
4307 while (*index < length) {
4308 type ^= canonical_types.At(*index);
4309 if (type.IsNull()) {
4310 break;
4311 }
4312 ASSERT(type.IsFinalized());
4313 if (lookup_type.Equals(type)) {
4314 ASSERT(type.IsCanonical());
4315 return type.raw();
4316 }
4317 *index = *index + 1;
4318 }
4319 return AbstractType::null();
4320 }
4321
4322
4323 // Canonicalizing the type arguments may have changed the index, may have
4324 // grown the table, or may even have canonicalized this type. Therefore
4325 // conrtinue search for canonical type at the last index visited.
4326 RawAbstractType* Class::LookupOrAddCanonicalType(
4327 const AbstractType& lookup_type, intptr_t start_index) const {
4328 Thread* thread = Thread::Current();
4329 Zone* zone = thread->zone();
4330 Isolate* isolate = thread->isolate();
4331 AbstractType& type = Type::Handle(zone);
4332 intptr_t index = start_index;
4333 type ^= LookupCanonicalType(zone, lookup_type, &index);
4334
4335 if (!type.IsNull()) {
4336 return type.raw();
4337 }
4338 {
4339 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
4340 // Lookup again, in case the canonicalization array changed.
4341 Array& canonical_types = Array::Handle(zone);
4342 canonical_types ^= this->canonical_types();
4343 if (canonical_types.IsNull()) {
4344 canonical_types = empty_array().raw();
4345 }
4346 const intptr_t length = canonical_types.Length();
4347 // Start looking after previously looked up last position ('length').
4348 type ^= LookupCanonicalType(zone, lookup_type, &index);
4349 if (!type.IsNull()) {
4350 return type.raw();
4351 }
4352
4353 // 'lookup_type' is not canonicalized yet.
4354 lookup_type.SetCanonical();
4355
4356 // The type needs to be added to the list. Grow the list if it is full.
4357 if (index >= length) {
4358 ASSERT((index == length) || ((index == 1) && (length == 0)));
4359 const intptr_t new_length = (length > 64) ?
4360 (length + 64) :
4361 ((length == 0) ? 2 : (length * 2));
4362 const Array& new_canonical_types = Array::Handle(
4363 zone, Array::Grow(canonical_types, new_length, Heap::kOld));
4364 new_canonical_types.SetAt(index, lookup_type);
4365 this->set_canonical_types(new_canonical_types);
4366 } else {
4367 canonical_types.SetAt(index, lookup_type);
4368 }
4369 }
4370 return lookup_type.raw();
4371 }
4372
4373
4374 const char* Class::ToCString() const { 4231 const char* Class::ToCString() const {
4375 const Library& lib = Library::Handle(library()); 4232 const Library& lib = Library::Handle(library());
4376 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); 4233 const char* library_name = lib.IsNull() ? "" : lib.ToCString();
4377 const char* patch_prefix = is_patch() ? "Patch " : ""; 4234 const char* patch_prefix = is_patch() ? "Patch " : "";
4378 const char* class_name = String::Handle(Name()).ToCString(); 4235 const char* class_name = String::Handle(Name()).ToCString();
4379 return OS::SCreate(Thread::Current()->zone(), 4236 return OS::SCreate(Thread::Current()->zone(),
4380 "%s %sClass: %s", library_name, patch_prefix, class_name); 4237 "%s %sClass: %s", library_name, patch_prefix, class_name);
4381 } 4238 }
4382 4239
4383 4240
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
4641 4498
4642 4499
4643 static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) { 4500 static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) {
4644 hash += other_hash; 4501 hash += other_hash;
4645 hash += hash << 10; 4502 hash += hash << 10;
4646 hash ^= hash >> 6; // Logical shift, unsigned hash. 4503 hash ^= hash >> 6; // Logical shift, unsigned hash.
4647 return hash; 4504 return hash;
4648 } 4505 }
4649 4506
4650 4507
4651 static uint32_t FinalizeHash(uint32_t hash) { 4508 static uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits) {
4652 hash += hash << 3; 4509 hash += hash << 3;
4653 hash ^= hash >> 11; // Logical shift, unsigned hash. 4510 hash ^= hash >> 11; // Logical shift, unsigned hash.
4654 hash += hash << 15; 4511 hash += hash << 15;
4655 return hash; 4512 hash &= ((static_cast<intptr_t>(1) << hashbits) - 1);
4513 return (hash == 0) ? 1 : hash;
4656 } 4514 }
4657 4515
4658 4516
4659 intptr_t TypeArguments::Hash() const { 4517 intptr_t TypeArguments::ComputeHash() const {
4660 if (IsNull()) return 0; 4518 if (IsNull()) return 0;
4661 const intptr_t num_types = Length(); 4519 const intptr_t num_types = Length();
4662 if (IsRaw(0, num_types)) return 0; 4520 if (IsRaw(0, num_types)) return 0;
4663 uint32_t result = 0; 4521 uint32_t result = 0;
4664 AbstractType& type = AbstractType::Handle(); 4522 AbstractType& type = AbstractType::Handle();
4665 for (intptr_t i = 0; i < num_types; i++) { 4523 for (intptr_t i = 0; i < num_types; i++) {
4666 type = TypeAt(i); 4524 type = TypeAt(i);
4667 // The hash may be calculated during type finalization (for debugging 4525 // The hash may be calculated during type finalization (for debugging
4668 // purposes only) while a type argument is still temporarily null. 4526 // purposes only) while a type argument is still temporarily null.
4669 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash()); 4527 result = CombineHashes(result, type.IsNull() ? 0 : type.Hash());
4670 } 4528 }
4671 return FinalizeHash(result); 4529 result = FinalizeHash(result, kHashBits);
4530 SetHash(result);
4531 return result;
4672 } 4532 }
4673 4533
4674 4534
4675 RawString* TypeArguments::SubvectorName(intptr_t from_index, 4535 RawString* TypeArguments::SubvectorName(intptr_t from_index,
4676 intptr_t len, 4536 intptr_t len,
4677 NameVisibility name_visibility) const { 4537 NameVisibility name_visibility) const {
4678 Thread* thread = Thread::Current(); 4538 Thread* thread = Thread::Current();
4679 Zone* zone = thread->zone(); 4539 Zone* zone = thread->zone();
4680 ASSERT(from_index + len <= Length()); 4540 ASSERT(from_index + len <= Length());
4681 String& name = String::Handle(zone); 4541 String& name = String::Handle(zone);
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
5112 } 4972 }
5113 TypeArguments& result = TypeArguments::Handle(); 4973 TypeArguments& result = TypeArguments::Handle();
5114 { 4974 {
5115 RawObject* raw = Object::Allocate(TypeArguments::kClassId, 4975 RawObject* raw = Object::Allocate(TypeArguments::kClassId,
5116 TypeArguments::InstanceSize(len), 4976 TypeArguments::InstanceSize(len),
5117 space); 4977 space);
5118 NoSafepointScope no_safepoint; 4978 NoSafepointScope no_safepoint;
5119 result ^= raw; 4979 result ^= raw;
5120 // Length must be set before we start storing into the array. 4980 // Length must be set before we start storing into the array.
5121 result.SetLength(len); 4981 result.SetLength(len);
4982 result.SetHash(0);
5122 } 4983 }
5123 // The zero array should have been initialized. 4984 // The zero array should have been initialized.
5124 ASSERT(Object::zero_array().raw() != Array::null()); 4985 ASSERT(Object::zero_array().raw() != Array::null());
5125 COMPILE_ASSERT(StubCode::kNoInstantiator == 0); 4986 COMPILE_ASSERT(StubCode::kNoInstantiator == 0);
5126 result.set_instantiations(Object::zero_array()); 4987 result.set_instantiations(Object::zero_array());
5127 return result.raw(); 4988 return result.raw();
5128 } 4989 }
5129 4990
5130 4991
5131 4992
5132 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const { 4993 RawAbstractType* const* TypeArguments::TypeAddr(intptr_t index) const {
5133 // TODO(iposva): Determine if we should throw an exception here. 4994 // TODO(iposva): Determine if we should throw an exception here.
5134 ASSERT((index >= 0) && (index < Length())); 4995 ASSERT((index >= 0) && (index < Length()));
5135 return &raw_ptr()->types()[index]; 4996 return &raw_ptr()->types()[index];
5136 } 4997 }
5137 4998
5138 4999
5139 void TypeArguments::SetLength(intptr_t value) const { 5000 void TypeArguments::SetLength(intptr_t value) const {
5140 ASSERT(!IsCanonical()); 5001 ASSERT(!IsCanonical());
5141 // This is only safe because we create a new Smi, which does not cause 5002 // This is only safe because we create a new Smi, which does not cause
5142 // heap allocation. 5003 // heap allocation.
5143 StoreSmi(&raw_ptr()->length_, Smi::New(value)); 5004 StoreSmi(&raw_ptr()->length_, Smi::New(value));
5144 } 5005 }
5145 5006
5146 5007
5147 static void GrowCanonicalTypeArguments(Thread* thread, const Array& table) {
5148 Isolate* isolate = thread->isolate();
5149 Zone* zone = thread->zone();
5150 // Last element of the array is the number of used elements.
5151 const intptr_t table_size = table.Length() - 1;
5152 const intptr_t new_table_size = table_size * 2;
5153 Array& new_table = Array::Handle(zone, Array::New(new_table_size + 1));
5154 // Copy all elements from the original table to the newly allocated
5155 // array.
5156 TypeArguments& element = TypeArguments::Handle(zone);
5157 Object& new_element = Object::Handle(zone);
5158 for (intptr_t i = 0; i < table_size; i++) {
5159 element ^= table.At(i);
5160 if (!element.IsNull()) {
5161 const intptr_t hash = element.Hash();
5162 ASSERT(Utils::IsPowerOfTwo(new_table_size));
5163 intptr_t index = hash & (new_table_size - 1);
5164 new_element = new_table.At(index);
5165 while (!new_element.IsNull()) {
5166 index = (index + 1) & (new_table_size - 1); // Move to next element.
5167 new_element = new_table.At(index);
5168 }
5169 new_table.SetAt(index, element);
5170 }
5171 }
5172 // Copy used count.
5173 new_element = table.At(table_size);
5174 new_table.SetAt(new_table_size, new_element);
5175 // Remember the new table now.
5176 isolate->object_store()->set_canonical_type_arguments(new_table);
5177 }
5178
5179
5180 static void InsertIntoCanonicalTypeArguments(Thread* thread,
5181 const Array& table,
5182 const TypeArguments& arguments,
5183 intptr_t index) {
5184 Zone* zone = thread->zone();
5185 arguments.SetCanonical(); // Mark object as being canonical.
5186 table.SetAt(index, arguments); // Remember the new element.
5187 // Update used count.
5188 // Last element of the array is the number of used elements.
5189 const intptr_t table_size = table.Length() - 1;
5190 const intptr_t used_elements =
5191 Smi::Value(Smi::RawCast(table.At(table_size))) + 1;
5192 const Smi& used = Smi::Handle(zone, Smi::New(used_elements));
5193 table.SetAt(table_size, used);
5194
5195 #ifdef DEBUG
5196 // Verify that there are no duplicates.
5197 // Duplicates could appear if hash values are not kept constant across
5198 // snapshots, e.g. if class ids are not preserved by the snapshots.
5199 TypeArguments& other_arguments = TypeArguments::Handle();
5200 for (intptr_t i = 0; i < table_size; i++) {
5201 if ((i != index) && (table.At(i) != TypeArguments::null())) {
5202 other_arguments ^= table.At(i);
5203 if (arguments.Equals(other_arguments)) {
5204 // Recursive types may be equal, but have different hashes.
5205 ASSERT(arguments.IsRecursive());
5206 ASSERT(other_arguments.IsRecursive());
5207 ASSERT(arguments.Hash() != other_arguments.Hash());
5208 }
5209 }
5210 }
5211 #endif
5212
5213 // Rehash if table is 75% full.
5214 if (used_elements > ((table_size / 4) * 3)) {
5215 GrowCanonicalTypeArguments(thread, table);
5216 }
5217 }
5218
5219
5220 static intptr_t FindIndexInCanonicalTypeArguments(
5221 Zone* zone,
5222 const Array& table,
5223 const TypeArguments& arguments,
5224 intptr_t hash) {
5225 // Last element of the array is the number of used elements.
5226 const intptr_t table_size = table.Length() - 1;
5227 ASSERT(Utils::IsPowerOfTwo(table_size));
5228 intptr_t index = hash & (table_size - 1);
5229
5230 TypeArguments& current = TypeArguments::Handle(zone);
5231 current ^= table.At(index);
5232 while (!current.IsNull() && !current.Equals(arguments)) {
5233 index = (index + 1) & (table_size - 1); // Move to next element.
5234 current ^= table.At(index);
5235 }
5236 return index; // Index of element if found or slot into which to add it.
5237 }
5238
5239
5240 RawTypeArguments* TypeArguments::CloneUnfinalized() const { 5008 RawTypeArguments* TypeArguments::CloneUnfinalized() const {
5241 if (IsNull() || IsFinalized()) { 5009 if (IsNull() || IsFinalized()) {
5242 return raw(); 5010 return raw();
5243 } 5011 }
5244 ASSERT(IsResolved()); 5012 ASSERT(IsResolved());
5245 AbstractType& type = AbstractType::Handle(); 5013 AbstractType& type = AbstractType::Handle();
5246 const intptr_t num_types = Length(); 5014 const intptr_t num_types = Length();
5247 const TypeArguments& clone = TypeArguments::Handle( 5015 const TypeArguments& clone = TypeArguments::Handle(
5248 TypeArguments::New(num_types)); 5016 TypeArguments::New(num_types));
5249 for (intptr_t i = 0; i < num_types; i++) { 5017 for (intptr_t i = 0; i < num_types; i++) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5284 return this->raw(); 5052 return this->raw();
5285 } 5053 }
5286 const intptr_t num_types = Length(); 5054 const intptr_t num_types = Length();
5287 if (IsRaw(0, num_types)) { 5055 if (IsRaw(0, num_types)) {
5288 return TypeArguments::null(); 5056 return TypeArguments::null();
5289 } 5057 }
5290 Thread* thread = Thread::Current(); 5058 Thread* thread = Thread::Current();
5291 Zone* zone = thread->zone(); 5059 Zone* zone = thread->zone();
5292 Isolate* isolate = thread->isolate(); 5060 Isolate* isolate = thread->isolate();
5293 ObjectStore* object_store = isolate->object_store(); 5061 ObjectStore* object_store = isolate->object_store();
5294 Array& table = Array::Handle(zone,
5295 object_store->canonical_type_arguments());
5296 // Last element of the array is the number of used elements.
5297 const intptr_t num_used =
5298 Smi::Value(Smi::RawCast(table.At(table.Length() - 1)));
5299 const intptr_t hash = Hash();
5300 intptr_t index = FindIndexInCanonicalTypeArguments(zone, table, *this, hash);
5301 TypeArguments& result = TypeArguments::Handle(zone); 5062 TypeArguments& result = TypeArguments::Handle(zone);
5302 result ^= table.At(index); 5063 {
5064 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
5065 CanonicalTypeArgumentsSet table(zone,
5066 object_store->canonical_type_arguments());
5067 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
5068 object_store->set_canonical_type_arguments(table.Release());
5069 }
5303 if (result.IsNull()) { 5070 if (result.IsNull()) {
5304 // Canonicalize each type argument. 5071 // Canonicalize each type argument.
5305 AbstractType& type_arg = AbstractType::Handle(zone); 5072 AbstractType& type_arg = AbstractType::Handle(zone);
5306 for (intptr_t i = 0; i < num_types; i++) { 5073 for (intptr_t i = 0; i < num_types; i++) {
5307 type_arg = TypeAt(i); 5074 type_arg = TypeAt(i);
5308 type_arg = type_arg.Canonicalize(trail); 5075 type_arg = type_arg.Canonicalize(trail);
5309 if (IsCanonical()) { 5076 if (IsCanonical()) {
5310 // Canonicalizing this type_arg canonicalized this type. 5077 // Canonicalizing this type_arg canonicalized this type.
5311 ASSERT(IsRecursive()); 5078 ASSERT(IsRecursive());
5312 return this->raw(); 5079 return this->raw();
5313 } 5080 }
5314 SetTypeAt(i, type_arg); 5081 SetTypeAt(i, type_arg);
5315 } 5082 }
5316 // Canonicalization of a recursive type may change its hash. 5083 // Canonicalization of a type argument of a recursive type argument vector
5317 intptr_t canonical_hash = hash; 5084 // may change the hash of the vector, so recompute.
5318 if (IsRecursive()) { 5085 if (IsRecursive()) {
5319 canonical_hash = Hash(); 5086 ComputeHash();
5320 } 5087 }
5321 // Canonicalization of the type argument's own type arguments may add an 5088 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
5322 // entry to the table, or even grow the table, and thereby change the 5089 CanonicalTypeArgumentsSet table(
5323 // previously calculated index. 5090 zone, object_store->canonical_type_arguments());
5324 table = object_store->canonical_type_arguments(); 5091 // Since we canonicalized some type arguments above we need to lookup
5325 if ((canonical_hash != hash) || 5092 // in the table again to make sure we don't already have an equivalent
5326 (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used)) { 5093 // canonical entry.
5327 index = FindIndexInCanonicalTypeArguments( 5094 result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
5328 zone, table, *this, canonical_hash);
5329 result ^= table.At(index);
5330 }
5331 if (result.IsNull()) { 5095 if (result.IsNull()) {
5332 // Make sure we have an old space object and add it to the table. 5096 // Make sure we have an old space object and add it to the table.
5333 if (this->IsNew()) { 5097 if (this->IsNew()) {
5334 result ^= Object::Clone(*this, Heap::kOld); 5098 result ^= Object::Clone(*this, Heap::kOld);
5335 } else { 5099 } else {
5336 result ^= this->raw(); 5100 result ^= this->raw();
5337 } 5101 }
5338 ASSERT(result.IsOld()); 5102 ASSERT(result.IsOld());
5339 InsertIntoCanonicalTypeArguments(thread, table, result, index); 5103 result.SetCanonical(); // Mark object as being canonical.
5104 // Now add this TypeArgument into the canonical list of type arguments.
5105 bool present = table.Insert(result);
5106 ASSERT(!present);
5340 } 5107 }
5108 object_store->set_canonical_type_arguments(table.Release());
5341 } 5109 }
5342 ASSERT(result.Equals(*this)); 5110 ASSERT(result.Equals(*this));
5343 ASSERT(!result.IsNull()); 5111 ASSERT(!result.IsNull());
5344 ASSERT(result.IsTypeArguments()); 5112 ASSERT(result.IsTypeArguments());
5345 ASSERT(result.IsCanonical()); 5113 ASSERT(result.IsCanonical());
5346 return result.raw(); 5114 return result.raw();
5347 } 5115 }
5348 5116
5349 5117
5350 RawString* TypeArguments::EnumerateURIs() const { 5118 RawString* TypeArguments::EnumerateURIs() const {
(...skipping 10 matching lines...) Expand all
5361 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); 5129 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs()));
5362 } 5130 }
5363 return String::ConcatAll(pieces); 5131 return String::ConcatAll(pieces);
5364 } 5132 }
5365 5133
5366 5134
5367 const char* TypeArguments::ToCString() const { 5135 const char* TypeArguments::ToCString() const {
5368 if (IsNull()) { 5136 if (IsNull()) {
5369 return "NULL TypeArguments"; 5137 return "NULL TypeArguments";
5370 } 5138 }
5371 const char* prev_cstr = "TypeArguments:"; 5139 Zone* zone = Thread::Current()->zone();
5140 const char* prev_cstr = OS::SCreate(
5141 zone, "TypeArguments: (%" Pd ")", Smi::Value(raw_ptr()->hash_));
5372 for (int i = 0; i < Length(); i++) { 5142 for (int i = 0; i < Length(); i++) {
5373 const AbstractType& type_at = AbstractType::Handle(TypeAt(i)); 5143 const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i));
5374 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); 5144 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString();
5375 char* chars = OS::SCreate(Thread::Current()->zone(), 5145 char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr);
5376 "%s [%s]", prev_cstr, type_cstr);
5377 prev_cstr = chars; 5146 prev_cstr = chars;
5378 } 5147 }
5379 return prev_cstr; 5148 return prev_cstr;
5380 } 5149 }
5381 5150
5382 5151
5383 const char* PatchClass::ToCString() const { 5152 const char* PatchClass::ToCString() const {
5384 const Class& cls = Class::Handle(patched_class()); 5153 const Class& cls = Class::Handle(patched_class());
5385 const char* cls_name = cls.ToCString(); 5154 const char* cls_name = cls.ToCString();
5386 return OS::SCreate(Thread::Current()->zone(), 5155 return OS::SCreate(Thread::Current()->zone(),
(...skipping 4081 matching lines...) Expand 10 before | Expand all | Expand 10 after
9468 // Called when growing the table. 9237 // Called when growing the table.
9469 static bool IsMatch(const Object& a, const Object& b) { 9238 static bool IsMatch(const Object& a, const Object& b) {
9470 ASSERT(a.IsLibrary() && b.IsLibrary()); 9239 ASSERT(a.IsLibrary() && b.IsLibrary());
9471 // Library objects are always canonical. 9240 // Library objects are always canonical.
9472 return a.raw() == b.raw(); 9241 return a.raw() == b.raw();
9473 } 9242 }
9474 static uword Hash(const Object& key) { 9243 static uword Hash(const Object& key) {
9475 return Library::Cast(key).UrlHash(); 9244 return Library::Cast(key).UrlHash();
9476 } 9245 }
9477 }; 9246 };
9478
9479
9480 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; 9247 typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet;
9481 9248
9482 9249
9483 RawInstance* Library::TransitiveLoadError() const { 9250 RawInstance* Library::TransitiveLoadError() const {
9484 if (LoadError() != Instance::null()) { 9251 if (LoadError() != Instance::null()) {
9485 return LoadError(); 9252 return LoadError();
9486 } 9253 }
9487 Thread* thread = Thread::Current(); 9254 Thread* thread = Thread::Current();
9488 Isolate* isolate = thread->isolate(); 9255 Isolate* isolate = thread->isolate();
9489 Zone* zone = thread->zone(); 9256 Zone* zone = thread->zone();
(...skipping 5947 matching lines...) Expand 10 before | Expand all | Expand 10 after
15437 ASSERT(instance_size != 0); 15204 ASSERT(instance_size != 0);
15438 uword hash = instance_size; 15205 uword hash = instance_size;
15439 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); 15206 uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
15440 for (intptr_t offset = Instance::NextFieldOffset(); 15207 for (intptr_t offset = Instance::NextFieldOffset();
15441 offset < instance_size; 15208 offset < instance_size;
15442 offset += kWordSize) { 15209 offset += kWordSize) {
15443 uword value = reinterpret_cast<uword>( 15210 uword value = reinterpret_cast<uword>(
15444 *reinterpret_cast<RawObject**>(this_addr + offset)); 15211 *reinterpret_cast<RawObject**>(this_addr + offset));
15445 hash = CombineHashes(hash, value); 15212 hash = CombineHashes(hash, value);
15446 } 15213 }
15447 return FinalizeHash(hash); 15214 return FinalizeHash(hash, (kBitsPerWord - 1));
15448 } 15215 }
15449 15216
15450 15217
15451 #if defined(DEBUG) 15218 #if defined(DEBUG)
15452 class CheckForPointers : public ObjectPointerVisitor { 15219 class CheckForPointers : public ObjectPointerVisitor {
15453 public: 15220 public:
15454 explicit CheckForPointers(Isolate* isolate) 15221 explicit CheckForPointers(Isolate* isolate)
15455 : ObjectPointerVisitor(isolate), has_pointers_(false) {} 15222 : ObjectPointerVisitor(isolate), has_pointers_(false) {}
15456 15223
15457 bool has_pointers() const { return has_pointers_; } 15224 bool has_pointers() const { return has_pointers_; }
(...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after
17217 16984
17218 RawAbstractType* Type::Canonicalize(TrailPtr trail) const { 16985 RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
17219 ASSERT(IsFinalized()); 16986 ASSERT(IsFinalized());
17220 if (IsCanonical() || IsMalformed()) { 16987 if (IsCanonical() || IsMalformed()) {
17221 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld()); 16988 ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
17222 return this->raw(); 16989 return this->raw();
17223 } 16990 }
17224 Thread* thread = Thread::Current(); 16991 Thread* thread = Thread::Current();
17225 Zone* zone = thread->zone(); 16992 Zone* zone = thread->zone();
17226 Isolate* isolate = thread->isolate(); 16993 Isolate* isolate = thread->isolate();
17227 AbstractType& type = Type::Handle(zone); 16994
17228 const Class& cls = Class::Handle(zone, type_class());
17229 // Since void is a keyword, we never have to canonicalize the void type after 16995 // Since void is a keyword, we never have to canonicalize the void type after
17230 // it is canonicalized once by the vm isolate. The parser does the mapping. 16996 // it is canonicalized once by the vm isolate. The parser does the mapping.
17231 ASSERT((cls.raw() != Object::void_class()) || 16997 ASSERT((type_class() != Object::void_class()) ||
17232 (isolate == Dart::vm_isolate())); 16998 (isolate == Dart::vm_isolate()));
16999
17233 // Since dynamic is not a keyword, the parser builds a type that requires 17000 // Since dynamic is not a keyword, the parser builds a type that requires
17234 // canonicalization. 17001 // canonicalization.
17235 if ((cls.raw() == Object::dynamic_class()) && 17002 if ((type_class() == Object::dynamic_class()) &&
17236 (isolate != Dart::vm_isolate())) { 17003 (isolate != Dart::vm_isolate())) {
17237 ASSERT(Object::dynamic_type().IsCanonical()); 17004 ASSERT(Object::dynamic_type().IsCanonical());
17238 return Object::dynamic_type().raw(); 17005 return Object::dynamic_type().raw();
17239 } 17006 }
17007
17008 AbstractType& type = Type::Handle(zone);
17009 const Class& cls = Class::Handle(zone, type_class());
17010
17240 // Fast canonical lookup/registry for simple types. 17011 // Fast canonical lookup/registry for simple types.
17241 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) { 17012 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
17242 ASSERT(!IsFunctionType()); 17013 ASSERT(!IsFunctionType());
17243 type = cls.CanonicalType(); 17014 type = cls.CanonicalType();
17244 if (type.IsNull()) { 17015 if (type.IsNull()) {
17245 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate())); 17016 ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
17246 // Canonicalize the type arguments of the supertype, if any. 17017 // Canonicalize the type arguments of the supertype, if any.
17247 TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); 17018 TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
17248 type_args = type_args.Canonicalize(trail); 17019 type_args = type_args.Canonicalize(trail);
17249 if (IsCanonical()) { 17020 if (IsCanonical()) {
17250 // Canonicalizing type_args canonicalized this type. 17021 // Canonicalizing type_args canonicalized this type.
17251 ASSERT(IsRecursive()); 17022 ASSERT(IsRecursive());
17252 return this->raw(); 17023 return this->raw();
17253 } 17024 }
17254 set_arguments(type_args); 17025 set_arguments(type_args);
17255 type = cls.CanonicalType(); // May be set while canonicalizing type args. 17026 type = cls.CanonicalType(); // May be set while canonicalizing type args.
17256 if (type.IsNull()) { 17027 if (type.IsNull()) {
17257 MutexLocker ml(isolate->type_canonicalization_mutex()); 17028 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
17258 // Recheck if type exists. 17029 // Recheck if type exists.
17259 type = cls.CanonicalType(); 17030 type = cls.CanonicalType();
17260 if (type.IsNull()) { 17031 if (type.IsNull()) {
17032 ComputeHash();
17261 SetCanonical(); 17033 SetCanonical();
17262 cls.set_canonical_types(*this); 17034 cls.set_canonical_type(*this);
17263 return this->raw(); 17035 return this->raw();
17264 } 17036 }
17265 } 17037 }
17266 } 17038 }
17267 ASSERT(this->Equals(type)); 17039 ASSERT(this->Equals(type));
17268 ASSERT(type.IsCanonical()); 17040 ASSERT(type.IsCanonical());
17269 return type.raw(); 17041 return type.raw();
17270 } 17042 }
17271 17043
17272 Array& canonical_types = Array::Handle(zone); 17044 ObjectStore* object_store = isolate->object_store();
17273 canonical_types ^= cls.canonical_types(); 17045 {
17274 if (canonical_types.IsNull()) { 17046 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
17275 canonical_types = empty_array().raw(); 17047 CanonicalTypeSet table(zone, object_store->canonical_types());
17048 type ^= table.GetOrNull(CanonicalTypeKey(*this));
17049 object_store->set_canonical_types(table.Release());
17276 } 17050 }
17277 intptr_t length = canonical_types.Length(); 17051 if (type.IsNull()) {
17278 // Linear search to see whether this type is already present in the 17052 // The type was not found in the table. It is not canonical yet.
17279 // list of canonicalized types. 17053
17280 // TODO(asiva): Try to re-factor this lookup code to make sharing 17054 // Canonicalize the type arguments.
17281 // easy between the 4 versions of this loop. 17055 TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
17282 intptr_t index = 1; // Slot 0 is reserved for CanonicalType(). 17056 // In case the type is first canonicalized at runtime, its type argument
17283 while (index < length) { 17057 // vector may be longer than necessary. This is not an issue.
17284 type ^= canonical_types.At(index); 17058 ASSERT(type_args.IsNull() ||
17059 (type_args.Length() >= cls.NumTypeArguments()));
17060 type_args = type_args.Canonicalize(trail);
17061 if (IsCanonical()) {
17062 // Canonicalizing type_args canonicalized this type as a side effect.
17063 ASSERT(IsRecursive());
17064 // Cycles via typedefs are detected and disallowed, but a function type
17065 // can be recursive due to a cycle in its type arguments.
17066 return this->raw();
17067 }
17068 set_arguments(type_args);
17069 ASSERT(type_args.IsNull() || type_args.IsOld());
17070
17071 // In case of a function type, replace the actual function by a signature
17072 // function.
17073 if (IsFunctionType()) {
17074 const Function& fun = Function::Handle(zone, signature());
17075 if (!fun.IsSignatureFunction()) {
17076 Function& sig_fun = Function::Handle(
17077 zone,
17078 Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
17079 type = fun.result_type();
17080 type = type.Canonicalize(trail);
17081 sig_fun.set_result_type(type);
17082 const intptr_t num_params = fun.NumParameters();
17083 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
17084 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
17085 fun.HasOptionalPositionalParameters());
17086 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
17087 Heap::kOld)));
17088 for (intptr_t i = 0; i < num_params; i++) {
17089 type = fun.ParameterTypeAt(i);
17090 type = type.Canonicalize(trail);
17091 sig_fun.SetParameterTypeAt(i, type);
17092 }
17093 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
17094 set_signature(sig_fun);
17095 }
17096 }
17097
17098 // Check to see if the type got added to canonical list as part of the
17099 // type arguments canonicalization.
17100 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
17101 CanonicalTypeSet table(zone, object_store->canonical_types());
17102 type ^= table.GetOrNull(CanonicalTypeKey(*this));
17285 if (type.IsNull()) { 17103 if (type.IsNull()) {
17286 break; 17104 // Add this Type into the canonical list of types.
17105 type ^= raw();
17106 ASSERT(type.IsOld());
17107 type.SetCanonical(); // Mark object as being canonical.
17108 bool present = table.Insert(type);
17109 ASSERT(!present);
17287 } 17110 }
17288 ASSERT(type.IsFinalized()); 17111 object_store->set_canonical_types(table.Release());
17289 if (this->Equals(type)) {
17290 ASSERT(type.IsCanonical());
17291 return type.raw();
17292 }
17293 index++;
17294 } 17112 }
17295 // The type was not found in the table. It is not canonical yet. 17113 return type.raw();
17296
17297 // Canonicalize the type arguments.
17298 TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
17299 // In case the type is first canonicalized at runtime, its type argument
17300 // vector may be longer than necessary. This is not an issue.
17301 ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
17302 type_args = type_args.Canonicalize(trail);
17303 if (IsCanonical()) {
17304 // Canonicalizing type_args canonicalized this type as a side effect.
17305 ASSERT(IsRecursive());
17306 // Cycles via typedefs are detected and disallowed, but a function type can
17307 // be recursive due to a cycle in its type arguments.
17308 return this->raw();
17309 }
17310 set_arguments(type_args);
17311 ASSERT(type_args.IsNull() || type_args.IsOld());
17312
17313 // In case of a function type, replace the actual function by a signature
17314 // function.
17315 if (IsFunctionType()) {
17316 const Function& fun = Function::Handle(zone, signature());
17317 if (!fun.IsSignatureFunction()) {
17318 Function& sig_fun = Function::Handle(zone,
17319 Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
17320 type = fun.result_type();
17321 type = type.Canonicalize(trail);
17322 sig_fun.set_result_type(type);
17323 const intptr_t num_params = fun.NumParameters();
17324 sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
17325 sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
17326 fun.HasOptionalPositionalParameters());
17327 sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
17328 Heap::kOld)));
17329 for (intptr_t i = 0; i < num_params; i++) {
17330 type = fun.ParameterTypeAt(i);
17331 type = type.Canonicalize(trail);
17332 sig_fun.SetParameterTypeAt(i, type);
17333 }
17334 sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
17335 set_signature(sig_fun);
17336 }
17337 }
17338 return cls.LookupOrAddCanonicalType(*this, index);
17339 } 17114 }
17340 17115
17341 17116
17342 RawString* Type::EnumerateURIs() const { 17117 RawString* Type::EnumerateURIs() const {
17343 if (IsDynamicType() || IsVoidType()) { 17118 if (IsDynamicType() || IsVoidType()) {
17344 return Symbols::Empty().raw(); 17119 return Symbols::Empty().raw();
17345 } 17120 }
17346 Thread* thread = Thread::Current(); 17121 Thread* thread = Thread::Current();
17347 Zone* zone = thread->zone(); 17122 Zone* zone = thread->zone();
17348 GrowableHandlePtrArray<const String> pieces(zone, 6); 17123 GrowableHandlePtrArray<const String> pieces(zone, 6);
(...skipping 20 matching lines...) Expand all
17369 const Library& library = Library::Handle(zone, cls.library()); 17144 const Library& library = Library::Handle(zone, cls.library());
17370 pieces.Add(String::Handle(zone, library.url())); 17145 pieces.Add(String::Handle(zone, library.url()));
17371 pieces.Add(Symbols::NewLine()); 17146 pieces.Add(Symbols::NewLine());
17372 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); 17147 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
17373 pieces.Add(String::Handle(zone, type_args.EnumerateURIs())); 17148 pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
17374 } 17149 }
17375 return Symbols::FromConcatAll(thread, pieces); 17150 return Symbols::FromConcatAll(thread, pieces);
17376 } 17151 }
17377 17152
17378 17153
17379 intptr_t Type::Hash() const { 17154 intptr_t Type::ComputeHash() const {
17380 ASSERT(IsFinalized()); 17155 ASSERT(IsFinalized());
17381 uint32_t result = 1; 17156 uint32_t result = 1;
17382 if (IsMalformed()) return result; 17157 if (IsMalformed()) return result;
17383 result = CombineHashes(result, Class::Handle(type_class()).id()); 17158 result = CombineHashes(result, Class::Handle(type_class()).id());
17384 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash()); 17159 result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
17385 if (IsFunctionType()) { 17160 if (IsFunctionType()) {
17386 const Function& sig_fun = Function::Handle(signature()); 17161 const Function& sig_fun = Function::Handle(signature());
17387 AbstractType& type = AbstractType::Handle(sig_fun.result_type()); 17162 AbstractType& type = AbstractType::Handle(sig_fun.result_type());
17388 result = CombineHashes(result, type.Hash()); 17163 result = CombineHashes(result, type.Hash());
17389 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters()); 17164 result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
17390 const intptr_t num_params = sig_fun.NumParameters(); 17165 const intptr_t num_params = sig_fun.NumParameters();
17391 for (intptr_t i = 0; i < num_params; i++) { 17166 for (intptr_t i = 0; i < num_params; i++) {
17392 type = sig_fun.ParameterTypeAt(i); 17167 type = sig_fun.ParameterTypeAt(i);
17393 result = CombineHashes(result, type.Hash()); 17168 result = CombineHashes(result, type.Hash());
17394 } 17169 }
17395 if (sig_fun.NumOptionalNamedParameters() > 0) { 17170 if (sig_fun.NumOptionalNamedParameters() > 0) {
17396 String& param_name = String::Handle(); 17171 String& param_name = String::Handle();
17397 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { 17172 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
17398 param_name = sig_fun.ParameterNameAt(i); 17173 param_name = sig_fun.ParameterNameAt(i);
17399 result = CombineHashes(result, param_name.Hash()); 17174 result = CombineHashes(result, param_name.Hash());
17400 } 17175 }
17401 } 17176 }
17402 } 17177 }
17403 return FinalizeHash(result); 17178 result = FinalizeHash(result, kHashBits);
17179 SetHash(result);
17180 return result;
17404 } 17181 }
17405 17182
17406 17183
17407 void Type::set_type_class(const Class& value) const { 17184 void Type::set_type_class(const Class& value) const {
17408 ASSERT(!value.IsNull()); 17185 ASSERT(!value.IsNull());
17409 StorePointer(&raw_ptr()->type_class_id_, 17186 StorePointer(&raw_ptr()->type_class_id_,
17410 reinterpret_cast<RawObject*>(Smi::New(value.id()))); 17187 reinterpret_cast<RawObject*>(Smi::New(value.id())));
17411 } 17188 }
17412 17189
17413 17190
(...skipping 21 matching lines...) Expand all
17435 const TypeArguments& arguments, 17212 const TypeArguments& arguments,
17436 TokenPosition token_pos, 17213 TokenPosition token_pos,
17437 Heap::Space space) { 17214 Heap::Space space) {
17438 const Type& result = Type::Handle(Type::New(space)); 17215 const Type& result = Type::Handle(Type::New(space));
17439 if (clazz.IsClass()) { 17216 if (clazz.IsClass()) {
17440 result.set_type_class(Class::Cast(clazz)); 17217 result.set_type_class(Class::Cast(clazz));
17441 } else { 17218 } else {
17442 result.set_unresolved_class(clazz); 17219 result.set_unresolved_class(clazz);
17443 } 17220 }
17444 result.set_arguments(arguments); 17221 result.set_arguments(arguments);
17222 result.SetHash(0);
17445 result.set_token_pos(token_pos); 17223 result.set_token_pos(token_pos);
17446 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); 17224 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
17447 return result.raw(); 17225 return result.raw();
17448 } 17226 }
17449 17227
17450 17228
17451 void Type::set_token_pos(TokenPosition token_pos) const { 17229 void Type::set_token_pos(TokenPosition token_pos) const {
17452 ASSERT(!token_pos.IsClassifying()); 17230 ASSERT(!token_pos.IsClassifying());
17453 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); 17231 StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
17454 } 17232 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
17614 pieces.Add(String::Handle(zone, library.url())); 17392 pieces.Add(String::Handle(zone, library.url()));
17615 pieces.Add(Symbols::NewLine()); 17393 pieces.Add(Symbols::NewLine());
17616 return Symbols::FromConcatAll(thread, pieces); 17394 return Symbols::FromConcatAll(thread, pieces);
17617 } 17395 }
17618 17396
17619 17397
17620 intptr_t TypeRef::Hash() const { 17398 intptr_t TypeRef::Hash() const {
17621 // Do not calculate the hash of the referenced type to avoid divergence. 17399 // Do not calculate the hash of the referenced type to avoid divergence.
17622 const uint32_t result = 17400 const uint32_t result =
17623 Class::Handle(AbstractType::Handle(type()).type_class()).id(); 17401 Class::Handle(AbstractType::Handle(type()).type_class()).id();
17624 return FinalizeHash(result); 17402 return FinalizeHash(result, kHashBits);
17625 } 17403 }
17626 17404
17627 17405
17628 RawTypeRef* TypeRef::New() { 17406 RawTypeRef* TypeRef::New() {
17629 RawObject* raw = Object::Allocate(TypeRef::kClassId, 17407 RawObject* raw = Object::Allocate(TypeRef::kClassId,
17630 TypeRef::InstanceSize(), 17408 TypeRef::InstanceSize(),
17631 Heap::kOld); 17409 Heap::kOld);
17632 return reinterpret_cast<RawTypeRef*>(raw); 17410 return reinterpret_cast<RawTypeRef*>(raw);
17633 } 17411 }
17634 17412
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
17862 const Class& cls = Class::Handle(zone, parameterized_class()); 17640 const Class& cls = Class::Handle(zone, parameterized_class());
17863 pieces.Add(String::Handle(zone, cls.UserVisibleName())); 17641 pieces.Add(String::Handle(zone, cls.UserVisibleName()));
17864 pieces.Add(Symbols::SpaceIsFromSpace()); 17642 pieces.Add(Symbols::SpaceIsFromSpace());
17865 const Library& library = Library::Handle(zone, cls.library()); 17643 const Library& library = Library::Handle(zone, cls.library());
17866 pieces.Add(String::Handle(zone, library.url())); 17644 pieces.Add(String::Handle(zone, library.url()));
17867 pieces.Add(Symbols::NewLine()); 17645 pieces.Add(Symbols::NewLine());
17868 return Symbols::FromConcatAll(thread, pieces); 17646 return Symbols::FromConcatAll(thread, pieces);
17869 } 17647 }
17870 17648
17871 17649
17872 intptr_t TypeParameter::Hash() const { 17650 intptr_t TypeParameter::ComputeHash() const {
17873 ASSERT(IsFinalized()); 17651 ASSERT(IsFinalized());
17874 uint32_t result = Class::Handle(parameterized_class()).id(); 17652 uint32_t result = Class::Handle(parameterized_class()).id();
17875 // No need to include the hash of the bound, since the type parameter is fully 17653 // No need to include the hash of the bound, since the type parameter is fully
17876 // identified by its class and index. 17654 // identified by its class and index.
17877 result = CombineHashes(result, index()); 17655 result = CombineHashes(result, index());
17878 return FinalizeHash(result); 17656 result = FinalizeHash(result, kHashBits);
17657 SetHash(result);
17658 return result;
17879 } 17659 }
17880 17660
17881 17661
17882 RawTypeParameter* TypeParameter::New() { 17662 RawTypeParameter* TypeParameter::New() {
17883 RawObject* raw = Object::Allocate(TypeParameter::kClassId, 17663 RawObject* raw = Object::Allocate(TypeParameter::kClassId,
17884 TypeParameter::InstanceSize(), 17664 TypeParameter::InstanceSize(),
17885 Heap::kOld); 17665 Heap::kOld);
17886 return reinterpret_cast<RawTypeParameter*>(raw); 17666 return reinterpret_cast<RawTypeParameter*>(raw);
17887 } 17667 }
17888 17668
17889 17669
17890 RawTypeParameter* TypeParameter::New(const Class& parameterized_class, 17670 RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
17891 intptr_t index, 17671 intptr_t index,
17892 const String& name, 17672 const String& name,
17893 const AbstractType& bound, 17673 const AbstractType& bound,
17894 TokenPosition token_pos) { 17674 TokenPosition token_pos) {
17895 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New()); 17675 const TypeParameter& result = TypeParameter::Handle(TypeParameter::New());
17896 result.set_parameterized_class(parameterized_class); 17676 result.set_parameterized_class(parameterized_class);
17897 result.set_index(index); 17677 result.set_index(index);
17898 result.set_name(name); 17678 result.set_name(name);
17899 result.set_bound(bound); 17679 result.set_bound(bound);
17680 result.SetHash(0);
17900 result.set_token_pos(token_pos); 17681 result.set_token_pos(token_pos);
17901 result.StoreNonPointer(&result.raw_ptr()->type_state_, 17682 result.StoreNonPointer(&result.raw_ptr()->type_state_,
17902 RawTypeParameter::kAllocated); 17683 RawTypeParameter::kAllocated);
17903 return result.raw(); 17684 return result.raw();
17904 } 17685 }
17905 17686
17906 17687
17907 void TypeParameter::set_token_pos(TokenPosition token_pos) const { 17688 void TypeParameter::set_token_pos(TokenPosition token_pos) const {
17908 ASSERT(!token_pos.IsClassifying()); 17689 ASSERT(!token_pos.IsClassifying());
17909 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); 17690 StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
18126 return BoundedType::New(bounded_type, upper_bound, type_param); 17907 return BoundedType::New(bounded_type, upper_bound, type_param);
18127 } 17908 }
18128 17909
18129 17910
18130 RawString* BoundedType::EnumerateURIs() const { 17911 RawString* BoundedType::EnumerateURIs() const {
18131 // The bound does not appear in the user visible name. 17912 // The bound does not appear in the user visible name.
18132 return AbstractType::Handle(type()).EnumerateURIs(); 17913 return AbstractType::Handle(type()).EnumerateURIs();
18133 } 17914 }
18134 17915
18135 17916
18136 intptr_t BoundedType::Hash() const { 17917 intptr_t BoundedType::ComputeHash() const {
18137 uint32_t result = AbstractType::Handle(type()).Hash(); 17918 uint32_t result = AbstractType::Handle(type()).Hash();
18138 // No need to include the hash of the bound, since the bound is defined by the 17919 // No need to include the hash of the bound, since the bound is defined by the
18139 // type parameter (modulo instantiation state). 17920 // type parameter (modulo instantiation state).
18140 result = CombineHashes(result, 17921 result = CombineHashes(result,
18141 TypeParameter::Handle(type_parameter()).Hash()); 17922 TypeParameter::Handle(type_parameter()).Hash());
18142 return FinalizeHash(result); 17923 result = FinalizeHash(result, kHashBits);
17924 SetHash(result);
17925 return result;
18143 } 17926 }
18144 17927
18145 17928
18146 RawBoundedType* BoundedType::New() { 17929 RawBoundedType* BoundedType::New() {
18147 RawObject* raw = Object::Allocate(BoundedType::kClassId, 17930 RawObject* raw = Object::Allocate(BoundedType::kClassId,
18148 BoundedType::InstanceSize(), 17931 BoundedType::InstanceSize(),
18149 Heap::kOld); 17932 Heap::kOld);
18150 return reinterpret_cast<RawBoundedType*>(raw); 17933 return reinterpret_cast<RawBoundedType*>(raw);
18151 } 17934 }
18152 17935
18153 17936
18154 RawBoundedType* BoundedType::New(const AbstractType& type, 17937 RawBoundedType* BoundedType::New(const AbstractType& type,
18155 const AbstractType& bound, 17938 const AbstractType& bound,
18156 const TypeParameter& type_parameter) { 17939 const TypeParameter& type_parameter) {
18157 const BoundedType& result = BoundedType::Handle(BoundedType::New()); 17940 const BoundedType& result = BoundedType::Handle(BoundedType::New());
18158 result.set_type(type); 17941 result.set_type(type);
18159 result.set_bound(bound); 17942 result.set_bound(bound);
17943 result.SetHash(0);
18160 result.set_type_parameter(type_parameter); 17944 result.set_type_parameter(type_parameter);
18161 return result.raw(); 17945 return result.raw();
18162 } 17946 }
18163 17947
18164 17948
18165 const char* BoundedType::ToCString() const { 17949 const char* BoundedType::ToCString() const {
18166 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s"; 17950 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s";
18167 const char* type_cstr = String::Handle(AbstractType::Handle( 17951 const char* type_cstr = String::Handle(AbstractType::Handle(
18168 type()).Name()).ToCString(); 17952 type()).Name()).ToCString();
18169 const char* bound_cstr = String::Handle(AbstractType::Handle( 17953 const char* bound_cstr = String::Handle(AbstractType::Handle(
(...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after
19687 public: 19471 public:
19688 StringHasher() : hash_(0) {} 19472 StringHasher() : hash_(0) {}
19689 void Add(int32_t ch) { 19473 void Add(int32_t ch) {
19690 hash_ = CombineHashes(hash_, ch); 19474 hash_ = CombineHashes(hash_, ch);
19691 } 19475 }
19692 void Add(const String& str, intptr_t begin_index, intptr_t len); 19476 void Add(const String& str, intptr_t begin_index, intptr_t len);
19693 19477
19694 // Return a non-zero hash of at most 'bits' bits. 19478 // Return a non-zero hash of at most 'bits' bits.
19695 intptr_t Finalize(int bits) { 19479 intptr_t Finalize(int bits) {
19696 ASSERT(1 <= bits && bits <= (kBitsPerWord - 1)); 19480 ASSERT(1 <= bits && bits <= (kBitsPerWord - 1));
19697 hash_ = FinalizeHash(hash_); 19481 hash_ = FinalizeHash(hash_, bits);
19698 hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
19699 ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32)); 19482 ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32));
19700 return hash_ == 0 ? 1 : hash_; 19483 return hash_;
19701 } 19484 }
19702 private: 19485 private:
19703 uint32_t hash_; 19486 uint32_t hash_;
19704 }; 19487 };
19705 19488
19706 19489
19707 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) { 19490 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) {
19708 ASSERT(begin_index >= 0); 19491 ASSERT(begin_index >= 0);
19709 ASSERT(len >= 0); 19492 ASSERT(len >= 0);
19710 ASSERT((begin_index + len) <= str.Length()); 19493 ASSERT((begin_index + len) <= str.Length());
(...skipping 12 matching lines...) Expand all
19723 while (it.Next()) { 19506 while (it.Next()) {
19724 Add(it.Current()); 19507 Add(it.Current());
19725 } 19508 }
19726 } 19509 }
19727 } 19510 }
19728 19511
19729 19512
19730 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) { 19513 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
19731 StringHasher hasher; 19514 StringHasher hasher;
19732 hasher.Add(str, begin_index, len); 19515 hasher.Add(str, begin_index, len);
19733 return hasher.Finalize(String::kHashBits); 19516 return hasher.Finalize(kHashBits);
19734 } 19517 }
19735 19518
19736 19519
19737 intptr_t String::HashConcat(const String& str1, const String& str2) { 19520 intptr_t String::HashConcat(const String& str1, const String& str2) {
19738 intptr_t len1 = str1.Length(); 19521 intptr_t len1 = str1.Length();
19739 // Since String::Hash works at the code point (rune) level, a surrogate pair 19522 // Since String::Hash works at the code point (rune) level, a surrogate pair
19740 // that crosses the boundary between str1 and str2 must be composed. 19523 // that crosses the boundary between str1 and str2 must be composed.
19741 if (str1.IsTwoByteString() && Utf16::IsLeadSurrogate(str1.CharAt(len1 - 1))) { 19524 if (str1.IsTwoByteString() && Utf16::IsLeadSurrogate(str1.CharAt(len1 - 1))) {
19742 const String& temp = String::Handle(String::Concat(str1, str2)); 19525 const String& temp = String::Handle(String::Concat(str1, str2));
19743 return temp.Hash(); 19526 return temp.Hash();
19744 } else { 19527 } else {
19745 StringHasher hasher; 19528 StringHasher hasher;
19746 hasher.Add(str1, 0, len1); 19529 hasher.Add(str1, 0, len1);
19747 hasher.Add(str2, 0, str2.Length()); 19530 hasher.Add(str2, 0, str2.Length());
19748 return hasher.Finalize(String::kHashBits); 19531 return hasher.Finalize(kHashBits);
19749 } 19532 }
19750 } 19533 }
19751 19534
19752 19535
19753 template<typename T> 19536 template<typename T>
19754 static intptr_t HashImpl(const T* characters, intptr_t len) { 19537 static intptr_t HashImpl(const T* characters, intptr_t len) {
19755 ASSERT(len >= 0); 19538 ASSERT(len >= 0);
19756 StringHasher hasher; 19539 StringHasher hasher;
19757 for (intptr_t i = 0; i < len; i++) { 19540 for (intptr_t i = 0; i < len; i++) {
19758 hasher.Add(characters[i]); 19541 hasher.Add(characters[i]);
(...skipping 11 matching lines...) Expand all
19770 return HashImpl(characters, len); 19553 return HashImpl(characters, len);
19771 } 19554 }
19772 19555
19773 19556
19774 intptr_t String::Hash(const uint16_t* characters, intptr_t len) { 19557 intptr_t String::Hash(const uint16_t* characters, intptr_t len) {
19775 StringHasher hasher; 19558 StringHasher hasher;
19776 intptr_t i = 0; 19559 intptr_t i = 0;
19777 while (i < len) { 19560 while (i < len) {
19778 hasher.Add(Utf16::Next(characters, &i, len)); 19561 hasher.Add(Utf16::Next(characters, &i, len));
19779 } 19562 }
19780 return hasher.Finalize(String::kHashBits); 19563 return hasher.Finalize(kHashBits);
19781 } 19564 }
19782 19565
19783 19566
19784 intptr_t String::Hash(const int32_t* characters, intptr_t len) { 19567 intptr_t String::Hash(const int32_t* characters, intptr_t len) {
19785 return HashImpl(characters, len); 19568 return HashImpl(characters, len);
19786 } 19569 }
19787 19570
19788 19571
19789 uint16_t String::CharAt(intptr_t index) const { 19572 uint16_t String::CharAt(intptr_t index) const {
19790 intptr_t class_id = raw()->GetClassId(); 19573 intptr_t class_id = raw()->GetClassId();
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after
21467 uword Array::ComputeCanonicalTableHash() const { 21250 uword Array::ComputeCanonicalTableHash() const {
21468 ASSERT(!IsNull()); 21251 ASSERT(!IsNull());
21469 intptr_t len = Length(); 21252 intptr_t len = Length();
21470 uword hash = len; 21253 uword hash = len;
21471 uword value = reinterpret_cast<uword>(GetTypeArguments()); 21254 uword value = reinterpret_cast<uword>(GetTypeArguments());
21472 hash = CombineHashes(hash, value); 21255 hash = CombineHashes(hash, value);
21473 for (intptr_t i = 0; i < len; i++) { 21256 for (intptr_t i = 0; i < len; i++) {
21474 value = reinterpret_cast<uword>(At(i)); 21257 value = reinterpret_cast<uword>(At(i));
21475 hash = CombineHashes(hash, value); 21258 hash = CombineHashes(hash, value);
21476 } 21259 }
21477 return FinalizeHash(hash); 21260 return FinalizeHash(hash, kHashBits);
21478 } 21261 }
21479 21262
21480 21263
21481 RawArray* Array::New(intptr_t len, Heap::Space space) { 21264 RawArray* Array::New(intptr_t len, Heap::Space space) {
21482 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); 21265 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
21483 return New(kClassId, len, space); 21266 return New(kClassId, len, space);
21484 } 21267 }
21485 21268
21486 21269
21487 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { 21270 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) {
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
22124 } 21907 }
22125 21908
22126 21909
22127 uword TypedData::ComputeCanonicalTableHash() const { 21910 uword TypedData::ComputeCanonicalTableHash() const {
22128 const intptr_t len = this->LengthInBytes(); 21911 const intptr_t len = this->LengthInBytes();
22129 ASSERT(len != 0); 21912 ASSERT(len != 0);
22130 uword hash = len; 21913 uword hash = len;
22131 for (intptr_t i = 0; i < len; i++) { 21914 for (intptr_t i = 0; i < len; i++) {
22132 hash = CombineHashes(len, GetUint8(i)); 21915 hash = CombineHashes(len, GetUint8(i));
22133 } 21916 }
22134 return FinalizeHash(hash); 21917 return FinalizeHash(hash, kHashBits);
22135 } 21918 }
22136 21919
22137 21920
22138 RawTypedData* TypedData::New(intptr_t class_id, 21921 RawTypedData* TypedData::New(intptr_t class_id,
22139 intptr_t len, 21922 intptr_t len,
22140 Heap::Space space) { 21923 Heap::Space space) {
22141 if (len < 0 || len > TypedData::MaxElements(class_id)) { 21924 if (len < 0 || len > TypedData::MaxElements(class_id)) {
22142 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); 21925 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len);
22143 } 21926 }
22144 TypedData& result = TypedData::Handle(); 21927 TypedData& result = TypedData::Handle();
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
22822 return UserTag::null(); 22605 return UserTag::null();
22823 } 22606 }
22824 22607
22825 22608
22826 const char* UserTag::ToCString() const { 22609 const char* UserTag::ToCString() const {
22827 const String& tag_label = String::Handle(label()); 22610 const String& tag_label = String::Handle(label());
22828 return tag_label.ToCString(); 22611 return tag_label.ToCString();
22829 } 22612 }
22830 22613
22831 } // namespace dart 22614 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_reload.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698