| 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 int32_t 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 18446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20370 static intptr_t HashImpl(const T* characters, intptr_t len) { | 20332 static intptr_t HashImpl(const T* characters, intptr_t len) { |
| 20371 ASSERT(len >= 0); | 20333 ASSERT(len >= 0); |
| 20372 StringHasher hasher; | 20334 StringHasher hasher; |
| 20373 for (intptr_t i = 0; i < len; i++) { | 20335 for (intptr_t i = 0; i < len; i++) { |
| 20374 hasher.Add(characters[i]); | 20336 hasher.Add(characters[i]); |
| 20375 } | 20337 } |
| 20376 return hasher.Finalize(String::kHashBits); | 20338 return hasher.Finalize(String::kHashBits); |
| 20377 } | 20339 } |
| 20378 | 20340 |
| 20379 | 20341 |
| 20380 intptr_t String::Hash(RawString* raw) { | |
| 20381 StringHasher hasher; | |
| 20382 uword length = Smi::Value(raw->ptr()->length_); | |
| 20383 if (raw->IsOneByteString() || raw->IsExternalOneByteString()) { | |
| 20384 const uint8_t* data; | |
| 20385 if (raw->IsOneByteString()) { | |
| 20386 data = reinterpret_cast<RawOneByteString*>(raw)->ptr()->data(); | |
| 20387 } else { | |
| 20388 ASSERT(raw->IsExternalOneByteString()); | |
| 20389 RawExternalOneByteString* str = | |
| 20390 reinterpret_cast<RawExternalOneByteString*>(raw); | |
| 20391 data = str->ptr()->external_data_->data(); | |
| 20392 } | |
| 20393 return String::Hash(data, length); | |
| 20394 } else { | |
| 20395 const uint16_t* data; | |
| 20396 if (raw->IsTwoByteString()) { | |
| 20397 data = reinterpret_cast<RawTwoByteString*>(raw)->ptr()->data(); | |
| 20398 } else { | |
| 20399 ASSERT(raw->IsExternalTwoByteString()); | |
| 20400 RawExternalTwoByteString* str = | |
| 20401 reinterpret_cast<RawExternalTwoByteString*>(raw); | |
| 20402 data = str->ptr()->external_data_->data(); | |
| 20403 } | |
| 20404 return String::Hash(data, length); | |
| 20405 } | |
| 20406 } | |
| 20407 | |
| 20408 | |
| 20409 intptr_t String::Hash(const char* characters, intptr_t len) { | 20342 intptr_t String::Hash(const char* characters, intptr_t len) { |
| 20410 return HashImpl(characters, len); | 20343 return HashImpl(characters, len); |
| 20411 } | 20344 } |
| 20412 | 20345 |
| 20413 | 20346 |
| 20414 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { | 20347 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { |
| 20415 return HashImpl(characters, len); | 20348 return HashImpl(characters, len); |
| 20416 } | 20349 } |
| 20417 | 20350 |
| 20418 | 20351 |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21219 memmove(array, OneByteString::CharAddr(*this, 0), str_length); | 21152 memmove(array, OneByteString::CharAddr(*this, 0), str_length); |
| 21220 } | 21153 } |
| 21221 | 21154 |
| 21222 // If there is any left over space fill it with either an Array object or | 21155 // If there is any left over space fill it with either an Array object or |
| 21223 // just a plain object (depending on the amount of left over space) so | 21156 // just a plain object (depending on the amount of left over space) so |
| 21224 // that it can be traversed over successfully during garbage collection. | 21157 // that it can be traversed over successfully during garbage collection. |
| 21225 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | 21158 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
| 21226 | 21159 |
| 21227 // Update the class information of the object. | 21160 // Update the class information of the object. |
| 21228 const intptr_t class_id = kExternalOneByteStringCid; | 21161 const intptr_t class_id = kExternalOneByteStringCid; |
| 21229 uint32_t tags = raw_ptr()->tags_; | 21162 uword tags = raw_ptr()->tags_; |
| 21230 uint32_t old_tags; | 21163 uword old_tags; |
| 21231 do { | 21164 do { |
| 21232 old_tags = tags; | 21165 old_tags = tags; |
| 21233 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | 21166 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); |
| 21234 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | 21167 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); |
| 21235 tags = CompareAndSwapTags(old_tags, new_tags); | 21168 tags = CompareAndSwapTags(old_tags, new_tags); |
| 21236 } while (tags != old_tags); | 21169 } while (tags != old_tags); |
| 21237 result = this->raw(); | 21170 result = this->raw(); |
| 21238 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); | 21171 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); |
| 21239 ExternalStringData<uint8_t>* ext_data = | 21172 ExternalStringData<uint8_t>* ext_data = |
| 21240 new ExternalStringData<uint8_t>(ext_array, peer, cback); | 21173 new ExternalStringData<uint8_t>(ext_array, peer, cback); |
| 21241 ASSERT(result.Length() == str_length); | 21174 ASSERT(result.Length() == str_length); |
| 21242 ASSERT(!result.HasHash() || | 21175 ASSERT(!result.HasHash() || |
| 21243 (result.Hash() == String::Hash(ext_array, str_length))); | 21176 (result.Hash() == String::Hash(ext_array, str_length))); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 21256 (str_length * kTwoByteChar)); | 21189 (str_length * kTwoByteChar)); |
| 21257 } | 21190 } |
| 21258 | 21191 |
| 21259 // If there is any left over space fill it with either an Array object or | 21192 // If there is any left over space fill it with either an Array object or |
| 21260 // just a plain object (depending on the amount of left over space) so | 21193 // just a plain object (depending on the amount of left over space) so |
| 21261 // that it can be traversed over successfully during garbage collection. | 21194 // that it can be traversed over successfully during garbage collection. |
| 21262 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | 21195 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
| 21263 | 21196 |
| 21264 // Update the class information of the object. | 21197 // Update the class information of the object. |
| 21265 const intptr_t class_id = kExternalTwoByteStringCid; | 21198 const intptr_t class_id = kExternalTwoByteStringCid; |
| 21266 uint32_t tags = raw_ptr()->tags_; | 21199 uword tags = raw_ptr()->tags_; |
| 21267 uint32_t old_tags; | 21200 uword old_tags; |
| 21268 do { | 21201 do { |
| 21269 old_tags = tags; | 21202 old_tags = tags; |
| 21270 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | 21203 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); |
| 21271 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | 21204 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); |
| 21272 tags = CompareAndSwapTags(old_tags, new_tags); | 21205 tags = CompareAndSwapTags(old_tags, new_tags); |
| 21273 } while (tags != old_tags); | 21206 } while (tags != old_tags); |
| 21274 result = this->raw(); | 21207 result = this->raw(); |
| 21275 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); | 21208 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); |
| 21276 ExternalStringData<uint16_t>* ext_data = | 21209 ExternalStringData<uint16_t>* ext_data = |
| 21277 new ExternalStringData<uint16_t>(ext_array, peer, cback); | 21210 new ExternalStringData<uint16_t>(ext_array, peer, cback); |
| 21278 ASSERT(result.Length() == str_length); | 21211 ASSERT(result.Length() == str_length); |
| 21279 ASSERT(!result.HasHash() || | 21212 ASSERT(!result.HasHash() || |
| 21280 (result.Hash() == String::Hash(ext_array, str_length))); | 21213 (result.Hash() == String::Hash(ext_array, str_length))); |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22148 } | 22081 } |
| 22149 | 22082 |
| 22150 return dest.raw(); | 22083 return dest.raw(); |
| 22151 } | 22084 } |
| 22152 | 22085 |
| 22153 | 22086 |
| 22154 void Array::MakeImmutable() const { | 22087 void Array::MakeImmutable() const { |
| 22155 if (IsImmutable()) return; | 22088 if (IsImmutable()) return; |
| 22156 ASSERT(!IsCanonical()); | 22089 ASSERT(!IsCanonical()); |
| 22157 NoSafepointScope no_safepoint; | 22090 NoSafepointScope no_safepoint; |
| 22158 uint32_t tags = raw_ptr()->tags_; | 22091 uword tags = raw_ptr()->tags_; |
| 22159 uint32_t old_tags; | 22092 uword old_tags; |
| 22160 do { | 22093 do { |
| 22161 old_tags = tags; | 22094 old_tags = tags; |
| 22162 uint32_t new_tags = | 22095 uword new_tags = |
| 22163 RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags); | 22096 RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags); |
| 22164 tags = CompareAndSwapTags(old_tags, new_tags); | 22097 tags = CompareAndSwapTags(old_tags, new_tags); |
| 22165 } while (tags != old_tags); | 22098 } while (tags != old_tags); |
| 22166 } | 22099 } |
| 22167 | 22100 |
| 22168 | 22101 |
| 22169 const char* Array::ToCString() const { | 22102 const char* Array::ToCString() const { |
| 22170 if (IsNull()) { | 22103 if (IsNull()) { |
| 22171 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; | 22104 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; |
| 22172 } | 22105 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22217 | 22150 |
| 22218 // The backing array may be a shared instance, or may not have correct | 22151 // The backing array may be a shared instance, or may not have correct |
| 22219 // type parameters. Create a new empty array. | 22152 // type parameters. Create a new empty array. |
| 22220 Heap::Space space = thread->IsMutatorThread() ? Heap::kNew : Heap::kOld; | 22153 Heap::Space space = thread->IsMutatorThread() ? Heap::kNew : Heap::kOld; |
| 22221 Array& array = Array::Handle(zone, Array::New(0, space)); | 22154 Array& array = Array::Handle(zone, Array::New(0, space)); |
| 22222 array.SetTypeArguments(type_arguments); | 22155 array.SetTypeArguments(type_arguments); |
| 22223 return array.raw(); | 22156 return array.raw(); |
| 22224 } | 22157 } |
| 22225 intptr_t capacity_len = growable_array.Capacity(); | 22158 intptr_t capacity_len = growable_array.Capacity(); |
| 22226 const Array& array = Array::Handle(zone, growable_array.data()); | 22159 const Array& array = Array::Handle(zone, growable_array.data()); |
| 22227 ASSERT(array.IsArray()); | |
| 22228 array.SetTypeArguments(type_arguments); | 22160 array.SetTypeArguments(type_arguments); |
| 22229 intptr_t capacity_size = Array::InstanceSize(capacity_len); | 22161 intptr_t capacity_size = Array::InstanceSize(capacity_len); |
| 22230 intptr_t used_size = Array::InstanceSize(used_len); | 22162 intptr_t used_size = Array::InstanceSize(used_len); |
| 22231 NoSafepointScope no_safepoint; | 22163 NoSafepointScope no_safepoint; |
| 22232 | 22164 |
| 22233 // If there is any left over space fill it with either an Array object or | 22165 // If there is any left over space fill it with either an Array object or |
| 22234 // just a plain object (depending on the amount of left over space) so | 22166 // just a plain object (depending on the amount of left over space) so |
| 22235 // that it can be traversed over successfully during garbage collection. | 22167 // that it can be traversed over successfully during garbage collection. |
| 22236 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); | 22168 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); |
| 22237 | 22169 |
| 22238 // Update the size in the header field and length of the array object. | 22170 // Update the size in the header field and length of the array object. |
| 22239 uword tags = array.raw_ptr()->tags_; | 22171 uword tags = array.raw_ptr()->tags_; |
| 22240 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); | 22172 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); |
| 22241 uint32_t old_tags; | 22173 uword old_tags; |
| 22242 do { | 22174 do { |
| 22243 old_tags = tags; | 22175 old_tags = tags; |
| 22244 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | 22176 uword new_tags = RawObject::SizeTag::update(used_size, old_tags); |
| 22245 tags = array.CompareAndSwapTags(old_tags, new_tags); | 22177 tags = array.CompareAndSwapTags(old_tags, new_tags); |
| 22246 } while (tags != old_tags); | 22178 } while (tags != old_tags); |
| 22247 // TODO(22501): For the heap to remain walkable by the sweeper, it must | 22179 // TODO(22501): For the heap to remain walkable by the sweeper, it must |
| 22248 // observe the creation of the filler object no later than the new length | 22180 // observe the creation of the filler object no later than the new length |
| 22249 // of the array. This assumption holds on ia32/x64 or if the CAS above is a | 22181 // of the array. This assumption holds on ia32/x64 or if the CAS above is a |
| 22250 // full memory barrier. | 22182 // full memory barrier. |
| 22251 // | 22183 // |
| 22252 // Also, between the CAS of the header above and the SetLength below, | 22184 // Also, between the CAS of the header above and the SetLength below, |
| 22253 // the array is temporarily in an inconsistent state. The header is considered | 22185 // the array is temporarily in an inconsistent state. The header is considered |
| 22254 // the overriding source of object size by RawObject::Size, but the ASSERTs | 22186 // the overriding source of object size by RawObject::Size, but the ASSERTs |
| (...skipping 1315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 23570 return UserTag::null(); | 23502 return UserTag::null(); |
| 23571 } | 23503 } |
| 23572 | 23504 |
| 23573 | 23505 |
| 23574 const char* UserTag::ToCString() const { | 23506 const char* UserTag::ToCString() const { |
| 23575 const String& tag_label = String::Handle(label()); | 23507 const String& tag_label = String::Handle(label()); |
| 23576 return tag_label.ToCString(); | 23508 return tag_label.ToCString(); |
| 23577 } | 23509 } |
| 23578 | 23510 |
| 23579 } // namespace dart | 23511 } // namespace dart |
| OLD | NEW |