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 10216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14628 } | 14643 } |
14629 | 14644 |
14630 private: | 14645 private: |
14631 bool has_pointers_; | 14646 bool has_pointers_; |
14632 | 14647 |
14633 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); | 14648 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); |
14634 }; | 14649 }; |
14635 #endif // DEBUG | 14650 #endif // DEBUG |
14636 | 14651 |
14637 | 14652 |
14638 bool Instance::CheckAndCanonicalizeFields(const char** error_str) const { | 14653 bool Instance::CheckAndCanonicalizeFields(Zone* zone, |
14639 const Class& cls = Class::Handle(this->clazz()); | 14654 const char** error_str) const { |
14655 const Class& cls = Class::Handle(zone, this->clazz()); | |
14640 if (cls.id() >= kNumPredefinedCids) { | 14656 if (cls.id() >= kNumPredefinedCids) { |
14641 // Iterate over all fields, canonicalize numbers and strings, expect all | 14657 // Iterate over all fields, canonicalize numbers and strings, expect all |
14642 // other instances to be canonical otherwise report error (return false). | 14658 // other instances to be canonical otherwise report error (return false). |
14643 Object& obj = Object::Handle(); | 14659 Object& obj = Object::Handle(zone); |
14644 intptr_t end_field_offset = cls.instance_size() - kWordSize; | 14660 intptr_t end_field_offset = cls.instance_size() - kWordSize; |
14645 for (intptr_t field_offset = 0; | 14661 for (intptr_t field_offset = 0; |
14646 field_offset <= end_field_offset; | 14662 field_offset <= end_field_offset; |
14647 field_offset += kWordSize) { | 14663 field_offset += kWordSize) { |
14648 obj = *this->FieldAddrAtOffset(field_offset); | 14664 obj = *this->FieldAddrAtOffset(field_offset); |
14649 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 14665 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
14650 if (obj.IsNumber() || obj.IsString()) { | 14666 if (obj.IsNumber() || obj.IsString()) { |
14651 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 14667 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); |
14652 ASSERT(!obj.IsNull()); | 14668 ASSERT(!obj.IsNull()); |
14653 this->SetFieldAtOffset(field_offset, obj); | 14669 this->SetFieldAtOffset(field_offset, obj); |
14654 } else { | 14670 } else { |
14655 ASSERT(error_str != NULL); | 14671 ASSERT(error_str != NULL); |
14656 char* chars = OS::SCreate(Thread::Current()->zone(), | 14672 char* chars = OS::SCreate(Thread::Current()->zone(), |
srdjan
2016/04/06 22:32:44
zone
siva
2016/04/06 22:35:33
Done.
| |
14657 "field: %s\n", obj.ToCString()); | 14673 "field: %s\n", obj.ToCString()); |
14658 *error_str = chars; | 14674 *error_str = chars; |
14659 return false; | 14675 return false; |
14660 } | 14676 } |
14661 } | 14677 } |
14662 } | 14678 } |
14663 } else { | 14679 } else { |
14664 #if defined(DEBUG) | 14680 #if defined(DEBUG) |
14665 // Make sure that we are not missing any fields. | 14681 // Make sure that we are not missing any fields. |
14666 CheckForPointers has_pointers(Isolate::Current()); | 14682 CheckForPointers has_pointers(Isolate::Current()); |
14667 this->raw()->VisitPointers(&has_pointers); | 14683 this->raw()->VisitPointers(&has_pointers); |
14668 ASSERT(!has_pointers.has_pointers()); | 14684 ASSERT(!has_pointers.has_pointers()); |
14669 #endif // DEBUG | 14685 #endif // DEBUG |
14670 } | 14686 } |
14671 return true; | 14687 return true; |
14672 } | 14688 } |
14673 | 14689 |
14674 | 14690 |
14675 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { | 14691 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { |
14676 ASSERT(!IsNull()); | 14692 ASSERT(!IsNull()); |
14677 if (this->IsCanonical()) { | 14693 if (this->IsCanonical()) { |
14678 return this->raw(); | 14694 return this->raw(); |
14679 } | 14695 } |
14680 if (!CheckAndCanonicalizeFields(error_str)) { | 14696 Thread* thread = Thread::Current(); |
14697 Zone* zone = thread->zone(); | |
14698 if (!CheckAndCanonicalizeFields(zone, error_str)) { | |
14681 return Instance::null(); | 14699 return Instance::null(); |
14682 } | 14700 } |
14683 Thread* thread = Thread::Current(); | |
14684 Zone* zone = thread->zone(); | |
14685 Isolate* isolate = thread->isolate(); | 14701 Isolate* isolate = thread->isolate(); |
14686 Instance& result = Instance::Handle(zone); | 14702 Instance& result = Instance::Handle(zone); |
14687 const Class& cls = Class::Handle(zone, this->clazz()); | 14703 const Class& cls = Class::Handle(zone, this->clazz()); |
14688 intptr_t index = 0; | 14704 intptr_t index = 0; |
14689 result ^= cls.LookupCanonicalInstance(zone, *this, &index); | 14705 result ^= cls.LookupCanonicalInstance(zone, *this, &index); |
14690 if (!result.IsNull()) { | 14706 if (!result.IsNull()) { |
14691 return result.raw(); | 14707 return result.raw(); |
14692 } | 14708 } |
14693 { | 14709 { |
14694 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 14710 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
14695 // Retry lookup. | 14711 // Retry lookup. |
14696 { | 14712 { |
14697 Instance& temp_result = Instance::Handle(zone, | 14713 result ^= cls.LookupCanonicalInstance(zone, *this, &index); |
14698 cls.LookupCanonicalInstance(zone, *this, &index)); | 14714 if (!result.IsNull()) { |
14699 if (!temp_result.IsNull()) { | 14715 return result.raw(); |
14700 return temp_result.raw(); | |
14701 } | 14716 } |
14702 } | 14717 } |
14703 | 14718 |
14704 // The value needs to be added to the list. Grow the list if | 14719 // The value needs to be added to the list. Grow the list if |
14705 // it is full. | 14720 // it is full. |
14706 result ^= this->raw(); | 14721 result ^= this->raw(); |
14707 if (result.IsNew() || | 14722 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap()); |
14708 (result.InVMHeap() && (isolate != Dart::vm_isolate()))) { | 14723 if (result.IsNew()) { |
14709 /** | |
14710 * When a snapshot is generated on a 64 bit architecture and then read | |
14711 * into a 32 bit architecture, values which are Smi on the 64 bit | |
14712 * architecture could potentially be converted to Mint objects, however | |
14713 * since Smi values do not have any notion of canonical bits we lose | |
14714 * that information when the object becomes a Mint. | |
14715 * Some of these values could be literal values and end up in the | |
14716 * VM isolate heap. Later when these values are referenced in a | |
14717 * constant list we try to ensure that all the objects in the list | |
14718 * are canonical and try to canonicalize them. When these Mint objects | |
14719 * are encountered they do not have the canonical bit set and | |
14720 * canonicalizing them won't work as the VM heap is read only now. | |
14721 * In these cases we clone the object into the isolate and then | |
14722 * canonicalize it. | |
14723 */ | |
14724 // Create a canonical object in old space. | 14724 // Create a canonical object in old space. |
14725 result ^= Object::Clone(result, Heap::kOld); | 14725 result ^= Object::Clone(result, Heap::kOld); |
14726 } | 14726 } |
14727 ASSERT(result.IsOld()); | 14727 ASSERT(result.IsOld()); |
14728 | |
14729 result.SetCanonical(); | 14728 result.SetCanonical(); |
14730 cls.InsertCanonicalConstant(index, result); | 14729 cls.InsertCanonicalConstant(index, result); |
14731 return result.raw(); | 14730 return result.raw(); |
14732 } | 14731 } |
14733 } | 14732 } |
14734 | 14733 |
14735 | 14734 |
14736 RawAbstractType* Instance::GetType() const { | 14735 RawAbstractType* Instance::GetType() const { |
14737 if (IsNull()) { | 14736 if (IsNull()) { |
14738 return Type::NullType(); | 14737 return Type::NullType(); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14930 return DartLibraryCalls::Equals(*this, other) == Object::bool_true().raw(); | 14929 return DartLibraryCalls::Equals(*this, other) == Object::bool_true().raw(); |
14931 } | 14930 } |
14932 | 14931 |
14933 | 14932 |
14934 bool Instance::IsIdenticalTo(const Instance& other) const { | 14933 bool Instance::IsIdenticalTo(const Instance& other) const { |
14935 if (raw() == other.raw()) return true; | 14934 if (raw() == other.raw()) return true; |
14936 if (IsInteger() && other.IsInteger()) { | 14935 if (IsInteger() && other.IsInteger()) { |
14937 return Integer::Cast(*this).Equals(other); | 14936 return Integer::Cast(*this).Equals(other); |
14938 } | 14937 } |
14939 if (IsDouble() && other.IsDouble()) { | 14938 if (IsDouble() && other.IsDouble()) { |
14940 return Double::Cast(*this).CanonicalizeEquals(other); | 14939 double other_value = Double::Cast(other).value(); |
14940 return Double::Cast(*this).BitwiseEqualsToDouble(other_value); | |
14941 } | 14941 } |
14942 return false; | 14942 return false; |
14943 } | 14943 } |
14944 | 14944 |
14945 | 14945 |
14946 intptr_t* Instance::NativeFieldsDataAddr() const { | 14946 intptr_t* Instance::NativeFieldsDataAddr() const { |
14947 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); | 14947 ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); |
14948 RawTypedData* native_fields = | 14948 RawTypedData* native_fields = |
14949 reinterpret_cast<RawTypedData*>(*NativeFieldsAddr()); | 14949 reinterpret_cast<RawTypedData*>(*NativeFieldsAddr()); |
14950 if (native_fields == TypedData::null()) { | 14950 if (native_fields == TypedData::null()) { |
(...skipping 2383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17334 | 17334 |
17335 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, | 17335 RawMixinAppType* MixinAppType::New(const AbstractType& super_type, |
17336 const Array& mixin_types) { | 17336 const Array& mixin_types) { |
17337 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); | 17337 const MixinAppType& result = MixinAppType::Handle(MixinAppType::New()); |
17338 result.set_super_type(super_type); | 17338 result.set_super_type(super_type); |
17339 result.set_mixin_types(mixin_types); | 17339 result.set_mixin_types(mixin_types); |
17340 return result.raw(); | 17340 return result.raw(); |
17341 } | 17341 } |
17342 | 17342 |
17343 | 17343 |
17344 RawInstance* Number::CheckAndCanonicalize(const char** error_str) const { | |
17345 intptr_t cid = GetClassId(); | |
17346 switch (cid) { | |
17347 case kSmiCid: | |
17348 return reinterpret_cast<RawSmi*>(raw_value()); | |
17349 case kMintCid: | |
17350 return Mint::NewCanonical(Mint::Cast(*this).value()); | |
17351 case kDoubleCid: | |
17352 return Double::NewCanonical(Double::Cast(*this).value()); | |
17353 case kBigintCid: { | |
regis
2016/04/06 22:02:39
Why are you not calling the existing Bigint::NewCa
siva
2016/04/06 22:26:36
Bigint::NewCanonical requires a String object whic
regis
2016/04/06 22:42:44
I missed the fact that the argument is a String.
| |
17354 Thread* thread = Thread::Current(); | |
17355 Zone* zone = thread->zone(); | |
17356 Isolate* isolate = thread->isolate(); | |
17357 if (!CheckAndCanonicalizeFields(zone, error_str)) { | |
17358 return Instance::null(); | |
17359 } | |
17360 Bigint& result = Bigint::Handle(zone); | |
17361 const Class& cls = Class::Handle(zone, this->clazz()); | |
17362 intptr_t index = 0; | |
17363 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); | |
17364 if (!result.IsNull()) { | |
17365 return result.raw(); | |
17366 } | |
17367 { | |
17368 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | |
17369 // Retry lookup. | |
17370 { | |
17371 result ^= cls.LookupCanonicalBigint( | |
17372 zone, Bigint::Cast(*this), &index); | |
17373 if (!result.IsNull()) { | |
17374 return result.raw(); | |
17375 } | |
17376 } | |
17377 | |
17378 // The value needs to be added to the list. Grow the list if | |
17379 // it is full. | |
17380 result ^= this->raw(); | |
17381 ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap()); | |
17382 if (result.IsNew()) { | |
17383 // Create a canonical object in old space. | |
17384 result ^= Object::Clone(result, Heap::kOld); | |
17385 } | |
17386 ASSERT(result.IsOld()); | |
17387 result.SetCanonical(); | |
17388 cls.InsertCanonicalNumber(zone, index, result); | |
17389 return result.raw(); | |
17390 } | |
17391 } | |
17392 default: | |
17393 UNREACHABLE(); | |
17394 } | |
17395 return Instance::null(); | |
17396 } | |
17397 | |
17398 | |
17344 const char* Number::ToCString() const { | 17399 const char* Number::ToCString() const { |
17345 // Number is an interface. No instances of Number should exist. | 17400 // Number is an interface. No instances of Number should exist. |
17346 UNREACHABLE(); | 17401 UNREACHABLE(); |
17347 return "Number"; | 17402 return "Number"; |
17348 } | 17403 } |
17349 | 17404 |
17350 | 17405 |
17351 const char* Integer::ToCString() const { | 17406 const char* Integer::ToCString() const { |
17352 // Integer is an interface. No instances of Integer should exist except null. | 17407 // Integer is an interface. No instances of Integer should exist except null. |
17353 ASSERT(IsNull()); | 17408 ASSERT(IsNull()); |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17757 Mint& canonical_value = Mint::Handle(zone); | 17812 Mint& canonical_value = Mint::Handle(zone); |
17758 intptr_t index = 0; | 17813 intptr_t index = 0; |
17759 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index); | 17814 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index); |
17760 if (!canonical_value.IsNull()) { | 17815 if (!canonical_value.IsNull()) { |
17761 return canonical_value.raw(); | 17816 return canonical_value.raw(); |
17762 } | 17817 } |
17763 { | 17818 { |
17764 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 17819 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
17765 // Retry lookup. | 17820 // Retry lookup. |
17766 { | 17821 { |
17767 const Mint& result = | 17822 canonical_value ^= cls.LookupCanonicalMint(zone, value, &index); |
17768 Mint::Handle(zone, cls.LookupCanonicalMint(zone, value, &index)); | 17823 if (!canonical_value.IsNull()) { |
17769 if (!result.IsNull()) { | 17824 return canonical_value.raw(); |
17770 return result.raw(); | |
17771 } | 17825 } |
17772 } | 17826 } |
17773 canonical_value = Mint::New(value, Heap::kOld); | 17827 canonical_value = Mint::New(value, Heap::kOld); |
17774 canonical_value.SetCanonical(); | 17828 canonical_value.SetCanonical(); |
17775 // The value needs to be added to the constants list. Grow the list if | 17829 // The value needs to be added to the constants list. Grow the list if |
17776 // it is full. | 17830 // it is full. |
17777 cls.InsertCanonicalConstant(index, canonical_value); | 17831 cls.InsertCanonicalNumber(zone, index, canonical_value); |
17778 return canonical_value.raw(); | 17832 return canonical_value.raw(); |
17779 } | 17833 } |
17780 } | 17834 } |
17781 | 17835 |
17782 | 17836 |
17783 bool Mint::Equals(const Instance& other) const { | 17837 bool Mint::Equals(const Instance& other) const { |
17784 if (this->raw() == other.raw()) { | 17838 if (this->raw() == other.raw()) { |
17785 // Both handles point to the same raw instance. | 17839 // Both handles point to the same raw instance. |
17786 return true; | 17840 return true; |
17787 } | 17841 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17910 intptr_t index = 0; | 17964 intptr_t index = 0; |
17911 | 17965 |
17912 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index); | 17966 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index); |
17913 if (!canonical_value.IsNull()) { | 17967 if (!canonical_value.IsNull()) { |
17914 return canonical_value.raw(); | 17968 return canonical_value.raw(); |
17915 } | 17969 } |
17916 { | 17970 { |
17917 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 17971 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
17918 // Retry lookup. | 17972 // Retry lookup. |
17919 { | 17973 { |
17920 const Double& result = | 17974 canonical_value ^= cls.LookupCanonicalDouble(zone, value, &index); |
17921 Double::Handle(zone, cls.LookupCanonicalDouble(zone, value, &index)); | 17975 if (!canonical_value.IsNull()) { |
17922 if (!result.IsNull()) { | 17976 return canonical_value.raw(); |
17923 return result.raw(); | |
17924 } | 17977 } |
17925 } | 17978 } |
17926 canonical_value = Double::New(value, Heap::kOld); | 17979 canonical_value = Double::New(value, Heap::kOld); |
17927 canonical_value.SetCanonical(); | 17980 canonical_value.SetCanonical(); |
17928 // The value needs to be added to the constants list. Grow the list if | 17981 // The value needs to be added to the constants list. Grow the list if |
17929 // it is full. | 17982 // it is full. |
17930 cls.InsertCanonicalConstant(index, canonical_value); | 17983 cls.InsertCanonicalNumber(zone, index, canonical_value); |
17931 return canonical_value.raw(); | 17984 return canonical_value.raw(); |
17932 } | 17985 } |
17933 } | 17986 } |
17934 | 17987 |
17935 | 17988 |
17936 RawDouble* Double::NewCanonical(const String& str) { | 17989 RawDouble* Double::NewCanonical(const String& str) { |
17937 double double_value; | 17990 double double_value; |
17938 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { | 17991 if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) { |
17939 return Double::Handle().raw(); | 17992 return Double::Handle().raw(); |
17940 } | 17993 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18047 | 18100 |
18048 for (intptr_t i = 0; i < used; i++) { | 18101 for (intptr_t i = 0; i < used; i++) { |
18049 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { | 18102 if (this->DigitAt(i) != other_bgi.DigitAt(i)) { |
18050 return false; | 18103 return false; |
18051 } | 18104 } |
18052 } | 18105 } |
18053 return true; | 18106 return true; |
18054 } | 18107 } |
18055 | 18108 |
18056 | 18109 |
18057 bool Bigint::CheckAndCanonicalizeFields(const char** error_str) const { | 18110 bool Bigint::CheckAndCanonicalizeFields(Zone* zone, |
18111 const char** error_str) const { | |
18058 // Bool field neg should always be canonical. | 18112 // Bool field neg should always be canonical. |
18059 ASSERT(Bool::Handle(neg()).IsCanonical()); | 18113 ASSERT(Bool::Handle(zone, neg()).IsCanonical()); |
18060 // Smi field used is canonical by definition. | 18114 // Smi field used is canonical by definition. |
18061 if (Used() > 0) { | 18115 if (Used() > 0) { |
18062 // Canonicalize TypedData field digits. | 18116 // Canonicalize TypedData field digits. |
18063 TypedData& digits_ = TypedData::Handle(digits()); | 18117 TypedData& digits_ = TypedData::Handle(zone, digits()); |
18064 digits_ ^= digits_.CheckAndCanonicalize(NULL); | 18118 digits_ ^= digits_.CheckAndCanonicalize(NULL); |
18065 ASSERT(!digits_.IsNull()); | 18119 ASSERT(!digits_.IsNull()); |
18066 set_digits(digits_); | 18120 set_digits(digits_); |
18067 } else { | 18121 } else { |
18068 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); | 18122 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); |
18069 } | 18123 } |
18070 return true; | 18124 return true; |
18071 } | 18125 } |
18072 | 18126 |
18073 | 18127 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18211 | 18265 |
18212 RawBigint* Bigint::NewCanonical(const String& str) { | 18266 RawBigint* Bigint::NewCanonical(const String& str) { |
18213 Thread* thread = Thread::Current(); | 18267 Thread* thread = Thread::Current(); |
18214 Zone* zone = thread->zone(); | 18268 Zone* zone = thread->zone(); |
18215 Isolate* isolate = thread->isolate(); | 18269 Isolate* isolate = thread->isolate(); |
18216 const Bigint& value = Bigint::Handle( | 18270 const Bigint& value = Bigint::Handle( |
18217 zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld)); | 18271 zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld)); |
18218 const Class& cls = | 18272 const Class& cls = |
18219 Class::Handle(zone, isolate->object_store()->bigint_class()); | 18273 Class::Handle(zone, isolate->object_store()->bigint_class()); |
18220 intptr_t index = 0; | 18274 intptr_t index = 0; |
18221 const Bigint& canonical_value = | 18275 Bigint& canonical_value = Bigint::Handle(zone); |
18222 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index)); | 18276 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index); |
18223 if (!canonical_value.IsNull()) { | 18277 if (!canonical_value.IsNull()) { |
18224 return canonical_value.raw(); | 18278 return canonical_value.raw(); |
18225 } | 18279 } |
18226 { | 18280 { |
18227 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); | 18281 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); |
18228 // Retry lookup. | 18282 // Retry lookup. |
18229 { | 18283 { |
18230 const Bigint& result = | 18284 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index); |
18231 Bigint::Handle(zone, cls.LookupCanonicalBigint(zone, value, &index)); | 18285 if (!canonical_value.IsNull()) { |
18232 if (!result.IsNull()) { | 18286 return canonical_value.raw(); |
18233 return result.raw(); | |
18234 } | 18287 } |
18235 } | 18288 } |
18236 value.SetCanonical(); | 18289 value.SetCanonical(); |
18237 // The value needs to be added to the constants list. Grow the list if | 18290 // The value needs to be added to the constants list. Grow the list if |
18238 // it is full. | 18291 // it is full. |
18239 cls.InsertCanonicalConstant(index, value); | 18292 cls.InsertCanonicalNumber(zone, index, value); |
18240 return value.raw(); | 18293 return value.raw(); |
18241 } | 18294 } |
18242 } | 18295 } |
18243 | 18296 |
18244 | 18297 |
18245 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, | 18298 RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used, |
18246 Heap::Space space) { | 18299 Heap::Space space) { |
18247 const int kBitsPerHexDigit = 4; | 18300 const int kBitsPerHexDigit = 4; |
18248 const int kHexDigitsPerDigit = 8; | 18301 const int kHexDigitsPerDigit = 8; |
18249 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; | 18302 const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit; |
(...skipping 2218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20468 if (this->raw() == other.raw()) { | 20521 if (this->raw() == other.raw()) { |
20469 // Both handles point to the same raw instance. | 20522 // Both handles point to the same raw instance. |
20470 return true; | 20523 return true; |
20471 } | 20524 } |
20472 | 20525 |
20473 // An Array may be compared to an ImmutableArray. | 20526 // An Array may be compared to an ImmutableArray. |
20474 if (!other.IsArray() || other.IsNull()) { | 20527 if (!other.IsArray() || other.IsNull()) { |
20475 return false; | 20528 return false; |
20476 } | 20529 } |
20477 | 20530 |
20478 // Both arrays must have the same type arguments. | 20531 // First check if both arrays have the same length and elements. |
20479 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | |
20480 const TypeArguments& other_type_args = TypeArguments::Handle( | |
20481 other.GetTypeArguments()); | |
20482 if (!type_args.Equals(other_type_args)) { | |
20483 return false; | |
20484 } | |
20485 | |
20486 const Array& other_arr = Array::Cast(other); | 20532 const Array& other_arr = Array::Cast(other); |
20487 | 20533 |
20488 intptr_t len = this->Length(); | 20534 intptr_t len = this->Length(); |
20489 if (len != other_arr.Length()) { | 20535 if (len != other_arr.Length()) { |
20490 return false; | 20536 return false; |
20491 } | 20537 } |
20492 | 20538 |
20493 for (intptr_t i = 0; i < len; i++) { | 20539 for (intptr_t i = 0; i < len; i++) { |
regis
2016/04/06 22:02:39
Depending on len, this loop could be much more exp
siva
2016/04/06 22:26:36
How many times do you think we will have a case wh
regis
2016/04/06 22:42:44
True, checking the (identical) type first would no
| |
20494 if (this->At(i) != other_arr.At(i)) { | 20540 if (this->At(i) != other_arr.At(i)) { |
20495 return false; | 20541 return false; |
20496 } | 20542 } |
20497 } | 20543 } |
20544 | |
20545 // Now check if both arrays have the same type arguments. | |
20546 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | |
20547 const TypeArguments& other_type_args = TypeArguments::Handle( | |
20548 other.GetTypeArguments()); | |
20549 if (!type_args.Equals(other_type_args)) { | |
20550 return false; | |
20551 } | |
20498 return true; | 20552 return true; |
20499 } | 20553 } |
20500 | 20554 |
20501 | 20555 |
20502 RawArray* Array::New(intptr_t len, Heap::Space space) { | 20556 RawArray* Array::New(intptr_t len, Heap::Space space) { |
20503 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); | 20557 ASSERT(Isolate::Current()->object_store()->array_class() != Class::null()); |
20504 return New(kClassId, len, space); | 20558 return New(kClassId, len, space); |
20505 } | 20559 } |
20506 | 20560 |
20507 | 20561 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20633 array.SetLength(used_len); | 20687 array.SetLength(used_len); |
20634 | 20688 |
20635 // Null the GrowableObjectArray, we are removing its backing array. | 20689 // Null the GrowableObjectArray, we are removing its backing array. |
20636 growable_array.SetLength(0); | 20690 growable_array.SetLength(0); |
20637 growable_array.SetData(Object::empty_array()); | 20691 growable_array.SetData(Object::empty_array()); |
20638 | 20692 |
20639 return array.raw(); | 20693 return array.raw(); |
20640 } | 20694 } |
20641 | 20695 |
20642 | 20696 |
20643 bool Array::CheckAndCanonicalizeFields(const char** error_str) const { | 20697 bool Array::CheckAndCanonicalizeFields(Zone* zone, |
20644 Object& obj = Object::Handle(); | 20698 const char** error_str) const { |
20699 Object& obj = Object::Handle(zone); | |
20645 // Iterate over all elements, canonicalize numbers and strings, expect all | 20700 // Iterate over all elements, canonicalize numbers and strings, expect all |
20646 // other instances to be canonical otherwise report error (return false). | 20701 // other instances to be canonical otherwise report error (return false). |
20647 for (intptr_t i = 0; i < Length(); i++) { | 20702 for (intptr_t i = 0; i < Length(); i++) { |
20648 obj = At(i); | 20703 obj = At(i); |
20649 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 20704 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
20650 if (obj.IsNumber() || obj.IsString()) { | 20705 if (obj.IsNumber() || obj.IsString()) { |
20651 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 20706 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); |
20652 ASSERT(!obj.IsNull()); | 20707 ASSERT(!obj.IsNull()); |
20653 this->SetAt(i, obj); | 20708 this->SetAt(i, obj); |
20654 } else { | 20709 } else { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
20704 ASSERT(Length() > 0); | 20759 ASSERT(Length() > 0); |
20705 intptr_t index = Length() - 1; | 20760 intptr_t index = Length() - 1; |
20706 const Array& contents = Array::Handle(data()); | 20761 const Array& contents = Array::Handle(data()); |
20707 const PassiveObject& obj = PassiveObject::Handle(contents.At(index)); | 20762 const PassiveObject& obj = PassiveObject::Handle(contents.At(index)); |
20708 contents.SetAt(index, Object::null_object()); | 20763 contents.SetAt(index, Object::null_object()); |
20709 SetLength(index); | 20764 SetLength(index); |
20710 return obj.raw(); | 20765 return obj.raw(); |
20711 } | 20766 } |
20712 | 20767 |
20713 | 20768 |
20714 bool GrowableObjectArray::CanonicalizeEquals(const Instance& other) const { | |
20715 // If both handles point to the same raw instance they are equal. | |
20716 if (this->raw() == other.raw()) { | |
20717 return true; | |
20718 } | |
20719 | |
20720 // Other instance must be non null and a GrowableObjectArray. | |
20721 if (!other.IsGrowableObjectArray() || other.IsNull()) { | |
20722 return false; | |
20723 } | |
20724 | |
20725 const GrowableObjectArray& other_arr = GrowableObjectArray::Cast(other); | |
20726 | |
20727 // The capacity and length of both objects must be equal. | |
20728 if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) { | |
20729 return false; | |
20730 } | |
20731 | |
20732 // Both arrays must have the same type arguments. | |
20733 const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments()); | |
20734 const TypeArguments& other_type_args = TypeArguments::Handle( | |
20735 other.GetTypeArguments()); | |
20736 if (!type_args.Equals(other_type_args)) { | |
20737 return false; | |
20738 } | |
20739 | |
20740 // The data part in both arrays must be identical. | |
20741 const Array& contents = Array::Handle(data()); | |
20742 const Array& other_contents = Array::Handle(other_arr.data()); | |
20743 for (intptr_t i = 0; i < Length(); i++) { | |
20744 if (contents.At(i) != other_contents.At(i)) { | |
20745 return false; | |
20746 } | |
20747 } | |
20748 return true; | |
20749 } | |
20750 | |
20751 | |
20752 RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity, | 20769 RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity, |
20753 Heap::Space space) { | 20770 Heap::Space space) { |
20754 const Array& data = Array::Handle(Array::New(capacity, space)); | 20771 const Array& data = Array::Handle(Array::New(capacity, space)); |
20755 return New(data, space); | 20772 return New(data, space); |
20756 } | 20773 } |
20757 | 20774 |
20758 | 20775 |
20759 RawGrowableObjectArray* GrowableObjectArray::New(const Array& array, | 20776 RawGrowableObjectArray* GrowableObjectArray::New(const Array& array, |
20760 Heap::Space space) { | 20777 Heap::Space space) { |
20761 ASSERT(Isolate::Current()->object_store()->growable_object_array_class() | 20778 ASSERT(Isolate::Current()->object_store()->growable_object_array_class() |
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
21862 return UserTag::null(); | 21879 return UserTag::null(); |
21863 } | 21880 } |
21864 | 21881 |
21865 | 21882 |
21866 const char* UserTag::ToCString() const { | 21883 const char* UserTag::ToCString() const { |
21867 const String& tag_label = String::Handle(label()); | 21884 const String& tag_label = String::Handle(label()); |
21868 return tag_label.ToCString(); | 21885 return tag_label.ToCString(); |
21869 } | 21886 } |
21870 | 21887 |
21871 } // namespace dart | 21888 } // namespace dart |
OLD | NEW |