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

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

Issue 1866713003: - Restructure the Canonicalization of instances in preparation for adding a (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review-comments 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') | no next file » | 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 4381 matching lines...) Expand 10 before | Expand all | Expand 10 after
4392 const Array& new_canonical_list = 4392 const Array& new_canonical_list =
4393 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); 4393 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld));
4394 set_constants(new_canonical_list); 4394 set_constants(new_canonical_list);
4395 new_canonical_list.SetAt(index, constant); 4395 new_canonical_list.SetAt(index, constant);
4396 } else { 4396 } else {
4397 canonical_list.SetAt(index, constant); 4397 canonical_list.SetAt(index, constant);
4398 } 4398 }
4399 } 4399 }
4400 4400
4401 4401
4402 void Class::InsertCanonicalNumber(Zone* zone,
4403 intptr_t index,
4404 const Number& constant) const {
4405 // The constant needs to be added to the list. Grow the list if it is full.
4406 Array& canonical_list = Array::Handle(zone, constants());
4407 const intptr_t list_len = canonical_list.Length();
4408 if (index >= list_len) {
4409 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
4410 canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld);
4411 set_constants(canonical_list);
4412 }
4413 canonical_list.SetAt(index, constant);
4414 }
4415
4416
4402 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix, 4417 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
4403 const String& ident, 4418 const String& ident,
4404 TokenPosition token_pos) { 4419 TokenPosition token_pos) {
4405 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); 4420 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New());
4406 type.set_library_prefix(library_prefix); 4421 type.set_library_prefix(library_prefix);
4407 type.set_ident(ident); 4422 type.set_ident(ident);
4408 type.set_token_pos(token_pos); 4423 type.set_token_pos(token_pos);
4409 return type.raw(); 4424 return type.raw();
4410 } 4425 }
4411 4426
(...skipping 10235 matching lines...) Expand 10 before | Expand all | Expand 10 after
14647 } 14662 }
14648 14663
14649 private: 14664 private:
14650 bool has_pointers_; 14665 bool has_pointers_;
14651 14666
14652 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); 14667 DISALLOW_COPY_AND_ASSIGN(CheckForPointers);
14653 }; 14668 };
14654 #endif // DEBUG 14669 #endif // DEBUG
14655 14670
14656 14671
14657 bool Instance::CheckAndCanonicalizeFields(const char** error_str) const { 14672 bool Instance::CheckAndCanonicalizeFields(Zone* zone,
14658 const Class& cls = Class::Handle(this->clazz()); 14673 const char** error_str) const {
14674 const Class& cls = Class::Handle(zone, this->clazz());
14659 if (cls.id() >= kNumPredefinedCids) { 14675 if (cls.id() >= kNumPredefinedCids) {
14660 // Iterate over all fields, canonicalize numbers and strings, expect all 14676 // Iterate over all fields, canonicalize numbers and strings, expect all
14661 // other instances to be canonical otherwise report error (return false). 14677 // other instances to be canonical otherwise report error (return false).
14662 Object& obj = Object::Handle(); 14678 Object& obj = Object::Handle(zone);
14663 intptr_t end_field_offset = cls.instance_size() - kWordSize; 14679 intptr_t end_field_offset = cls.instance_size() - kWordSize;
14664 for (intptr_t field_offset = 0; 14680 for (intptr_t field_offset = 0;
14665 field_offset <= end_field_offset; 14681 field_offset <= end_field_offset;
14666 field_offset += kWordSize) { 14682 field_offset += kWordSize) {
14667 obj = *this->FieldAddrAtOffset(field_offset); 14683 obj = *this->FieldAddrAtOffset(field_offset);
14668 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { 14684 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
14669 if (obj.IsNumber() || obj.IsString()) { 14685 if (obj.IsNumber() || obj.IsString()) {
14670 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); 14686 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL);
14671 ASSERT(!obj.IsNull()); 14687 ASSERT(!obj.IsNull());
14672 this->SetFieldAtOffset(field_offset, obj); 14688 this->SetFieldAtOffset(field_offset, obj);
14673 } else { 14689 } else {
14674 ASSERT(error_str != NULL); 14690 ASSERT(error_str != NULL);
14675 char* chars = OS::SCreate(Thread::Current()->zone(), 14691 char* chars = OS::SCreate(zone, "field: %s\n", obj.ToCString());
14676 "field: %s\n", obj.ToCString());
14677 *error_str = chars; 14692 *error_str = chars;
14678 return false; 14693 return false;
14679 } 14694 }
14680 } 14695 }
14681 } 14696 }
14682 } else { 14697 } else {
14683 #if defined(DEBUG) 14698 #if defined(DEBUG)
14684 // Make sure that we are not missing any fields. 14699 // Make sure that we are not missing any fields.
14685 CheckForPointers has_pointers(Isolate::Current()); 14700 CheckForPointers has_pointers(Isolate::Current());
14686 this->raw()->VisitPointers(&has_pointers); 14701 this->raw()->VisitPointers(&has_pointers);
14687 ASSERT(!has_pointers.has_pointers()); 14702 ASSERT(!has_pointers.has_pointers());
14688 #endif // DEBUG 14703 #endif // DEBUG
14689 } 14704 }
14690 return true; 14705 return true;
14691 } 14706 }
14692 14707
14693 14708
14694 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { 14709 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
14695 ASSERT(!IsNull()); 14710 ASSERT(!IsNull());
14696 if (this->IsCanonical()) { 14711 if (this->IsCanonical()) {
14697 return this->raw(); 14712 return this->raw();
14698 } 14713 }
14699 if (!CheckAndCanonicalizeFields(error_str)) { 14714 Thread* thread = Thread::Current();
14715 Zone* zone = thread->zone();
14716 if (!CheckAndCanonicalizeFields(zone, error_str)) {
14700 return Instance::null(); 14717 return Instance::null();
14701 } 14718 }
14702 Thread* thread = Thread::Current();
14703 Zone* zone = thread->zone();
14704 Isolate* isolate = thread->isolate(); 14719 Isolate* isolate = thread->isolate();
14705 Instance& result = Instance::Handle(zone); 14720 Instance& result = Instance::Handle(zone);
14706 const Class& cls = Class::Handle(zone, this->clazz()); 14721 const Class& cls = Class::Handle(zone, this->clazz());
14707 intptr_t index = 0; 14722 intptr_t index = 0;
14708 result ^= cls.LookupCanonicalInstance(zone, *this, &index); 14723 result ^= cls.LookupCanonicalInstance(zone, *this, &index);
14709 if (!result.IsNull()) { 14724 if (!result.IsNull()) {
14710 return result.raw(); 14725 return result.raw();
14711 } 14726 }
14712 { 14727 {
14713 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); 14728 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
14714 // Retry lookup. 14729 // Retry lookup.
14715 { 14730 {
14716 Instance& temp_result = Instance::Handle(zone, 14731 result ^= cls.LookupCanonicalInstance(zone, *this, &index);
14717 cls.LookupCanonicalInstance(zone, *this, &index)); 14732 if (!result.IsNull()) {
14718 if (!temp_result.IsNull()) { 14733 return result.raw();
14719 return temp_result.raw();
14720 } 14734 }
14721 } 14735 }
14722 14736
14723 // The value needs to be added to the list. Grow the list if 14737 // The value needs to be added to the list. Grow the list if
14724 // it is full. 14738 // it is full.
14725 result ^= this->raw(); 14739 result ^= this->raw();
14726 if (result.IsNew() || 14740 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap());
14727 (result.InVMHeap() && (isolate != Dart::vm_isolate()))) { 14741 if (result.IsNew()) {
14728 /**
14729 * When a snapshot is generated on a 64 bit architecture and then read
14730 * into a 32 bit architecture, values which are Smi on the 64 bit
14731 * architecture could potentially be converted to Mint objects, however
14732 * since Smi values do not have any notion of canonical bits we lose
14733 * that information when the object becomes a Mint.
14734 * Some of these values could be literal values and end up in the
14735 * VM isolate heap. Later when these values are referenced in a
14736 * constant list we try to ensure that all the objects in the list
14737 * are canonical and try to canonicalize them. When these Mint objects
14738 * are encountered they do not have the canonical bit set and
14739 * canonicalizing them won't work as the VM heap is read only now.
14740 * In these cases we clone the object into the isolate and then
14741 * canonicalize it.
14742 */
14743 // Create a canonical object in old space. 14742 // Create a canonical object in old space.
14744 result ^= Object::Clone(result, Heap::kOld); 14743 result ^= Object::Clone(result, Heap::kOld);
14745 } 14744 }
14746 ASSERT(result.IsOld()); 14745 ASSERT(result.IsOld());
14747
14748 result.SetCanonical(); 14746 result.SetCanonical();
14749 cls.InsertCanonicalConstant(index, result); 14747 cls.InsertCanonicalConstant(index, result);
14750 return result.raw(); 14748 return result.raw();
14751 } 14749 }
14752 } 14750 }
14753 14751
14754 14752
14755 RawAbstractType* Instance::GetType() const { 14753 RawAbstractType* Instance::GetType() const {
14756 if (IsNull()) { 14754 if (IsNull()) {
14757 return Type::NullType(); 14755 return Type::NullType();
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
14949 return DartLibraryCalls::Equals(*this, other) == Object::bool_true().raw(); 14947 return DartLibraryCalls::Equals(*this, other) == Object::bool_true().raw();
14950 } 14948 }
14951 14949
14952 14950
14953 bool Instance::IsIdenticalTo(const Instance& other) const { 14951 bool Instance::IsIdenticalTo(const Instance& other) const {
14954 if (raw() == other.raw()) return true; 14952 if (raw() == other.raw()) return true;
14955 if (IsInteger() && other.IsInteger()) { 14953 if (IsInteger() && other.IsInteger()) {
14956 return Integer::Cast(*this).Equals(other); 14954 return Integer::Cast(*this).Equals(other);
14957 } 14955 }
14958 if (IsDouble() && other.IsDouble()) { 14956 if (IsDouble() && other.IsDouble()) {
14959 return Double::Cast(*this).CanonicalizeEquals(other); 14957 double other_value = Double::Cast(other).value();
14958 return Double::Cast(*this).BitwiseEqualsToDouble(other_value);
14960 } 14959 }
14961 return false; 14960 return false;
14962 } 14961 }
14963 14962
14964 14963
14965 intptr_t* Instance::NativeFieldsDataAddr() const { 14964 intptr_t* Instance::NativeFieldsDataAddr() const {
14966 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); 14965 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
14967 RawTypedData* native_fields = 14966 RawTypedData* native_fields =
14968 reinterpret_cast<RawTypedData*>(*NativeFieldsAddr()); 14967 reinterpret_cast<RawTypedData*>(*NativeFieldsAddr());
14969 if (native_fields == TypedData::null()) { 14968 if (native_fields == TypedData::null()) {
(...skipping 2383 matching lines...) Expand 10 before | Expand all | Expand 10 after
17353 17352
17354 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, 17353 RawMixinAppType* MixinAppType::New(const AbstractType& super_type,
17355 const Array& mixin_types) { 17354 const Array& mixin_types) {
17356 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); 17355 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New());
17357 result.set_super_type(super_type); 17356 result.set_super_type(super_type);
17358 result.set_mixin_types(mixin_types); 17357 result.set_mixin_types(mixin_types);
17359 return result.raw(); 17358 return result.raw();
17360 } 17359 }
17361 17360
17362 17361
17362 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const {
17363 intptr_t cid = GetClassId();
17364 switch (cid) {
17365 case kSmiCid:
17366 return reinterpret_cast<RawSmi*>(raw_value());
17367 case kMintCid:
17368 return Mint::NewCanonical(Mint::Cast(*this).value());
17369 case kDoubleCid:
17370 return Double::NewCanonical(Double::Cast(*this).value());
17371 case kBigintCid: {
17372 Thread* thread = Thread::Current();
17373 Zone* zone = thread->zone();
17374 Isolate* isolate = thread->isolate();
17375 if (!CheckAndCanonicalizeFields(zone, error_str)) {
17376 return Instance::null();
17377 }
17378 Bigint& result = Bigint::Handle(zone);
17379 const Class& cls = Class::Handle(zone, this->clazz());
17380 intptr_t index = 0;
17381 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index);
17382 if (!result.IsNull()) {
17383 return result.raw();
17384 }
17385 {
17386 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17387 // Retry lookup.
17388 {
17389 result ^= cls.LookupCanonicalBigint(
17390 zone, Bigint::Cast(*this), &index);
17391 if (!result.IsNull()) {
17392 return result.raw();
17393 }
17394 }
17395
17396 // The value needs to be added to the list. Grow the list if
17397 // it is full.
17398 result ^= this->raw();
17399 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap());
17400 if (result.IsNew()) {
17401 // Create a canonical object in old space.
17402 result ^= Object::Clone(result, Heap::kOld);
17403 }
17404 ASSERT(result.IsOld());
17405 result.SetCanonical();
17406 cls.InsertCanonicalNumber(zone, index, result);
17407 return result.raw();
17408 }
17409 }
17410 default:
17411 UNREACHABLE();
17412 }
17413 return Instance::null();
17414 }
17415
17416
17363 const char* Number::ToCString() const { 17417 const char* Number::ToCString() const {
17364 // Number is an interface. No instances of Number should exist. 17418 // Number is an interface. No instances of Number should exist.
17365 UNREACHABLE(); 17419 UNREACHABLE();
17366 return "Number"; 17420 return "Number";
17367 } 17421 }
17368 17422
17369 17423
17370 const char* Integer::ToCString() const { 17424 const char* Integer::ToCString() const {
17371 // Integer is an interface. No instances of Integer should exist except null. 17425 // Integer is an interface. No instances of Integer should exist except null.
17372 ASSERT(IsNull()); 17426 ASSERT(IsNull());
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
17776 Mint& canonical_value = Mint::Handle(zone); 17830 Mint& canonical_value = Mint::Handle(zone);
17777 intptr_t index = 0; 17831 intptr_t index = 0;
17778 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index); 17832 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index);
17779 if (!canonical_value.IsNull()) { 17833 if (!canonical_value.IsNull()) {
17780 return canonical_value.raw(); 17834 return canonical_value.raw();
17781 } 17835 }
17782 { 17836 {
17783 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); 17837 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17784 // Retry lookup. 17838 // Retry lookup.
17785 { 17839 {
17786 const Mint& result = 17840 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index);
17787 Mint::Handle(zone, cls.LookupCanonicalMint(zone, value, &index)); 17841 if (!canonical_value.IsNull()) {
17788 if (!result.IsNull()) { 17842 return canonical_value.raw();
17789 return result.raw();
17790 } 17843 }
17791 } 17844 }
17792 canonical_value = Mint::New(value, Heap::kOld); 17845 canonical_value = Mint::New(value, Heap::kOld);
17793 canonical_value.SetCanonical(); 17846 canonical_value.SetCanonical();
17794 // The value needs to be added to the constants list. Grow the list if 17847 // The value needs to be added to the constants list. Grow the list if
17795 // it is full. 17848 // it is full.
17796 cls.InsertCanonicalConstant(index, canonical_value); 17849 cls.InsertCanonicalNumber(zone, index, canonical_value);
17797 return canonical_value.raw(); 17850 return canonical_value.raw();
17798 } 17851 }
17799 } 17852 }
17800 17853
17801 17854
17802 bool Mint::Equals(const Instance& other) const { 17855 bool Mint::Equals(const Instance& other) const {
17803 if (this->raw() == other.raw()) { 17856 if (this->raw() == other.raw()) {
17804 // Both handles point to the same raw instance. 17857 // Both handles point to the same raw instance.
17805 return true; 17858 return true;
17806 } 17859 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
17929 intptr_t index = 0; 17982 intptr_t index = 0;
17930 17983
17931 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index); 17984 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index);
17932 if (!canonical_value.IsNull()) { 17985 if (!canonical_value.IsNull()) {
17933 return canonical_value.raw(); 17986 return canonical_value.raw();
17934 } 17987 }
17935 { 17988 {
17936 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); 17989 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
17937 // Retry lookup. 17990 // Retry lookup.
17938 { 17991 {
17939 const Double& result = 17992 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index);
17940 Double::Handle(zone, cls.LookupCanonicalDouble(zone, value, &index)); 17993 if (!canonical_value.IsNull()) {
17941 if (!result.IsNull()) { 17994 return canonical_value.raw();
17942 return result.raw();
17943 } 17995 }
17944 } 17996 }
17945 canonical_value = Double::New(value, Heap::kOld); 17997 canonical_value = Double::New(value, Heap::kOld);
17946 canonical_value.SetCanonical(); 17998 canonical_value.SetCanonical();
17947 // The value needs to be added to the constants list. Grow the list if 17999 // The value needs to be added to the constants list. Grow the list if
17948 // it is full. 18000 // it is full.
17949 cls.InsertCanonicalConstant(index, canonical_value); 18001 cls.InsertCanonicalNumber(zone, index, canonical_value);
17950 return canonical_value.raw(); 18002 return canonical_value.raw();
17951 } 18003 }
17952 } 18004 }
17953 18005
17954 18006
17955 RawDouble* Double::NewCanonical(const String& str) { 18007 RawDouble* Double::NewCanonical(const String& str) {
17956 double double_value; 18008 double double_value;
17957 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { 18009 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
17958 return Double::Handle().raw(); 18010 return Double::Handle().raw();
17959 } 18011 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
18066 18118
18067 for (intptr_t i = 0; i < used; i++) { 18119 for (intptr_t i = 0; i < used; i++) {
18068 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { 18120 if (this->DigitAt(i) != other_bgi.DigitAt(i)) {
18069 return false; 18121 return false;
18070 } 18122 }
18071 } 18123 }
18072 return true; 18124 return true;
18073 } 18125 }
18074 18126
18075 18127
18076 bool Bigint::CheckAndCanonicalizeFields(const char** error_str) const { 18128 bool Bigint::CheckAndCanonicalizeFields(Zone* zone,
18129 const char** error_str) const {
18077 // Bool field neg should always be canonical. 18130 // Bool field neg should always be canonical.
18078 ASSERT(Bool::Handle(neg()).IsCanonical()); 18131 ASSERT(Bool::Handle(zone, neg()).IsCanonical());
18079 // Smi field used is canonical by definition. 18132 // Smi field used is canonical by definition.
18080 if (Used() > 0) { 18133 if (Used() > 0) {
18081 // Canonicalize TypedData field digits. 18134 // Canonicalize TypedData field digits.
18082 TypedData& digits_ = TypedData::Handle(digits()); 18135 TypedData& digits_ = TypedData::Handle(zone, digits());
18083 digits_ ^= digits_.CheckAndCanonicalize(NULL); 18136 digits_ ^= digits_.CheckAndCanonicalize(NULL);
18084 ASSERT(!digits_.IsNull()); 18137 ASSERT(!digits_.IsNull());
18085 set_digits(digits_); 18138 set_digits(digits_);
18086 } else { 18139 } else {
18087 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); 18140 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current()));
18088 } 18141 }
18089 return true; 18142 return true;
18090 } 18143 }
18091 18144
18092 18145
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
18230 18283
18231 RawBigint* Bigint::NewCanonical(const String& str) { 18284 RawBigint* Bigint::NewCanonical(const String& str) {
18232 Thread* thread = Thread::Current(); 18285 Thread* thread = Thread::Current();
18233 Zone* zone = thread->zone(); 18286 Zone* zone = thread->zone();
18234 Isolate* isolate = thread->isolate(); 18287 Isolate* isolate = thread->isolate();
18235 const Bigint& value = Bigint::Handle( 18288 const Bigint& value = Bigint::Handle(
18236 zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld)); 18289 zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld));
18237 const Class& cls = 18290 const Class& cls =
18238 Class::Handle(zone, isolate->object_store()->bigint_class()); 18291 Class::Handle(zone, isolate->object_store()->bigint_class());
18239 intptr_t index = 0; 18292 intptr_t index = 0;
18240 const Bigint& canonical_value = 18293 Bigint& canonical_value = Bigint::Handle(zone);
18241 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index)); 18294 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index);
18242 if (!canonical_value.IsNull()) { 18295 if (!canonical_value.IsNull()) {
18243 return canonical_value.raw(); 18296 return canonical_value.raw();
18244 } 18297 }
18245 { 18298 {
18246 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); 18299 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
18247 // Retry lookup. 18300 // Retry lookup.
18248 { 18301 {
18249 const Bigint& result = 18302 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index);
18250 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index)); 18303 if (!canonical_value.IsNull()) {
18251 if (!result.IsNull()) { 18304 return canonical_value.raw();
18252 return result.raw();
18253 } 18305 }
18254 } 18306 }
18255 value.SetCanonical(); 18307 value.SetCanonical();
18256 // The value needs to be added to the constants list. Grow the list if 18308 // The value needs to be added to the constants list. Grow the list if
18257 // it is full. 18309 // it is full.
18258 cls.InsertCanonicalConstant(index, value); 18310 cls.InsertCanonicalNumber(zone, index, value);
18259 return value.raw(); 18311 return value.raw();
18260 } 18312 }
18261 } 18313 }
18262 18314
18263 18315
18264 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, 18316 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used,
18265 Heap::Space space) { 18317 Heap::Space space) {
18266 const int kBitsPerHexDigit = 4; 18318 const int kBitsPerHexDigit = 4;
18267 const int kHexDigitsPerDigit = 8; 18319 const int kHexDigitsPerDigit = 8;
18268 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; 18320 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
(...skipping 2218 matching lines...) Expand 10 before | Expand all | Expand 10 after
20487 if (this->raw() == other.raw()) { 20539 if (this->raw() == other.raw()) {
20488 // Both handles point to the same raw instance. 20540 // Both handles point to the same raw instance.
20489 return true; 20541 return true;
20490 } 20542 }
20491 20543
20492 // An Array may be compared to an ImmutableArray. 20544 // An Array may be compared to an ImmutableArray.
20493 if (!other.IsArray() || other.IsNull()) { 20545 if (!other.IsArray() || other.IsNull()) {
20494 return false; 20546 return false;
20495 } 20547 }
20496 20548
20497 // Both arrays must have the same type arguments. 20549 // First check if both arrays have the same length and elements.
20498 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
20499 const TypeArguments& other_type_args = TypeArguments::Handle(
20500 other.GetTypeArguments());
20501 if (!type_args.Equals(other_type_args)) {
20502 return false;
20503 }
20504
20505 const Array& other_arr = Array::Cast(other); 20550 const Array& other_arr = Array::Cast(other);
20506 20551
20507 intptr_t len = this->Length(); 20552 intptr_t len = this->Length();
20508 if (len != other_arr.Length()) { 20553 if (len != other_arr.Length()) {
20509 return false; 20554 return false;
20510 } 20555 }
20511 20556
20512 for (intptr_t i = 0; i < len; i++) { 20557 for (intptr_t i = 0; i < len; i++) {
20513 if (this->At(i) != other_arr.At(i)) { 20558 if (this->At(i) != other_arr.At(i)) {
20514 return false; 20559 return false;
20515 } 20560 }
20516 } 20561 }
20562
20563 // Now check if both arrays have the same type arguments.
20564 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
20565 const TypeArguments& other_type_args = TypeArguments::Handle(
20566 other.GetTypeArguments());
20567 if (!type_args.Equals(other_type_args)) {
20568 return false;
20569 }
20517 return true; 20570 return true;
20518 } 20571 }
20519 20572
20520 20573
20521 RawArray* Array::New(intptr_t len, Heap::Space space) { 20574 RawArray* Array::New(intptr_t len, Heap::Space space) {
20522 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); 20575 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
20523 return New(kClassId, len, space); 20576 return New(kClassId, len, space);
20524 } 20577 }
20525 20578
20526 20579
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
20652 array.SetLength(used_len); 20705 array.SetLength(used_len);
20653 20706
20654 // Null the GrowableObjectArray, we are removing its backing array. 20707 // Null the GrowableObjectArray, we are removing its backing array.
20655 growable_array.SetLength(0); 20708 growable_array.SetLength(0);
20656 growable_array.SetData(Object::empty_array()); 20709 growable_array.SetData(Object::empty_array());
20657 20710
20658 return array.raw(); 20711 return array.raw();
20659 } 20712 }
20660 20713
20661 20714
20662 bool Array::CheckAndCanonicalizeFields(const char** error_str) const { 20715 bool Array::CheckAndCanonicalizeFields(Zone* zone,
20663 Object& obj = Object::Handle(); 20716 const char** error_str) const {
20717 Object& obj = Object::Handle(zone);
20664 // Iterate over all elements, canonicalize numbers and strings, expect all 20718 // Iterate over all elements, canonicalize numbers and strings, expect all
20665 // other instances to be canonical otherwise report error (return false). 20719 // other instances to be canonical otherwise report error (return false).
20666 for (intptr_t i = 0; i < Length(); i++) { 20720 for (intptr_t i = 0; i < Length(); i++) {
20667 obj = At(i); 20721 obj = At(i);
20668 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { 20722 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
20669 if (obj.IsNumber() || obj.IsString()) { 20723 if (obj.IsNumber() || obj.IsString()) {
20670 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); 20724 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL);
20671 ASSERT(!obj.IsNull()); 20725 ASSERT(!obj.IsNull());
20672 this->SetAt(i, obj); 20726 this->SetAt(i, obj);
20673 } else { 20727 } else {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
20723 ASSERT(Length() > 0); 20777 ASSERT(Length() > 0);
20724 intptr_t index = Length() - 1; 20778 intptr_t index = Length() - 1;
20725 const Array& contents = Array::Handle(data()); 20779 const Array& contents = Array::Handle(data());
20726 const PassiveObject& obj = PassiveObject::Handle(contents.At(index)); 20780 const PassiveObject& obj = PassiveObject::Handle(contents.At(index));
20727 contents.SetAt(index, Object::null_object()); 20781 contents.SetAt(index, Object::null_object());
20728 SetLength(index); 20782 SetLength(index);
20729 return obj.raw(); 20783 return obj.raw();
20730 } 20784 }
20731 20785
20732 20786
20733 bool GrowableObjectArray::CanonicalizeEquals(const Instance& other) const {
20734 // If both handles point to the same raw instance they are equal.
20735 if (this->raw() == other.raw()) {
20736 return true;
20737 }
20738
20739 // Other instance must be non null and a GrowableObjectArray.
20740 if (!other.IsGrowableObjectArray() || other.IsNull()) {
20741 return false;
20742 }
20743
20744 const GrowableObjectArray& other_arr = GrowableObjectArray::Cast(other);
20745
20746 // The capacity and length of both objects must be equal.
20747 if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) {
20748 return false;
20749 }
20750
20751 // Both arrays must have the same type arguments.
20752 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
20753 const TypeArguments& other_type_args = TypeArguments::Handle(
20754 other.GetTypeArguments());
20755 if (!type_args.Equals(other_type_args)) {
20756 return false;
20757 }
20758
20759 // The data part in both arrays must be identical.
20760 const Array& contents = Array::Handle(data());
20761 const Array& other_contents = Array::Handle(other_arr.data());
20762 for (intptr_t i = 0; i < Length(); i++) {
20763 if (contents.At(i) != other_contents.At(i)) {
20764 return false;
20765 }
20766 }
20767 return true;
20768 }
20769
20770
20771 RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity, 20787 RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity,
20772 Heap::Space space) { 20788 Heap::Space space) {
20773 const Array& data = Array::Handle(Array::New(capacity, space)); 20789 const Array& data = Array::Handle(Array::New(capacity, space));
20774 return New(data, space); 20790 return New(data, space);
20775 } 20791 }
20776 20792
20777 20793
20778 RawGrowableObjectArray* GrowableObjectArray::New(const Array& array, 20794 RawGrowableObjectArray* GrowableObjectArray::New(const Array& array,
20779 Heap::Space space) { 20795 Heap::Space space) {
20780 ASSERT(Isolate::Current()->object_store()->growable_object_array_class() 20796 ASSERT(Isolate::Current()->object_store()->growable_object_array_class()
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after
21881 return UserTag::null(); 21897 return UserTag::null();
21882 } 21898 }
21883 21899
21884 21900
21885 const char* UserTag::ToCString() const { 21901 const char* UserTag::ToCString() const {
21886 const String& tag_label = String::Handle(label()); 21902 const String& tag_label = String::Handle(label());
21887 return tag_label.ToCString(); 21903 return tag_label.ToCString();
21888 } 21904 }
21889 21905
21890 } // namespace dart 21906 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698