From 7971928828f6c429b5fb3a2fddfed05c3b20bdcc Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Thu, 10 Apr 2014 12:46:22 -0700 Subject: [PATCH] Insert read barriers in more places. Bug: 12687968 Change-Id: If3ffca4741e039f314ac848551c481d44cbcd3ca --- runtime/mirror/object.cc | 33 +++++++++++++++++++++++++++++++++ runtime/mirror/object_array-inl.h | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index d9155f530..be7e9f20e 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -39,6 +39,32 @@ namespace art { namespace mirror { +class CopyReferenceFieldsWithReadBarrierVisitor { + public: + explicit CopyReferenceFieldsWithReadBarrierVisitor(Object* dest_obj) + : dest_obj_(dest_obj) {} + + void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const + ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // GetFieldObject() contains a RB. + Object* ref = obj->GetFieldObject(offset, false); + // No WB here as a large object space does not have a card table + // coverage. Instead, cards will be marked separately. + dest_obj_->SetFieldObjectWithoutWriteBarrier(offset, ref, false); + } + + void operator()(mirror::Class* klass, mirror::Reference* ref) const + ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // Copy java.lang.ref.Reference.referent which isn't visited in + // Object::VisitReferences(). + DCHECK(klass->IsReferenceClass()); + this->operator()(ref, mirror::Reference::ReferentOffset(), false); + } + + private: + Object* const dest_obj_; +}; + static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* src, size_t num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Copy instance data. We assume memcpy copies by words. @@ -47,6 +73,13 @@ static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* sr byte* dst_bytes = reinterpret_cast(dest); size_t offset = sizeof(Object); memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset); + if (kUseBakerOrBrooksReadBarrier) { + // We need a RB here. After the memcpy that covers the whole + // object above, copy references fields one by one again with a + // RB. TODO: Optimize this later? + CopyReferenceFieldsWithReadBarrierVisitor visitor(dest); + src->VisitReferences(visitor, visitor); + } gc::Heap* heap = Runtime::Current()->GetHeap(); // Perform write barriers on copied object references. Class* c = src->GetClass(); diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h index 8032cc367..e0c14c3ea 100644 --- a/runtime/mirror/object_array-inl.h +++ b/runtime/mirror/object_array-inl.h @@ -128,7 +128,27 @@ inline void ObjectArray::AssignableMemmove(int32_t dst_pos, ObjectArray* s CHECK_EQ(sizeof(HeapReference), sizeof(uint32_t)); IntArray* dstAsIntArray = reinterpret_cast(this); IntArray* srcAsIntArray = reinterpret_cast(src); - dstAsIntArray->Memmove(dst_pos, srcAsIntArray, src_pos, count); + if (kUseBakerOrBrooksReadBarrier) { + // TODO: Optimize this later? + const bool copy_forward = (src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count); + if (copy_forward) { + // Forward copy. + for (int i = 0; i < count; ++i) { + // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB. + Object* obj = src->GetWithoutChecks(src_pos + i); + SetWithoutChecks(dst_pos + i, obj); + } + } else { + // Backward copy. + for (int i = count - 1; i >= 0; --i) { + // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB. + Object* obj = src->GetWithoutChecks(src_pos + i); + SetWithoutChecks(dst_pos + i, obj); + } + } + } else { + dstAsIntArray->Memmove(dst_pos, srcAsIntArray, src_pos, count); + } Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count); if (kIsDebugBuild) { for (int i = 0; i < count; ++i) { @@ -151,7 +171,16 @@ inline void ObjectArray::AssignableMemcpy(int32_t dst_pos, ObjectArray* sr CHECK_EQ(sizeof(HeapReference), sizeof(uint32_t)); IntArray* dstAsIntArray = reinterpret_cast(this); IntArray* srcAsIntArray = reinterpret_cast(src); - dstAsIntArray->Memcpy(dst_pos, srcAsIntArray, src_pos, count); + if (kUseBakerOrBrooksReadBarrier) { + // TODO: Optimize this later? + for (int i = 0; i < count; ++i) { + // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB. + T* obj = src->GetWithoutChecks(src_pos + i); + SetWithoutChecks(dst_pos + i, obj); + } + } else { + dstAsIntArray->Memcpy(dst_pos, srcAsIntArray, src_pos, count); + } Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count); if (kIsDebugBuild) { for (int i = 0; i < count; ++i) { @@ -176,6 +205,7 @@ inline void ObjectArray::AssignableCheckingMemcpy(int32_t dst_pos, ObjectArra int i = 0; for (; i < count; ++i) { // The follow get operations force the objects to be verified. + // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB. o = src->GetWithoutChecks(src_pos + i); if (o == nullptr) { // Null is always assignable. -- 2.11.0