| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 DEFINE_FLAG(bool, | 78 DEFINE_FLAG(bool, |
| 79 remove_script_timestamps_for_test, | 79 remove_script_timestamps_for_test, |
| 80 false, | 80 false, |
| 81 "Remove script timestamps to allow for deterministic testing."); | 81 "Remove script timestamps to allow for deterministic testing."); |
| 82 | 82 |
| 83 DECLARE_FLAG(bool, show_invisible_frames); | 83 DECLARE_FLAG(bool, show_invisible_frames); |
| 84 DECLARE_FLAG(bool, trace_deoptimization); | 84 DECLARE_FLAG(bool, trace_deoptimization); |
| 85 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 85 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 86 DECLARE_FLAG(bool, trace_reload); | 86 DECLARE_FLAG(bool, trace_reload); |
| 87 DECLARE_FLAG(bool, write_protect_code); | 87 DECLARE_FLAG(bool, write_protect_code); |
| 88 DECLARE_FLAG(bool, support_externalizable_strings); | |
| 89 | 88 |
| 90 static const char* const kGetterPrefix = "get:"; | 89 static const char* const kGetterPrefix = "get:"; |
| 91 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); | 90 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); |
| 92 static const char* const kSetterPrefix = "set:"; | 91 static const char* const kSetterPrefix = "set:"; |
| 93 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); | 92 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); |
| 94 | 93 |
| 95 // A cache of VM heap allocated preinitialized empty ic data entry arrays. | 94 // A cache of VM heap allocated preinitialized empty ic data entry arrays. |
| 96 RawArray* ICData::cached_icdata_arrays_[kCachedICDataArrayCount]; | 95 RawArray* ICData::cached_icdata_arrays_[kCachedICDataArrayCount]; |
| 97 | 96 |
| 98 cpp_vtable Object::handle_vtable_ = 0; | 97 cpp_vtable Object::handle_vtable_ = 0; |
| (...skipping 8093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8192 return Thread::Current()->zone()->PrintToString( | 8191 return Thread::Current()->zone()->PrintToString( |
| 8193 "<%s [%" Pd " @%" Pd "]>", class_name, guarded_list_length(), | 8192 "<%s [%" Pd " @%" Pd "]>", class_name, guarded_list_length(), |
| 8194 guarded_list_length_in_object_offset()); | 8193 guarded_list_length_in_object_offset()); |
| 8195 } | 8194 } |
| 8196 } | 8195 } |
| 8197 | 8196 |
| 8198 return Thread::Current()->zone()->PrintToString( | 8197 return Thread::Current()->zone()->PrintToString( |
| 8199 "<%s %s>", is_nullable() ? "nullable" : "not-nullable", class_name); | 8198 "<%s %s>", is_nullable() ? "nullable" : "not-nullable", class_name); |
| 8200 } | 8199 } |
| 8201 | 8200 |
| 8202 bool Field::IsExternalizableCid(intptr_t cid) { | |
| 8203 if (FLAG_support_externalizable_strings) { | |
| 8204 return (cid == kOneByteStringCid) || (cid == kTwoByteStringCid); | |
| 8205 } else { | |
| 8206 return false; | |
| 8207 } | |
| 8208 } | |
| 8209 | |
| 8210 void Field::InitializeGuardedListLengthInObjectOffset() const { | 8201 void Field::InitializeGuardedListLengthInObjectOffset() const { |
| 8211 ASSERT(IsOriginal()); | 8202 ASSERT(IsOriginal()); |
| 8212 if (needs_length_check() && | 8203 if (needs_length_check() && |
| 8213 (guarded_list_length() != Field::kUnknownFixedLength)) { | 8204 (guarded_list_length() != Field::kUnknownFixedLength)) { |
| 8214 const intptr_t offset = GetListLengthOffset(guarded_cid()); | 8205 const intptr_t offset = GetListLengthOffset(guarded_cid()); |
| 8215 set_guarded_list_length_in_object_offset(offset); | 8206 set_guarded_list_length_in_object_offset(offset); |
| 8216 ASSERT(offset != Field::kUnknownLengthOffset); | 8207 ASSERT(offset != Field::kUnknownLengthOffset); |
| 8217 } else { | 8208 } else { |
| 8218 set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset); | 8209 set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset); |
| 8219 } | 8210 } |
| (...skipping 12065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20285 const Object& referent, | 20276 const Object& referent, |
| 20286 void* peer, | 20277 void* peer, |
| 20287 Dart_WeakPersistentHandleFinalizer callback, | 20278 Dart_WeakPersistentHandleFinalizer callback, |
| 20288 intptr_t external_size) { | 20279 intptr_t external_size) { |
| 20289 ASSERT((callback != NULL && peer != NULL) || | 20280 ASSERT((callback != NULL && peer != NULL) || |
| 20290 (callback == NULL && peer == NULL)); | 20281 (callback == NULL && peer == NULL)); |
| 20291 return FinalizablePersistentHandle::New(Isolate::Current(), referent, peer, | 20282 return FinalizablePersistentHandle::New(Isolate::Current(), referent, peer, |
| 20292 callback, external_size); | 20283 callback, external_size); |
| 20293 } | 20284 } |
| 20294 | 20285 |
| 20295 RawString* String::MakeExternal(void* array, | |
| 20296 intptr_t external_size, | |
| 20297 void* peer, | |
| 20298 Dart_PeerFinalizer cback) const { | |
| 20299 ASSERT(FLAG_support_externalizable_strings); | |
| 20300 String& result = String::Handle(); | |
| 20301 void* external_data; | |
| 20302 Dart_WeakPersistentHandleFinalizer finalizer; | |
| 20303 { | |
| 20304 NoSafepointScope no_safepoint; | |
| 20305 ASSERT(array != NULL); | |
| 20306 intptr_t str_length = this->Length(); | |
| 20307 ASSERT(external_size >= (str_length * this->CharSize())); | |
| 20308 intptr_t class_id = raw()->GetClassId(); | |
| 20309 | |
| 20310 ASSERT(!InVMHeap()); | |
| 20311 if (class_id == kOneByteStringCid) { | |
| 20312 intptr_t used_size = ExternalOneByteString::InstanceSize(); | |
| 20313 intptr_t original_size = OneByteString::InstanceSize(str_length); | |
| 20314 ASSERT(original_size >= used_size); | |
| 20315 | |
| 20316 // Copy the data into the external array. | |
| 20317 if (str_length > 0) { | |
| 20318 memmove(array, OneByteString::CharAddr(*this, 0), str_length); | |
| 20319 } | |
| 20320 | |
| 20321 // If there is any left over space fill it with either an Array object or | |
| 20322 // just a plain object (depending on the amount of left over space) so | |
| 20323 // that it can be traversed over successfully during garbage collection. | |
| 20324 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | |
| 20325 | |
| 20326 // Update the class information of the object. | |
| 20327 const intptr_t class_id = kExternalOneByteStringCid; | |
| 20328 uint32_t tags = raw_ptr()->tags_; | |
| 20329 uint32_t old_tags; | |
| 20330 do { | |
| 20331 old_tags = tags; | |
| 20332 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | |
| 20333 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | |
| 20334 tags = CompareAndSwapTags(old_tags, new_tags); | |
| 20335 } while (tags != old_tags); | |
| 20336 result = this->raw(); | |
| 20337 const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array); | |
| 20338 ExternalStringData<uint8_t>* ext_data = | |
| 20339 new ExternalStringData<uint8_t>(ext_array, peer, cback); | |
| 20340 ASSERT(result.Length() == str_length); | |
| 20341 ASSERT(!result.HasHash() || | |
| 20342 (result.Hash() == String::Hash(ext_array, str_length))); | |
| 20343 ExternalOneByteString::SetExternalData(result, ext_data); | |
| 20344 external_data = ext_data; | |
| 20345 finalizer = ExternalOneByteString::Finalize; | |
| 20346 } else { | |
| 20347 ASSERT(class_id == kTwoByteStringCid); | |
| 20348 intptr_t used_size = ExternalTwoByteString::InstanceSize(); | |
| 20349 intptr_t original_size = TwoByteString::InstanceSize(str_length); | |
| 20350 ASSERT(original_size >= used_size); | |
| 20351 | |
| 20352 // Copy the data into the external array. | |
| 20353 if (str_length > 0) { | |
| 20354 memmove(array, TwoByteString::CharAddr(*this, 0), | |
| 20355 (str_length * kTwoByteChar)); | |
| 20356 } | |
| 20357 | |
| 20358 // If there is any left over space fill it with either an Array object or | |
| 20359 // just a plain object (depending on the amount of left over space) so | |
| 20360 // that it can be traversed over successfully during garbage collection. | |
| 20361 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); | |
| 20362 | |
| 20363 // Update the class information of the object. | |
| 20364 const intptr_t class_id = kExternalTwoByteStringCid; | |
| 20365 uint32_t tags = raw_ptr()->tags_; | |
| 20366 uint32_t old_tags; | |
| 20367 do { | |
| 20368 old_tags = tags; | |
| 20369 uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags); | |
| 20370 new_tags = RawObject::ClassIdTag::update(class_id, new_tags); | |
| 20371 tags = CompareAndSwapTags(old_tags, new_tags); | |
| 20372 } while (tags != old_tags); | |
| 20373 result = this->raw(); | |
| 20374 const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array); | |
| 20375 ExternalStringData<uint16_t>* ext_data = | |
| 20376 new ExternalStringData<uint16_t>(ext_array, peer, cback); | |
| 20377 ASSERT(result.Length() == str_length); | |
| 20378 ASSERT(!result.HasHash() || | |
| 20379 (result.Hash() == String::Hash(ext_array, str_length))); | |
| 20380 ExternalTwoByteString::SetExternalData(result, ext_data); | |
| 20381 external_data = ext_data; | |
| 20382 finalizer = ExternalTwoByteString::Finalize; | |
| 20383 } | |
| 20384 } // NoSafepointScope | |
| 20385 AddFinalizer(result, external_data, finalizer, external_size); | |
| 20386 return this->raw(); | |
| 20387 } | |
| 20388 | |
| 20389 RawString* String::Transform(int32_t (*mapping)(int32_t ch), | 20286 RawString* String::Transform(int32_t (*mapping)(int32_t ch), |
| 20390 const String& str, | 20287 const String& str, |
| 20391 Heap::Space space) { | 20288 Heap::Space space) { |
| 20392 ASSERT(!str.IsNull()); | 20289 ASSERT(!str.IsNull()); |
| 20393 bool has_mapping = false; | 20290 bool has_mapping = false; |
| 20394 int32_t dst_max = 0; | 20291 int32_t dst_max = 0; |
| 20395 CodePointIterator it(str); | 20292 CodePointIterator it(str); |
| 20396 while (it.Next()) { | 20293 while (it.Next()) { |
| 20397 int32_t src = it.Current(); | 20294 int32_t src = it.Current(); |
| 20398 int32_t dst = mapping(src); | 20295 int32_t dst = mapping(src); |
| (...skipping 2140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22539 } | 22436 } |
| 22540 return UserTag::null(); | 22437 return UserTag::null(); |
| 22541 } | 22438 } |
| 22542 | 22439 |
| 22543 const char* UserTag::ToCString() const { | 22440 const char* UserTag::ToCString() const { |
| 22544 const String& tag_label = String::Handle(label()); | 22441 const String& tag_label = String::Handle(label()); |
| 22545 return tag_label.ToCString(); | 22442 return tag_label.ToCString(); |
| 22546 } | 22443 } |
| 22547 | 22444 |
| 22548 } // namespace dart | 22445 } // namespace dart |
| OLD | NEW |