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/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index af10817..2a1d644 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -88,24 +88,30 @@
                                                        r_result));
 }
 
+void Mir2Lir::LoadTypeFromCache(uint32_t type_index, RegStorage class_reg) {
+  if (CanUseOpPcRelDexCacheArrayLoad()) {
+    uint32_t offset = dex_cache_arrays_layout_.TypeOffset(type_index);
+    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
+  } else {
+    RegStorage r_method = LoadCurrMethodWithHint(class_reg);
+    MemberOffset resolved_types_offset = ArtMethod::DexCacheResolvedTypesOffset(
+        GetInstructionSetPointerSize(cu_->instruction_set));
+    LoadBaseDisp(r_method, resolved_types_offset.Int32Value(), class_reg,
+                 cu_->target64 ? k64 : k32, kNotVolatile);
+    int32_t offset_of_type = GetCacheOffset(type_index);
+    LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
+  }
+}
+
 RegStorage Mir2Lir::GenGetOtherTypeForSgetSput(const MirSFieldLoweringInfo& field_info,
                                                int opt_flags) {
   DCHECK_NE(field_info.StorageIndex(), DexFile::kDexNoIndex);
   // May do runtime call so everything to home locations.
   FlushAllRegs();
+  // Using fixed register to sync with possible call to runtime support.
   RegStorage r_base = TargetReg(kArg0, kRef);
   LockTemp(r_base);
-  if (CanUseOpPcRelDexCacheArrayLoad()) {
-    uint32_t offset = dex_cache_arrays_layout_.TypeOffset(field_info.StorageIndex());
-    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, r_base, false);
-  } else {
-    // Using fixed register to sync with possible call to runtime support.
-    RegStorage r_method = LoadCurrMethodWithHint(r_base);
-    LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
-                kNotVolatile);
-    int32_t offset_of_field = ObjArray::OffsetOfElement(field_info.StorageIndex()).Int32Value();
-    LoadRefDisp(r_base, offset_of_field, r_base, kNotVolatile);
-  }
+  LoadTypeFromCache(field_info.StorageIndex(), r_base);
   // r_base now points at static storage (Class*) or null if the type is not yet resolved.
   LIR* unresolved_branch = nullptr;
   if (!field_info.IsClassInDexCache() && (opt_flags & MIR_CLASS_IS_IN_DEX_CACHE) == 0) {
@@ -1029,19 +1035,7 @@
   } else {
     rl_result = EvalLoc(rl_dest, kRefReg, true);
     // We don't need access checks, load type from dex cache
-    if (CanUseOpPcRelDexCacheArrayLoad()) {
-      size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg, false);
-    } else {
-      int32_t dex_cache_offset =
-          ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
-      RegStorage res_reg = AllocTempRef();
-      RegStorage r_method = LoadCurrMethodWithHint(res_reg);
-      LoadRefDisp(r_method, dex_cache_offset, res_reg, kNotVolatile);
-      int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
-      LoadRefDisp(res_reg, offset_of_type, rl_result.reg, kNotVolatile);
-      FreeTemp(res_reg);
-    }
+    LoadTypeFromCache(type_idx, rl_result.reg);
     if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file,
         type_idx) || ForceSlowTypePath(cu_)) {
       // Slow path, at runtime test if type is null and if so initialize
@@ -1054,8 +1048,7 @@
 
 void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
   /* NOTE: Most strings should be available at compile time */
-  int32_t offset_of_string = mirror::ObjectArray<mirror::String>::OffsetOfElement(string_idx).
-                                                                                      Int32Value();
+  int32_t offset_of_string = GetCacheOffset(string_idx);
   if (!cu_->compiler_driver->CanAssumeStringIsPresentInDexCache(
       *cu_->dex_file, string_idx) || ForceSlowStringPath(cu_)) {
     // slow path, resolve string if not in dex cache
@@ -1073,7 +1066,8 @@
       RegStorage r_method = LoadCurrMethodWithHint(arg0);
       LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), arg0, kNotVolatile);
       // Declaring class to dex cache strings.
-      LoadRefDisp(arg0, mirror::Class::DexCacheStringsOffset().Int32Value(), arg0, kNotVolatile);
+      LoadBaseDisp(arg0, mirror::Class::DexCacheStringsOffset().Int32Value(), arg0,
+                   cu_->target64 ? k64 : k32, kNotVolatile);
 
       LoadRefDisp(arg0, offset_of_string, ret0, kNotVolatile);
     }
@@ -1091,8 +1085,8 @@
       RegStorage res_reg = AllocTempRef();
       LoadRefDisp(rl_method.reg, ArtMethod::DeclaringClassOffset().Int32Value(), res_reg,
                   kNotVolatile);
-      LoadRefDisp(res_reg, mirror::Class::DexCacheStringsOffset().Int32Value(), res_reg,
-                  kNotVolatile);
+      LoadBaseDisp(res_reg, mirror::Class::DexCacheStringsOffset().Int32Value(), res_reg,
+                   cu_->target64 ? k64 : k32, kNotVolatile);
       LoadRefDisp(res_reg, offset_of_string, rl_result.reg, kNotVolatile);
       FreeTemp(res_reg);
     }
@@ -1176,19 +1170,10 @@
                 kNotVolatile);
     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
                 kNotVolatile);
-  } else if (CanUseOpPcRelDexCacheArrayLoad()) {
-    size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, check_class, false);
-    LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
-                kNotVolatile);
   } else {
-    RegStorage r_method = LoadCurrMethodWithHint(check_class);
-    LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
-                check_class, kNotVolatile);
+    LoadTypeFromCache(type_idx, check_class);
     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
                 kNotVolatile);
-    int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
-    LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
   }
 
   // FIXME: what should we be comparing here? compressed or decompressed references?
@@ -1239,17 +1224,8 @@
       LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
     }
 
-    if (CanUseOpPcRelDexCacheArrayLoad()) {
-      size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
-    } else {
-      RegStorage r_method = LoadCurrMethodWithHint(class_reg);
-      // Load dex cache entry into class_reg (kArg2)
-      LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
-                  class_reg, kNotVolatile);
-      int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
-      LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
-    }
+    // Load dex cache entry into class_reg (kArg2)
+    LoadTypeFromCache(type_idx, class_reg);
     if (!can_assume_type_is_in_dex_cache) {
       GenIfNullUseHelperImm(class_reg, kQuickInitializeType, type_idx);
 
@@ -1370,17 +1346,7 @@
                 class_reg, kNotVolatile);
   } else {
     // Load dex cache entry into class_reg (kArg2)
-    if (CanUseOpPcRelDexCacheArrayLoad()) {
-      size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
-    } else {
-      RegStorage r_method = LoadCurrMethodWithHint(class_reg);
-
-      LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
-                  class_reg, kNotVolatile);
-      int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
-      LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
-    }
+    LoadTypeFromCache(type_idx, class_reg);
     if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx)) {
       // Need to test presence of type in dex cache at runtime
       GenIfNullUseHelperImm(class_reg, kQuickInitializeType, type_idx);