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

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

Issue 529823002: - Add AtomicOperations::CompareAndSwapWord (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 791
792 // Set up names for object array and one byte string class which are 792 // Set up names for object array and one byte string class which are
793 // pre-allocated in the vm isolate also. 793 // pre-allocated in the vm isolate also.
794 cls = Dart::vm_isolate()->object_store()->array_class(); 794 cls = Dart::vm_isolate()->object_store()->array_class();
795 cls.set_name(Symbols::_List()); 795 cls.set_name(Symbols::_List());
796 cls = Dart::vm_isolate()->object_store()->one_byte_string_class(); 796 cls = Dart::vm_isolate()->object_store()->one_byte_string_class();
797 cls.set_name(Symbols::OneByteString()); 797 cls.set_name(Symbols::OneByteString());
798 } 798 }
799 799
800 800
801 // Make unused space in an object whose type has been transformed safe 801 // Make unused space in an object whose type has been transformed safe
koda 2014/09/02 04:18:31 Update comment to reflect that this method must no
802 // for traversing during GC. 802 // for traversing during GC.
803 // The unused part of the transformed object is marked as an TypedDataInt8Array 803 // The unused part of the transformed object is marked as an TypedDataInt8Array
804 // object. 804 // object.
805 void Object::MakeUnusedSpaceTraversable(const Object& obj, 805 void Object::MakeUnusedSpaceTraversable(const Object& obj,
806 intptr_t original_size, 806 intptr_t original_size,
807 intptr_t used_size) { 807 intptr_t used_size) {
808 ASSERT(Isolate::Current()->no_gc_scope_depth() > 0); 808 ASSERT(Isolate::Current()->no_gc_scope_depth() > 0);
809 ASSERT(!obj.IsNull()); 809 ASSERT(!obj.IsNull());
810 ASSERT(original_size >= used_size); 810 ASSERT(original_size >= used_size);
811 if (original_size > used_size) { 811 if (original_size > used_size) {
812 intptr_t leftover_size = original_size - used_size; 812 intptr_t leftover_size = original_size - used_size;
813 813
814 uword addr = RawObject::ToAddr(obj.raw()) + used_size; 814 uword addr = RawObject::ToAddr(obj.raw()) + used_size;
815 if (leftover_size >= TypedData::InstanceSize(0)) { 815 if (leftover_size >= TypedData::InstanceSize(0)) {
816 // Update the leftover space as an TypedDataInt8Array object. 816 // Update the leftover space as a TypedDataInt8Array object.
817 RawTypedData* raw = 817 RawTypedData* raw =
818 reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr)); 818 reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr));
819 uword tags = 0; 819 uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0);
820 tags = RawObject::SizeTag::update(leftover_size, tags); 820 new_tags = RawObject::SizeTag::update(leftover_size, new_tags);
821 tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, tags); 821 uword tags = raw->ptr()->tags_;
822 raw->ptr()->tags_ = tags; 822 uword old_tags;
823 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary.
koda 2014/09/02 04:18:31 As long as this update happens strictly before the
824 do {
825 old_tags = tags;
826 tags = AtomicOperations::CompareAndSwapWord(
827 &raw->ptr()->tags_, old_tags, new_tags);
828 } while (tags != old_tags);
829
823 intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0)); 830 intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
824 ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size); 831 ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size);
825 raw->ptr()->length_ = Smi::New(leftover_len); 832 raw->ptr()->length_ = Smi::New(leftover_len);
826 } else { 833 } else {
827 // Update the leftover space as a basic object. 834 // Update the leftover space as a basic object.
828 ASSERT(leftover_size == Object::InstanceSize()); 835 ASSERT(leftover_size == Object::InstanceSize());
829 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); 836 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
830 uword tags = 0; 837 uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0);
831 tags = RawObject::SizeTag::update(leftover_size, tags); 838 new_tags = RawObject::SizeTag::update(leftover_size, new_tags);
832 tags = RawObject::ClassIdTag::update(kInstanceCid, tags); 839 uword tags = raw->ptr()->tags_;
833 raw->ptr()->tags_ = tags; 840 uword old_tags;
841 // TODO(iposva): Investigate whether CompareAndSwapWord is necessary.
842 do {
843 old_tags = tags;
844 tags = AtomicOperations::CompareAndSwapWord(
845 &raw->ptr()->tags_, old_tags, new_tags);
846 } while (tags != old_tags);
834 } 847 }
835 } 848 }
836 } 849 }
837 850
838 851
839 void Object::VerifyBuiltinVtables() { 852 void Object::VerifyBuiltinVtables() {
840 #if defined(DEBUG) 853 #if defined(DEBUG)
841 Isolate* isolate = Isolate::Current(); 854 Isolate* isolate = Isolate::Current();
842 ASSERT(isolate != NULL); 855 ASSERT(isolate != NULL);
843 Class& cls = Class::Handle(isolate, Class::null()); 856 Class& cls = Class::Handle(isolate, Class::null());
(...skipping 16343 matching lines...) Expand 10 before | Expand all | Expand 10 after
17187 Dart_PeerFinalizer cback) const { 17200 Dart_PeerFinalizer cback) const {
17188 String& result = String::Handle(); 17201 String& result = String::Handle();
17189 void* external_data; 17202 void* external_data;
17190 Dart_WeakPersistentHandleFinalizer finalizer; 17203 Dart_WeakPersistentHandleFinalizer finalizer;
17191 { 17204 {
17192 NoGCScope no_gc; 17205 NoGCScope no_gc;
17193 ASSERT(array != NULL); 17206 ASSERT(array != NULL);
17194 intptr_t str_length = this->Length(); 17207 intptr_t str_length = this->Length();
17195 ASSERT(length >= (str_length * this->CharSize())); 17208 ASSERT(length >= (str_length * this->CharSize()));
17196 intptr_t class_id = raw()->GetClassId(); 17209 intptr_t class_id = raw()->GetClassId();
17197 intptr_t used_size = 0;
17198 intptr_t original_size = 0;
17199 uword tags = raw_ptr()->tags_;
17200 17210
17201 ASSERT(!InVMHeap()); 17211 ASSERT(!InVMHeap());
17202 if (class_id == kOneByteStringCid) { 17212 if (class_id == kOneByteStringCid) {
17203 used_size = ExternalOneByteString::InstanceSize(); 17213 intptr_t used_size = ExternalOneByteString::InstanceSize();
17204 original_size = OneByteString::InstanceSize(str_length); 17214 intptr_t original_size = OneByteString::InstanceSize(str_length);
17205 ASSERT(original_size >= used_size); 17215 ASSERT(original_size >= used_size);
17206 17216
17207 // Copy the data into the external array. 17217 // Copy the data into the external array.
17208 if (str_length > 0) { 17218 if (str_length > 0) {
17209 memmove(array, OneByteString::CharAddr(*this, 0), str_length); 17219 memmove(array, OneByteString::CharAddr(*this, 0), str_length);
17210 } 17220 }
17211 17221
17222 // If there is any left over space fill it with either an Array object or
koda 2014/09/02 04:18:31 is -> will be
17223 // just a plain object (depending on the amount of left over space) so
17224 // that it can be traversed over successfully during garbage collection.
17225 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
17226
17212 // Update the class information of the object. 17227 // Update the class information of the object.
17213 const intptr_t class_id = kExternalOneByteStringCid; 17228 const intptr_t class_id = kExternalOneByteStringCid;
17214 tags = RawObject::SizeTag::update(used_size, tags); 17229 uword tags = raw_ptr()->tags_;
17215 tags = RawObject::ClassIdTag::update(class_id, tags); 17230 uword old_tags;
17216 raw_ptr()->tags_ = tags; 17231 do {
17232 old_tags = tags;
17233 uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
17234 new_tags = RawObject::ClassIdTag::update(class_id, new_tags);
17235 tags = AtomicOperations::CompareAndSwapWord(
17236 &raw_ptr()->tags_, old_tags, new_tags);
17237 } while (tags != old_tags);
17217 result = this->raw(); 17238 result = this->raw();
17218 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); 17239 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array);
17219 ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>( 17240 ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
17220 ext_array, peer, cback); 17241 ext_array, peer, cback);
17221 ASSERT(result.Length() == str_length); 17242 ASSERT(result.Length() == str_length);
17222 ASSERT(!result.HasHash() || 17243 ASSERT(!result.HasHash() ||
17223 (result.Hash() == String::Hash(ext_array, str_length))); 17244 (result.Hash() == String::Hash(ext_array, str_length)));
17224 ExternalOneByteString::SetExternalData(result, ext_data); 17245 ExternalOneByteString::SetExternalData(result, ext_data);
17225 external_data = ext_data; 17246 external_data = ext_data;
17226 finalizer = ExternalOneByteString::Finalize; 17247 finalizer = ExternalOneByteString::Finalize;
17227 } else { 17248 } else {
17228 ASSERT(class_id == kTwoByteStringCid); 17249 ASSERT(class_id == kTwoByteStringCid);
17229 used_size = ExternalTwoByteString::InstanceSize(); 17250 intptr_t used_size = ExternalTwoByteString::InstanceSize();
17230 original_size = TwoByteString::InstanceSize(str_length); 17251 intptr_t original_size = TwoByteString::InstanceSize(str_length);
17231 ASSERT(original_size >= used_size); 17252 ASSERT(original_size >= used_size);
17232 17253
17233 // Copy the data into the external array. 17254 // Copy the data into the external array.
17234 if (str_length > 0) { 17255 if (str_length > 0) {
17235 memmove(array, 17256 memmove(array,
17236 TwoByteString::CharAddr(*this, 0), 17257 TwoByteString::CharAddr(*this, 0),
17237 (str_length * kTwoByteChar)); 17258 (str_length * kTwoByteChar));
17238 } 17259 }
17239 17260
17261 // If there is any left over space fill it with either an Array object or
koda 2014/09/02 04:18:31 Ditto.
17262 // just a plain object (depending on the amount of left over space) so
17263 // that it can be traversed over successfully during garbage collection.
17264 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
17265
17240 // Update the class information of the object. 17266 // Update the class information of the object.
17241 const intptr_t class_id = kExternalTwoByteStringCid; 17267 const intptr_t class_id = kExternalTwoByteStringCid;
17242 tags = RawObject::SizeTag::update(used_size, tags); 17268 uword tags = raw_ptr()->tags_;
17243 tags = RawObject::ClassIdTag::update(class_id, tags); 17269 uword old_tags;
17244 raw_ptr()->tags_ = tags; 17270 do {
17271 old_tags = tags;
17272 uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
17273 new_tags = RawObject::ClassIdTag::update(class_id, new_tags);
17274 tags = AtomicOperations::CompareAndSwapWord(
17275 &raw_ptr()->tags_, old_tags, new_tags);
17276 } while (tags != old_tags);
17245 result = this->raw(); 17277 result = this->raw();
17246 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); 17278 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array);
17247 ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>( 17279 ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
17248 ext_array, peer, cback); 17280 ext_array, peer, cback);
17249 ASSERT(result.Length() == str_length); 17281 ASSERT(result.Length() == str_length);
17250 ASSERT(!result.HasHash() || 17282 ASSERT(!result.HasHash() ||
17251 (result.Hash() == String::Hash(ext_array, str_length))); 17283 (result.Hash() == String::Hash(ext_array, str_length)));
17252 ExternalTwoByteString::SetExternalData(result, ext_data); 17284 ExternalTwoByteString::SetExternalData(result, ext_data);
17253 external_data = ext_data; 17285 external_data = ext_data;
17254 finalizer = ExternalTwoByteString::Finalize; 17286 finalizer = ExternalTwoByteString::Finalize;
17255 } 17287 }
17256
17257 // If there is any left over space fill it with either an Array object or
17258 // just a plain object (depending on the amount of left over space) so
17259 // that it can be traversed over successfully during garbage collection.
17260 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
17261 } // NoGCScope 17288 } // NoGCScope
17262 AddFinalizer(result, external_data, finalizer); 17289 AddFinalizer(result, external_data, finalizer);
17263 return this->raw(); 17290 return this->raw();
17264 } 17291 }
17265 17292
17266 17293
17267 RawString* String::Transform(int32_t (*mapping)(int32_t ch), 17294 RawString* String::Transform(int32_t (*mapping)(int32_t ch),
17268 const String& str, 17295 const String& str,
17269 Heap::Space space) { 17296 Heap::Space space) {
17270 ASSERT(!str.IsNull()); 17297 ASSERT(!str.IsNull());
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
18066 NoGCScope no_gc; 18093 NoGCScope no_gc;
18067 raw->ptr()->length_ = Smi::New(len); 18094 raw->ptr()->length_ = Smi::New(len);
18068 return raw; 18095 return raw;
18069 } 18096 }
18070 } 18097 }
18071 18098
18072 18099
18073 void Array::MakeImmutable() const { 18100 void Array::MakeImmutable() const {
18074 NoGCScope no_gc; 18101 NoGCScope no_gc;
18075 uword tags = raw_ptr()->tags_; 18102 uword tags = raw_ptr()->tags_;
18076 tags = RawObject::ClassIdTag::update(kImmutableArrayCid, tags); 18103 uword old_tags;
18077 raw_ptr()->tags_ = tags; 18104 do {
18105 old_tags = tags;
18106 uword new_tags = RawObject::ClassIdTag::update(kImmutableArrayCid,
18107 old_tags);
18108 tags = AtomicOperations::CompareAndSwapWord(
18109 &raw_ptr()->tags_, old_tags, new_tags);
18110 } while (tags != old_tags);
18078 } 18111 }
18079 18112
18080 18113
18081 const char* Array::ToCString() const { 18114 const char* Array::ToCString() const {
18082 if (IsNull()) { 18115 if (IsNull()) {
18083 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; 18116 return IsImmutable() ? "_ImmutableList NULL" : "_List NULL";
18084 } 18117 }
18085 const char* format = IsImmutable() ? 18118 const char* format = IsImmutable() ?
18086 "_ImmutableList len:%" Pd : "_List len:%" Pd; 18119 "_ImmutableList len:%" Pd : "_List len:%" Pd;
18087 intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1; 18120 intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
18148 return Object::empty_array().raw(); 18181 return Object::empty_array().raw();
18149 } 18182 }
18150 intptr_t capacity_len = growable_array.Capacity(); 18183 intptr_t capacity_len = growable_array.Capacity();
18151 Isolate* isolate = Isolate::Current(); 18184 Isolate* isolate = Isolate::Current();
18152 const Array& array = Array::Handle(isolate, growable_array.data()); 18185 const Array& array = Array::Handle(isolate, growable_array.data());
18153 array.SetTypeArguments(type_arguments); 18186 array.SetTypeArguments(type_arguments);
18154 intptr_t capacity_size = Array::InstanceSize(capacity_len); 18187 intptr_t capacity_size = Array::InstanceSize(capacity_len);
18155 intptr_t used_size = Array::InstanceSize(used_len); 18188 intptr_t used_size = Array::InstanceSize(used_len);
18156 NoGCScope no_gc; 18189 NoGCScope no_gc;
18157 18190
18191 // If there is any left over space fill it with either an Array object or
koda 2014/09/02 04:18:31 Ditto.
18192 // just a plain object (depending on the amount of left over space) so
18193 // that it can be traversed over successfully during garbage collection.
18194 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);
18195
18158 // Update the size in the header field and length of the array object. 18196 // Update the size in the header field and length of the array object.
18159 uword tags = array.raw_ptr()->tags_; 18197 uword tags = array.raw_ptr()->tags_;
18160 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags)); 18198 ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags));
18161 tags = RawObject::SizeTag::update(used_size, tags); 18199 uword old_tags;
18162 array.raw_ptr()->tags_ = tags; 18200 do {
18201 old_tags = tags;
18202 uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
18203 tags = AtomicOperations::CompareAndSwapWord(
18204 &array.raw_ptr()->tags_, old_tags, new_tags);
18205 } while (tags != old_tags);
18163 array.SetLength(used_len); 18206 array.SetLength(used_len);
18164 18207
18165 // Null the GrowableObjectArray, we are removing it's backing array. 18208 // Null the GrowableObjectArray, we are removing it's backing array.
18166 growable_array.SetLength(0); 18209 growable_array.SetLength(0);
18167 growable_array.SetData(Object::empty_array()); 18210 growable_array.SetData(Object::empty_array());
18168 18211
18169 // If there is any left over space fill it with either an Array object or
18170 // just a plain object (depending on the amount of left over space) so
18171 // that it can be traversed over successfully during garbage collection.
18172 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);
18173
18174 return array.raw(); 18212 return array.raw();
18175 } 18213 }
18176 18214
18177 18215
18178 bool Array::CheckAndCanonicalizeFields(const char** error_str) const { 18216 bool Array::CheckAndCanonicalizeFields(const char** error_str) const {
18179 Object& obj = Object::Handle(); 18217 Object& obj = Object::Handle();
18180 // Iterate over all elements, canonicalize numbers and strings, expect all 18218 // Iterate over all elements, canonicalize numbers and strings, expect all
18181 // other instances to be canonical otherwise report error (return false). 18219 // other instances to be canonical otherwise report error (return false).
18182 for (intptr_t i = 0; i < Length(); i++) { 18220 for (intptr_t i = 0; i < Length(); i++) {
18183 obj = At(i); 18221 obj = At(i);
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
19582 return tag_label.ToCString(); 19620 return tag_label.ToCString();
19583 } 19621 }
19584 19622
19585 19623
19586 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 19624 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
19587 Instance::PrintJSONImpl(stream, ref); 19625 Instance::PrintJSONImpl(stream, ref);
19588 } 19626 }
19589 19627
19590 19628
19591 } // namespace dart 19629 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698