Improve object clone performance and make compaction proof.

Bug: 11551604
Bug: 8981901

Change-Id: I60646d838dbb51e125303d1a8fe869191aa63e78
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 7d2441b..91909e4 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -300,6 +300,10 @@
     card_table_->MarkCard(dst);
   }
 
+  void WriteBarrierEveryFieldOf(const mirror::Object* obj) {
+    card_table_->MarkCard(obj);
+  }
+
   accounting::CardTable* GetCardTable() const {
     return card_table_.get();
   }
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 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() {