| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 Class::NewTypedDataClass(kTypedDataInt8ArrayCid); | 698 Class::NewTypedDataClass(kTypedDataInt8ArrayCid); |
| 699 | 699 |
| 700 // Allocate and initialize the empty_array instance. | 700 // Allocate and initialize the empty_array instance. |
| 701 { | 701 { |
| 702 uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld); | 702 uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld); |
| 703 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0), true); | 703 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0), true); |
| 704 Array::initializeHandle( | 704 Array::initializeHandle( |
| 705 empty_array_, | 705 empty_array_, |
| 706 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); | 706 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); |
| 707 empty_array_->StoreSmi(&empty_array_->raw_ptr()->length_, Smi::New(0)); | 707 empty_array_->StoreSmi(&empty_array_->raw_ptr()->length_, Smi::New(0)); |
| 708 empty_array_->SetCanonical(); |
| 708 } | 709 } |
| 709 | 710 |
| 710 Smi& smi = Smi::Handle(); | 711 Smi& smi = Smi::Handle(); |
| 711 // Allocate and initialize the zero_array instance. | 712 // Allocate and initialize the zero_array instance. |
| 712 { | 713 { |
| 713 uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); | 714 uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); |
| 714 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); | 715 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); |
| 715 Array::initializeHandle( | 716 Array::initializeHandle( |
| 716 zero_array_, | 717 zero_array_, |
| 717 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); | 718 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); |
| 718 zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1)); | 719 zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1)); |
| 719 smi = Smi::New(0); | 720 smi = Smi::New(0); |
| 720 zero_array_->SetAt(0, smi); | 721 zero_array_->SetAt(0, smi); |
| 722 zero_array_->SetCanonical(); |
| 721 } | 723 } |
| 722 | 724 |
| 723 // Allocate and initialize the canonical empty context scope object. | 725 // Allocate and initialize the canonical empty context scope object. |
| 724 { | 726 { |
| 725 uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld); | 727 uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld); |
| 726 InitializeObject(address, | 728 InitializeObject(address, |
| 727 kContextScopeCid, | 729 kContextScopeCid, |
| 728 ContextScope::InstanceSize(0), | 730 ContextScope::InstanceSize(0), |
| 729 true); | 731 true); |
| 730 ContextScope::initializeHandle( | 732 ContextScope::initializeHandle( |
| 731 empty_context_scope_, | 733 empty_context_scope_, |
| 732 reinterpret_cast<RawContextScope*>(address + kHeapObjectTag)); | 734 reinterpret_cast<RawContextScope*>(address + kHeapObjectTag)); |
| 733 empty_context_scope_->StoreNonPointer( | 735 empty_context_scope_->StoreNonPointer( |
| 734 &empty_context_scope_->raw_ptr()->num_variables_, 0); | 736 &empty_context_scope_->raw_ptr()->num_variables_, 0); |
| 735 empty_context_scope_->StoreNonPointer( | 737 empty_context_scope_->StoreNonPointer( |
| 736 &empty_context_scope_->raw_ptr()->is_implicit_, true); | 738 &empty_context_scope_->raw_ptr()->is_implicit_, true); |
| 739 empty_context_scope_->SetCanonical(); |
| 737 } | 740 } |
| 738 | 741 |
| 739 // Allocate and initialize the canonical empty object pool object. | 742 // Allocate and initialize the canonical empty object pool object. |
| 740 { | 743 { |
| 741 uword address = | 744 uword address = |
| 742 heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); | 745 heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); |
| 743 InitializeObject(address, | 746 InitializeObject(address, |
| 744 kObjectPoolCid, | 747 kObjectPoolCid, |
| 745 ObjectPool::InstanceSize(0), | 748 ObjectPool::InstanceSize(0), |
| 746 true); | 749 true); |
| 747 ObjectPool::initializeHandle( | 750 ObjectPool::initializeHandle( |
| 748 empty_object_pool_, | 751 empty_object_pool_, |
| 749 reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag)); | 752 reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag)); |
| 750 empty_object_pool_->StoreNonPointer( | 753 empty_object_pool_->StoreNonPointer( |
| 751 &empty_object_pool_->raw_ptr()->length_, 0); | 754 &empty_object_pool_->raw_ptr()->length_, 0); |
| 755 empty_object_pool_->SetCanonical(); |
| 752 } | 756 } |
| 753 | 757 |
| 754 // Allocate and initialize the empty_descriptors instance. | 758 // Allocate and initialize the empty_descriptors instance. |
| 755 { | 759 { |
| 756 uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); | 760 uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); |
| 757 InitializeObject(address, kPcDescriptorsCid, | 761 InitializeObject(address, kPcDescriptorsCid, |
| 758 PcDescriptors::InstanceSize(0), | 762 PcDescriptors::InstanceSize(0), |
| 759 true); | 763 true); |
| 760 PcDescriptors::initializeHandle( | 764 PcDescriptors::initializeHandle( |
| 761 empty_descriptors_, | 765 empty_descriptors_, |
| 762 reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag)); | 766 reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag)); |
| 763 empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_, | 767 empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_, |
| 764 0); | 768 0); |
| 769 empty_descriptors_->SetCanonical(); |
| 765 } | 770 } |
| 766 | 771 |
| 767 // Allocate and initialize the canonical empty variable descriptor object. | 772 // Allocate and initialize the canonical empty variable descriptor object. |
| 768 { | 773 { |
| 769 uword address = | 774 uword address = |
| 770 heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); | 775 heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); |
| 771 InitializeObject(address, | 776 InitializeObject(address, |
| 772 kLocalVarDescriptorsCid, | 777 kLocalVarDescriptorsCid, |
| 773 LocalVarDescriptors::InstanceSize(0), | 778 LocalVarDescriptors::InstanceSize(0), |
| 774 true); | 779 true); |
| 775 LocalVarDescriptors::initializeHandle( | 780 LocalVarDescriptors::initializeHandle( |
| 776 empty_var_descriptors_, | 781 empty_var_descriptors_, |
| 777 reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag)); | 782 reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag)); |
| 778 empty_var_descriptors_->StoreNonPointer( | 783 empty_var_descriptors_->StoreNonPointer( |
| 779 &empty_var_descriptors_->raw_ptr()->num_entries_, 0); | 784 &empty_var_descriptors_->raw_ptr()->num_entries_, 0); |
| 785 empty_var_descriptors_->SetCanonical(); |
| 780 } | 786 } |
| 781 | 787 |
| 782 // Allocate and initialize the canonical empty exception handler info object. | 788 // Allocate and initialize the canonical empty exception handler info object. |
| 783 // The vast majority of all functions do not contain an exception handler | 789 // The vast majority of all functions do not contain an exception handler |
| 784 // and can share this canonical descriptor. | 790 // and can share this canonical descriptor. |
| 785 { | 791 { |
| 786 uword address = | 792 uword address = |
| 787 heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); | 793 heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); |
| 788 InitializeObject(address, | 794 InitializeObject(address, |
| 789 kExceptionHandlersCid, | 795 kExceptionHandlersCid, |
| 790 ExceptionHandlers::InstanceSize(0), | 796 ExceptionHandlers::InstanceSize(0), |
| 791 true); | 797 true); |
| 792 ExceptionHandlers::initializeHandle( | 798 ExceptionHandlers::initializeHandle( |
| 793 empty_exception_handlers_, | 799 empty_exception_handlers_, |
| 794 reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag)); | 800 reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag)); |
| 795 empty_exception_handlers_->StoreNonPointer( | 801 empty_exception_handlers_->StoreNonPointer( |
| 796 &empty_exception_handlers_->raw_ptr()->num_entries_, 0); | 802 &empty_exception_handlers_->raw_ptr()->num_entries_, 0); |
| 803 empty_exception_handlers_->SetCanonical(); |
| 797 } | 804 } |
| 798 | 805 |
| 799 // The VM isolate snapshot object table is initialized to an empty array | 806 // The VM isolate snapshot object table is initialized to an empty array |
| 800 // as we do not have any VM isolate snapshot at this time. | 807 // as we do not have any VM isolate snapshot at this time. |
| 801 *vm_isolate_snapshot_object_table_ = Object::empty_array().raw(); | 808 *vm_isolate_snapshot_object_table_ = Object::empty_array().raw(); |
| 802 | 809 |
| 803 cls = Class::New<Instance>(kDynamicCid); | 810 cls = Class::New<Instance>(kDynamicCid); |
| 804 cls.set_is_abstract(); | 811 cls.set_is_abstract(); |
| 805 cls.set_num_type_arguments(0); | 812 cls.set_num_type_arguments(0); |
| 806 cls.set_num_own_type_arguments(0); | 813 cls.set_num_own_type_arguments(0); |
| (...skipping 3607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4414 if (canonical_value.Equals(value)) { | 4421 if (canonical_value.Equals(value)) { |
| 4415 ASSERT(canonical_value.IsCanonical()); | 4422 ASSERT(canonical_value.IsCanonical()); |
| 4416 return canonical_value.raw(); | 4423 return canonical_value.raw(); |
| 4417 } | 4424 } |
| 4418 *index = *index + 1; | 4425 *index = *index + 1; |
| 4419 } | 4426 } |
| 4420 return Bigint::null(); | 4427 return Bigint::null(); |
| 4421 } | 4428 } |
| 4422 | 4429 |
| 4423 | 4430 |
| 4431 class CanonicalInstanceKey { |
| 4432 public: |
| 4433 explicit CanonicalInstanceKey(const Instance& key) : key_(key) { |
| 4434 ASSERT(!(key.IsString() || key.IsInteger() || key.IsAbstractType())); |
| 4435 } |
| 4436 bool Matches(const Instance& obj) const { |
| 4437 ASSERT(!(obj.IsString() || obj.IsInteger() || obj.IsAbstractType())); |
| 4438 if (key_.CanonicalizeEquals(obj)) { |
| 4439 ASSERT(obj.IsCanonical()); |
| 4440 return true; |
| 4441 } |
| 4442 return false; |
| 4443 } |
| 4444 uword Hash() const { |
| 4445 return key_.ComputeCanonicalTableHash(); |
| 4446 } |
| 4447 const Instance& key_; |
| 4448 |
| 4449 private: |
| 4450 DISALLOW_ALLOCATION(); |
| 4451 }; |
| 4452 |
| 4453 |
| 4454 // Traits for looking up Canonical Instances based on a hash of the fields. |
| 4455 class CanonicalInstanceTraits { |
| 4456 public: |
| 4457 static const char* Name() { return "CanonicalInstanceTraits"; } |
| 4458 static bool ReportStats() { return false; } |
| 4459 |
| 4460 // Called when growing the table. |
| 4461 static bool IsMatch(const Object& a, const Object& b) { |
| 4462 ASSERT(!(a.IsString() || a.IsInteger() || a.IsAbstractType())); |
| 4463 ASSERT(!(b.IsString() || b.IsInteger() || b.IsAbstractType())); |
| 4464 return a.raw() == b.raw(); |
| 4465 } |
| 4466 static bool IsMatch(const CanonicalInstanceKey& a, const Object& b) { |
| 4467 return a.Matches(Instance::Cast(b)); |
| 4468 } |
| 4469 static uword Hash(const Object& key) { |
| 4470 ASSERT(!(key.IsString() || key.IsNumber() || key.IsAbstractType())); |
| 4471 ASSERT(key.IsInstance()); |
| 4472 return Instance::Cast(key).ComputeCanonicalTableHash(); |
| 4473 } |
| 4474 static uword Hash(const CanonicalInstanceKey& key) { |
| 4475 return key.Hash(); |
| 4476 } |
| 4477 static RawObject* NewKey(const CanonicalInstanceKey& obj) { |
| 4478 return obj.key_.raw(); |
| 4479 } |
| 4480 }; |
| 4481 typedef UnorderedHashSet <CanonicalInstanceTraits> CanonicalInstancesSet; |
| 4482 |
| 4483 |
| 4424 RawInstance* Class::LookupCanonicalInstance(Zone* zone, | 4484 RawInstance* Class::LookupCanonicalInstance(Zone* zone, |
| 4425 const Instance& value, | 4485 const Instance& value) const { |
| 4426 intptr_t* index) const { | |
| 4427 ASSERT(this->raw() == value.clazz()); | 4486 ASSERT(this->raw() == value.clazz()); |
| 4428 const Array& constants = Array::Handle(zone, this->constants()); | |
| 4429 const intptr_t constants_len = constants.Length(); | |
| 4430 // Linear search to see whether this value is already present in the | |
| 4431 // list of canonicalized constants. | |
| 4432 Instance& canonical_value = Instance::Handle(zone); | 4487 Instance& canonical_value = Instance::Handle(zone); |
| 4433 while (*index < constants_len) { | 4488 if (this->constants() != Object::empty_array().raw()) { |
| 4434 canonical_value ^= constants.At(*index); | 4489 CanonicalInstancesSet constants(zone, this->constants()); |
| 4435 if (canonical_value.IsNull()) { | 4490 canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value)); |
| 4436 break; | 4491 this->set_constants(constants.Release()); |
| 4437 } | |
| 4438 if (value.CanonicalizeEquals(canonical_value)) { | |
| 4439 ASSERT(canonical_value.IsCanonical()); | |
| 4440 return canonical_value.raw(); | |
| 4441 } | |
| 4442 *index = *index + 1; | |
| 4443 } | 4492 } |
| 4444 return Instance::null(); | 4493 return canonical_value.raw(); |
| 4445 } | 4494 } |
| 4446 | 4495 |
| 4447 | 4496 |
| 4448 void Class::InsertCanonicalConstant(intptr_t index, | 4497 RawInstance* Class::InsertCanonicalConstant(Zone* zone, |
| 4449 const Instance& constant) const { | 4498 const Instance& constant) const { |
| 4450 // The constant needs to be added to the list. Grow the list if it is full. | 4499 ASSERT(this->raw() == constant.clazz()); |
| 4451 Array& canonical_list = Array::Handle(constants()); | 4500 Instance& canonical_value = Instance::Handle(zone); |
| 4452 const intptr_t list_len = canonical_list.Length(); | 4501 if (this->constants() == Object::empty_array().raw()) { |
| 4453 if (index >= list_len) { | 4502 CanonicalInstancesSet constants( |
| 4454 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; | 4503 HashTables::New<CanonicalInstancesSet>(128, Heap::kOld)); |
| 4455 const Array& new_canonical_list = | 4504 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); |
| 4456 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); | 4505 this->set_constants(constants.Release()); |
| 4457 set_constants(new_canonical_list); | |
| 4458 new_canonical_list.SetAt(index, constant); | |
| 4459 } else { | 4506 } else { |
| 4460 canonical_list.SetAt(index, constant); | 4507 CanonicalInstancesSet constants(Thread::Current()->zone(), |
| 4508 this->constants()); |
| 4509 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); |
| 4510 this->set_constants(constants.Release()); |
| 4461 } | 4511 } |
| 4512 return canonical_value.raw(); |
| 4462 } | 4513 } |
| 4463 | 4514 |
| 4464 | 4515 |
| 4465 void Class::InsertCanonicalNumber(Zone* zone, | 4516 void Class::InsertCanonicalNumber(Zone* zone, |
| 4466 intptr_t index, | 4517 intptr_t index, |
| 4467 const Number& constant) const { | 4518 const Number& constant) const { |
| 4468 // The constant needs to be added to the list. Grow the list if it is full. | 4519 // The constant needs to be added to the list. Grow the list if it is full. |
| 4469 Array& canonical_list = Array::Handle(zone, constants()); | 4520 Array& canonical_list = Array::Handle(zone, constants()); |
| 4470 const intptr_t list_len = canonical_list.Length(); | 4521 const intptr_t list_len = canonical_list.Length(); |
| 4471 if (index >= list_len) { | 4522 if (index >= list_len) { |
| 4472 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; | 4523 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; |
| 4473 canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld); | 4524 canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld); |
| 4474 set_constants(canonical_list); | 4525 set_constants(canonical_list); |
| 4475 } | 4526 } |
| 4476 canonical_list.SetAt(index, constant); | 4527 canonical_list.SetAt(index, constant); |
| 4477 } | 4528 } |
| 4478 | 4529 |
| 4479 | 4530 |
| 4531 void Class::RehashConstants(Zone* zone) const { |
| 4532 intptr_t cid = id(); |
| 4533 if ((cid == kMintCid) || (cid == kBigintCid) || (cid == kDoubleCid)) { |
| 4534 // Constants stored as a plain list, no rehashing needed. |
| 4535 return; |
| 4536 } |
| 4537 |
| 4538 const Array& old_constants = Array::Handle(zone, constants()); |
| 4539 if (old_constants.Length() == 0) return; |
| 4540 |
| 4541 set_constants(Object::empty_array()); |
| 4542 CanonicalInstancesSet set(zone, old_constants.raw()); |
| 4543 Instance& constant = Instance::Handle(zone); |
| 4544 CanonicalInstancesSet::Iterator it(&set); |
| 4545 while (it.MoveNext()) { |
| 4546 constant ^= set.GetKey(it.Current()); |
| 4547 ASSERT(!constant.IsNull()); |
| 4548 InsertCanonicalConstant(zone, constant); |
| 4549 } |
| 4550 set.Release(); |
| 4551 } |
| 4552 |
| 4553 |
| 4480 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix, | 4554 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix, |
| 4481 const String& ident, | 4555 const String& ident, |
| 4482 TokenPosition token_pos) { | 4556 TokenPosition token_pos) { |
| 4483 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); | 4557 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); |
| 4484 type.set_library_prefix(library_prefix); | 4558 type.set_library_prefix(library_prefix); |
| 4485 type.set_ident(ident); | 4559 type.set_ident(ident); |
| 4486 type.set_token_pos(token_pos); | 4560 type.set_token_pos(token_pos); |
| 4487 return type.raw(); | 4561 return type.raw(); |
| 4488 } | 4562 } |
| 4489 | 4563 |
| (...skipping 10257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14747 return true; // "===". | 14821 return true; // "===". |
| 14748 } | 14822 } |
| 14749 | 14823 |
| 14750 if (other.IsNull() || (this->clazz() != other.clazz())) { | 14824 if (other.IsNull() || (this->clazz() != other.clazz())) { |
| 14751 return false; | 14825 return false; |
| 14752 } | 14826 } |
| 14753 | 14827 |
| 14754 { | 14828 { |
| 14755 NoSafepointScope no_safepoint; | 14829 NoSafepointScope no_safepoint; |
| 14756 // Raw bits compare. | 14830 // Raw bits compare. |
| 14757 const intptr_t instance_size = Class::Handle(this->clazz()).instance_size(); | 14831 const intptr_t instance_size = SizeFromClass(); |
| 14758 ASSERT(instance_size != 0); | 14832 ASSERT(instance_size != 0); |
| 14833 const intptr_t other_instance_size = other.SizeFromClass(); |
| 14834 ASSERT(other_instance_size != 0); |
| 14835 if (instance_size != other_instance_size) { |
| 14836 return false; |
| 14837 } |
| 14759 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | 14838 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
| 14760 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); | 14839 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); |
| 14761 for (intptr_t offset = Instance::NextFieldOffset(); | 14840 for (intptr_t offset = Instance::NextFieldOffset(); |
| 14762 offset < instance_size; | 14841 offset < instance_size; |
| 14763 offset += kWordSize) { | 14842 offset += kWordSize) { |
| 14764 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != | 14843 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != |
| 14765 (*reinterpret_cast<RawObject**>(other_addr + offset))) { | 14844 (*reinterpret_cast<RawObject**>(other_addr + offset))) { |
| 14766 return false; | 14845 return false; |
| 14767 } | 14846 } |
| 14768 } | 14847 } |
| 14769 } | 14848 } |
| 14770 return true; | 14849 return true; |
| 14771 } | 14850 } |
| 14772 | 14851 |
| 14773 | 14852 |
| 14853 uword Instance::ComputeCanonicalTableHash() const { |
| 14854 ASSERT(!IsNull()); |
| 14855 NoSafepointScope no_safepoint; |
| 14856 const intptr_t instance_size = SizeFromClass(); |
| 14857 ASSERT(instance_size != 0); |
| 14858 uword hash = instance_size; |
| 14859 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
| 14860 for (intptr_t offset = Instance::NextFieldOffset(); |
| 14861 offset < instance_size; |
| 14862 offset += kWordSize) { |
| 14863 uword value = reinterpret_cast<uword>( |
| 14864 *reinterpret_cast<RawObject**>(this_addr + offset)); |
| 14865 hash = CombineHashes(hash, value); |
| 14866 } |
| 14867 return FinalizeHash(hash); |
| 14868 } |
| 14869 |
| 14870 |
| 14774 #if defined(DEBUG) | 14871 #if defined(DEBUG) |
| 14775 class CheckForPointers : public ObjectPointerVisitor { | 14872 class CheckForPointers : public ObjectPointerVisitor { |
| 14776 public: | 14873 public: |
| 14777 explicit CheckForPointers(Isolate* isolate) | 14874 explicit CheckForPointers(Isolate* isolate) |
| 14778 : ObjectPointerVisitor(isolate), has_pointers_(false) {} | 14875 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
| 14779 | 14876 |
| 14780 bool has_pointers() const { return has_pointers_; } | 14877 bool has_pointers() const { return has_pointers_; } |
| 14781 | 14878 |
| 14782 void VisitPointers(RawObject** first, RawObject** last) { | 14879 void VisitPointers(RawObject** first, RawObject** last) { |
| 14783 if (first != last) { | 14880 if (first != last) { |
| 14784 has_pointers_ = true; | 14881 has_pointers_ = true; |
| 14785 } | 14882 } |
| 14786 } | 14883 } |
| 14787 | 14884 |
| 14788 private: | 14885 private: |
| 14789 bool has_pointers_; | 14886 bool has_pointers_; |
| 14790 | 14887 |
| 14791 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); | 14888 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); |
| 14792 }; | 14889 }; |
| 14793 #endif // DEBUG | 14890 #endif // DEBUG |
| 14794 | 14891 |
| 14795 | 14892 |
| 14796 bool Instance::CheckAndCanonicalizeFields(Zone* zone, | 14893 bool Instance::CheckAndCanonicalizeFields(Thread* thread, |
| 14797 const char** error_str) const { | 14894 const char** error_str) const { |
| 14798 const Class& cls = Class::Handle(zone, this->clazz()); | 14895 if (GetClassId() >= kNumPredefinedCids) { |
| 14799 if (cls.id() >= kNumPredefinedCids) { | |
| 14800 // Iterate over all fields, canonicalize numbers and strings, expect all | 14896 // Iterate over all fields, canonicalize numbers and strings, expect all |
| 14801 // other instances to be canonical otherwise report error (return false). | 14897 // other instances to be canonical otherwise report error (return false). |
| 14898 Zone* zone = thread->zone(); |
| 14802 Object& obj = Object::Handle(zone); | 14899 Object& obj = Object::Handle(zone); |
| 14803 intptr_t end_field_offset = cls.instance_size() - kWordSize; | 14900 intptr_t end_field_offset = SizeFromClass() - kWordSize; |
| 14804 for (intptr_t field_offset = 0; | 14901 for (intptr_t field_offset = 0; |
| 14805 field_offset <= end_field_offset; | 14902 field_offset <= end_field_offset; |
| 14806 field_offset += kWordSize) { | 14903 field_offset += kWordSize) { |
| 14807 obj = *this->FieldAddrAtOffset(field_offset); | 14904 obj = *this->FieldAddrAtOffset(field_offset); |
| 14808 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 14905 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
| 14809 if (obj.IsNumber() || obj.IsString()) { | 14906 if (obj.IsNumber() || obj.IsString()) { |
| 14810 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 14907 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); |
| 14811 ASSERT(!obj.IsNull()); | 14908 ASSERT(!obj.IsNull()); |
| 14812 this->SetFieldAtOffset(field_offset, obj); | 14909 this->SetFieldAtOffset(field_offset, obj); |
| 14813 } else { | 14910 } else { |
| 14814 ASSERT(error_str != NULL); | 14911 ASSERT(error_str != NULL); |
| 14815 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); | 14912 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); |
| 14816 *error_str = chars; | 14913 *error_str = chars; |
| 14817 return false; | 14914 return false; |
| 14818 } | 14915 } |
| 14819 } | 14916 } |
| 14820 } | 14917 } |
| 14821 } else { | 14918 } else { |
| 14822 #if defined(DEBUG) | 14919 #if defined(DEBUG) |
| 14823 // Make sure that we are not missing any fields. | 14920 // Make sure that we are not missing any fields. |
| 14824 CheckForPointers has_pointers(Isolate::Current()); | 14921 CheckForPointers has_pointers(Isolate::Current()); |
| 14825 this->raw()->VisitPointers(&has_pointers); | 14922 this->raw()->VisitPointers(&has_pointers); |
| 14826 ASSERT(!has_pointers.has_pointers()); | 14923 ASSERT(!has_pointers.has_pointers()); |
| 14827 #endif // DEBUG | 14924 #endif // DEBUG |
| 14828 } | 14925 } |
| 14829 return true; | 14926 return true; |
| 14830 } | 14927 } |
| 14831 | 14928 |
| 14832 | 14929 |
| 14833 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { | 14930 RawInstance* Instance::CheckAndCanonicalize(Thread* thread, |
| 14931 const char** error_str) const { |
| 14834 ASSERT(!IsNull()); | 14932 ASSERT(!IsNull()); |
| 14835 if (this->IsCanonical()) { | 14933 if (this->IsCanonical()) { |
| 14836 return this->raw(); | 14934 return this->raw(); |
| 14837 } | 14935 } |
| 14838 Thread* thread = Thread::Current(); | 14936 if (!CheckAndCanonicalizeFields(thread, error_str)) { |
| 14839 Zone* zone = thread->zone(); | |
| 14840 if (!CheckAndCanonicalizeFields(zone, error_str)) { | |
| 14841 return Instance::null(); | 14937 return Instance::null(); |
| 14842 } | 14938 } |
| 14939 Zone* zone = thread->zone(); |
| 14843 Isolate* isolate = thread->isolate(); | 14940 Isolate* isolate = thread->isolate(); |
| 14844 Instance& result = Instance::Handle(zone); | 14941 Instance& result = Instance::Handle(zone); |
| 14845 const Class& cls = Class::Handle(zone, this->clazz()); | 14942 const Class& cls = Class::Handle(zone, this->clazz()); |
| 14846 intptr_t index = 0; | |
| 14847 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | |
| 14848 if (!result.IsNull()) { | |
| 14849 return result.raw(); | |
| 14850 } | |
| 14851 { | 14943 { |
| 14852 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 14944 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
| 14853 // Retry lookup. | 14945 if (IsNew()) { |
| 14854 { | 14946 result ^= cls.LookupCanonicalInstance(zone, *this); |
| 14855 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | |
| 14856 if (!result.IsNull()) { | 14947 if (!result.IsNull()) { |
| 14857 return result.raw(); | 14948 return result.raw(); |
| 14858 } | 14949 } |
| 14859 } | 14950 ASSERT((isolate == Dart::vm_isolate()) || !InVMHeap()); |
| 14860 | |
| 14861 // The value needs to be added to the list. Grow the list if | |
| 14862 // it is full. | |
| 14863 result ^= this->raw(); | |
| 14864 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap()); | |
| 14865 if (result.IsNew()) { | |
| 14866 // Create a canonical object in old space. | 14951 // Create a canonical object in old space. |
| 14867 result ^= Object::Clone(result, Heap::kOld); | 14952 result ^= Object::Clone(*this, Heap::kOld); |
| 14953 } else { |
| 14954 result ^= this->raw(); |
| 14868 } | 14955 } |
| 14869 ASSERT(result.IsOld()); | 14956 ASSERT(result.IsOld()); |
| 14870 result.SetCanonical(); | 14957 result.SetCanonical(); |
| 14871 cls.InsertCanonicalConstant(index, result); | 14958 return cls.InsertCanonicalConstant(zone, result); |
| 14872 return result.raw(); | |
| 14873 } | 14959 } |
| 14874 } | 14960 } |
| 14875 | 14961 |
| 14876 | 14962 |
| 14877 RawAbstractType* Instance::GetType() const { | 14963 RawAbstractType* Instance::GetType() const { |
| 14878 if (IsNull()) { | 14964 if (IsNull()) { |
| 14879 return Type::NullType(); | 14965 return Type::NullType(); |
| 14880 } | 14966 } |
| 14881 const Class& cls = Class::Handle(clazz()); | 14967 const Class& cls = Class::Handle(clazz()); |
| 14882 if (cls.IsClosureClass()) { | 14968 if (cls.IsClosureClass()) { |
| (...skipping 2601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17484 | 17570 |
| 17485 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, | 17571 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, |
| 17486 const Array& mixin_types) { | 17572 const Array& mixin_types) { |
| 17487 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); | 17573 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); |
| 17488 result.set_super_type(super_type); | 17574 result.set_super_type(super_type); |
| 17489 result.set_mixin_types(mixin_types); | 17575 result.set_mixin_types(mixin_types); |
| 17490 return result.raw(); | 17576 return result.raw(); |
| 17491 } | 17577 } |
| 17492 | 17578 |
| 17493 | 17579 |
| 17494 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const { | 17580 RawInstance* Number::CheckAndCanonicalize(Thread* thread, |
| 17581 const char** error_str) const { |
| 17495 intptr_t cid = GetClassId(); | 17582 intptr_t cid = GetClassId(); |
| 17496 switch (cid) { | 17583 switch (cid) { |
| 17497 case kSmiCid: | 17584 case kSmiCid: |
| 17498 return reinterpret_cast<RawSmi*>(raw_value()); | 17585 return reinterpret_cast<RawSmi*>(raw_value()); |
| 17499 case kMintCid: | 17586 case kMintCid: |
| 17500 return Mint::NewCanonical(Mint::Cast(*this).value()); | 17587 return Mint::NewCanonical(Mint::Cast(*this).value()); |
| 17501 case kDoubleCid: | 17588 case kDoubleCid: |
| 17502 return Double::NewCanonical(Double::Cast(*this).value()); | 17589 return Double::NewCanonical(Double::Cast(*this).value()); |
| 17503 case kBigintCid: { | 17590 case kBigintCid: { |
| 17504 Thread* thread = Thread::Current(); | |
| 17505 Zone* zone = thread->zone(); | 17591 Zone* zone = thread->zone(); |
| 17506 Isolate* isolate = thread->isolate(); | 17592 Isolate* isolate = thread->isolate(); |
| 17507 if (!CheckAndCanonicalizeFields(zone, error_str)) { | 17593 if (!CheckAndCanonicalizeFields(thread, error_str)) { |
| 17508 return Instance::null(); | 17594 return Instance::null(); |
| 17509 } | 17595 } |
| 17510 Bigint& result = Bigint::Handle(zone); | 17596 Bigint& result = Bigint::Handle(zone); |
| 17511 const Class& cls = Class::Handle(zone, this->clazz()); | 17597 const Class& cls = Class::Handle(zone, this->clazz()); |
| 17512 intptr_t index = 0; | 17598 intptr_t index = 0; |
| 17513 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); | 17599 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); |
| 17514 if (!result.IsNull()) { | 17600 if (!result.IsNull()) { |
| 17515 return result.raw(); | 17601 return result.raw(); |
| 17516 } | 17602 } |
| 17517 { | 17603 { |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 18250 | 18336 |
| 18251 for (intptr_t i = 0; i < used; i++) { | 18337 for (intptr_t i = 0; i < used; i++) { |
| 18252 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { | 18338 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { |
| 18253 return false; | 18339 return false; |
| 18254 } | 18340 } |
| 18255 } | 18341 } |
| 18256 return true; | 18342 return true; |
| 18257 } | 18343 } |
| 18258 | 18344 |
| 18259 | 18345 |
| 18260 bool Bigint::CheckAndCanonicalizeFields(Zone* zone, | 18346 bool Bigint::CheckAndCanonicalizeFields(Thread* thread, |
| 18261 const char** error_str) const { | 18347 const char** error_str) const { |
| 18348 Zone* zone = thread->zone(); |
| 18262 // Bool field neg should always be canonical. | 18349 // Bool field neg should always be canonical. |
| 18263 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); | 18350 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); |
| 18264 // Smi field used is canonical by definition. | 18351 // Smi field used is canonical by definition. |
| 18265 if (Used() > 0) { | 18352 if (Used() > 0) { |
| 18266 // Canonicalize TypedData field digits. | 18353 // Canonicalize TypedData field digits. |
| 18267 TypedData& digits_ = TypedData::Handle(zone, digits()); | 18354 TypedData& digits_ = TypedData::Handle(zone, digits()); |
| 18268 digits_ ^= digits_.CheckAndCanonicalize(NULL); | 18355 digits_ ^= digits_.CheckAndCanonicalize(thread, NULL); |
| 18269 ASSERT(!digits_.IsNull()); | 18356 ASSERT(!digits_.IsNull()); |
| 18270 set_digits(digits_); | 18357 set_digits(digits_); |
| 18271 } else { | 18358 } else { |
| 18272 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); | 18359 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); |
| 18273 } | 18360 } |
| 18274 return true; | 18361 return true; |
| 18275 } | 18362 } |
| 18276 | 18363 |
| 18277 | 18364 |
| 18278 RawBigint* Bigint::New(Heap::Space space) { | 18365 RawBigint* Bigint::New(Heap::Space space) { |
| (...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19230 intptr_t slen = other.Length(); | 19317 intptr_t slen = other.Length(); |
| 19231 for (int i = 0; i < slen; i++) { | 19318 for (int i = 0; i < slen; i++) { |
| 19232 if (this->CharAt(i) != other.CharAt(i)) { | 19319 if (this->CharAt(i) != other.CharAt(i)) { |
| 19233 return false; | 19320 return false; |
| 19234 } | 19321 } |
| 19235 } | 19322 } |
| 19236 return true; | 19323 return true; |
| 19237 } | 19324 } |
| 19238 | 19325 |
| 19239 | 19326 |
| 19240 RawInstance* String::CheckAndCanonicalize(const char** error_str) const { | 19327 RawInstance* String::CheckAndCanonicalize(Thread* thread, |
| 19328 const char** error_str) const { |
| 19241 if (IsCanonical()) { | 19329 if (IsCanonical()) { |
| 19242 return this->raw(); | 19330 return this->raw(); |
| 19243 } | 19331 } |
| 19244 return Symbols::New(Thread::Current(), *this); | 19332 return Symbols::New(Thread::Current(), *this); |
| 19245 } | 19333 } |
| 19246 | 19334 |
| 19247 | 19335 |
| 19248 RawString* String::New(const char* cstr, Heap::Space space) { | 19336 RawString* String::New(const char* cstr, Heap::Space space) { |
| 19249 ASSERT(cstr != NULL); | 19337 ASSERT(cstr != NULL); |
| 19250 intptr_t array_len = strlen(cstr); | 19338 intptr_t array_len = strlen(cstr); |
| (...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20687 return false; | 20775 return false; |
| 20688 } | 20776 } |
| 20689 | 20777 |
| 20690 for (intptr_t i = 0; i < len; i++) { | 20778 for (intptr_t i = 0; i < len; i++) { |
| 20691 if (this->At(i) != other_arr.At(i)) { | 20779 if (this->At(i) != other_arr.At(i)) { |
| 20692 return false; | 20780 return false; |
| 20693 } | 20781 } |
| 20694 } | 20782 } |
| 20695 | 20783 |
| 20696 // Now check if both arrays have the same type arguments. | 20784 // Now check if both arrays have the same type arguments. |
| 20785 if (GetTypeArguments() == other.GetTypeArguments()) { |
| 20786 return true; |
| 20787 } |
| 20697 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | 20788 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); |
| 20698 const TypeArguments& other_type_args = TypeArguments::Handle( | 20789 const TypeArguments& other_type_args = TypeArguments::Handle( |
| 20699 other.GetTypeArguments()); | 20790 other.GetTypeArguments()); |
| 20700 if (!type_args.Equals(other_type_args)) { | 20791 if (!type_args.Equals(other_type_args)) { |
| 20701 return false; | 20792 return false; |
| 20702 } | 20793 } |
| 20703 return true; | 20794 return true; |
| 20704 } | 20795 } |
| 20705 | 20796 |
| 20706 | 20797 |
| 20798 uword Array::ComputeCanonicalTableHash() const { |
| 20799 ASSERT(!IsNull()); |
| 20800 intptr_t len = Length(); |
| 20801 uword hash = len; |
| 20802 uword value = reinterpret_cast<uword>(GetTypeArguments()); |
| 20803 hash = CombineHashes(hash, value); |
| 20804 for (intptr_t i = 0; i < len; i++) { |
| 20805 value = reinterpret_cast<uword>(At(i)); |
| 20806 hash = CombineHashes(hash, value); |
| 20807 } |
| 20808 return FinalizeHash(hash); |
| 20809 } |
| 20810 |
| 20811 |
| 20707 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20812 RawArray* Array::New(intptr_t len, Heap::Space space) { |
| 20708 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20813 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
| 20709 return New(kClassId, len, space); | 20814 return New(kClassId, len, space); |
| 20710 } | 20815 } |
| 20711 | 20816 |
| 20712 | 20817 |
| 20713 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 20818 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { |
| 20714 if ((len < 0) || (len > Array::kMaxElements)) { | 20819 if ((len < 0) || (len > Array::kMaxElements)) { |
| 20715 // This should be caught before we reach here. | 20820 // This should be caught before we reach here. |
| 20716 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); | 20821 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20838 array.SetLength(used_len); | 20943 array.SetLength(used_len); |
| 20839 | 20944 |
| 20840 // Null the GrowableObjectArray, we are removing its backing array. | 20945 // Null the GrowableObjectArray, we are removing its backing array. |
| 20841 growable_array.SetLength(0); | 20946 growable_array.SetLength(0); |
| 20842 growable_array.SetData(Object::empty_array()); | 20947 growable_array.SetData(Object::empty_array()); |
| 20843 | 20948 |
| 20844 return array.raw(); | 20949 return array.raw(); |
| 20845 } | 20950 } |
| 20846 | 20951 |
| 20847 | 20952 |
| 20848 bool Array::CheckAndCanonicalizeFields(Zone* zone, | 20953 bool Array::CheckAndCanonicalizeFields(Thread* thread, |
| 20849 const char** error_str) const { | 20954 const char** error_str) const { |
| 20850 Object& obj = Object::Handle(zone); | 20955 intptr_t len = Length(); |
| 20851 // Iterate over all elements, canonicalize numbers and strings, expect all | 20956 if (len > 0) { |
| 20852 // other instances to be canonical otherwise report error (return false). | 20957 Zone* zone = thread->zone(); |
| 20853 for (intptr_t i = 0; i < Length(); i++) { | 20958 Object& obj = Object::Handle(zone); |
| 20854 obj = At(i); | 20959 // Iterate over all elements, canonicalize numbers and strings, expect all |
| 20855 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 20960 // other instances to be canonical otherwise report error (return false). |
| 20856 if (obj.IsNumber() || obj.IsString()) { | 20961 for (intptr_t i = 0; i < len; i++) { |
| 20857 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 20962 obj = At(i); |
| 20858 ASSERT(!obj.IsNull()); | 20963 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
| 20859 this->SetAt(i, obj); | 20964 if (obj.IsNumber() || obj.IsString()) { |
| 20860 } else { | 20965 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); |
| 20861 ASSERT(error_str != NULL); | 20966 ASSERT(!obj.IsNull()); |
| 20862 char* chars = OS::SCreate(Thread::Current()->zone(), | 20967 this->SetAt(i, obj); |
| 20863 "element at index %" Pd ": %s\n", i, obj.ToCString()); | 20968 } else { |
| 20864 *error_str = chars; | 20969 ASSERT(error_str != NULL); |
| 20865 return false; | 20970 char* chars = OS::SCreate( |
| 20971 zone, "element at index %" Pd ": %s\n", i, obj.ToCString()); |
| 20972 *error_str = chars; |
| 20973 return false; |
| 20974 } |
| 20866 } | 20975 } |
| 20867 } | 20976 } |
| 20868 } | 20977 } |
| 20869 return true; | 20978 return true; |
| 20870 } | 20979 } |
| 20871 | 20980 |
| 20872 | 20981 |
| 20873 RawImmutableArray* ImmutableArray::New(intptr_t len, | 20982 RawImmutableArray* ImmutableArray::New(intptr_t len, |
| 20874 Heap::Space space) { | 20983 Heap::Space space) { |
| 20875 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != | 20984 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21339 const intptr_t len = this->LengthInBytes(); | 21448 const intptr_t len = this->LengthInBytes(); |
| 21340 if (len != other_typed_data.LengthInBytes()) { | 21449 if (len != other_typed_data.LengthInBytes()) { |
| 21341 return false; | 21450 return false; |
| 21342 } | 21451 } |
| 21343 NoSafepointScope no_safepoint; | 21452 NoSafepointScope no_safepoint; |
| 21344 return (len == 0) || | 21453 return (len == 0) || |
| 21345 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); | 21454 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); |
| 21346 } | 21455 } |
| 21347 | 21456 |
| 21348 | 21457 |
| 21458 uword TypedData::ComputeCanonicalTableHash() const { |
| 21459 const intptr_t len = this->LengthInBytes(); |
| 21460 ASSERT(len != 0); |
| 21461 uword hash = len; |
| 21462 for (intptr_t i = 0; i < len; i++) { |
| 21463 hash = CombineHashes(len, GetUint8(i)); |
| 21464 } |
| 21465 return FinalizeHash(hash); |
| 21466 } |
| 21467 |
| 21468 |
| 21349 RawTypedData* TypedData::New(intptr_t class_id, | 21469 RawTypedData* TypedData::New(intptr_t class_id, |
| 21350 intptr_t len, | 21470 intptr_t len, |
| 21351 Heap::Space space) { | 21471 Heap::Space space) { |
| 21352 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21472 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
| 21353 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21473 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
| 21354 } | 21474 } |
| 21355 TypedData& result = TypedData::Handle(); | 21475 TypedData& result = TypedData::Handle(); |
| 21356 { | 21476 { |
| 21357 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); | 21477 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); |
| 21358 RawObject* raw = Object::Allocate(class_id, | 21478 RawObject* raw = Object::Allocate(class_id, |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22033 return UserTag::null(); | 22153 return UserTag::null(); |
| 22034 } | 22154 } |
| 22035 | 22155 |
| 22036 | 22156 |
| 22037 const char* UserTag::ToCString() const { | 22157 const char* UserTag::ToCString() const { |
| 22038 const String& tag_label = String::Handle(label()); | 22158 const String& tag_label = String::Handle(label()); |
| 22039 return tag_label.ToCString(); | 22159 return tag_label.ToCString(); |
| 22040 } | 22160 } |
| 22041 | 22161 |
| 22042 } // namespace dart | 22162 } // namespace dart |
| OLD | NEW |