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

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

Issue 1873143003: - Use a hash table to canonicalize instances/arrays to avoid having to iterate over a linear list a… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address-code-review 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();
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
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
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
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
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
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
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
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
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
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
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