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