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 DISALLOW_COPY_AND_ASSIGN(CanonicalInstanceKey); | |
4452 }; | |
4453 | |
4454 | |
4455 // Traits for looking up Canonical Instances based on a hash of the fields. | |
4456 class CanonicalInstanceTraits { | |
4457 public: | |
4458 static const char* Name() { return "CanonicalInstanceTraits"; } | |
4459 static bool ReportStats() { return false; } | |
4460 | |
4461 // Called when growing the table. | |
4462 static bool IsMatch(const Object& a, const Object& b) { | |
4463 ASSERT(!(a.IsString() || a.IsInteger() || a.IsAbstractType())); | |
4464 ASSERT(!(b.IsString() || b.IsInteger() || b.IsAbstractType())); | |
4465 return a.raw() == b.raw(); | |
4466 } | |
4467 static bool IsMatch(const CanonicalInstanceKey& a, const Object& b) { | |
4468 return a.Matches(Instance::Cast(b)); | |
4469 } | |
4470 static uword Hash(const Object& key) { | |
4471 ASSERT(!(key.IsString() || key.IsNumber() || key.IsAbstractType())); | |
4472 ASSERT(key.IsInstance()); | |
4473 return Instance::Cast(key).ComputeCanonicalTableHash(); | |
4474 } | |
4475 static uword Hash(const CanonicalInstanceKey& key) { | |
4476 return key.Hash(); | |
4477 } | |
4478 static RawObject* NewKey(const CanonicalInstanceKey& obj) { | |
4479 return obj.key_.raw(); | |
4480 } | |
4481 }; | |
4482 typedef UnorderedHashSet<CanonicalInstanceTraits> CanonicalInstancesSet; | |
4483 | |
4484 | |
4424 RawInstance* Class::LookupCanonicalInstance(Zone* zone, | 4485 RawInstance* Class::LookupCanonicalInstance(Zone* zone, |
4425 const Instance& value, | 4486 const Instance& value) const { |
4426 intptr_t* index) const { | |
4427 ASSERT(this->raw() == value.clazz()); | 4487 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); | 4488 Instance& canonical_value = Instance::Handle(zone); |
4433 while (*index < constants_len) { | 4489 if (this->constants() != Object::empty_array().raw()) { |
4434 canonical_value ^= constants.At(*index); | 4490 CanonicalInstancesSet constants(zone, this->constants()); |
4435 if (canonical_value.IsNull()) { | 4491 canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value)); |
4436 break; | 4492 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 } | 4493 } |
4444 return Instance::null(); | 4494 return canonical_value.raw(); |
4445 } | 4495 } |
4446 | 4496 |
4447 | 4497 |
4448 void Class::InsertCanonicalConstant(intptr_t index, | 4498 RawInstance* Class::InsertCanonicalConstant(Zone* zone, |
4449 const Instance& constant) const { | 4499 const Instance& constant) const { |
4450 // The constant needs to be added to the list. Grow the list if it is full. | 4500 ASSERT(this->raw() == constant.clazz()); |
4451 Array& canonical_list = Array::Handle(constants()); | 4501 Instance& canonical_value = Instance::Handle(zone); |
4452 const intptr_t list_len = canonical_list.Length(); | 4502 if (this->constants() == Object::empty_array().raw()) { |
4453 if (index >= list_len) { | 4503 CanonicalInstancesSet constants( |
4454 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; | 4504 HashTables::New<CanonicalInstancesSet>(128, Heap::kOld)); |
4455 const Array& new_canonical_list = | 4505 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); |
4456 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); | 4506 this->set_constants(constants.Release()); |
4457 set_constants(new_canonical_list); | |
4458 new_canonical_list.SetAt(index, constant); | |
4459 } else { | 4507 } else { |
4460 canonical_list.SetAt(index, constant); | 4508 CanonicalInstancesSet constants(Thread::Current()->zone(), |
4509 this->constants()); | |
4510 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant)); | |
4511 this->set_constants(constants.Release()); | |
4461 } | 4512 } |
4513 return canonical_value.raw(); | |
4462 } | 4514 } |
4463 | 4515 |
4464 | 4516 |
4465 void Class::InsertCanonicalNumber(Zone* zone, | 4517 void Class::InsertCanonicalNumber(Zone* zone, |
4466 intptr_t index, | 4518 intptr_t index, |
4467 const Number& constant) const { | 4519 const Number& constant) const { |
4468 // The constant needs to be added to the list. Grow the list if it is full. | 4520 // The constant needs to be added to the list. Grow the list if it is full. |
4469 Array& canonical_list = Array::Handle(zone, constants()); | 4521 Array& canonical_list = Array::Handle(zone, constants()); |
4470 const intptr_t list_len = canonical_list.Length(); | 4522 const intptr_t list_len = canonical_list.Length(); |
4471 if (index >= list_len) { | 4523 if (index >= list_len) { |
(...skipping 10274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14746 return true; // "===". | 14798 return true; // "===". |
14747 } | 14799 } |
14748 | 14800 |
14749 if (other.IsNull() || (this->clazz() != other.clazz())) { | 14801 if (other.IsNull() || (this->clazz() != other.clazz())) { |
14750 return false; | 14802 return false; |
14751 } | 14803 } |
14752 | 14804 |
14753 { | 14805 { |
14754 NoSafepointScope no_safepoint; | 14806 NoSafepointScope no_safepoint; |
14755 // Raw bits compare. | 14807 // Raw bits compare. |
14756 const intptr_t instance_size = Class::Handle(this->clazz()).instance_size(); | 14808 const intptr_t instance_size = SizeFromClass(); |
14757 ASSERT(instance_size != 0); | 14809 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 } | |
14758 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); | 14815 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); |
14759 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); | 14816 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); |
14760 for (intptr_t offset = Instance::NextFieldOffset(); | 14817 for (intptr_t offset = Instance::NextFieldOffset(); |
14761 offset < instance_size; | 14818 offset < instance_size; |
14762 offset += kWordSize) { | 14819 offset += kWordSize) { |
14763 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != | 14820 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != |
14764 (*reinterpret_cast<RawObject**>(other_addr + offset))) { | 14821 (*reinterpret_cast<RawObject**>(other_addr + offset))) { |
14765 return false; | 14822 return false; |
14766 } | 14823 } |
14767 } | 14824 } |
14768 } | 14825 } |
14769 return true; | 14826 return true; |
14770 } | 14827 } |
14771 | 14828 |
14772 | 14829 |
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>( | |
rmacnak
2016/04/15 18:19:18
This won't work for precompiled or app snapshots,
| |
14841 *reinterpret_cast<RawObject**>(this_addr + offset)); | |
14842 hash = CombineHashes(hash, value); | |
14843 } | |
14844 return FinalizeHash(hash); | |
14845 } | |
14846 | |
14847 | |
14773 #if defined(DEBUG) | 14848 #if defined(DEBUG) |
14774 class CheckForPointers : public ObjectPointerVisitor { | 14849 class CheckForPointers : public ObjectPointerVisitor { |
14775 public: | 14850 public: |
14776 explicit CheckForPointers(Isolate* isolate) | 14851 explicit CheckForPointers(Isolate* isolate) |
14777 : ObjectPointerVisitor(isolate), has_pointers_(false) {} | 14852 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
14778 | 14853 |
14779 bool has_pointers() const { return has_pointers_; } | 14854 bool has_pointers() const { return has_pointers_; } |
14780 | 14855 |
14781 void VisitPointers(RawObject** first, RawObject** last) { | 14856 void VisitPointers(RawObject** first, RawObject** last) { |
14782 if (first != last) { | 14857 if (first != last) { |
14783 has_pointers_ = true; | 14858 has_pointers_ = true; |
14784 } | 14859 } |
14785 } | 14860 } |
14786 | 14861 |
14787 private: | 14862 private: |
14788 bool has_pointers_; | 14863 bool has_pointers_; |
14789 | 14864 |
14790 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); | 14865 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); |
14791 }; | 14866 }; |
14792 #endif // DEBUG | 14867 #endif // DEBUG |
14793 | 14868 |
14794 | 14869 |
14795 bool Instance::CheckAndCanonicalizeFields(Zone* zone, | 14870 bool Instance::CheckAndCanonicalizeFields(Thread* thread, |
14796 const char** error_str) const { | 14871 const char** error_str) const { |
14797 const Class& cls = Class::Handle(zone, this->clazz()); | 14872 if (GetClassId() >= kNumPredefinedCids) { |
14798 if (cls.id() >= kNumPredefinedCids) { | |
14799 // Iterate over all fields, canonicalize numbers and strings, expect all | 14873 // Iterate over all fields, canonicalize numbers and strings, expect all |
14800 // other instances to be canonical otherwise report error (return false). | 14874 // other instances to be canonical otherwise report error (return false). |
14875 Zone* zone = thread->zone(); | |
14801 Object& obj = Object::Handle(zone); | 14876 Object& obj = Object::Handle(zone); |
14802 intptr_t end_field_offset = cls.instance_size() - kWordSize; | 14877 intptr_t end_field_offset = SizeFromClass() - kWordSize; |
14803 for (intptr_t field_offset = 0; | 14878 for (intptr_t field_offset = 0; |
14804 field_offset <= end_field_offset; | 14879 field_offset <= end_field_offset; |
14805 field_offset += kWordSize) { | 14880 field_offset += kWordSize) { |
14806 obj = *this->FieldAddrAtOffset(field_offset); | 14881 obj = *this->FieldAddrAtOffset(field_offset); |
14807 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 14882 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
14808 if (obj.IsNumber() || obj.IsString()) { | 14883 if (obj.IsNumber() || obj.IsString()) { |
14809 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 14884 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); |
14810 ASSERT(!obj.IsNull()); | 14885 ASSERT(!obj.IsNull()); |
14811 this->SetFieldAtOffset(field_offset, obj); | 14886 this->SetFieldAtOffset(field_offset, obj); |
14812 } else { | 14887 } else { |
14813 ASSERT(error_str != NULL); | 14888 ASSERT(error_str != NULL); |
14814 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); | 14889 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); |
14815 *error_str = chars; | 14890 *error_str = chars; |
14816 return false; | 14891 return false; |
14817 } | 14892 } |
14818 } | 14893 } |
14819 } | 14894 } |
14820 } else { | 14895 } else { |
14821 #if defined(DEBUG) | 14896 #if defined(DEBUG) |
14822 // Make sure that we are not missing any fields. | 14897 // Make sure that we are not missing any fields. |
14823 CheckForPointers has_pointers(Isolate::Current()); | 14898 CheckForPointers has_pointers(Isolate::Current()); |
14824 this->raw()->VisitPointers(&has_pointers); | 14899 this->raw()->VisitPointers(&has_pointers); |
14825 ASSERT(!has_pointers.has_pointers()); | 14900 ASSERT(!has_pointers.has_pointers()); |
14826 #endif // DEBUG | 14901 #endif // DEBUG |
14827 } | 14902 } |
14828 return true; | 14903 return true; |
14829 } | 14904 } |
14830 | 14905 |
14831 | 14906 |
14832 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { | 14907 RawInstance* Instance::CheckAndCanonicalize(Thread* thread, |
14908 const char** error_str) const { | |
14833 ASSERT(!IsNull()); | 14909 ASSERT(!IsNull()); |
14834 if (this->IsCanonical()) { | 14910 if (this->IsCanonical()) { |
14835 return this->raw(); | 14911 return this->raw(); |
14836 } | 14912 } |
14837 Thread* thread = Thread::Current(); | 14913 if (!CheckAndCanonicalizeFields(thread, error_str)) { |
14838 Zone* zone = thread->zone(); | |
14839 if (!CheckAndCanonicalizeFields(zone, error_str)) { | |
14840 return Instance::null(); | 14914 return Instance::null(); |
14841 } | 14915 } |
14916 Zone* zone = thread->zone(); | |
14842 Isolate* isolate = thread->isolate(); | 14917 Isolate* isolate = thread->isolate(); |
14843 Instance& result = Instance::Handle(zone); | 14918 Instance& result = Instance::Handle(zone); |
14844 const Class& cls = Class::Handle(zone, this->clazz()); | 14919 const Class& cls = Class::Handle(zone, this->clazz()); |
14845 intptr_t index = 0; | |
14846 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | |
14847 if (!result.IsNull()) { | |
14848 return result.raw(); | |
14849 } | |
14850 { | 14920 { |
14851 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 14921 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
14852 // Retry lookup. | 14922 if (IsNew()) { |
14853 { | 14923 result ^= cls.LookupCanonicalInstance(zone, *this); |
14854 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | |
14855 if (!result.IsNull()) { | 14924 if (!result.IsNull()) { |
14856 return result.raw(); | 14925 return result.raw(); |
14857 } | 14926 } |
14858 } | 14927 ASSERT((isolate == Dart::vm_isolate()) || !InVMHeap()); |
14859 | |
14860 // The value needs to be added to the list. Grow the list if | |
14861 // it is full. | |
14862 result ^= this->raw(); | |
14863 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap()); | |
14864 if (result.IsNew()) { | |
14865 // Create a canonical object in old space. | 14928 // Create a canonical object in old space. |
14866 result ^= Object::Clone(result, Heap::kOld); | 14929 result ^= Object::Clone(*this, Heap::kOld); |
14930 } else { | |
14931 result ^= this->raw(); | |
14867 } | 14932 } |
14868 ASSERT(result.IsOld()); | 14933 ASSERT(result.IsOld()); |
14869 result.SetCanonical(); | 14934 result.SetCanonical(); |
14870 cls.InsertCanonicalConstant(index, result); | 14935 return cls.InsertCanonicalConstant(zone, result); |
14871 return result.raw(); | |
14872 } | 14936 } |
14873 } | 14937 } |
14874 | 14938 |
14875 | 14939 |
14876 RawAbstractType* Instance::GetType() const { | 14940 RawAbstractType* Instance::GetType() const { |
14877 if (IsNull()) { | 14941 if (IsNull()) { |
14878 return Type::NullType(); | 14942 return Type::NullType(); |
14879 } | 14943 } |
14880 const Class& cls = Class::Handle(clazz()); | 14944 const Class& cls = Class::Handle(clazz()); |
14881 if (cls.IsClosureClass()) { | 14945 if (cls.IsClosureClass()) { |
(...skipping 2598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17480 | 17544 |
17481 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, | 17545 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, |
17482 const Array& mixin_types) { | 17546 const Array& mixin_types) { |
17483 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); | 17547 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); |
17484 result.set_super_type(super_type); | 17548 result.set_super_type(super_type); |
17485 result.set_mixin_types(mixin_types); | 17549 result.set_mixin_types(mixin_types); |
17486 return result.raw(); | 17550 return result.raw(); |
17487 } | 17551 } |
17488 | 17552 |
17489 | 17553 |
17490 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const { | 17554 RawInstance* Number::CheckAndCanonicalize(Thread* thread, |
17555 const char** error_str) const { | |
17491 intptr_t cid = GetClassId(); | 17556 intptr_t cid = GetClassId(); |
17492 switch (cid) { | 17557 switch (cid) { |
17493 case kSmiCid: | 17558 case kSmiCid: |
17494 return reinterpret_cast<RawSmi*>(raw_value()); | 17559 return reinterpret_cast<RawSmi*>(raw_value()); |
17495 case kMintCid: | 17560 case kMintCid: |
17496 return Mint::NewCanonical(Mint::Cast(*this).value()); | 17561 return Mint::NewCanonical(Mint::Cast(*this).value()); |
17497 case kDoubleCid: | 17562 case kDoubleCid: |
17498 return Double::NewCanonical(Double::Cast(*this).value()); | 17563 return Double::NewCanonical(Double::Cast(*this).value()); |
17499 case kBigintCid: { | 17564 case kBigintCid: { |
17500 Thread* thread = Thread::Current(); | |
17501 Zone* zone = thread->zone(); | 17565 Zone* zone = thread->zone(); |
17502 Isolate* isolate = thread->isolate(); | 17566 Isolate* isolate = thread->isolate(); |
17503 if (!CheckAndCanonicalizeFields(zone, error_str)) { | 17567 if (!CheckAndCanonicalizeFields(thread, error_str)) { |
17504 return Instance::null(); | 17568 return Instance::null(); |
17505 } | 17569 } |
17506 Bigint& result = Bigint::Handle(zone); | 17570 Bigint& result = Bigint::Handle(zone); |
17507 const Class& cls = Class::Handle(zone, this->clazz()); | 17571 const Class& cls = Class::Handle(zone, this->clazz()); |
17508 intptr_t index = 0; | 17572 intptr_t index = 0; |
17509 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); | 17573 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); |
17510 if (!result.IsNull()) { | 17574 if (!result.IsNull()) { |
17511 return result.raw(); | 17575 return result.raw(); |
17512 } | 17576 } |
17513 { | 17577 { |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18246 | 18310 |
18247 for (intptr_t i = 0; i < used; i++) { | 18311 for (intptr_t i = 0; i < used; i++) { |
18248 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { | 18312 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { |
18249 return false; | 18313 return false; |
18250 } | 18314 } |
18251 } | 18315 } |
18252 return true; | 18316 return true; |
18253 } | 18317 } |
18254 | 18318 |
18255 | 18319 |
18256 bool Bigint::CheckAndCanonicalizeFields(Zone* zone, | 18320 bool Bigint::CheckAndCanonicalizeFields(Thread* thread, |
18257 const char** error_str) const { | 18321 const char** error_str) const { |
18322 Zone* zone = thread->zone(); | |
18258 // Bool field neg should always be canonical. | 18323 // Bool field neg should always be canonical. |
18259 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); | 18324 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); |
18260 // Smi field used is canonical by definition. | 18325 // Smi field used is canonical by definition. |
18261 if (Used() > 0) { | 18326 if (Used() > 0) { |
18262 // Canonicalize TypedData field digits. | 18327 // Canonicalize TypedData field digits. |
18263 TypedData& digits_ = TypedData::Handle(zone, digits()); | 18328 TypedData& digits_ = TypedData::Handle(zone, digits()); |
18264 digits_ ^= digits_.CheckAndCanonicalize(NULL); | 18329 digits_ ^= digits_.CheckAndCanonicalize(thread, NULL); |
18265 ASSERT(!digits_.IsNull()); | 18330 ASSERT(!digits_.IsNull()); |
18266 set_digits(digits_); | 18331 set_digits(digits_); |
18267 } else { | 18332 } else { |
18268 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); | 18333 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); |
18269 } | 18334 } |
18270 return true; | 18335 return true; |
18271 } | 18336 } |
18272 | 18337 |
18273 | 18338 |
18274 RawBigint* Bigint::New(Heap::Space space) { | 18339 RawBigint* Bigint::New(Heap::Space space) { |
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
19226 intptr_t slen = other.Length(); | 19291 intptr_t slen = other.Length(); |
19227 for (int i = 0; i < slen; i++) { | 19292 for (int i = 0; i < slen; i++) { |
19228 if (this->CharAt(i) != other.CharAt(i)) { | 19293 if (this->CharAt(i) != other.CharAt(i)) { |
19229 return false; | 19294 return false; |
19230 } | 19295 } |
19231 } | 19296 } |
19232 return true; | 19297 return true; |
19233 } | 19298 } |
19234 | 19299 |
19235 | 19300 |
19236 RawInstance* String::CheckAndCanonicalize(const char** error_str) const { | 19301 RawInstance* String::CheckAndCanonicalize(Thread* thread, |
19302 const char** error_str) const { | |
19237 if (IsCanonical()) { | 19303 if (IsCanonical()) { |
19238 return this->raw(); | 19304 return this->raw(); |
19239 } | 19305 } |
19240 return Symbols::New(Thread::Current(), *this); | 19306 return Symbols::New(Thread::Current(), *this); |
19241 } | 19307 } |
19242 | 19308 |
19243 | 19309 |
19244 RawString* String::New(const char* cstr, Heap::Space space) { | 19310 RawString* String::New(const char* cstr, Heap::Space space) { |
19245 ASSERT(cstr != NULL); | 19311 ASSERT(cstr != NULL); |
19246 intptr_t array_len = strlen(cstr); | 19312 intptr_t array_len = strlen(cstr); |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20683 return false; | 20749 return false; |
20684 } | 20750 } |
20685 | 20751 |
20686 for (intptr_t i = 0; i < len; i++) { | 20752 for (intptr_t i = 0; i < len; i++) { |
20687 if (this->At(i) != other_arr.At(i)) { | 20753 if (this->At(i) != other_arr.At(i)) { |
20688 return false; | 20754 return false; |
20689 } | 20755 } |
20690 } | 20756 } |
20691 | 20757 |
20692 // Now check if both arrays have the same type arguments. | 20758 // Now check if both arrays have the same type arguments. |
20759 if (GetTypeArguments() == other.GetTypeArguments()) { | |
20760 return true; | |
20761 } | |
20693 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | 20762 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); |
20694 const TypeArguments& other_type_args = TypeArguments::Handle( | 20763 const TypeArguments& other_type_args = TypeArguments::Handle( |
20695 other.GetTypeArguments()); | 20764 other.GetTypeArguments()); |
20696 if (!type_args.Equals(other_type_args)) { | 20765 if (!type_args.Equals(other_type_args)) { |
20697 return false; | 20766 return false; |
20698 } | 20767 } |
20699 return true; | 20768 return true; |
20700 } | 20769 } |
20701 | 20770 |
20702 | 20771 |
20772 uword Array::ComputeCanonicalTableHash() const { | |
20773 ASSERT(!IsNull()); | |
20774 intptr_t len = Length(); | |
20775 uword hash = len; | |
20776 uword value = reinterpret_cast<uword>(GetTypeArguments()); | |
20777 hash = CombineHashes(hash, value); | |
20778 for (intptr_t i = 0; i < len; i++) { | |
20779 value = reinterpret_cast<uword>(At(i)); | |
20780 hash = CombineHashes(hash, value); | |
20781 } | |
20782 return FinalizeHash(hash); | |
20783 } | |
20784 | |
20785 | |
20703 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20786 RawArray* Array::New(intptr_t len, Heap::Space space) { |
20704 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20787 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
20705 return New(kClassId, len, space); | 20788 return New(kClassId, len, space); |
20706 } | 20789 } |
20707 | 20790 |
20708 | 20791 |
20709 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { | 20792 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { |
20710 if ((len < 0) || (len > Array::kMaxElements)) { | 20793 if ((len < 0) || (len > Array::kMaxElements)) { |
20711 // This should be caught before we reach here. | 20794 // This should be caught before we reach here. |
20712 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); | 20795 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20834 array.SetLength(used_len); | 20917 array.SetLength(used_len); |
20835 | 20918 |
20836 // Null the GrowableObjectArray, we are removing its backing array. | 20919 // Null the GrowableObjectArray, we are removing its backing array. |
20837 growable_array.SetLength(0); | 20920 growable_array.SetLength(0); |
20838 growable_array.SetData(Object::empty_array()); | 20921 growable_array.SetData(Object::empty_array()); |
20839 | 20922 |
20840 return array.raw(); | 20923 return array.raw(); |
20841 } | 20924 } |
20842 | 20925 |
20843 | 20926 |
20844 bool Array::CheckAndCanonicalizeFields(Zone* zone, | 20927 bool Array::CheckAndCanonicalizeFields(Thread* thread, |
20845 const char** error_str) const { | 20928 const char** error_str) const { |
20846 Object& obj = Object::Handle(zone); | 20929 intptr_t len = Length(); |
20847 // Iterate over all elements, canonicalize numbers and strings, expect all | 20930 if (len > 0) { |
20848 // other instances to be canonical otherwise report error (return false). | 20931 Zone* zone = thread->zone(); |
20849 for (intptr_t i = 0; i < Length(); i++) { | 20932 Object& obj = Object::Handle(zone); |
20850 obj = At(i); | 20933 // Iterate over all elements, canonicalize numbers and strings, expect all |
20851 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 20934 // other instances to be canonical otherwise report error (return false). |
20852 if (obj.IsNumber() || obj.IsString()) { | 20935 for (intptr_t i = 0; i < len; i++) { |
20853 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 20936 obj = At(i); |
20854 ASSERT(!obj.IsNull()); | 20937 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
20855 this->SetAt(i, obj); | 20938 if (obj.IsNumber() || obj.IsString()) { |
20856 } else { | 20939 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL); |
20857 ASSERT(error_str != NULL); | 20940 ASSERT(!obj.IsNull()); |
20858 char* chars = OS::SCreate(Thread::Current()->zone(), | 20941 this->SetAt(i, obj); |
20859 "element at index %" Pd ": %s\n", i, obj.ToCString()); | 20942 } else { |
20860 *error_str = chars; | 20943 ASSERT(error_str != NULL); |
20861 return false; | 20944 char* chars = OS::SCreate( |
20945 zone, "element at index %" Pd ": %s\n", i, obj.ToCString()); | |
20946 *error_str = chars; | |
20947 return false; | |
20948 } | |
20862 } | 20949 } |
20863 } | 20950 } |
20864 } | 20951 } |
20865 return true; | 20952 return true; |
20866 } | 20953 } |
20867 | 20954 |
20868 | 20955 |
20869 RawImmutableArray* ImmutableArray::New(intptr_t len, | 20956 RawImmutableArray* ImmutableArray::New(intptr_t len, |
20870 Heap::Space space) { | 20957 Heap::Space space) { |
20871 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != | 20958 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
21335 const intptr_t len = this->LengthInBytes(); | 21422 const intptr_t len = this->LengthInBytes(); |
21336 if (len != other_typed_data.LengthInBytes()) { | 21423 if (len != other_typed_data.LengthInBytes()) { |
21337 return false; | 21424 return false; |
21338 } | 21425 } |
21339 NoSafepointScope no_safepoint; | 21426 NoSafepointScope no_safepoint; |
21340 return (len == 0) || | 21427 return (len == 0) || |
21341 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); | 21428 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); |
21342 } | 21429 } |
21343 | 21430 |
21344 | 21431 |
21432 uword TypedData::ComputeCanonicalTableHash() const { | |
21433 const intptr_t len = this->LengthInBytes(); | |
21434 ASSERT(len != 0); | |
21435 uword hash = len; | |
21436 for (intptr_t i = 0; i < len; i++) { | |
21437 hash = CombineHashes(len, GetUint8(i)); | |
21438 } | |
21439 return FinalizeHash(hash); | |
21440 } | |
21441 | |
21442 | |
21345 RawTypedData* TypedData::New(intptr_t class_id, | 21443 RawTypedData* TypedData::New(intptr_t class_id, |
21346 intptr_t len, | 21444 intptr_t len, |
21347 Heap::Space space) { | 21445 Heap::Space space) { |
21348 if (len < 0 || len > TypedData::MaxElements(class_id)) { | 21446 if (len < 0 || len > TypedData::MaxElements(class_id)) { |
21349 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); | 21447 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); |
21350 } | 21448 } |
21351 TypedData& result = TypedData::Handle(); | 21449 TypedData& result = TypedData::Handle(); |
21352 { | 21450 { |
21353 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); | 21451 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); |
21354 RawObject* raw = Object::Allocate(class_id, | 21452 RawObject* raw = Object::Allocate(class_id, |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
22029 return UserTag::null(); | 22127 return UserTag::null(); |
22030 } | 22128 } |
22031 | 22129 |
22032 | 22130 |
22033 const char* UserTag::ToCString() const { | 22131 const char* UserTag::ToCString() const { |
22034 const String& tag_label = String::Handle(label()); | 22132 const String& tag_label = String::Handle(label()); |
22035 return tag_label.ToCString(); | 22133 return tag_label.ToCString(); |
22036 } | 22134 } |
22037 | 22135 |
22038 } // namespace dart | 22136 } // namespace dart |
OLD | NEW |