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/become.h" | 10 #include "vm/become.h" |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 ASSERT(!speculative_inlining_error_->IsSmi()); | 985 ASSERT(!speculative_inlining_error_->IsSmi()); |
986 ASSERT(speculative_inlining_error_->IsLanguageError()); | 986 ASSERT(speculative_inlining_error_->IsLanguageError()); |
987 ASSERT(!background_compilation_error_->IsSmi()); | 987 ASSERT(!background_compilation_error_->IsSmi()); |
988 ASSERT(background_compilation_error_->IsLanguageError()); | 988 ASSERT(background_compilation_error_->IsLanguageError()); |
989 ASSERT(!vm_isolate_snapshot_object_table_->IsSmi()); | 989 ASSERT(!vm_isolate_snapshot_object_table_->IsSmi()); |
990 ASSERT(vm_isolate_snapshot_object_table_->IsArray()); | 990 ASSERT(vm_isolate_snapshot_object_table_->IsArray()); |
991 } | 991 } |
992 | 992 |
993 | 993 |
994 // An object visitor which will mark all visited objects. This is used to | 994 // An object visitor which will mark all visited objects. This is used to |
995 // premark all objects in the vm_isolate_ heap. | 995 // premark all objects in the vm_isolate_ heap. Also precalculates hash |
996 class PremarkingVisitor : public ObjectVisitor { | 996 // codes so that we can get the identity hash code of objects in the read- |
| 997 // only VM isolate. |
| 998 class FinalizeVMIsolateVisitor : public ObjectVisitor { |
997 public: | 999 public: |
998 PremarkingVisitor() {} | 1000 FinalizeVMIsolateVisitor() : counter_(1337) {} |
999 | 1001 |
1000 void VisitObject(RawObject* obj) { | 1002 void VisitObject(RawObject* obj) { |
1001 // Free list elements should never be marked. | 1003 // Free list elements should never be marked. |
1002 ASSERT(!obj->IsMarked()); | 1004 ASSERT(!obj->IsMarked()); |
1003 // No forwarding corpses in the VM isolate. | 1005 // No forwarding corpses in the VM isolate. |
1004 ASSERT(!obj->IsForwardingCorpse()); | 1006 ASSERT(!obj->IsForwardingCorpse()); |
1005 if (!obj->IsFreeListElement()) { | 1007 if (!obj->IsFreeListElement()) { |
1006 ASSERT(obj->IsVMHeapObject()); | 1008 ASSERT(obj->IsVMHeapObject()); |
1007 obj->SetMarkBitUnsynchronized(); | 1009 obj->SetMarkBitUnsynchronized(); |
| 1010 if (obj->IsStringInstance()) { |
| 1011 RawString* str = reinterpret_cast<RawString*>(obj); |
| 1012 intptr_t hash = String::Hash(str); |
| 1013 String::SetCachedHash(str, hash); |
| 1014 } |
| 1015 #if defined(HASH_IN_OBJECT_HEADER) |
| 1016 // These objects end up in the read-only VM isolate which is shared |
| 1017 // between isolates, so we have to prepopulate them with identity hash |
| 1018 // codes, since we can't add hash codes later. |
| 1019 if (Object::GetCachedHash(obj) == 0) { |
| 1020 // Some classes have identity hash codes that depend on their contents, |
| 1021 // not per object. |
| 1022 ASSERT(!obj->IsStringInstance()); |
| 1023 if (!obj->IsMint() && !obj->IsDouble() && !obj->IsBigint() && |
| 1024 !obj->IsRawNull() && !obj->IsBool()) { |
| 1025 counter_ += 2011; // The year Dart was announced and a prime. |
| 1026 counter_ &= 0x3fffffff; |
| 1027 if (counter_ == 0) counter_++; |
| 1028 Object::SetCachedHash(obj, counter_); |
| 1029 } |
| 1030 } |
| 1031 #endif |
1008 } | 1032 } |
1009 } | 1033 } |
| 1034 |
| 1035 private: |
| 1036 int counter_; |
1010 }; | 1037 }; |
1011 | 1038 |
1012 | 1039 |
1013 #define SET_CLASS_NAME(class_name, name) \ | 1040 #define SET_CLASS_NAME(class_name, name) \ |
1014 cls = class_name##_class(); \ | 1041 cls = class_name##_class(); \ |
1015 cls.set_name(Symbols::name()); | 1042 cls.set_name(Symbols::name()); |
1016 | 1043 |
1017 void Object::FinalizeVMIsolate(Isolate* isolate) { | 1044 void Object::FinalizeVMIsolate(Isolate* isolate) { |
1018 // Should only be run by the vm isolate. | 1045 // Should only be run by the vm isolate. |
1019 ASSERT(isolate == Dart::vm_isolate()); | 1046 ASSERT(isolate == Dart::vm_isolate()); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1079 // Set up names for the pseudo-classes for free list elements and forwarding | 1106 // Set up names for the pseudo-classes for free list elements and forwarding |
1080 // corpses. Mainly this makes VM debugging easier. | 1107 // corpses. Mainly this makes VM debugging easier. |
1081 cls = isolate->class_table()->At(kFreeListElement); | 1108 cls = isolate->class_table()->At(kFreeListElement); |
1082 cls.set_name(Symbols::FreeListElement()); | 1109 cls.set_name(Symbols::FreeListElement()); |
1083 cls = isolate->class_table()->At(kForwardingCorpse); | 1110 cls = isolate->class_table()->At(kForwardingCorpse); |
1084 cls.set_name(Symbols::ForwardingCorpse()); | 1111 cls.set_name(Symbols::ForwardingCorpse()); |
1085 | 1112 |
1086 { | 1113 { |
1087 ASSERT(isolate == Dart::vm_isolate()); | 1114 ASSERT(isolate == Dart::vm_isolate()); |
1088 WritableVMIsolateScope scope(Thread::Current()); | 1115 WritableVMIsolateScope scope(Thread::Current()); |
1089 PremarkingVisitor premarker; | 1116 FinalizeVMIsolateVisitor premarker; |
1090 ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0); | 1117 ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0); |
1091 isolate->heap()->IterateOldObjectsNoImagePages(&premarker); | 1118 isolate->heap()->IterateOldObjectsNoImagePages(&premarker); |
1092 // Make the VM isolate read-only again after setting all objects as marked. | 1119 // Make the VM isolate read-only again after setting all objects as marked. |
1093 // Note objects in image pages are already pre-marked. | 1120 // Note objects in image pages are already pre-marked. |
1094 } | 1121 } |
1095 } | 1122 } |
1096 | 1123 |
1097 | 1124 |
1098 void Object::set_vm_isolate_snapshot_object_table(const Array& table) { | 1125 void Object::set_vm_isolate_snapshot_object_table(const Array& table) { |
1099 ASSERT(Isolate::Current() == Dart::vm_isolate()); | 1126 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
(...skipping 14 matching lines...) Expand all Loading... |
1114 if (original_size > used_size) { | 1141 if (original_size > used_size) { |
1115 intptr_t leftover_size = original_size - used_size; | 1142 intptr_t leftover_size = original_size - used_size; |
1116 | 1143 |
1117 uword addr = RawObject::ToAddr(obj.raw()) + used_size; | 1144 uword addr = RawObject::ToAddr(obj.raw()) + used_size; |
1118 if (leftover_size >= TypedData::InstanceSize(0)) { | 1145 if (leftover_size >= TypedData::InstanceSize(0)) { |
1119 // Update the leftover space as a TypedDataInt8Array object. | 1146 // Update the leftover space as a TypedDataInt8Array object. |
1120 RawTypedData* raw = | 1147 RawTypedData* raw = |
1121 reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr)); | 1148 reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr)); |
1122 uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0); | 1149 uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0); |
1123 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); | 1150 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); |
1124 uword tags = raw->ptr()->tags_; | 1151 uint32_t tags = raw->ptr()->tags_; |
1125 uword old_tags; | 1152 uint32_t old_tags; |
1126 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. | 1153 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. |
1127 do { | 1154 do { |
1128 old_tags = tags; | 1155 old_tags = tags; |
1129 tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_, | 1156 // We can't use obj.CompareAndSwapTags here because we don't have a |
1130 old_tags, new_tags); | 1157 // handle for the new object. |
| 1158 tags = AtomicOperations::CompareAndSwapUint32(&raw->ptr()->tags_, |
| 1159 old_tags, new_tags); |
1131 } while (tags != old_tags); | 1160 } while (tags != old_tags); |
1132 | 1161 |
1133 intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0)); | 1162 intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0)); |
1134 ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size); | 1163 ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size); |
1135 raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len)); | 1164 raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len)); |
1136 } else { | 1165 } else { |
1137 // Update the leftover space as a basic object. | 1166 // Update the leftover space as a basic object. |
1138 ASSERT(leftover_size == Object::InstanceSize()); | 1167 ASSERT(leftover_size == Object::InstanceSize()); |
1139 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); | 1168 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); |
1140 uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0); | 1169 uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0); |
1141 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); | 1170 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); |
1142 uword tags = raw->ptr()->tags_; | 1171 uint32_t tags = raw->ptr()->tags_; |
1143 uword old_tags; | 1172 uint32_t old_tags; |
1144 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. | 1173 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. |
1145 do { | 1174 do { |
1146 old_tags = tags; | 1175 old_tags = tags; |
1147 tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_, | 1176 tags = obj.CompareAndSwapTags(old_tags, new_tags); |
1148 old_tags, new_tags); | |
1149 } while (tags != old_tags); | 1177 } while (tags != old_tags); |
1150 } | 1178 } |
1151 } | 1179 } |
1152 } | 1180 } |
1153 | 1181 |
1154 | 1182 |
1155 void Object::VerifyBuiltinVtables() { | 1183 void Object::VerifyBuiltinVtables() { |
1156 #if defined(DEBUG) | 1184 #if defined(DEBUG) |
1157 Thread* thread = Thread::Current(); | 1185 Thread* thread = Thread::Current(); |
1158 Isolate* isolate = thread->isolate(); | 1186 Isolate* isolate = thread->isolate(); |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1860 bool is_vm_object) { | 1888 bool is_vm_object) { |
1861 uword initial_value = (class_id == kInstructionsCid) | 1889 uword initial_value = (class_id == kInstructionsCid) |
1862 ? Assembler::GetBreakInstructionFiller() | 1890 ? Assembler::GetBreakInstructionFiller() |
1863 : reinterpret_cast<uword>(null_); | 1891 : reinterpret_cast<uword>(null_); |
1864 uword cur = address; | 1892 uword cur = address; |
1865 uword end = address + size; | 1893 uword end = address + size; |
1866 while (cur < end) { | 1894 while (cur < end) { |
1867 *reinterpret_cast<uword*>(cur) = initial_value; | 1895 *reinterpret_cast<uword*>(cur) = initial_value; |
1868 cur += kWordSize; | 1896 cur += kWordSize; |
1869 } | 1897 } |
1870 uword tags = 0; | 1898 uint32_t tags = 0; |
1871 ASSERT(class_id != kIllegalCid); | 1899 ASSERT(class_id != kIllegalCid); |
1872 tags = RawObject::ClassIdTag::update(class_id, tags); | 1900 tags = RawObject::ClassIdTag::update(class_id, tags); |
1873 tags = RawObject::SizeTag::update(size, tags); | 1901 tags = RawObject::SizeTag::update(size, tags); |
1874 tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags); | 1902 tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags); |
1875 reinterpret_cast<RawObject*>(address)->tags_ = tags; | 1903 reinterpret_cast<RawObject*>(address)->tags_ = tags; |
| 1904 #if defined(HASH_IN_OBJECT_HEADER) |
| 1905 reinterpret_cast<RawObject*>(address)->hash_ = 0; |
| 1906 #endif |
1876 ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags)); | 1907 ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags)); |
1877 } | 1908 } |
1878 | 1909 |
1879 | 1910 |
1880 void Object::CheckHandle() const { | 1911 void Object::CheckHandle() const { |
1881 #if defined(DEBUG) | 1912 #if defined(DEBUG) |
1882 if (raw_ != Object::null()) { | 1913 if (raw_ != Object::null()) { |
1883 if ((reinterpret_cast<uword>(raw_) & kSmiTagMask) == kSmiTag) { | 1914 if ((reinterpret_cast<uword>(raw_) & kSmiTagMask) == kSmiTag) { |
1884 ASSERT(vtable() == Smi::handle_vtable_); | 1915 ASSERT(vtable() == Smi::handle_vtable_); |
1885 return; | 1916 return; |
(...skipping 18314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20200 static intptr_t HashImpl(const T* characters, intptr_t len) { | 20231 static intptr_t HashImpl(const T* characters, intptr_t len) { |
20201 ASSERT(len >= 0); | 20232 ASSERT(len >= 0); |
20202 StringHasher hasher; | 20233 StringHasher hasher; |
20203 for (intptr_t i = 0; i < len; i++) { | 20234 for (intptr_t i = 0; i < len; i++) { |
20204 hasher.Add(characters[i]); | 20235 hasher.Add(characters[i]); |
20205 } | 20236 } |
20206 return hasher.Finalize(String::kHashBits); | 20237 return hasher.Finalize(String::kHashBits); |
20207 } | 20238 } |
20208 | 20239 |
20209 | 20240 |
| 20241 intptr_t String::Hash(RawString* raw) { |
| 20242 StringHasher hasher; |
| 20243 uword length = Smi::Value(raw->ptr()->length_); |
| 20244 if (raw->IsOneByteString() || raw->IsExternalOneByteString()) { |
| 20245 const uint8_t* data; |
| 20246 if (raw->IsOneByteString()) { |
| 20247 data = reinterpret_cast<RawOneByteString*>(raw)->ptr()->data(); |
| 20248 } else { |
| 20249 ASSERT(raw->IsExternalOneByteString()); |
| 20250 RawExternalOneByteString* str = |
| 20251 reinterpret_cast<RawExternalOneByteString*>(raw); |
| 20252 data = str->ptr()->external_data_->data(); |
| 20253 } |
| 20254 return String::Hash(data, length); |
| 20255 } else { |
| 20256 const uint16_t* data; |
| 20257 if (raw->IsTwoByteString()) { |
| 20258 data = reinterpret_cast<RawTwoByteString*>(raw)->ptr()->data(); |
| 20259 } else { |
| 20260 ASSERT(raw->IsExternalTwoByteString()); |
| 20261 RawExternalTwoByteString* str = |
| 20262 reinterpret_cast<RawExternalTwoByteString*>(raw); |
| 20263 data = str->ptr()->external_data_->data(); |
| 20264 } |
| 20265 return String::Hash(data, length); |
| 20266 } |
| 20267 } |
| 20268 |
| 20269 |
20210 intptr_t String::Hash(const char* characters, intptr_t len) { | 20270 intptr_t String::Hash(const char* characters, intptr_t len) { |
20211 return HashImpl(characters, len); | 20271 return HashImpl(characters, len); |
20212 } | 20272 } |
20213 | 20273 |
20214 | 20274 |
20215 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { | 20275 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { |
20216 return HashImpl(characters, len); | 20276 return HashImpl(characters, len); |
20217 } | 20277 } |
20218 | 20278 |
20219 | 20279 |
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21020 memmove(array, OneByteString::CharAddr(*this, 0), str_length); | 21080 memmove(array, OneByteString::CharAddr(*this, 0), str_length); |
21021 } | 21081 } |
21022 | 21082 |
21023 // If there is any left over space fill it with either an Array object or | 21083 // If there is any left over space fill it with either an Array object or |
21024 // just a plain object (depending on the amount of left over space) so | 21084 // just a plain object (depending on the amount of left over space) so |
21025 // that it can be traversed over successfully during garbage collection. | 21085 // that it can be traversed over successfully during garbage collection. |
21026 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | 21086 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
21027 | 21087 |
21028 // Update the class information of the object. | 21088 // Update the class information of the object. |
21029 const intptr_t class_id = kExternalOneByteStringCid; | 21089 const intptr_t class_id = kExternalOneByteStringCid; |
21030 uword tags = raw_ptr()->tags_; | 21090 uint32_t tags = raw_ptr()->tags_; |
21031 uword old_tags; | 21091 uint32_t old_tags; |
21032 do { | 21092 do { |
21033 old_tags = tags; | 21093 old_tags = tags; |
21034 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); | 21094 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); |
21035 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | 21095 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); |
21036 tags = CompareAndSwapTags(old_tags, new_tags); | 21096 tags = CompareAndSwapTags(old_tags, new_tags); |
21037 } while (tags != old_tags); | 21097 } while (tags != old_tags); |
21038 result = this->raw(); | 21098 result = this->raw(); |
21039 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); | 21099 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); |
21040 ExternalStringData<uint8_t>* ext_data = | 21100 ExternalStringData<uint8_t>* ext_data = |
21041 new ExternalStringData<uint8_t>(ext_array, peer, cback); | 21101 new ExternalStringData<uint8_t>(ext_array, peer, cback); |
21042 ASSERT(result.Length() == str_length); | 21102 ASSERT(result.Length() == str_length); |
21043 ASSERT(!result.HasHash() || | 21103 ASSERT(!result.HasHash() || |
21044 (result.Hash() == String::Hash(ext_array, str_length))); | 21104 (result.Hash() == String::Hash(ext_array, str_length))); |
(...skipping 12 matching lines...) Expand all Loading... |
21057 (str_length * kTwoByteChar)); | 21117 (str_length * kTwoByteChar)); |
21058 } | 21118 } |
21059 | 21119 |
21060 // If there is any left over space fill it with either an Array object or | 21120 // If there is any left over space fill it with either an Array object or |
21061 // just a plain object (depending on the amount of left over space) so | 21121 // just a plain object (depending on the amount of left over space) so |
21062 // that it can be traversed over successfully during garbage collection. | 21122 // that it can be traversed over successfully during garbage collection. |
21063 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | 21123 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
21064 | 21124 |
21065 // Update the class information of the object. | 21125 // Update the class information of the object. |
21066 const intptr_t class_id = kExternalTwoByteStringCid; | 21126 const intptr_t class_id = kExternalTwoByteStringCid; |
21067 uword tags = raw_ptr()->tags_; | 21127 uint32_t tags = raw_ptr()->tags_; |
21068 uword old_tags; | 21128 uint32_t old_tags; |
21069 do { | 21129 do { |
21070 old_tags = tags; | 21130 old_tags = tags; |
21071 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); | 21131 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); |
21072 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | 21132 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); |
21073 tags = CompareAndSwapTags(old_tags, new_tags); | 21133 tags = CompareAndSwapTags(old_tags, new_tags); |
21074 } while (tags != old_tags); | 21134 } while (tags != old_tags); |
21075 result = this->raw(); | 21135 result = this->raw(); |
21076 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); | 21136 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); |
21077 ExternalStringData<uint16_t>* ext_data = | 21137 ExternalStringData<uint16_t>* ext_data = |
21078 new ExternalStringData<uint16_t>(ext_array, peer, cback); | 21138 new ExternalStringData<uint16_t>(ext_array, peer, cback); |
21079 ASSERT(result.Length() == str_length); | 21139 ASSERT(result.Length() == str_length); |
21080 ASSERT(!result.HasHash() || | 21140 ASSERT(!result.HasHash() || |
21081 (result.Hash() == String::Hash(ext_array, str_length))); | 21141 (result.Hash() == String::Hash(ext_array, str_length))); |
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21949 } | 22009 } |
21950 | 22010 |
21951 return dest.raw(); | 22011 return dest.raw(); |
21952 } | 22012 } |
21953 | 22013 |
21954 | 22014 |
21955 void Array::MakeImmutable() const { | 22015 void Array::MakeImmutable() const { |
21956 if (IsImmutable()) return; | 22016 if (IsImmutable()) return; |
21957 ASSERT(!IsCanonical()); | 22017 ASSERT(!IsCanonical()); |
21958 NoSafepointScope no_safepoint; | 22018 NoSafepointScope no_safepoint; |
21959 uword tags = raw_ptr()->tags_; | 22019 uint32_t tags = raw_ptr()->tags_; |
21960 uword old_tags; | 22020 uint32_t old_tags; |
21961 do { | 22021 do { |
21962 old_tags = tags; | 22022 old_tags = tags; |
21963 uword new_tags = | 22023 uint32_t new_tags = |
21964 RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags); | 22024 RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags); |
21965 tags = CompareAndSwapTags(old_tags, new_tags); | 22025 tags = CompareAndSwapTags(old_tags, new_tags); |
21966 } while (tags != old_tags); | 22026 } while (tags != old_tags); |
21967 } | 22027 } |
21968 | 22028 |
21969 | 22029 |
21970 const char* Array::ToCString() const { | 22030 const char* Array::ToCString() const { |
21971 if (IsNull()) { | 22031 if (IsNull()) { |
21972 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; | 22032 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; |
21973 } | 22033 } |
(...skipping 21 matching lines...) Expand all Loading... |
21995 for (int i = 0; i < len; i++) { | 22055 for (int i = 0; i < len; i++) { |
21996 obj = source.At(i); | 22056 obj = source.At(i); |
21997 result.SetAt(i, obj); | 22057 result.SetAt(i, obj); |
21998 } | 22058 } |
21999 return result.raw(); | 22059 return result.raw(); |
22000 } | 22060 } |
22001 | 22061 |
22002 | 22062 |
22003 RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) { | 22063 RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) { |
22004 ASSERT(!growable_array.IsNull()); | 22064 ASSERT(!growable_array.IsNull()); |
| 22065 ASSERT(growable_array.IsGrowableObjectArray()); |
22005 intptr_t used_len = growable_array.Length(); | 22066 intptr_t used_len = growable_array.Length(); |
22006 // Get the type arguments and prepare to copy them. | 22067 // Get the type arguments and prepare to copy them. |
22007 const TypeArguments& type_arguments = | 22068 const TypeArguments& type_arguments = |
22008 TypeArguments::Handle(growable_array.GetTypeArguments()); | 22069 TypeArguments::Handle(growable_array.GetTypeArguments()); |
22009 if ((used_len == 0) && (type_arguments.IsNull())) { | 22070 if ((used_len == 0) && (type_arguments.IsNull())) { |
22010 // This is a raw List (as in no type arguments), so we can return the | 22071 // This is a raw List (as in no type arguments), so we can return the |
22011 // simple empty array. | 22072 // simple empty array. |
22012 return Object::empty_array().raw(); | 22073 return Object::empty_array().raw(); |
22013 } | 22074 } |
22014 intptr_t capacity_len = growable_array.Capacity(); | 22075 intptr_t capacity_len = growable_array.Capacity(); |
22015 Zone* zone = Thread::Current()->zone(); | 22076 Zone* zone = Thread::Current()->zone(); |
22016 const Array& array = Array::Handle(zone, growable_array.data()); | 22077 const Array& array = Array::Handle(zone, growable_array.data()); |
| 22078 ASSERT(array.IsArray()); |
22017 array.SetTypeArguments(type_arguments); | 22079 array.SetTypeArguments(type_arguments); |
22018 intptr_t capacity_size = Array::InstanceSize(capacity_len); | 22080 intptr_t capacity_size = Array::InstanceSize(capacity_len); |
22019 intptr_t used_size = Array::InstanceSize(used_len); | 22081 intptr_t used_size = Array::InstanceSize(used_len); |
22020 NoSafepointScope no_safepoint; | 22082 NoSafepointScope no_safepoint; |
22021 | 22083 |
22022 // If there is any left over space fill it with either an Array object or | 22084 // If there is any left over space fill it with either an Array object or |
22023 // just a plain object (depending on the amount of left over space) so | 22085 // just a plain object (depending on the amount of left over space) so |
22024 // that it can be traversed over successfully during garbage collection. | 22086 // that it can be traversed over successfully during garbage collection. |
22025 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); | 22087 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); |
22026 | 22088 |
22027 // Update the size in the header field and length of the array object. | 22089 // Update the size in the header field and length of the array object. |
22028 uword tags = array.raw_ptr()->tags_; | 22090 uword tags = array.raw_ptr()->tags_; |
22029 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); | 22091 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); |
22030 uword old_tags; | 22092 uint32_t old_tags; |
22031 do { | 22093 do { |
22032 old_tags = tags; | 22094 old_tags = tags; |
22033 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); | 22095 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); |
22034 tags = array.CompareAndSwapTags(old_tags, new_tags); | 22096 tags = array.CompareAndSwapTags(old_tags, new_tags); |
22035 } while (tags != old_tags); | 22097 } while (tags != old_tags); |
22036 // TODO(22501): For the heap to remain walkable by the sweeper, it must | 22098 // TODO(22501): For the heap to remain walkable by the sweeper, it must |
22037 // observe the creation of the filler object no later than the new length | 22099 // observe the creation of the filler object no later than the new length |
22038 // of the array. This assumption holds on ia32/x64 or if the CAS above is a | 22100 // of the array. This assumption holds on ia32/x64 or if the CAS above is a |
22039 // full memory barrier. | 22101 // full memory barrier. |
22040 // | 22102 // |
22041 // Also, between the CAS of the header above and the SetLength below, | 22103 // Also, between the CAS of the header above and the SetLength below, |
22042 // the array is temporarily in an inconsistent state. The header is considered | 22104 // the array is temporarily in an inconsistent state. The header is considered |
22043 // the overriding source of object size by RawObject::Size, but the ASSERTs | 22105 // the overriding source of object size by RawObject::Size, but the ASSERTs |
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
23353 return UserTag::null(); | 23415 return UserTag::null(); |
23354 } | 23416 } |
23355 | 23417 |
23356 | 23418 |
23357 const char* UserTag::ToCString() const { | 23419 const char* UserTag::ToCString() const { |
23358 const String& tag_label = String::Handle(label()); | 23420 const String& tag_label = String::Handle(label()); |
23359 return tag_label.ToCString(); | 23421 return tag_label.ToCString(); |
23360 } | 23422 } |
23361 | 23423 |
23362 } // namespace dart | 23424 } // namespace dart |
OLD | NEW |