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/patchoat/patchoat.cc b/patchoat/patchoat.cc
index a71197a..88622cc 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -523,18 +523,60 @@
   auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>(
       img_roots->Get(ImageHeader::kDexCaches));
   for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
-    auto* dex_cache = dex_caches->GetWithoutChecks(i);
-    auto* fields = dex_cache->GetResolvedFields();
-    if (fields != nullptr) {
-      CHECK(!fields->IsObjectArray());
-      CHECK(fields->IsArrayInstance());
-      FixupNativePointerArray(fields);
+    auto* orig_dex_cache = dex_caches->GetWithoutChecks(i);
+    auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache);
+    const size_t pointer_size = InstructionSetPointerSize(isa_);
+    // Though the DexCache array fields are usually treated as native pointers, we set the full
+    // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
+    // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
+    //     static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
+    GcRoot<mirror::String>* orig_strings = orig_dex_cache->GetStrings();
+    GcRoot<mirror::String>* relocated_strings = RelocatedAddressOfPointer(orig_strings);
+    copy_dex_cache->SetField64<false>(
+        mirror::DexCache::StringsOffset(),
+        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings)));
+    if (orig_strings != nullptr) {
+      GcRoot<mirror::String>* copy_strings = RelocatedCopyOf(orig_strings);
+      for (size_t j = 0, num = orig_dex_cache->NumStrings(); j != num; ++j) {
+        copy_strings[j] = GcRoot<mirror::String>(RelocatedAddressOfPointer(orig_strings[j].Read()));
+      }
     }
-    auto* methods = dex_cache->GetResolvedMethods();
-    if (methods != nullptr) {
-      CHECK(!methods->IsObjectArray());
-      CHECK(methods->IsArrayInstance());
-      FixupNativePointerArray(methods);
+    GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes();
+    GcRoot<mirror::Class>* relocated_types = RelocatedAddressOfPointer(orig_types);
+    copy_dex_cache->SetField64<false>(
+        mirror::DexCache::ResolvedTypesOffset(),
+        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types)));
+    if (orig_types != nullptr) {
+      GcRoot<mirror::Class>* copy_types = RelocatedCopyOf(orig_types);
+      for (size_t j = 0, num = orig_dex_cache->NumResolvedTypes(); j != num; ++j) {
+        copy_types[j] = GcRoot<mirror::Class>(RelocatedAddressOfPointer(orig_types[j].Read()));
+      }
+    }
+    ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods();
+    ArtMethod** relocated_methods = RelocatedAddressOfPointer(orig_methods);
+    copy_dex_cache->SetField64<false>(
+        mirror::DexCache::ResolvedMethodsOffset(),
+        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_methods)));
+    if (orig_methods != nullptr) {
+      ArtMethod** copy_methods = RelocatedCopyOf(orig_methods);
+      for (size_t j = 0, num = orig_dex_cache->NumResolvedMethods(); j != num; ++j) {
+        ArtMethod* orig = mirror::DexCache::GetElementPtrSize(orig_methods, j, pointer_size);
+        ArtMethod* copy = RelocatedAddressOfPointer(orig);
+        mirror::DexCache::SetElementPtrSize(copy_methods, j, copy, pointer_size);
+      }
+    }
+    ArtField** orig_fields = orig_dex_cache->GetResolvedFields();
+    ArtField** relocated_fields = RelocatedAddressOfPointer(orig_fields);
+    copy_dex_cache->SetField64<false>(
+        mirror::DexCache::ResolvedFieldsOffset(),
+        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_fields)));
+    if (orig_fields != nullptr) {
+      ArtField** copy_fields = RelocatedCopyOf(orig_fields);
+      for (size_t j = 0, num = orig_dex_cache->NumResolvedFields(); j != num; ++j) {
+        ArtField* orig = mirror::DexCache::GetElementPtrSize(orig_fields, j, pointer_size);
+        ArtField* copy = RelocatedAddressOfPointer(orig);
+        mirror::DexCache::SetElementPtrSize(copy_fields, j, copy, pointer_size);
+      }
     }
   }
 }
@@ -627,6 +669,7 @@
   if (object->IsClass<kVerifyNone>()) {
     auto* klass = object->AsClass();
     auto* copy_klass = down_cast<mirror::Class*>(copy);
+    copy_klass->SetDexCacheStrings(RelocatedAddressOfPointer(klass->GetDexCacheStrings()));
     copy_klass->SetSFieldsPtrUnchecked(RelocatedAddressOfPointer(klass->GetSFieldsPtr()));
     copy_klass->SetIFieldsPtrUnchecked(RelocatedAddressOfPointer(klass->GetIFieldsPtr()));
     copy_klass->SetDirectMethodsPtrUnchecked(
@@ -673,8 +716,10 @@
   // Just update the entry points if it looks like we should.
   // TODO: sanity check all the pointers' values
   copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass()));
-  copy->SetDexCacheResolvedMethods(RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods()));
-  copy->SetDexCacheResolvedTypes(RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes()));
+  copy->SetDexCacheResolvedMethods(
+      RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods(pointer_size)), pointer_size);
+  copy->SetDexCacheResolvedTypes(
+      RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes(pointer_size)), pointer_size);
   copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
       object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
   copy->SetEntryPointFromJniPtrSize(RelocatedAddressOfPointer(