Use art::Atomic for CopyObject
Just to be sure it doesn't get turned into memcpy.
Also avoid casting ObjectArray to IntArray. This is a strict aliasing
violation.
Bug: 32012820
Test: test-art-host
Change-Id: Icc5d4a758cb4f4e1686389bb0cb74ac08e554f04
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 8e49743..9d3c26e 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -86,14 +86,16 @@
DCHECK_ALIGNED(dst_bytes, sizeof(uintptr_t));
// Use word sized copies to begin.
while (num_bytes >= sizeof(uintptr_t)) {
- *reinterpret_cast<uintptr_t*>(dst_bytes) = *reinterpret_cast<uintptr_t*>(src_bytes);
+ reinterpret_cast<Atomic<uintptr_t>*>(dst_bytes)->StoreRelaxed(
+ reinterpret_cast<Atomic<uintptr_t>*>(src_bytes)->LoadRelaxed());
src_bytes += sizeof(uintptr_t);
dst_bytes += sizeof(uintptr_t);
num_bytes -= sizeof(uintptr_t);
}
// Copy possible 32 bit word.
if (sizeof(uintptr_t) != sizeof(uint32_t) && num_bytes >= sizeof(uint32_t)) {
- *reinterpret_cast<uint32_t*>(dst_bytes) = *reinterpret_cast<uint32_t*>(src_bytes);
+ reinterpret_cast<Atomic<uint32_t>*>(dst_bytes)->StoreRelaxed(
+ reinterpret_cast<Atomic<uint32_t>*>(src_bytes)->LoadRelaxed());
src_bytes += sizeof(uint32_t);
dst_bytes += sizeof(uint32_t);
num_bytes -= sizeof(uint32_t);
@@ -101,7 +103,8 @@
// Copy remaining bytes, avoid going past the end of num_bytes since there may be a redzone
// there.
while (num_bytes > 0) {
- *reinterpret_cast<uint8_t*>(dst_bytes) = *reinterpret_cast<uint8_t*>(src_bytes);
+ reinterpret_cast<Atomic<uint8_t>*>(dst_bytes)->StoreRelaxed(
+ reinterpret_cast<Atomic<uint8_t>*>(src_bytes)->LoadRelaxed());
src_bytes += sizeof(uint8_t);
dst_bytes += sizeof(uint8_t);
num_bytes -= sizeof(uint8_t);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index c3c5231..d5bc256 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -131,28 +131,24 @@
// Perform the memmove using int memmove then perform the write barrier.
static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
"art::mirror::HeapReference<T> and uint32_t have different sizes.");
- IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
- IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
- if (kUseReadBarrier) {
- // 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<false>(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<false>(dst_pos + i, obj);
- }
+ // TODO: Optimize this later?
+ // We can't use memmove since it does not handle read barriers and may do by per byte copying.
+ // See b/32012820.
+ 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);
+ SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
} else {
- dstAsIntArray->Memmove(dst_pos, srcAsIntArray, src_pos, count);
+ // 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);
+ SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
+ }
}
Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
if (kIsDebugBuild) {
@@ -175,17 +171,13 @@
// Perform the memmove using int memcpy then perform the write barrier.
static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
"art::mirror::HeapReference<T> and uint32_t have different sizes.");
- IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
- IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
- if (kUseReadBarrier) {
- // 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<false>(dst_pos + i, obj);
- }
- } else {
- dstAsIntArray->Memcpy(dst_pos, srcAsIntArray, src_pos, count);
+ // TODO: Optimize this later?
+ // We can't use memmove since it does not handle read barriers and may do by per byte copying.
+ // See b/32012820.
+ for (int i = 0; i < count; ++i) {
+ // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
+ T* obj = src->GetWithoutChecks(src_pos + i);
+ SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
if (kIsDebugBuild) {