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

Unified Diff: vm/object.cc

Issue 11360114: - Add functionality to morph a string into an external string (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « vm/object.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vm/object.cc
===================================================================
--- vm/object.cc (revision 14977)
+++ vm/object.cc (working copy)
@@ -474,6 +474,48 @@
}
+// Make unused space in an object whose type has been transformed safe
+// for traversing during GC.
+// The unused part of the transformed object is marked as an Array
+// object or a regular Object so that it can be traversed during garbage
+// collection.
+void Object::MakeUnusedSpaceTraversable(const Object& obj,
+ intptr_t original_size,
+ intptr_t used_size) {
+ ASSERT(Isolate::Current()->no_gc_scope_depth() > 0);
+ ASSERT(!obj.IsNull());
+ ASSERT(original_size >= used_size);
+ if (original_size > used_size) {
+ intptr_t leftover_size = original_size - used_size;
+
+ uword addr = RawObject::ToAddr(obj.raw()) + used_size;
+ if (leftover_size >= Array::InstanceSize(0)) {
+ // As we have enough space to use an array object, update the leftover
+ // space as an Array object.
+ RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
+ uword tags = 0;
+ tags = RawObject::SizeTag::update(leftover_size, tags);
+ tags = RawObject::ClassIdTag::update(kArrayCid, tags);
+ raw->ptr()->tags_ = tags;
+ intptr_t leftover_len =
+ ((leftover_size - Array::InstanceSize(0)) / kWordSize);
+ ASSERT(Array::InstanceSize(leftover_len) == leftover_size);
+ raw->ptr()->tags_ = tags;
+ raw->ptr()->length_ = Smi::New(leftover_len);
+ } else {
+ // Update the leftover space as a basic object.
+ ASSERT(leftover_size == Object::InstanceSize());
+ RawObject* raw =
+ reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
+ uword tags = 0;
+ tags = RawObject::SizeTag::update(leftover_size, tags);
+ tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
+ raw->ptr()->tags_ = tags;
+ }
+ }
+}
+
+
RawClass* Object::CreateAndRegisterInterface(const char* cname,
const Script& script,
const Library& lib) {
@@ -10384,6 +10426,91 @@
}
+static void AddFinalizer(const Object& referent,
+ void* peer,
+ Dart_WeakPersistentHandleFinalizer callback) {
+ ASSERT(callback != NULL);
+ ApiState* state = Isolate::Current()->api_state();
+ ASSERT(state != NULL);
+ FinalizablePersistentHandle* weak_ref =
+ state->weak_persistent_handles().AllocateHandle();
+ weak_ref->set_raw(referent);
+ weak_ref->set_peer(peer);
+ weak_ref->set_callback(callback);
+}
+
+
+RawString* String::MakeExternal(void* array,
+ intptr_t length,
+ void* peer,
+ Dart_PeerFinalizer cback) const {
+ ASSERT(array != NULL);
+ intptr_t str_length = this->Length();
+ ASSERT(length >= (str_length * this->CharSize()));
+ intptr_t class_id = raw()->GetClassId();
+ intptr_t used_size = 0;
+ intptr_t original_size = 0;
+ uword tags = 0;
+ NoGCScope no_gc;
+
+ if (class_id == kOneByteStringCid) {
+ used_size = ExternalOneByteString::InstanceSize();
+ original_size = OneByteString::InstanceSize(str_length);
+ ASSERT(original_size >= used_size);
+
+ // Copy the data into the external array.
+ if (str_length > 0) {
+ memmove(array, OneByteString::CharAddr(*this, 0), str_length);
+ }
+
+ // Update the class information of the object.
+ const intptr_t class_id = kExternalOneByteStringCid;
+ tags = RawObject::SizeTag::update(used_size, tags);
+ tags = RawObject::ClassIdTag::update(class_id, tags);
+ raw_ptr()->tags_ = tags;
+ const String& result = String::Handle(this->raw());
+ ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
+ reinterpret_cast<const uint8_t*>(array), peer, cback);
+ result.SetLength(str_length);
+ result.SetHash(0);
+ ExternalOneByteString::SetExternalData(result, ext_data);
+ AddFinalizer(result, ext_data, ExternalOneByteString::Finalize);
+ } else {
+ ASSERT(class_id == kTwoByteStringCid);
+ used_size = ExternalTwoByteString::InstanceSize();
+ original_size = TwoByteString::InstanceSize(str_length);
+ ASSERT(original_size >= used_size);
+
+ // Copy the data into the external array.
+ if (str_length > 0) {
+ memmove(array,
+ TwoByteString::CharAddr(*this, 0),
+ (str_length * kTwoByteChar));
+ }
+
+ // Update the class information of the object.
+ const intptr_t class_id = kExternalTwoByteStringCid;
+ tags = RawObject::SizeTag::update(used_size, tags);
+ tags = RawObject::ClassIdTag::update(class_id, tags);
+ raw_ptr()->tags_ = tags;
+ const String& result = String::Handle(this->raw());
+ ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
+ reinterpret_cast<const uint16_t*>(array), peer, cback);
+ result.SetLength(str_length);
+ result.SetHash(0);
+ ExternalTwoByteString::SetExternalData(result, ext_data);
+ AddFinalizer(result, ext_data, ExternalTwoByteString::Finalize);
+ }
+
+ // If there is any left over space fill it with either an Array object or
+ // just a plain object (depending on the amount of left over space) so
+ // that it can be traversed over successfully during garbage collection.
+ Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
+
+ return this->raw();
+}
+
+
RawString* String::Transform(int32_t (*mapping)(int32_t ch),
const String& str,
Heap::Space space) {
@@ -10774,20 +10901,6 @@
}
-static void AddFinalizer(const Object& referent,
- void* peer,
- Dart_WeakPersistentHandleFinalizer callback) {
- ASSERT(callback != NULL);
- ApiState* state = Isolate::Current()->api_state();
- ASSERT(state != NULL);
- FinalizablePersistentHandle* weak_ref =
- state->weak_persistent_handles().AllocateHandle();
- weak_ref->set_raw(referent);
- weak_ref->set_peer(peer);
- weak_ref->set_callback(callback);
-}
-
-
RawExternalOneByteString* ExternalOneByteString::New(
const uint8_t* data,
intptr_t len,
@@ -11017,33 +11130,8 @@
// If there is any left over space fill it with either an Array object or
// just a plain object (depending on the amount of left over space) so
// that it can be traversed over successfully during garbage collection.
- if (capacity_size != used_size) {
- ASSERT(capacity_len > used_len);
- intptr_t leftover_size = capacity_size - used_size;
+ Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);
- uword addr = RawObject::ToAddr(array.raw()) + used_size;
- if (leftover_size >= Array::InstanceSize(0)) {
- // As we have enough space to use an array object, update the leftover
- // space as an Array object.
- RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
- tags = 0;
- tags = RawObject::SizeTag::update(leftover_size, tags);
- tags = RawObject::ClassIdTag::update(kArrayCid, tags);
- raw->ptr()->tags_ = tags;
- intptr_t leftover_len =
- ((leftover_size - Array::InstanceSize(0)) / kWordSize);
- raw->ptr()->tags_ = tags;
- raw->ptr()->length_ = Smi::New(leftover_len);
- } else {
- // Update the leftover space as a basic object.
- ASSERT(leftover_size == Object::InstanceSize());
- RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
- tags = 0;
- tags = RawObject::SizeTag::update(leftover_size, tags);
- tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
- raw->ptr()->tags_ = tags;
- }
- }
return array.raw();
}
« no previous file with comments | « vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698