template<class T> inlinevoid ObjectArray<T>::AssignableMemmove(int32_t dst_pos,
ObjPtr<ObjectArray<T>> src,
int32_t src_pos,
int32_t count) { if (kIsDebugBuild) { for (int i = 0; i < count; ++i) { // The get will perform the VerifyObject.
src->GetWithoutChecks(src_pos + i);
}
} // 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."); // 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. constbool copy_forward = (src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count); if (copy_forward) { // Forward copy. bool baker_non_gray_case = false; if (gUseReadBarrier && kUseBakerReadBarrier) {
uintptr_t fake_address_dependency; if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
baker_non_gray_case = true;
DCHECK_EQ(fake_address_dependency, 0U);
src.Assign(reinterpret_cast<ObjectArray<T>*>( reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency)); for (int i = 0; i < count; ++i) { // We can skip the RB here because 'src' isn't gray.
ObjPtr<T> obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
src_pos + i);
SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
}
} if (!baker_non_gray_case) { for (int i = 0; i < count; ++i) { // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
}
} else { // Backward copy. bool baker_non_gray_case = false; if (gUseReadBarrier && kUseBakerReadBarrier) {
uintptr_t fake_address_dependency; if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
baker_non_gray_case = true;
DCHECK_EQ(fake_address_dependency, 0U);
src.Assign(reinterpret_cast<ObjectArray<T>*>( reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency)); for (int i = count - 1; i >= 0; --i) { // We can skip the RB here because 'src' isn't gray.
ObjPtr<T> obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
src_pos + i);
SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
}
} if (!baker_non_gray_case) { for (int i = count - 1; i >= 0; --i) { // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
}
}
WriteBarrier::ForArrayWrite(this, dst_pos, count); if (kIsDebugBuild) { for (int i = 0; i < count; ++i) { // The get will perform the VerifyObject.
GetWithoutChecks(dst_pos + i);
}
}
}
template<class T> inlinevoid ObjectArray<T>::AssignableMemcpy(int32_t dst_pos,
ObjPtr<ObjectArray<T>> src,
int32_t src_pos,
int32_t count) { if (kIsDebugBuild) { for (int i = 0; i < count; ++i) { // The get will perform the VerifyObject.
src->GetWithoutChecks(src_pos + i);
}
} // 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."); // 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. bool baker_non_gray_case = false; if (gUseReadBarrier && kUseBakerReadBarrier) {
uintptr_t fake_address_dependency; if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
baker_non_gray_case = true;
DCHECK_EQ(fake_address_dependency, 0U);
src.Assign(reinterpret_cast<ObjectArray<T>*>( reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency)); for (int i = 0; i < count; ++i) { // We can skip the RB here because 'src' isn't gray.
ObjPtr<Object> obj =
src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(src_pos + i);
SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
}
} if (!baker_non_gray_case) { for (int i = 0; i < count; ++i) { // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
}
}
WriteBarrier::ForArrayWrite(this, dst_pos, count); if (kIsDebugBuild) { for (int i = 0; i < count; ++i) { // The get will perform the VerifyObject.
GetWithoutChecks(dst_pos + i);
}
}
}
template<class T> template<bool kTransactionActive> inlinevoid ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos,
ObjPtr<ObjectArray<T>> src,
int32_t src_pos,
int32_t count, bool throw_exception) {
DCHECK_NE(this, src)
<< "This case should be handled with memmove that handles overlaps correctly"; // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that // we know is assignable to the destination array's component type.
ObjPtr<Class> dst_class = GetClass()->GetComponentType();
ObjPtr<Class> lastAssignableElementClass = dst_class;
ObjPtr<T> o = nullptr; int i = 0; bool baker_non_gray_case = false; if (gUseReadBarrier && kUseBakerReadBarrier) {
uintptr_t fake_address_dependency; if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
baker_non_gray_case = true;
DCHECK_EQ(fake_address_dependency, 0U);
src.Assign(reinterpret_cast<ObjectArray<T>*>( reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency)); for (; i < count; ++i) { // The follow get operations force the objects to be verified. // We can skip the RB here because 'src' isn't gray.
o = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
src_pos + i); if (o == nullptr) { // Null is always assignable.
SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
} else { // TODO: use the underlying class reference to avoid uncompression when not necessary.
ObjPtr<Class> o_class = o->GetClass(); if (LIKELY(lastAssignableElementClass == o_class)) {
SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
} elseif (LIKELY(dst_class->IsAssignableFrom(o_class))) {
lastAssignableElementClass = o_class;
SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
} else { // Can't put this element into the array, break to perform write-barrier and throw // exception. break;
}
}
}
}
} if (!baker_non_gray_case) { 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.
SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
} else { // TODO: use the underlying class reference to avoid uncompression when not necessary.
ObjPtr<Class> o_class = o->GetClass(); if (LIKELY(lastAssignableElementClass == o_class)) {
SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
} elseif (LIKELY(dst_class->IsAssignableFrom(o_class))) {
lastAssignableElementClass = o_class;
SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
} else { // Can't put this element into the array, break to perform write-barrier and throw // exception. break;
}
}
}
}
WriteBarrier::ForArrayWrite(this, dst_pos, count); if (UNLIKELY(i != count)) {
std::string actualSrcType(mirror::Object::PrettyTypeOf(o));
std::string dstType(PrettyTypeOf());
Thread* self = Thread::Current();
std::string msg = android::base::StringPrintf( "source[%d] of type %s cannot be stored in destination array of type %s",
src_pos + i,
actualSrcType.c_str(),
dstType.c_str()); if (throw_exception) {
self->ThrowNewException("Ljava/lang/ArrayStoreException;", msg.c_str());
} else {
LOG(FATAL) << msg;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.