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

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

Issue 1866713003: - Restructure the Canonicalization of instances in preparation for adding a (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: self-review-comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 4381 matching lines...) Expand 10 before | Expand all | Expand 10 after
4392 const Array& new_canonical_list = 4392 const Array& new_canonical_list =
4393 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); 4393 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld));
4394 set_constants(new_canonical_list); 4394 set_constants(new_canonical_list);
4395 new_canonical_list.SetAt(index, constant); 4395 new_canonical_list.SetAt(index, constant);
4396 } else { 4396 } else {
4397 canonical_list.SetAt(index, constant); 4397 canonical_list.SetAt(index, constant);
4398 } 4398 }
4399 } 4399 }
4400 4400
4401 4401
4402 void Class::InsertCanonicalNumber(Zone* zone,
4403 intptr_t index,
4404 const Number& constant) const {
4405 // The constant needs to be added to the list. Grow the list if it is full.
4406 Array& canonical_list = Array::Handle(zone, constants());
4407 const intptr_t list_len = canonical_list.Length();
4408 if (index >= list_len) {
4409 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
4410 canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld);
4411 set_constants(canonical_list);
4412 }
4413 canonical_list.SetAt(index, constant);
4414 }
4415
4416
4402 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix, 4417 RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
4403 const String& ident, 4418 const String& ident,
4404 TokenPosition token_pos) { 4419 TokenPosition token_pos) {
4405 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); 4420 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New());
4406 type.set_library_prefix(library_prefix); 4421 type.set_library_prefix(library_prefix);
4407 type.set_ident(ident); 4422 type.set_ident(ident);
4408 type.set_token_pos(token_pos); 4423 type.set_token_pos(token_pos);
4409 return type.raw(); 4424 return type.raw();
4410 } 4425 }
4411 4426
(...skipping 10216 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698