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. Also precalculates hash | 995 // premark all objects in the vm_isolate_ heap. |
996 // codes so that we can get the identity hash code of objects in the read- | 996 class PremarkingVisitor : public ObjectVisitor { |
997 // only VM isolate. | |
998 class FinalizeVMIsolateVisitor : public ObjectVisitor { | |
999 public: | 997 public: |
1000 FinalizeVMIsolateVisitor() | 998 PremarkingVisitor() {} |
1001 #if defined(HASH_IN_OBJECT_HEADER) | |
1002 : counter_(1337) | |
1003 #endif | |
1004 { | |
1005 } | |
1006 | 999 |
1007 void VisitObject(RawObject* obj) { | 1000 void VisitObject(RawObject* obj) { |
1008 // Free list elements should never be marked. | 1001 // Free list elements should never be marked. |
1009 ASSERT(!obj->IsMarked()); | 1002 ASSERT(!obj->IsMarked()); |
1010 // No forwarding corpses in the VM isolate. | 1003 // No forwarding corpses in the VM isolate. |
1011 ASSERT(!obj->IsForwardingCorpse()); | 1004 ASSERT(!obj->IsForwardingCorpse()); |
1012 if (!obj->IsFreeListElement()) { | 1005 if (!obj->IsFreeListElement()) { |
1013 ASSERT(obj->IsVMHeapObject()); | 1006 ASSERT(obj->IsVMHeapObject()); |
1014 obj->SetMarkBitUnsynchronized(); | 1007 obj->SetMarkBitUnsynchronized(); |
1015 if (obj->IsStringInstance()) { | |
1016 RawString* str = reinterpret_cast<RawString*>(obj); | |
1017 intptr_t hash = String::Hash(str); | |
1018 String::SetCachedHash(str, hash); | |
1019 } | |
1020 #if defined(HASH_IN_OBJECT_HEADER) | |
1021 // These objects end up in the read-only VM isolate which is shared | |
1022 // between isolates, so we have to prepopulate them with identity hash | |
1023 // codes, since we can't add hash codes later. | |
1024 if (Object::GetCachedHash(obj) == 0) { | |
1025 // Some classes have identity hash codes that depend on their contents, | |
1026 // not per object. | |
1027 ASSERT(!obj->IsStringInstance()); | |
1028 if (!obj->IsMint() && !obj->IsDouble() && !obj->IsBigint() && | |
1029 !obj->IsRawNull() && !obj->IsBool()) { | |
1030 counter_ += 2011; // The year Dart was announced and a prime. | |
1031 counter_ &= 0x3fffffff; | |
1032 if (counter_ == 0) counter_++; | |
1033 Object::SetCachedHash(obj, counter_); | |
1034 } | |
1035 } | |
1036 #endif | |
1037 } | 1008 } |
1038 } | 1009 } |
1039 | |
1040 private: | |
1041 #if defined(HASH_IN_OBJECT_HEADER) | |
1042 int counter_; | |
1043 #endif | |
1044 }; | 1010 }; |
1045 | 1011 |
1046 | 1012 |
1047 #define SET_CLASS_NAME(class_name, name) \ | 1013 #define SET_CLASS_NAME(class_name, name) \ |
1048 cls = class_name##_class(); \ | 1014 cls = class_name##_class(); \ |
1049 cls.set_name(Symbols::name()); | 1015 cls.set_name(Symbols::name()); |
1050 | 1016 |
1051 void Object::FinalizeVMIsolate(Isolate* isolate) { | 1017 void Object::FinalizeVMIsolate(Isolate* isolate) { |
1052 // Should only be run by the vm isolate. | 1018 // Should only be run by the vm isolate. |
1053 ASSERT(isolate == Dart::vm_isolate()); | 1019 ASSERT(isolate == Dart::vm_isolate()); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 // Set up names for the pseudo-classes for free list elements and forwarding | 1079 // Set up names for the pseudo-classes for free list elements and forwarding |
1114 // corpses. Mainly this makes VM debugging easier. | 1080 // corpses. Mainly this makes VM debugging easier. |
1115 cls = isolate->class_table()->At(kFreeListElement); | 1081 cls = isolate->class_table()->At(kFreeListElement); |
1116 cls.set_name(Symbols::FreeListElement()); | 1082 cls.set_name(Symbols::FreeListElement()); |
1117 cls = isolate->class_table()->At(kForwardingCorpse); | 1083 cls = isolate->class_table()->At(kForwardingCorpse); |
1118 cls.set_name(Symbols::ForwardingCorpse()); | 1084 cls.set_name(Symbols::ForwardingCorpse()); |
1119 | 1085 |
1120 { | 1086 { |
1121 ASSERT(isolate == Dart::vm_isolate()); | 1087 ASSERT(isolate == Dart::vm_isolate()); |
1122 WritableVMIsolateScope scope(Thread::Current()); | 1088 WritableVMIsolateScope scope(Thread::Current()); |
1123 FinalizeVMIsolateVisitor premarker; | 1089 PremarkingVisitor premarker; |
1124 ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0); | 1090 ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0); |
1125 isolate->heap()->IterateOldObjectsNoImagePages(&premarker); | 1091 isolate->heap()->IterateOldObjectsNoImagePages(&premarker); |
1126 // Make the VM isolate read-only again after setting all objects as marked. | 1092 // Make the VM isolate read-only again after setting all objects as marked. |
1127 // Note objects in image pages are already pre-marked. | 1093 // Note objects in image pages are already pre-marked. |
1128 } | 1094 } |
1129 } | 1095 } |
1130 | 1096 |
1131 | 1097 |
1132 void Object::set_vm_isolate_snapshot_object_table(const Array& table) { | 1098 void Object::set_vm_isolate_snapshot_object_table(const Array& table) { |
1133 ASSERT(Isolate::Current() == Dart::vm_isolate()); | 1099 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
(...skipping 14 matching lines...) Expand all Loading... |
1148 if (original_size > used_size) { | 1114 if (original_size > used_size) { |
1149 intptr_t leftover_size = original_size - used_size; | 1115 intptr_t leftover_size = original_size - used_size; |
1150 | 1116 |
1151 uword addr = RawObject::ToAddr(obj.raw()) + used_size; | 1117 uword addr = RawObject::ToAddr(obj.raw()) + used_size; |
1152 if (leftover_size >= TypedData::InstanceSize(0)) { | 1118 if (leftover_size >= TypedData::InstanceSize(0)) { |
1153 // Update the leftover space as a TypedDataInt8Array object. | 1119 // Update the leftover space as a TypedDataInt8Array object. |
1154 RawTypedData* raw = | 1120 RawTypedData* raw = |
1155 reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr)); | 1121 reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr)); |
1156 uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0); | 1122 uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0); |
1157 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); | 1123 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); |
1158 uint32_t tags = raw->ptr()->tags_; | 1124 uword tags = raw->ptr()->tags_; |
1159 uint32_t old_tags; | 1125 uword old_tags; |
1160 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. | 1126 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. |
1161 do { | 1127 do { |
1162 old_tags = tags; | 1128 old_tags = tags; |
1163 // We can't use obj.CompareAndSwapTags here because we don't have a | 1129 tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_, |
1164 // handle for the new object. | 1130 old_tags, new_tags); |
1165 tags = AtomicOperations::CompareAndSwapUint32(&raw->ptr()->tags_, | |
1166 old_tags, new_tags); | |
1167 } while (tags != old_tags); | 1131 } while (tags != old_tags); |
1168 | 1132 |
1169 intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0)); | 1133 intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0)); |
1170 ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size); | 1134 ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size); |
1171 raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len)); | 1135 raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len)); |
1172 } else { | 1136 } else { |
1173 // Update the leftover space as a basic object. | 1137 // Update the leftover space as a basic object. |
1174 ASSERT(leftover_size == Object::InstanceSize()); | 1138 ASSERT(leftover_size == Object::InstanceSize()); |
1175 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); | 1139 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); |
1176 uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0); | 1140 uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0); |
1177 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); | 1141 new_tags = RawObject::SizeTag::update(leftover_size, new_tags); |
1178 uint32_t tags = raw->ptr()->tags_; | 1142 uword tags = raw->ptr()->tags_; |
1179 uint32_t old_tags; | 1143 uword old_tags; |
1180 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. | 1144 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary. |
1181 do { | 1145 do { |
1182 old_tags = tags; | 1146 old_tags = tags; |
1183 tags = obj.CompareAndSwapTags(old_tags, new_tags); | 1147 tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_, |
| 1148 old_tags, new_tags); |
1184 } while (tags != old_tags); | 1149 } while (tags != old_tags); |
1185 } | 1150 } |
1186 } | 1151 } |
1187 } | 1152 } |
1188 | 1153 |
1189 | 1154 |
1190 void Object::VerifyBuiltinVtables() { | 1155 void Object::VerifyBuiltinVtables() { |
1191 #if defined(DEBUG) | 1156 #if defined(DEBUG) |
1192 Thread* thread = Thread::Current(); | 1157 Thread* thread = Thread::Current(); |
1193 Isolate* isolate = thread->isolate(); | 1158 Isolate* isolate = thread->isolate(); |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 bool is_vm_object) { | 1860 bool is_vm_object) { |
1896 uword initial_value = (class_id == kInstructionsCid) | 1861 uword initial_value = (class_id == kInstructionsCid) |
1897 ? Assembler::GetBreakInstructionFiller() | 1862 ? Assembler::GetBreakInstructionFiller() |
1898 : reinterpret_cast<uword>(null_); | 1863 : reinterpret_cast<uword>(null_); |
1899 uword cur = address; | 1864 uword cur = address; |
1900 uword end = address + size; | 1865 uword end = address + size; |
1901 while (cur < end) { | 1866 while (cur < end) { |
1902 *reinterpret_cast<uword*>(cur) = initial_value; | 1867 *reinterpret_cast<uword*>(cur) = initial_value; |
1903 cur += kWordSize; | 1868 cur += kWordSize; |
1904 } | 1869 } |
1905 uint32_t tags = 0; | 1870 uword tags = 0; |
1906 ASSERT(class_id != kIllegalCid); | 1871 ASSERT(class_id != kIllegalCid); |
1907 tags = RawObject::ClassIdTag::update(class_id, tags); | 1872 tags = RawObject::ClassIdTag::update(class_id, tags); |
1908 tags = RawObject::SizeTag::update(size, tags); | 1873 tags = RawObject::SizeTag::update(size, tags); |
1909 tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags); | 1874 tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags); |
1910 reinterpret_cast<RawObject*>(address)->tags_ = tags; | 1875 reinterpret_cast<RawObject*>(address)->tags_ = tags; |
1911 #if defined(HASH_IN_OBJECT_HEADER) | |
1912 reinterpret_cast<RawObject*>(address)->hash_ = 0; | |
1913 #endif | |
1914 ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags)); | 1876 ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags)); |
1915 } | 1877 } |
1916 | 1878 |
1917 | 1879 |
1918 void Object::CheckHandle() const { | 1880 void Object::CheckHandle() const { |
1919 #if defined(DEBUG) | 1881 #if defined(DEBUG) |
1920 if (raw_ != Object::null()) { | 1882 if (raw_ != Object::null()) { |
1921 if ((reinterpret_cast<uword>(raw_) & kSmiTagMask) == kSmiTag) { | 1883 if ((reinterpret_cast<uword>(raw_) & kSmiTagMask) == kSmiTag) { |
1922 ASSERT(vtable() == Smi::handle_vtable_); | 1884 ASSERT(vtable() == Smi::handle_vtable_); |
1923 return; | 1885 return; |
(...skipping 18434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20358 static intptr_t HashImpl(const T* characters, intptr_t len) { | 20320 static intptr_t HashImpl(const T* characters, intptr_t len) { |
20359 ASSERT(len >= 0); | 20321 ASSERT(len >= 0); |
20360 StringHasher hasher; | 20322 StringHasher hasher; |
20361 for (intptr_t i = 0; i < len; i++) { | 20323 for (intptr_t i = 0; i < len; i++) { |
20362 hasher.Add(characters[i]); | 20324 hasher.Add(characters[i]); |
20363 } | 20325 } |
20364 return hasher.Finalize(String::kHashBits); | 20326 return hasher.Finalize(String::kHashBits); |
20365 } | 20327 } |
20366 | 20328 |
20367 | 20329 |
20368 intptr_t String::Hash(RawString* raw) { | |
20369 StringHasher hasher; | |
20370 uword length = Smi::Value(raw->ptr()->length_); | |
20371 if (raw->IsOneByteString() || raw->IsExternalOneByteString()) { | |
20372 const uint8_t* data; | |
20373 if (raw->IsOneByteString()) { | |
20374 data = reinterpret_cast<RawOneByteString*>(raw)->ptr()->data(); | |
20375 } else { | |
20376 ASSERT(raw->IsExternalOneByteString()); | |
20377 RawExternalOneByteString* str = | |
20378 reinterpret_cast<RawExternalOneByteString*>(raw); | |
20379 data = str->ptr()->external_data_->data(); | |
20380 } | |
20381 return String::Hash(data, length); | |
20382 } else { | |
20383 const uint16_t* data; | |
20384 if (raw->IsTwoByteString()) { | |
20385 data = reinterpret_cast<RawTwoByteString*>(raw)->ptr()->data(); | |
20386 } else { | |
20387 ASSERT(raw->IsExternalTwoByteString()); | |
20388 RawExternalTwoByteString* str = | |
20389 reinterpret_cast<RawExternalTwoByteString*>(raw); | |
20390 data = str->ptr()->external_data_->data(); | |
20391 } | |
20392 return String::Hash(data, length); | |
20393 } | |
20394 } | |
20395 | |
20396 | |
20397 intptr_t String::Hash(const char* characters, intptr_t len) { | 20330 intptr_t String::Hash(const char* characters, intptr_t len) { |
20398 return HashImpl(characters, len); | 20331 return HashImpl(characters, len); |
20399 } | 20332 } |
20400 | 20333 |
20401 | 20334 |
20402 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { | 20335 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { |
20403 return HashImpl(characters, len); | 20336 return HashImpl(characters, len); |
20404 } | 20337 } |
20405 | 20338 |
20406 | 20339 |
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21207 memmove(array, OneByteString::CharAddr(*this, 0), str_length); | 21140 memmove(array, OneByteString::CharAddr(*this, 0), str_length); |
21208 } | 21141 } |
21209 | 21142 |
21210 // If there is any left over space fill it with either an Array object or | 21143 // If there is any left over space fill it with either an Array object or |
21211 // just a plain object (depending on the amount of left over space) so | 21144 // just a plain object (depending on the amount of left over space) so |
21212 // that it can be traversed over successfully during garbage collection. | 21145 // that it can be traversed over successfully during garbage collection. |
21213 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | 21146 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
21214 | 21147 |
21215 // Update the class information of the object. | 21148 // Update the class information of the object. |
21216 const intptr_t class_id = kExternalOneByteStringCid; | 21149 const intptr_t class_id = kExternalOneByteStringCid; |
21217 uint32_t tags = raw_ptr()->tags_; | 21150 uword tags = raw_ptr()->tags_; |
21218 uint32_t old_tags; | 21151 uword old_tags; |
21219 do { | 21152 do { |
21220 old_tags = tags; | 21153 old_tags = tags; |
21221 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | 21154 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); |
21222 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | 21155 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); |
21223 tags = CompareAndSwapTags(old_tags, new_tags); | 21156 tags = CompareAndSwapTags(old_tags, new_tags); |
21224 } while (tags != old_tags); | 21157 } while (tags != old_tags); |
21225 result = this->raw(); | 21158 result = this->raw(); |
21226 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); | 21159 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); |
21227 ExternalStringData<uint8_t>* ext_data = | 21160 ExternalStringData<uint8_t>* ext_data = |
21228 new ExternalStringData<uint8_t>(ext_array, peer, cback); | 21161 new ExternalStringData<uint8_t>(ext_array, peer, cback); |
21229 ASSERT(result.Length() == str_length); | 21162 ASSERT(result.Length() == str_length); |
21230 ASSERT(!result.HasHash() || | 21163 ASSERT(!result.HasHash() || |
21231 (result.Hash() == String::Hash(ext_array, str_length))); | 21164 (result.Hash() == String::Hash(ext_array, str_length))); |
(...skipping 12 matching lines...) Expand all Loading... |
21244 (str_length * kTwoByteChar)); | 21177 (str_length * kTwoByteChar)); |
21245 } | 21178 } |
21246 | 21179 |
21247 // If there is any left over space fill it with either an Array object or | 21180 // If there is any left over space fill it with either an Array object or |
21248 // just a plain object (depending on the amount of left over space) so | 21181 // just a plain object (depending on the amount of left over space) so |
21249 // that it can be traversed over successfully during garbage collection. | 21182 // that it can be traversed over successfully during garbage collection. |
21250 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | 21183 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
21251 | 21184 |
21252 // Update the class information of the object. | 21185 // Update the class information of the object. |
21253 const intptr_t class_id = kExternalTwoByteStringCid; | 21186 const intptr_t class_id = kExternalTwoByteStringCid; |
21254 uint32_t tags = raw_ptr()->tags_; | 21187 uword tags = raw_ptr()->tags_; |
21255 uint32_t old_tags; | 21188 uword old_tags; |
21256 do { | 21189 do { |
21257 old_tags = tags; | 21190 old_tags = tags; |
21258 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | 21191 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); |
21259 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | 21192 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); |
21260 tags = CompareAndSwapTags(old_tags, new_tags); | 21193 tags = CompareAndSwapTags(old_tags, new_tags); |
21261 } while (tags != old_tags); | 21194 } while (tags != old_tags); |
21262 result = this->raw(); | 21195 result = this->raw(); |
21263 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); | 21196 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); |
21264 ExternalStringData<uint16_t>* ext_data = | 21197 ExternalStringData<uint16_t>* ext_data = |
21265 new ExternalStringData<uint16_t>(ext_array, peer, cback); | 21198 new ExternalStringData<uint16_t>(ext_array, peer, cback); |
21266 ASSERT(result.Length() == str_length); | 21199 ASSERT(result.Length() == str_length); |
21267 ASSERT(!result.HasHash() || | 21200 ASSERT(!result.HasHash() || |
21268 (result.Hash() == String::Hash(ext_array, str_length))); | 21201 (result.Hash() == String::Hash(ext_array, str_length))); |
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22136 } | 22069 } |
22137 | 22070 |
22138 return dest.raw(); | 22071 return dest.raw(); |
22139 } | 22072 } |
22140 | 22073 |
22141 | 22074 |
22142 void Array::MakeImmutable() const { | 22075 void Array::MakeImmutable() const { |
22143 if (IsImmutable()) return; | 22076 if (IsImmutable()) return; |
22144 ASSERT(!IsCanonical()); | 22077 ASSERT(!IsCanonical()); |
22145 NoSafepointScope no_safepoint; | 22078 NoSafepointScope no_safepoint; |
22146 uint32_t tags = raw_ptr()->tags_; | 22079 uword tags = raw_ptr()->tags_; |
22147 uint32_t old_tags; | 22080 uword old_tags; |
22148 do { | 22081 do { |
22149 old_tags = tags; | 22082 old_tags = tags; |
22150 uint32_t new_tags = | 22083 uword new_tags = |
22151 RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags); | 22084 RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags); |
22152 tags = CompareAndSwapTags(old_tags, new_tags); | 22085 tags = CompareAndSwapTags(old_tags, new_tags); |
22153 } while (tags != old_tags); | 22086 } while (tags != old_tags); |
22154 } | 22087 } |
22155 | 22088 |
22156 | 22089 |
22157 const char* Array::ToCString() const { | 22090 const char* Array::ToCString() const { |
22158 if (IsNull()) { | 22091 if (IsNull()) { |
22159 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; | 22092 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; |
22160 } | 22093 } |
(...skipping 21 matching lines...) Expand all Loading... |
22182 for (int i = 0; i < len; i++) { | 22115 for (int i = 0; i < len; i++) { |
22183 obj = source.At(i); | 22116 obj = source.At(i); |
22184 result.SetAt(i, obj); | 22117 result.SetAt(i, obj); |
22185 } | 22118 } |
22186 return result.raw(); | 22119 return result.raw(); |
22187 } | 22120 } |
22188 | 22121 |
22189 | 22122 |
22190 RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) { | 22123 RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) { |
22191 ASSERT(!growable_array.IsNull()); | 22124 ASSERT(!growable_array.IsNull()); |
22192 ASSERT(growable_array.IsGrowableObjectArray()); | |
22193 intptr_t used_len = growable_array.Length(); | 22125 intptr_t used_len = growable_array.Length(); |
22194 // Get the type arguments and prepare to copy them. | 22126 // Get the type arguments and prepare to copy them. |
22195 const TypeArguments& type_arguments = | 22127 const TypeArguments& type_arguments = |
22196 TypeArguments::Handle(growable_array.GetTypeArguments()); | 22128 TypeArguments::Handle(growable_array.GetTypeArguments()); |
22197 if ((used_len == 0) && (type_arguments.IsNull())) { | 22129 if ((used_len == 0) && (type_arguments.IsNull())) { |
22198 // This is a raw List (as in no type arguments), so we can return the | 22130 // This is a raw List (as in no type arguments), so we can return the |
22199 // simple empty array. | 22131 // simple empty array. |
22200 return Object::empty_array().raw(); | 22132 return Object::empty_array().raw(); |
22201 } | 22133 } |
22202 intptr_t capacity_len = growable_array.Capacity(); | 22134 intptr_t capacity_len = growable_array.Capacity(); |
22203 Zone* zone = Thread::Current()->zone(); | 22135 Zone* zone = Thread::Current()->zone(); |
22204 const Array& array = Array::Handle(zone, growable_array.data()); | 22136 const Array& array = Array::Handle(zone, growable_array.data()); |
22205 ASSERT(array.IsArray()); | |
22206 array.SetTypeArguments(type_arguments); | 22137 array.SetTypeArguments(type_arguments); |
22207 intptr_t capacity_size = Array::InstanceSize(capacity_len); | 22138 intptr_t capacity_size = Array::InstanceSize(capacity_len); |
22208 intptr_t used_size = Array::InstanceSize(used_len); | 22139 intptr_t used_size = Array::InstanceSize(used_len); |
22209 NoSafepointScope no_safepoint; | 22140 NoSafepointScope no_safepoint; |
22210 | 22141 |
22211 // If there is any left over space fill it with either an Array object or | 22142 // If there is any left over space fill it with either an Array object or |
22212 // just a plain object (depending on the amount of left over space) so | 22143 // just a plain object (depending on the amount of left over space) so |
22213 // that it can be traversed over successfully during garbage collection. | 22144 // that it can be traversed over successfully during garbage collection. |
22214 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); | 22145 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); |
22215 | 22146 |
22216 // Update the size in the header field and length of the array object. | 22147 // Update the size in the header field and length of the array object. |
22217 uword tags = array.raw_ptr()->tags_; | 22148 uword tags = array.raw_ptr()->tags_; |
22218 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); | 22149 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); |
22219 uint32_t old_tags; | 22150 uword old_tags; |
22220 do { | 22151 do { |
22221 old_tags = tags; | 22152 old_tags = tags; |
22222 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | 22153 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); |
22223 tags = array.CompareAndSwapTags(old_tags, new_tags); | 22154 tags = array.CompareAndSwapTags(old_tags, new_tags); |
22224 } while (tags != old_tags); | 22155 } while (tags != old_tags); |
22225 // TODO(22501): For the heap to remain walkable by the sweeper, it must | 22156 // TODO(22501): For the heap to remain walkable by the sweeper, it must |
22226 // observe the creation of the filler object no later than the new length | 22157 // observe the creation of the filler object no later than the new length |
22227 // of the array. This assumption holds on ia32/x64 or if the CAS above is a | 22158 // of the array. This assumption holds on ia32/x64 or if the CAS above is a |
22228 // full memory barrier. | 22159 // full memory barrier. |
22229 // | 22160 // |
22230 // Also, between the CAS of the header above and the SetLength below, | 22161 // Also, between the CAS of the header above and the SetLength below, |
22231 // the array is temporarily in an inconsistent state. The header is considered | 22162 // the array is temporarily in an inconsistent state. The header is considered |
22232 // the overriding source of object size by RawObject::Size, but the ASSERTs | 22163 // the overriding source of object size by RawObject::Size, but the ASSERTs |
(...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
23546 return UserTag::null(); | 23477 return UserTag::null(); |
23547 } | 23478 } |
23548 | 23479 |
23549 | 23480 |
23550 const char* UserTag::ToCString() const { | 23481 const char* UserTag::ToCString() const { |
23551 const String& tag_label = String::Handle(label()); | 23482 const String& tag_label = String::Handle(label()); |
23552 return tag_label.ToCString(); | 23483 return tag_label.ToCString(); |
23553 } | 23484 } |
23554 | 23485 |
23555 } // namespace dart | 23486 } // namespace dart |
OLD | NEW |