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

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

Issue 1900863002: Reapply "- Use a hash table to canonicalize instances/arrays to avoid having to iterate over a line… (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();
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 };
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
4424 RawInstance* Class::LookupCanonicalInstance(Zone* zone, 4484 RawInstance* Class::LookupCanonicalInstance(Zone* zone,
4425 const Instance& value, 4485 const Instance& value) const {
4426 intptr_t* index) const {
4427 ASSERT(this->raw() == value.clazz()); 4486 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); 4487 Instance& canonical_value = Instance::Handle(zone);
4433 while (*index < constants_len) { 4488 if (this->constants() != Object::empty_array().raw()) {
4434 canonical_value ^= constants.At(*index); 4489 CanonicalInstancesSet constants(zone, this->constants());
4435 if (canonical_value.IsNull()) { 4490 canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value));
4436 break; 4491 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 } 4492 }
4444 return Instance::null(); 4493 return canonical_value.raw();
4445 } 4494 }
4446 4495
4447 4496
4448 void Class::InsertCanonicalConstant(intptr_t index, 4497 RawInstance* Class::InsertCanonicalConstant(Zone* zone,
4449 const Instance& constant) const { 4498 const Instance& constant) const {
4450 // The constant needs to be added to the list. Grow the list if it is full. 4499 ASSERT(this->raw() == constant.clazz());
4451 Array& canonical_list = Array::Handle(constants()); 4500 Instance& canonical_value = Instance::Handle(zone);
4452 const intptr_t list_len = canonical_list.Length(); 4501 if (this->constants() == Object::empty_array().raw()) {
4453 if (index >= list_len) { 4502 CanonicalInstancesSet constants(
4454 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; 4503 HashTables::New<CanonicalInstancesSet>(128, Heap::kOld));
4455 const Array& new_canonical_list = 4504 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
4456 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); 4505 this->set_constants(constants.Release());
4457 set_constants(new_canonical_list);
4458 new_canonical_list.SetAt(index, constant);
4459 } else { 4506 } else {
4460 canonical_list.SetAt(index, constant); 4507 CanonicalInstancesSet constants(Thread::Current()->zone(),
4508 this->constants());
4509 canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
4510 this->set_constants(constants.Release());
4461 } 4511 }
4512 return canonical_value.raw();
4462 } 4513 }
4463 4514
4464 4515
4465 void Class::InsertCanonicalNumber(Zone* zone, 4516 void Class::InsertCanonicalNumber(Zone* zone,
4466 intptr_t index, 4517 intptr_t index,
4467 const Number& constant) const { 4518 const Number& constant) const {
4468 // The constant needs to be added to the list. Grow the list if it is full. 4519 // The constant needs to be added to the list. Grow the list if it is full.
4469 Array& canonical_list = Array::Handle(zone, constants()); 4520 Array& canonical_list = Array::Handle(zone, constants());
4470 const intptr_t list_len = canonical_list.Length(); 4521 const intptr_t list_len = canonical_list.Length();
4471 if (index >= list_len) { 4522 if (index >= list_len) {
4472 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; 4523 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
4473 canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld); 4524 canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld);
4474 set_constants(canonical_list); 4525 set_constants(canonical_list);
4475 } 4526 }
4476 canonical_list.SetAt(index, constant); 4527 canonical_list.SetAt(index, constant);
4477 } 4528 }
4478 4529
4479 4530
4531 void Class::RehashConstants(Zone* zone) const {
4532 intptr_t cid = id();
4533 if ((cid == kMintCid) || (cid == kBigintCid) || (cid == kDoubleCid)) {
4534 // Constants stored as a plain list, no rehashing needed.
4535 return;
4536 }
4537
4538 const Array& old_constants = Array::Handle(zone, constants());
4539 if (old_constants.Length() == 0) return;
4540
4541 set_constants(Object::empty_array());
4542 CanonicalInstancesSet set(zone, old_constants.raw());
4543 Instance& constant = Instance::Handle(zone);
4544 CanonicalInstancesSet::Iterator it(&set);
4545 while (it.MoveNext()) {
4546 constant ^= set.GetKey(it.Current());
4547 ASSERT(!constant.IsNull());
4548 InsertCanonicalConstant(zone, constant);
4549 }
4550 set.Release();
4551 }
4552
4553
4480 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix, 4554 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
4481 const String& ident, 4555 const String& ident,
4482 TokenPosition token_pos) { 4556 TokenPosition token_pos) {
4483 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); 4557 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New());
4484 type.set_library_prefix(library_prefix); 4558 type.set_library_prefix(library_prefix);
4485 type.set_ident(ident); 4559 type.set_ident(ident);
4486 type.set_token_pos(token_pos); 4560 type.set_token_pos(token_pos);
4487 return type.raw(); 4561 return type.raw();
4488 } 4562 }
4489 4563
(...skipping 10257 matching lines...) Expand 10 before | Expand all | Expand 10 after
14747 return true; // "===". 14821 return true; // "===".
14748 } 14822 }
14749 14823
14750 if (other.IsNull() || (this->clazz() != other.clazz())) { 14824 if (other.IsNull() || (this->clazz() != other.clazz())) {
14751 return false; 14825 return false;
14752 } 14826 }
14753 14827
14754 { 14828 {
14755 NoSafepointScope no_safepoint; 14829 NoSafepointScope no_safepoint;
14756 // Raw bits compare. 14830 // Raw bits compare.
14757 const intptr_t instance_size = Class::Handle(this->clazz()).instance_size(); 14831 const intptr_t instance_size = SizeFromClass();
14758 ASSERT(instance_size != 0); 14832 ASSERT(instance_size != 0);
14833 const intptr_t other_instance_size = other.SizeFromClass();
14834 ASSERT(other_instance_size != 0);
14835 if (instance_size != other_instance_size) {
14836 return false;
14837 }
14759 uword this_addr = reinterpret_cast<uword>(this->raw_ptr()); 14838 uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
14760 uword other_addr = reinterpret_cast<uword>(other.raw_ptr()); 14839 uword other_addr = reinterpret_cast<uword>(other.raw_ptr());
14761 for (intptr_t offset = Instance::NextFieldOffset(); 14840 for (intptr_t offset = Instance::NextFieldOffset();
14762 offset < instance_size; 14841 offset < instance_size;
14763 offset += kWordSize) { 14842 offset += kWordSize) {
14764 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != 14843 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) !=
14765 (*reinterpret_cast<RawObject**>(other_addr + offset))) { 14844 (*reinterpret_cast<RawObject**>(other_addr + offset))) {
14766 return false; 14845 return false;
14767 } 14846 }
14768 } 14847 }
14769 } 14848 }
14770 return true; 14849 return true;
14771 } 14850 }
14772 14851
14773 14852
14853 uword Instance::ComputeCanonicalTableHash() const {
14854 ASSERT(!IsNull());
14855 NoSafepointScope no_safepoint;
14856 const intptr_t instance_size = SizeFromClass();
14857 ASSERT(instance_size != 0);
14858 uword hash = instance_size;
14859 uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
14860 for (intptr_t offset = Instance::NextFieldOffset();
14861 offset < instance_size;
14862 offset += kWordSize) {
14863 uword value = reinterpret_cast<uword>(
14864 *reinterpret_cast<RawObject**>(this_addr + offset));
14865 hash = CombineHashes(hash, value);
14866 }
14867 return FinalizeHash(hash);
14868 }
14869
14870
14774 #if defined(DEBUG) 14871 #if defined(DEBUG)
14775 class CheckForPointers : public ObjectPointerVisitor { 14872 class CheckForPointers : public ObjectPointerVisitor {
14776 public: 14873 public:
14777 explicit CheckForPointers(Isolate* isolate) 14874 explicit CheckForPointers(Isolate* isolate)
14778 : ObjectPointerVisitor(isolate), has_pointers_(false) {} 14875 : ObjectPointerVisitor(isolate), has_pointers_(false) {}
14779 14876
14780 bool has_pointers() const { return has_pointers_; } 14877 bool has_pointers() const { return has_pointers_; }
14781 14878
14782 void VisitPointers(RawObject** first, RawObject** last) { 14879 void VisitPointers(RawObject** first, RawObject** last) {
14783 if (first != last) { 14880 if (first != last) {
14784 has_pointers_ = true; 14881 has_pointers_ = true;
14785 } 14882 }
14786 } 14883 }
14787 14884
14788 private: 14885 private:
14789 bool has_pointers_; 14886 bool has_pointers_;
14790 14887
14791 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); 14888 DISALLOW_COPY_AND_ASSIGN(CheckForPointers);
14792 }; 14889 };
14793 #endif // DEBUG 14890 #endif // DEBUG
14794 14891
14795 14892
14796 bool Instance::CheckAndCanonicalizeFields(Zone* zone, 14893 bool Instance::CheckAndCanonicalizeFields(Thread* thread,
14797 const char** error_str) const { 14894 const char** error_str) const {
14798 const Class& cls = Class::Handle(zone, this->clazz()); 14895 if (GetClassId() >= kNumPredefinedCids) {
14799 if (cls.id() >= kNumPredefinedCids) {
14800 // Iterate over all fields, canonicalize numbers and strings, expect all 14896 // Iterate over all fields, canonicalize numbers and strings, expect all
14801 // other instances to be canonical otherwise report error (return false). 14897 // other instances to be canonical otherwise report error (return false).
14898 Zone* zone = thread->zone();
14802 Object& obj = Object::Handle(zone); 14899 Object& obj = Object::Handle(zone);
14803 intptr_t end_field_offset = cls.instance_size() - kWordSize; 14900 intptr_t end_field_offset = SizeFromClass() - kWordSize;
14804 for (intptr_t field_offset = 0; 14901 for (intptr_t field_offset = 0;
14805 field_offset <= end_field_offset; 14902 field_offset <= end_field_offset;
14806 field_offset += kWordSize) { 14903 field_offset += kWordSize) {
14807 obj = *this->FieldAddrAtOffset(field_offset); 14904 obj = *this->FieldAddrAtOffset(field_offset);
14808 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { 14905 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
14809 if (obj.IsNumber() || obj.IsString()) { 14906 if (obj.IsNumber() || obj.IsString()) {
14810 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); 14907 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL);
14811 ASSERT(!obj.IsNull()); 14908 ASSERT(!obj.IsNull());
14812 this->SetFieldAtOffset(field_offset, obj); 14909 this->SetFieldAtOffset(field_offset, obj);
14813 } else { 14910 } else {
14814 ASSERT(error_str != NULL); 14911 ASSERT(error_str != NULL);
14815 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString()); 14912 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString());
14816 *error_str = chars; 14913 *error_str = chars;
14817 return false; 14914 return false;
14818 } 14915 }
14819 } 14916 }
14820 } 14917 }
14821 } else { 14918 } else {
14822 #if defined(DEBUG) 14919 #if defined(DEBUG)
14823 // Make sure that we are not missing any fields. 14920 // Make sure that we are not missing any fields.
14824 CheckForPointers has_pointers(Isolate::Current()); 14921 CheckForPointers has_pointers(Isolate::Current());
14825 this->raw()->VisitPointers(&has_pointers); 14922 this->raw()->VisitPointers(&has_pointers);
14826 ASSERT(!has_pointers.has_pointers()); 14923 ASSERT(!has_pointers.has_pointers());
14827 #endif // DEBUG 14924 #endif // DEBUG
14828 } 14925 }
14829 return true; 14926 return true;
14830 } 14927 }
14831 14928
14832 14929
14833 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { 14930 RawInstance* Instance::CheckAndCanonicalize(Thread* thread,
14931 const char** error_str) const {
14834 ASSERT(!IsNull()); 14932 ASSERT(!IsNull());
14835 if (this->IsCanonical()) { 14933 if (this->IsCanonical()) {
14836 return this->raw(); 14934 return this->raw();
14837 } 14935 }
14838 Thread* thread = Thread::Current(); 14936 if (!CheckAndCanonicalizeFields(thread, error_str)) {
14839 Zone* zone = thread->zone();
14840 if (!CheckAndCanonicalizeFields(zone, error_str)) {
14841 return Instance::null(); 14937 return Instance::null();
14842 } 14938 }
14939 Zone* zone = thread->zone();
14843 Isolate* isolate = thread->isolate(); 14940 Isolate* isolate = thread->isolate();
14844 Instance& result = Instance::Handle(zone); 14941 Instance& result = Instance::Handle(zone);
14845 const Class& cls = Class::Handle(zone, this->clazz()); 14942 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 }
14851 { 14943 {
14852 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); 14944 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
14853 // Retry lookup. 14945 if (IsNew()) {
14854 { 14946 result ^= cls.LookupCanonicalInstance(zone, *this);
14855 result ^= cls.LookupCanonicalInstance(zone, *this, &index);
14856 if (!result.IsNull()) { 14947 if (!result.IsNull()) {
14857 return result.raw(); 14948 return result.raw();
14858 } 14949 }
14859 } 14950 ASSERT((isolate == Dart::vm_isolate()) || !InVMHeap());
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()) {
14866 // Create a canonical object in old space. 14951 // Create a canonical object in old space.
14867 result ^= Object::Clone(result, Heap::kOld); 14952 result ^= Object::Clone(*this, Heap::kOld);
14953 } else {
14954 result ^= this->raw();
14868 } 14955 }
14869 ASSERT(result.IsOld()); 14956 ASSERT(result.IsOld());
14870 result.SetCanonical(); 14957 result.SetCanonical();
14871 cls.InsertCanonicalConstant(index, result); 14958 return cls.InsertCanonicalConstant(zone, result);
14872 return result.raw();
14873 } 14959 }
14874 } 14960 }
14875 14961
14876 14962
14877 RawAbstractType* Instance::GetType() const { 14963 RawAbstractType* Instance::GetType() const {
14878 if (IsNull()) { 14964 if (IsNull()) {
14879 return Type::NullType(); 14965 return Type::NullType();
14880 } 14966 }
14881 const Class& cls = Class::Handle(clazz()); 14967 const Class& cls = Class::Handle(clazz());
14882 if (cls.IsClosureClass()) { 14968 if (cls.IsClosureClass()) {
(...skipping 2601 matching lines...) Expand 10 before | Expand all | Expand 10 after
17484 17570
17485 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, 17571 RawMixinAppType* MixinAppType::New(const AbstractType& super_type,
17486 const Array& mixin_types) { 17572 const Array& mixin_types) {
17487 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); 17573 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New());
17488 result.set_super_type(super_type); 17574 result.set_super_type(super_type);
17489 result.set_mixin_types(mixin_types); 17575 result.set_mixin_types(mixin_types);
17490 return result.raw(); 17576 return result.raw();
17491 } 17577 }
17492 17578
17493 17579
17494 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const { 17580 RawInstance* Number::CheckAndCanonicalize(Thread* thread,
17581 const char** error_str) const {
17495 intptr_t cid = GetClassId(); 17582 intptr_t cid = GetClassId();
17496 switch (cid) { 17583 switch (cid) {
17497 case kSmiCid: 17584 case kSmiCid:
17498 return reinterpret_cast<RawSmi*>(raw_value()); 17585 return reinterpret_cast<RawSmi*>(raw_value());
17499 case kMintCid: 17586 case kMintCid:
17500 return Mint::NewCanonical(Mint::Cast(*this).value()); 17587 return Mint::NewCanonical(Mint::Cast(*this).value());
17501 case kDoubleCid: 17588 case kDoubleCid:
17502 return Double::NewCanonical(Double::Cast(*this).value()); 17589 return Double::NewCanonical(Double::Cast(*this).value());
17503 case kBigintCid: { 17590 case kBigintCid: {
17504 Thread* thread = Thread::Current();
17505 Zone* zone = thread->zone(); 17591 Zone* zone = thread->zone();
17506 Isolate* isolate = thread->isolate(); 17592 Isolate* isolate = thread->isolate();
17507 if (!CheckAndCanonicalizeFields(zone, error_str)) { 17593 if (!CheckAndCanonicalizeFields(thread, error_str)) {
17508 return Instance::null(); 17594 return Instance::null();
17509 } 17595 }
17510 Bigint& result = Bigint::Handle(zone); 17596 Bigint& result = Bigint::Handle(zone);
17511 const Class& cls = Class::Handle(zone, this->clazz()); 17597 const Class& cls = Class::Handle(zone, this->clazz());
17512 intptr_t index = 0; 17598 intptr_t index = 0;
17513 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); 17599 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index);
17514 if (!result.IsNull()) { 17600 if (!result.IsNull()) {
17515 return result.raw(); 17601 return result.raw();
17516 } 17602 }
17517 { 17603 {
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after
18250 18336
18251 for (intptr_t i = 0; i < used; i++) { 18337 for (intptr_t i = 0; i < used; i++) {
18252 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { 18338 if (this->DigitAt(i) != other_bgi.DigitAt(i)) {
18253 return false; 18339 return false;
18254 } 18340 }
18255 } 18341 }
18256 return true; 18342 return true;
18257 } 18343 }
18258 18344
18259 18345
18260 bool Bigint::CheckAndCanonicalizeFields(Zone* zone, 18346 bool Bigint::CheckAndCanonicalizeFields(Thread* thread,
18261 const char** error_str) const { 18347 const char** error_str) const {
18348 Zone* zone = thread->zone();
18262 // Bool field neg should always be canonical. 18349 // Bool field neg should always be canonical.
18263 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); 18350 ASSERT(Bool::Handle(zone, neg()).IsCanonical());
18264 // Smi field used is canonical by definition. 18351 // Smi field used is canonical by definition.
18265 if (Used() > 0) { 18352 if (Used() > 0) {
18266 // Canonicalize TypedData field digits. 18353 // Canonicalize TypedData field digits.
18267 TypedData& digits_ = TypedData::Handle(zone, digits()); 18354 TypedData& digits_ = TypedData::Handle(zone, digits());
18268 digits_ ^= digits_.CheckAndCanonicalize(NULL); 18355 digits_ ^= digits_.CheckAndCanonicalize(thread, NULL);
18269 ASSERT(!digits_.IsNull()); 18356 ASSERT(!digits_.IsNull());
18270 set_digits(digits_); 18357 set_digits(digits_);
18271 } else { 18358 } else {
18272 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); 18359 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current()));
18273 } 18360 }
18274 return true; 18361 return true;
18275 } 18362 }
18276 18363
18277 18364
18278 RawBigint* Bigint::New(Heap::Space space) { 18365 RawBigint* Bigint::New(Heap::Space space) {
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after
19230 intptr_t slen = other.Length(); 19317 intptr_t slen = other.Length();
19231 for (int i = 0; i < slen; i++) { 19318 for (int i = 0; i < slen; i++) {
19232 if (this->CharAt(i) != other.CharAt(i)) { 19319 if (this->CharAt(i) != other.CharAt(i)) {
19233 return false; 19320 return false;
19234 } 19321 }
19235 } 19322 }
19236 return true; 19323 return true;
19237 } 19324 }
19238 19325
19239 19326
19240 RawInstance* String::CheckAndCanonicalize(const char** error_str) const { 19327 RawInstance* String::CheckAndCanonicalize(Thread* thread,
19328 const char** error_str) const {
19241 if (IsCanonical()) { 19329 if (IsCanonical()) {
19242 return this->raw(); 19330 return this->raw();
19243 } 19331 }
19244 return Symbols::New(Thread::Current(), *this); 19332 return Symbols::New(Thread::Current(), *this);
19245 } 19333 }
19246 19334
19247 19335
19248 RawString* String::New(const char* cstr, Heap::Space space) { 19336 RawString* String::New(const char* cstr, Heap::Space space) {
19249 ASSERT(cstr != NULL); 19337 ASSERT(cstr != NULL);
19250 intptr_t array_len = strlen(cstr); 19338 intptr_t array_len = strlen(cstr);
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after
20687 return false; 20775 return false;
20688 } 20776 }
20689 20777
20690 for (intptr_t i = 0; i < len; i++) { 20778 for (intptr_t i = 0; i < len; i++) {
20691 if (this->At(i) != other_arr.At(i)) { 20779 if (this->At(i) != other_arr.At(i)) {
20692 return false; 20780 return false;
20693 } 20781 }
20694 } 20782 }
20695 20783
20696 // Now check if both arrays have the same type arguments. 20784 // Now check if both arrays have the same type arguments.
20785 if (GetTypeArguments() == other.GetTypeArguments()) {
20786 return true;
20787 }
20697 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); 20788 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
20698 const TypeArguments& other_type_args = TypeArguments::Handle( 20789 const TypeArguments& other_type_args = TypeArguments::Handle(
20699 other.GetTypeArguments()); 20790 other.GetTypeArguments());
20700 if (!type_args.Equals(other_type_args)) { 20791 if (!type_args.Equals(other_type_args)) {
20701 return false; 20792 return false;
20702 } 20793 }
20703 return true; 20794 return true;
20704 } 20795 }
20705 20796
20706 20797
20798 uword Array::ComputeCanonicalTableHash() const {
20799 ASSERT(!IsNull());
20800 intptr_t len = Length();
20801 uword hash = len;
20802 uword value = reinterpret_cast<uword>(GetTypeArguments());
20803 hash = CombineHashes(hash, value);
20804 for (intptr_t i = 0; i < len; i++) {
20805 value = reinterpret_cast<uword>(At(i));
20806 hash = CombineHashes(hash, value);
20807 }
20808 return FinalizeHash(hash);
20809 }
20810
20811
20707 RawArray* Array::New(intptr_t len, Heap::Space space) { 20812 RawArray* Array::New(intptr_t len, Heap::Space space) {
20708 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); 20813 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
20709 return New(kClassId, len, space); 20814 return New(kClassId, len, space);
20710 } 20815 }
20711 20816
20712 20817
20713 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) { 20818 RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) {
20714 if ((len < 0) || (len > Array::kMaxElements)) { 20819 if ((len < 0) || (len > Array::kMaxElements)) {
20715 // This should be caught before we reach here. 20820 // This should be caught before we reach here.
20716 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len); 20821 FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
20838 array.SetLength(used_len); 20943 array.SetLength(used_len);
20839 20944
20840 // Null the GrowableObjectArray, we are removing its backing array. 20945 // Null the GrowableObjectArray, we are removing its backing array.
20841 growable_array.SetLength(0); 20946 growable_array.SetLength(0);
20842 growable_array.SetData(Object::empty_array()); 20947 growable_array.SetData(Object::empty_array());
20843 20948
20844 return array.raw(); 20949 return array.raw();
20845 } 20950 }
20846 20951
20847 20952
20848 bool Array::CheckAndCanonicalizeFields(Zone* zone, 20953 bool Array::CheckAndCanonicalizeFields(Thread* thread,
20849 const char** error_str) const { 20954 const char** error_str) const {
20850 Object& obj = Object::Handle(zone); 20955 intptr_t len = Length();
20851 // Iterate over all elements, canonicalize numbers and strings, expect all 20956 if (len > 0) {
20852 // other instances to be canonical otherwise report error (return false). 20957 Zone* zone = thread->zone();
20853 for (intptr_t i = 0; i < Length(); i++) { 20958 Object& obj = Object::Handle(zone);
20854 obj = At(i); 20959 // Iterate over all elements, canonicalize numbers and strings, expect all
20855 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { 20960 // other instances to be canonical otherwise report error (return false).
20856 if (obj.IsNumber() || obj.IsString()) { 20961 for (intptr_t i = 0; i < len; i++) {
20857 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); 20962 obj = At(i);
20858 ASSERT(!obj.IsNull()); 20963 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
20859 this->SetAt(i, obj); 20964 if (obj.IsNumber() || obj.IsString()) {
20860 } else { 20965 obj = Instance::Cast(obj).CheckAndCanonicalize(thread, NULL);
20861 ASSERT(error_str != NULL); 20966 ASSERT(!obj.IsNull());
20862 char* chars = OS::SCreate(Thread::Current()->zone(), 20967 this->SetAt(i, obj);
20863 "element at index %" Pd ": %s\n", i, obj.ToCString()); 20968 } else {
20864 *error_str = chars; 20969 ASSERT(error_str != NULL);
20865 return false; 20970 char* chars = OS::SCreate(
20971 zone, "element at index %" Pd ": %s\n", i, obj.ToCString());
20972 *error_str = chars;
20973 return false;
20974 }
20866 } 20975 }
20867 } 20976 }
20868 } 20977 }
20869 return true; 20978 return true;
20870 } 20979 }
20871 20980
20872 20981
20873 RawImmutableArray* ImmutableArray::New(intptr_t len, 20982 RawImmutableArray* ImmutableArray::New(intptr_t len,
20874 Heap::Space space) { 20983 Heap::Space space) {
20875 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != 20984 ASSERT(Isolate::Current()->object_store()->immutable_array_class() !=
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
21339 const intptr_t len = this->LengthInBytes(); 21448 const intptr_t len = this->LengthInBytes();
21340 if (len != other_typed_data.LengthInBytes()) { 21449 if (len != other_typed_data.LengthInBytes()) {
21341 return false; 21450 return false;
21342 } 21451 }
21343 NoSafepointScope no_safepoint; 21452 NoSafepointScope no_safepoint;
21344 return (len == 0) || 21453 return (len == 0) ||
21345 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0); 21454 (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0);
21346 } 21455 }
21347 21456
21348 21457
21458 uword TypedData::ComputeCanonicalTableHash() const {
21459 const intptr_t len = this->LengthInBytes();
21460 ASSERT(len != 0);
21461 uword hash = len;
21462 for (intptr_t i = 0; i < len; i++) {
21463 hash = CombineHashes(len, GetUint8(i));
21464 }
21465 return FinalizeHash(hash);
21466 }
21467
21468
21349 RawTypedData* TypedData::New(intptr_t class_id, 21469 RawTypedData* TypedData::New(intptr_t class_id,
21350 intptr_t len, 21470 intptr_t len,
21351 Heap::Space space) { 21471 Heap::Space space) {
21352 if (len < 0 || len > TypedData::MaxElements(class_id)) { 21472 if (len < 0 || len > TypedData::MaxElements(class_id)) {
21353 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len); 21473 FATAL1("Fatal error in TypedData::New: invalid len %" Pd "\n", len);
21354 } 21474 }
21355 TypedData& result = TypedData::Handle(); 21475 TypedData& result = TypedData::Handle();
21356 { 21476 {
21357 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id); 21477 const intptr_t lengthInBytes = len * ElementSizeInBytes(class_id);
21358 RawObject* raw = Object::Allocate(class_id, 21478 RawObject* raw = Object::Allocate(class_id,
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
22033 return UserTag::null(); 22153 return UserTag::null();
22034 } 22154 }
22035 22155
22036 22156
22037 const char* UserTag::ToCString() const { 22157 const char* UserTag::ToCString() const {
22038 const String& tag_label = String::Handle(label()); 22158 const String& tag_label = String::Handle(label());
22039 return tag_label.ToCString(); 22159 return tag_label.ToCString();
22040 } 22160 }
22041 22161
22042 } // namespace dart 22162 } // 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