| 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/bigint_operations.h" | 10 #include "vm/bigint_operations.h" |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 // pre-allocated in the vm isolate also. | 467 // pre-allocated in the vm isolate also. |
| 468 cls = Dart::vm_isolate()->object_store()->array_class(); | 468 cls = Dart::vm_isolate()->object_store()->array_class(); |
| 469 str = Symbols::ObjectArray(); | 469 str = Symbols::ObjectArray(); |
| 470 cls.set_name(str); | 470 cls.set_name(str); |
| 471 cls = Dart::vm_isolate()->object_store()->one_byte_string_class(); | 471 cls = Dart::vm_isolate()->object_store()->one_byte_string_class(); |
| 472 str = Symbols::OneByteString(); | 472 str = Symbols::OneByteString(); |
| 473 cls.set_name(str); | 473 cls.set_name(str); |
| 474 } | 474 } |
| 475 | 475 |
| 476 | 476 |
| 477 // Make unused space in an object whose type has been transformed safe |
| 478 // for traversing during GC. |
| 479 // The unused part of the transformed object is marked as an Array |
| 480 // object or a regular Object so that it can be traversed during garbage |
| 481 // collection. |
| 482 void Object::MakeUnusedSpaceTraversable(const Object& obj, |
| 483 intptr_t original_size, |
| 484 intptr_t used_size) { |
| 485 ASSERT(Isolate::Current()->no_gc_scope_depth() > 0); |
| 486 ASSERT(!obj.IsNull()); |
| 487 ASSERT(original_size >= used_size); |
| 488 if (original_size > used_size) { |
| 489 intptr_t leftover_size = original_size - used_size; |
| 490 |
| 491 uword addr = RawObject::ToAddr(obj.raw()) + used_size; |
| 492 if (leftover_size >= Array::InstanceSize(0)) { |
| 493 // As we have enough space to use an array object, update the leftover |
| 494 // space as an Array object. |
| 495 RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr)); |
| 496 uword tags = 0; |
| 497 tags = RawObject::SizeTag::update(leftover_size, tags); |
| 498 tags = RawObject::ClassIdTag::update(kArrayCid, tags); |
| 499 raw->ptr()->tags_ = tags; |
| 500 intptr_t leftover_len = |
| 501 ((leftover_size - Array::InstanceSize(0)) / kWordSize); |
| 502 ASSERT(Array::InstanceSize(leftover_len) == leftover_size); |
| 503 raw->ptr()->tags_ = tags; |
| 504 raw->ptr()->length_ = Smi::New(leftover_len); |
| 505 } else { |
| 506 // Update the leftover space as a basic object. |
| 507 ASSERT(leftover_size == Object::InstanceSize()); |
| 508 RawObject* raw = |
| 509 reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); |
| 510 uword tags = 0; |
| 511 tags = RawObject::SizeTag::update(leftover_size, tags); |
| 512 tags = RawObject::ClassIdTag::update(kInstanceCid, tags); |
| 513 raw->ptr()->tags_ = tags; |
| 514 } |
| 515 } |
| 516 } |
| 517 |
| 518 |
| 477 RawClass* Object::CreateAndRegisterInterface(const char* cname, | 519 RawClass* Object::CreateAndRegisterInterface(const char* cname, |
| 478 const Script& script, | 520 const Script& script, |
| 479 const Library& lib) { | 521 const Library& lib) { |
| 480 const String& name = String::Handle(Symbols::New(cname)); | 522 const String& name = String::Handle(Symbols::New(cname)); |
| 481 const Class& cls = Class::Handle( | 523 const Class& cls = Class::Handle( |
| 482 Class::NewInterface(name, script, Scanner::kDummyTokenIndex)); | 524 Class::NewInterface(name, script, Scanner::kDummyTokenIndex)); |
| 483 lib.AddClass(cls); | 525 lib.AddClass(cls); |
| 484 return cls.raw(); | 526 return cls.raw(); |
| 485 } | 527 } |
| 486 | 528 |
| (...skipping 9890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10377 if (obj.Length() > 0) { | 10419 if (obj.Length() > 0) { |
| 10378 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length()); | 10420 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length()); |
| 10379 } | 10421 } |
| 10380 } else { | 10422 } else { |
| 10381 ASSERT(array_len >= Utf8::Length(*this)); | 10423 ASSERT(array_len >= Utf8::Length(*this)); |
| 10382 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); | 10424 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); |
| 10383 } | 10425 } |
| 10384 } | 10426 } |
| 10385 | 10427 |
| 10386 | 10428 |
| 10429 static void AddFinalizer(const Object& referent, |
| 10430 void* peer, |
| 10431 Dart_WeakPersistentHandleFinalizer callback) { |
| 10432 ASSERT(callback != NULL); |
| 10433 ApiState* state = Isolate::Current()->api_state(); |
| 10434 ASSERT(state != NULL); |
| 10435 FinalizablePersistentHandle* weak_ref = |
| 10436 state->weak_persistent_handles().AllocateHandle(); |
| 10437 weak_ref->set_raw(referent); |
| 10438 weak_ref->set_peer(peer); |
| 10439 weak_ref->set_callback(callback); |
| 10440 } |
| 10441 |
| 10442 |
| 10443 RawString* String::MakeExternal(void* array, |
| 10444 intptr_t length, |
| 10445 void* peer, |
| 10446 Dart_PeerFinalizer cback) const { |
| 10447 ASSERT(array != NULL); |
| 10448 intptr_t str_length = this->Length(); |
| 10449 ASSERT(length >= (str_length * this->CharSize())); |
| 10450 intptr_t class_id = raw()->GetClassId(); |
| 10451 intptr_t used_size = 0; |
| 10452 intptr_t original_size = 0; |
| 10453 uword tags = 0; |
| 10454 NoGCScope no_gc; |
| 10455 |
| 10456 if (class_id == kOneByteStringCid) { |
| 10457 used_size = ExternalOneByteString::InstanceSize(); |
| 10458 original_size = OneByteString::InstanceSize(str_length); |
| 10459 ASSERT(original_size >= used_size); |
| 10460 |
| 10461 // Copy the data into the external array. |
| 10462 if (str_length > 0) { |
| 10463 memmove(array, OneByteString::CharAddr(*this, 0), str_length); |
| 10464 } |
| 10465 |
| 10466 // Update the class information of the object. |
| 10467 const intptr_t class_id = kExternalOneByteStringCid; |
| 10468 tags = RawObject::SizeTag::update(used_size, tags); |
| 10469 tags = RawObject::ClassIdTag::update(class_id, tags); |
| 10470 raw_ptr()->tags_ = tags; |
| 10471 const String& result = String::Handle(this->raw()); |
| 10472 ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>( |
| 10473 reinterpret_cast<const uint8_t*>(array), peer, cback); |
| 10474 result.SetLength(str_length); |
| 10475 result.SetHash(0); |
| 10476 ExternalOneByteString::SetExternalData(result, ext_data); |
| 10477 AddFinalizer(result, ext_data, ExternalOneByteString::Finalize); |
| 10478 } else { |
| 10479 ASSERT(class_id == kTwoByteStringCid); |
| 10480 used_size = ExternalTwoByteString::InstanceSize(); |
| 10481 original_size = TwoByteString::InstanceSize(str_length); |
| 10482 ASSERT(original_size >= used_size); |
| 10483 |
| 10484 // Copy the data into the external array. |
| 10485 if (str_length > 0) { |
| 10486 memmove(array, |
| 10487 TwoByteString::CharAddr(*this, 0), |
| 10488 (str_length * kTwoByteChar)); |
| 10489 } |
| 10490 |
| 10491 // Update the class information of the object. |
| 10492 const intptr_t class_id = kExternalTwoByteStringCid; |
| 10493 tags = RawObject::SizeTag::update(used_size, tags); |
| 10494 tags = RawObject::ClassIdTag::update(class_id, tags); |
| 10495 raw_ptr()->tags_ = tags; |
| 10496 const String& result = String::Handle(this->raw()); |
| 10497 ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>( |
| 10498 reinterpret_cast<const uint16_t*>(array), peer, cback); |
| 10499 result.SetLength(str_length); |
| 10500 result.SetHash(0); |
| 10501 ExternalTwoByteString::SetExternalData(result, ext_data); |
| 10502 AddFinalizer(result, ext_data, ExternalTwoByteString::Finalize); |
| 10503 } |
| 10504 |
| 10505 // If there is any left over space fill it with either an Array object or |
| 10506 // just a plain object (depending on the amount of left over space) so |
| 10507 // that it can be traversed over successfully during garbage collection. |
| 10508 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size); |
| 10509 |
| 10510 return this->raw(); |
| 10511 } |
| 10512 |
| 10513 |
| 10387 RawString* String::Transform(int32_t (*mapping)(int32_t ch), | 10514 RawString* String::Transform(int32_t (*mapping)(int32_t ch), |
| 10388 const String& str, | 10515 const String& str, |
| 10389 Heap::Space space) { | 10516 Heap::Space space) { |
| 10390 ASSERT(!str.IsNull()); | 10517 ASSERT(!str.IsNull()); |
| 10391 bool has_mapping = false; | 10518 bool has_mapping = false; |
| 10392 int32_t dst_max = 0; | 10519 int32_t dst_max = 0; |
| 10393 intptr_t len = str.Length(); | 10520 intptr_t len = str.Length(); |
| 10394 // TODO(cshapiro): assume a transform is required, rollback if not. | 10521 // TODO(cshapiro): assume a transform is required, rollback if not. |
| 10395 for (intptr_t i = 0; i < len; ++i) { | 10522 for (intptr_t i = 0; i < len; ++i) { |
| 10396 int32_t src = str.CharAt(i); | 10523 int32_t src = str.CharAt(i); |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10767 const String& result = String::Handle(TwoByteString::New(len, space)); | 10894 const String& result = String::Handle(TwoByteString::New(len, space)); |
| 10768 for (intptr_t i = 0; i < len; ++i) { | 10895 for (intptr_t i = 0; i < len; ++i) { |
| 10769 int32_t ch = mapping(str.CharAt(i)); | 10896 int32_t ch = mapping(str.CharAt(i)); |
| 10770 ASSERT(ch >= 0 && ch <= 0xFFFF); | 10897 ASSERT(ch >= 0 && ch <= 0xFFFF); |
| 10771 *CharAddr(result, i) = ch; | 10898 *CharAddr(result, i) = ch; |
| 10772 } | 10899 } |
| 10773 return TwoByteString::raw(result); | 10900 return TwoByteString::raw(result); |
| 10774 } | 10901 } |
| 10775 | 10902 |
| 10776 | 10903 |
| 10777 static void AddFinalizer(const Object& referent, | |
| 10778 void* peer, | |
| 10779 Dart_WeakPersistentHandleFinalizer callback) { | |
| 10780 ASSERT(callback != NULL); | |
| 10781 ApiState* state = Isolate::Current()->api_state(); | |
| 10782 ASSERT(state != NULL); | |
| 10783 FinalizablePersistentHandle* weak_ref = | |
| 10784 state->weak_persistent_handles().AllocateHandle(); | |
| 10785 weak_ref->set_raw(referent); | |
| 10786 weak_ref->set_peer(peer); | |
| 10787 weak_ref->set_callback(callback); | |
| 10788 } | |
| 10789 | |
| 10790 | |
| 10791 RawExternalOneByteString* ExternalOneByteString::New( | 10904 RawExternalOneByteString* ExternalOneByteString::New( |
| 10792 const uint8_t* data, | 10905 const uint8_t* data, |
| 10793 intptr_t len, | 10906 intptr_t len, |
| 10794 void* peer, | 10907 void* peer, |
| 10795 Dart_PeerFinalizer callback, | 10908 Dart_PeerFinalizer callback, |
| 10796 Heap::Space space) { | 10909 Heap::Space space) { |
| 10797 ASSERT(Isolate::Current()->object_store()-> | 10910 ASSERT(Isolate::Current()->object_store()-> |
| 10798 external_one_byte_string_class() != Class::null()); | 10911 external_one_byte_string_class() != Class::null()); |
| 10799 if (len < 0 || len > kMaxElements) { | 10912 if (len < 0 || len > kMaxElements) { |
| 10800 // This should be caught before we reach here. | 10913 // This should be caught before we reach here. |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11010 array.raw_ptr()->tags_ = tags; | 11123 array.raw_ptr()->tags_ = tags; |
| 11011 array.SetLength(used_len); | 11124 array.SetLength(used_len); |
| 11012 | 11125 |
| 11013 // Null the GrowableObjectArray, we are removing it's backing array. | 11126 // Null the GrowableObjectArray, we are removing it's backing array. |
| 11014 growable_array.SetLength(0); | 11127 growable_array.SetLength(0); |
| 11015 growable_array.SetData(new_array); | 11128 growable_array.SetData(new_array); |
| 11016 | 11129 |
| 11017 // If there is any left over space fill it with either an Array object or | 11130 // If there is any left over space fill it with either an Array object or |
| 11018 // just a plain object (depending on the amount of left over space) so | 11131 // just a plain object (depending on the amount of left over space) so |
| 11019 // that it can be traversed over successfully during garbage collection. | 11132 // that it can be traversed over successfully during garbage collection. |
| 11020 if (capacity_size != used_size) { | 11133 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); |
| 11021 ASSERT(capacity_len > used_len); | |
| 11022 intptr_t leftover_size = capacity_size - used_size; | |
| 11023 | 11134 |
| 11024 uword addr = RawObject::ToAddr(array.raw()) + used_size; | |
| 11025 if (leftover_size >= Array::InstanceSize(0)) { | |
| 11026 // As we have enough space to use an array object, update the leftover | |
| 11027 // space as an Array object. | |
| 11028 RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr)); | |
| 11029 tags = 0; | |
| 11030 tags = RawObject::SizeTag::update(leftover_size, tags); | |
| 11031 tags = RawObject::ClassIdTag::update(kArrayCid, tags); | |
| 11032 raw->ptr()->tags_ = tags; | |
| 11033 intptr_t leftover_len = | |
| 11034 ((leftover_size - Array::InstanceSize(0)) / kWordSize); | |
| 11035 raw->ptr()->tags_ = tags; | |
| 11036 raw->ptr()->length_ = Smi::New(leftover_len); | |
| 11037 } else { | |
| 11038 // Update the leftover space as a basic object. | |
| 11039 ASSERT(leftover_size == Object::InstanceSize()); | |
| 11040 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr)); | |
| 11041 tags = 0; | |
| 11042 tags = RawObject::SizeTag::update(leftover_size, tags); | |
| 11043 tags = RawObject::ClassIdTag::update(kInstanceCid, tags); | |
| 11044 raw->ptr()->tags_ = tags; | |
| 11045 } | |
| 11046 } | |
| 11047 return array.raw(); | 11135 return array.raw(); |
| 11048 } | 11136 } |
| 11049 | 11137 |
| 11050 | 11138 |
| 11051 RawImmutableArray* ImmutableArray::New(intptr_t len, | 11139 RawImmutableArray* ImmutableArray::New(intptr_t len, |
| 11052 Heap::Space space) { | 11140 Heap::Space space) { |
| 11053 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != | 11141 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != |
| 11054 Class::null()); | 11142 Class::null()); |
| 11055 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); | 11143 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); |
| 11056 } | 11144 } |
| (...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12003 } | 12091 } |
| 12004 return result.raw(); | 12092 return result.raw(); |
| 12005 } | 12093 } |
| 12006 | 12094 |
| 12007 | 12095 |
| 12008 const char* WeakProperty::ToCString() const { | 12096 const char* WeakProperty::ToCString() const { |
| 12009 return "_WeakProperty"; | 12097 return "_WeakProperty"; |
| 12010 } | 12098 } |
| 12011 | 12099 |
| 12012 } // namespace dart | 12100 } // namespace dart |
| OLD | NEW |