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(); | |
709 } | 708 } |
710 | 709 |
711 Smi& smi = Smi::Handle(); | 710 Smi& smi = Smi::Handle(); |
712 // Allocate and initialize the zero_array instance. | 711 // Allocate and initialize the zero_array instance. |
713 { | 712 { |
714 uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); | 713 uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld); |
715 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); | 714 InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1), true); |
716 Array::initializeHandle( | 715 Array::initializeHandle( |
717 zero_array_, | 716 zero_array_, |
718 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); | 717 reinterpret_cast<RawArray*>(address + kHeapObjectTag)); |
719 zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1)); | 718 zero_array_->StoreSmi(&zero_array_->raw_ptr()->length_, Smi::New(1)); |
720 smi = Smi::New(0); | 719 smi = Smi::New(0); |
721 zero_array_->SetAt(0, smi); | 720 zero_array_->SetAt(0, smi); |
722 zero_array_->SetCanonical(); | |
723 } | 721 } |
724 | 722 |
725 // Allocate and initialize the canonical empty context scope object. | 723 // Allocate and initialize the canonical empty context scope object. |
726 { | 724 { |
727 uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld); | 725 uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld); |
728 InitializeObject(address, | 726 InitializeObject(address, |
729 kContextScopeCid, | 727 kContextScopeCid, |
730 ContextScope::InstanceSize(0), | 728 ContextScope::InstanceSize(0), |
731 true); | 729 true); |
732 ContextScope::initializeHandle( | 730 ContextScope::initializeHandle( |
733 empty_context_scope_, | 731 empty_context_scope_, |
734 reinterpret_cast<RawContextScope*>(address + kHeapObjectTag)); | 732 reinterpret_cast<RawContextScope*>(address + kHeapObjectTag)); |
735 empty_context_scope_->StoreNonPointer( | 733 empty_context_scope_->StoreNonPointer( |
736 &empty_context_scope_->raw_ptr()->num_variables_, 0); | 734 &empty_context_scope_->raw_ptr()->num_variables_, 0); |
737 empty_context_scope_->StoreNonPointer( | 735 empty_context_scope_->StoreNonPointer( |
738 &empty_context_scope_->raw_ptr()->is_implicit_, true); | 736 &empty_context_scope_->raw_ptr()->is_implicit_, true); |
739 empty_context_scope_->SetCanonical(); | |
740 } | 737 } |
741 | 738 |
742 // Allocate and initialize the canonical empty object pool object. | 739 // Allocate and initialize the canonical empty object pool object. |
743 { | 740 { |
744 uword address = | 741 uword address = |
745 heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); | 742 heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld); |
746 InitializeObject(address, | 743 InitializeObject(address, |
747 kObjectPoolCid, | 744 kObjectPoolCid, |
748 ObjectPool::InstanceSize(0), | 745 ObjectPool::InstanceSize(0), |
749 true); | 746 true); |
750 ObjectPool::initializeHandle( | 747 ObjectPool::initializeHandle( |
751 empty_object_pool_, | 748 empty_object_pool_, |
752 reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag)); | 749 reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag)); |
753 empty_object_pool_->StoreNonPointer( | 750 empty_object_pool_->StoreNonPointer( |
754 &empty_object_pool_->raw_ptr()->length_, 0); | 751 &empty_object_pool_->raw_ptr()->length_, 0); |
755 empty_object_pool_->SetCanonical(); | |
756 } | 752 } |
757 | 753 |
758 // Allocate and initialize the empty_descriptors instance. | 754 // Allocate and initialize the empty_descriptors instance. |
759 { | 755 { |
760 uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); | 756 uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld); |
761 InitializeObject(address, kPcDescriptorsCid, | 757 InitializeObject(address, kPcDescriptorsCid, |
762 PcDescriptors::InstanceSize(0), | 758 PcDescriptors::InstanceSize(0), |
763 true); | 759 true); |
764 PcDescriptors::initializeHandle( | 760 PcDescriptors::initializeHandle( |
765 empty_descriptors_, | 761 empty_descriptors_, |
766 reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag)); | 762 reinterpret_cast<RawPcDescriptors*>(address + kHeapObjectTag)); |
767 empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_, | 763 empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_, |
768 0); | 764 0); |
769 empty_descriptors_->SetCanonical(); | |
770 } | 765 } |
771 | 766 |
772 // Allocate and initialize the canonical empty variable descriptor object. | 767 // Allocate and initialize the canonical empty variable descriptor object. |
773 { | 768 { |
774 uword address = | 769 uword address = |
775 heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); | 770 heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld); |
776 InitializeObject(address, | 771 InitializeObject(address, |
777 kLocalVarDescriptorsCid, | 772 kLocalVarDescriptorsCid, |
778 LocalVarDescriptors::InstanceSize(0), | 773 LocalVarDescriptors::InstanceSize(0), |
779 true); | 774 true); |
780 LocalVarDescriptors::initializeHandle( | 775 LocalVarDescriptors::initializeHandle( |
781 empty_var_descriptors_, | 776 empty_var_descriptors_, |
782 reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag)); | 777 reinterpret_cast<RawLocalVarDescriptors*>(address + kHeapObjectTag)); |
783 empty_var_descriptors_->StoreNonPointer( | 778 empty_var_descriptors_->StoreNonPointer( |
784 &empty_var_descriptors_->raw_ptr()->num_entries_, 0); | 779 &empty_var_descriptors_->raw_ptr()->num_entries_, 0); |
785 empty_var_descriptors_->SetCanonical(); | |
786 } | 780 } |
787 | 781 |
788 // Allocate and initialize the canonical empty exception handler info object. | 782 // Allocate and initialize the canonical empty exception handler info object. |
789 // The vast majority of all functions do not contain an exception handler | 783 // The vast majority of all functions do not contain an exception handler |
790 // and can share this canonical descriptor. | 784 // and can share this canonical descriptor. |
791 { | 785 { |
792 uword address = | 786 uword address = |
793 heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); | 787 heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld); |
794 InitializeObject(address, | 788 InitializeObject(address, |
795 kExceptionHandlersCid, | 789 kExceptionHandlersCid, |
796 ExceptionHandlers::InstanceSize(0), | 790 ExceptionHandlers::InstanceSize(0), |
797 true); | 791 true); |
798 ExceptionHandlers::initializeHandle( | 792 ExceptionHandlers::initializeHandle( |
799 empty_exception_handlers_, | 793 empty_exception_handlers_, |
800 reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag)); | 794 reinterpret_cast<RawExceptionHandlers*>(address + kHeapObjectTag)); |
801 empty_exception_handlers_->StoreNonPointer( | 795 empty_exception_handlers_->StoreNonPointer( |
802 &empty_exception_handlers_->raw_ptr()->num_entries_, 0); | 796 &empty_exception_handlers_->raw_ptr()->num_entries_, 0); |
803 empty_exception_handlers_->SetCanonical(); | |
804 } | 797 } |
805 | 798 |
806 // The VM isolate snapshot object table is initialized to an empty array | 799 // The VM isolate snapshot object table is initialized to an empty array |
807 // as we do not have any VM isolate snapshot at this time. | 800 // as we do not have any VM isolate snapshot at this time. |
808 *vm_isolate_snapshot_object_table_ = Object::empty_array().raw(); | 801 *vm_isolate_snapshot_object_table_ = Object::empty_array().raw(); |
809 | 802 |
810 cls = Class::New<Instance>(kDynamicCid); | 803 cls = Class::New<Instance>(kDynamicCid); |
811 cls.set_is_abstract(); | 804 cls.set_is_abstract(); |
812 cls.set_num_type_arguments(0); | 805 cls.set_num_type_arguments(0); |
813 cls.set_num_own_type_arguments(0); | 806 cls.set_num_own_type_arguments(0); |
(...skipping 3607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4421 if (canonical_value.Equals(value)) { | 4414 if (canonical_value.Equals(value)) { |
4422 ASSERT(canonical_value.IsCanonical()); | 4415 ASSERT(canonical_value.IsCanonical()); |
4423 return canonical_value.raw(); | 4416 return canonical_value.raw(); |
4424 } | 4417 } |
4425 *index = *index + 1; | 4418 *index = *index + 1; |
4426 } | 4419 } |
4427 return Bigint::null(); | 4420 return Bigint::null(); |
4428 } | 4421 } |
4429 | 4422 |
4430 | 4423 |
4431 class CanonicalInstanceKey { | 4424 RawInstance* Class::LookupCanonicalInstance(Zone* zone, |
4432 public: | 4425 const Instance& value, |
4433 explicit CanonicalInstanceKey(const Instance& key) : key_(key) { | 4426 intptr_t* index) const { |
4434 ASSERT(!(key.IsString() || key.IsInteger() || key.IsAbstractType())); | 4427 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); |
| 4433 while (*index < constants_len) { |
| 4434 canonical_value ^= constants.At(*index); |
| 4435 if (canonical_value.IsNull()) { |
| 4436 break; |
| 4437 } |
| 4438 if (value.CanonicalizeEquals(canonical_value)) { |
| 4439 ASSERT(canonical_value.IsCanonical()); |
| 4440 return canonical_value.raw(); |
| 4441 } |
| 4442 *index = *index + 1; |
4435 } | 4443 } |
4436 bool Matches(const Instance& obj) const { | 4444 return Instance::null(); |
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 | |
4484 RawInstance* Class::LookupCanonicalInstance(Zone* zone, | |
4485 const Instance& value) const { | |
4486 ASSERT(this->raw() == value.clazz()); | |
4487 Instance& canonical_value = Instance::Handle(zone); | |
4488 if (this->constants() != Object::empty_array().raw()) { | |
4489 CanonicalInstancesSet constants(zone, this->constants()); | |
4490 canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value)); | |
4491 this->set_constants(constants.Release()); | |
4492 } | |
4493 return canonical_value.raw(); | |
4494 } | 4445 } |
4495 | 4446 |
4496 | 4447 |
4497 RawInstance* Class::InsertCanonicalConstant(Zone* zone, | 4448 void Class::InsertCanonicalConstant(intptr_t index, |
4498 const Instance& constant) const { | 4449 const Instance& constant) const { |
4499 ASSERT(this->raw() == constant.clazz()); | 4450 // The constant needs to be added to the list. Grow the list if it is full. |
4500 Instance& canonical_value = Instance::Handle(zone); | 4451 Array& canonical_list = Array::Handle(constants()); |
4501 if (this->constants() == Object::empty_array().raw()) { | 4452 const intptr_t list_len = canonical_list.Length(); |
4502 CanonicalInstancesSet constants( | 4453 if (index >= list_len) { |
4503 HashTables::New<CanonicalInstancesSet>(128, Heap::kOld)); | 4454 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; |
4504 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); | 4455 const Array& new_canonical_list = |
4505 this->set_constants(constants.Release()); | 4456 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); |
| 4457 set_constants(new_canonical_list); |
| 4458 new_canonical_list.SetAt(index, constant); |
4506 } else { | 4459 } else { |
4507 CanonicalInstancesSet constants(Thread::Current()->zone(), | 4460 canonical_list.SetAt(index, constant); |
4508 this->constants()); | |
4509 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); | |
4510 this->set_constants(constants.Release()); | |
4511 } | 4461 } |
4512 return canonical_value.raw(); | |
4513 } | 4462 } |
4514 | 4463 |
4515 | 4464 |
4516 void Class::InsertCanonicalNumber(Zone* zone, | 4465 void Class::InsertCanonicalNumber(Zone* zone, |
4517 intptr_t index, | 4466 intptr_t index, |
4518 const Number& constant) const { | 4467 const Number& constant) const { |
4519 // The constant needs to be added to the list. Grow the list if it is full. | 4468 // The constant needs to be added to the list. Grow the list if it is full. |
4520 Array& canonical_list = Array::Handle(zone, constants()); | 4469 Array& canonical_list = Array::Handle(zone, constants()); |
4521 const intptr_t list_len = canonical_list.Length(); | 4470 const intptr_t list_len = canonical_list.Length(); |
4522 if (index >= list_len) { | 4471 if (index >= list_len) { |
(...skipping 10275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14798 return true; // "===". | 14747 return true; // "===". |
14799 } | 14748 } |
14800 | 14749 |
14801 if (other.IsNull() || (this->clazz() != other.clazz())) { | 14750 if (other.IsNull() || (this->clazz() != other.clazz())) { |
14802 return false; | 14751 return false; |
14803 } | 14752 } |
14804 | 14753 |
14805 { | 14754 { |
14806 NoSafepointScope no_safepoint; | 14755 NoSafepointScope no_safepoint; |
14807 // Raw bits compare. | 14756 // Raw bits compare. |
14808 const intptr_t instance_size = SizeFromClass(); | 14757 const intptr_t instance_size = Class::Handle(this->clazz()).instance_size(); |
14809 ASSERT(instance_size != 0); | 14758 ASSERT(instance_size != 0); |
14810 const intptr_t other_instance_size = other.SizeFromClass(); | |
14811 ASSERT(other_instance_size != 0); | |
14812 if (instance_size != other_instance_size) { | |
14813 return false; | |
14814 } | |
14815 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | 14759 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
14816 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); | 14760 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); |
14817 for (intptr_t offset = Instance::NextFieldOffset(); | 14761 for (intptr_t offset = Instance::NextFieldOffset(); |
14818 offset < instance_size; | 14762 offset < instance_size; |
14819 offset += kWordSize) { | 14763 offset += kWordSize) { |
14820 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != | 14764 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != |
14821 (*reinterpret_cast<RawObject**>(other_addr + offset))) { | 14765 (*reinterpret_cast<RawObject**>(other_addr + offset))) { |
14822 return false; | 14766 return false; |
14823 } | 14767 } |
14824 } | 14768 } |
14825 } | 14769 } |
14826 return true; | 14770 return true; |
14827 } | 14771 } |
14828 | 14772 |
14829 | 14773 |
14830 uword Instance::ComputeCanonicalTableHash() const { | |
14831 ASSERT(!IsNull()); | |
14832 NoSafepointScope no_safepoint; | |
14833 const intptr_t instance_size = SizeFromClass(); | |
14834 ASSERT(instance_size != 0); | |
14835 uword hash = instance_size; | |
14836 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | |
14837 for (intptr_t offset = Instance::NextFieldOffset(); | |
14838 offset < instance_size; | |
14839 offset += kWordSize) { | |
14840 uword value = reinterpret_cast<uword>( | |
14841 *reinterpret_cast<RawObject**>(this_addr + offset)); | |
14842 hash = CombineHashes(hash, value); | |
14843 } | |
14844 return FinalizeHash(hash); | |
14845 } | |
14846 | |
14847 | |
14848 #if defined(DEBUG) | 14774 #if defined(DEBUG) |
14849 class CheckForPointers : public ObjectPointerVisitor { | 14775 class CheckForPointers : public ObjectPointerVisitor { |
14850 public: | 14776 public: |
14851 explicit CheckForPointers(Isolate* isolate) | 14777 explicit CheckForPointers(Isolate* isolate) |
14852 : ObjectPointerVisitor(isolate), has_pointers_(false) {} | 14778 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
14853 | 14779 |
14854 bool has_pointers() const { return has_pointers_; } | 14780 bool has_pointers() const { return has_pointers_; } |
14855 | 14781 |
14856 void VisitPointers(RawObject** first, RawObject** last) { | 14782 void VisitPointers(RawObject** first, RawObject** last) { |
14857 if (first != last) { | 14783 if (first != last) { |
14858 has_pointers_ = true; | 14784 has_pointers_ = true; |
14859 } | 14785 } |
14860 } | 14786 } |
14861 | 14787 |
14862 private: | 14788 private: |
14863 bool has_pointers_; | 14789 bool has_pointers_; |
14864 | 14790 |
14865 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); | 14791 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); |
14866 }; | 14792 }; |
14867 #endif // DEBUG | 14793 #endif // DEBUG |
14868 | 14794 |
14869 | 14795 |
14870 bool Instance::CheckAndCanonicalizeFields(Thread* thread, | 14796 bool Instance::CheckAndCanonicalizeFields(Zone* zone, |
14871 const char** error_str) const { | 14797 const char** error_str) const { |
14872 if (GetClassId() >= kNumPredefinedCids) { | 14798 const Class& cls = Class::Handle(zone, this->clazz()); |
| 14799 if (cls.id() >= kNumPredefinedCids) { |
14873 // Iterate over all fields, canonicalize numbers and strings, expect all | 14800 // Iterate over all fields, canonicalize numbers and strings, expect all |
14874 // other instances to be canonical otherwise report error (return false). | 14801 // other instances to be canonical otherwise report error (return false). |
14875 Zone* zone = thread->zone(); | |
14876 Object& obj = Object::Handle(zone); | 14802 Object& obj = Object::Handle(zone); |
14877 intptr_t end_field_offset = SizeFromClass() - kWordSize; | 14803 intptr_t end_field_offset = cls.instance_size() - kWordSize; |
14878 for (intptr_t field_offset = 0; | 14804 for (intptr_t field_offset = 0; |
14879 field_offset <= end_field_offset; | 14805 field_offset <= end_field_offset; |
14880 field_offset += kWordSize) { | 14806 field_offset += kWordSize) { |
14881 obj = *this->FieldAddrAtOffset(field_offset); | 14807 obj = *this->FieldAddrAtOffset(field_offset); |
14882 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 14808 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
14883 if (obj.IsNumber() || obj.IsString()) { | 14809 if (obj.IsNumber() || obj.IsString()) { |
14884 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); | 14810 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); |
14885 ASSERT(!obj.IsNull()); | 14811 ASSERT(!obj.IsNull()); |
14886 this->SetFieldAtOffset(field_offset, obj); | 14812 this->SetFieldAtOffset(field_offset, obj); |
14887 } else { | 14813 } else { |
14888 ASSERT(error_str != NULL); | 14814 ASSERT(error_str != NULL); |
14889 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); | 14815 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); |
14890 *error_str = chars; | 14816 *error_str = chars; |
14891 return false; | 14817 return false; |
14892 } | 14818 } |
14893 } | 14819 } |
14894 } | 14820 } |
14895 } else { | 14821 } else { |
14896 #if defined(DEBUG) | 14822 #if defined(DEBUG) |
14897 // Make sure that we are not missing any fields. | 14823 // Make sure that we are not missing any fields. |
14898 CheckForPointers has_pointers(Isolate::Current()); | 14824 CheckForPointers has_pointers(Isolate::Current()); |
14899 this->raw()->VisitPointers(&has_pointers); | 14825 this->raw()->VisitPointers(&has_pointers); |
14900 ASSERT(!has_pointers.has_pointers()); | 14826 ASSERT(!has_pointers.has_pointers()); |
14901 #endif // DEBUG | 14827 #endif // DEBUG |
14902 } | 14828 } |
14903 return true; | 14829 return true; |
14904 } | 14830 } |
14905 | 14831 |
14906 | 14832 |
14907 RawInstance* Instance::CheckAndCanonicalize(Thread* thread, | 14833 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { |
14908 const char** error_str) const { | |
14909 ASSERT(!IsNull()); | 14834 ASSERT(!IsNull()); |
14910 if (this->IsCanonical()) { | 14835 if (this->IsCanonical()) { |
14911 return this->raw(); | 14836 return this->raw(); |
14912 } | 14837 } |
14913 if (!CheckAndCanonicalizeFields(thread, error_str)) { | 14838 Thread* thread = Thread::Current(); |
| 14839 Zone* zone = thread->zone(); |
| 14840 if (!CheckAndCanonicalizeFields(zone, error_str)) { |
14914 return Instance::null(); | 14841 return Instance::null(); |
14915 } | 14842 } |
14916 Zone* zone = thread->zone(); | |
14917 Isolate* isolate = thread->isolate(); | 14843 Isolate* isolate = thread->isolate(); |
14918 Instance& result = Instance::Handle(zone); | 14844 Instance& result = Instance::Handle(zone); |
14919 const Class& cls = Class::Handle(zone, this->clazz()); | 14845 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 } |
14920 { | 14851 { |
14921 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 14852 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
14922 if (IsNew()) { | 14853 // Retry lookup. |
14923 result ^= cls.LookupCanonicalInstance(zone, *this); | 14854 { |
| 14855 result ^= cls.LookupCanonicalInstance(zone, *this, &index); |
14924 if (!result.IsNull()) { | 14856 if (!result.IsNull()) { |
14925 return result.raw(); | 14857 return result.raw(); |
14926 } | 14858 } |
14927 ASSERT((isolate == Dart::vm_isolate()) || !InVMHeap()); | 14859 } |
| 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()) { |
14928 // Create a canonical object in old space. | 14866 // Create a canonical object in old space. |
14929 result ^= Object::Clone(*this, Heap::kOld); | 14867 result ^= Object::Clone(result, Heap::kOld); |
14930 } else { | |
14931 result ^= this->raw(); | |
14932 } | 14868 } |
14933 ASSERT(result.IsOld()); | 14869 ASSERT(result.IsOld()); |
14934 result.SetCanonical(); | 14870 result.SetCanonical(); |
14935 return cls.InsertCanonicalConstant(zone, result); | 14871 cls.InsertCanonicalConstant(index, result); |
| 14872 return result.raw(); |
14936 } | 14873 } |
14937 } | 14874 } |
14938 | 14875 |
14939 | 14876 |
14940 RawAbstractType* Instance::GetType() const { | 14877 RawAbstractType* Instance::GetType() const { |
14941 if (IsNull()) { | 14878 if (IsNull()) { |
14942 return Type::NullType(); | 14879 return Type::NullType(); |
14943 } | 14880 } |
14944 const Class& cls = Class::Handle(clazz()); | 14881 const Class& cls = Class::Handle(clazz()); |
14945 if (cls.IsClosureClass()) { | 14882 if (cls.IsClosureClass()) { |
(...skipping 2601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17547 | 17484 |
17548 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, | 17485 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, |
17549 const Array& mixin_types) { | 17486 const Array& mixin_types) { |
17550 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); | 17487 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); |
17551 result.set_super_type(super_type); | 17488 result.set_super_type(super_type); |
17552 result.set_mixin_types(mixin_types); | 17489 result.set_mixin_types(mixin_types); |
17553 return result.raw(); | 17490 return result.raw(); |
17554 } | 17491 } |
17555 | 17492 |
17556 | 17493 |
17557 RawInstance* Number::CheckAndCanonicalize(Thread* thread, | 17494 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const { |
17558 const char** error_str) const { | |
17559 intptr_t cid = GetClassId(); | 17495 intptr_t cid = GetClassId(); |
17560 switch (cid) { | 17496 switch (cid) { |
17561 case kSmiCid: | 17497 case kSmiCid: |
17562 return reinterpret_cast<RawSmi*>(raw_value()); | 17498 return reinterpret_cast<RawSmi*>(raw_value()); |
17563 case kMintCid: | 17499 case kMintCid: |
17564 return Mint::NewCanonical(Mint::Cast(*this).value()); | 17500 return Mint::NewCanonical(Mint::Cast(*this).value()); |
17565 case kDoubleCid: | 17501 case kDoubleCid: |
17566 return Double::NewCanonical(Double::Cast(*this).value()); | 17502 return Double::NewCanonical(Double::Cast(*this).value()); |
17567 case kBigintCid: { | 17503 case kBigintCid: { |
| 17504 Thread* thread = Thread::Current(); |
17568 Zone* zone = thread->zone(); | 17505 Zone* zone = thread->zone(); |
17569 Isolate* isolate = thread->isolate(); | 17506 Isolate* isolate = thread->isolate(); |
17570 if (!CheckAndCanonicalizeFields(thread, error_str)) { | 17507 if (!CheckAndCanonicalizeFields(zone, error_str)) { |
17571 return Instance::null(); | 17508 return Instance::null(); |
17572 } | 17509 } |
17573 Bigint& result = Bigint::Handle(zone); | 17510 Bigint& result = Bigint::Handle(zone); |
17574 const Class& cls = Class::Handle(zone, this->clazz()); | 17511 const Class& cls = Class::Handle(zone, this->clazz()); |
17575 intptr_t index = 0; | 17512 intptr_t index = 0; |
17576 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); | 17513 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); |
17577 if (!result.IsNull()) { | 17514 if (!result.IsNull()) { |
17578 return result.raw(); | 17515 return result.raw(); |
17579 } | 17516 } |
17580 { | 17517 { |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18313 | 18250 |
18314 for (intptr_t i = 0; i < used; i++) { | 18251 for (intptr_t i = 0; i < used; i++) { |
18315 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { | 18252 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { |
18316 return false; | 18253 return false; |
18317 } | 18254 } |
18318 } | 18255 } |
18319 return true; | 18256 return true; |
18320 } | 18257 } |
18321 | 18258 |
18322 | 18259 |
18323 bool Bigint::CheckAndCanonicalizeFields(Thread* thread, | 18260 bool Bigint::CheckAndCanonicalizeFields(Zone* zone, |
18324 const char** error_str) const { | 18261 const char** error_str) const { |
18325 Zone* zone = thread->zone(); | |
18326 // Bool field neg should always be canonical. | 18262 // Bool field neg should always be canonical. |
18327 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); | 18263 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); |
18328 // Smi field used is canonical by definition. | 18264 // Smi field used is canonical by definition. |
18329 if (Used() > 0) { | 18265 if (Used() > 0) { |
18330 // Canonicalize TypedData field digits. | 18266 // Canonicalize TypedData field digits. |
18331 TypedData& digits_ = TypedData::Handle(zone, digits()); | 18267 TypedData& digits_ = TypedData::Handle(zone, digits()); |
18332 digits_ ^= digits_.CheckAndCanonicalize(thread, NULL); | 18268 digits_ ^= digits_.CheckAndCanonicalize(NULL); |
18333 ASSERT(!digits_.IsNull()); | 18269 ASSERT(!digits_.IsNull()); |
18334 set_digits(digits_); | 18270 set_digits(digits_); |
18335 } else { | 18271 } else { |
18336 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); | 18272 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); |
18337 } | 18273 } |
18338 return true; | 18274 return true; |
18339 } | 18275 } |
18340 | 18276 |
18341 | 18277 |
18342 RawBigint* Bigint::New(Heap::Space space) { | 18278 RawBigint* Bigint::New(Heap::Space space) { |
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19294 intptr_t slen = other.Length(); | 19230 intptr_t slen = other.Length(); |
19295 for (int i = 0; i < slen; i++) { | 19231 for (int i = 0; i < slen; i++) { |
19296 if (this->CharAt(i) != other.CharAt(i)) { | 19232 if (this->CharAt(i) != other.CharAt(i)) { |
19297 return false; | 19233 return false; |
19298 } | 19234 } |
19299 } | 19235 } |
19300 return true; | 19236 return true; |
19301 } | 19237 } |
19302 | 19238 |
19303 | 19239 |
19304 RawInstance* String::CheckAndCanonicalize(Thread* thread, | 19240 RawInstance* String::CheckAndCanonicalize(const char** error_str) const { |
19305 const char** error_str) const { | |
19306 if (IsCanonical()) { | 19241 if (IsCanonical()) { |
19307 return this->raw(); | 19242 return this->raw(); |
19308 } | 19243 } |
19309 return Symbols::New(Thread::Current(), *this); | 19244 return Symbols::New(Thread::Current(), *this); |
19310 } | 19245 } |
19311 | 19246 |
19312 | 19247 |
19313 RawString* String::New(const char* cstr, Heap::Space space) { | 19248 RawString* String::New(const char* cstr, Heap::Space space) { |
19314 ASSERT(cstr != NULL); | 19249 ASSERT(cstr != NULL); |
19315 intptr_t array_len = strlen(cstr); | 19250 intptr_t array_len = strlen(cstr); |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20752 return false; | 20687 return false; |
20753 } | 20688 } |
20754 | 20689 |
20755 for (intptr_t i = 0; i < len; i++) { | 20690 for (intptr_t i = 0; i < len; i++) { |
20756 if (this->At(i) != other_arr.At(i)) { | 20691 if (this->At(i) != other_arr.At(i)) { |
20757 return false; | 20692 return false; |
20758 } | 20693 } |
20759 } | 20694 } |
20760 | 20695 |
20761 // Now check if both arrays have the same type arguments. | 20696 // Now check if both arrays have the same type arguments. |
20762 if (GetTypeArguments() == other.GetTypeArguments()) { | |
20763 return true; | |
20764 } | |
20765 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | 20697 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); |
20766 const TypeArguments& other_type_args = TypeArguments::Handle( | 20698 const TypeArguments& other_type_args = TypeArguments::Handle( |
20767 other.GetTypeArguments()); | 20699 other.GetTypeArguments()); |
20768 if (!type_args.Equals(other_type_args)) { | 20700 if (!type_args.Equals(other_type_args)) { |
20769 return false; | 20701 return false; |
20770 } | 20702 } |
20771 return true; | 20703 return true; |
20772 } | 20704 } |
20773 | 20705 |
20774 | 20706 |
20775 uword Array::ComputeCanonicalTableHash() const { | |
20776 ASSERT(!IsNull()); | |
20777 intptr_t len = Length(); | |
20778 uword hash = len; | |
20779 uword value = reinterpret_cast<uword>(GetTypeArguments()); | |
20780 hash = CombineHashes(hash, value); | |
20781 for (intptr_t i = 0; i < len; i++) { | |
20782 value = reinterpret_cast<uword>(At(i)); | |
20783 hash = CombineHashes(hash, value); | |
20784 } | |
20785 return FinalizeHash(hash); | |
20786 } | |
20787 | |
20788 | |
20789 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20707 RawArray* Array::New(intptr_t len, Heap::Space space) { |
20790 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20708 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
20791 return New(kClassId, len, space); | 20709 return New(kClassId, len, space); |
20792 } | 20710 } |
20793 | 20711 |
20794 | 20712 |
20795 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 20713 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { |
20796 if ((len < 0) || (len > Array::kMaxElements)) { | 20714 if ((len < 0) || (len > Array::kMaxElements)) { |
20797 // This should be caught before we reach here. | 20715 // This should be caught before we reach here. |
20798 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); | 20716 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20920 array.SetLength(used_len); | 20838 array.SetLength(used_len); |
20921 | 20839 |
20922 // Null the GrowableObjectArray, we are removing its backing array. | 20840 // Null the GrowableObjectArray, we are removing its backing array. |
20923 growable_array.SetLength(0); | 20841 growable_array.SetLength(0); |
20924 growable_array.SetData(Object::empty_array()); | 20842 growable_array.SetData(Object::empty_array()); |
20925 | 20843 |
20926 return array.raw(); | 20844 return array.raw(); |
20927 } | 20845 } |
20928 | 20846 |
20929 | 20847 |
20930 bool Array::CheckAndCanonicalizeFields(Thread* thread, | 20848 bool Array::CheckAndCanonicalizeFields(Zone* zone, |
20931 const char** error_str) const { | 20849 const char** error_str) const { |
20932 intptr_t len = Length(); | 20850 Object& obj = Object::Handle(zone); |
20933 if (len > 0) { | 20851 // Iterate over all elements, canonicalize numbers and strings, expect all |
20934 Zone* zone = thread->zone(); | 20852 // other instances to be canonical otherwise report error (return false). |
20935 Object& obj = Object::Handle(zone); | 20853 for (intptr_t i = 0; i < Length(); i++) { |
20936 // Iterate over all elements, canonicalize numbers and strings, expect all | 20854 obj = At(i); |
20937 // other instances to be canonical otherwise report error (return false). | 20855 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
20938 for (intptr_t i = 0; i < len; i++) { | 20856 if (obj.IsNumber() || obj.IsString()) { |
20939 obj = At(i); | 20857 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); |
20940 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 20858 ASSERT(!obj.IsNull()); |
20941 if (obj.IsNumber() || obj.IsString()) { | 20859 this->SetAt(i, obj); |
20942 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); | 20860 } else { |
20943 ASSERT(!obj.IsNull()); | 20861 ASSERT(error_str != NULL); |
20944 this->SetAt(i, obj); | 20862 char* chars = OS::SCreate(Thread::Current()->zone(), |
20945 } else { | 20863 "element at index %" Pd ": %s\n", i, obj.ToCString()); |
20946 ASSERT(error_str != NULL); | 20864 *error_str = chars; |
20947 char* chars = OS::SCreate( | 20865 return false; |
20948 zone, "element at index %" Pd ": %s\n", i, obj.ToCString()); | |
20949 *error_str = chars; | |
20950 return false; | |
20951 } | |
20952 } | 20866 } |
20953 } | 20867 } |
20954 } | 20868 } |
20955 return true; | 20869 return true; |
20956 } | 20870 } |
20957 | 20871 |
20958 | 20872 |
20959 RawImmutableArray* ImmutableArray::New(intptr_t len, | 20873 RawImmutableArray* ImmutableArray::New(intptr_t len, |
20960 Heap::Space space) { | 20874 Heap::Space space) { |
20961 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != | 20875 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21425 const intptr_t len = this->LengthInBytes(); | 21339 const intptr_t len = this->LengthInBytes(); |
21426 if (len != other_typed_data.LengthInBytes()) { | 21340 if (len != other_typed_data.LengthInBytes()) { |
21427 return false; | 21341 return false; |
21428 } | 21342 } |
21429 NoSafepointScope no_safepoint; | 21343 NoSafepointScope no_safepoint; |
21430 return (len == 0) || | 21344 return (len == 0) || |
21431 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); | 21345 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); |
21432 } | 21346 } |
21433 | 21347 |
21434 | 21348 |
21435 uword TypedData::ComputeCanonicalTableHash() const { | |
21436 const intptr_t len = this->LengthInBytes(); | |
21437 ASSERT(len != 0); | |
21438 uword hash = len; | |
21439 for (intptr_t i = 0; i < len; i++) { | |
21440 hash = CombineHashes(len, GetUint8(i)); | |
21441 } | |
21442 return FinalizeHash(hash); | |
21443 } | |
21444 | |
21445 | |
21446 RawTypedData* TypedData::New(intptr_t class_id, | 21349 RawTypedData* TypedData::New(intptr_t class_id, |
21447 intptr_t len, | 21350 intptr_t len, |
21448 Heap::Space space) { | 21351 Heap::Space space) { |
21449 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21352 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
21450 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21353 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
21451 } | 21354 } |
21452 TypedData& result = TypedData::Handle(); | 21355 TypedData& result = TypedData::Handle(); |
21453 { | 21356 { |
21454 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); | 21357 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); |
21455 RawObject* raw = Object::Allocate(class_id, | 21358 RawObject* raw = Object::Allocate(class_id, |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22130 return UserTag::null(); | 22033 return UserTag::null(); |
22131 } | 22034 } |
22132 | 22035 |
22133 | 22036 |
22134 const char* UserTag::ToCString() const { | 22037 const char* UserTag::ToCString() const { |
22135 const String& tag_label = String::Handle(label()); | 22038 const String& tag_label = String::Handle(label()); |
22136 return tag_label.ToCString(); | 22039 return tag_label.ToCString(); |
22137 } | 22040 } |
22138 | 22041 |
22139 } // namespace dart | 22042 } // namespace dart |
OLD | NEW |