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 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 Class::NewTypedDataClass(kTypedDataInt8ArrayCid); | 697 Class::NewTypedDataClass(kTypedDataInt8ArrayCid); |
698 | 698 |
699 // Allocate and initialize the empty_array instance. | 699 // Allocate and initialize the empty_array instance. |
700 { | 700 { |
701 uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld); | 701 uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld); |
702 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0), true); | 702 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0), true); |
703 Array::initializeHandle( | 703 Array::initializeHandle( |
704 empty_array_, | 704 empty_array_, |
705 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); | 705 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); |
706 empty_array_->StoreSmi(&empty_array_->raw_ptr()->length_, Smi::New(0)); | 706 empty_array_->StoreSmi(&empty_array_->raw_ptr()->length_, Smi::New(0)); |
707 empty_array_->SetCanonical(); | |
707 } | 708 } |
708 | 709 |
709 Smi& smi = Smi::Handle(); | 710 Smi& smi = Smi::Handle(); |
710 // Allocate and initialize the zero_array instance. | 711 // Allocate and initialize the zero_array instance. |
711 { | 712 { |
712 uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); | 713 uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); |
713 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); | 714 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); |
714 Array::initializeHandle( | 715 Array::initializeHandle( |
715 zero_array_, | 716 zero_array_, |
716 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); | 717 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); |
717 zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1)); | 718 zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1)); |
718 smi = Smi::New(0); | 719 smi = Smi::New(0); |
719 zero_array_->SetAt(0, smi); | 720 zero_array_->SetAt(0, smi); |
721 zero_array_->SetCanonical(); | |
720 } | 722 } |
721 | 723 |
722 // Allocate and initialize the canonical empty context scope object. | 724 // Allocate and initialize the canonical empty context scope object. |
723 { | 725 { |
724 uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld); | 726 uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld); |
725 InitializeObject(address, | 727 InitializeObject(address, |
726 kContextScopeCid, | 728 kContextScopeCid, |
727 ContextScope::InstanceSize(0), | 729 ContextScope::InstanceSize(0), |
728 true); | 730 true); |
729 ContextScope::initializeHandle( | 731 ContextScope::initializeHandle( |
730 empty_context_scope_, | 732 empty_context_scope_, |
731 reinterpret_cast<RawContextScope*>(address + kHeapObjectTag)); | 733 reinterpret_cast<RawContextScope*>(address + kHeapObjectTag)); |
732 empty_context_scope_->StoreNonPointer( | 734 empty_context_scope_->StoreNonPointer( |
733 &empty_context_scope_->raw_ptr()->num_variables_, 0); | 735 &empty_context_scope_->raw_ptr()->num_variables_, 0); |
734 empty_context_scope_->StoreNonPointer( | 736 empty_context_scope_->StoreNonPointer( |
735 &empty_context_scope_->raw_ptr()->is_implicit_, true); | 737 &empty_context_scope_->raw_ptr()->is_implicit_, true); |
738 empty_context_scope_->SetCanonical(); | |
736 } | 739 } |
737 | 740 |
738 // Allocate and initialize the canonical empty object pool object. | 741 // Allocate and initialize the canonical empty object pool object. |
739 { | 742 { |
740 uword address = | 743 uword address = |
741 heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); | 744 heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); |
742 InitializeObject(address, | 745 InitializeObject(address, |
743 kObjectPoolCid, | 746 kObjectPoolCid, |
744 ObjectPool::InstanceSize(0), | 747 ObjectPool::InstanceSize(0), |
745 true); | 748 true); |
746 ObjectPool::initializeHandle( | 749 ObjectPool::initializeHandle( |
747 empty_object_pool_, | 750 empty_object_pool_, |
748 reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag)); | 751 reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag)); |
749 empty_object_pool_->StoreNonPointer( | 752 empty_object_pool_->StoreNonPointer( |
750 &empty_object_pool_->raw_ptr()->length_, 0); | 753 &empty_object_pool_->raw_ptr()->length_, 0); |
754 empty_object_pool_->SetCanonical(); | |
751 } | 755 } |
752 | 756 |
753 // Allocate and initialize the empty_descriptors instance. | 757 // Allocate and initialize the empty_descriptors instance. |
754 { | 758 { |
755 uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); | 759 uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); |
756 InitializeObject(address, kPcDescriptorsCid, | 760 InitializeObject(address, kPcDescriptorsCid, |
757 PcDescriptors::InstanceSize(0), | 761 PcDescriptors::InstanceSize(0), |
758 true); | 762 true); |
759 PcDescriptors::initializeHandle( | 763 PcDescriptors::initializeHandle( |
760 empty_descriptors_, | 764 empty_descriptors_, |
761 reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag)); | 765 reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag)); |
762 empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_, | 766 empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_, |
763 0); | 767 0); |
768 empty_descriptors_->SetCanonical(); | |
764 } | 769 } |
765 | 770 |
766 // Allocate and initialize the canonical empty variable descriptor object. | 771 // Allocate and initialize the canonical empty variable descriptor object. |
767 { | 772 { |
768 uword address = | 773 uword address = |
769 heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); | 774 heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); |
770 InitializeObject(address, | 775 InitializeObject(address, |
771 kLocalVarDescriptorsCid, | 776 kLocalVarDescriptorsCid, |
772 LocalVarDescriptors::InstanceSize(0), | 777 LocalVarDescriptors::InstanceSize(0), |
773 true); | 778 true); |
774 LocalVarDescriptors::initializeHandle( | 779 LocalVarDescriptors::initializeHandle( |
775 empty_var_descriptors_, | 780 empty_var_descriptors_, |
776 reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag)); | 781 reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag)); |
777 empty_var_descriptors_->StoreNonPointer( | 782 empty_var_descriptors_->StoreNonPointer( |
778 &empty_var_descriptors_->raw_ptr()->num_entries_, 0); | 783 &empty_var_descriptors_->raw_ptr()->num_entries_, 0); |
784 empty_var_descriptors_->SetCanonical(); | |
779 } | 785 } |
780 | 786 |
781 // Allocate and initialize the canonical empty exception handler info object. | 787 // Allocate and initialize the canonical empty exception handler info object. |
782 // The vast majority of all functions do not contain an exception handler | 788 // The vast majority of all functions do not contain an exception handler |
783 // and can share this canonical descriptor. | 789 // and can share this canonical descriptor. |
784 { | 790 { |
785 uword address = | 791 uword address = |
786 heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); | 792 heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); |
787 InitializeObject(address, | 793 InitializeObject(address, |
788 kExceptionHandlersCid, | 794 kExceptionHandlersCid, |
789 ExceptionHandlers::InstanceSize(0), | 795 ExceptionHandlers::InstanceSize(0), |
790 true); | 796 true); |
791 ExceptionHandlers::initializeHandle( | 797 ExceptionHandlers::initializeHandle( |
792 empty_exception_handlers_, | 798 empty_exception_handlers_, |
793 reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag)); | 799 reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag)); |
794 empty_exception_handlers_->StoreNonPointer( | 800 empty_exception_handlers_->StoreNonPointer( |
795 &empty_exception_handlers_->raw_ptr()->num_entries_, 0); | 801 &empty_exception_handlers_->raw_ptr()->num_entries_, 0); |
802 empty_exception_handlers_->SetCanonical(); | |
796 } | 803 } |
797 | 804 |
798 // The VM isolate snapshot object table is initialized to an empty array | 805 // The VM isolate snapshot object table is initialized to an empty array |
799 // as we do not have any VM isolate snapshot at this time. | 806 // as we do not have any VM isolate snapshot at this time. |
800 *vm_isolate_snapshot_object_table_ = Object::empty_array().raw(); | 807 *vm_isolate_snapshot_object_table_ = Object::empty_array().raw(); |
801 | 808 |
802 cls = Class::New<Instance>(kDynamicCid); | 809 cls = Class::New<Instance>(kDynamicCid); |
803 cls.set_is_abstract(); | 810 cls.set_is_abstract(); |
804 cls.set_num_type_arguments(0); | 811 cls.set_num_type_arguments(0); |
805 cls.set_num_own_type_arguments(0); | 812 cls.set_num_own_type_arguments(0); |
(...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4405 if (canonical_value.Equals(value)) { | 4412 if (canonical_value.Equals(value)) { |
4406 ASSERT(canonical_value.IsCanonical()); | 4413 ASSERT(canonical_value.IsCanonical()); |
4407 return canonical_value.raw(); | 4414 return canonical_value.raw(); |
4408 } | 4415 } |
4409 *index = *index + 1; | 4416 *index = *index + 1; |
4410 } | 4417 } |
4411 return Bigint::null(); | 4418 return Bigint::null(); |
4412 } | 4419 } |
4413 | 4420 |
4414 | 4421 |
4422 class CanonicalInstanceKey { | |
4423 public: | |
4424 explicit CanonicalInstanceKey(const Instance& key) : key_(key) { | |
4425 ASSERT(!(key.IsString() || key.IsInteger() || key.IsAbstractType())); | |
4426 } | |
4427 bool Matches(const Instance& obj) const { | |
4428 ASSERT(!(obj.IsString() || obj.IsInteger() || obj.IsAbstractType())); | |
4429 if (key_.CanonicalizeEquals(obj)) { | |
4430 ASSERT(obj.IsCanonical()); | |
4431 return true; | |
4432 } | |
4433 return false; | |
4434 } | |
4435 uword Hash() const { | |
4436 return key_.ComputeCanonicalTableHash(); | |
4437 } | |
4438 const Instance& key_; | |
4439 | |
4440 private: | |
4441 DISALLOW_ALLOCATION(); | |
4442 DISALLOW_COPY_AND_ASSIGN(CanonicalInstanceKey); | |
4443 }; | |
4444 | |
4445 | |
4446 // Traits for looking up Canonical Instances based on a hash of the fields. | |
4447 class CanonicalInstanceTraits { | |
4448 public: | |
4449 // Called when growing the table. | |
4450 static bool IsMatch(const Object& a, const Object& b) { | |
4451 ASSERT(!(a.IsString() || a.IsInteger() || a.IsAbstractType())); | |
4452 ASSERT(!(b.IsString() || b.IsInteger() || b.IsAbstractType())); | |
4453 return a.raw() == b.raw(); | |
4454 } | |
4455 static bool IsMatch(const CanonicalInstanceKey& a, const Object& b) { | |
4456 return a.Matches(Instance::Cast(b)); | |
4457 } | |
4458 static uword Hash(const Object& key) { | |
4459 ASSERT(!(key.IsString() || key.IsNumber() || key.IsAbstractType())); | |
4460 ASSERT(key.IsInstance()); | |
4461 return Instance::Cast(key).ComputeCanonicalTableHash(); | |
4462 } | |
4463 static uword Hash(const CanonicalInstanceKey& key) { | |
4464 return key.Hash(); | |
4465 } | |
4466 static RawObject* NewKey(const CanonicalInstanceKey& obj) { | |
4467 return obj.key_.raw(); | |
4468 } | |
4469 }; | |
regis
2016/04/12 21:12:32
No blank line(s)?
siva
2016/04/13 16:52:41
This seems to be the pattern that everybody has us
| |
4470 typedef UnorderedHashSet<CanonicalInstanceTraits> CanonicalInstancesSet; | |
4471 | |
4472 | |
4415 RawInstance* Class::LookupCanonicalInstance(Zone* zone, | 4473 RawInstance* Class::LookupCanonicalInstance(Zone* zone, |
4416 const Instance& value, | 4474 const Instance& value) const { |
4417 intptr_t* index) const { | |
4418 ASSERT(this->raw() == value.clazz()); | 4475 ASSERT(this->raw() == value.clazz()); |
4419 const Array& constants = Array::Handle(zone, this->constants()); | |
4420 const intptr_t constants_len = constants.Length(); | |
4421 // Linear search to see whether this value is already present in the | |
4422 // list of canonicalized constants. | |
4423 Instance& canonical_value = Instance::Handle(zone); | 4476 Instance& canonical_value = Instance::Handle(zone); |
4424 while (*index < constants_len) { | 4477 if (this->constants() != Object::empty_array().raw()) { |
4425 canonical_value ^= constants.At(*index); | 4478 CanonicalInstancesSet constants(zone, this->constants()); |
4426 if (canonical_value.IsNull()) { | 4479 canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value)); |
4427 break; | 4480 this->set_constants(constants.Release()); |
regis
2016/04/12 21:12:32
Since you are only doing a lookup in the constants
siva
2016/04/13 16:52:41
The problem is constants.Release() needs to be cal
| |
4428 } | |
4429 if (value.CanonicalizeEquals(canonical_value)) { | |
4430 ASSERT(canonical_value.IsCanonical()); | |
4431 return canonical_value.raw(); | |
4432 } | |
4433 *index = *index + 1; | |
4434 } | 4481 } |
4435 return Instance::null(); | 4482 return canonical_value.raw(); |
4436 } | 4483 } |
4437 | 4484 |
4438 | 4485 |
4439 void Class::InsertCanonicalConstant(intptr_t index, | 4486 RawInstance* Class::InsertCanonicalConstant(Zone* zone, |
4440 const Instance& constant) const { | 4487 const Instance& constant) const { |
4441 // The constant needs to be added to the list. Grow the list if it is full. | 4488 ASSERT(this->raw() == constant.clazz()); |
4442 Array& canonical_list = Array::Handle(constants()); | 4489 Instance& canonical_value = Instance::Handle(zone); |
4443 const intptr_t list_len = canonical_list.Length(); | 4490 if (this->constants() == Object::empty_array().raw()) { |
4444 if (index >= list_len) { | 4491 CanonicalInstancesSet constants( |
4445 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; | 4492 HashTables::New<CanonicalInstancesSet>(128, Heap::kOld)); |
4446 const Array& new_canonical_list = | 4493 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); |
4447 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); | 4494 this->set_constants(constants.Release()); |
4448 set_constants(new_canonical_list); | |
4449 new_canonical_list.SetAt(index, constant); | |
4450 } else { | 4495 } else { |
4451 canonical_list.SetAt(index, constant); | 4496 CanonicalInstancesSet constants(Thread::Current()->zone(), |
4497 this->constants()); | |
4498 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); | |
4499 this->set_constants(constants.Release()); | |
4452 } | 4500 } |
4501 return canonical_value.raw(); | |
4453 } | 4502 } |
4454 | 4503 |
4455 | 4504 |
4456 void Class::InsertCanonicalNumber(Zone* zone, | 4505 void Class::InsertCanonicalNumber(Zone* zone, |
4457 intptr_t index, | 4506 intptr_t index, |
4458 const Number& constant) const { | 4507 const Number& constant) const { |
4459 // The constant needs to be added to the list. Grow the list if it is full. | 4508 // The constant needs to be added to the list. Grow the list if it is full. |
4460 Array& canonical_list = Array::Handle(zone, constants()); | 4509 Array& canonical_list = Array::Handle(zone, constants()); |
4461 const intptr_t list_len = canonical_list.Length(); | 4510 const intptr_t list_len = canonical_list.Length(); |
4462 if (index >= list_len) { | 4511 if (index >= list_len) { |
(...skipping 10218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14681 return true; // "===". | 14730 return true; // "===". |
14682 } | 14731 } |
14683 | 14732 |
14684 if (other.IsNull() || (this->clazz() != other.clazz())) { | 14733 if (other.IsNull() || (this->clazz() != other.clazz())) { |
14685 return false; | 14734 return false; |
14686 } | 14735 } |
14687 | 14736 |
14688 { | 14737 { |
14689 NoSafepointScope no_safepoint; | 14738 NoSafepointScope no_safepoint; |
14690 // Raw bits compare. | 14739 // Raw bits compare. |
14691 const intptr_t instance_size = Class::Handle(this->clazz()).instance_size(); | 14740 const intptr_t instance_size = SizeFromClass(); |
14692 ASSERT(instance_size != 0); | 14741 ASSERT(instance_size != 0); |
14742 const intptr_t other_instance_size = other.SizeFromClass(); | |
14743 ASSERT(other_instance_size != 0); | |
14744 if (instance_size != other_instance_size) { | |
14745 return false; | |
14746 } | |
14693 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | 14747 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
14694 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); | 14748 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); |
14695 for (intptr_t offset = Instance::NextFieldOffset(); | 14749 for (intptr_t offset = Instance::NextFieldOffset(); |
14696 offset < instance_size; | 14750 offset < instance_size; |
14697 offset += kWordSize) { | 14751 offset += kWordSize) { |
14698 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != | 14752 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != |
14699 (*reinterpret_cast<RawObject**>(other_addr + offset))) { | 14753 (*reinterpret_cast<RawObject**>(other_addr + offset))) { |
14700 return false; | 14754 return false; |
14701 } | 14755 } |
14702 } | 14756 } |
14703 } | 14757 } |
14704 return true; | 14758 return true; |
14705 } | 14759 } |
14706 | 14760 |
14707 | 14761 |
14762 uword Instance::ComputeCanonicalTableHash() const { | |
14763 ASSERT(!IsNull()); | |
14764 NoSafepointScope no_safepoint; | |
14765 const intptr_t instance_size = SizeFromClass(); | |
14766 ASSERT(instance_size != 0); | |
14767 uword hash = instance_size; | |
14768 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | |
14769 for (intptr_t offset = Instance::NextFieldOffset(); | |
14770 offset < instance_size; | |
14771 offset += kWordSize) { | |
14772 uword value = reinterpret_cast<uword>( | |
14773 *reinterpret_cast<RawObject**>(this_addr + offset)); | |
14774 hash = CombineHashes(hash, (value >> 3)); | |
regis
2016/04/12 21:12:32
If the field is a Smi, you ignore 2 bits of its va
siva
2016/04/13 16:52:41
Removed teh shift as discussed offline.
| |
14775 } | |
14776 return FinalizeHash(hash); | |
14777 } | |
14778 | |
14779 | |
14708 #if defined(DEBUG) | 14780 #if defined(DEBUG) |
14709 class CheckForPointers : public ObjectPointerVisitor { | 14781 class CheckForPointers : public ObjectPointerVisitor { |
14710 public: | 14782 public: |
14711 explicit CheckForPointers(Isolate* isolate) | 14783 explicit CheckForPointers(Isolate* isolate) |
14712 : ObjectPointerVisitor(isolate), has_pointers_(false) {} | 14784 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
14713 | 14785 |
14714 bool has_pointers() const { return has_pointers_; } | 14786 bool has_pointers() const { return has_pointers_; } |
14715 | 14787 |
14716 void VisitPointers(RawObject** first, RawObject** last) { | 14788 void VisitPointers(RawObject** first, RawObject** last) { |
14717 if (first != last) { | 14789 if (first != last) { |
14718 has_pointers_ = true; | 14790 has_pointers_ = true; |
14719 } | 14791 } |
14720 } | 14792 } |
14721 | 14793 |
14722 private: | 14794 private: |
14723 bool has_pointers_; | 14795 bool has_pointers_; |
14724 | 14796 |
14725 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); | 14797 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); |
14726 }; | 14798 }; |
14727 #endif // DEBUG | 14799 #endif // DEBUG |
14728 | 14800 |
14729 | 14801 |
14730 bool Instance::CheckAndCanonicalizeFields(Zone* zone, | 14802 bool Instance::CheckAndCanonicalizeFields(Thread* thread, |
14731 const char** error_str) const { | 14803 const char** error_str) const { |
14732 const Class& cls = Class::Handle(zone, this->clazz()); | 14804 if (GetClassId() >= kNumPredefinedCids) { |
14733 if (cls.id() >= kNumPredefinedCids) { | |
14734 // Iterate over all fields, canonicalize numbers and strings, expect all | 14805 // Iterate over all fields, canonicalize numbers and strings, expect all |
14735 // other instances to be canonical otherwise report error (return false). | 14806 // other instances to be canonical otherwise report error (return false). |
14807 Zone* zone = thread->zone(); | |
14736 Object& obj = Object::Handle(zone); | 14808 Object& obj = Object::Handle(zone); |
14737 intptr_t end_field_offset = cls.instance_size() - kWordSize; | 14809 intptr_t end_field_offset = SizeFromClass() - kWordSize; |
14738 for (intptr_t field_offset = 0; | 14810 for (intptr_t field_offset = 0; |
14739 field_offset <= end_field_offset; | 14811 field_offset <= end_field_offset; |
14740 field_offset += kWordSize) { | 14812 field_offset += kWordSize) { |
14741 obj = *this->FieldAddrAtOffset(field_offset); | 14813 obj = *this->FieldAddrAtOffset(field_offset); |
14742 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 14814 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
14743 if (obj.IsNumber() || obj.IsString()) { | 14815 if (obj.IsNumber() || obj.IsString()) { |
14744 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 14816 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); |
14745 ASSERT(!obj.IsNull()); | 14817 ASSERT(!obj.IsNull()); |
14746 this->SetFieldAtOffset(field_offset, obj); | 14818 this->SetFieldAtOffset(field_offset, obj); |
14747 } else { | 14819 } else { |
14748 ASSERT(error_str != NULL); | 14820 ASSERT(error_str != NULL); |
14749 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); | 14821 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); |
14750 *error_str = chars; | 14822 *error_str = chars; |
14751 return false; | 14823 return false; |
14752 } | 14824 } |
14753 } | 14825 } |
14754 } | 14826 } |
14755 } else { | 14827 } else { |
14756 #if defined(DEBUG) | 14828 #if defined(DEBUG) |
14757 // Make sure that we are not missing any fields. | 14829 // Make sure that we are not missing any fields. |
14758 CheckForPointers has_pointers(Isolate::Current()); | 14830 CheckForPointers has_pointers(Isolate::Current()); |
14759 this->raw()->VisitPointers(&has_pointers); | 14831 this->raw()->VisitPointers(&has_pointers); |
14760 ASSERT(!has_pointers.has_pointers()); | 14832 ASSERT(!has_pointers.has_pointers()); |
14761 #endif // DEBUG | 14833 #endif // DEBUG |
14762 } | 14834 } |
14763 return true; | 14835 return true; |
14764 } | 14836 } |
14765 | 14837 |
14766 | 14838 |
14767 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { | 14839 RawInstance* Instance::CheckAndCanonicalize(Thread* thread, |
14840 const char** error_str) const { | |
14768 ASSERT(!IsNull()); | 14841 ASSERT(!IsNull()); |
14769 if (this->IsCanonical()) { | 14842 if (this->IsCanonical()) { |
14770 return this->raw(); | 14843 return this->raw(); |
14771 } | 14844 } |
14772 Thread* thread = Thread::Current(); | 14845 if (!CheckAndCanonicalizeFields(thread, error_str)) { |
14773 Zone* zone = thread->zone(); | |
14774 if (!CheckAndCanonicalizeFields(zone, error_str)) { | |
14775 return Instance::null(); | 14846 return Instance::null(); |
14776 } | 14847 } |
14848 Zone* zone = thread->zone(); | |
14777 Isolate* isolate = thread->isolate(); | 14849 Isolate* isolate = thread->isolate(); |
14778 Instance& result = Instance::Handle(zone); | 14850 Instance& result = Instance::Handle(zone); |
14779 const Class& cls = Class::Handle(zone, this->clazz()); | 14851 const Class& cls = Class::Handle(zone, this->clazz()); |
14780 intptr_t index = 0; | |
14781 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | |
14782 if (!result.IsNull()) { | |
14783 return result.raw(); | |
14784 } | |
14785 { | 14852 { |
14786 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 14853 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
14787 // Retry lookup. | 14854 if (IsNew()) { |
14788 { | 14855 result ^= cls.LookupCanonicalInstance(zone, *this); |
14789 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | |
14790 if (!result.IsNull()) { | 14856 if (!result.IsNull()) { |
14791 return result.raw(); | 14857 return result.raw(); |
14792 } | 14858 } |
14793 } | 14859 ASSERT((isolate == Dart::vm_isolate()) || !InVMHeap()); |
14794 | |
14795 // The value needs to be added to the list. Grow the list if | |
14796 // it is full. | |
14797 result ^= this->raw(); | |
14798 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap()); | |
14799 if (result.IsNew()) { | |
14800 // Create a canonical object in old space. | 14860 // Create a canonical object in old space. |
14801 result ^= Object::Clone(result, Heap::kOld); | 14861 result ^= Object::Clone(*this, Heap::kOld); |
14862 } else { | |
14863 result ^= this->raw(); | |
14802 } | 14864 } |
14803 ASSERT(result.IsOld()); | 14865 ASSERT(result.IsOld()); |
14804 result.SetCanonical(); | 14866 result.SetCanonical(); |
14805 cls.InsertCanonicalConstant(index, result); | 14867 return cls.InsertCanonicalConstant(zone, result); |
14806 return result.raw(); | |
14807 } | 14868 } |
14808 } | 14869 } |
14809 | 14870 |
14810 | 14871 |
14811 RawAbstractType* Instance::GetType() const { | 14872 RawAbstractType* Instance::GetType() const { |
14812 if (IsNull()) { | 14873 if (IsNull()) { |
14813 return Type::NullType(); | 14874 return Type::NullType(); |
14814 } | 14875 } |
14815 const Class& cls = Class::Handle(clazz()); | 14876 const Class& cls = Class::Handle(clazz()); |
14816 if (cls.IsClosureClass()) { | 14877 if (cls.IsClosureClass()) { |
(...skipping 2593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17410 | 17471 |
17411 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, | 17472 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, |
17412 const Array& mixin_types) { | 17473 const Array& mixin_types) { |
17413 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); | 17474 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); |
17414 result.set_super_type(super_type); | 17475 result.set_super_type(super_type); |
17415 result.set_mixin_types(mixin_types); | 17476 result.set_mixin_types(mixin_types); |
17416 return result.raw(); | 17477 return result.raw(); |
17417 } | 17478 } |
17418 | 17479 |
17419 | 17480 |
17420 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const { | 17481 RawInstance* Number::CheckAndCanonicalize(Thread* thread, |
17482 const char** error_str) const { | |
17421 intptr_t cid = GetClassId(); | 17483 intptr_t cid = GetClassId(); |
17422 switch (cid) { | 17484 switch (cid) { |
17423 case kSmiCid: | 17485 case kSmiCid: |
17424 return reinterpret_cast<RawSmi*>(raw_value()); | 17486 return reinterpret_cast<RawSmi*>(raw_value()); |
17425 case kMintCid: | 17487 case kMintCid: |
17426 return Mint::NewCanonical(Mint::Cast(*this).value()); | 17488 return Mint::NewCanonical(Mint::Cast(*this).value()); |
17427 case kDoubleCid: | 17489 case kDoubleCid: |
17428 return Double::NewCanonical(Double::Cast(*this).value()); | 17490 return Double::NewCanonical(Double::Cast(*this).value()); |
17429 case kBigintCid: { | 17491 case kBigintCid: { |
17430 Thread* thread = Thread::Current(); | |
17431 Zone* zone = thread->zone(); | 17492 Zone* zone = thread->zone(); |
17432 Isolate* isolate = thread->isolate(); | 17493 Isolate* isolate = thread->isolate(); |
17433 if (!CheckAndCanonicalizeFields(zone, error_str)) { | 17494 if (!CheckAndCanonicalizeFields(thread, error_str)) { |
17434 return Instance::null(); | 17495 return Instance::null(); |
17435 } | 17496 } |
17436 Bigint& result = Bigint::Handle(zone); | 17497 Bigint& result = Bigint::Handle(zone); |
17437 const Class& cls = Class::Handle(zone, this->clazz()); | 17498 const Class& cls = Class::Handle(zone, this->clazz()); |
17438 intptr_t index = 0; | 17499 intptr_t index = 0; |
17439 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); | 17500 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); |
17440 if (!result.IsNull()) { | 17501 if (!result.IsNull()) { |
17441 return result.raw(); | 17502 return result.raw(); |
17442 } | 17503 } |
17443 { | 17504 { |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18176 | 18237 |
18177 for (intptr_t i = 0; i < used; i++) { | 18238 for (intptr_t i = 0; i < used; i++) { |
18178 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { | 18239 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { |
18179 return false; | 18240 return false; |
18180 } | 18241 } |
18181 } | 18242 } |
18182 return true; | 18243 return true; |
18183 } | 18244 } |
18184 | 18245 |
18185 | 18246 |
18186 bool Bigint::CheckAndCanonicalizeFields(Zone* zone, | 18247 bool Bigint::CheckAndCanonicalizeFields(Thread* thread, |
18187 const char** error_str) const { | 18248 const char** error_str) const { |
18249 Zone* zone = thread->zone(); | |
18188 // Bool field neg should always be canonical. | 18250 // Bool field neg should always be canonical. |
18189 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); | 18251 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); |
18190 // Smi field used is canonical by definition. | 18252 // Smi field used is canonical by definition. |
18191 if (Used() > 0) { | 18253 if (Used() > 0) { |
18192 // Canonicalize TypedData field digits. | 18254 // Canonicalize TypedData field digits. |
18193 TypedData& digits_ = TypedData::Handle(zone, digits()); | 18255 TypedData& digits_ = TypedData::Handle(zone, digits()); |
18194 digits_ ^= digits_.CheckAndCanonicalize(NULL); | 18256 digits_ ^= digits_.CheckAndCanonicalize(thread, NULL); |
18195 ASSERT(!digits_.IsNull()); | 18257 ASSERT(!digits_.IsNull()); |
18196 set_digits(digits_); | 18258 set_digits(digits_); |
18197 } else { | 18259 } else { |
18198 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); | 18260 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); |
18199 } | 18261 } |
18200 return true; | 18262 return true; |
18201 } | 18263 } |
18202 | 18264 |
18203 | 18265 |
18204 RawBigint* Bigint::New(Heap::Space space) { | 18266 RawBigint* Bigint::New(Heap::Space space) { |
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
19156 intptr_t slen = other.Length(); | 19218 intptr_t slen = other.Length(); |
19157 for (int i = 0; i < slen; i++) { | 19219 for (int i = 0; i < slen; i++) { |
19158 if (this->CharAt(i) != other.CharAt(i)) { | 19220 if (this->CharAt(i) != other.CharAt(i)) { |
19159 return false; | 19221 return false; |
19160 } | 19222 } |
19161 } | 19223 } |
19162 return true; | 19224 return true; |
19163 } | 19225 } |
19164 | 19226 |
19165 | 19227 |
19166 RawInstance* String::CheckAndCanonicalize(const char** error_str) const { | 19228 RawInstance* String::CheckAndCanonicalize(Thread* thread, |
19229 const char** error_str) const { | |
19167 if (IsCanonical()) { | 19230 if (IsCanonical()) { |
19168 return this->raw(); | 19231 return this->raw(); |
19169 } | 19232 } |
19170 return Symbols::New(*this); | 19233 return Symbols::New(*this); |
19171 } | 19234 } |
19172 | 19235 |
19173 | 19236 |
19174 RawString* String::New(const char* cstr, Heap::Space space) { | 19237 RawString* String::New(const char* cstr, Heap::Space space) { |
19175 ASSERT(cstr != NULL); | 19238 ASSERT(cstr != NULL); |
19176 intptr_t array_len = strlen(cstr); | 19239 intptr_t array_len = strlen(cstr); |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20613 return false; | 20676 return false; |
20614 } | 20677 } |
20615 | 20678 |
20616 for (intptr_t i = 0; i < len; i++) { | 20679 for (intptr_t i = 0; i < len; i++) { |
20617 if (this->At(i) != other_arr.At(i)) { | 20680 if (this->At(i) != other_arr.At(i)) { |
20618 return false; | 20681 return false; |
20619 } | 20682 } |
20620 } | 20683 } |
20621 | 20684 |
20622 // Now check if both arrays have the same type arguments. | 20685 // Now check if both arrays have the same type arguments. |
20686 if (GetTypeArguments() == other.GetTypeArguments()) { | |
20687 return true; | |
20688 } | |
20623 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | 20689 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); |
20624 const TypeArguments& other_type_args = TypeArguments::Handle( | 20690 const TypeArguments& other_type_args = TypeArguments::Handle( |
20625 other.GetTypeArguments()); | 20691 other.GetTypeArguments()); |
20626 if (!type_args.Equals(other_type_args)) { | 20692 if (!type_args.Equals(other_type_args)) { |
20627 return false; | 20693 return false; |
20628 } | 20694 } |
20629 return true; | 20695 return true; |
20630 } | 20696 } |
20631 | 20697 |
20632 | 20698 |
20699 uword Array::ComputeCanonicalTableHash() const { | |
20700 ASSERT(!IsNull()); | |
20701 intptr_t len = Length(); | |
20702 uword hash = len; | |
20703 uword value = reinterpret_cast<uword>(GetTypeArguments()); | |
20704 hash = CombineHashes(hash, (value >> 3)); | |
20705 for (intptr_t i = 0; i < len; i++) { | |
20706 value = reinterpret_cast<uword>(At(i)); | |
20707 hash = CombineHashes(hash, (value >> 3)); | |
regis
2016/04/12 21:12:32
Same comment about ignoring 2 bits if the array el
siva
2016/04/13 16:52:41
Done.
| |
20708 } | |
20709 return FinalizeHash(hash); | |
20710 } | |
20711 | |
20712 | |
20633 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20713 RawArray* Array::New(intptr_t len, Heap::Space space) { |
20634 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20714 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
20635 return New(kClassId, len, space); | 20715 return New(kClassId, len, space); |
20636 } | 20716 } |
20637 | 20717 |
20638 | 20718 |
20639 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 20719 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { |
20640 if ((len < 0) || (len > Array::kMaxElements)) { | 20720 if ((len < 0) || (len > Array::kMaxElements)) { |
20641 // This should be caught before we reach here. | 20721 // This should be caught before we reach here. |
20642 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); | 20722 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20764 array.SetLength(used_len); | 20844 array.SetLength(used_len); |
20765 | 20845 |
20766 // Null the GrowableObjectArray, we are removing its backing array. | 20846 // Null the GrowableObjectArray, we are removing its backing array. |
20767 growable_array.SetLength(0); | 20847 growable_array.SetLength(0); |
20768 growable_array.SetData(Object::empty_array()); | 20848 growable_array.SetData(Object::empty_array()); |
20769 | 20849 |
20770 return array.raw(); | 20850 return array.raw(); |
20771 } | 20851 } |
20772 | 20852 |
20773 | 20853 |
20774 bool Array::CheckAndCanonicalizeFields(Zone* zone, | 20854 bool Array::CheckAndCanonicalizeFields(Thread* thread, |
20775 const char** error_str) const { | 20855 const char** error_str) const { |
20776 Object& obj = Object::Handle(zone); | 20856 intptr_t len = Length(); |
20777 // Iterate over all elements, canonicalize numbers and strings, expect all | 20857 if (len > 0) { |
20778 // other instances to be canonical otherwise report error (return false). | 20858 Zone* zone = thread->zone(); |
20779 for (intptr_t i = 0; i < Length(); i++) { | 20859 Object& obj = Object::Handle(zone); |
20780 obj = At(i); | 20860 // Iterate over all elements, canonicalize numbers and strings, expect all |
20781 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 20861 // other instances to be canonical otherwise report error (return false). |
20782 if (obj.IsNumber() || obj.IsString()) { | 20862 for (intptr_t i = 0; i < len; i++) { |
20783 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 20863 obj = At(i); |
20784 ASSERT(!obj.IsNull()); | 20864 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
20785 this->SetAt(i, obj); | 20865 if (obj.IsNumber() || obj.IsString()) { |
20786 } else { | 20866 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); |
20787 ASSERT(error_str != NULL); | 20867 ASSERT(!obj.IsNull()); |
20788 char* chars = OS::SCreate(Thread::Current()->zone(), | 20868 this->SetAt(i, obj); |
20789 "element at index %" Pd ": %s\n", i, obj.ToCString()); | 20869 } else { |
20790 *error_str = chars; | 20870 ASSERT(error_str != NULL); |
20791 return false; | 20871 char* chars = OS::SCreate( |
20872 zone, "element at index %" Pd ": %s\n", i, obj.ToCString()); | |
20873 *error_str = chars; | |
20874 return false; | |
20875 } | |
20792 } | 20876 } |
20793 } | 20877 } |
20794 } | 20878 } |
20795 return true; | 20879 return true; |
20796 } | 20880 } |
20797 | 20881 |
20798 | 20882 |
20799 RawImmutableArray* ImmutableArray::New(intptr_t len, | 20883 RawImmutableArray* ImmutableArray::New(intptr_t len, |
20800 Heap::Space space) { | 20884 Heap::Space space) { |
20801 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != | 20885 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
21262 const intptr_t len = this->LengthInBytes(); | 21346 const intptr_t len = this->LengthInBytes(); |
21263 if (len != other_typed_data.LengthInBytes()) { | 21347 if (len != other_typed_data.LengthInBytes()) { |
21264 return false; | 21348 return false; |
21265 } | 21349 } |
21266 NoSafepointScope no_safepoint; | 21350 NoSafepointScope no_safepoint; |
21267 return (len == 0) || | 21351 return (len == 0) || |
21268 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); | 21352 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); |
21269 } | 21353 } |
21270 | 21354 |
21271 | 21355 |
21356 uword TypedData::ComputeCanonicalTableHash() const { | |
21357 const intptr_t len = this->LengthInBytes(); | |
21358 ASSERT(len != 0); | |
21359 uword hash = len; | |
21360 for (intptr_t i = 0; i < len; i++) { | |
21361 hash = CombineHashes(len, GetUint8(i)); | |
21362 } | |
21363 return FinalizeHash(hash); | |
21364 } | |
21365 | |
21366 | |
21272 RawTypedData* TypedData::New(intptr_t class_id, | 21367 RawTypedData* TypedData::New(intptr_t class_id, |
21273 intptr_t len, | 21368 intptr_t len, |
21274 Heap::Space space) { | 21369 Heap::Space space) { |
21275 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21370 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
21276 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21371 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
21277 } | 21372 } |
21278 TypedData& result = TypedData::Handle(); | 21373 TypedData& result = TypedData::Handle(); |
21279 { | 21374 { |
21280 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); | 21375 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); |
21281 RawObject* raw = Object::Allocate(class_id, | 21376 RawObject* raw = Object::Allocate(class_id, |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
21956 return UserTag::null(); | 22051 return UserTag::null(); |
21957 } | 22052 } |
21958 | 22053 |
21959 | 22054 |
21960 const char* UserTag::ToCString() const { | 22055 const char* UserTag::ToCString() const { |
21961 const String& tag_label = String::Handle(label()); | 22056 const String& tag_label = String::Handle(label()); |
21962 return tag_label.ToCString(); | 22057 return tag_label.ToCString(); |
21963 } | 22058 } |
21964 | 22059 |
21965 } // namespace dart | 22060 } // namespace dart |
OLD | NEW |