Chromium Code Reviews| 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/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |