ART: Move DexCache arrays to native.
This CL has a companion CL in libcore/
https://android-review.googlesource.com/162985
Change-Id: Icbc9e20ad1b565e603195b12714762bb446515fa
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 4b5063a..f8ccfb1 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -21,6 +21,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
+#include "base/casts.h"
#include "base/logging.h"
#include "mirror/class.h"
#include "runtime.h"
@@ -33,29 +34,53 @@
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
}
-inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
- // TODO default transaction support.
- DCHECK(resolved == nullptr || !resolved->IsErroneous());
- GetResolvedTypes()->Set(type_idx, resolved);
+inline String* DexCache::GetResolvedString(uint32_t string_idx) {
+ DCHECK_LT(string_idx, NumStrings());
+ return GetStrings()[string_idx].Read();
}
-inline ArtField* DexCache::GetResolvedField(uint32_t idx, size_t ptr_size) {
+inline void DexCache::SetResolvedString(uint32_t string_idx, String* resolved) {
+ DCHECK_LT(string_idx, NumStrings());
+ // TODO default transaction support.
+ GetStrings()[string_idx] = GcRoot<String>(resolved);
+ // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
+ Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
+}
+
+inline Class* DexCache::GetResolvedType(uint32_t type_idx) {
+ DCHECK_LT(type_idx, NumResolvedTypes());
+ return GetResolvedTypes()[type_idx].Read();
+}
+
+inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
+ DCHECK_LT(type_idx, NumResolvedTypes()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ // TODO default transaction support.
+ DCHECK(resolved == nullptr || !resolved->IsErroneous());
+ GetResolvedTypes()[type_idx] = GcRoot<Class>(resolved);
+ // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
+ Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
+}
+
+inline ArtField* DexCache::GetResolvedField(uint32_t field_idx, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- auto* field = GetResolvedFields()->GetElementPtrSize<ArtField*>(idx, ptr_size);
+ DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ ArtField* field = GetElementPtrSize(GetResolvedFields(), field_idx, ptr_size);
if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) {
return nullptr;
}
return field;
}
-inline void DexCache::SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size) {
+inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- GetResolvedFields()->SetElementPtrSize(idx, field, ptr_size);
+ DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ SetElementPtrSize(GetResolvedFields(), field_idx, field, ptr_size);
}
inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- auto* method = GetResolvedMethods()->GetElementPtrSize<ArtMethod*>(method_idx, ptr_size);
+ DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ ArtMethod* method = GetElementPtrSize<ArtMethod*>(GetResolvedMethods(), method_idx, ptr_size);
// Hide resolution trampoline methods from the caller
if (method != nullptr && method->IsRuntimeMethod()) {
DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod());
@@ -64,9 +89,52 @@
return method;
}
-inline void DexCache::SetResolvedMethod(uint32_t idx, ArtMethod* method, size_t ptr_size) {
+inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method, size_t ptr_size) {
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
- GetResolvedMethods()->SetElementPtrSize(idx, method, ptr_size);
+ DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB.
+ SetElementPtrSize(GetResolvedMethods(), method_idx, method, ptr_size);
+}
+
+template <typename PtrType>
+inline PtrType DexCache::GetElementPtrSize(PtrType* ptr_array, size_t idx, size_t ptr_size) {
+ if (ptr_size == 8u) {
+ uint64_t element = reinterpret_cast<const uint64_t*>(ptr_array)[idx];
+ return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element));
+ } else {
+ DCHECK_EQ(ptr_size, 4u);
+ uint32_t element = reinterpret_cast<const uint32_t*>(ptr_array)[idx];
+ return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element));
+ }
+}
+
+template <typename PtrType>
+inline void DexCache::SetElementPtrSize(PtrType* ptr_array,
+ size_t idx,
+ PtrType ptr,
+ size_t ptr_size) {
+ if (ptr_size == 8u) {
+ reinterpret_cast<uint64_t*>(ptr_array)[idx] =
+ dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
+ } else {
+ DCHECK_EQ(ptr_size, 4u);
+ reinterpret_cast<uint32_t*>(ptr_array)[idx] =
+ dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr));
+ }
+}
+
+template <VerifyObjectFlags kVerifyFlags, typename Visitor>
+inline void DexCache::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
+ // Visit instance fields first.
+ VisitInstanceFieldsReferences(klass, visitor);
+ // Visit arrays after.
+ GcRoot<mirror::String>* strings = GetStrings();
+ for (size_t i = 0, num_strings = NumStrings(); i != num_strings; ++i) {
+ visitor.VisitRootIfNonNull(strings[i].AddressWithoutBarrier());
+ }
+ GcRoot<mirror::Class>* resolved_types = GetResolvedTypes();
+ for (size_t i = 0, num_types = NumResolvedTypes(); i != num_types; ++i) {
+ visitor.VisitRootIfNonNull(resolved_types[i].AddressWithoutBarrier());
+ }
}
} // namespace mirror