| 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 |