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

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

Issue 2912863006: Inline instance object hash code into object header on 64 bit. (Closed)
Patch Set: Add assembler tests and other feedback from Ryan Created 3 years, 6 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') | runtime/vm/profiler.cc » ('j') | 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/become.h" 10 #include "vm/become.h"
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698