diff options
author | Mathieu Chartier <mathieuc@google.com> | 2013-11-06 11:02:50 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2013-11-06 11:15:42 -0800 |
commit | 0732d59d42523b8c2d807de3a380d2fbfa781364 (patch) | |
tree | 17b6bd9883bc52765e6a814271251b8fe56ac3df /runtime/mirror/object.cc | |
parent | 01a52c75ff92b24195b7f3455db80a0e02d50f9f (diff) | |
download | art-0732d59d42523b8c2d807de3a380d2fbfa781364.zip art-0732d59d42523b8c2d807de3a380d2fbfa781364.tar.gz art-0732d59d42523b8c2d807de3a380d2fbfa781364.tar.bz2 |
Improve object clone performance and make compaction proof.
Bug: 11551604
Bug: 8981901
Change-Id: I60646d838dbb51e125303d1a8fe869191aa63e78
Diffstat (limited to 'runtime/mirror/object.cc')
-rw-r--r-- | runtime/mirror/object.cc | 37 |
1 files changed, 14 insertions, 23 deletions
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index bd187c1..87d02c9 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -40,48 +40,39 @@ namespace art { namespace mirror { Object* Object::Clone(Thread* self) { - Class* c = GetClass(); + mirror::Class* c = GetClass(); DCHECK(!c->IsClassClass()); - // Object::SizeOf gets the right size even if we're an array. // Using c->AllocObject() here would be wrong. size_t num_bytes = SizeOf(); gc::Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes)); - if (copy.get() == NULL) { - return NULL; + SirtRef<mirror::Object> sirt_this(self, this); + Object* copy = heap->AllocObject(self, c, num_bytes); + if (UNLIKELY(copy == nullptr)) { + return nullptr; } - // Copy instance data. We assume memcpy copies by words. // TODO: expose and use move32. - byte* src_bytes = reinterpret_cast<byte*>(this); - byte* dst_bytes = reinterpret_cast<byte*>(copy.get()); + byte* src_bytes = reinterpret_cast<byte*>(sirt_this.get()); + byte* dst_bytes = reinterpret_cast<byte*>(copy); size_t offset = sizeof(Object); memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset); - // Perform write barriers on copied object references. + c = copy->GetClass(); // Re-read Class in case it moved. if (c->IsArrayClass()) { if (!c->GetComponentType()->IsPrimitive()) { const ObjectArray<Object>* array = copy->AsObjectArray<Object>(); - heap->WriteBarrierArray(copy.get(), 0, array->GetLength()); + heap->WriteBarrierArray(copy, 0, array->GetLength()); } } else { - for (const Class* klass = c; klass != NULL; klass = klass->GetSuperClass()) { - size_t num_reference_fields = klass->NumReferenceInstanceFields(); - for (size_t i = 0; i < num_reference_fields; ++i) { - ArtField* field = klass->GetInstanceField(i); - MemberOffset field_offset = field->GetOffset(); - const Object* ref = copy->GetFieldObject<const Object*>(field_offset, false); - heap->WriteBarrierField(copy.get(), field_offset, ref); - } - } + heap->WriteBarrierEveryFieldOf(copy); } - if (c->IsFinalizable()) { - heap->AddFinalizerReference(Thread::Current(), copy.get()); + SirtRef<mirror::Object> sirt_copy(self, copy); + heap->AddFinalizerReference(self, copy); + return sirt_copy.get(); } - - return copy.get(); + return copy; } int32_t Object::GenerateIdentityHashCode() { |