OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 4381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |