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

Side by Side Diff: runtime/vm/object.cc

Issue 1888593003: Revert "- Use a hash table to canonicalize instances/arrays to avoid having to iterate over a linea… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698