Move ArtField to native

Add linear alloc. Moved ArtField to be native object. Changed image
writer to put ArtFields after the mirror section.

Savings:
2MB on low ram devices
4MB on normal devices

Total PSS measurements before (normal N5, 95s after shell start):
Image size: 7729152 bytes
23112 kB: .NonMoving
23212 kB: .NonMoving
22868 kB: .NonMoving
23072 kB: .NonMoving
22836 kB: .NonMoving
19618 kB: .Zygote
19850 kB: .Zygote
19623 kB: .Zygote
19924 kB: .Zygote
19612 kB: .Zygote
Avg: 42745.4 kB

After:
Image size: 7462912 bytes
17440 kB: .NonMoving
16776 kB: .NonMoving
16804 kB: .NonMoving
17812 kB: .NonMoving
16820 kB: .NonMoving
18788 kB: .Zygote
18856 kB: .Zygote
19064 kB: .Zygote
18841 kB: .Zygote
18629 kB: .Zygote
3499 kB: .LinearAlloc
3408 kB: .LinearAlloc
3424 kB: .LinearAlloc
3600 kB: .LinearAlloc
3436 kB: .LinearAlloc
Avg: 39439.4 kB

No reflection performance changes.

Bug: 19264997
Bug: 17643507

Change-Id: I10c73a37913332080aeb978c7c94713bdfe4fe1c
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 548b6f8..ef94d8b 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/mutex.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
diff --git a/compiler/dex/mir_field_info.cc b/compiler/dex/mir_field_info.cc
index a9ab3bb..4dfec17 100644
--- a/compiler/dex/mir_field_info.cc
+++ b/compiler/dex/mir_field_info.cc
@@ -56,7 +56,7 @@
   // definition) we still want to resolve fields and record all available info.
   for (auto it = field_infos, end = field_infos + count; it != end; ++it) {
     uint32_t field_idx;
-    mirror::ArtField* resolved_field;
+    ArtField* resolved_field;
     if (!it->IsQuickened()) {
       field_idx = it->field_idx_;
       resolved_field = compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit,
@@ -121,7 +121,7 @@
 
   for (auto it = field_infos, end = field_infos + count; it != end; ++it) {
     uint32_t field_idx = it->field_idx_;
-    mirror::ArtField* resolved_field =
+    ArtField* resolved_field =
         compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit, field_idx, true);
     if (UNLIKELY(resolved_field == nullptr)) {
       continue;
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 5b90ba9..ae814b4 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -222,7 +222,7 @@
     } else if (IsInstructionIGetQuickOrIPutQuick(inst->Opcode())) {
       uint32_t dex_pc = inst->GetDexPc(insns);
       verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
-      mirror::ArtField* field = method_verifier->GetQuickFieldAccess(inst, line);
+      ArtField* field = method_verifier->GetQuickFieldAccess(inst, line);
       if (field == nullptr) {
         // It can be null if the line wasn't verified since it was unreachable.
         return false;
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 8babc28..b4d4695 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -19,12 +19,11 @@
 
 #include "compiler_driver.h"
 
+#include "art_field-inl.h"
 #include "dex_compilation_unit.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
-#include "mirror/art_field-inl.h"
 #include "scoped_thread_state_change.h"
 #include "handle_scope-inl.h"
 
@@ -65,12 +64,12 @@
   return ResolveClass(soa, dex_cache, class_loader, referrer_method_id.class_idx_, mUnit);
 }
 
-inline mirror::ArtField* CompilerDriver::ResolveFieldWithDexFile(
+inline ArtField* CompilerDriver::ResolveFieldWithDexFile(
     const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
     Handle<mirror::ClassLoader> class_loader, const DexFile* dex_file,
     uint32_t field_idx, bool is_static) {
   DCHECK_EQ(dex_cache->GetDexFile(), dex_file);
-  mirror::ArtField* resolved_field = Runtime::Current()->GetClassLinker()->ResolveField(
+  ArtField* resolved_field = Runtime::Current()->GetClassLinker()->ResolveField(
       *dex_file, field_idx, dex_cache, class_loader, is_static);
   DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending());
   if (UNLIKELY(resolved_field == nullptr)) {
@@ -90,7 +89,7 @@
   return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
 }
 
-inline mirror::ArtField* CompilerDriver::ResolveField(
+inline ArtField* CompilerDriver::ResolveField(
     const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
     uint32_t field_idx, bool is_static) {
@@ -100,7 +99,7 @@
 }
 
 inline void CompilerDriver::GetResolvedFieldDexFileLocation(
-    mirror::ArtField* resolved_field, const DexFile** declaring_dex_file,
+    ArtField* resolved_field, const DexFile** declaring_dex_file,
     uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) {
   mirror::Class* declaring_class = resolved_field->GetDeclaringClass();
   *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile();
@@ -108,17 +107,17 @@
   *declaring_field_idx = resolved_field->GetDexFieldIndex();
 }
 
-inline bool CompilerDriver::IsFieldVolatile(mirror::ArtField* field) {
+inline bool CompilerDriver::IsFieldVolatile(ArtField* field) {
   return field->IsVolatile();
 }
 
-inline MemberOffset CompilerDriver::GetFieldOffset(mirror::ArtField* field) {
+inline MemberOffset CompilerDriver::GetFieldOffset(ArtField* field) {
   return field->GetOffset();
 }
 
 inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField(
     mirror::DexCache* dex_cache, mirror::Class* referrer_class,
-    mirror::ArtField* resolved_field, uint16_t field_idx) {
+    ArtField* resolved_field, uint16_t field_idx) {
   DCHECK(!resolved_field->IsStatic());
   mirror::Class* fields_class = resolved_field->GetDeclaringClass();
   bool fast_get = referrer_class != nullptr &&
@@ -130,7 +129,7 @@
 
 inline std::pair<bool, bool> CompilerDriver::IsFastStaticField(
     mirror::DexCache* dex_cache, mirror::Class* referrer_class,
-    mirror::ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) {
+    ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) {
   DCHECK(resolved_field->IsStatic());
   if (LIKELY(referrer_class != nullptr)) {
     mirror::Class* fields_class = resolved_field->GetDeclaringClass();
@@ -177,14 +176,14 @@
 }
 
 inline bool CompilerDriver::IsStaticFieldInReferrerClass(mirror::Class* referrer_class,
-                                                         mirror::ArtField* resolved_field) {
+                                                         ArtField* resolved_field) {
   DCHECK(resolved_field->IsStatic());
   mirror::Class* fields_class = resolved_field->GetDeclaringClass();
   return referrer_class == fields_class;
 }
 
 inline bool CompilerDriver::IsStaticFieldsClassInitialized(mirror::Class* referrer_class,
-                                                           mirror::ArtField* resolved_field) {
+                                                           ArtField* resolved_field) {
   DCHECK(resolved_field->IsStatic());
   mirror::Class* fields_class = resolved_field->GetDeclaringClass();
   return fields_class == referrer_class || fields_class->IsInitialized();
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index f263f6d..6d79248 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -27,6 +27,7 @@
 #include <malloc.h>  // For mallinfo
 #endif
 
+#include "art_field-inl.h"
 #include "base/stl_util.h"
 #include "base/timing_logger.h"
 #include "class_linker.h"
@@ -48,7 +49,6 @@
 #include "gc/accounting/card_table-inl.h"
 #include "gc/accounting/heap_bitmap.h"
 #include "gc/space/space.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/class-inl.h"
@@ -1183,7 +1183,7 @@
 DexCacheArraysLayout CompilerDriver::GetDexCacheArraysLayout(const DexFile* dex_file) {
   // Currently only image dex caches have fixed array layout.
   return IsImage() && GetSupportBootImageFixup()
-      ? DexCacheArraysLayout(dex_file)
+      ? DexCacheArraysLayout(GetInstructionSetPointerSize(instruction_set_), dex_file)
       : DexCacheArraysLayout();
 }
 
@@ -1209,12 +1209,11 @@
   stats_->ProcessedInvoke(invoke_type, flags);
 }
 
-mirror::ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx,
-                                                           const DexCompilationUnit* mUnit,
-                                                           bool is_put,
-                                                           const ScopedObjectAccess& soa) {
+ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx,
+                                                   const DexCompilationUnit* mUnit, bool is_put,
+                                                   const ScopedObjectAccess& soa) {
   // Try to resolve the field and compiling method's class.
-  mirror::ArtField* resolved_field;
+  ArtField* resolved_field;
   mirror::Class* referrer_class;
   mirror::DexCache* dex_cache;
   {
@@ -1223,11 +1222,10 @@
         hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
     Handle<mirror::ClassLoader> class_loader_handle(
         hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
-    Handle<mirror::ArtField> resolved_field_handle(hs.NewHandle(
-        ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, false)));
-    referrer_class = (resolved_field_handle.Get() != nullptr)
+    resolved_field =
+        ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, false);
+    referrer_class = resolved_field != nullptr
         ? ResolveCompilingMethodsClass(soa, dex_cache_handle, class_loader_handle, mUnit) : nullptr;
-    resolved_field = resolved_field_handle.Get();
     dex_cache = dex_cache_handle.Get();
   }
   bool can_link = false;
@@ -1244,11 +1242,9 @@
                                               bool is_put, MemberOffset* field_offset,
                                               bool* is_volatile) {
   ScopedObjectAccess soa(Thread::Current());
-  StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ArtField> resolved_field =
-      hs.NewHandle(ComputeInstanceFieldInfo(field_idx, mUnit, is_put, soa));
+  ArtField* resolved_field = ComputeInstanceFieldInfo(field_idx, mUnit, is_put, soa);
 
-  if (resolved_field.Get() == nullptr) {
+  if (resolved_field == nullptr) {
     // Conservative defaults.
     *is_volatile = true;
     *field_offset = MemberOffset(static_cast<size_t>(-1));
@@ -1267,20 +1263,19 @@
                                             Primitive::Type* type) {
   ScopedObjectAccess soa(Thread::Current());
   // Try to resolve the field and compiling method's class.
-  mirror::ArtField* resolved_field;
+  ArtField* resolved_field;
   mirror::Class* referrer_class;
   mirror::DexCache* dex_cache;
   {
-    StackHandleScope<3> hs(soa.Self());
+    StackHandleScope<2> hs(soa.Self());
     Handle<mirror::DexCache> dex_cache_handle(
         hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
     Handle<mirror::ClassLoader> class_loader_handle(
         hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
-    Handle<mirror::ArtField> resolved_field_handle(hs.NewHandle(
-        ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, true)));
-    referrer_class = (resolved_field_handle.Get() != nullptr)
+    resolved_field =
+        ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, true);
+    referrer_class = resolved_field != nullptr
         ? ResolveCompilingMethodsClass(soa, dex_cache_handle, class_loader_handle, mUnit) : nullptr;
-    resolved_field = resolved_field_handle.Get();
     dex_cache = dex_cache_handle.Get();
   }
   bool result = false;
@@ -1728,7 +1723,7 @@
     ClassDataItemIterator it(dex_file, class_data);
     while (it.HasNextStaticField()) {
       if (resolve_fields_and_methods) {
-        mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(),
+        ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(),
                                                              dex_cache, class_loader, true);
         if (field == nullptr) {
           CheckAndClearResolveException(soa.Self());
@@ -1743,7 +1738,7 @@
         requires_constructor_barrier = true;
       }
       if (resolve_fields_and_methods) {
-        mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(),
+        ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(),
                                                              dex_cache, class_loader, false);
         if (field == nullptr) {
           CheckAndClearResolveException(soa.Self());
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index a6ed559..f1066a5 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -239,14 +239,14 @@
 
   // Resolve a field. Returns nullptr on failure, including incompatible class change.
   // NOTE: Unlike ClassLinker's ResolveField(), this method enforces is_static.
-  mirror::ArtField* ResolveField(
+  ArtField* ResolveField(
       const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
       Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
       uint32_t field_idx, bool is_static)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a field with a given dex file.
-  mirror::ArtField* ResolveFieldWithDexFile(
+  ArtField* ResolveFieldWithDexFile(
       const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
       Handle<mirror::ClassLoader> class_loader, const DexFile* dex_file,
       uint32_t field_idx, bool is_static)
@@ -254,12 +254,12 @@
 
   // Get declaration location of a resolved field.
   void GetResolvedFieldDexFileLocation(
-      mirror::ArtField* resolved_field, const DexFile** declaring_dex_file,
+      ArtField* resolved_field, const DexFile** declaring_dex_file,
       uint16_t* declaring_class_idx, uint16_t* declaring_field_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool IsFieldVolatile(mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  MemberOffset GetFieldOffset(mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool IsFieldVolatile(ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  MemberOffset GetFieldOffset(ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Find a dex cache for a dex file.
   inline mirror::DexCache* FindDexCache(const DexFile* dex_file)
@@ -268,23 +268,23 @@
   // Can we fast-path an IGET/IPUT access to an instance field? If yes, compute the field offset.
   std::pair<bool, bool> IsFastInstanceField(
       mirror::DexCache* dex_cache, mirror::Class* referrer_class,
-      mirror::ArtField* resolved_field, uint16_t field_idx)
+      ArtField* resolved_field, uint16_t field_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Can we fast-path an SGET/SPUT access to a static field? If yes, compute the type index
   // of the declaring class in the referrer's dex file.
   std::pair<bool, bool> IsFastStaticField(
       mirror::DexCache* dex_cache, mirror::Class* referrer_class,
-      mirror::ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index)
+      ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Is static field's in referrer's class?
-  bool IsStaticFieldInReferrerClass(mirror::Class* referrer_class, mirror::ArtField* resolved_field)
+  bool IsStaticFieldInReferrerClass(mirror::Class* referrer_class, ArtField* resolved_field)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Is static field's class initialized?
   bool IsStaticFieldsClassInitialized(mirror::Class* referrer_class,
-                                      mirror::ArtField* resolved_field)
+                                      ArtField* resolved_field)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a method. Returns nullptr on failure, including incompatible class change.
@@ -331,7 +331,7 @@
 
   void ComputeFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit,
                         const ScopedObjectAccess& soa, bool is_static,
-                        mirror::ArtField** resolved_field,
+                        ArtField** resolved_field,
                         mirror::Class** referrer_class,
                         mirror::DexCache** dex_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -341,7 +341,7 @@
                                 MemberOffset* field_offset, bool* is_volatile)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
-  mirror::ArtField* ComputeInstanceFieldInfo(uint32_t field_idx,
+  ArtField* ComputeInstanceFieldInfo(uint32_t field_idx,
                                              const DexCompilationUnit* mUnit,
                                              bool is_put,
                                              const ScopedObjectAccess& soa)
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 5ebc029..7200cda 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -132,7 +132,7 @@
   }
   EXPECT_EQ(dex.NumFieldIds(), dex_cache->NumResolvedFields());
   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
-    mirror::ArtField* field = dex_cache->GetResolvedField(i);
+    ArtField* field = Runtime::Current()->GetClassLinker()->GetResolvedField(i, dex_cache);
     EXPECT_TRUE(field != NULL) << "field_idx=" << i
                                << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
                                << " " << dex.GetFieldName(dex.GetFieldId(i));
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index cf97943..627a42e 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -205,6 +205,7 @@
     uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB);
     ImageHeader image_header(image_begin,
                              image_size_,
+                             0u, 0u,
                              image_bitmap_offset,
                              image_bitmap_size,
                              image_roots,
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 1ede228..6f8884a 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -22,6 +22,7 @@
 #include <numeric>
 #include <vector>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
@@ -40,8 +41,8 @@
 #include "globals.h"
 #include "image.h"
 #include "intern_table.h"
+#include "linear_alloc.h"
 #include "lock_word.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
@@ -57,7 +58,6 @@
 #include "handle_scope-inl.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
 
-using ::art::mirror::ArtField;
 using ::art::mirror::ArtMethod;
 using ::art::mirror::Class;
 using ::art::mirror::DexCache;
@@ -164,6 +164,9 @@
 
   Thread::Current()->TransitionFromSuspendedToRunnable();
   CreateHeader(oat_loaded_size, oat_data_offset);
+  // TODO: heap validation can't handle these fix up passes.
+  Runtime::Current()->GetHeap()->DisableObjectValidation();
+  CopyAndFixupNativeData();
   CopyAndFixupObjects();
   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
 
@@ -186,9 +189,10 @@
     return EXIT_FAILURE;
   }
 
-  // Write out the image.
+  // Write out the image + fields.
+  const auto write_count = image_header->GetImageSize() + image_header->GetArtFieldsSize();
   CHECK_EQ(image_end_, image_header->GetImageSize());
-  if (!image_file->WriteFully(image_->Begin(), image_end_)) {
+  if (!image_file->WriteFully(image_->Begin(), write_count)) {
     PLOG(ERROR) << "Failed to write image file " << image_filename;
     image_file->Erase();
     return false;
@@ -204,6 +208,8 @@
     return false;
   }
 
+  CHECK_EQ(image_header->GetImageBitmapOffset() + image_header->GetImageBitmapSize(),
+           static_cast<size_t>(image_file->GetLength()));
   if (image_file->FlushCloseOrErase() != 0) {
     PLOG(ERROR) << "Failed to flush and close image file " << image_filename;
     return false;
@@ -219,6 +225,8 @@
   mirror::Object* obj = reinterpret_cast<mirror::Object*>(image_->Begin() + offset);
   DCHECK_ALIGNED(obj, kObjectAlignment);
 
+  static size_t max_offset = 0;
+  max_offset = std::max(max_offset, offset);
   image_bitmap_->Set(obj);  // Mark the obj as mutated, since we will end up changing it.
   {
     // Remember the object-inside-of-the-image's hash code so we can restore it after the copy.
@@ -302,13 +310,26 @@
     DexCache* dex_cache = class_linker->GetDexCache(idx);
     const DexFile* dex_file = dex_cache->GetDexFile();
     dex_cache_array_starts_.Put(dex_file, size);
-    DexCacheArraysLayout layout(dex_file);
+    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
     DCHECK(layout.Valid());
-    dex_cache_array_indexes_.Put(dex_cache->GetResolvedTypes(), size + layout.TypesOffset());
-    dex_cache_array_indexes_.Put(dex_cache->GetResolvedMethods(), size + layout.MethodsOffset());
-    dex_cache_array_indexes_.Put(dex_cache->GetResolvedFields(), size + layout.FieldsOffset());
-    dex_cache_array_indexes_.Put(dex_cache->GetStrings(), size + layout.StringsOffset());
+    auto types_size = layout.TypesSize(dex_file->NumTypeIds());
+    auto methods_size = layout.MethodsSize(dex_file->NumMethodIds());
+    auto fields_size = layout.FieldsSize(dex_file->NumFieldIds());
+    auto strings_size = layout.StringsSize(dex_file->NumStringIds());
+    dex_cache_array_indexes_.Put(
+        dex_cache->GetResolvedTypes(),
+        DexCacheArrayLocation {size + layout.TypesOffset(), types_size});
+    dex_cache_array_indexes_.Put(
+        dex_cache->GetResolvedMethods(),
+        DexCacheArrayLocation {size + layout.MethodsOffset(), methods_size});
+    dex_cache_array_indexes_.Put(
+        dex_cache->GetResolvedFields(),
+        DexCacheArrayLocation {size + layout.FieldsOffset(), fields_size});
+    dex_cache_array_indexes_.Put(
+        dex_cache->GetStrings(),
+        DexCacheArrayLocation {size + layout.StringsOffset(), strings_size});
     size += layout.Size();
+    CHECK_EQ(layout.Size(), types_size + methods_size + fields_size + strings_size);
   }
   // Set the slot size early to avoid DCHECK() failures in IsImageBinSlotAssigned()
   // when AssignImageBinSlot() assigns their indexes out or order.
@@ -405,12 +426,20 @@
       }
     } else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
       bin = kBinString;  // Strings are almost always immutable (except for object header).
-    } else if (object->IsObjectArray()) {
-      auto it = dex_cache_array_indexes_.find(object);
-      if (it != dex_cache_array_indexes_.end()) {
-        bin = kBinDexCacheArray;
-        current_offset = it->second;  // Use prepared offset defined by the DexCacheLayout.
-      }  // else bin = kBinRegular
+    } else if (object->IsArrayInstance()) {
+      mirror::Class* klass = object->GetClass<kVerifyNone>();
+      auto* component_type = klass->GetComponentType();
+      if (!component_type->IsPrimitive() || component_type->IsPrimitiveInt() ||
+          component_type->IsPrimitiveLong()) {
+        auto it = dex_cache_array_indexes_.find(object);
+        if (it != dex_cache_array_indexes_.end()) {
+          bin = kBinDexCacheArray;
+          // Use prepared offset defined by the DexCacheLayout.
+          current_offset = it->second.offset_;
+          // Override incase of cross compilation.
+          object_size = it->second.length_;
+        }  // else bin = kBinRegular
+      }
     }  // else bin = kBinRegular
   }
 
@@ -465,7 +494,10 @@
 }
 
 bool ImageWriter::AllocMemory() {
-  size_t length = RoundUp(Runtime::Current()->GetHeap()->GetTotalMemory(), kPageSize);
+  auto* runtime = Runtime::Current();
+  const size_t heap_size = runtime->GetHeap()->GetTotalMemory();
+  // Add linear alloc usage since we need to have room for the ArtFields.
+  const size_t length = RoundUp(heap_size + runtime->GetLinearAlloc()->GetUsedMemory(), kPageSize);
   std::string error_msg;
   image_.reset(MemMap::MapAnonymous("image writer image", nullptr, length, PROT_READ | PROT_WRITE,
                                     false, false, &error_msg));
@@ -476,7 +508,7 @@
 
   // Create the image bitmap.
   image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create("image bitmap", image_->Begin(),
-                                                                    length));
+                                                                    RoundUp(length, kPageSize)));
   if (image_bitmap_.get() == nullptr) {
     LOG(ERROR) << "Failed to allocate memory for image bitmap";
     return false;
@@ -698,9 +730,9 @@
       }
     }
     for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
-      ArtField* field = dex_cache->GetResolvedField(i);
-      if (field != NULL && !IsImageClass(field->GetDeclaringClass())) {
-        dex_cache->SetResolvedField(i, NULL);
+      ArtField* field = dex_cache->GetResolvedField(i, sizeof(void*));
+      if (field != nullptr && !IsImageClass(field->GetDeclaringClass())) {
+        dex_cache->SetResolvedField(i, nullptr, sizeof(void*));
       }
     }
     // Clean the dex field. It might have been populated during the initialization phase, but
@@ -786,7 +818,7 @@
   // caches. We check that the number of dex caches does not change.
   size_t dex_cache_count;
   {
-    ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
+    ReaderMutexLock mu(self, *class_linker->DexLock());
     dex_cache_count = class_linker->GetDexCacheCount();
   }
   Handle<ObjectArray<Object>> dex_caches(
@@ -794,7 +826,7 @@
                                               dex_cache_count)));
   CHECK(dex_caches.Get() != nullptr) << "Failed to allocate a dex cache array.";
   {
-    ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
+    ReaderMutexLock mu(self, *class_linker->DexLock());
     CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount())
         << "The number of dex caches changed.";
     for (size_t i = 0; i < dex_cache_count; ++i) {
@@ -861,9 +893,9 @@
     WalkInstanceFields(h_obj.Get(), klass.Get());
     // Walk static fields of a Class.
     if (h_obj->IsClass()) {
-      size_t num_static_fields = klass->NumReferenceStaticFields();
+      size_t num_reference_static_fields = klass->NumReferenceStaticFields();
       MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset();
-      for (size_t i = 0; i < num_static_fields; ++i) {
+      for (size_t i = 0; i < num_reference_static_fields; ++i) {
         mirror::Object* value = h_obj->GetFieldObject<mirror::Object>(field_offset);
         if (value != nullptr) {
           WalkFieldsInOrder(value);
@@ -871,6 +903,21 @@
         field_offset = MemberOffset(field_offset.Uint32Value() +
                                     sizeof(mirror::HeapReference<mirror::Object>));
       }
+
+      // Visit and assign offsets for fields.
+      ArtField* fields[2] = { h_obj->AsClass()->GetSFields(), h_obj->AsClass()->GetIFields() };
+      size_t num_fields[2] = { h_obj->AsClass()->NumStaticFields(),
+          h_obj->AsClass()->NumInstanceFields() };
+      for (size_t i = 0; i < 2; ++i) {
+        for (size_t j = 0; j < num_fields[i]; ++j) {
+          auto* field = fields[i] + j;
+          auto it = art_field_reloc_.find(field);
+          CHECK(it == art_field_reloc_.end()) << "Field at index " << i << ":" << j
+              << " already assigned " << PrettyField(field);
+          art_field_reloc_.emplace(field, bin_slot_sizes_[kBinArtField]);
+          bin_slot_sizes_[kBinArtField] += sizeof(ArtField);
+        }
+      }
     } else if (h_obj->IsObjectArray()) {
       // Walk elements of an object array.
       int32_t length = h_obj->AsObjectArray<mirror::Object>()->GetLength();
@@ -921,7 +968,6 @@
   // know where image_roots is going to end up
   image_end_ += RoundUp(sizeof(ImageHeader), kObjectAlignment);  // 64-bit-alignment
 
-  // TODO: Image spaces only?
   DCHECK_LT(image_end_, image_->Size());
   image_objects_offset_begin_ = image_end_;
   // Prepare bin slots for dex cache arrays.
@@ -935,34 +981,47 @@
     previous_sizes += bin_slot_sizes_[i];
   }
   DCHECK_EQ(previous_sizes, GetBinSizeSum());
+  DCHECK_EQ(image_end_, GetBinSizeSum(kBinMirrorCount) + image_objects_offset_begin_);
+
   // Transform each object's bin slot into an offset which will be used to do the final copy.
   heap->VisitObjects(UnbinObjectsIntoOffsetCallback, this);
   DCHECK(saved_hashes_map_.empty());  // All binslot hashes should've been put into vector by now.
 
-  DCHECK_GT(image_end_, GetBinSizeSum());
+  DCHECK_EQ(image_end_, GetBinSizeSum(kBinMirrorCount) + image_objects_offset_begin_);
 
   image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots.Get()));
 
-  // Note that image_end_ is left at end of used space
+  // Note that image_end_ is left at end of used mirror space
 }
 
 void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) {
   CHECK_NE(0U, oat_loaded_size);
   const uint8_t* oat_file_begin = GetOatFileBegin();
   const uint8_t* oat_file_end = oat_file_begin + oat_loaded_size;
-
   oat_data_begin_ = oat_file_begin + oat_data_offset;
   const uint8_t* oat_data_end = oat_data_begin_ + oat_file_->Size();
-
+  // Write out sections.
+  size_t cur_pos = image_end_;
+  // Add fields.
+  auto fields_offset = cur_pos;
+  CHECK_EQ(image_objects_offset_begin_ + GetBinSizeSum(kBinArtField), fields_offset);
+  auto fields_size = bin_slot_sizes_[kBinArtField];
+  cur_pos += fields_size;
   // Return to write header at start of image with future location of image_roots. At this point,
-  // image_end_ is the size of the image (excluding bitmaps).
+  // image_end_ is the size of the image (excluding bitmaps, ArtFields).
+  /*
   const size_t heap_bytes_per_bitmap_byte = kBitsPerByte * kObjectAlignment;
   const size_t bitmap_bytes = RoundUp(image_end_, heap_bytes_per_bitmap_byte) /
       heap_bytes_per_bitmap_byte;
+      */
+  const size_t bitmap_bytes = image_bitmap_->Size();
+  auto bitmap_offset = RoundUp(cur_pos, kPageSize);
+  auto bitmap_size = RoundUp(bitmap_bytes, kPageSize);
+  cur_pos += bitmap_size;
   new (image_->Begin()) ImageHeader(PointerToLowMemUInt32(image_begin_),
                                     static_cast<uint32_t>(image_end_),
-                                    RoundUp(image_end_, kPageSize),
-                                    RoundUp(bitmap_bytes, kPageSize),
+                                    fields_offset, fields_size,
+                                    bitmap_offset, bitmap_size,
                                     image_roots_address_,
                                     oat_file_->GetOatHeader().GetChecksum(),
                                     PointerToLowMemUInt32(oat_file_begin),
@@ -972,11 +1031,21 @@
                                     compile_pic_);
 }
 
+void ImageWriter::CopyAndFixupNativeData() {
+  // Copy ArtFields to their locations and update the array for convenience.
+  auto fields_offset = image_objects_offset_begin_ + GetBinSizeSum(kBinArtField);
+  for (auto& pair : art_field_reloc_) {
+    pair.second += fields_offset;
+    auto* dest = image_->Begin() + pair.second;
+    DCHECK_GE(dest, image_->Begin() + image_end_);
+    memcpy(dest, pair.first, sizeof(ArtField));
+    reinterpret_cast<ArtField*>(dest)->SetDeclaringClass(
+        down_cast<Class*>(GetImageAddress(pair.first->GetDeclaringClass())));
+  }
+}
+
 void ImageWriter::CopyAndFixupObjects() {
   gc::Heap* heap = Runtime::Current()->GetHeap();
-  // TODO: heap validation can't handle this fix up pass
-  heap->DisableObjectValidation();
-  // TODO: Image spaces only?
   heap->VisitObjects(CopyAndFixupObjectsCallback, this);
   // Fix up the object previously had hash codes.
   for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) {
@@ -990,26 +1059,88 @@
 void ImageWriter::CopyAndFixupObjectsCallback(Object* obj, void* arg) {
   DCHECK(obj != nullptr);
   DCHECK(arg != nullptr);
-  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
+  reinterpret_cast<ImageWriter*>(arg)->CopyAndFixupObject(obj);
+}
+
+bool ImageWriter::CopyAndFixupIfDexCacheFieldArray(mirror::Object* dst, mirror::Object* obj,
+                                                   mirror::Class* klass) {
+  if (!klass->IsArrayClass()) {
+    return false;
+  }
+  auto* component_type = klass->GetComponentType();
+  bool is_int_arr = component_type->IsPrimitiveInt();
+  bool is_long_arr = component_type->IsPrimitiveLong();
+  if (!is_int_arr && !is_long_arr) {
+    return false;
+  }
+  auto it = dex_cache_array_indexes_.find(obj);  // Is this a dex cache array?
+  if (it == dex_cache_array_indexes_.end()) {
+    return false;
+  }
+  mirror::Array* arr = obj->AsArray();
+  CHECK_EQ(reinterpret_cast<Object*>(
+      image_->Begin() + it->second.offset_ + image_objects_offset_begin_), dst);
+  dex_cache_array_indexes_.erase(it);
+  // Fixup int pointers for the field array.
+  CHECK(!arr->IsObjectArray());
+  const size_t num_elements = arr->GetLength();
+  if (target_ptr_size_ == 4) {
+    // Will get fixed up by fixup object.
+    dst->SetClass(down_cast<mirror::Class*>(
+    GetImageAddress(mirror::IntArray::GetArrayClass())));
+  } else {
+    DCHECK_EQ(target_ptr_size_, 8u);
+    dst->SetClass(down_cast<mirror::Class*>(
+    GetImageAddress(mirror::LongArray::GetArrayClass())));
+  }
+  mirror::Array* dest_array = down_cast<mirror::Array*>(dst);
+  dest_array->SetLength(num_elements);
+  for (size_t i = 0, count = num_elements; i < count; ++i) {
+    ArtField* field = reinterpret_cast<ArtField*>(is_int_arr ?
+        arr->AsIntArray()->GetWithoutChecks(i) : arr->AsLongArray()->GetWithoutChecks(i));
+    uint8_t* fixup_location = nullptr;
+    if (field != nullptr) {
+      auto it2 = art_field_reloc_.find(field);
+      CHECK(it2 != art_field_reloc_.end()) << "No relocation for field " << PrettyField(field);
+      fixup_location = image_begin_ + it2->second;
+    }
+    if (target_ptr_size_ == 4) {
+      down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
+          i, static_cast<uint32_t>(reinterpret_cast<uint64_t>(fixup_location)));
+    } else {
+      down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
+          i, reinterpret_cast<uint64_t>(fixup_location));
+    }
+  }
+  dst->SetLockWord(LockWord::Default(), false);
+  return true;
+}
+
+void ImageWriter::CopyAndFixupObject(Object* obj) {
   // see GetLocalAddress for similar computation
-  size_t offset = image_writer->GetImageOffset(obj);
-  uint8_t* dst = image_writer->image_->Begin() + offset;
+  size_t offset = GetImageOffset(obj);
+  auto* dst = reinterpret_cast<Object*>(image_->Begin() + offset);
   const uint8_t* src = reinterpret_cast<const uint8_t*>(obj);
   size_t n;
-  if (obj->IsArtMethod()) {
+  mirror::Class* klass = obj->GetClass();
+
+  if (CopyAndFixupIfDexCacheFieldArray(dst, obj, klass)) {
+    return;
+  }
+  if (klass->IsArtMethodClass()) {
     // Size without pointer fields since we don't want to overrun the buffer if target art method
     // is 32 bits but source is 64 bits.
-    n = mirror::ArtMethod::SizeWithoutPointerFields(image_writer->target_ptr_size_);
+    n = mirror::ArtMethod::SizeWithoutPointerFields(target_ptr_size_);
   } else {
     n = obj->SizeOf();
   }
-  DCHECK_LT(offset + n, image_writer->image_->Size());
+  DCHECK_LE(offset + n, image_->Size());
   memcpy(dst, src, n);
-  Object* copy = reinterpret_cast<Object*>(dst);
+
   // Write in a hash code of objects which have inflated monitors or a hash code in their monitor
   // word.
-  copy->SetLockWord(LockWord::Default(), false);
-  image_writer->FixupObject(obj, copy);
+  dst->SetLockWord(LockWord::Default(), false);
+  FixupObject(obj, dst);
 }
 
 // Rewrite all the references in the copied object to point to their image address equivalent
@@ -1045,15 +1176,10 @@
   FixupClassVisitor(ImageWriter* image_writer, Object* copy) : FixupVisitor(image_writer, copy) {
   }
 
-  void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const
+  void operator()(Object* obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
       EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
     DCHECK(obj->IsClass());
     FixupVisitor::operator()(obj, offset, /*is_static*/false);
-
-    // TODO: Remove dead code
-    if (offset.Uint32Value() < mirror::Class::EmbeddedVTableOffset().Uint32Value()) {
-      return;
-    }
   }
 
   void operator()(mirror::Class* klass ATTRIBUTE_UNUSED,
@@ -1064,6 +1190,31 @@
   }
 };
 
+void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
+  // Copy and fix up ArtFields in the class.
+  ArtField* fields[2] = { orig->AsClass()->GetSFields(), orig->AsClass()->GetIFields() };
+  size_t num_fields[2] = { orig->AsClass()->NumStaticFields(),
+      orig->AsClass()->NumInstanceFields() };
+  // Update the arrays.
+  for (size_t i = 0; i < 2; ++i) {
+    if (num_fields[i] == 0) {
+      CHECK(fields[i] == nullptr);
+      continue;
+    }
+    auto it = art_field_reloc_.find(fields[i]);
+    CHECK(it != art_field_reloc_.end()) << PrettyClass(orig->AsClass()) << " : "
+        << PrettyField(fields[i]);
+    auto* image_fields = reinterpret_cast<ArtField*>(image_begin_ + it->second);
+    if (i == 0) {
+      down_cast<Class*>(copy)->SetSFieldsUnchecked(image_fields);
+    } else {
+      down_cast<Class*>(copy)->SetIFieldsUnchecked(image_fields);
+    }
+  }
+  FixupClassVisitor visitor(this, copy);
+  static_cast<mirror::Object*>(orig)->VisitReferences<true /*visit class*/>(visitor, visitor);
+}
+
 void ImageWriter::FixupObject(Object* orig, Object* copy) {
   DCHECK(orig != nullptr);
   DCHECK(copy != nullptr);
@@ -1075,9 +1226,8 @@
       DCHECK_EQ(copy->GetReadBarrierPointer(), GetImageAddress(orig));
     }
   }
-  if (orig->IsClass() && orig->AsClass()->ShouldHaveEmbeddedImtAndVTable()) {
-    FixupClassVisitor visitor(this, copy);
-    orig->VisitReferences<true /*visit class*/>(visitor, visitor);
+  if (orig->IsClass()) {
+    FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
   } else {
     FixupVisitor visitor(this, copy);
     orig->VisitReferences<true /*visit class*/>(visitor, visitor);
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 71044f7..a2d99ee 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -90,7 +90,7 @@
   }
 
   uint8_t* GetOatFileBegin() const {
-    return image_begin_ + RoundUp(image_end_, kPageSize);
+    return image_begin_ + RoundUp(image_end_ + bin_slot_sizes_[kBinArtField], kPageSize);
   }
 
   bool Write(const std::string& image_filename,
@@ -127,12 +127,16 @@
     kBinArtMethodNative,          // Art method that is actually native
     kBinArtMethodNotInitialized,  // Art method with a declaring class that wasn't initialized
     // Add more bins here if we add more segregation code.
+    // Non mirror fields must be below. ArtFields should be always clean.
+    kBinArtField,
     kBinSize,
+    // Number of bins which are for mirror objects.
+    kBinMirrorCount = kBinArtField,
   };
 
   friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
 
-  static constexpr size_t kBinBits = MinimumBitsToStore(kBinSize - 1);
+  static constexpr size_t kBinBits = MinimumBitsToStore(kBinMirrorCount - 1);
   // uint32 = typeof(lockword_)
   static constexpr size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits;
   // 111000.....0
@@ -251,11 +255,18 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Creates the contiguous image in memory and adjusts pointers.
+  void CopyAndFixupNativeData() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void CopyAndFixupObjects() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void CopyAndFixupObjectsCallback(mirror::Object* obj, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void CopyAndFixupObject(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool CopyAndFixupIfDexCacheFieldArray(mirror::Object* dst, mirror::Object* obj,
+                                        mirror::Class* klass)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FixupMethod(mirror::ArtMethod* orig, mirror::ArtMethod* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void FixupClass(mirror::Class* orig, mirror::Class* copy)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FixupObject(mirror::Object* orig, mirror::Object* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -295,8 +306,13 @@
   // Memory mapped for generating the image.
   std::unique_ptr<MemMap> image_;
 
-  // Indexes for dex cache arrays (objects are inside of the image so that they don't move).
-  SafeMap<mirror::Object*, size_t> dex_cache_array_indexes_;
+  // Indexes, lengths for dex cache arrays (objects are inside of the image so that they don't
+  // move).
+  struct DexCacheArrayLocation {
+    size_t offset_;
+    size_t length_;
+  };
+  SafeMap<mirror::Object*, DexCacheArrayLocation> dex_cache_array_indexes_;
 
   // The start offsets of the dex cache arrays.
   SafeMap<const DexFile*, size_t> dex_cache_array_starts_;
@@ -331,6 +347,11 @@
   size_t bin_slot_previous_sizes_[kBinSize];  // Number of bytes in previous bins.
   size_t bin_slot_count_[kBinSize];  // Number of objects in a bin
 
+  // ArtField relocating map, ArtFields are allocated as array of structs but we want to have one
+  // entry per art field for convenience.
+  // ArtFields are placed right after the end of the image objects (aka sum of bin_slot_sizes_).
+  std::unordered_map<ArtField*, uintptr_t> art_field_reloc_;
+
   void* string_data_array_;  // The backing for the interned strings.
 
   friend class FixupVisitor;
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index a912d4c..8a64d81 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -16,16 +16,13 @@
 
 #include "builder.h"
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "class_linker.h"
-#include "dex_file.h"
 #include "dex_file-inl.h"
-#include "dex_instruction.h"
 #include "dex_instruction-inl.h"
 #include "driver/compiler_driver-inl.h"
 #include "driver/compiler_options.h"
-#include "mirror/art_field.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache.h"
 #include "nodes.h"
@@ -656,11 +653,10 @@
   uint16_t field_index = instruction.VRegC_22c();
 
   ScopedObjectAccess soa(Thread::Current());
-  StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ArtField> resolved_field(hs.NewHandle(
-      compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa)));
+  ArtField* resolved_field =
+      compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa);
 
-  if (resolved_field.Get() == nullptr) {
+  if (resolved_field == nullptr) {
     MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
     return false;
   }
@@ -728,15 +724,15 @@
   uint16_t field_index = instruction.VRegB_21c();
 
   ScopedObjectAccess soa(Thread::Current());
-  StackHandleScope<5> hs(soa.Self());
+  StackHandleScope<4> hs(soa.Self());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(
       dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
       soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
-  Handle<mirror::ArtField> resolved_field(hs.NewHandle(compiler_driver_->ResolveField(
-      soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true)));
+  ArtField* resolved_field = compiler_driver_->ResolveField(
+      soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true);
 
-  if (resolved_field.Get() == nullptr) {
+  if (resolved_field == nullptr) {
     MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
     return false;
   }
@@ -758,7 +754,7 @@
     std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
         outer_dex_cache.Get(),
         referrer_class.Get(),
-        resolved_field.Get(),
+        resolved_field,
         field_index,
         &storage_index);
     bool can_easily_access = is_put ? pair.second : pair.first;
diff --git a/compiler/utils/dex_cache_arrays_layout-inl.h b/compiler/utils/dex_cache_arrays_layout-inl.h
index 7d02ce3..2c50c96 100644
--- a/compiler/utils/dex_cache_arrays_layout-inl.h
+++ b/compiler/utils/dex_cache_arrays_layout-inl.h
@@ -26,7 +26,6 @@
 #include "utils.h"
 
 namespace mirror {
-class ArtField;
 class ArtMethod;
 class Class;
 class String;
@@ -34,40 +33,55 @@
 
 namespace art {
 
-inline DexCacheArraysLayout::DexCacheArraysLayout(const DexFile* dex_file)
+inline DexCacheArraysLayout::DexCacheArraysLayout(size_t pointer_size, const DexFile* dex_file)
     : /* types_offset_ is always 0u */
-      methods_offset_(types_offset_ + ArraySize<mirror::Class>(dex_file->NumTypeIds())),
-      strings_offset_(methods_offset_ + ArraySize<mirror::ArtMethod>(dex_file->NumMethodIds())),
-      fields_offset_(strings_offset_ + ArraySize<mirror::String>(dex_file->NumStringIds())),
-      size_(fields_offset_ + ArraySize<mirror::ArtField>(dex_file->NumFieldIds())) {
+      pointer_size_(pointer_size),
+      methods_offset_(types_offset_ + TypesSize(dex_file->NumTypeIds())),
+      strings_offset_(methods_offset_ + MethodsSize(dex_file->NumMethodIds())),
+      fields_offset_(strings_offset_ + StringsSize(dex_file->NumStringIds())),
+      size_(fields_offset_ + FieldsSize(dex_file->NumFieldIds())) {
+  DCHECK(pointer_size == 4u || pointer_size == 8u);
 }
 
 inline size_t DexCacheArraysLayout::TypeOffset(uint32_t type_idx) const {
-  return types_offset_ + ElementOffset<mirror::Class>(type_idx);
+  return types_offset_ + ElementOffset(sizeof(mirror::HeapReference<mirror::Class>), type_idx);
+}
+
+inline size_t DexCacheArraysLayout::TypesSize(size_t num_elements) const {
+  return ArraySize(sizeof(mirror::HeapReference<mirror::Class>), num_elements);
 }
 
 inline size_t DexCacheArraysLayout::MethodOffset(uint32_t method_idx) const {
-  return methods_offset_ + ElementOffset<mirror::ArtMethod>(method_idx);
+  return methods_offset_ + ElementOffset(
+      sizeof(mirror::HeapReference<mirror::ArtMethod>), method_idx);
+}
+
+inline size_t DexCacheArraysLayout::MethodsSize(size_t num_elements) const {
+  return ArraySize(sizeof(mirror::HeapReference<mirror::ArtMethod>), num_elements);
 }
 
 inline size_t DexCacheArraysLayout::StringOffset(uint32_t string_idx) const {
-  return strings_offset_ + ElementOffset<mirror::String>(string_idx);
+  return strings_offset_ + ElementOffset(sizeof(mirror::HeapReference<mirror::String>), string_idx);
+}
+
+inline size_t DexCacheArraysLayout::StringsSize(size_t num_elements) const {
+  return ArraySize(sizeof(mirror::HeapReference<mirror::String>), num_elements);
 }
 
 inline size_t DexCacheArraysLayout::FieldOffset(uint32_t field_idx) const {
-  return fields_offset_ + ElementOffset<mirror::ArtField>(field_idx);
+  return fields_offset_ + ElementOffset(pointer_size_, field_idx);
 }
 
-template <typename MirrorType>
-inline size_t DexCacheArraysLayout::ElementOffset(uint32_t idx) {
-  return mirror::Array::DataOffset(sizeof(mirror::HeapReference<MirrorType>)).Uint32Value() +
-      sizeof(mirror::HeapReference<MirrorType>) * idx;
+inline size_t DexCacheArraysLayout::FieldsSize(size_t num_elements) const {
+  return ArraySize(pointer_size_, num_elements);
 }
 
-template <typename MirrorType>
-inline size_t DexCacheArraysLayout::ArraySize(uint32_t num_elements) {
-  size_t array_size = mirror::ComputeArraySize(
-      num_elements, ComponentSizeShiftWidth<sizeof(mirror::HeapReference<MirrorType>)>());
+inline size_t DexCacheArraysLayout::ElementOffset(size_t element_size, uint32_t idx) {
+  return mirror::Array::DataOffset(element_size).Uint32Value() + element_size * idx;
+}
+
+inline size_t DexCacheArraysLayout::ArraySize(size_t element_size, uint32_t num_elements) {
+  size_t array_size = mirror::ComputeArraySize(num_elements, ComponentSizeShiftWidth(element_size));
   DCHECK_NE(array_size, 0u);  // No overflow expected for dex cache arrays.
   return RoundUp(array_size, kObjectAlignment);
 }
diff --git a/compiler/utils/dex_cache_arrays_layout.h b/compiler/utils/dex_cache_arrays_layout.h
index b461256..8f98ea1 100644
--- a/compiler/utils/dex_cache_arrays_layout.h
+++ b/compiler/utils/dex_cache_arrays_layout.h
@@ -29,6 +29,7 @@
   // Construct an invalid layout.
   DexCacheArraysLayout()
       : /* types_offset_ is always 0u */
+        pointer_size_(0u),
         methods_offset_(0u),
         strings_offset_(0u),
         fields_offset_(0u),
@@ -36,7 +37,7 @@
   }
 
   // Construct a layout for a particular dex file.
-  explicit DexCacheArraysLayout(const DexFile* dex_file);
+  explicit DexCacheArraysLayout(size_t pointer_size, const DexFile* dex_file);
 
   bool Valid() const {
     return Size() != 0u;
@@ -52,36 +53,43 @@
 
   size_t TypeOffset(uint32_t type_idx) const;
 
+  size_t TypesSize(size_t num_elements) const;
+
   size_t MethodsOffset() const {
     return methods_offset_;
   }
 
   size_t MethodOffset(uint32_t method_idx) const;
 
+  size_t MethodsSize(size_t num_elements) const;
+
   size_t StringsOffset() const {
     return strings_offset_;
   }
 
   size_t StringOffset(uint32_t string_idx) const;
 
+  size_t StringsSize(size_t num_elements) const;
+
   size_t FieldsOffset() const {
     return fields_offset_;
   }
 
   size_t FieldOffset(uint32_t field_idx) const;
 
+  size_t FieldsSize(size_t num_elements) const;
+
  private:
   static constexpr size_t types_offset_ = 0u;
+  const size_t pointer_size_;  // Must be first for construction initialization order.
   const size_t methods_offset_;
   const size_t strings_offset_;
   const size_t fields_offset_;
   const size_t size_;
 
-  template <typename MirrorType>
-  static size_t ElementOffset(uint32_t idx);
+  static size_t ElementOffset(size_t element_size, uint32_t idx);
 
-  template <typename MirrorType>
-  static size_t ArraySize(uint32_t num_elements);
+  static size_t ArraySize(size_t element_size, uint32_t num_elements);
 };
 
 }  // namespace art
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index 9b57ecb..34a4c14 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -168,7 +168,10 @@
        << "\n\n";
 
     const uint8_t* image_begin_unaligned = boot_image_header.GetImageBegin();
-    const uint8_t* image_end_unaligned = image_begin_unaligned + boot_image_header.GetImageSize();
+    const uint8_t* image_mirror_end_unaligned = image_begin_unaligned +
+        boot_image_header.GetImageSize();
+    const uint8_t* image_end_unaligned = image_mirror_end_unaligned +
+        boot_image_header.GetArtFieldsSize();
 
     // Adjust range to nearest page
     const uint8_t* image_begin = AlignDown(image_begin_unaligned, kPageSize);
@@ -350,7 +353,7 @@
     size_t dirty_object_bytes = 0;
     {
       const uint8_t* begin_image_ptr = image_begin_unaligned;
-      const uint8_t* end_image_ptr = image_end_unaligned;
+      const uint8_t* end_image_ptr = image_mirror_end_unaligned;
 
       const uint8_t* current = begin_image_ptr + RoundUp(sizeof(ImageHeader), kObjectAlignment);
       while (reinterpret_cast<const uintptr_t>(current)
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 322d3aa..a36e5b1 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include "arch/instruction_set_features.h"
+#include "art_field-inl.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "class_linker-inl.h"
@@ -40,7 +41,6 @@
 #include "image.h"
 #include "indenter.h"
 #include "mapping_table.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
@@ -1549,9 +1549,6 @@
     } else if (type->IsClassClass()) {
       mirror::Class* klass = value->AsClass();
       os << StringPrintf("%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
-    } else if (type->IsArtFieldClass()) {
-      mirror::ArtField* field = value->AsArtField();
-      os << StringPrintf("%p   Field: %s\n", field, PrettyField(field).c_str());
     } else if (type->IsArtMethodClass()) {
       mirror::ArtMethod* method = value->AsArtMethod();
       os << StringPrintf("%p   Method: %s\n", method, PrettyMethod(method).c_str());
@@ -1560,7 +1557,7 @@
     }
   }
 
-  static void PrintField(std::ostream& os, mirror::ArtField* field, mirror::Object* obj)
+  static void PrintField(std::ostream& os, ArtField* field, mirror::Object* obj)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     os << StringPrintf("%s: ", field->GetName());
     switch (field->GetTypeAsPrimitiveType()) {
@@ -1619,12 +1616,9 @@
     if (super != nullptr) {
       DumpFields(os, obj, super);
     }
-    mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
-    if (fields != nullptr) {
-      for (int32_t i = 0; i < fields->GetLength(); i++) {
-        mirror::ArtField* field = fields->Get(i);
-        PrintField(os, field, obj);
-      }
+    ArtField* fields = klass->GetIFields();
+    for (size_t i = 0, count = klass->NumInstanceFields(); i < count; i++) {
+      PrintField(os, &fields[i], obj);
     }
   }
 
@@ -1686,9 +1680,6 @@
       mirror::Class* klass = obj->AsClass();
       os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str())
          << klass->GetStatus() << ")\n";
-    } else if (obj->IsArtField()) {
-      os << StringPrintf("%p: java.lang.reflect.ArtField %s\n", obj,
-                         PrettyField(obj->AsArtField()).c_str());
     } else if (obj->IsArtMethod()) {
       os << StringPrintf("%p: java.lang.reflect.ArtMethod %s\n", obj,
                          PrettyMethod(obj->AsArtMethod()).c_str());
@@ -1725,14 +1716,15 @@
         PrettyObjectValue(indent_os, value_class, value);
       }
     } else if (obj->IsClass()) {
-      mirror::ObjectArray<mirror::ArtField>* sfields = obj->AsClass()->GetSFields();
-      if (sfields != nullptr) {
+      mirror::Class* klass = obj->AsClass();
+      ArtField* sfields = klass->GetSFields();
+      const size_t num_fields = klass->NumStaticFields();
+      if (num_fields != 0) {
         indent_os << "STATICS:\n";
         Indenter indent2_filter(indent_os.rdbuf(), kIndentChar, kIndentBy1Count);
         std::ostream indent2_os(&indent2_filter);
-        for (int32_t i = 0; i < sfields->GetLength(); i++) {
-          mirror::ArtField* field = sfields->Get(i);
-          PrintField(indent2_os, field, field->GetDeclaringClass());
+        for (size_t i = 0; i < num_fields; i++) {
+          PrintField(indent2_os, &sfields[i], sfields[i].GetDeclaringClass());
         }
       }
     } else if (obj->IsArtMethod()) {
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 9584064..74c9c38 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -24,6 +24,7 @@
 #include <string>
 #include <vector>
 
+#include "art_field-inl.h"
 #include "base/dumpable.h"
 #include "base/scoped_flock.h"
 #include "base/stringpiece.h"
@@ -34,7 +35,6 @@
 #include "elf_file_impl.h"
 #include "gc/space/image_space.h"
 #include "image.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/reference.h"
@@ -415,13 +415,64 @@
   return true;
 }
 
+void PatchOat::PatchArtFields(const ImageHeader* image_header) {
+  const size_t art_field_size = image_header->GetArtFieldsSize();
+  const size_t art_field_offset = image_header->GetArtFieldsOffset();
+  for (size_t pos = 0; pos < art_field_size; pos += sizeof(ArtField)) {
+    auto* field = reinterpret_cast<ArtField*>(heap_->Begin() + art_field_offset + pos);
+    auto* dest_field = RelocatedCopyOf(field);
+    dest_field->SetDeclaringClass(RelocatedAddressOfPointer(field->GetDeclaringClass()));
+  }
+}
+
+void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) {
+  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) {
+      continue;
+    }
+    CHECK(!fields->IsObjectArray());
+    CHECK(fields->IsArrayInstance());
+    auto* component_type = fields->GetClass()->GetComponentType();
+    if (component_type->IsPrimitiveInt()) {
+      mirror::IntArray* arr = fields->AsIntArray();
+      mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr));
+      for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
+        auto f = arr->GetWithoutChecks(j);
+        if (f != 0) {
+          copy_arr->SetWithoutChecks<false>(j, f + delta_);
+        }
+      }
+    } else {
+      CHECK(component_type->IsPrimitiveLong());
+      mirror::LongArray* arr = fields->AsLongArray();
+      mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr));
+      for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
+        auto f = arr->GetWithoutChecks(j);
+        if (f != 0) {
+          copy_arr->SetWithoutChecks<false>(j, f + delta_);
+        }
+      }
+    }
+  }
+}
+
 bool PatchOat::PatchImage() {
   ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
   CHECK_GT(image_->Size(), sizeof(ImageHeader));
   // These are the roots from the original file.
-  mirror::Object* img_roots = image_header->GetImageRoots();
+  auto* img_roots = image_header->GetImageRoots();
   image_header->RelocateImage(delta_);
 
+  // Patch and update ArtFields.
+  PatchArtFields(image_header);
+
+  // Patch dex file int/long arrays which point to ArtFields.
+  PatchDexFileArrays(img_roots);
+
   VisitObject(img_roots);
   if (!image_header->IsValid()) {
     LOG(ERROR) << "reloction renders image header invalid";
@@ -448,7 +499,7 @@
                                          bool is_static_unused ATTRIBUTE_UNUSED) const {
   mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off);
   DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap.";
-  mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent);
+  mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
 }
 
@@ -457,30 +508,10 @@
   MemberOffset off = mirror::Reference::ReferentOffset();
   mirror::Object* referent = ref->GetReferent();
   DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap.";
-  mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent);
+  mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent);
   copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object);
 }
 
-mirror::Object* PatchOat::RelocatedCopyOf(mirror::Object* obj) {
-  if (obj == nullptr) {
-    return nullptr;
-  }
-  DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin()));
-  DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End()));
-  uintptr_t heap_off =
-      reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin());
-  DCHECK_LT(heap_off, image_->Size());
-  return reinterpret_cast<mirror::Object*>(image_->Begin() + heap_off);
-}
-
-mirror::Object* PatchOat::RelocatedAddressOf(mirror::Object* obj) {
-  if (obj == nullptr) {
-    return nullptr;
-  } else {
-    return reinterpret_cast<mirror::Object*>(reinterpret_cast<uint8_t*>(obj) + delta_);
-  }
-}
-
 const OatHeader* PatchOat::GetOatHeader(const ElfFile* elf_file) {
   if (elf_file->Is64Bit()) {
     return GetOatHeader<ElfFileImpl64>(elf_file->GetImpl64());
@@ -507,7 +538,7 @@
   if (kUseBakerOrBrooksReadBarrier) {
     object->AssertReadBarrierPointer();
     if (kUseBrooksReadBarrier) {
-      mirror::Object* moved_to = RelocatedAddressOf(object);
+      mirror::Object* moved_to = RelocatedAddressOfPointer(object);
       copy->SetReadBarrierPointer(moved_to);
       DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to);
     }
@@ -516,6 +547,12 @@
   object->VisitReferences<true, kVerifyNone>(visitor, visitor);
   if (object->IsArtMethod<kVerifyNone>()) {
     FixupMethod(down_cast<mirror::ArtMethod*>(object), down_cast<mirror::ArtMethod*>(copy));
+  } else if (object->IsClass<kVerifyNone>()) {
+    mirror::Class* klass = down_cast<mirror::Class*>(object);
+    down_cast<mirror::Class*>(copy)->SetSFieldsUnchecked(
+        RelocatedAddressOfPointer(klass->GetSFields()));
+    down_cast<mirror::Class*>(copy)->SetIFieldsUnchecked(
+        RelocatedAddressOfPointer(klass->GetIFields()));
   }
 }
 
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index 578df3a..418650a 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -117,12 +117,31 @@
   bool PatchOatHeader(ElfFileImpl* oat_file);
 
   bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void PatchArtFields(const ImageHeader* image_header) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool WriteElf(File* out);
   bool WriteImage(File* out);
 
-  mirror::Object* RelocatedCopyOf(mirror::Object*);
-  mirror::Object* RelocatedAddressOf(mirror::Object* obj);
+  template <typename T>
+  T* RelocatedCopyOf(T* obj) {
+    if (obj == nullptr) {
+      return nullptr;
+    }
+    DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin()));
+    DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End()));
+    uintptr_t heap_off =
+        reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin());
+    DCHECK_LT(heap_off, image_->Size());
+    return reinterpret_cast<T*>(image_->Begin() + heap_off);
+  }
+
+  template <typename T>
+  T* RelocatedAddressOfPointer(T* obj) {
+    return obj == nullptr ? nullptr :
+        reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(obj) + delta_);
+  }
 
   // Look up the oat header from any elf file.
   static const OatHeader* GetOatHeader(const ElfFile* elf_file);
diff --git a/runtime/Android.mk b/runtime/Android.mk
index c0e7f47..d3488fc 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -19,6 +19,7 @@
 include art/build/Android.common_build.mk
 
 LIBART_COMMON_SRC_FILES := \
+  art_field.cc \
   atomic.cc.arm \
   barrier.cc \
   base/allocator.cc \
@@ -96,9 +97,9 @@
   jit/jit_instrumentation.cc \
   jni_internal.cc \
   jobject_comparator.cc \
+  linear_alloc.cc \
   mem_map.cc \
   memory_region.cc \
-  mirror/art_field.cc \
   mirror/art_method.cc \
   mirror/array.cc \
   mirror/class.cc \
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 0769687..d7de119 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -16,9 +16,9 @@
 
 #include <cstdio>
 
+#include "art_field-inl.h"
 #include "common_runtime_test.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/string-inl.h"
@@ -1305,7 +1305,7 @@
 }
 
 
-static void GetSetBooleanStatic(Handle<mirror::ArtField>* f, Thread* self,
+static void GetSetBooleanStatic(ArtField* f, Thread* self,
                                 mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
@@ -1313,14 +1313,14 @@
   uint8_t values[num_values] = { 0, 1, 2, 128, 0xFF };
 
   for (size_t i = 0; i < num_values; ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               static_cast<size_t>(values[i]),
                               0U,
                               StubTest::GetEntrypoint(self, kQuickSet8Static),
                               self,
                               referrer);
 
-    size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                            0U, 0U,
                                            StubTest::GetEntrypoint(self, kQuickGetBooleanStatic),
                                            self,
@@ -1335,21 +1335,21 @@
   std::cout << "Skipping set_boolean_static as I don't know how to do that on " << kRuntimeISA << std::endl;
 #endif
 }
-static void GetSetByteStatic(Handle<mirror::ArtField>* f, Thread* self,
-                             mirror::ArtMethod* referrer, StubTest* test)
+static void GetSetByteStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
+                             StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   int8_t values[] = { -128, -64, 0, 64, 127 };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               static_cast<size_t>(values[i]),
                               0U,
                               StubTest::GetEntrypoint(self, kQuickSet8Static),
                               self,
                               referrer);
 
-    size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                            0U, 0U,
                                            StubTest::GetEntrypoint(self, kQuickGetByteStatic),
                                            self,
@@ -1365,26 +1365,26 @@
 }
 
 
-static void GetSetBooleanInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
-                                  Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+static void GetSetBooleanInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self,
+                                  mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   uint8_t values[] = { 0, true, 2, 128, 0xFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               reinterpret_cast<size_t>(obj->Get()),
                               static_cast<size_t>(values[i]),
                               StubTest::GetEntrypoint(self, kQuickSet8Instance),
                               self,
                               referrer);
 
-    uint8_t res = f->Get()->GetBoolean(obj->Get());
+    uint8_t res = f->GetBoolean(obj->Get());
     EXPECT_EQ(values[i], res) << "Iteration " << i;
 
-    f->Get()->SetBoolean<false>(obj->Get(), res);
+    f->SetBoolean<false>(obj->Get(), res);
 
-    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                             reinterpret_cast<size_t>(obj->Get()),
                                             0U,
                                             StubTest::GetEntrypoint(self, kQuickGetBooleanInstance),
@@ -1399,25 +1399,25 @@
   std::cout << "Skipping set_boolean_instance as I don't know how to do that on " << kRuntimeISA << std::endl;
 #endif
 }
-static void GetSetByteInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
+static void GetSetByteInstance(Handle<mirror::Object>* obj, ArtField* f,
                              Thread* self, mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   int8_t values[] = { -128, -64, 0, 64, 127 };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               reinterpret_cast<size_t>(obj->Get()),
                               static_cast<size_t>(values[i]),
                               StubTest::GetEntrypoint(self, kQuickSet8Instance),
                               self,
                               referrer);
 
-    int8_t res = f->Get()->GetByte(obj->Get());
+    int8_t res = f->GetByte(obj->Get());
     EXPECT_EQ(res, values[i]) << "Iteration " << i;
-    f->Get()->SetByte<false>(obj->Get(), ++res);
+    f->SetByte<false>(obj->Get(), ++res);
 
-    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                             reinterpret_cast<size_t>(obj->Get()),
                                             0U,
                                             StubTest::GetEntrypoint(self, kQuickGetByteInstance),
@@ -1433,21 +1433,21 @@
 #endif
 }
 
-static void GetSetCharStatic(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSetCharStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
                              StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   uint16_t values[] = { 0, 1, 2, 255, 32768, 0xFFFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               static_cast<size_t>(values[i]),
                               0U,
                               StubTest::GetEntrypoint(self, kQuickSet16Static),
                               self,
                               referrer);
 
-    size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                            0U, 0U,
                                            StubTest::GetEntrypoint(self, kQuickGetCharStatic),
                                            self,
@@ -1462,21 +1462,21 @@
   std::cout << "Skipping set_char_static as I don't know how to do that on " << kRuntimeISA << std::endl;
 #endif
 }
-static void GetSetShortStatic(Handle<mirror::ArtField>* f, Thread* self,
+static void GetSetShortStatic(ArtField* f, Thread* self,
                               mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   int16_t values[] = { -0x7FFF, -32768, 0, 255, 32767, 0x7FFE };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               static_cast<size_t>(values[i]),
                               0U,
                               StubTest::GetEntrypoint(self, kQuickSet16Static),
                               self,
                               referrer);
 
-    size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                            0U, 0U,
                                            StubTest::GetEntrypoint(self, kQuickGetShortStatic),
                                            self,
@@ -1492,25 +1492,25 @@
 #endif
 }
 
-static void GetSetCharInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
-                             Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+static void GetSetCharInstance(Handle<mirror::Object>* obj, ArtField* f,
+                               Thread* self, mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   uint16_t values[] = { 0, 1, 2, 255, 32768, 0xFFFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               reinterpret_cast<size_t>(obj->Get()),
                               static_cast<size_t>(values[i]),
                               StubTest::GetEntrypoint(self, kQuickSet16Instance),
                               self,
                               referrer);
 
-    uint16_t res = f->Get()->GetChar(obj->Get());
+    uint16_t res = f->GetChar(obj->Get());
     EXPECT_EQ(res, values[i]) << "Iteration " << i;
-    f->Get()->SetChar<false>(obj->Get(), ++res);
+    f->SetChar<false>(obj->Get(), ++res);
 
-    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                             reinterpret_cast<size_t>(obj->Get()),
                                             0U,
                                             StubTest::GetEntrypoint(self, kQuickGetCharInstance),
@@ -1525,25 +1525,25 @@
   std::cout << "Skipping set_char_instance as I don't know how to do that on " << kRuntimeISA << std::endl;
 #endif
 }
-static void GetSetShortInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
+static void GetSetShortInstance(Handle<mirror::Object>* obj, ArtField* f,
                              Thread* self, mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   int16_t values[] = { -0x7FFF, -32768, 0, 255, 32767, 0x7FFE };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               reinterpret_cast<size_t>(obj->Get()),
                               static_cast<size_t>(values[i]),
                               StubTest::GetEntrypoint(self, kQuickSet16Instance),
                               self,
                               referrer);
 
-    int16_t res = f->Get()->GetShort(obj->Get());
+    int16_t res = f->GetShort(obj->Get());
     EXPECT_EQ(res, values[i]) << "Iteration " << i;
-    f->Get()->SetShort<false>(obj->Get(), ++res);
+    f->SetShort<false>(obj->Get(), ++res);
 
-    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                             reinterpret_cast<size_t>(obj->Get()),
                                             0U,
                                             StubTest::GetEntrypoint(self, kQuickGetShortInstance),
@@ -1559,21 +1559,21 @@
 #endif
 }
 
-static void GetSet32Static(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSet32Static(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
                            StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   uint32_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               static_cast<size_t>(values[i]),
                               0U,
                               StubTest::GetEntrypoint(self, kQuickSet32Static),
                               self,
                               referrer);
 
-    size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                            0U, 0U,
                                            StubTest::GetEntrypoint(self, kQuickGet32Static),
                                            self,
@@ -1590,27 +1590,27 @@
 }
 
 
-static void GetSet32Instance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
+static void GetSet32Instance(Handle<mirror::Object>* obj, ArtField* f,
                              Thread* self, mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
   uint32_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               reinterpret_cast<size_t>(obj->Get()),
                               static_cast<size_t>(values[i]),
                               StubTest::GetEntrypoint(self, kQuickSet32Instance),
                               self,
                               referrer);
 
-    int32_t res = f->Get()->GetInt(obj->Get());
+    int32_t res = f->GetInt(obj->Get());
     EXPECT_EQ(res, static_cast<int32_t>(values[i])) << "Iteration " << i;
 
     res++;
-    f->Get()->SetInt<false>(obj->Get(), res);
+    f->SetInt<false>(obj->Get(), res);
 
-    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                             reinterpret_cast<size_t>(obj->Get()),
                                             0U,
                                             StubTest::GetEntrypoint(self, kQuickGet32Instance),
@@ -1649,17 +1649,17 @@
 }
 #endif
 
-static void GetSetObjStatic(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSetObjStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
                             StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
-  set_and_check_static((*f)->GetDexFieldIndex(), nullptr, self, referrer, test);
+  set_and_check_static(f->GetDexFieldIndex(), nullptr, self, referrer, test);
 
   // Allocate a string object for simplicity.
   mirror::String* str = mirror::String::AllocFromModifiedUtf8(self, "Test");
-  set_and_check_static((*f)->GetDexFieldIndex(), str, self, referrer, test);
+  set_and_check_static(f->GetDexFieldIndex(), str, self, referrer, test);
 
-  set_and_check_static((*f)->GetDexFieldIndex(), nullptr, self, referrer, test);
+  set_and_check_static(f->GetDexFieldIndex(), nullptr, self, referrer, test);
 #else
   UNUSED(f, self, referrer, test);
   LOG(INFO) << "Skipping setObjstatic as I don't know how to do that on " << kRuntimeISA;
@@ -1670,18 +1670,18 @@
 
 
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
-static void set_and_check_instance(Handle<mirror::ArtField>* f, mirror::Object* trg,
+static void set_and_check_instance(ArtField* f, mirror::Object* trg,
                                    mirror::Object* val, Thread* self, mirror::ArtMethod* referrer,
                                    StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+  test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                             reinterpret_cast<size_t>(trg),
                             reinterpret_cast<size_t>(val),
                             StubTest::GetEntrypoint(self, kQuickSetObjInstance),
                             self,
                             referrer);
 
-  size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+  size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                          reinterpret_cast<size_t>(trg),
                                          0U,
                                          StubTest::GetEntrypoint(self, kQuickGetObjInstance),
@@ -1690,11 +1690,11 @@
 
   EXPECT_EQ(res, reinterpret_cast<size_t>(val)) << "Value " << val;
 
-  EXPECT_EQ(val, f->Get()->GetObj(trg));
+  EXPECT_EQ(val, f->GetObj(trg));
 }
 #endif
 
-static void GetSetObjInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
+static void GetSetObjInstance(Handle<mirror::Object>* obj, ArtField* f,
                               Thread* self, mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__))
@@ -1716,20 +1716,20 @@
 
 // TODO: Complete these tests for 32b architectures.
 
-static void GetSet64Static(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSet64Static(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
                            StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if (defined(__x86_64__) && !defined(__APPLE__)) || defined(__aarch64__)
   uint64_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF, 0xFFFFFFFFFFFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3UWithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3UWithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                values[i],
                                StubTest::GetEntrypoint(self, kQuickSet64Static),
                                self,
                                referrer);
 
-    size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                            0U, 0U,
                                            StubTest::GetEntrypoint(self, kQuickGet64Static),
                                            self,
@@ -1746,27 +1746,27 @@
 }
 
 
-static void GetSet64Instance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f,
+static void GetSet64Instance(Handle<mirror::Object>* obj, ArtField* f,
                              Thread* self, mirror::ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if (defined(__x86_64__) && !defined(__APPLE__)) || defined(__aarch64__)
   uint64_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF, 0xFFFFFFFFFFFF };
 
   for (size_t i = 0; i < arraysize(values); ++i) {
-    test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                               reinterpret_cast<size_t>(obj->Get()),
                               static_cast<size_t>(values[i]),
                               StubTest::GetEntrypoint(self, kQuickSet64Instance),
                               self,
                               referrer);
 
-    int64_t res = f->Get()->GetLong(obj->Get());
+    int64_t res = f->GetLong(obj->Get());
     EXPECT_EQ(res, static_cast<int64_t>(values[i])) << "Iteration " << i;
 
     res++;
-    f->Get()->SetLong<false>(obj->Get(), res);
+    f->SetLong<false>(obj->Get(), res);
 
-    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()),
+    size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
                                             reinterpret_cast<size_t>(obj->Get()),
                                             0U,
                                             StubTest::GetEntrypoint(self, kQuickGet64Instance),
@@ -1792,7 +1792,7 @@
   CHECK(o != NULL);
 
   ScopedObjectAccess soa(self);
-  StackHandleScope<5> hs(self);
+  StackHandleScope<4> hs(self);
   Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object*>(o)));
   Handle<mirror::Class> c(hs.NewHandle(obj->GetClass()));
   // Need a method as a referrer
@@ -1801,112 +1801,80 @@
   // Play with it...
 
   // Static fields.
-  {
-    Handle<mirror::ObjectArray<mirror::ArtField>> fields(hs.NewHandle(c.Get()->GetSFields()));
-    int32_t num_fields = fields->GetLength();
-    for (int32_t i = 0; i < num_fields; ++i) {
-      StackHandleScope<1> hs2(self);
-      Handle<mirror::ArtField> f(hs2.NewHandle(fields->Get(i)));
-
-      Primitive::Type type = f->GetTypeAsPrimitiveType();
-      switch (type) {
-        case Primitive::Type::kPrimBoolean:
-          if (test_type == type) {
-            GetSetBooleanStatic(&f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimByte:
-          if (test_type == type) {
-            GetSetByteStatic(&f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimChar:
-          if (test_type == type) {
-            GetSetCharStatic(&f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimShort:
-          if (test_type == type) {
-            GetSetShortStatic(&f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimInt:
-          if (test_type == type) {
-            GetSet32Static(&f, self, m.Get(), test);
-          }
-          break;
-
-        case Primitive::Type::kPrimLong:
-          if (test_type == type) {
-            GetSet64Static(&f, self, m.Get(), test);
-          }
-          break;
-
-        case Primitive::Type::kPrimNot:
-          // Don't try array.
-          if (test_type == type && f->GetTypeDescriptor()[0] != '[') {
-            GetSetObjStatic(&f, self, m.Get(), test);
-          }
-          break;
-
-        default:
-          break;  // Skip.
-      }
+  ArtField* fields = c->GetSFields();
+  size_t num_fields = c->NumStaticFields();
+  for (size_t i = 0; i < num_fields; ++i) {
+    ArtField* f = &fields[i];
+    Primitive::Type type = f->GetTypeAsPrimitiveType();
+    if (test_type != type) {
+     continue;
+    }
+    switch (type) {
+      case Primitive::Type::kPrimBoolean:
+        GetSetBooleanStatic(f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimByte:
+        GetSetByteStatic(f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimChar:
+        GetSetCharStatic(f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimShort:
+        GetSetShortStatic(f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimInt:
+        GetSet32Static(f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimLong:
+        GetSet64Static(f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimNot:
+        // Don't try array.
+        if (f->GetTypeDescriptor()[0] != '[') {
+          GetSetObjStatic(f, self, m.Get(), test);
+        }
+        break;
+      default:
+        break;  // Skip.
     }
   }
 
   // Instance fields.
-  {
-    Handle<mirror::ObjectArray<mirror::ArtField>> fields(hs.NewHandle(c.Get()->GetIFields()));
-    int32_t num_fields = fields->GetLength();
-    for (int32_t i = 0; i < num_fields; ++i) {
-      StackHandleScope<1> hs2(self);
-      Handle<mirror::ArtField> f(hs2.NewHandle(fields->Get(i)));
-
-      Primitive::Type type = f->GetTypeAsPrimitiveType();
-      switch (type) {
-        case Primitive::Type::kPrimBoolean:
-          if (test_type == type) {
-            GetSetBooleanInstance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimByte:
-          if (test_type == type) {
-            GetSetByteInstance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimChar:
-          if (test_type == type) {
-            GetSetCharInstance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimShort:
-          if (test_type == type) {
-            GetSetShortInstance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-        case Primitive::Type::kPrimInt:
-          if (test_type == type) {
-            GetSet32Instance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-
-        case Primitive::Type::kPrimLong:
-          if (test_type == type) {
-            GetSet64Instance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-
-        case Primitive::Type::kPrimNot:
-          // Don't try array.
-          if (test_type == type && f->GetTypeDescriptor()[0] != '[') {
-            GetSetObjInstance(&obj, &f, self, m.Get(), test);
-          }
-          break;
-
-        default:
-          break;  // Skip.
-      }
+  fields = c->GetIFields();
+  num_fields = c->NumInstanceFields();
+  for (size_t i = 0; i < num_fields; ++i) {
+    ArtField* f = &fields[i];
+    Primitive::Type type = f->GetTypeAsPrimitiveType();
+    if (test_type != type) {
+      continue;
+    }
+    switch (type) {
+      case Primitive::Type::kPrimBoolean:
+        GetSetBooleanInstance(&obj, f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimByte:
+        GetSetByteInstance(&obj, f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimChar:
+        GetSetCharInstance(&obj, f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimShort:
+        GetSetShortInstance(&obj, f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimInt:
+        GetSet32Instance(&obj, f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimLong:
+        GetSet64Instance(&obj, f, self, m.Get(), test);
+        break;
+      case Primitive::Type::kPrimNot:
+        // Don't try array.
+        if (f->GetTypeDescriptor()[0] != '[') {
+          GetSetObjInstance(&obj, f, self, m.Get(), test);
+        }
+        break;
+      default:
+        break;  // Skip.
     }
   }
 
diff --git a/runtime/mirror/art_field-inl.h b/runtime/art_field-inl.h
similarity index 78%
rename from runtime/mirror/art_field-inl.h
rename to runtime/art_field-inl.h
index 986852f..aeb1273 100644
--- a/runtime/mirror/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -14,57 +14,51 @@
  * limitations under the License.
  */
 
-#ifndef ART_RUNTIME_MIRROR_ART_FIELD_INL_H_
-#define ART_RUNTIME_MIRROR_ART_FIELD_INL_H_
+#ifndef ART_RUNTIME_ART_FIELD_INL_H_
+#define ART_RUNTIME_ART_FIELD_INL_H_
 
 #include "art_field.h"
 
 #include "base/logging.h"
 #include "class_linker.h"
-#include "dex_cache.h"
 #include "gc/accounting/card_table-inl.h"
 #include "jvalue.h"
-#include "object-inl.h"
+#include "mirror/dex_cache.h"
+#include "mirror/object-inl.h"
 #include "primitive.h"
 #include "thread-inl.h"
 #include "scoped_thread_state_change.h"
 #include "well_known_classes.h"
 
 namespace art {
-namespace mirror {
 
-inline uint32_t ArtField::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength;
-  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
-}
-
-inline Class* ArtField::GetDeclaringClass() {
-  Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_));
-  DCHECK(result != NULL);
+inline mirror::Class* ArtField::GetDeclaringClass() {
+  mirror::Class* result = declaring_class_.Read();
+  DCHECK(result != nullptr);
   DCHECK(result->IsLoaded() || result->IsErroneous());
   return result;
 }
 
-inline void ArtField::SetDeclaringClass(Class *new_declaring_class) {
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), new_declaring_class);
+inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) {
+  declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
 }
 
 inline uint32_t ArtField::GetAccessFlags() {
   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_));
+  return access_flags_;
 }
 
 inline MemberOffset ArtField::GetOffset() {
   DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
-  return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_)));
+  return MemberOffset(offset_);
 }
 
 inline MemberOffset ArtField::GetOffsetDuringLinking() {
   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_)));
+  return MemberOffset(offset_);
 }
 
-inline uint32_t ArtField::Get32(Object* object) {
+inline uint32_t ArtField::Get32(mirror::Object* object) {
   DCHECK(object != nullptr) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
@@ -74,7 +68,7 @@
 }
 
 template<bool kTransactionActive>
-inline void ArtField::Set32(Object* object, uint32_t new_value) {
+inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) {
   DCHECK(object != nullptr) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
@@ -84,7 +78,7 @@
   }
 }
 
-inline uint64_t ArtField::Get64(Object* object) {
+inline uint64_t ArtField::Get64(mirror::Object* object) {
   DCHECK(object != NULL) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
@@ -94,7 +88,7 @@
 }
 
 template<bool kTransactionActive>
-inline void ArtField::Set64(Object* object, uint64_t new_value) {
+inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) {
   DCHECK(object != NULL) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
@@ -104,17 +98,17 @@
   }
 }
 
-inline Object* ArtField::GetObj(Object* object) {
+inline mirror::Object* ArtField::GetObj(mirror::Object* object) {
   DCHECK(object != NULL) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
-    return object->GetFieldObjectVolatile<Object>(GetOffset());
+    return object->GetFieldObjectVolatile<mirror::Object>(GetOffset());
   }
-  return object->GetFieldObject<Object>(GetOffset());
+  return object->GetFieldObject<mirror::Object>(GetOffset());
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetObj(Object* object, Object* new_value) {
+inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) {
   DCHECK(object != NULL) << PrettyField(this);
   DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
   if (UNLIKELY(IsVolatile())) {
@@ -143,46 +137,46 @@
     object->SetField ## type<kTransactionActive>(GetOffset(), value); \
   }
 
-inline uint8_t ArtField::GetBoolean(Object* object) {
+inline uint8_t ArtField::GetBoolean(mirror::Object* object) {
   FIELD_GET(object, Boolean);
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetBoolean(Object* object, uint8_t z) {
+inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) {
   FIELD_SET(object, Boolean, z);
 }
 
-inline int8_t ArtField::GetByte(Object* object) {
+inline int8_t ArtField::GetByte(mirror::Object* object) {
   FIELD_GET(object, Byte);
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetByte(Object* object, int8_t b) {
+inline void ArtField::SetByte(mirror::Object* object, int8_t b) {
   FIELD_SET(object, Byte, b);
 }
 
-inline uint16_t ArtField::GetChar(Object* object) {
+inline uint16_t ArtField::GetChar(mirror::Object* object) {
   FIELD_GET(object, Char);
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetChar(Object* object, uint16_t c) {
+inline void ArtField::SetChar(mirror::Object* object, uint16_t c) {
   FIELD_SET(object, Char, c);
 }
 
-inline int16_t ArtField::GetShort(Object* object) {
+inline int16_t ArtField::GetShort(mirror::Object* object) {
   FIELD_GET(object, Short);
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetShort(Object* object, int16_t s) {
+inline void ArtField::SetShort(mirror::Object* object, int16_t s) {
   FIELD_SET(object, Short, s);
 }
 
 #undef FIELD_GET
 #undef FIELD_SET
 
-inline int32_t ArtField::GetInt(Object* object) {
+inline int32_t ArtField::GetInt(mirror::Object* object) {
   if (kIsDebugBuild) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
@@ -191,7 +185,7 @@
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetInt(Object* object, int32_t i) {
+inline void ArtField::SetInt(mirror::Object* object, int32_t i) {
   if (kIsDebugBuild) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
@@ -199,7 +193,7 @@
   Set32<kTransactionActive>(object, i);
 }
 
-inline int64_t ArtField::GetLong(Object* object) {
+inline int64_t ArtField::GetLong(mirror::Object* object) {
   if (kIsDebugBuild) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
@@ -208,7 +202,7 @@
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetLong(Object* object, int64_t j) {
+inline void ArtField::SetLong(mirror::Object* object, int64_t j) {
   if (kIsDebugBuild) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
@@ -216,7 +210,7 @@
   Set64<kTransactionActive>(object, j);
 }
 
-inline float ArtField::GetFloat(Object* object) {
+inline float ArtField::GetFloat(mirror::Object* object) {
   DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this);
   JValue bits;
   bits.SetI(Get32(object));
@@ -224,14 +218,14 @@
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetFloat(Object* object, float f) {
+inline void ArtField::SetFloat(mirror::Object* object, float f) {
   DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this);
   JValue bits;
   bits.SetF(f);
   Set32<kTransactionActive>(object, bits.GetI());
 }
 
-inline double ArtField::GetDouble(Object* object) {
+inline double ArtField::GetDouble(mirror::Object* object) {
   DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this);
   JValue bits;
   bits.SetJ(Get64(object));
@@ -239,20 +233,20 @@
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetDouble(Object* object, double d) {
+inline void ArtField::SetDouble(mirror::Object* object, double d) {
   DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this);
   JValue bits;
   bits.SetD(d);
   Set64<kTransactionActive>(object, bits.GetJ());
 }
 
-inline Object* ArtField::GetObject(Object* object) {
+inline mirror::Object* ArtField::GetObject(mirror::Object* object) {
   DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this);
   return GetObj(object);
 }
 
 template<bool kTransactionActive>
-inline void ArtField::SetObject(Object* object, Object* l) {
+inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) {
   DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this);
   SetObj<kTransactionActive>(object, l);
 }
@@ -291,7 +285,7 @@
 }
 
 template <bool kResolve>
-inline Class* ArtField::GetType() {
+inline mirror::Class* ArtField::GetType() {
   const uint32_t field_index = GetDexFieldIndex();
   auto* declaring_class = GetDeclaringClass();
   if (UNLIKELY(declaring_class->IsProxyClass())) {
@@ -321,7 +315,7 @@
   return GetDexCache()->GetDexFile();
 }
 
-inline String* ArtField::GetStringName(Thread* self, bool resolve) {
+inline mirror::String* ArtField::GetStringName(Thread* self, bool resolve) {
   auto dex_field_index = GetDexFieldIndex();
   CHECK_NE(dex_field_index, DexFile::kDexNoIndex);
   auto* dex_cache = GetDexCache();
@@ -336,7 +330,6 @@
   return name;
 }
 
-}  // namespace mirror
 }  // namespace art
 
-#endif  // ART_RUNTIME_MIRROR_ART_FIELD_INL_H_
+#endif  // ART_RUNTIME_ART_FIELD_INL_H_
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
new file mode 100644
index 0000000..cdf8967
--- /dev/null
+++ b/runtime/art_field.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "art_field.h"
+
+#include "art_field-inl.h"
+#include "gc/accounting/card_table-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "runtime.h"
+#include "scoped_thread_state_change.h"
+#include "utils.h"
+#include "well_known_classes.h"
+
+namespace art {
+
+ArtField::ArtField() : access_flags_(0), field_dex_idx_(0), offset_(0) {
+  declaring_class_ = GcRoot<mirror::Class>(nullptr);
+}
+
+void ArtField::SetOffset(MemberOffset num_bytes) {
+  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
+  if (kIsDebugBuild && Runtime::Current()->IsAotCompiler() &&
+      Runtime::Current()->IsCompilingBootImage()) {
+    Primitive::Type type = GetTypeAsPrimitiveType();
+    if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
+      DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
+    }
+  }
+  // Not called within a transaction.
+  offset_ = num_bytes.Uint32Value();
+}
+
+void ArtField::VisitRoots(RootVisitor* visitor) {
+  declaring_class_.VisitRoot(visitor, RootInfo(kRootStickyClass));
+}
+
+ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
+  DCHECK(klass != nullptr);
+  auto* instance_fields = klass->GetIFields();
+  for (size_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) {
+    if (instance_fields[i].GetOffset().Uint32Value() == field_offset) {
+      return &instance_fields[i];
+    }
+  }
+  // We did not find field in the class: look into superclass.
+  return (klass->GetSuperClass() != nullptr) ?
+      FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset) : nullptr;
+}
+
+}  // namespace art
diff --git a/runtime/art_field.h b/runtime/art_field.h
new file mode 100644
index 0000000..5bdbe71
--- /dev/null
+++ b/runtime/art_field.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ART_FIELD_H_
+#define ART_RUNTIME_ART_FIELD_H_
+
+#include <jni.h>
+
+#include "gc_root.h"
+#include "modifiers.h"
+#include "object_callbacks.h"
+#include "offsets.h"
+#include "primitive.h"
+#include "read_barrier_option.h"
+
+namespace art {
+
+class DexFile;
+class ScopedObjectAccessAlreadyRunnable;
+
+namespace mirror {
+class Class;
+class DexCache;
+class Object;
+class String;
+}  // namespace mirror
+
+class ArtField {
+ public:
+  ArtField();
+
+  mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetDeclaringClass(mirror::Class *new_declaring_class)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // Not called within a transaction.
+    access_flags_ = new_access_flags;
+  }
+
+  bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccPublic) != 0;
+  }
+
+  bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccStatic) != 0;
+  }
+
+  bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccFinal) != 0;
+  }
+
+  uint32_t GetDexFieldIndex() {
+    return field_dex_idx_;
+  }
+
+  void SetDexFieldIndex(uint32_t new_idx) {
+    // Not called within a transaction.
+    field_dex_idx_ = new_idx;
+  }
+
+  // Offset to field within an Object.
+  MemberOffset GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static MemberOffset OffsetOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_));
+  }
+
+  MemberOffset GetOffsetDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetOffset(MemberOffset num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // field access, null object for static fields
+  uint8_t GetBoolean(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetBoolean(mirror::Object* object, uint8_t z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  int8_t GetByte(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetByte(mirror::Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  uint16_t GetChar(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetChar(mirror::Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  int16_t GetShort(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetShort(mirror::Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  int32_t GetInt(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetInt(mirror::Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  int64_t GetLong(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetLong(mirror::Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  float GetFloat(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetFloat(mirror::Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  double GetDouble(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetDouble(mirror::Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  mirror::Object* GetObject(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetObject(mirror::Object* object, mirror::Object* l)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Raw field accesses.
+  uint32_t Get32(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void Set32(mirror::Object* object, uint32_t new_value)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  uint64_t Get64(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void Set64(mirror::Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  mirror::Object* GetObj(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive>
+  void SetObj(mirror::Object* object, mirror::Object* new_value)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void VisitRoots(RootVisitor* visitor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return (GetAccessFlags() & kAccVolatile) != 0;
+  }
+
+  // Returns an instance field with this offset in the given class or nullptr if not found.
+  static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Resolves / returns the name from the dex cache.
+  mirror::String* GetStringName(Thread* self, bool resolve)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  Primitive::Type GetTypeAsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template <bool kResolve>
+  mirror::Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  GcRoot<mirror::Class>& DeclaringClassRoot() {
+    return declaring_class_;
+  }
+
+ private:
+  GcRoot<mirror::Class> declaring_class_;
+
+  uint32_t access_flags_;
+
+  // Dex cache index of field id
+  uint32_t field_dex_idx_;
+
+  // Offset of field within an instance or in the Class' static fields
+  uint32_t offset_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ART_FIELD_H_
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index dba4af8..4c83e88 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -135,13 +135,13 @@
 #define MIRROR_CLASS_COMPONENT_TYPE_OFFSET (4 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_COMPONENT_TYPE_OFFSET,
             art::mirror::Class::ComponentTypeOffset().Int32Value())
-#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (52 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (44 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_ACCESS_FLAGS_OFFSET,
             art::mirror::Class::AccessFlagsOffset().Int32Value())
-#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (80 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (96 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_OBJECT_SIZE_OFFSET,
             art::mirror::Class::ObjectSizeOffset().Int32Value())
-#define MIRROR_CLASS_STATUS_OFFSET (92 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_STATUS_OFFSET (108 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_STATUS_OFFSET,
             art::mirror::Class::StatusOffset().Int32Value())
 
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index dd29404..59d38ad 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -132,11 +132,10 @@
   free(reinterpret_cast<void*>(memory_));
 }
 
-MemMapArena::MemMapArena(size_t size) {
+MemMapArena::MemMapArena(size_t size, bool low_4gb) {
   std::string error_msg;
-  map_.reset(
-      MemMap::MapAnonymous("dalvik-LinearAlloc", nullptr, size, PROT_READ | PROT_WRITE, false,
-                           false, &error_msg));
+  map_.reset(MemMap::MapAnonymous(
+      "LinearAlloc", nullptr, size, PROT_READ | PROT_WRITE, low_4gb, false, &error_msg));
   CHECK(map_.get() != nullptr) << error_msg;
   memory_ = map_->Begin();
   size_ = map_->Size();
@@ -156,8 +155,12 @@
   }
 }
 
-ArenaPool::ArenaPool(bool use_malloc)
-    : use_malloc_(use_malloc), lock_("Arena pool lock"), free_arenas_(nullptr) {
+ArenaPool::ArenaPool(bool use_malloc, bool low_4gb)
+    : use_malloc_(use_malloc), lock_("Arena pool lock", kArenaPoolLock), free_arenas_(nullptr),
+      low_4gb_(low_4gb) {
+  if (low_4gb) {
+    CHECK(!use_malloc) << "low4gb must use map implementation";
+  }
   if (!use_malloc) {
     MemMap::Init();
   }
@@ -182,7 +185,8 @@
     }
   }
   if (ret == nullptr) {
-    ret = use_malloc_ ? static_cast<Arena*>(new MallocArena(size)) : new MemMapArena(size);
+    ret = use_malloc_ ? static_cast<Arena*>(new MallocArena(size)) :
+        new MemMapArena(size, low_4gb_);
   }
   ret->Reset();
   return ret;
@@ -229,6 +233,17 @@
   return ArenaAllocatorStats::BytesAllocated();
 }
 
+size_t ArenaAllocator::BytesUsed() const {
+  size_t total = ptr_ - begin_;
+  if (arena_head_ != nullptr) {
+    for (Arena* cur_arena = arena_head_->next_; cur_arena != nullptr;
+         cur_arena = cur_arena->next_) {
+     total += cur_arena->GetBytesAllocated();
+    }
+  }
+  return total;
+}
+
 ArenaAllocator::ArenaAllocator(ArenaPool* pool)
   : pool_(pool),
     begin_(nullptr),
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index cc7b856..3a86b61 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -165,7 +165,7 @@
 
 class MemMapArena FINAL : public Arena {
  public:
-  explicit MemMapArena(size_t size = Arena::kDefaultSize);
+  explicit MemMapArena(size_t size, bool low_4gb);
   virtual ~MemMapArena() { }
   void Release() OVERRIDE;
 
@@ -175,7 +175,7 @@
 
 class ArenaPool {
  public:
-  explicit ArenaPool(bool use_malloc = true);
+  explicit ArenaPool(bool use_malloc = true, bool low_4gb = false);
   ~ArenaPool();
   Arena* AllocArena(size_t size) LOCKS_EXCLUDED(lock_);
   void FreeArenaChain(Arena* first) LOCKS_EXCLUDED(lock_);
@@ -188,6 +188,7 @@
   const bool use_malloc_;
   mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   Arena* free_arenas_ GUARDED_BY(lock_);
+  const bool low_4gb_;
   DISALLOW_COPY_AND_ASSIGN(ArenaPool);
 };
 
@@ -227,6 +228,9 @@
   void ObtainNewArenaForAllocation(size_t allocation_size);
   size_t BytesAllocated() const;
   MemStats GetMemStats() const;
+  // The BytesUsed method sums up bytes allocated from arenas in arena_head_ and nodes.
+  // TODO: Change BytesAllocated to this behavior?
+  size_t BytesUsed() const;
 
  private:
   static constexpr size_t kAlignment = 8;
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index af00834..6e4b96c 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -73,6 +73,7 @@
   kRosAllocBulkFreeLock,
   kAllocSpaceLock,
   kBumpPointerSpaceBlockLock,
+  kArenaPoolLock,
   kDexFileMethodInlinerLock,
   kDexFileToMethodInlinerMapLock,
   kMarkSweepMarkStackLock,
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 2b0167d..f94ebea 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -19,6 +19,7 @@
 #include <sys/mman.h>
 #include <zlib.h>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/to_str.h"
 #include "class_linker.h"
@@ -27,7 +28,6 @@
 #include "gc/space/space.h"
 #include "java_vm_ext.h"
 #include "jni_internal.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -169,7 +169,7 @@
       return false;
     }
 
-    mirror::ArtField* f = CheckFieldID(soa, fid);
+    ArtField* f = CheckFieldID(soa, fid);
     if (f == nullptr) {
       return false;
     }
@@ -248,7 +248,7 @@
   bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
-    mirror::ArtField* f = CheckFieldID(soa, fid);
+    ArtField* f = CheckFieldID(soa, fid);
     if (f == nullptr) {
       return false;
     }
@@ -565,7 +565,7 @@
     if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
       return false;
     }
-    mirror::ArtField* field = soa.DecodeField(fid);
+    ArtField* field = soa.DecodeField(fid);
     DCHECK(field != nullptr);  // Already checked by Check.
     if (is_static != field->IsStatic()) {
       AbortF("attempt to access %s field %s: %p",
@@ -817,7 +817,7 @@
       }
       case 'f': {  // jfieldID
         jfieldID fid = arg.f;
-        mirror::ArtField* f = soa.DecodeField(fid);
+        ArtField* f = soa.DecodeField(fid);
         *msg += PrettyField(f);
         if (!entry) {
           StringAppendF(msg, " (%p)", fid);
@@ -986,14 +986,15 @@
     return true;
   }
 
-  mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
+  ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (fid == nullptr) {
       AbortF("jfieldID was NULL");
       return nullptr;
     }
-    mirror::ArtField* f = soa.DecodeField(fid);
-    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
+    ArtField* f = soa.DecodeField(fid);
+    // TODO: Better check here.
+    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
       Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
       AbortF("invalid jfieldID: %p", fid);
       return nullptr;
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 5198769..87d1c4c 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -17,10 +17,10 @@
 #ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
 #define ART_RUNTIME_CLASS_LINKER_INL_H_
 
+#include "art_field.h"
 #include "class_linker.h"
 #include "gc_root-inl.h"
 #include "gc/heap-inl.h"
-#include "mirror/art_field.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/iftable.h"
@@ -88,7 +88,7 @@
   return resolved_type;
 }
 
-inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtField* referrer) {
+inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtField* referrer) {
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
   mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache();
   mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx);
@@ -133,15 +133,19 @@
   return resolved_method;
 }
 
-inline mirror::ArtField* ClassLinker::GetResolvedField(uint32_t field_idx,
-                                                       mirror::Class* field_declaring_class) {
-  return field_declaring_class->GetDexCache()->GetResolvedField(field_idx);
+inline ArtField* ClassLinker::GetResolvedField(uint32_t field_idx, mirror::DexCache* dex_cache) {
+  return dex_cache->GetResolvedField(field_idx, image_pointer_size_);
 }
 
-inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
+inline ArtField* ClassLinker::GetResolvedField(
+    uint32_t field_idx, mirror::Class* field_declaring_class) {
+  return GetResolvedField(field_idx, field_declaring_class->GetDexCache());
+}
+
+inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
                                                    bool is_static) {
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
-  mirror::ArtField* resolved_field = GetResolvedField(field_idx, declaring_class);
+  ArtField* resolved_field = GetResolvedField(field_idx, declaring_class);
   if (UNLIKELY(resolved_field == NULL)) {
     StackHandleScope<2> hs(Thread::Current());
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
@@ -187,17 +191,6 @@
                              ifcount * mirror::IfTable::kMax));
 }
 
-inline mirror::ObjectArray<mirror::ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
-                                                                              size_t length) {
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  // Can't have movable field arrays for mark compact since we need these arrays to always be valid
-  // so that we can do Object::VisitReferences in the case where the fields don't fit in the
-  // reference offsets word.
-  return mirror::ObjectArray<mirror::ArtField>::Alloc(
-      self, GetClassRoot(kJavaLangReflectArtFieldArrayClass), length,
-      kMoveFieldArrays ? heap->GetCurrentAllocator() : heap->GetCurrentNonMovingAllocator());
-}
-
 inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(!class_roots_.IsNull());
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 12fa546..935c401 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -25,6 +25,7 @@
 #include <utility>
 #include <vector>
 
+#include "art_field-inl.h"
 #include "base/casts.h"
 #include "base/logging.h"
 #include "base/scoped_flock.h"
@@ -46,11 +47,11 @@
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
 #include "leb128.h"
+#include "linear_alloc.h"
 #include "oat.h"
 #include "oat_file.h"
 #include "oat_file_assistant.h"
 #include "object_lock.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
@@ -77,6 +78,8 @@
 
 namespace art {
 
+static constexpr bool kSanityCheckObjects = kIsDebugBuild;
+
 static void ThrowNoClassDefFoundError(const char* fmt, ...)
     __attribute__((__format__(__printf__, 1, 2)))
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -186,7 +189,7 @@
 template<int n>
 static void ShuffleForward(size_t* current_field_idx,
                            MemberOffset* field_offset,
-                           std::deque<mirror::ArtField*>* grouped_and_sorted_fields,
+                           std::deque<ArtField*>* grouped_and_sorted_fields,
                            FieldGaps* gaps)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(current_field_idx != nullptr);
@@ -196,7 +199,7 @@
 
   DCHECK(IsPowerOfTwo(n));
   while (!grouped_and_sorted_fields->empty()) {
-    mirror::ArtField* field = grouped_and_sorted_fields->front();
+    ArtField* field = grouped_and_sorted_fields->front();
     Primitive::Type type = field->GetTypeAsPrimitiveType();
     if (Primitive::ComponentSize(type) < n) {
       break;
@@ -357,6 +360,13 @@
   mirror::IntArray::SetArrayClass(int_array_class.Get());
   SetClassRoot(kIntArrayClass, int_array_class.Get());
 
+  // Create long array type for AllocDexCache (done in AppendToBootClassPath).
+  Handle<mirror::Class> long_array_class(hs.NewHandle(
+      AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize())));
+  long_array_class->SetComponentType(GetClassRoot(kPrimitiveLong));
+  mirror::LongArray::SetArrayClass(long_array_class.Get());
+  SetClassRoot(kLongArrayClass, long_array_class.Get());
+
   // now that these are registered, we can use AllocClass() and AllocObjectArray
 
   // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache.
@@ -366,15 +376,8 @@
   java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize());
   mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusResolved, self);
 
-  // Constructor, Field, Method, and AbstractMethod are necessary so
+  // Constructor, Method, and AbstractMethod are necessary so
   // that FindClass can link members.
-  Handle<mirror::Class> java_lang_reflect_ArtField(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::ArtField::ClassSize())));
-  CHECK(java_lang_reflect_ArtField.Get() != nullptr);
-  java_lang_reflect_ArtField->SetObjectSize(mirror::ArtField::InstanceSize());
-  SetClassRoot(kJavaLangReflectArtField, java_lang_reflect_ArtField.Get());
-  mirror::Class::SetStatus(java_lang_reflect_ArtField, mirror::Class::kStatusResolved, self);
-  mirror::ArtField::SetClass(java_lang_reflect_ArtField.Get());
 
   Handle<mirror::Class> java_lang_reflect_ArtMethod(hs.NewHandle(
     AllocClass(self, java_lang_Class.Get(), mirror::ArtMethod::ClassSize())));
@@ -398,12 +401,6 @@
   object_array_art_method->SetComponentType(java_lang_reflect_ArtMethod.Get());
   SetClassRoot(kJavaLangReflectArtMethodArrayClass, object_array_art_method.Get());
 
-  Handle<mirror::Class> object_array_art_field(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(),
-                 mirror::ObjectArray<mirror::ArtField>::ClassSize())));
-  object_array_art_field->SetComponentType(java_lang_reflect_ArtField.Get());
-  SetClassRoot(kJavaLangReflectArtFieldArrayClass, object_array_art_field.Get());
-
   // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
   // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
   // these roots.
@@ -471,8 +468,8 @@
   mirror::Class* found_int_array_class = FindSystemClass(self, "[I");
   CHECK_EQ(int_array_class.Get(), found_int_array_class);
 
-  SetClassRoot(kLongArrayClass, FindSystemClass(self, "[J"));
-  mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
+  mirror::Class* found_long_array_class = FindSystemClass(self, "[J");
+  CHECK_EQ(long_array_class.Get(), found_long_array_class);
 
   SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F"));
   mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
@@ -513,10 +510,6 @@
   mirror::Class* Art_method_class = FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;");
   CHECK_EQ(java_lang_reflect_ArtMethod.Get(), Art_method_class);
 
-  mirror::Class::SetStatus(java_lang_reflect_ArtField, mirror::Class::kStatusNotReady, self);
-  mirror::Class* Art_field_class = FindSystemClass(self, "Ljava/lang/reflect/ArtField;");
-  CHECK_EQ(java_lang_reflect_ArtField.Get(), Art_field_class);
-
   mirror::Class* String_array_class =
       FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass));
   CHECK_EQ(object_array_string.Get(), String_array_class);
@@ -525,10 +518,6 @@
       FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass));
   CHECK_EQ(object_array_art_method.Get(), Art_method_array_class);
 
-  mirror::Class* Art_field_array_class =
-      FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtFieldArrayClass));
-  CHECK_EQ(object_array_art_field.Get(), Art_field_array_class);
-
   // End of special init trickery, subsequent classes may be loaded via FindSystemClass.
 
   // Create java.lang.reflect.Proxy root.
@@ -624,23 +613,23 @@
   mirror::Class* java_lang_ref_FinalizerReference =
       FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
 
-  mirror::ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
+  ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
   CHECK_STREQ(pendingNext->GetName(), "pendingNext");
   CHECK_STREQ(pendingNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;");
 
-  mirror::ArtField* queue = java_lang_ref_Reference->GetInstanceField(1);
+  ArtField* queue = java_lang_ref_Reference->GetInstanceField(1);
   CHECK_STREQ(queue->GetName(), "queue");
   CHECK_STREQ(queue->GetTypeDescriptor(), "Ljava/lang/ref/ReferenceQueue;");
 
-  mirror::ArtField* queueNext = java_lang_ref_Reference->GetInstanceField(2);
+  ArtField* queueNext = java_lang_ref_Reference->GetInstanceField(2);
   CHECK_STREQ(queueNext->GetName(), "queueNext");
   CHECK_STREQ(queueNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;");
 
-  mirror::ArtField* referent = java_lang_ref_Reference->GetInstanceField(3);
+  ArtField* referent = java_lang_ref_Reference->GetInstanceField(3);
   CHECK_STREQ(referent->GetName(), "referent");
   CHECK_STREQ(referent->GetTypeDescriptor(), "Ljava/lang/Object;");
 
-  mirror::ArtField* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
+  ArtField* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
   CHECK_STREQ(zombie->GetName(), "zombie");
   CHECK_STREQ(zombie->GetTypeDescriptor(), "Ljava/lang/Object;");
 
@@ -802,6 +791,23 @@
   }
 }
 
+void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_UNUSED)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(obj != nullptr);
+  CHECK(obj->GetClass() != nullptr) << "Null class " << obj;
+  CHECK(obj->GetClass()->GetClass() != nullptr) << "Null class class " << obj;
+  if (obj->IsClass()) {
+    auto klass = obj->AsClass();
+    ArtField* fields[2] = { klass->GetSFields(), klass->GetIFields() };
+    size_t num_fields[2] = { klass->NumStaticFields(), klass->NumInstanceFields() };
+    for (size_t i = 0; i < 2; ++i) {
+      for (size_t j = 0; j < num_fields[i]; ++j) {
+        CHECK_EQ(fields[i][j].GetDeclaringClass(), klass);
+      }
+    }
+  }
+}
+
 void ClassLinker::InitFromImage() {
   VLOG(startup) << "ClassLinker::InitFromImage entering";
   CHECK(!init_done_);
@@ -882,6 +888,18 @@
   if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) {
     heap->VisitObjects(InitFromImageInterpretOnlyCallback, this);
   }
+  if (kSanityCheckObjects) {
+    for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
+      auto* dex_cache = dex_caches->Get(i);
+      for (size_t j = 0; j < dex_cache->NumResolvedFields(); ++j) {
+        auto* field = dex_cache->GetResolvedField(j, image_pointer_size_);
+        if (field != nullptr) {
+          CHECK(field->GetDeclaringClass()->GetClass() != nullptr);
+        }
+      }
+    }
+    heap->VisitObjects(SanityCheckObjectsCallback, nullptr);
+  }
 
   // reinit class_roots_
   mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass));
@@ -894,7 +912,6 @@
   mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
   mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass));
   mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
-  mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField));
   mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
   mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
   mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -913,18 +930,22 @@
 
 void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+  BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
+      visitor, RootInfo(kRootStickyClass));
   if ((flags & kVisitRootFlagAllRoots) != 0) {
-    BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
-        visitor, RootInfo(kRootStickyClass));
     for (GcRoot<mirror::Class>& root : class_table_) {
       buffered_visitor.VisitRoot(root);
+      root.Read()->VisitFieldRoots(buffered_visitor);
     }
+    // PreZygote classes can't move so we won't need to update fields' declaring classes.
     for (GcRoot<mirror::Class>& root : pre_zygote_class_table_) {
       buffered_visitor.VisitRoot(root);
+      root.Read()->VisitFieldRoots(buffered_visitor);
     }
   } else if ((flags & kVisitRootFlagNewRoots) != 0) {
     for (auto& root : new_class_roots_) {
       mirror::Class* old_ref = root.Read<kWithoutReadBarrier>();
+      old_ref->VisitFieldRoots(buffered_visitor);
       root.VisitRoot(visitor, RootInfo(kRootStickyClass));
       mirror::Class* new_ref = root.Read<kWithoutReadBarrier>();
       if (UNLIKELY(new_ref != old_ref)) {
@@ -937,6 +958,7 @@
       }
     }
   }
+  buffered_visitor.Flush();  // Flush before clearing new_class_roots_.
   if ((flags & kVisitRootFlagClearRootLog) != 0) {
     new_class_roots_.clear();
   }
@@ -1077,7 +1099,6 @@
   mirror::Class::ResetClass();
   mirror::String::ResetClass();
   mirror::Reference::ResetClass();
-  mirror::ArtField::ResetClass();
   mirror::ArtMethod::ResetClass();
   mirror::Field::ResetClass();
   mirror::Field::ResetArrayClass();
@@ -1095,7 +1116,7 @@
 }
 
 mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) {
-  gc::Heap* heap = Runtime::Current()->GetHeap();
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
   StackHandleScope<16> hs(self);
   Handle<mirror::Class> dex_cache_class(hs.NewHandle(GetClassRoot(kJavaLangDexCache)));
   Handle<mirror::DexCache> dex_cache(
@@ -1125,8 +1146,12 @@
   if (methods.Get() == nullptr) {
     return nullptr;
   }
-  Handle<mirror::ObjectArray<mirror::ArtField>>
-      fields(hs.NewHandle(AllocArtFieldArray(self, dex_file.NumFieldIds())));
+  Handle<mirror::Array> fields;
+  if (image_pointer_size_ == 8) {
+    fields = hs.NewHandle<mirror::Array>(mirror::LongArray::Alloc(self, dex_file.NumFieldIds()));
+  } else {
+    fields = hs.NewHandle<mirror::Array>(mirror::IntArray::Alloc(self, dex_file.NumFieldIds()));
+  }
   if (fields.Get() == nullptr) {
     return nullptr;
   }
@@ -1154,11 +1179,6 @@
   return AllocClass(self, GetClassRoot(kJavaLangClass), class_size);
 }
 
-mirror::ArtField* ClassLinker::AllocArtField(Thread* self) {
-  return down_cast<mirror::ArtField*>(
-      GetClassRoot(kJavaLangReflectArtField)->AllocNonMovableObject(self));
-}
-
 mirror::ArtMethod* ClassLinker::AllocArtMethod(Thread* self) {
   return down_cast<mirror::ArtMethod*>(
       GetClassRoot(kJavaLangReflectArtMethod)->AllocNonMovableObject(self));
@@ -1273,16 +1293,13 @@
     StackHandleScope<3> hs(self);
     // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
     // We need to get the DexPathList and loop through it.
-    Handle<mirror::ArtField> cookie_field =
-        hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
-    Handle<mirror::ArtField> dex_file_field =
-        hs.NewHandle(
-            soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
+    ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie);
+    ArtField* const dex_file_field =
+        soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
     mirror::Object* dex_path_list =
         soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)->
         GetObject(class_loader.Get());
-    if (dex_path_list != nullptr && dex_file_field.Get() != nullptr &&
-        cookie_field.Get() != nullptr) {
+    if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) {
       // DexPathList has an array dexElements of Elements[] which each contain a dex file.
       mirror::Object* dex_elements_obj =
           soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
@@ -1433,8 +1450,6 @@
       klass.Assign(GetClassRoot(kJavaLangRefReference));
     } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) {
       klass.Assign(GetClassRoot(kJavaLangDexCache));
-    } else if (strcmp(descriptor, "Ljava/lang/reflect/ArtField;") == 0) {
-      klass.Assign(GetClassRoot(kJavaLangReflectArtField));
     } else if (strcmp(descriptor, "Ljava/lang/reflect/ArtMethod;") == 0) {
       klass.Assign(GetClassRoot(kJavaLangReflectArtMethod));
     }
@@ -1452,16 +1467,10 @@
     return nullptr;
   }
   klass->SetDexCache(FindDexCache(dex_file));
-  LoadClass(self, dex_file, dex_class_def, klass, class_loader.Get());
+
+  SetupClass(dex_file, dex_class_def, klass, class_loader.Get());
+
   ObjectLock<mirror::Class> lock(self, klass);
-  if (self->IsExceptionPending()) {
-    // An exception occured during load, set status to erroneous while holding klass' lock in case
-    // notification is necessary.
-    if (!klass->IsErroneous()) {
-      mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
-    }
-    return nullptr;
-  }
   klass->SetClinitThreadId(self->GetTid());
 
   // Add the newly loaded class to the loaded classes table.
@@ -1472,6 +1481,20 @@
     return EnsureResolved(self, descriptor, existing);
   }
 
+  // Load the fields and other things after we are inserted in the table. This is so that we don't
+  // end up allocating unfree-able linear alloc resources and then lose the race condition. The
+  // other reason is that the field roots are only visited from the class table. So we need to be
+  // inserted before we allocate / fill in these fields.
+  LoadClass(self, dex_file, dex_class_def, klass);
+  if (self->IsExceptionPending()) {
+    // An exception occured during load, set status to erroneous while holding klass' lock in case
+    // notification is necessary.
+    if (!klass->IsErroneous()) {
+      mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
+    }
+    return nullptr;
+  }
+
   // Finish loading (if necessary) by finding parents
   CHECK(!klass->IsLoaded());
   if (!LoadSuperAndInterfaces(klass, dex_file)) {
@@ -1845,12 +1868,8 @@
   }
 }
 
-
-
-void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file,
-                            const DexFile::ClassDef& dex_class_def,
-                            Handle<mirror::Class> klass,
-                            mirror::ClassLoader* class_loader) {
+void ClassLinker::SetupClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+                             Handle<mirror::Class> klass, mirror::ClassLoader* class_loader) {
   CHECK(klass.Get() != nullptr);
   CHECK(klass->GetDexCache() != nullptr);
   CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus());
@@ -1868,13 +1887,15 @@
   klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
   klass->SetDexTypeIndex(dex_class_def.class_idx_);
   CHECK(klass->GetDexCacheStrings() != nullptr);
+}
 
+void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file,
+                            const DexFile::ClassDef& dex_class_def,
+                            Handle<mirror::Class> klass) {
   const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
   if (class_data == nullptr) {
     return;  // no fields or methods - for example a marker interface
   }
-
-
   bool has_oat_class = false;
   if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) {
     OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(),
@@ -1888,51 +1909,41 @@
   }
 }
 
+ArtField* ClassLinker::AllocArtFieldArray(Thread* self, size_t length) {
+  auto* const la = Runtime::Current()->GetLinearAlloc();
+  auto* ptr = reinterpret_cast<ArtField*>(la->AllocArray<ArtField>(self, length));
+  CHECK(ptr!= nullptr);
+  std::uninitialized_fill_n(ptr, length, ArtField());
+  return ptr;
+}
+
 void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file,
                                    const uint8_t* class_data,
                                    Handle<mirror::Class> klass,
                                    const OatFile::OatClass* oat_class) {
-  // Load fields.
+  // Load static fields.
   ClassDataItemIterator it(dex_file, class_data);
-  if (it.NumStaticFields() != 0) {
-    mirror::ObjectArray<mirror::ArtField>* statics = AllocArtFieldArray(self, it.NumStaticFields());
-    if (UNLIKELY(statics == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetSFields(statics);
-  }
-  if (it.NumInstanceFields() != 0) {
-    mirror::ObjectArray<mirror::ArtField>* fields =
-        AllocArtFieldArray(self, it.NumInstanceFields());
-    if (UNLIKELY(fields == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetIFields(fields);
-  }
+  const size_t num_sfields = it.NumStaticFields();
+  ArtField* sfields = num_sfields != 0 ? AllocArtFieldArray(self, num_sfields) : nullptr;
   for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+    CHECK_LT(i, num_sfields);
     self->AllowThreadSuspension();
-    StackHandleScope<1> hs(self);
-    Handle<mirror::ArtField> sfield(hs.NewHandle(AllocArtField(self)));
-    if (UNLIKELY(sfield.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetStaticField(i, sfield.Get());
-    LoadField(dex_file, it, klass, sfield);
+    LoadField(it, klass, &sfields[i]);
   }
+  klass->SetSFields(sfields);
+  klass->SetNumStaticFields(num_sfields);
+  DCHECK_EQ(klass->NumStaticFields(), num_sfields);
+  // Load instance fields.
+  const size_t num_ifields = it.NumInstanceFields();
+  ArtField* ifields = num_ifields != 0 ? AllocArtFieldArray(self, num_ifields) : nullptr;
   for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
+    CHECK_LT(i, num_ifields);
     self->AllowThreadSuspension();
-    StackHandleScope<1> hs(self);
-    Handle<mirror::ArtField> ifield(hs.NewHandle(AllocArtField(self)));
-    if (UNLIKELY(ifield.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetInstanceField(i, ifield.Get());
-    LoadField(dex_file, it, klass, ifield);
+    LoadField(it, klass, &ifields[i]);
   }
+  klass->SetIFields(ifields);
+  klass->SetNumInstanceFields(num_ifields);
+  DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
 
   // Load methods.
   if (it.NumDirectMethods() != 0) {
@@ -1995,10 +2006,9 @@
   DCHECK(!it.HasNext());
 }
 
-void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIterator& it,
-                            Handle<mirror::Class> klass,
-                            Handle<mirror::ArtField> dst) {
-  uint32_t field_idx = it.GetMemberIndex();
+void ClassLinker::LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass,
+                            ArtField* dst) {
+  const uint32_t field_idx = it.GetMemberIndex();
   dst->SetDexFieldIndex(field_idx);
   dst->SetDeclaringClass(klass.Get());
   dst->SetAccessFlags(it.GetFieldAccessFlags());
@@ -2282,13 +2292,12 @@
     } else if (strcmp(descriptor,
                       GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)) == 0) {
       new_class.Assign(GetClassRoot(kJavaLangReflectArtMethodArrayClass));
-    } else if (strcmp(descriptor,
-                      GetClassRootDescriptor(kJavaLangReflectArtFieldArrayClass)) == 0) {
-      new_class.Assign(GetClassRoot(kJavaLangReflectArtFieldArrayClass));
     } else if (strcmp(descriptor, "[C") == 0) {
       new_class.Assign(GetClassRoot(kCharArrayClass));
     } else if (strcmp(descriptor, "[I") == 0) {
       new_class.Assign(GetClassRoot(kIntArrayClass));
+    } else if (strcmp(descriptor, "[J") == 0) {
+      new_class.Assign(GetClassRoot(kLongArrayClass));
     }
   }
   if (new_class.Get() == nullptr) {
@@ -2919,32 +2928,20 @@
   mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
 
   // Instance fields are inherited, but we add a couple of static fields...
-  {
-    mirror::ObjectArray<mirror::ArtField>* sfields = AllocArtFieldArray(self, 2);
-    if (UNLIKELY(sfields == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetSFields(sfields);
-  }
+  const size_t num_fields = 2;
+  ArtField* sfields = AllocArtFieldArray(self, num_fields);
+  klass->SetSFields(sfields);
+  klass->SetNumStaticFields(num_fields);
+
   // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
   // our proxy, so Class.getInterfaces doesn't return the flattened set.
-  Handle<mirror::ArtField> interfaces_sfield(hs.NewHandle(AllocArtField(self)));
-  if (UNLIKELY(interfaces_sfield.Get() == nullptr)) {
-    CHECK(self->IsExceptionPending());  // OOME.
-    return nullptr;
-  }
-  klass->SetStaticField(0, interfaces_sfield.Get());
+  ArtField* interfaces_sfield = &sfields[0];
   interfaces_sfield->SetDexFieldIndex(0);
   interfaces_sfield->SetDeclaringClass(klass.Get());
   interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
+
   // 2. Create a static field 'throws' that holds exceptions thrown by our methods.
-  Handle<mirror::ArtField> throws_sfield(hs.NewHandle(AllocArtField(self)));
-  if (UNLIKELY(throws_sfield.Get() == nullptr)) {
-    CHECK(self->IsExceptionPending());  // OOME.
-    return nullptr;
-  }
-  klass->SetStaticField(1, throws_sfield.Get());
+  ArtField* throws_sfield = &sfields[1];
   throws_sfield->SetDexFieldIndex(1);
   throws_sfield->SetDeclaringClass(klass.Get());
   throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
@@ -3332,11 +3329,11 @@
     // Eagerly fill in static fields so that the we don't have to do as many expensive
     // Class::FindStaticField in ResolveField.
     for (size_t i = 0; i < num_static_fields; ++i) {
-      mirror::ArtField* field = klass->GetStaticField(i);
+      ArtField* field = klass->GetStaticField(i);
       const uint32_t field_idx = field->GetDexFieldIndex();
-      mirror::ArtField* resolved_field = dex_cache->GetResolvedField(field_idx);
+      ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
       if (resolved_field == nullptr) {
-        dex_cache->SetResolvedField(field_idx, field);
+        dex_cache->SetResolvedField(field_idx, field, image_pointer_size_);
       } else {
         DCHECK_EQ(field, resolved_field);
       }
@@ -3350,9 +3347,8 @@
       DCHECK(field_it.HasNextStaticField());
       CHECK(can_init_statics);
       for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
-        StackHandleScope<1> hs2(self);
-        Handle<mirror::ArtField> field(hs2.NewHandle(
-            ResolveField(dex_file, field_it.GetMemberIndex(), dex_cache, class_loader, true)));
+        ArtField* field = ResolveField(
+            dex_file, field_it.GetMemberIndex(), dex_cache, class_loader, true);
         if (Runtime::Current()->IsActiveTransaction()) {
           value_it.ReadValueToField<true>(field);
         } else {
@@ -3586,21 +3582,17 @@
 }
 
 void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class, mirror::Class* new_class) {
-  mirror::ObjectArray<mirror::ArtField>* fields = new_class->GetIFields();
-  if (fields != nullptr) {
-    for (int index = 0; index < fields->GetLength(); index ++) {
-      if (fields->Get(index)->GetDeclaringClass() == temp_class) {
-        fields->Get(index)->SetDeclaringClass(new_class);
-      }
+  ArtField* fields = new_class->GetIFields();
+  for (size_t i = 0, count = new_class->NumInstanceFields(); i < count; i++) {
+    if (fields[i].GetDeclaringClass() == temp_class) {
+      fields[i].SetDeclaringClass(new_class);
     }
   }
 
   fields = new_class->GetSFields();
-  if (fields != nullptr) {
-    for (int index = 0; index < fields->GetLength(); index ++) {
-      if (fields->Get(index)->GetDeclaringClass() == temp_class) {
-        fields->Get(index)->SetDeclaringClass(new_class);
-      }
+  for (size_t i = 0, count = new_class->NumStaticFields(); i < count; i++) {
+    if (fields[i].GetDeclaringClass() == temp_class) {
+      fields[i].SetDeclaringClass(new_class);
     }
   }
 
@@ -4567,7 +4559,7 @@
   explicit LinkFieldsComparator() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   }
   // No thread safety analysis as will be called from STL. Checked lock held in constructor.
-  bool operator()(mirror::ArtField* field1, mirror::ArtField* field2)
+  bool operator()(ArtField* field1, ArtField* field2)
       NO_THREAD_SAFETY_ANALYSIS {
     // First come reference fields, then 64-bit, then 32-bit, and then 16-bit, then finally 8-bit.
     Primitive::Type type1 = field1->GetTypeAsPrimitiveType();
@@ -4600,11 +4592,8 @@
 bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_static,
                              size_t* class_size) {
   self->AllowThreadSuspension();
-  size_t num_fields =
-      is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
-
-  mirror::ObjectArray<mirror::ArtField>* fields =
-      is_static ? klass->GetSFields() : klass->GetIFields();
+  const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
+  ArtField* const fields = is_static ? klass->GetSFields() : klass->GetIFields();
 
   // Initialize field_offset
   MemberOffset field_offset(0);
@@ -4623,13 +4612,11 @@
 
   // we want a relatively stable order so that adding new fields
   // minimizes disruption of C++ version such as Class and Method.
-  std::deque<mirror::ArtField*> grouped_and_sorted_fields;
+  std::deque<ArtField*> grouped_and_sorted_fields;
   const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension(
       "Naked ArtField references in deque");
   for (size_t i = 0; i < num_fields; i++) {
-    mirror::ArtField* f = fields->Get(i);
-    CHECK(f != nullptr) << PrettyClass(klass.Get());
-    grouped_and_sorted_fields.push_back(f);
+    grouped_and_sorted_fields.push_back(&fields[i]);
   }
   std::sort(grouped_and_sorted_fields.begin(), grouped_and_sorted_fields.end(),
             LinkFieldsComparator());
@@ -4640,7 +4627,7 @@
   FieldGaps gaps;
 
   for (; current_field < num_fields; current_field++) {
-    mirror::ArtField* field = grouped_and_sorted_fields.front();
+    ArtField* field = grouped_and_sorted_fields.front();
     Primitive::Type type = field->GetTypeAsPrimitiveType();
     bool isPrimitive = type != Primitive::kPrimNot;
     if (isPrimitive) {
@@ -4674,7 +4661,7 @@
     // We know there are no non-reference fields in the Reference classes, and we know
     // that 'referent' is alphabetically last, so this is easy...
     CHECK_EQ(num_reference_fields, num_fields) << PrettyClass(klass.Get());
-    CHECK_STREQ(fields->Get(num_fields - 1)->GetName(), "referent") << PrettyClass(klass.Get());
+    CHECK_STREQ(fields[num_fields - 1].GetName(), "referent") << PrettyClass(klass.Get());
     --num_reference_fields;
   }
 
@@ -4713,16 +4700,12 @@
                                     sizeof(mirror::HeapReference<mirror::Object>));
     MemberOffset current_ref_offset = start_ref_offset;
     for (size_t i = 0; i < num_fields; i++) {
-      mirror::ArtField* field = fields->Get(i);
-      if ((false)) {  // enable to debug field layout
-        LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
-                    << " class=" << PrettyClass(klass.Get())
-                    << " field=" << PrettyField(field)
-                    << " offset="
-                    << field->GetField32(mirror::ArtField::OffsetOffset());
-      }
+      ArtField* field = &fields[i];
+      VLOG(class_linker) << "LinkFields: " << (is_static ? "static" : "instance")
+          << " class=" << PrettyClass(klass.Get()) << " field=" << PrettyField(field) << " offset="
+          << field->GetOffset();
       if (i != 0) {
-        mirror::ArtField* prev_field = fields->Get(i - 1u);
+        ArtField* const prev_field = &fields[i - 1];
         // NOTE: The field names can be the same. This is not possible in the Java language
         // but it's valid Java/dex bytecode and for example proguard can generate such bytecode.
         CHECK_LE(strcmp(prev_field->GetName(), field->GetName()), 0);
@@ -4994,12 +4977,11 @@
   }
 }
 
-mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx,
-                                            Handle<mirror::DexCache> dex_cache,
-                                            Handle<mirror::ClassLoader> class_loader,
-                                            bool is_static) {
+ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx,
+                                    Handle<mirror::DexCache> dex_cache,
+                                    Handle<mirror::ClassLoader> class_loader, bool is_static) {
   DCHECK(dex_cache.Get() != nullptr);
-  mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
+  ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
   if (resolved != nullptr) {
     return resolved;
   }
@@ -5032,16 +5014,15 @@
       return nullptr;
     }
   }
-  dex_cache->SetResolvedField(field_idx, resolved);
+  dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_);
   return resolved;
 }
 
-mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
-                                               uint32_t field_idx,
-                                               Handle<mirror::DexCache> dex_cache,
-                                               Handle<mirror::ClassLoader> class_loader) {
+ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx,
+                                       Handle<mirror::DexCache> dex_cache,
+                                       Handle<mirror::ClassLoader> class_loader) {
   DCHECK(dex_cache.Get() != nullptr);
-  mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
+  ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
   if (resolved != nullptr) {
     return resolved;
   }
@@ -5060,7 +5041,7 @@
       dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
   resolved = mirror::Class::FindField(self, klass, name, type);
   if (resolved != nullptr) {
-    dex_cache->SetResolvedField(field_idx, resolved);
+    dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_);
   } else {
     ThrowNoSuchFieldError("", klass.Get(), type, name);
   }
@@ -5190,12 +5171,10 @@
     "Ljava/lang/String;",
     "Ljava/lang/DexCache;",
     "Ljava/lang/ref/Reference;",
-    "Ljava/lang/reflect/ArtField;",
     "Ljava/lang/reflect/ArtMethod;",
     "Ljava/lang/reflect/Field;",
     "Ljava/lang/reflect/Proxy;",
     "[Ljava/lang/String;",
-    "[Ljava/lang/reflect/ArtField;",
     "[Ljava/lang/reflect/ArtMethod;",
     "[Ljava/lang/reflect/Field;",
     "Ljava/lang/ClassLoader;",
@@ -5310,12 +5289,12 @@
   }
 
   // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex.
-  StackHandleScope<11> hs(self);
+  StackHandleScope<10> hs(self);
 
-  Handle<mirror::ArtField> h_dex_elements_field =
-      hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements));
+  ArtField* dex_elements_field =
+      soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements);
 
-  mirror::Class* dex_elements_class = h_dex_elements_field->GetType<true>();
+  mirror::Class* dex_elements_class = dex_elements_field->GetType<true>();
   DCHECK(dex_elements_class != nullptr);
   DCHECK(dex_elements_class->IsArrayClass());
   Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle(
@@ -5323,14 +5302,12 @@
   Handle<mirror::Class> h_dex_element_class =
       hs.NewHandle(dex_elements_class->GetComponentType());
 
-  Handle<mirror::ArtField> h_element_file_field =
-      hs.NewHandle(
-          soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
-  DCHECK_EQ(h_dex_element_class.Get(), h_element_file_field->GetDeclaringClass());
+  ArtField* element_file_field =
+      soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
+  DCHECK_EQ(h_dex_element_class.Get(), element_file_field->GetDeclaringClass());
 
-  Handle<mirror::ArtField> h_cookie_field =
-      hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
-  DCHECK_EQ(h_cookie_field->GetDeclaringClass(), h_element_file_field->GetType<false>());
+  ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie);
+  DCHECK_EQ(cookie_field->GetDeclaringClass(), element_file_field->GetType<false>());
 
   // Fill the elements array.
   int32_t index = 0;
@@ -5342,13 +5319,13 @@
     h_long_array->Set(0, reinterpret_cast<intptr_t>(dex_file));
 
     Handle<mirror::Object> h_dex_file = hs2.NewHandle(
-        h_cookie_field->GetDeclaringClass()->AllocObject(self));
+        cookie_field->GetDeclaringClass()->AllocObject(self));
     DCHECK(h_dex_file.Get() != nullptr);
-    h_cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get());
+    cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get());
 
     Handle<mirror::Object> h_element = hs2.NewHandle(h_dex_element_class->AllocObject(self));
     DCHECK(h_element.Get() != nullptr);
-    h_element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get());
+    element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get());
 
     h_dex_elements->Set(index, h_element.Get());
     index++;
@@ -5357,10 +5334,10 @@
 
   // Create DexPathList.
   Handle<mirror::Object> h_dex_path_list = hs.NewHandle(
-      h_dex_elements_field->GetDeclaringClass()->AllocObject(self));
+      dex_elements_field->GetDeclaringClass()->AllocObject(self));
   DCHECK(h_dex_path_list.Get() != nullptr);
   // Set elements.
-  h_dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get());
+  dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get());
 
   // Create PathClassLoader.
   Handle<mirror::Class> h_path_class_class = hs.NewHandle(
@@ -5369,20 +5346,20 @@
       h_path_class_class->AllocObject(self));
   DCHECK(h_path_class_loader.Get() != nullptr);
   // Set DexPathList.
-  Handle<mirror::ArtField> h_path_list_field = hs.NewHandle(
-      soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList));
-  DCHECK(h_path_list_field.Get() != nullptr);
-  h_path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get());
+  ArtField* path_list_field =
+      soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList);
+  DCHECK(path_list_field != nullptr);
+  path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get());
 
   // Make a pretend boot-classpath.
   // TODO: Should we scan the image?
-  Handle<mirror::ArtField> h_parent_field = hs.NewHandle(
+  ArtField* const parent_field =
       mirror::Class::FindField(self, hs.NewHandle(h_path_class_loader->GetClass()), "parent",
-                               "Ljava/lang/ClassLoader;"));
-  DCHECK(h_parent_field.Get() != nullptr);
+                               "Ljava/lang/ClassLoader;");
+  DCHECK(parent_field!= nullptr);
   mirror::Object* boot_cl =
       soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self);
-  h_parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl);
+  parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl);
 
   // Make it a global ref and return.
   ScopedLocalRef<jobject> local_ref(
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 577fec2..2427462 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -70,12 +70,10 @@
     kJavaLangString,
     kJavaLangDexCache,
     kJavaLangRefReference,
-    kJavaLangReflectArtField,
     kJavaLangReflectArtMethod,
     kJavaLangReflectField,
     kJavaLangReflectProxy,
     kJavaLangStringArrayClass,
-    kJavaLangReflectArtFieldArrayClass,
     kJavaLangReflectArtMethodArrayClass,
     kJavaLangReflectFieldArrayClass,
     kJavaLangClassLoader,
@@ -201,7 +199,7 @@
   mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtMethod* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtField* referrer)
+  mirror::Class* ResolveType(uint16_t type_idx, ArtField* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a type with the given ID from the DexFile, storing the
@@ -232,10 +230,11 @@
                                    InvokeType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtField* GetResolvedField(uint32_t field_idx, mirror::Class* field_declaring_class)
+  ArtField* GetResolvedField(uint32_t field_idx, mirror::Class* field_declaring_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
-                                 bool is_static)
+  ArtField* GetResolvedField(uint32_t field_idx, mirror::DexCache* dex_cache)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer, bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a field with a given ID from the DexFile, storing the
@@ -243,7 +242,7 @@
   // in ResolveType. What is unique is the is_static argument which is
   // used to determine if we are resolving a static or non-static
   // field.
-  mirror::ArtField* ResolveField(const DexFile& dex_file,
+  ArtField* ResolveField(const DexFile& dex_file,
                                  uint32_t field_idx,
                                  Handle<mirror::DexCache> dex_cache,
                                  Handle<mirror::ClassLoader> class_loader,
@@ -254,7 +253,7 @@
   // result in DexCache. The ClassLinker and ClassLoader are used as
   // in ResolveType. No is_static argument is provided so that Java
   // field resolution semantics are followed.
-  mirror::ArtField* ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx,
+  ArtField* ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx,
                                     Handle<mirror::DexCache> dex_cache,
                                     Handle<mirror::ClassLoader> class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -354,7 +353,7 @@
   mirror::IfTable* AllocIfTable(Thread* self, size_t ifcount)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ObjectArray<mirror::ArtField>* AllocArtFieldArray(Thread* self, size_t length)
+  ArtField* AllocArtFieldArray(Thread* self, size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::ObjectArray<mirror::StackTraceElement>* AllocStackTraceElementArray(Thread* self,
@@ -485,7 +484,6 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::DexCache* AllocDexCache(Thread* self, const DexFile& dex_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtField* AllocArtField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::Class* CreatePrimitiveClass(Thread* self, Primitive::Type type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -507,15 +505,21 @@
   uint32_t SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
                                             const DexFile::ClassDef& dex_class_def);
 
+  // Setup the classloader, class def index, type idx so that we can insert this class in the class
+  // table.
+  void SetupClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
+                  Handle<mirror::Class> klass, mirror::ClassLoader* class_loader)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   void LoadClass(Thread* self, const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
-                 Handle<mirror::Class> klass, mirror::ClassLoader* class_loader)
+                 Handle<mirror::Class> klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void LoadClassMembers(Thread* self, const DexFile& dex_file, const uint8_t* class_data,
                         Handle<mirror::Class> klass, const OatFile::OatClass* oat_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
-                 Handle<mirror::Class> klass, Handle<mirror::ArtField> dst)
+  void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass,
+                 ArtField* dst)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::ArtMethod* LoadMethod(Thread* self, const DexFile& dex_file,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 3f6c5a0..a31a785 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -19,14 +19,13 @@
 #include <memory>
 #include <string>
 
+#include "art_field-inl.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "dex_file.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "gc/heap.h"
 #include "mirror/accessible_object.h"
-#include "mirror/art_field-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
@@ -173,10 +172,9 @@
         method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes()));
   }
 
-  void AssertField(mirror::Class* klass, mirror::ArtField* field)
+  void AssertField(mirror::Class* klass, ArtField* field)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     EXPECT_TRUE(field != nullptr);
-    EXPECT_TRUE(field->GetClass() != nullptr);
     EXPECT_EQ(klass, field->GetDeclaringClass());
     EXPECT_TRUE(field->GetName() != nullptr);
     EXPECT_TRUE(field->GetType<true>() != nullptr);
@@ -262,30 +260,27 @@
     }
 
     for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
-      mirror::ArtField* field = klass->GetInstanceField(i);
+      ArtField* field = klass->GetInstanceField(i);
       AssertField(klass.Get(), field);
       EXPECT_FALSE(field->IsStatic());
     }
 
     for (size_t i = 0; i < klass->NumStaticFields(); i++) {
-      mirror::ArtField* field = klass->GetStaticField(i);
+      ArtField* field = klass->GetStaticField(i);
       AssertField(klass.Get(), field);
       EXPECT_TRUE(field->IsStatic());
     }
 
     // Confirm that all instances field offsets are packed together at the start.
     EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
-    StackHandleScope<1> hs(Thread::Current());
-    MutableHandle<mirror::ArtField> fhandle = hs.NewHandle<mirror::ArtField>(nullptr);
     MemberOffset start_ref_offset = klass->GetFirstReferenceInstanceFieldOffset();
     MemberOffset end_ref_offset(start_ref_offset.Uint32Value() +
                                 klass->NumReferenceInstanceFields() *
                                     sizeof(mirror::HeapReference<mirror::Object>));
     MemberOffset current_ref_offset = start_ref_offset;
     for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
-      mirror::ArtField* field = klass->GetInstanceField(i);
-      fhandle.Assign(field);
-      mirror::Class* field_type = fhandle->GetType<true>();
+      ArtField* field = klass->GetInstanceField(i);
+      mirror::Class* field_type = field->GetType<true>();
       ASSERT_TRUE(field_type != nullptr);
       if (!field->IsPrimitiveType()) {
         ASSERT_TRUE(!field_type->IsPrimitive());
@@ -293,7 +288,7 @@
         if (current_ref_offset.Uint32Value() == end_ref_offset.Uint32Value()) {
           // While Reference.referent is not primitive, the ClassLinker
           // treats it as such so that the garbage collector won't scan it.
-          EXPECT_EQ(PrettyField(fhandle.Get()),
+          EXPECT_EQ(PrettyField(field),
                     "java.lang.Object java.lang.ref.Reference.referent");
         } else {
           current_ref_offset = MemberOffset(current_ref_offset.Uint32Value() +
@@ -425,7 +420,7 @@
     }
 
     for (size_t i = 0; i < offsets.size(); i++) {
-      mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+      ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
       StringPiece field_name(field->GetName());
       if (field_name != offsets[i].java_name) {
         error = true;
@@ -434,7 +429,7 @@
     if (error) {
       for (size_t i = 0; i < offsets.size(); i++) {
         CheckOffset& offset = offsets[i];
-        mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+        ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
         StringPiece field_name(field->GetName());
         if (field_name != offsets[i].java_name) {
           LOG(ERROR) << "JAVA FIELD ORDER MISMATCH NEXT LINE:";
@@ -448,7 +443,7 @@
 
     for (size_t i = 0; i < offsets.size(); i++) {
       CheckOffset& offset = offsets[i];
-      mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+      ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
       if (field->GetOffset().Uint32Value() != offset.cpp_offset) {
         error = true;
       }
@@ -456,7 +451,7 @@
     if (error) {
       for (size_t i = 0; i < offsets.size(); i++) {
         CheckOffset& offset = offsets[i];
-        mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
+        ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i);
         if (field->GetOffset().Uint32Value() != offset.cpp_offset) {
           LOG(ERROR) << "OFFSET MISMATCH NEXT LINE:";
         }
@@ -486,15 +481,6 @@
   };
 };
 
-struct ArtFieldOffsets : public CheckOffsets<mirror::ArtField> {
-  ArtFieldOffsets() : CheckOffsets<mirror::ArtField>(false, "Ljava/lang/reflect/ArtField;") {
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, access_flags_),    "accessFlags"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, declaring_class_), "declaringClass"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, field_dex_idx_),   "fieldDexIndex"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, offset_),          "offset"));
-  };
-};
-
 struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
   ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") {
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_),                   "accessFlags"));
@@ -522,8 +508,10 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, ifields_),                       "iFields"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, iftable_),                       "ifTable"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, name_),                          "name"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_),           "numInstanceFields"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_), "numReferenceInstanceFields"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),   "numReferenceStaticFields"));
+    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_),             "numStaticFields"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, object_size_),                   "objectSize"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_),                "primitiveType"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),    "referenceInstanceOffsets"));
@@ -629,7 +617,6 @@
 TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
   ScopedObjectAccess soa(Thread::Current());
   EXPECT_TRUE(ObjectOffsets().Check());
-  EXPECT_TRUE(ArtFieldOffsets().Check());
   EXPECT_TRUE(ArtMethodOffsets().Check());
   EXPECT_TRUE(ClassOffsets().Check());
   EXPECT_TRUE(StringOffsets().Check());
@@ -844,21 +831,21 @@
   NullHandle<mirror::ClassLoader> class_loader;
   mirror::Class* c;
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Byte;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Character;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Double;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Float;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Integer;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Long;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Short;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName());
+  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
 }
 
 TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
@@ -892,49 +879,47 @@
 
   EXPECT_EQ(9U, statics->NumStaticFields());
 
-  mirror::ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z");
-  std::string temp;
-  EXPECT_STREQ(s0->GetClass()->GetDescriptor(&temp), "Ljava/lang/reflect/ArtField;");
+  ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z");
   EXPECT_EQ(s0->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
   EXPECT_EQ(true, s0->GetBoolean(statics.Get()));
   s0->SetBoolean<false>(statics.Get(), false);
 
-  mirror::ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics, "s1", "B");
+  ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics, "s1", "B");
   EXPECT_EQ(s1->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
   EXPECT_EQ(5, s1->GetByte(statics.Get()));
   s1->SetByte<false>(statics.Get(), 6);
 
-  mirror::ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics, "s2", "C");
+  ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics, "s2", "C");
   EXPECT_EQ(s2->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
   EXPECT_EQ('a', s2->GetChar(statics.Get()));
   s2->SetChar<false>(statics.Get(), 'b');
 
-  mirror::ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics, "s3", "S");
+  ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics, "s3", "S");
   EXPECT_EQ(s3->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
   EXPECT_EQ(-536, s3->GetShort(statics.Get()));
   s3->SetShort<false>(statics.Get(), -535);
 
-  mirror::ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics, "s4", "I");
+  ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics, "s4", "I");
   EXPECT_EQ(s4->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   EXPECT_EQ(2000000000, s4->GetInt(statics.Get()));
   s4->SetInt<false>(statics.Get(), 2000000001);
 
-  mirror::ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics, "s5", "J");
+  ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics, "s5", "J");
   EXPECT_EQ(s5->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
   EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.Get()));
   s5->SetLong<false>(statics.Get(), INT64_C(0x34567890abcdef12));
 
-  mirror::ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F");
+  ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F");
   EXPECT_EQ(s6->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
   EXPECT_DOUBLE_EQ(0.5, s6->GetFloat(statics.Get()));
   s6->SetFloat<false>(statics.Get(), 0.75);
 
-  mirror::ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D");
+  ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D");
   EXPECT_EQ(s7->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
   EXPECT_DOUBLE_EQ(16777217.0, s7->GetDouble(statics.Get()));
   s7->SetDouble<false>(statics.Get(), 16777219);
 
-  mirror::ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8",
+  ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8",
                                                         "Ljava/lang/String;");
   EXPECT_EQ(s8->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
   EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android"));
@@ -1006,13 +991,13 @@
   EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
   EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
 
-  mirror::ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo",
+  ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo",
                                                           "Ljava/lang/String;");
-  mirror::ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo",
+  ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo",
                                                           "Ljava/lang/String;");
-  mirror::ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo",
+  ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo",
                                                           "Ljava/lang/String;");
-  mirror::ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo",
+  ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo",
                                                           "Ljava/lang/String;");
   ASSERT_TRUE(Afoo != nullptr);
   EXPECT_EQ(Afoo, Bfoo);
@@ -1110,9 +1095,6 @@
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/DexCache;", class_loader);
   EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize());
 
-  c = class_linker_->FindClass(soa.Self(), "Ljava/lang/reflect/ArtField;", class_loader);
-  EXPECT_EQ(c->GetClassSize(), mirror::ArtField::ClassSize());
-
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/reflect/ArtMethod;", class_loader);
   EXPECT_EQ(c->GetClassSize(), mirror::ArtMethod::ClassSize());
 }
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index d400010..60b7fa2 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -398,7 +398,7 @@
 
   ScopedObjectAccess soa(Thread::Current());
 
-  StackHandleScope<4> hs(Thread::Current());
+  StackHandleScope<2> hs(soa.Self());
   Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
       soa.Decode<mirror::ClassLoader*>(jclass_loader));
 
@@ -409,16 +409,13 @@
 
   // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
   // We need to get the DexPathList and loop through it.
-  Handle<mirror::ArtField> cookie_field =
-      hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie));
-  Handle<mirror::ArtField> dex_file_field =
-      hs.NewHandle(
-          soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile));
+  ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie);
+  ArtField* dex_file_field =
+      soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
   mirror::Object* dex_path_list =
       soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)->
       GetObject(class_loader.Get());
-  if (dex_path_list != nullptr && dex_file_field.Get() != nullptr &&
-      cookie_field.Get() != nullptr) {
+  if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) {
     // DexPathList has an array dexElements of Elements[] which each contain a dex file.
     mirror::Object* dex_elements_obj =
         soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 36de221..407746f 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -18,6 +18,7 @@
 
 #include <sstream>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
@@ -160,7 +161,7 @@
   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
 }
 
-void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) {
+void ThrowIllegalAccessErrorField(mirror::Class* referrer, ArtField* accessed) {
   std::ostringstream msg;
   msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
       << PrettyDescriptor(referrer) << "'";
@@ -168,7 +169,7 @@
 }
 
 void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
-                                       mirror::ArtField* accessed) {
+                                       ArtField* accessed) {
   std::ostringstream msg;
   msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
       << PrettyMethod(referrer) << "'";
@@ -226,7 +227,7 @@
                  msg.str().c_str());
 }
 
-void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
+void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static,
                                             mirror::ArtMethod* referrer) {
   std::ostringstream msg;
   msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
@@ -314,7 +315,7 @@
 
 // NullPointerException
 
-void ThrowNullPointerExceptionForFieldAccess(mirror::ArtField* field, bool is_read) {
+void ThrowNullPointerExceptionForFieldAccess(ArtField* field, bool is_read) {
   std::ostringstream msg;
   msg << "Attempt to " << (is_read ? "read from" : "write to")
       << " field '" << PrettyField(field, true) << "' on a null object reference";
@@ -394,7 +395,7 @@
     case Instruction::IGET_BYTE:
     case Instruction::IGET_CHAR:
     case Instruction::IGET_SHORT: {
-      mirror::ArtField* field =
+      ArtField* field =
           Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
       ThrowNullPointerExceptionForFieldAccess(field, true /* read */);
       break;
@@ -408,7 +409,7 @@
     case Instruction::IGET_OBJECT_QUICK: {
       // Since we replaced the field index, we ask the verifier to tell us which
       // field is accessed at this location.
-      mirror::ArtField* field =
+      ArtField* field =
           verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc);
       if (field != NULL) {
         // NPE with precise message.
@@ -426,7 +427,7 @@
     case Instruction::IPUT_BYTE:
     case Instruction::IPUT_CHAR:
     case Instruction::IPUT_SHORT: {
-      mirror::ArtField* field =
+      ArtField* field =
           Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
       ThrowNullPointerExceptionForFieldAccess(field, false /* write */);
       break;
@@ -440,7 +441,7 @@
     case Instruction::IPUT_OBJECT_QUICK: {
       // Since we replaced the field index, we ask the verifier to tell us which
       // field is accessed at this location.
-      mirror::ArtField* field =
+      ArtField* field =
           verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc);
       if (field != NULL) {
         // NPE with precise message.
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index 9e749e3..df95cf9 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -22,11 +22,11 @@
 
 namespace art {
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class Class;
   class Object;
 }  // namespace mirror
+class ArtField;
 class Signature;
 class StringPiece;
 
@@ -81,10 +81,10 @@
 void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed)
+void ThrowIllegalAccessErrorField(mirror::Class* referrer, ArtField* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, mirror::ArtField* accessed)
+void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, ArtField* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...)
@@ -112,7 +112,7 @@
                                                                 mirror::ArtMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
+void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static,
                                             mirror::ArtMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
@@ -160,7 +160,7 @@
 
 // NullPointerException
 
-void ThrowNullPointerExceptionForFieldAccess(mirror::ArtField* field,
+void ThrowNullPointerExceptionForFieldAccess(ArtField* field,
                                              bool is_read)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index a909a1a..12fe863 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -21,6 +21,7 @@
 #include <set>
 
 #include "arch/context.h"
+#include "art_field-inl.h"
 #include "class_linker.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
@@ -30,7 +31,6 @@
 #include "gc/space/space-inl.h"
 #include "handle_scope.h"
 #include "jdwp/object_registry.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
@@ -266,14 +266,14 @@
   }
 
   void FieldRead(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
-                 uint32_t dex_pc, mirror::ArtField* field)
+                 uint32_t dex_pc, ArtField* field)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     UNUSED(thread);
     Dbg::PostFieldAccessEvent(method, dex_pc, this_object, field);
   }
 
   void FieldWritten(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
-                    mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field,
+                    mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
                     const JValue& field_value)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value);
@@ -1336,8 +1336,7 @@
   return JDWP::ERR_NONE;
 }
 
-JDWP::FieldId Dbg::ToFieldId(const mirror::ArtField* f) {
-  CHECK(!kMovingFields);
+JDWP::FieldId Dbg::ToFieldId(const ArtField* f) {
   return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f));
 }
 
@@ -1347,10 +1346,9 @@
   return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(m));
 }
 
-static mirror::ArtField* FromFieldId(JDWP::FieldId fid)
+static ArtField* FromFieldId(JDWP::FieldId fid)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CHECK(!kMovingFields);
-  return reinterpret_cast<mirror::ArtField*>(static_cast<uintptr_t>(fid));
+  return reinterpret_cast<ArtField*>(static_cast<uintptr_t>(fid));
 }
 
 static mirror::ArtMethod* FromMethodId(JDWP::MethodId mid)
@@ -1387,8 +1385,8 @@
 }
 
 bool Dbg::MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id,
-                     mirror::ArtField* event_field) {
-  mirror::ArtField* expected_field = FromFieldId(expected_field_id);
+                     ArtField* event_field) {
+  ArtField* expected_field = FromFieldId(expected_field_id);
   if (expected_field != event_field) {
     return false;
   }
@@ -1423,7 +1421,7 @@
 }
 
 std::string Dbg::GetFieldName(JDWP::FieldId field_id) {
-  mirror::ArtField* f = FromFieldId(field_id);
+  ArtField* f = FromFieldId(field_id);
   if (f == nullptr) {
     return "NULL";
   }
@@ -1510,7 +1508,7 @@
   expandBufAdd4BE(pReply, instance_field_count + static_field_count);
 
   for (size_t i = 0; i < instance_field_count + static_field_count; ++i) {
-    mirror::ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count);
+    ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count);
     expandBufAddFieldId(pReply, ToFieldId(f));
     expandBufAddUtf8String(pReply, f->GetName());
     expandBufAddUtf8String(pReply, f->GetTypeDescriptor());
@@ -1680,7 +1678,7 @@
 
 void Dbg::OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value,
                            JDWP::ExpandBuf* pReply) {
-  mirror::ArtField* f = FromFieldId(field_id);
+  ArtField* f = FromFieldId(field_id);
   JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
   OutputJValue(tag, field_value, pReply);
 }
@@ -1723,7 +1721,7 @@
   if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) {
     return JDWP::ERR_INVALID_OBJECT;
   }
-  mirror::ArtField* f = FromFieldId(field_id);
+  ArtField* f = FromFieldId(field_id);
 
   mirror::Class* receiver_class = c;
   if (receiver_class == nullptr && o != nullptr) {
@@ -1785,7 +1783,7 @@
   if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) {
     return JDWP::ERR_INVALID_OBJECT;
   }
-  mirror::ArtField* f = FromFieldId(field_id);
+  ArtField* f = FromFieldId(field_id);
 
   // The RI only enforces the static/non-static mismatch in one direction.
   // TODO: should we change the tests and check both?
@@ -1822,11 +1820,10 @@
     if (v != nullptr) {
       mirror::Class* field_type;
       {
-        StackHandleScope<3> hs(Thread::Current());
+        StackHandleScope<2> hs(Thread::Current());
         HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v));
-        HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
         HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
-        field_type = h_f->GetType<true>();
+        field_type = f->GetType<true>();
       }
       if (!field_type->IsAssignableFrom(v->GetClass())) {
         return JDWP::ERR_INVALID_OBJECT;
@@ -1904,7 +1901,7 @@
   // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName.
   mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error);
   CHECK(thread_object != nullptr) << error;
-  mirror::ArtField* java_lang_Thread_name_field =
+  ArtField* java_lang_Thread_name_field =
       soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
   mirror::String* s =
       reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object));
@@ -1935,7 +1932,7 @@
   } else if (error == JDWP::ERR_NONE) {
     mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
     CHECK(c != nullptr);
-    mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
+    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
     CHECK(f != nullptr);
     mirror::Object* group = f->GetObject(thread_object);
     CHECK(group != nullptr);
@@ -1976,7 +1973,7 @@
     return error;
   }
   ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupName");
-  mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name);
+  ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name);
   CHECK(f != nullptr);
   mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group));
 
@@ -1995,7 +1992,7 @@
   mirror::Object* parent;
   {
     ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupParent");
-    mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent);
+    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent);
     CHECK(f != nullptr);
     parent = f->GetObject(thread_group);
   }
@@ -2010,7 +2007,7 @@
   CHECK(thread_group != nullptr);
 
   // Get the ArrayList<ThreadGroup> "groups" out of this thread group...
-  mirror::ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups);
+  ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups);
   mirror::Object* groups_array_list = groups_field->GetObject(thread_group);
   {
     // The "groups" field is declared as a java.util.List: check it really is
@@ -2022,8 +2019,8 @@
   }
 
   // Get the array and size out of the ArrayList<ThreadGroup>...
-  mirror::ArtField* array_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_array);
-  mirror::ArtField* size_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_size);
+  ArtField* array_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_array);
+  ArtField* size_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_size);
   mirror::ObjectArray<mirror::Object>* groups_array =
       array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>();
   const int32_t size = size_field->GetInt(groups_array_list);
@@ -2069,7 +2066,7 @@
 
 JDWP::ObjectId Dbg::GetSystemThreadGroupId() {
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup);
+  ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup);
   mirror::Object* group = f->GetObject(f->GetDeclaringClass());
   return gRegistry->Add(group);
 }
@@ -2166,7 +2163,7 @@
   if (desired_thread_group == nullptr) {
     return true;
   }
-  mirror::ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
+  ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
   DCHECK(thread_group_field != nullptr);
   mirror::Object* group = thread_group_field->GetObject(peer);
   return (group == desired_thread_group);
@@ -2771,7 +2768,7 @@
 }
 
 void Dbg::PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc,
-                               mirror::Object* this_object, mirror::ArtField* f) {
+                               mirror::Object* this_object, ArtField* f) {
   if (!IsDebuggerActive()) {
     return;
   }
@@ -2784,7 +2781,7 @@
 }
 
 void Dbg::PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc,
-                                     mirror::Object* this_object, mirror::ArtField* f,
+                                     mirror::Object* this_object, ArtField* f,
                                      const JValue* field_value) {
   if (!IsDebuggerActive()) {
     return;
diff --git a/runtime/debugger.h b/runtime/debugger.h
index dd7f9c5..c287121 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -37,13 +37,13 @@
 
 namespace art {
 namespace mirror {
-class ArtField;
 class ArtMethod;
 class Class;
 class Object;
 class Throwable;
 }  // namespace mirror
 class AllocRecord;
+class ArtField;
 class ObjectRegistry;
 class ScopedObjectAccessUnchecked;
 class StackVisitor;
@@ -340,7 +340,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static bool MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id,
-                         mirror::ArtField* event_field)
+                         ArtField* event_field)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static bool MatchInstance(JDWP::ObjectId expected_instance_id, mirror::Object* event_instance)
@@ -525,10 +525,10 @@
     kMethodExit     = 0x08,
   };
   static void PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
-                                   mirror::ArtField* f)
+                                   ArtField* f)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc,
-                                         mirror::Object* this_object, mirror::ArtField* f,
+                                         mirror::Object* this_object, ArtField* f,
                                          const JValue* field_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void PostException(mirror::Throwable* exception)
@@ -706,7 +706,7 @@
   static JDWP::JdwpTypeTag GetTypeTag(mirror::Class* klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static JDWP::FieldId ToFieldId(const mirror::ArtField* f)
+  static JDWP::FieldId ToFieldId(const ArtField* f)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void SetJdwpLocation(JDWP::JdwpLocation* location, mirror::ArtMethod* m, uint32_t dex_pc)
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 8685d8e..03a47a3 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -27,6 +27,7 @@
 #include <memory>
 #include <sstream>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
 #include "class_linker.h"
@@ -34,7 +35,6 @@
 #include "dex_file_verifier.h"
 #include "globals.h"
 #include "leb128.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/string.h"
 #include "os.h"
@@ -1210,7 +1210,7 @@
 }
 
 template<bool kTransactionActive>
-void EncodedStaticFieldValueIterator::ReadValueToField(Handle<mirror::ArtField> field) const {
+void EncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const {
   switch (type_) {
     case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z); break;
     case kByte:    field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
@@ -1222,13 +1222,11 @@
     case kDouble:  field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break;
     case kNull:    field->SetObject<kTransactionActive>(field->GetDeclaringClass(), NULL); break;
     case kString: {
-      CHECK(!kMovingFields);
       mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_);
       field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
       break;
     }
     case kType: {
-      CHECK(!kMovingFields);
       mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_,
                                                      *class_loader_);
       field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
@@ -1237,8 +1235,8 @@
     default: UNIMPLEMENTED(FATAL) << ": type " << type_;
   }
 }
-template void EncodedStaticFieldValueIterator::ReadValueToField<true>(Handle<mirror::ArtField> field) const;
-template void EncodedStaticFieldValueIterator::ReadValueToField<false>(Handle<mirror::ArtField> field) const;
+template void EncodedStaticFieldValueIterator::ReadValueToField<true>(ArtField* field) const;
+template void EncodedStaticFieldValueIterator::ReadValueToField<false>(ArtField* field) const;
 
 CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
   handler_.address_ = -1;
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 8e2d6c2..5bdd9b6 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -37,11 +37,11 @@
 // TODO: remove dependencies on mirror classes, primarily by moving
 // EncodedStaticFieldValueIterator to its own file.
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class ClassLoader;
   class DexCache;
 }  // namespace mirror
+class ArtField;
 class ClassLinker;
 class MemMap;
 class OatDexFile;
@@ -1298,7 +1298,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<bool kTransactionActive>
-  void ReadValueToField(Handle<mirror::ArtField> field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void ReadValueToField(ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool HasNext() const { return pos_ < array_size_; }
 
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 8a13d34..cbfba12 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -252,7 +252,7 @@
 }
 
 template<FindFieldType type, bool access_check>
-inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
                                            Thread* self, size_t expected_size) {
   bool is_primitive;
   bool is_set;
@@ -269,7 +269,7 @@
     default:                     is_primitive = true;  is_set = true;  is_static = true;  break;
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
+  ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
   if (UNLIKELY(resolved_field == nullptr)) {
     DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
     return nullptr;  // Failure.
@@ -324,7 +324,7 @@
 // Explicit template declarations of FindFieldFromCode for all field access types.
 #define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \
 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \
-mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \
+ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \
                                                           mirror::ArtMethod* referrer, \
                                                           Thread* self, size_t expected_size) \
 
@@ -469,11 +469,11 @@
 #undef EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL
 
 // Fast path field resolution that can't initialize classes or throw exceptions.
-inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
+inline ArtField* FindFieldFast(uint32_t field_idx,
                                        mirror::ArtMethod* referrer,
                                        FindFieldType type, size_t expected_size) {
-  mirror::ArtField* resolved_field =
-      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
+  ArtField* resolved_field =
+      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx, sizeof(void*));
   if (UNLIKELY(resolved_field == nullptr)) {
     return nullptr;
   }
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 70e2851..1d8df68 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -16,11 +16,11 @@
 
 #include "entrypoints/entrypoint_utils.h"
 
+#include "art_field-inl.h"
 #include "base/mutex.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 77eec46..8d419f8 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -30,14 +30,14 @@
 namespace art {
 
 namespace mirror {
-  class Class;
   class Array;
-  class ArtField;
   class ArtMethod;
+  class Class;
   class Object;
   class String;
 }  // namespace mirror
 
+class ArtField;
 class ScopedObjectAccessAlreadyRunnable;
 class Thread;
 
@@ -132,7 +132,7 @@
 };
 
 template<FindFieldType type, bool access_check>
-inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
                                            Thread* self, size_t expected_size)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -143,7 +143,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // Fast path field resolution that can't initialize classes or throw exceptions.
-inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
+inline ArtField* FindFieldFast(uint32_t field_idx,
                                        mirror::ArtMethod* referrer,
                                        FindFieldType type, size_t expected_size)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 22bf939..b5a7c09 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
+#include "art_field-inl.h"
 #include "callee_save_frame.h"
 #include "dex_file-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 
@@ -29,8 +29,7 @@
                                            Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
-                                          sizeof(int8_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
   if (LIKELY(field != nullptr)) {
     return field->GetByte(field->GetDeclaringClass());
   }
@@ -45,8 +44,7 @@
                                                Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
-                                          sizeof(int8_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t));
   if (LIKELY(field != nullptr)) {
     return field->GetBoolean(field->GetDeclaringClass());
   }
@@ -61,8 +59,7 @@
                                              Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
-                                          sizeof(int16_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
   if (LIKELY(field != nullptr)) {
     return field->GetShort(field->GetDeclaringClass());
   }
@@ -78,8 +75,7 @@
                                              Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
-                                          sizeof(int16_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t));
   if (LIKELY(field != nullptr)) {
     return field->GetChar(field->GetDeclaringClass());
   }
@@ -95,8 +91,7 @@
                                            Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
-                                          sizeof(int32_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t));
   if (LIKELY(field != nullptr)) {
     return field->Get32(field->GetDeclaringClass());
   }
@@ -112,8 +107,7 @@
                                            Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead,
-                                          sizeof(int64_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t));
   if (LIKELY(field != nullptr)) {
     return field->Get64(field->GetDeclaringClass());
   }
@@ -129,8 +123,8 @@
                                                    Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
-                                          sizeof(mirror::HeapReference<mirror::Object>));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
+                                  sizeof(mirror::HeapReference<mirror::Object>));
   if (LIKELY(field != nullptr)) {
     return field->GetObj(field->GetDeclaringClass());
   }
@@ -146,8 +140,7 @@
                                              mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
-                                          sizeof(int8_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->GetByte(obj);
   }
@@ -167,8 +160,7 @@
                                                  mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
-                                          sizeof(int8_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->GetBoolean(obj);
   }
@@ -187,8 +179,7 @@
                                                mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
-                                          sizeof(int16_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->GetShort(obj);
   }
@@ -208,8 +199,7 @@
                                                mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
-                                          sizeof(int16_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->GetChar(obj);
   }
@@ -229,8 +219,7 @@
                                              mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
-                                          sizeof(int32_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->Get32(obj);
   }
@@ -250,8 +239,7 @@
                                              mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead,
-                                          sizeof(int64_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->Get64(obj);
   }
@@ -272,13 +260,13 @@
                                                      Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
-                                          sizeof(mirror::HeapReference<mirror::Object>));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
+                                  sizeof(mirror::HeapReference<mirror::Object>));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     return field->GetObj(obj);
   }
-  field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self,
-                                                      sizeof(mirror::HeapReference<mirror::Object>));
+  field = FindFieldFromCode<InstanceObjectRead, true>(
+      field_idx, referrer, self, sizeof(mirror::HeapReference<mirror::Object>));
   if (LIKELY(field != nullptr)) {
     if (UNLIKELY(obj == nullptr)) {
       ThrowNullPointerExceptionForFieldAccess(field, true);
@@ -293,8 +281,7 @@
                                      mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
-                                          sizeof(int8_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t));
   if (LIKELY(field != nullptr)) {
     Primitive::Type type = field->GetTypeAsPrimitiveType();
     // Compiled code can't use transactional mode.
@@ -325,8 +312,7 @@
                                       mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
-                                          sizeof(int16_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t));
   if (LIKELY(field != nullptr)) {
     Primitive::Type type = field->GetTypeAsPrimitiveType();
     // Compiled code can't use transactional mode.
@@ -357,8 +343,7 @@
                                       mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
-                                          sizeof(int32_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t));
   if (LIKELY(field != nullptr)) {
     // Compiled code can't use transactional mode.
     field->Set32<false>(field->GetDeclaringClass(), new_value);
@@ -377,8 +362,7 @@
                                       uint64_t new_value, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite,
-                                          sizeof(int64_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
   if (LIKELY(field != nullptr)) {
     // Compiled code can't use transactional mode.
     field->Set64<false>(field->GetDeclaringClass(), new_value);
@@ -397,8 +381,8 @@
                                        mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
-                                          sizeof(mirror::HeapReference<mirror::Object>));
+  ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
+                                  sizeof(mirror::HeapReference<mirror::Object>));
   if (LIKELY(field != nullptr)) {
     if (LIKELY(!field->IsPrimitiveType())) {
       // Compiled code can't use transactional mode.
@@ -420,8 +404,7 @@
                                        mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
-                                          sizeof(int8_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     Primitive::Type type = field->GetTypeAsPrimitiveType();
     // Compiled code can't use transactional mode.
@@ -460,8 +443,7 @@
                                         mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
-                                          sizeof(int16_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     Primitive::Type type = field->GetTypeAsPrimitiveType();
     // Compiled code can't use transactional mode.
@@ -501,8 +483,7 @@
                                         mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
-                                          sizeof(int32_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     // Compiled code can't use transactional mode.
     field->Set32<false>(obj, new_value);
@@ -530,8 +511,7 @@
                                         mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite,
-                                          sizeof(int64_t));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t));
   if (LIKELY(field != nullptr  && obj != nullptr)) {
     // Compiled code can't use transactional mode.
     field->Set64<false>(obj, new_value);
@@ -556,8 +536,8 @@
                                          mirror::ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
-                                          sizeof(mirror::HeapReference<mirror::Object>));
+  ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
+                                  sizeof(mirror::HeapReference<mirror::Object>));
   if (LIKELY(field != nullptr && obj != nullptr)) {
     // Compiled code can't use transactional mode.
     field->SetObj<false>(obj, new_value);
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index a3fac58..cd3f910 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -28,7 +28,6 @@
 #include "gc/heap.h"
 #include "gc/space/space.h"
 #include "gc/space/image_space.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index b16a146..eeb385e 100644
--- a/runtime/gc/accounting/remembered_set.cc
+++ b/runtime/gc/accounting/remembered_set.cc
@@ -26,7 +26,6 @@
 #include "gc/collector/semi_space.h"
 #include "gc/heap.h"
 #include "gc/space/space.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index ad8d988..2da8325 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -16,12 +16,12 @@
 
 #include "space_bitmap-inl.h"
 
+#include "art_field-inl.h"
 #include "base/stringprintf.h"
 #include "dex_file-inl.h"
 #include "mem_map.h"
 #include "mirror/object-inl.h"
 #include "mirror/class.h"
-#include "mirror/art_field.h"
 #include "mirror/object_array.h"
 
 namespace art {
@@ -190,15 +190,13 @@
     WalkInstanceFields(visited, callback, obj, super, arg);
   }
   // Walk instance fields
-  mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
-  if (fields != NULL) {
-    for (int32_t i = 0; i < fields->GetLength(); i++) {
-      mirror::ArtField* field = fields->Get(i);
-      if (!field->IsPrimitiveType()) {
-        mirror::Object* value = field->GetObj(obj);
-        if (value != NULL) {
-          WalkFieldsInOrder(visited, callback, value, arg);
-        }
+  auto* fields = klass->GetIFields();
+  for (size_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) {
+    ArtField* field = &fields[i];
+    if (!field->IsPrimitiveType()) {
+      mirror::Object* value = field->GetObj(obj);
+      if (value != nullptr) {
+        WalkFieldsInOrder(visited, callback, value, arg);
       }
     }
   }
@@ -219,15 +217,13 @@
   WalkInstanceFields(visited, callback, obj, klass, arg);
   // Walk static fields of a Class
   if (obj->IsClass()) {
-    mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
-    if (fields != NULL) {
-      for (int32_t i = 0; i < fields->GetLength(); i++) {
-        mirror::ArtField* field = fields->Get(i);
-        if (!field->IsPrimitiveType()) {
-          mirror::Object* value = field->GetObj(NULL);
-          if (value != NULL) {
-            WalkFieldsInOrder(visited, callback, value, arg);
-          }
+    auto* sfields = klass->GetSFields();
+    for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
+      ArtField* field = &sfields[i];
+      if (!field->IsPrimitiveType()) {
+        mirror::Object* value = field->GetObj(nullptr);
+        if (value != nullptr) {
+          WalkFieldsInOrder(visited, callback, value, arg);
         }
       }
     }
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 6a68880..eabb1c2 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -16,12 +16,12 @@
 
 #include "concurrent_copying.h"
 
+#include "art_field-inl.h"
 #include "gc/accounting/heap_bitmap-inl.h"
 #include "gc/accounting/space_bitmap-inl.h"
 #include "gc/space/image_space.h"
 #include "gc/space/space.h"
 #include "intern_table.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/object-inl.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index 8902df8..3c247cd 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -35,8 +35,6 @@
 #include "jni_internal.h"
 #include "mark_sweep-inl.h"
 #include "monitor.h"
-#include "mirror/art_field.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache.h"
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 104ed36..4e3845e 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -17,10 +17,9 @@
 #ifndef ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_
 #define ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_
 
-#include "gc/collector/mark_sweep.h"
+#include "mark_sweep.h"
 
 #include "gc/heap.h"
-#include "mirror/art_field.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/reference.h"
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 79d1034..ed2e295 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -39,7 +39,6 @@
 #include "gc/space/large_object_space.h"
 #include "gc/space/space-inl.h"
 #include "mark_sweep-inl.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/object-inl.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b9153c1..83da5a8 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -23,6 +23,7 @@
 #include <memory>
 #include <vector>
 
+#include "art_field-inl.h"
 #include "base/allocator.h"
 #include "base/dumpable.h"
 #include "base/histogram-inl.h"
@@ -58,7 +59,6 @@
 #include "heap-inl.h"
 #include "image.h"
 #include "intern_table.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object.h"
 #include "mirror/object-inl.h"
@@ -233,7 +233,7 @@
       CHECK_GT(oat_file_end_addr, image_space->End());
       requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
     } else {
-      LOG(WARNING) << "Could not create image space with image file '" << image_file_name << "'. "
+      LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. "
                    << "Attempting to fall back to imageless running. Error was: " << error_msg;
     }
   }
@@ -482,7 +482,7 @@
                                       non_moving_space_->GetMemMap());
     if (!no_gap) {
       MemMap::DumpMaps(LOG(ERROR));
-      LOG(FATAL) << "There's a gap between the image space and the main space";
+      LOG(FATAL) << "There's a gap between the image space and the non-moving space";
     }
   }
   if (running_on_valgrind_) {
@@ -2708,12 +2708,12 @@
           // Print which field of the object is dead.
           if (!obj->IsObjectArray()) {
             mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
-            CHECK(klass != NULL);
-            mirror::ObjectArray<mirror::ArtField>* fields = is_static ? klass->GetSFields()
-                                                                      : klass->GetIFields();
-            CHECK(fields != NULL);
-            for (int32_t i = 0; i < fields->GetLength(); ++i) {
-              mirror::ArtField* cur = fields->Get(i);
+            CHECK(klass != nullptr);
+            auto* fields = is_static ? klass->GetSFields() : klass->GetIFields();
+            auto num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
+            CHECK_EQ(fields == nullptr, num_fields == 0u);
+            for (size_t i = 0; i < num_fields; ++i) {
+              ArtField* cur = &fields[i];
               if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
                 LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is "
                           << PrettyField(cur);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 1fb3252..e28e8d7 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -43,8 +43,9 @@
 Atomic<uint32_t> ImageSpace::bitmap_index_(0);
 
 ImageSpace::ImageSpace(const std::string& image_filename, const char* image_location,
-                       MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap)
-    : MemMapSpace(image_filename, mem_map, mem_map->Begin(), mem_map->End(), mem_map->End(),
+                       MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap,
+                       uint8_t* end)
+    : MemMapSpace(image_filename, mem_map, mem_map->Begin(), end, end,
                   kGcRetentionPolicyNeverCollect),
       image_location_(image_location) {
   DCHECK(live_bitmap != nullptr);
@@ -642,10 +643,10 @@
 void ImageSpace::VerifyImageAllocations() {
   uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
   while (current < End()) {
-    DCHECK_ALIGNED(current, kObjectAlignment);
-    mirror::Object* obj = reinterpret_cast<mirror::Object*>(current);
-    CHECK(live_bitmap_->Test(obj));
+    CHECK_ALIGNED(current, kObjectAlignment);
+    auto* obj = reinterpret_cast<mirror::Object*>(current);
     CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
+    CHECK(live_bitmap_->Test(obj)) << PrettyTypeOf(obj);
     if (kUseBakerOrBrooksReadBarrier) {
       obj->AssertReadBarrierPointer();
     }
@@ -675,7 +676,6 @@
     *error_msg = StringPrintf("Invalid image header in '%s'", image_filename);
     return nullptr;
   }
-
   // Check that the file is large enough.
   uint64_t image_file_size = static_cast<uint64_t>(file->GetLength());
   if (image_header.GetImageSize() > image_file_size) {
@@ -683,23 +683,18 @@
                               image_file_size, image_header.GetImageSize());
     return nullptr;
   }
-  if (image_header.GetBitmapOffset() + image_header.GetImageBitmapSize() != image_file_size) {
-    *error_msg = StringPrintf("Image file too small for image bitmap: %" PRIu64 " vs. %zu.",
-                              image_file_size,
-                              image_header.GetBitmapOffset() + image_header.GetImageBitmapSize());
+  auto end_of_bitmap = image_header.GetImageBitmapOffset() + image_header.GetImageBitmapSize();
+  if (end_of_bitmap != image_file_size) {
+    *error_msg = StringPrintf(
+        "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size,
+        end_of_bitmap);
     return nullptr;
   }
 
   // Note: The image header is part of the image due to mmap page alignment required of offset.
-  std::unique_ptr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(),
-                                                 image_header.GetImageSize(),
-                                                 PROT_READ | PROT_WRITE,
-                                                 MAP_PRIVATE,
-                                                 file->Fd(),
-                                                 0,
-                                                 false,
-                                                 image_filename,
-                                                 error_msg));
+  std::unique_ptr<MemMap> map(MemMap::MapFileAtAddress(
+      image_header.GetImageBegin(), image_header.GetImageSize() + image_header.GetArtFieldsSize(),
+      PROT_READ | PROT_WRITE, MAP_PRIVATE, file->Fd(), 0, false, image_filename, error_msg));
   if (map.get() == NULL) {
     DCHECK(!error_msg->empty());
     return nullptr;
@@ -710,7 +705,7 @@
   std::unique_ptr<MemMap> image_map(
       MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(),
                                PROT_READ, MAP_PRIVATE,
-                               file->Fd(), image_header.GetBitmapOffset(),
+                               file->Fd(), image_header.GetImageBitmapOffset(),
                                false,
                                image_filename,
                                error_msg));
@@ -730,8 +725,9 @@
     return nullptr;
   }
 
+  uint8_t* const image_end = map->Begin() + image_header.GetImageSize();
   std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename, image_location,
-                                             map.release(), bitmap.release()));
+                                                   map.release(), bitmap.release(), image_end));
 
   // VerifyImageAllocations() will be called later in Runtime::Init()
   // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index d7f8057..9ae2af4 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -145,7 +145,7 @@
   std::unique_ptr<accounting::ContinuousSpaceBitmap> live_bitmap_;
 
   ImageSpace(const std::string& name, const char* image_location,
-             MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap);
+             MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap, uint8_t* end);
 
   // The OatFile associated with the image during early startup to
   // reserve space contiguous to the image. It is later released to
diff --git a/runtime/globals.h b/runtime/globals.h
index ac8751c..4d7fd2e 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -71,8 +71,6 @@
 static constexpr bool kMoveFieldArrays = !kMarkCompactSupport;
 // True if we allow moving classes.
 static constexpr bool kMovingClasses = !kMarkCompactSupport;
-// True if we allow moving fields.
-static constexpr bool kMovingFields = false;
 // True if we allow moving methods.
 static constexpr bool kMovingMethods = false;
 
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index cdb3e2a..23af25d 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -37,6 +37,7 @@
 
 #include <set>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
 #include "base/unix_file/fd_file.h"
@@ -51,7 +52,6 @@
 #include "globals.h"
 #include "jdwp/jdwp.h"
 #include "jdwp/jdwp_priv.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -999,7 +999,7 @@
     __ AddClassStaticsId(klass);
 
     for (size_t i = 0; i < sFieldCount; ++i) {
-      mirror::ArtField* f = klass->GetStaticField(i);
+      ArtField* f = klass->GetStaticField(i);
 
       size_t size;
       HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
@@ -1038,7 +1038,7 @@
   int iFieldCount = klass->IsObjectClass() ? 0 : klass->NumInstanceFields();
   __ AddU2((uint16_t)iFieldCount);
   for (int i = 0; i < iFieldCount; ++i) {
-    mirror::ArtField* f = klass->GetInstanceField(i);
+    ArtField* f = klass->GetInstanceField(i);
     __ AddStringId(LookupStringId(f->GetName()));
     HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), nullptr);
     __ AddU1(t);
@@ -1102,7 +1102,7 @@
   while (!klass->IsObjectClass()) {
     int ifieldCount = klass->NumInstanceFields();
     for (int i = 0; i < ifieldCount; ++i) {
-      mirror::ArtField* f = klass->GetInstanceField(i);
+      ArtField* f = klass->GetInstanceField(i);
       size_t size;
       auto t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
       switch (t) {
diff --git a/runtime/image.cc b/runtime/image.cc
index 3cb2580..2d8c1c4 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -24,10 +24,12 @@
 namespace art {
 
 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '4', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '5', '\0' };
 
 ImageHeader::ImageHeader(uint32_t image_begin,
                          uint32_t image_size,
+                         uint32_t art_fields_offset,
+                         uint32_t art_fields_size,
                          uint32_t image_bitmap_offset,
                          uint32_t image_bitmap_size,
                          uint32_t image_roots,
@@ -39,6 +41,8 @@
                          bool compile_pic)
   : image_begin_(image_begin),
     image_size_(image_size),
+    art_fields_offset_(art_fields_offset),
+    art_fields_size_(art_fields_size),
     image_bitmap_offset_(image_bitmap_offset),
     image_bitmap_size_(image_bitmap_size),
     oat_checksum_(oat_checksum),
diff --git a/runtime/image.h b/runtime/image.h
index 3c527b8..613414a 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -32,6 +32,8 @@
 
   ImageHeader(uint32_t image_begin,
               uint32_t image_size_,
+              uint32_t art_fields_offset,
+              uint32_t art_fields_size,
               uint32_t image_bitmap_offset,
               uint32_t image_bitmap_size,
               uint32_t image_roots,
@@ -53,6 +55,14 @@
     return static_cast<uint32_t>(image_size_);
   }
 
+  size_t GetArtFieldsOffset() const {
+    return art_fields_offset_;
+  }
+
+  size_t GetArtFieldsSize() const {
+    return art_fields_size_;
+  }
+
   size_t GetImageBitmapOffset() const {
     return image_bitmap_offset_;
   }
@@ -89,10 +99,6 @@
     return patch_delta_;
   }
 
-  size_t GetBitmapOffset() const {
-    return RoundUp(image_size_, kPageSize);
-  }
-
   static std::string GetOatLocationFromImageLocation(const std::string& image) {
     std::string oat_filename = image;
     if (oat_filename.length() <= 3) {
@@ -140,6 +146,12 @@
   // Image size, not page aligned.
   uint32_t image_size_;
 
+  // ArtField array offset.
+  uint32_t art_fields_offset_;
+
+  // ArtField size in bytes.
+  uint32_t art_fields_size_;
+
   // Image bitmap offset in the file.
   uint32_t image_bitmap_offset_;
 
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 680b563..f8c0e83 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -929,7 +929,7 @@
 
 void Instrumentation::FieldReadEventImpl(Thread* thread, mirror::Object* this_object,
                                          mirror::ArtMethod* method, uint32_t dex_pc,
-                                         mirror::ArtField* field) const {
+                                         ArtField* field) const {
   if (HasFieldReadListeners()) {
     std::shared_ptr<std::list<InstrumentationListener*>> original(field_read_listeners_);
     for (InstrumentationListener* listener : *original.get()) {
@@ -940,7 +940,7 @@
 
 void Instrumentation::FieldWriteEventImpl(Thread* thread, mirror::Object* this_object,
                                          mirror::ArtMethod* method, uint32_t dex_pc,
-                                         mirror::ArtField* field, const JValue& field_value) const {
+                                         ArtField* field, const JValue& field_value) const {
   if (HasFieldWriteListeners()) {
     std::shared_ptr<std::list<InstrumentationListener*>> original(field_write_listeners_);
     for (InstrumentationListener* listener : *original.get()) {
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 77314c60..41821a6 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -30,12 +30,12 @@
 
 namespace art {
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class Class;
   class Object;
   class Throwable;
 }  // namespace mirror
+class ArtField;
 union JValue;
 class Thread;
 
@@ -82,11 +82,11 @@
 
   // Call-back for when we read from a field.
   virtual void FieldRead(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
-                         uint32_t dex_pc, mirror::ArtField* field) = 0;
+                         uint32_t dex_pc, ArtField* field) = 0;
 
   // Call-back for when we write into a field.
   virtual void FieldWritten(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
-                            uint32_t dex_pc, mirror::ArtField* field, const JValue& field_value) = 0;
+                            uint32_t dex_pc, ArtField* field, const JValue& field_value) = 0;
 
   // Call-back when an exception is caught.
   virtual void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
@@ -301,7 +301,7 @@
   // Inform listeners that we read a field (only supported by the interpreter).
   void FieldReadEvent(Thread* thread, mirror::Object* this_object,
                       mirror::ArtMethod* method, uint32_t dex_pc,
-                      mirror::ArtField* field) const
+                      ArtField* field) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasFieldReadListeners())) {
       FieldReadEventImpl(thread, this_object, method, dex_pc, field);
@@ -311,7 +311,7 @@
   // Inform listeners that we write a field (only supported by the interpreter).
   void FieldWriteEvent(Thread* thread, mirror::Object* this_object,
                        mirror::ArtMethod* method, uint32_t dex_pc,
-                       mirror::ArtField* field, const JValue& field_value) const
+                       ArtField* field, const JValue& field_value) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasFieldWriteListeners())) {
       FieldWriteEventImpl(thread, this_object, method, dex_pc, field, field_value);
@@ -377,11 +377,11 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FieldReadEventImpl(Thread* thread, mirror::Object* this_object,
                            mirror::ArtMethod* method, uint32_t dex_pc,
-                           mirror::ArtField* field) const
+                           ArtField* field) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FieldWriteEventImpl(Thread* thread, mirror::Object* this_object,
                            mirror::ArtMethod* method, uint32_t dex_pc,
-                           mirror::ArtField* field, const JValue& field_value) const
+                           ArtField* field, const JValue& field_value) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Read barrier-aware utility functions for accessing deoptimized_methods_
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 375d644..3ae611b 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -281,11 +281,10 @@
         // object in the destructor.
         Class* field_class;
         {
-          StackHandleScope<3> hs(self);
-          HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
+          StackHandleScope<2> hs(self);
           HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
           HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
-          field_class = h_f->GetType<true>();
+          field_class = f->GetType<true>();
         }
         if (!reg->VerifierInstanceOf(field_class)) {
           // This should never happen.
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 2f8bf55..0e0d56a 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -24,6 +24,7 @@
 #include <iostream>
 #include <sstream>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "class_linker-inl.h"
@@ -32,7 +33,6 @@
 #include "dex_instruction-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "handle_scope-inl.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -41,7 +41,6 @@
 #include "thread.h"
 #include "well_known_classes.h"
 
-using ::art::mirror::ArtField;
 using ::art::mirror::ArtMethod;
 using ::art::mirror::Array;
 using ::art::mirror::BooleanArray;
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 9af8102..dd8c57b 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -208,20 +208,22 @@
   // going the reflective Dex way.
   mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
   mirror::String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
-  mirror::ArtField* found = nullptr;
-  mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
-  for (int32_t i = 0; i < fields->GetLength() && found == nullptr; ++i) {
-    mirror::ArtField* f = fields->Get(i);
+  ArtField* found = nullptr;
+  ArtField* fields = klass->GetIFields();
+  for (int32_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) {
+    ArtField* f = &fields[i];
     if (name2->Equals(f->GetName())) {
       found = f;
+      break;
     }
   }
   if (found == nullptr) {
     fields = klass->GetSFields();
-    for (int32_t i = 0; i < fields->GetLength() && found == nullptr; ++i) {
-      mirror::ArtField* f = fields->Get(i);
+    for (int32_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
+      ArtField* f = &fields[i];
       if (name2->Equals(f->GetName())) {
         found = f;
+        break;
       }
     }
   }
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index 31c9a0b..a503b17 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -33,11 +33,11 @@
 
 namespace art {
 
+class ArtField;
 union JValue;
 class Thread;
 
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class Class;
   class Object;
@@ -207,7 +207,7 @@
    * "fieldValue" is non-null for field modification events only.
    * "is_modification" is true for field modification, false for field access.
    */
-  void PostFieldEvent(const EventLocation* pLoc, mirror::ArtField* field, mirror::Object* thisPtr,
+  void PostFieldEvent(const EventLocation* pLoc, ArtField* field, mirror::Object* thisPtr,
                       const JValue* fieldValue, bool is_modification)
       LOCKS_EXCLUDED(event_list_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index c9a4483..ccf8bff 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
 #include "debugger.h"
@@ -28,7 +29,6 @@
 #include "jdwp/jdwp_expand_buf.h"
 #include "jdwp/jdwp_priv.h"
 #include "jdwp/object_registry.h"
-#include "mirror/art_field-inl.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
 
@@ -119,7 +119,7 @@
   mirror::Class*        locationClass;    /* ClassOnly */
   mirror::Class*        exceptionClass;   /* ExceptionOnly */
   bool                  caught;           /* ExceptionOnly */
-  mirror::ArtField*     field;            /* FieldOnly */
+  ArtField*             field;            /* FieldOnly */
   mirror::Object*       thisPtr;          /* InstanceOnly */
   /* nothing for StepOnly -- handled differently */
 };
@@ -914,7 +914,7 @@
   SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
 }
 
-void JdwpState::PostFieldEvent(const EventLocation* pLoc, mirror::ArtField* field,
+void JdwpState::PostFieldEvent(const EventLocation* pLoc, ArtField* field,
                                mirror::Object* this_object, const JValue* fieldValue,
                                bool is_modification) {
   DCHECK(pLoc != nullptr);
diff --git a/runtime/jit/jit_instrumentation.h b/runtime/jit/jit_instrumentation.h
index 425d2d3..9d5d74f 100644
--- a/runtime/jit/jit_instrumentation.h
+++ b/runtime/jit/jit_instrumentation.h
@@ -31,12 +31,12 @@
 
 namespace art {
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class Class;
   class Object;
   class Throwable;
 }  // namespace mirror
+class ArtField;
 union JValue;
 class Thread;
 
@@ -77,10 +77,10 @@
                             mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/) OVERRIDE { }
   virtual void FieldRead(Thread* /*thread*/, mirror::Object* /*this_object*/,
                          mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/,
-                         mirror::ArtField* /*field*/) OVERRIDE { }
+                         ArtField* /*field*/) OVERRIDE { }
   virtual void FieldWritten(Thread* /*thread*/, mirror::Object* /*this_object*/,
                             mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/,
-                            mirror::ArtField* /*field*/, const JValue& /*field_value*/)
+                            ArtField* /*field*/, const JValue& /*field_value*/)
       OVERRIDE { }
   virtual void ExceptionCaught(Thread* /*thread*/,
                                mirror::Throwable* /*exception_object*/) OVERRIDE { }
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 9ec64d4..8a5461b 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -23,6 +23,7 @@
 #include <utility>
 #include <vector>
 
+#include "art_field-inl.h"
 #include "atomic.h"
 #include "base/allocator.h"
 #include "base/logging.h"
@@ -37,7 +38,6 @@
 #include "interpreter/interpreter.h"
 #include "jni_env_ext.h"
 #include "java_vm_ext.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
@@ -184,7 +184,7 @@
   if (c.Get() == nullptr) {
     return nullptr;
   }
-  mirror::ArtField* field = nullptr;
+  ArtField* field = nullptr;
   mirror::Class* field_type;
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   if (sig[1] != '\0') {
@@ -379,7 +379,7 @@
   static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
-    mirror::ArtField* f = soa.DecodeField(fid);
+    ArtField* f = soa.DecodeField(fid);
     return soa.AddLocalReference<jobject>(mirror::Field::CreateFromArtField(soa.Self(), f, true));
   }
 
@@ -1203,14 +1203,14 @@
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(obj);
-    mirror::ArtField* f = soa.DecodeField(fid);
+    ArtField* f = soa.DecodeField(fid);
     return soa.AddLocalReference<jobject>(f->GetObject(o));
   }
 
   static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
-    mirror::ArtField* f = soa.DecodeField(fid);
+    ArtField* f = soa.DecodeField(fid);
     return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
   }
 
@@ -1220,7 +1220,7 @@
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
-    mirror::ArtField* f = soa.DecodeField(fid);
+    ArtField* f = soa.DecodeField(fid);
     f->SetObject<false>(o, v);
   }
 
@@ -1228,7 +1228,7 @@
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
-    mirror::ArtField* f = soa.DecodeField(fid);
+    ArtField* f = soa.DecodeField(fid);
     f->SetObject<false>(f->GetDeclaringClass(), v);
   }
 
@@ -1237,13 +1237,13 @@
   CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
   ScopedObjectAccess soa(env); \
   mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
-  mirror::ArtField* f = soa.DecodeField(fid); \
+  ArtField* f = soa.DecodeField(fid); \
   return f->Get ##fn (o)
 
 #define GET_STATIC_PRIMITIVE_FIELD(fn) \
   CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
   ScopedObjectAccess soa(env); \
-  mirror::ArtField* f = soa.DecodeField(fid); \
+  ArtField* f = soa.DecodeField(fid); \
   return f->Get ##fn (f->GetDeclaringClass())
 
 #define SET_PRIMITIVE_FIELD(fn, instance, value) \
@@ -1251,13 +1251,13 @@
   CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
   ScopedObjectAccess soa(env); \
   mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
-  mirror::ArtField* f = soa.DecodeField(fid); \
+  ArtField* f = soa.DecodeField(fid); \
   f->Set ##fn <false>(o, value)
 
 #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
   CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
   ScopedObjectAccess soa(env); \
-  mirror::ArtField* f = soa.DecodeField(fid); \
+  ArtField* f = soa.DecodeField(fid); \
   f->Set ##fn <false>(f->GetDeclaringClass(), value)
 
   static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
diff --git a/runtime/linear_alloc.cc b/runtime/linear_alloc.cc
new file mode 100644
index 0000000..fe6bee6
--- /dev/null
+++ b/runtime/linear_alloc.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "linear_alloc.h"
+
+#include "thread-inl.h"
+
+namespace art {
+
+LinearAlloc::LinearAlloc(ArenaPool* pool) : lock_("linear alloc"), allocator_(pool) {
+}
+
+void* LinearAlloc::Alloc(Thread* self, size_t size) {
+  MutexLock mu(self, lock_);
+  return allocator_.Alloc(size);
+}
+
+size_t LinearAlloc::GetUsedMemory() const {
+  MutexLock mu(Thread::Current(), lock_);
+  return allocator_.BytesUsed();
+}
+
+}  // namespace art
diff --git a/runtime/linear_alloc.h b/runtime/linear_alloc.h
new file mode 100644
index 0000000..6d8eda6
--- /dev/null
+++ b/runtime/linear_alloc.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_LINEAR_ALLOC_H_
+#define ART_RUNTIME_LINEAR_ALLOC_H_
+
+#include "base/arena_allocator.h"
+
+namespace art {
+
+class ArenaPool;
+
+// TODO: Support freeing if we add poor man's class unloading.
+class LinearAlloc {
+ public:
+  explicit LinearAlloc(ArenaPool* pool);
+
+  void* Alloc(Thread* self, size_t size);
+
+  // Allocate and construct an array of structs of type T.
+  template<class T>
+  T* AllocArray(Thread* self, size_t elements) {
+    return reinterpret_cast<T*>(Alloc(self, elements * sizeof(T)));
+  }
+
+  // Return the number of bytes used in the allocator.
+  size_t GetUsedMemory() const;
+
+ private:
+  mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  ArenaAllocator allocator_ GUARDED_BY(lock_);
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_LINEAR_ALLOC_H_
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 588615f..edd2888 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -622,7 +622,7 @@
 }
 
 void MemMap::DumpMapsLocked(std::ostream& os) {
-  os << maps_;
+  os << *maps_;
 }
 
 bool MemMap::HasMemMap(MemMap* map) {
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 6452f31..8b3418d 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -203,7 +203,7 @@
 template<typename T>
 inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
   Array* raw_array = Array::Alloc<true>(self, GetArrayClass(), length,
-                                        ComponentSizeShiftWidth<sizeof(T)>(),
+                                        ComponentSizeShiftWidth(sizeof(T)),
                                         Runtime::Current()->GetHeap()->GetCurrentAllocator());
   return down_cast<PrimitiveArray<T>*>(raw_array);
 }
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 115fcf2..832ad68 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -54,7 +54,7 @@
   }
 
   void SetLength(int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK_GE(length, 0);
+    DCHECK_GE(length, 0);
     // We use non transactional version since we can't undo this write. We also disable checking
     // since it would fail during a transaction.
     SetField32<false, false, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length);
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
deleted file mode 100644
index 83602d4..0000000
--- a/runtime/mirror/art_field.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "art_field.h"
-
-#include "art_field-inl.h"
-#include "gc/accounting/card_table-inl.h"
-#include "object-inl.h"
-#include "object_array-inl.h"
-#include "runtime.h"
-#include "scoped_thread_state_change.h"
-#include "utils.h"
-#include "well_known_classes.h"
-
-namespace art {
-namespace mirror {
-
-// TODO: Get global references for these
-GcRoot<Class> ArtField::java_lang_reflect_ArtField_;
-
-void ArtField::SetClass(Class* java_lang_reflect_ArtField) {
-  CHECK(java_lang_reflect_ArtField_.IsNull());
-  CHECK(java_lang_reflect_ArtField != NULL);
-  java_lang_reflect_ArtField_ = GcRoot<Class>(java_lang_reflect_ArtField);
-}
-
-void ArtField::ResetClass() {
-  CHECK(!java_lang_reflect_ArtField_.IsNull());
-  java_lang_reflect_ArtField_ = GcRoot<Class>(nullptr);
-}
-
-void ArtField::SetOffset(MemberOffset num_bytes) {
-  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  if (kIsDebugBuild && Runtime::Current()->IsAotCompiler() &&
-      Runtime::Current()->IsCompilingBootImage()) {
-    Primitive::Type type = GetTypeAsPrimitiveType();
-    if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
-      DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
-    }
-  }
-  // Not called within a transaction.
-  SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), num_bytes.Uint32Value());
-}
-
-void ArtField::VisitRoots(RootVisitor* visitor) {
-  java_lang_reflect_ArtField_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-// TODO: we could speed up the search if fields are ordered by offsets.
-ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
-  DCHECK(klass != nullptr);
-  ObjectArray<ArtField>* instance_fields = klass->GetIFields();
-  if (instance_fields != nullptr) {
-    for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) {
-      mirror::ArtField* field = instance_fields->GetWithoutChecks(i);
-      if (field->GetOffset().Uint32Value() == field_offset) {
-        return field;
-      }
-    }
-  }
-  // We did not find field in the class: look into superclass.
-  if (klass->GetSuperClass() != NULL) {
-    return FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset);
-  } else {
-    return nullptr;
-  }
-}
-
-}  // namespace mirror
-}  // namespace art
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
deleted file mode 100644
index 9d95cb9..0000000
--- a/runtime/mirror/art_field.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_MIRROR_ART_FIELD_H_
-#define ART_RUNTIME_MIRROR_ART_FIELD_H_
-
-#include <jni.h>
-
-#include "gc_root.h"
-#include "modifiers.h"
-#include "object.h"
-#include "object_callbacks.h"
-#include "primitive.h"
-#include "read_barrier_option.h"
-
-namespace art {
-
-struct ArtFieldOffsets;
-class DexFile;
-class ScopedObjectAccessAlreadyRunnable;
-
-namespace mirror {
-
-class DexCache;
-
-// C++ mirror of java.lang.reflect.ArtField
-class MANAGED ArtField FINAL : public Object {
- public:
-  // Size of java.lang.reflect.ArtField.class.
-  static uint32_t ClassSize();
-
-  // Size of an instance of java.lang.reflect.ArtField not including its value array.
-  static constexpr uint32_t InstanceSize() {
-    return sizeof(ArtField);
-  }
-
-  Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_), new_access_flags);
-  }
-
-  bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccPublic) != 0;
-  }
-
-  bool IsStatic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccStatic) != 0;
-  }
-
-  bool IsFinal() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccFinal) != 0;
-  }
-
-  uint32_t GetDexFieldIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_));
-  }
-
-  void SetDexFieldIndex(uint32_t new_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_), new_idx);
-  }
-
-  // Offset to field within an Object.
-  MemberOffset GetOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  static MemberOffset OffsetOffset() {
-    return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_));
-  }
-
-  MemberOffset GetOffsetDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  void SetOffset(MemberOffset num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  // field access, null object for static fields
-  uint8_t GetBoolean(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetBoolean(Object* object, uint8_t z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  int8_t GetByte(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetByte(Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  uint16_t GetChar(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetChar(Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  int16_t GetShort(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetShort(Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  int32_t GetInt(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetInt(Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  int64_t GetLong(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetLong(Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  float GetFloat(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetFloat(Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  double GetDouble(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetDouble(Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  Object* GetObject(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetObject(Object* object, Object* l) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  // Raw field accesses.
-  uint32_t Get32(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void Set32(Object* object, uint32_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  uint64_t Get64(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void Set64(Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  Object* GetObj(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<bool kTransactionActive>
-  void SetObj(Object* object, Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  static Class* GetJavaLangReflectArtField()  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(!java_lang_reflect_ArtField_.IsNull());
-    return java_lang_reflect_ArtField_.Read<kReadBarrierOption>();
-  }
-
-  static void SetClass(Class* java_lang_reflect_ArtField);
-  static void ResetClass();
-  static void VisitRoots(RootVisitor* visitor)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return (GetAccessFlags() & kAccVolatile) != 0;
-  }
-
-  // Returns an instance field with this offset in the given class or nullptr if not found.
-  static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  // Resolves / returns the name from the dex cache.
-  String* GetStringName(Thread* self, bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  Primitive::Type GetTypeAsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  template <bool kResolve>
-  Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- private:
-  // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
-  // The class we are a part of
-  HeapReference<Class> declaring_class_;
-
-  uint32_t access_flags_;
-
-  // Dex cache index of field id
-  uint32_t field_dex_idx_;
-
-  // Offset of field within an instance or in the Class' static fields
-  uint32_t offset_;
-
-  static GcRoot<Class> java_lang_reflect_ArtField_;
-
-  friend struct art::ArtFieldOffsets;  // for verifying offset information
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ArtField);
-};
-
-}  // namespace mirror
-}  // namespace art
-
-#endif  // ART_RUNTIME_MIRROR_ART_FIELD_H_
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index edbbb4a..92aea1f 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -53,7 +53,7 @@
 
 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                                           jobject jlr_method) {
-  mirror::ArtField* f =
+  ArtField* f =
       soa.DecodeField(WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
   mirror::ArtMethod* method = f->GetObject(soa.Decode<mirror::Object*>(jlr_method))->AsArtMethod();
   DCHECK(method != nullptr);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index c368dc6..5b72e5a 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -397,9 +397,9 @@
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable);
 }
 
-inline ObjectArray<ArtField>* Class::GetIFields() {
+inline ArtField* Class::GetIFields() {
   DCHECK(IsLoaded() || IsErroneous());
-  return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+  return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
 }
 
 inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() {
@@ -432,55 +432,46 @@
   return MemberOffset(base);
 }
 
-inline void Class::SetIFields(ObjectArray<ArtField>* new_ifields)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)));
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
+inline void Class::SetIFields(ArtField* new_ifields) {
+  DCHECK(GetIFieldsUnchecked() == nullptr);
+  return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
 }
 
-inline ObjectArray<ArtField>* Class::GetSFields() {
+inline void Class::SetIFieldsUnchecked(ArtField* new_ifields) {
+  SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
+}
+
+inline ArtField* Class::GetSFieldsUnchecked() {
+  return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+}
+
+inline ArtField* Class::GetIFieldsUnchecked() {
+  return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+}
+
+inline ArtField* Class::GetSFields() {
   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
-  return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+  return GetSFieldsUnchecked();
 }
 
-inline void Class::SetSFields(ObjectArray<ArtField>* new_sfields)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+inline void Class::SetSFields(ArtField* new_sfields) {
   DCHECK((IsRetired() && new_sfields == nullptr) ||
-         (NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_))));
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
+         GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr);
+  SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
 }
 
-inline uint32_t Class::NumStaticFields() {
-  return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
+inline void Class::SetSFieldsUnchecked(ArtField* new_sfields) {
+  SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
 }
 
-
-inline ArtField* Class::GetStaticField(uint32_t i)  // TODO: uint16_t
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return GetSFields()->GetWithoutChecks(i);
+inline ArtField* Class::GetStaticField(uint32_t i) {
+  DCHECK_LT(i, NumStaticFields());
+  return &GetSFields()[i];
 }
 
-inline void Class::SetStaticField(uint32_t i, ArtField* f)  // TODO: uint16_t
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField>>(
-      OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
-  sfields->Set<false>(i, f);
-}
-
-inline uint32_t Class::NumInstanceFields() {
-  return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
-}
-
-inline ArtField* Class::GetInstanceField(uint32_t i) {  // TODO: uint16_t
-  DCHECK_NE(NumInstanceFields(), 0U);
-  return GetIFields()->GetWithoutChecks(i);
-}
-
-inline void Class::SetInstanceField(uint32_t i, ArtField* f)  // TODO: uint16_t
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField>>(
-      OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
-  ifields->Set<false>(i, f);
+inline ArtField* Class::GetInstanceField(uint32_t i) {
+  DCHECK_LT(i, NumInstanceFields());
+  return &GetIFields()[i];
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -513,14 +504,12 @@
   DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() ||
          IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
          this == String::GetJavaLangString() ||
-         this == ArtField::GetJavaLangReflectArtField() ||
          this == ArtMethod::GetJavaLangReflectArtMethod())
       << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>()
       << " IsRetired=" << IsRetired<kVerifyFlags>()
       << " IsErroneous=" <<
           IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()
       << " IsString=" << (this == String::GetJavaLangString())
-      << " IsArtField=" << (this == ArtField::GetJavaLangReflectArtField())
       << " IsArtMethod=" << (this == ArtMethod::GetJavaLangReflectArtMethod())
       << " descriptor=" << PrettyDescriptor(this);
   return GetField32<kVerifyFlags>(AccessFlagsOffset());
@@ -691,11 +680,6 @@
 }
 
 template<ReadBarrierOption kReadBarrierOption>
-inline bool Class::IsArtFieldClass() const {
-  return this == ArtField::GetJavaLangReflectArtField<kReadBarrierOption>();
-}
-
-template<ReadBarrierOption kReadBarrierOption>
 inline bool Class::IsArtMethodClass() const {
   return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
 }
@@ -741,35 +725,35 @@
 inline ObjectArray<Class>* Class::GetInterfaces() {
   CHECK(IsProxyClass());
   // First static field.
-  DCHECK(GetSFields()->Get(0)->IsArtField());
-  DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "interfaces");
-  MemberOffset field_offset = GetSFields()->Get(0)->GetOffset();
+  auto* field = GetStaticField(0);
+  DCHECK_STREQ(field->GetName(), "interfaces");
+  MemberOffset field_offset = field->GetOffset();
   return GetFieldObject<ObjectArray<Class>>(field_offset);
 }
 
 inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() {
   CHECK(IsProxyClass());
   // Second static field.
-  DCHECK(GetSFields()->Get(1)->IsArtField());
-  DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "throws");
-  MemberOffset field_offset = GetSFields()->Get(1)->GetOffset();
+  auto* field = GetStaticField(1);
+  DCHECK_STREQ(field->GetName(), "throws");
+  MemberOffset field_offset = field->GetOffset();
   return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
 }
 
 inline MemberOffset Class::GetDisableIntrinsicFlagOffset() {
   CHECK(IsReferenceClass());
   // First static field
-  DCHECK(GetSFields()->Get(0)->IsArtField());
-  DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "disableIntrinsic");
-  return GetSFields()->Get(0)->GetOffset();
+  auto* field = GetStaticField(0);
+  DCHECK_STREQ(field->GetName(), "disableIntrinsic");
+  return field->GetOffset();
 }
 
 inline MemberOffset Class::GetSlowPathFlagOffset() {
   CHECK(IsReferenceClass());
   // Second static field
-  DCHECK(GetSFields()->Get(1)->IsArtField());
-  DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "slowPathEnabled");
-  return GetSFields()->Get(1)->GetOffset();
+  auto* field = GetStaticField(1);
+  DCHECK_STREQ(field->GetName(), "slowPathEnabled");
+  return field->GetOffset();
 }
 
 inline bool Class::GetSlowPathEnabled() {
@@ -827,6 +811,24 @@
   return GetFieldObject<ObjectArray<String>>(DexCacheStringsOffset());
 }
 
+template<class Visitor>
+void mirror::Class::VisitFieldRoots(Visitor& visitor) {
+  ArtField* const sfields = GetSFieldsUnchecked();
+  for (size_t i = 0, count = NumStaticFields(); i < count; ++i) {
+    if (kIsDebugBuild && GetStatus() != kStatusRetired) {
+      CHECK_EQ(sfields[i].GetDeclaringClass(), this);
+    }
+    visitor.VisitRoot(sfields[i].DeclaringClassRoot().AddressWithoutBarrier());
+  }
+  ArtField* const ifields = GetIFieldsUnchecked();
+  for (size_t i = 0, count = NumInstanceFields(); i < count; ++i) {
+    if (kIsDebugBuild && GetStatus() != kStatusRetired) {
+      CHECK_EQ(ifields[i].GetDeclaringClass(), this);
+    }
+    visitor.VisitRoot(ifields[i].DeclaringClassRoot().AddressWithoutBarrier());
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index b82a58f..92493bc 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -35,6 +35,7 @@
 
 namespace art {
 
+class ArtField;
 struct ClassOffsets;
 template<class T> class Handle;
 template<class T> class Handle;
@@ -44,7 +45,6 @@
 
 namespace mirror {
 
-class ArtField;
 class ArtMethod;
 class ClassLoader;
 class DexCache;
@@ -420,9 +420,6 @@
   bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  bool IsArtFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   bool IsArtMethodClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
@@ -823,17 +820,22 @@
   ALWAYS_INLINE void SetIfTable(IfTable* new_iftable) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get instance fields of the class (See also GetSFields).
-  ObjectArray<ArtField>* GetIFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtField* GetIFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetIFields(ObjectArray<ArtField>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetIFields(ArtField* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  uint32_t NumInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Unchecked edition has no verification flags.
+  void SetIFieldsUnchecked(ArtField* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtField* GetInstanceField(uint32_t i)  // TODO: uint16_t
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  uint32_t NumInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_instance_fields_));
+  }
 
-  void SetInstanceField(uint32_t i, ArtField* f)  // TODO: uint16_t
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetNumInstanceFields(uint32_t num) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_instance_fields_), num);
+  }
+
+  ArtField* GetInstanceField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns the number of instance fields containing reference types.
   uint32_t NumReferenceInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -884,18 +886,24 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Gets the static fields of the class.
-  ObjectArray<ArtField>* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtField* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetSFields(ObjectArray<ArtField>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetSFields(ArtField* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  uint32_t NumStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Unchecked edition has no verification flags.
+  void SetSFieldsUnchecked(ArtField* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  uint32_t NumStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_static_fields_));
+  }
+
+  void SetNumStaticFields(uint32_t num) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_static_fields_), num);
+  }
 
   // TODO: uint16_t
   ArtField* GetStaticField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  // TODO: uint16_t
-  void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   // Find a static or instance field using the JLS resolution order
   static ArtField* FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
                              const StringPiece& type)
@@ -974,6 +982,10 @@
   static void VisitRoots(RootVisitor* visitor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<class Visitor>
+  // Visit field roots.
+  void VisitFieldRoots(Visitor& visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // When class is verified, set the kAccPreverified flag on each method.
   void SetPreverifiedFlagOnAllMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -1079,6 +1091,10 @@
 
   void CheckObjectAlloc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Unchecked editions is for root visiting.
+  ArtField* GetSFieldsUnchecked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtField* GetIFieldsUnchecked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // defining class loader, or NULL for the "bootstrap" system loader
   HeapReference<ClassLoader> class_loader_;
 
@@ -1096,18 +1112,6 @@
   // static, private, and <init> methods
   HeapReference<ObjectArray<ArtMethod>> direct_methods_;
 
-  // instance fields
-  //
-  // These describe the layout of the contents of an Object.
-  // Note that only the fields directly declared by this class are
-  // listed in ifields; fields declared by a superclass are listed in
-  // the superclass's Class.ifields.
-  //
-  // All instance fields that refer to objects are guaranteed to be at
-  // the beginning of the field list.  num_reference_instance_fields_
-  // specifies the number of reference fields.
-  HeapReference<ObjectArray<ArtField>> ifields_;
-
   // The interface table (iftable_) contains pairs of a interface class and an array of the
   // interface methods. There is one pair per interface supported by this class.  That means one
   // pair for each interface we support directly, indirectly via superclass, or indirectly via a
@@ -1124,9 +1128,6 @@
   // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
   HeapReference<String> name_;
 
-  // Static fields
-  HeapReference<ObjectArray<ArtField>> sfields_;
-
   // The superclass, or NULL if this is java.lang.Object, an interface or primitive type.
   HeapReference<Class> super_class_;
 
@@ -1143,8 +1144,22 @@
   HeapReference<ObjectArray<ArtMethod>> vtable_;
 
   // Access flags; low 16 bits are defined by VM spec.
+  // Note: Shuffled back.
   uint32_t access_flags_;
 
+  // instance fields
+  //
+  // These describe the layout of the contents of an Object.
+  // Note that only the fields directly declared by this class are
+  // listed in ifields; fields declared by a superclass are listed in
+  // the superclass's Class.ifields.
+  //
+  // ArtField arrays are allocated as an array of fields, and not an array of fields pointers.
+  uint64_t ifields_;
+
+  // Static fields
+  uint64_t sfields_;
+
   // Total size of the Class instance; used when allocating storage on gc heap.
   // See also object_size_.
   uint32_t class_size_;
@@ -1160,12 +1175,18 @@
   // TODO: really 16bits
   int32_t dex_type_idx_;
 
+  // Number of static fields.
+  uint32_t num_instance_fields_;
+
   // Number of instance fields that are object refs.
   uint32_t num_reference_instance_fields_;
 
   // Number of static fields that are object refs,
   uint32_t num_reference_static_fields_;
 
+  // Number of static fields.
+  uint32_t num_static_fields_;
+
   // Total object size; used when allocating storage on gc heap.
   // (For interfaces and abstract classes this will be zero.)
   // See also class_size_.
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 6758e22..1cb437e 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -19,6 +19,7 @@
 
 #include "dex_cache.h"
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "mirror/class.h"
 #include "runtime.h"
@@ -35,12 +36,11 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ArtMethod* method = GetResolvedMethods()->Get(method_idx);
   // Hide resolution trampoline methods from the caller
-  if (method != NULL && method->IsRuntimeMethod()) {
-    DCHECK(method == Runtime::Current()->GetResolutionMethod());
-    return NULL;
-  } else {
-    return method;
+  if (method != nullptr && method->IsRuntimeMethod()) {
+    DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod());
+    return nullptr;
   }
+  return method;
 }
 
 inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
@@ -49,6 +49,34 @@
   GetResolvedTypes()->Set(type_idx, resolved);
 }
 
+inline ArtField* DexCache::GetResolvedField(uint32_t idx, size_t ptr_size) {
+  ArtField* field = nullptr;
+  if (ptr_size == 8) {
+    field = reinterpret_cast<ArtField*>(
+        static_cast<uintptr_t>(GetResolvedFields()->AsLongArray()->GetWithoutChecks(idx)));
+  } else {
+    DCHECK_EQ(ptr_size, 4u);
+    field = reinterpret_cast<ArtField*>(
+      static_cast<uintptr_t>(GetResolvedFields()->AsIntArray()->GetWithoutChecks(idx)));
+  }
+  if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) {
+    return nullptr;
+  }
+  return field;
+}
+
+inline void DexCache::SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size) {
+  if (ptr_size == 8) {
+    GetResolvedFields()->AsLongArray()->Set(
+        idx, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(field)));
+  } else {
+    DCHECK_EQ(ptr_size, 4u);
+    CHECK_LE(reinterpret_cast<uintptr_t>(field), 0xFFFFFFFF);
+    GetResolvedFields()->AsIntArray()->Set(
+        idx, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(field)));
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index d6c11e8..ade8bd2 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -36,7 +36,7 @@
                     ObjectArray<String>* strings,
                     ObjectArray<Class>* resolved_types,
                     ObjectArray<ArtMethod>* resolved_methods,
-                    ObjectArray<ArtField>* resolved_fields) {
+                    Array* resolved_fields) {
   CHECK(dex_file != nullptr);
   CHECK(location != nullptr);
   CHECK(strings != nullptr);
@@ -44,19 +44,18 @@
   CHECK(resolved_methods != nullptr);
   CHECK(resolved_fields != nullptr);
 
-  SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file);
+  SetDexFile(dex_file);
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
   SetFieldObject<false>(StringsOffset(), strings);
+  SetFieldObject<false>(ResolvedFieldsOffset(), resolved_fields);
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types);
   SetFieldObject<false>(ResolvedMethodsOffset(), resolved_methods);
-  SetFieldObject<false>(ResolvedFieldsOffset(), resolved_fields);
 
   Runtime* runtime = Runtime::Current();
   if (runtime->HasResolutionMethod()) {
     // Initialize the resolve methods array to contain trampolines for resolution.
     ArtMethod* trampoline = runtime->GetResolutionMethod();
-    size_t length = resolved_methods->GetLength();
-    for (size_t i = 0; i < length; i++) {
+    for (size_t i = 0, length = resolved_methods->GetLength(); i < length; i++) {
       resolved_methods->SetWithoutChecks<false>(i, trampoline);
     }
   }
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index c548c03..7e30b89 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -50,7 +50,7 @@
             ObjectArray<String>* strings,
             ObjectArray<Class>* types,
             ObjectArray<ArtMethod>* methods,
-            ObjectArray<ArtField>* fields)
+            Array* fields)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void Fixup(ArtMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -116,23 +116,16 @@
     GetResolvedMethods()->Set(method_idx, resolved);
   }
 
-  ArtField* GetResolvedField(uint32_t field_idx) ALWAYS_INLINE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ArtField* field = GetResolvedFields()->Get(field_idx);
-    if (UNLIKELY(field == nullptr || field->GetDeclaringClass()->IsErroneous())) {
-      return nullptr;
-    } else {
-      return field;
-    }
-  }
+  // Pointer sized variant, used for patching.
+  ArtField* GetResolvedField(uint32_t idx, size_t ptr_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetResolvedField(uint32_t field_idx, ArtField* resolved) ALWAYS_INLINE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    GetResolvedFields()->Set(field_idx, resolved);
-  }
+  // Pointer sized variant, used for patching.
+  void SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ObjectArray<String>* GetStrings() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject< ObjectArray<String>>(StringsOffset());
+    return GetFieldObject<ObjectArray<String>>(StringsOffset());
   }
 
   ObjectArray<Class>* GetResolvedTypes() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -145,9 +138,8 @@
     return GetFieldObject< ObjectArray<ArtMethod>>(ResolvedMethodsOffset());
   }
 
-  ObjectArray<ArtField>* GetResolvedFields() ALWAYS_INLINE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject<ObjectArray<ArtField>>(ResolvedFieldsOffset());
+  Array* GetResolvedFields() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject<Array>(ResolvedFieldsOffset());
   }
 
   const DexFile* GetDexFile() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -162,7 +154,8 @@
  private:
   HeapReference<Object> dex_;
   HeapReference<String> location_;
-  HeapReference<ObjectArray<ArtField>> resolved_fields_;
+  // Either an int array or long array (64 bit).
+  HeapReference<Object> resolved_fields_;
   HeapReference<ObjectArray<ArtMethod>> resolved_methods_;
   HeapReference<ObjectArray<Class>> resolved_types_;
   HeapReference<ObjectArray<String>> strings_;
diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc
index 53e5534..1d6846b 100644
--- a/runtime/mirror/dex_cache_test.cc
+++ b/runtime/mirror/dex_cache_test.cc
@@ -47,7 +47,7 @@
   EXPECT_LE(0, dex_cache->GetStrings()->GetLength());
   EXPECT_LE(0, dex_cache->GetResolvedTypes()->GetLength());
   EXPECT_LE(0, dex_cache->GetResolvedMethods()->GetLength());
-  EXPECT_LE(0, dex_cache->GetResolvedFields()->GetLength());
+  EXPECT_LE(0u, dex_cache->NumResolvedFields());
 
   EXPECT_EQ(java_lang_dex_file_->NumStringIds(),
             static_cast<uint32_t>(dex_cache->GetStrings()->GetLength()));
@@ -55,8 +55,7 @@
             static_cast<uint32_t>(dex_cache->GetResolvedTypes()->GetLength()));
   EXPECT_EQ(java_lang_dex_file_->NumMethodIds(),
             static_cast<uint32_t>(dex_cache->GetResolvedMethods()->GetLength()));
-  EXPECT_EQ(java_lang_dex_file_->NumFieldIds(),
-            static_cast<uint32_t>(dex_cache->GetResolvedFields()->GetLength()));
+  EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumResolvedFields());
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 24ebc48..7db1811 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -27,9 +27,8 @@
 namespace mirror {
 
 template <bool kTransactionActive>
-inline mirror::Field* Field::CreateFromArtField(Thread* self, mirror::ArtField* field,
+inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field,
                                                 bool force_resolve) {
-  CHECK(!kMovingFields);
   // Try to resolve type before allocating since this is a thread suspension point.
   mirror::Class* type = field->GetType<true>();
 
@@ -57,13 +56,13 @@
     return nullptr;
   }
   auto dex_field_index = field->GetDexFieldIndex();
-  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index);
+  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, sizeof(void*));
   if (resolved_field != nullptr) {
     DCHECK_EQ(resolved_field, field);
   } else {
     // We rely on the field being resolved so that we can back to the ArtField
     // (i.e. FromReflectedMethod).
-    field->GetDexCache()->SetResolvedField(dex_field_index, field);
+    field->GetDexCache()->SetResolvedField(dex_field_index, field, sizeof(void*));
   }
   ret->SetType<kTransactionActive>(type);
   ret->SetDeclaringClass<kTransactionActive>(field->GetDeclaringClass());
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index 82cc26e..70311bb 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -55,7 +55,7 @@
 
 ArtField* Field::GetArtField() {
   mirror::DexCache* const dex_cache = GetDeclaringClass()->GetDexCache();
-  mirror::ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex());
+  ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex(), sizeof(void*));
   CHECK(art_field != nullptr);
   return art_field;
 }
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index cea06f5..9988f84 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -25,11 +25,11 @@
 
 namespace art {
 
+class ArtField;
 struct FieldOffsets;
 
 namespace mirror {
 
-class ArtField;
 class Class;
 class String;
 
@@ -93,10 +93,10 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Slow, try to use only for PrettyField and such.
-  mirror::ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template <bool kTransactionActive = false>
-  static mirror::Field* CreateFromArtField(Thread* self, mirror::ArtField* field,
+  static mirror::Field* CreateFromArtField(Thread* self, ArtField* field,
                                            bool force_resolve)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index d690163..af0e856 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -225,18 +225,6 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
-inline bool Object::IsArtField() {
-  return GetClass<kVerifyFlags, kReadBarrierOption>()->
-      template IsArtFieldClass<kReadBarrierOption>();
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline ArtField* Object::AsArtField() {
-  DCHECK(IsArtField<kVerifyFlags>());
-  return down_cast<ArtField*>(this);
-}
-
-template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 inline bool Object::IsArtMethod() {
   return GetClass<kVerifyFlags, kReadBarrierOption>()->
       template IsArtMethodClass<kReadBarrierOption>();
@@ -318,8 +306,8 @@
 template<VerifyObjectFlags kVerifyFlags>
 inline IntArray* Object::AsIntArray() {
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
-  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
-  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
+  CHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
   return down_cast<IntArray*>(this);
 }
@@ -327,8 +315,8 @@
 template<VerifyObjectFlags kVerifyFlags>
 inline LongArray* Object::AsLongArray() {
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
-  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
-  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
+  CHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+  CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
   return down_cast<LongArray*>(this);
 }
@@ -403,7 +391,6 @@
   }
   DCHECK_GE(result, sizeof(Object))
       << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>());
-  DCHECK(!(IsArtField<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtField));
   return result;
 }
 
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 57ac46f..04d0cd8 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -204,22 +204,19 @@
     return;
   }
   for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
-    ObjectArray<ArtField>* fields = cur->GetIFields();
-    if (fields != NULL) {
-      size_t num_ifields = fields->GetLength();
-      for (size_t i = 0; i < num_ifields; ++i) {
-        StackHandleScope<1> hs(Thread::Current());
-        Handle<Object> h_object(hs.NewHandle(new_value));
-        ArtField* field = fields->Get(i);
-        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
-          CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
-          // TODO: resolve the field type for moving GC.
-          mirror::Class* field_type = field->GetType<!kMovingCollector>();
-          if (field_type != nullptr) {
-            CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
-          }
-          return;
+    ArtField* fields = cur->GetIFields();
+    for (size_t i = 0, count = cur->NumInstanceFields(); i < count; ++i) {
+      StackHandleScope<1> hs(Thread::Current());
+      Handle<Object> h_object(hs.NewHandle(new_value));
+      ArtField* field = &fields[i];
+      if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+        CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+        // TODO: resolve the field type for moving GC.
+        mirror::Class* field_type = field->GetType<!kMovingCollector>();
+        if (field_type != nullptr) {
+          CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
         }
+        return;
       }
     }
   }
@@ -228,20 +225,17 @@
     return;
   }
   if (IsClass()) {
-    ObjectArray<ArtField>* fields = AsClass()->GetSFields();
-    if (fields != NULL) {
-      size_t num_sfields = fields->GetLength();
-      for (size_t i = 0; i < num_sfields; ++i) {
-        ArtField* field = fields->Get(i);
-        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
-          CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
-          // TODO: resolve the field type for moving GC.
-          mirror::Class* field_type = field->GetType<!kMovingCollector>();
-          if (field_type != nullptr) {
-            CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
-          }
-          return;
+    ArtField* fields = AsClass()->GetSFields();
+    for (size_t i = 0, count = AsClass()->NumStaticFields(); i < count; ++i) {
+      ArtField* field = &fields[i];
+      if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+        CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+        // TODO: resolve the field type for moving GC.
+        mirror::Class* field_type = field->GetType<!kMovingCollector>();
+        if (field_type != nullptr) {
+          CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
         }
+        return;
       }
     }
   }
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index cfc8549..bfd5d4d 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -24,6 +24,7 @@
 
 namespace art {
 
+class ArtField;
 class ImageWriter;
 class LockWord;
 class Monitor;
@@ -33,7 +34,6 @@
 
 namespace mirror {
 
-class ArtField;
 class ArtMethod;
 class Array;
 class Class;
@@ -191,12 +191,6 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
-           ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 80d5135..30bc1cd 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -22,7 +22,6 @@
 #include "array-inl.h"
 #include "base/stringprintf.h"
 #include "gc/heap.h"
-#include "mirror/art_field.h"
 #include "mirror/class.h"
 #include "runtime.h"
 #include "handle_scope-inl.h"
@@ -36,13 +35,13 @@
 inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
                                              int32_t length, gc::AllocatorType allocator_type) {
   Array* array = Array::Alloc<true>(self, object_array_class, length,
-                                    ComponentSizeShiftWidth<sizeof(HeapReference<Object>)>(),
+                                    ComponentSizeShiftWidth(sizeof(HeapReference<Object>)),
                                     allocator_type);
   if (UNLIKELY(array == nullptr)) {
     return nullptr;
   } else {
     DCHECK_EQ(array->GetClass()->GetComponentSizeShift(),
-              ComponentSizeShiftWidth<sizeof(HeapReference<Object>)>());
+              ComponentSizeShiftWidth(sizeof(HeapReference<Object>)));
     return array->AsObjectArray<T>();
   }
 }
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 1ce298d..747a008 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -722,14 +722,12 @@
                                      "Ljava/util/Comparator;") == NULL);
 
   // Right name and type.
-  Handle<ArtField> f1(hs.NewHandle(
-      c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;")));
-  Handle<ArtField> f2(hs.NewHandle(
-      mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER",
-                                     "Ljava/util/Comparator;")));
-  EXPECT_TRUE(f1.Get() != NULL);
-  EXPECT_TRUE(f2.Get() != NULL);
-  EXPECT_EQ(f1.Get(), f2.Get());
+  ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+  ArtField* f2 = mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER",
+                                                "Ljava/util/Comparator;");
+  EXPECT_TRUE(f1 != NULL);
+  EXPECT_TRUE(f2 != NULL);
+  EXPECT_EQ(f1, f2);
 
   // TODO: test static fields via superclasses.
   // TODO: test static fields via interfaces.
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 760038a..1a6adf8 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -313,8 +313,8 @@
 static void PreloadDexCachesResolveField(Handle<mirror::DexCache> dex_cache, uint32_t field_idx,
                                          bool is_static)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtField* field = dex_cache->GetResolvedField(field_idx);
-  if (field != NULL) {
+  ArtField* field = dex_cache->GetResolvedField(field_idx, sizeof(void*));
+  if (field != nullptr) {
     return;
   }
   const DexFile* dex_file = dex_cache->GetDexFile();
@@ -334,7 +334,7 @@
     return;
   }
   // LOG(INFO) << "VMRuntime.preloadDexCaches resolved field " << PrettyField(field);
-  dex_cache->SetResolvedField(field_idx, field);
+  dex_cache->SetResolvedField(field_idx, field, sizeof(void*));
 }
 
 // Based on ClassLinker::ResolveMethod.
@@ -437,7 +437,7 @@
       }
     }
     for (size_t j = 0; j < dex_cache->NumResolvedFields(); j++) {
-      mirror::ArtField* field = dex_cache->GetResolvedField(j);
+      ArtField* field = linker->GetResolvedField(j, dex_cache);
       if (field != NULL) {
         filled->num_fields++;
       }
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index b657aec..5ad18f8 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -16,12 +16,12 @@
 
 #include "java_lang_Class.h"
 
+#include "art_field-inl.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
 #include "nth_caller_visitor.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field-inl.h"
@@ -119,33 +119,33 @@
 static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
     Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  StackHandleScope<3> hs(self);
-  auto h_ifields = hs.NewHandle(klass->GetIFields());
-  auto h_sfields = hs.NewHandle(klass->GetSFields());
-  const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0;
-  const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0;
-  int32_t array_size = num_ifields + num_sfields;
+  StackHandleScope<1> hs(self);
+  auto* ifields = klass->GetIFields();
+  auto* sfields = klass->GetSFields();
+  const auto num_ifields = klass->NumInstanceFields();
+  const auto num_sfields = klass->NumStaticFields();
+  size_t array_size = num_ifields + num_sfields;
   if (public_only) {
     // Lets go subtract all the non public fields.
-    for (int32_t i = 0; i < num_ifields; ++i) {
-      if (!h_ifields->GetWithoutChecks(i)->IsPublic()) {
+    for (size_t i = 0; i < num_ifields; ++i) {
+      if (!ifields[i].IsPublic()) {
         --array_size;
       }
     }
-    for (int32_t i = 0; i < num_sfields; ++i) {
-      if (!h_sfields->GetWithoutChecks(i)->IsPublic()) {
+    for (size_t i = 0; i < num_sfields; ++i) {
+      if (!sfields[i].IsPublic()) {
         --array_size;
       }
     }
   }
-  int32_t array_idx = 0;
+  size_t array_idx = 0;
   auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
       self, mirror::Field::ArrayClass(), array_size));
   if (object_array.Get() == nullptr) {
     return nullptr;
   }
-  for (int32_t i = 0; i < num_ifields; ++i) {
-    auto* art_field = h_ifields->GetWithoutChecks(i);
+  for (size_t i = 0; i < num_ifields; ++i) {
+    auto* art_field = &ifields[i];
     if (!public_only || art_field->IsPublic()) {
       auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
       if (field == nullptr) {
@@ -158,8 +158,8 @@
       object_array->SetWithoutChecks<false>(array_idx++, field);
     }
   }
-  for (int32_t i = 0; i < num_sfields; ++i) {
-    auto* art_field = h_sfields->GetWithoutChecks(i);
+  for (size_t i = 0; i < num_sfields; ++i) {
+    auto* art_field = &sfields[i];
     if (!public_only || art_field->IsPublic()) {
       auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
       if (field == nullptr) {
@@ -197,17 +197,16 @@
 // Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
 // the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
 // fast.
-ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName(
-    Thread* self ATTRIBUTE_UNUSED, mirror::String* name,
-    mirror::ObjectArray<mirror::ArtField>* fields)
+ALWAYS_INLINE static inline ArtField* FindFieldByName(
+    Thread* self ATTRIBUTE_UNUSED, mirror::String* name, ArtField* fields, size_t num_fields)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  uint32_t low = 0;
-  uint32_t high = fields->GetLength();
+  size_t low = 0;
+  size_t high = num_fields;
   const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
   const size_t length = name->GetLength();
   while (low < high) {
     auto mid = (low + high) / 2;
-    mirror::ArtField* const field = fields->GetWithoutChecks(mid);
+    ArtField* const field = &fields[mid];
     int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
     // Alternate approach, only a few % faster at the cost of more allocations.
     // int result = field->GetStringName(self, true)->CompareTo(name);
@@ -220,8 +219,8 @@
     }
   }
   if (kIsDebugBuild) {
-    for (int32_t i = 0; i < fields->GetLength(); ++i) {
-      CHECK_NE(fields->GetWithoutChecks(i)->GetName(), name->ToModifiedUtf8());
+    for (size_t i = 0; i < num_fields; ++i) {
+      CHECK_NE(fields[i].GetName(), name->ToModifiedUtf8());
     }
   }
   return nullptr;
@@ -231,18 +230,14 @@
     Thread* self, mirror::Class* c, mirror::String* name)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   auto* instance_fields = c->GetIFields();
-  if (instance_fields != nullptr) {
-    auto* art_field = FindFieldByName(self, name, instance_fields);
-    if (art_field != nullptr) {
-      return mirror::Field::CreateFromArtField(self, art_field, true);
-    }
+  auto* art_field = FindFieldByName(self, name, instance_fields, c->NumInstanceFields());
+  if (art_field != nullptr) {
+    return mirror::Field::CreateFromArtField(self, art_field, true);
   }
   auto* static_fields = c->GetSFields();
-  if (static_fields != nullptr) {
-    auto* art_field = FindFieldByName(self, name, static_fields);
-    if (art_field != nullptr) {
-      return mirror::Field::CreateFromArtField(self, art_field, true);
-    }
+  art_field = FindFieldByName(self, name, static_fields, c->NumStaticFields());
+  if (art_field != nullptr) {
+    return mirror::Field::CreateFromArtField(self, art_field, true);
   }
   return nullptr;
 }
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 1ffcbdf..681b261 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -63,7 +63,7 @@
   DCHECK(array_class->IsObjectArrayClass());
   mirror::Array* new_array = mirror::Array::Alloc<true>(
       soa.Self(), array_class, length,
-      ComponentSizeShiftWidth<sizeof(mirror::HeapReference<mirror::Object>)>(),
+      ComponentSizeShiftWidth(sizeof(mirror::HeapReference<mirror::Object>)),
       runtime->GetHeap()->GetCurrentAllocator());
   return soa.AddLocalReference<jobject>(new_array);
 }
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 765f548..5e1a4c5 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -57,8 +57,6 @@
   bool movable = true;
   if (!kMovingMethods && c->IsArtMethodClass()) {
     movable = false;
-  } else if (!kMovingFields && c->IsArtFieldClass()) {
-    movable = false;
   } else if (!kMovingClasses && c->IsClassClass()) {
     movable = false;
   }
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index d2362a2..37c6353 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -25,11 +25,11 @@
 #include <backtrace/BacktraceMap.h>
 #include <gtest/gtest.h>
 
+#include "art_field-inl.h"
 #include "class_linker.h"
 #include "common_runtime_test.h"
 #include "compiler_callbacks.h"
 #include "mem_map.h"
-#include "mirror/art_field-inl.h"
 #include "os.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
@@ -959,25 +959,25 @@
   ASSERT_FALSE(dexfile.Get() == nullptr);
   linker->EnsureInitialized(soa.Self(), dexfile, true, true);
 
-  mirror::ArtField* no_dexopt_needed = mirror::Class::FindStaticField(
+  ArtField* no_dexopt_needed = mirror::Class::FindStaticField(
       soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I");
   ASSERT_FALSE(no_dexopt_needed == nullptr);
   EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get()));
 
-  mirror::ArtField* dex2oat_needed = mirror::Class::FindStaticField(
+  ArtField* dex2oat_needed = mirror::Class::FindStaticField(
       soa.Self(), dexfile, "DEX2OAT_NEEDED", "I");
   ASSERT_FALSE(dex2oat_needed == nullptr);
   EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get()));
 
-  mirror::ArtField* patchoat_needed = mirror::Class::FindStaticField(
+  ArtField* patchoat_needed = mirror::Class::FindStaticField(
       soa.Self(), dexfile, "PATCHOAT_NEEDED", "I");
   ASSERT_FALSE(patchoat_needed == nullptr);
   EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get()));
 
-  mirror::ArtField* self_patchoat_needed = mirror::Class::FindStaticField(
+  ArtField* self_patchoat_needed = mirror::Class::FindStaticField(
       soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I");
   ASSERT_FALSE(self_patchoat_needed == nullptr);
   EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
diff --git a/runtime/primitive.h b/runtime/primitive.h
index 32bfdaf..3818487 100644
--- a/runtime/primitive.h
+++ b/runtime/primitive.h
@@ -27,21 +27,11 @@
 static constexpr size_t kObjectReferenceSize = 4;
 
 
-template<size_t kComponentSize>
-size_t ComponentSizeShiftWidth() {
-  switch (kComponentSize) {
-    case 1:
-      return 0U;
-    case 2:
-      return 1U;
-    case 4:
-      return 2U;
-    case 8:
-      return 3U;
-    default:
-      LOG(FATAL) << "Unexpected component size : " << kComponentSize;
-      return 0U;
-  }
+constexpr size_t ComponentSizeShiftWidth(size_t component_size) {
+  return component_size == 1u ? 0u :
+      component_size == 2u ? 1u :
+          component_size == 4u ? 2u :
+              component_size == 8u ? 3u : 0u;
 }
 
 class Primitive {
@@ -95,7 +85,7 @@
       case kPrimFloat:   return 2;
       case kPrimLong:
       case kPrimDouble:  return 3;
-      case kPrimNot:     return ComponentSizeShiftWidth<kObjectReferenceSize>();
+      case kPrimNot:     return ComponentSizeShiftWidth(kObjectReferenceSize);
       default:
         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
         return 0;
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index cb97049..a3156b4 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -17,8 +17,8 @@
 #include <jni.h>
 #include <vector>
 
+#include "art_field-inl.h"
 #include "common_compiler_test.h"
-#include "mirror/art_field-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -165,14 +165,12 @@
   ASSERT_TRUE(proxyClass->IsProxyClass());
   ASSERT_TRUE(proxyClass->IsInitialized());
 
-  Handle<mirror::ObjectArray<mirror::ArtField>> instance_fields(
-      hs.NewHandle(proxyClass->GetIFields()));
-  EXPECT_TRUE(instance_fields.Get() == nullptr);
+  ArtField* instance_fields = proxyClass->GetIFields();
+  EXPECT_TRUE(instance_fields == nullptr);
 
-  Handle<mirror::ObjectArray<mirror::ArtField>> static_fields(
-      hs.NewHandle(proxyClass->GetSFields()));
-  ASSERT_TRUE(static_fields.Get() != nullptr);
-  ASSERT_EQ(2, static_fields->GetLength());
+  ArtField* static_fields = proxyClass->GetSFields();
+  ASSERT_TRUE(static_fields != nullptr);
+  ASSERT_EQ(2u, proxyClass->NumStaticFields());
 
   Handle<mirror::Class> interfacesFieldClass(
       hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Class;")));
@@ -182,21 +180,21 @@
   ASSERT_TRUE(throwsFieldClass.Get() != nullptr);
 
   // Test "Class[] interfaces" field.
-  MutableHandle<mirror::ArtField> fhandle = hs.NewHandle(static_fields->Get(0));
-  EXPECT_EQ("interfaces", std::string(fhandle->GetName()));
-  EXPECT_EQ("[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor()));
-  EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType<true>());
+  ArtField* field = &static_fields[0];
+  EXPECT_STREQ("interfaces", field->GetName());
+  EXPECT_STREQ("[Ljava/lang/Class;", field->GetTypeDescriptor());
+  EXPECT_EQ(interfacesFieldClass.Get(), field->GetType<true>());
   std::string temp;
-  EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp)));
-  EXPECT_FALSE(fhandle->IsPrimitiveType());
+  EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp));
+  EXPECT_FALSE(field->IsPrimitiveType());
 
   // Test "Class[][] throws" field.
-  fhandle.Assign(static_fields->Get(1));
-  EXPECT_EQ("throws", std::string(fhandle->GetName()));
-  EXPECT_EQ("[[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor()));
-  EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType<true>());
-  EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp)));
-  EXPECT_FALSE(fhandle->IsPrimitiveType());
+  field = &static_fields[1];
+  EXPECT_STREQ("throws", field->GetName());
+  EXPECT_STREQ("[[Ljava/lang/Class;", field->GetTypeDescriptor());
+  EXPECT_EQ(throwsFieldClass.Get(), field->GetType<true>());
+  EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp));
+  EXPECT_FALSE(field->IsPrimitiveType());
 }
 
 }  // namespace art
diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc
index 44e2844..efaa0ac 100644
--- a/runtime/quick/inline_method_analyser.cc
+++ b/runtime/quick/inline_method_analyser.cc
@@ -15,18 +15,14 @@
  */
 
 #include "inline_method_analyser.h"
+
+#include "art_field-inl.h"
 #include "dex_file-inl.h"
 #include "dex_instruction.h"
 #include "dex_instruction-inl.h"
-#include "mirror/art_field.h"
-#include "mirror/art_field-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/art_method-inl.h"
-#include "mirror/class.h"
 #include "mirror/class-inl.h"
-#include "mirror/dex_cache.h"
 #include "mirror/dex_cache-inl.h"
-#include "verifier/method_verifier.h"
 #include "verifier/method_verifier-inl.h"
 
 /*
@@ -331,7 +327,7 @@
   mirror::DexCache* dex_cache = verifier->GetDexCache();
   uint32_t method_idx = verifier->GetMethodReference().dex_method_index;
   mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
-  mirror::ArtField* field = dex_cache->GetResolvedField(field_idx);
+  ArtField* field = Runtime::Current()->GetClassLinker()->GetResolvedField(field_idx, dex_cache);
   if (method == nullptr || field == nullptr || field->IsStatic()) {
     return false;
   }
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
index 471b37c..52d83a2 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -30,7 +30,6 @@
 namespace art {
 
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class Object;
   template<typename MirrorType> class HeapReference;
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 4e94de4..3e1315c 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -16,16 +16,15 @@
 
 #include "reflection-inl.h"
 
+#include "art_field-inl.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #include "dex_file-inl.h"
 #include "entrypoints/entrypoint_utils.h"
 #include "jni_internal.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
-#include "mirror/object_array.h"
 #include "nth_caller_visitor.h"
 #include "scoped_thread_state_change.h"
 #include "stack.h"
@@ -238,13 +237,13 @@
 
 #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
           if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
-            mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \
+            ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
             append(primitive_field-> get_fn(arg));
 
 #define DO_ARG(match_descriptor, get_fn, append) \
           } else if (LIKELY(arg != nullptr && \
                             arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
-            mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \
+            ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
             append(primitive_field-> get_fn(arg));
 
 #define DO_FAIL(expected) \
@@ -692,7 +691,7 @@
   return result.GetL();
 }
 
-static std::string UnboxingFailureKind(mirror::ArtField* f)
+static std::string UnboxingFailureKind(ArtField* f)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (f != nullptr) {
     return "field " + PrettyField(f, false);
@@ -701,7 +700,7 @@
 }
 
 static bool UnboxPrimitive(mirror::Object* o,
-                           mirror::Class* dst_class, mirror::ArtField* f,
+                           mirror::Class* dst_class, ArtField* f,
                            JValue* unboxed_value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   bool unbox_for_result = (f == nullptr);
@@ -742,8 +741,8 @@
   JValue boxed_value;
   mirror::Class* klass = o->GetClass();
   mirror::Class* src_class = nullptr;
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0);
+  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+  ArtField* primitive_field = &klass->GetIFields()[0];
   if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
     src_class = class_linker->FindPrimitiveClass('Z');
     boxed_value.SetZ(primitive_field->GetBoolean(o));
@@ -782,7 +781,7 @@
                                boxed_value, unboxed_value);
 }
 
-bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, mirror::ArtField* f,
+bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f,
                             JValue* unboxed_value) {
   DCHECK(f != nullptr);
   return UnboxPrimitive(o, dst_class, f, unboxed_value);
diff --git a/runtime/reflection.h b/runtime/reflection.h
index ff970e5..c2d406a 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -23,18 +23,18 @@
 
 namespace art {
 namespace mirror {
-  class ArtField;
   class ArtMethod;
   class Class;
   class Object;
 }  // namespace mirror
+class ArtField;
 union JValue;
 class ScopedObjectAccessAlreadyRunnable;
 class ShadowFrame;
 
 mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, mirror::ArtField* f,
+bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f,
                             JValue* unboxed_value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value)
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1cd0a96..66d38ce 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -48,6 +48,7 @@
 #include "arch/x86/registers_x86.h"
 #include "arch/x86_64/quick_method_frame_info_x86_64.h"
 #include "arch/x86_64/registers_x86_64.h"
+#include "art_field-inl.h"
 #include "asm_support.h"
 #include "atomic.h"
 #include "base/arena_allocator.h"
@@ -70,8 +71,8 @@
 #include "interpreter/interpreter.h"
 #include "jit/jit.h"
 #include "jni_internal.h"
+#include "linear_alloc.h"
 #include "mirror/array.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
@@ -257,7 +258,9 @@
     VLOG(jit) << "Deleting jit";
     jit_.reset(nullptr);
   }
+  linear_alloc_.reset();
   arena_pool_.reset();
+  low_4gb_arena_pool_.reset();
 
   // Shutdown the fault manager if it was initialized.
   fault_manager.Shutdown();
@@ -441,7 +444,7 @@
       hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread)));
   CHECK(cl->EnsureInitialized(soa.Self(), thread_class, true, true));
 
-  mirror::ArtField* contextClassLoader =
+  ArtField* contextClassLoader =
       thread_class->FindDeclaredInstanceField("contextClassLoader", "Ljava/lang/ClassLoader;");
   CHECK(contextClassLoader != NULL);
 
@@ -862,7 +865,14 @@
   // Use MemMap arena pool for jit, malloc otherwise. Malloc arenas are faster to allocate but
   // can't be trimmed as easily.
   const bool use_malloc = !use_jit;
-  arena_pool_.reset(new ArenaPool(use_malloc));
+  arena_pool_.reset(new ArenaPool(use_malloc, false));
+  if (IsCompiler() && Is64BitInstructionSet(kRuntimeISA)) {
+    // 4gb, no malloc. Explanation in header.
+    low_4gb_arena_pool_.reset(new ArenaPool(false, true));
+    linear_alloc_.reset(new LinearAlloc(low_4gb_arena_pool_.get()));
+  } else {
+    linear_alloc_.reset(new LinearAlloc(arena_pool_.get()));
+  }
 
   BlockSignals();
   InitPlatformSignalHandlers();
@@ -1294,7 +1304,6 @@
 void Runtime::VisitConstantRoots(RootVisitor* visitor) {
   // Visit the classes held as static in mirror classes, these can be visited concurrently and only
   // need to be visited once per GC since they never change.
-  mirror::ArtField::VisitRoots(visitor);
   mirror::ArtMethod::VisitRoots(visitor);
   mirror::Class::VisitRoots(visitor);
   mirror::Reference::VisitRoots(visitor);
diff --git a/runtime/runtime.h b/runtime/runtime.h
index baa4d18..d95640d 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -42,6 +42,7 @@
 
 class ArenaPool;
 class CompilerCallbacks;
+class LinearAlloc;
 
 namespace gc {
   class Heap;
@@ -549,6 +550,9 @@
   const ArenaPool* GetArenaPool() const {
     return arena_pool_.get();
   }
+  LinearAlloc* GetLinearAlloc() {
+    return linear_alloc_.get();
+  }
 
   jit::JitOptions* GetJITOptions() {
     return jit_options_.get();
@@ -618,6 +622,13 @@
   gc::Heap* heap_;
 
   std::unique_ptr<ArenaPool> arena_pool_;
+  // Special low 4gb pool for compiler linear alloc. We need ArtFields to be in low 4gb if we are
+  // compiling using a 32 bit image on a 64 bit compiler in case we resolve things in the image
+  // since the field arrays are int arrays in this case.
+  std::unique_ptr<ArenaPool> low_4gb_arena_pool_;
+
+  // Shared linear alloc for now.
+  std::unique_ptr<LinearAlloc> linear_alloc_;
 
   // The number of spins that are done before thread suspension is used to forcibly inflate.
   size_t max_spins_before_thin_lock_inflation_;
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index adf3480..11b7df6 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -20,7 +20,7 @@
 #include "base/casts.h"
 #include "java_vm_ext.h"
 #include "jni_env_ext-inl.h"
-#include "mirror/art_field.h"
+#include "art_field.h"
 #include "read_barrier.h"
 #include "thread-inl.h"
 #include "verify_object.h"
@@ -148,20 +148,16 @@
     return down_cast<T>(Self()->DecodeJObject(obj));
   }
 
-  mirror::ArtField* DecodeField(jfieldID fid) const
+  ArtField* DecodeField(jfieldID fid) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Locks::mutator_lock_->AssertSharedHeld(Self());
     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
-    CHECK(!kMovingFields);
-    mirror::ArtField* field = reinterpret_cast<mirror::ArtField*>(fid);
-    return ReadBarrier::BarrierForRoot<mirror::ArtField, kWithReadBarrier>(&field);
+    return reinterpret_cast<ArtField*>(fid);
   }
 
-  jfieldID EncodeField(mirror::ArtField* field) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jfieldID EncodeField(ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Locks::mutator_lock_->AssertSharedHeld(Self());
     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
-    CHECK(!kMovingFields);
     return reinterpret_cast<jfieldID>(field);
   }
 
diff --git a/runtime/thread.cc b/runtime/thread.cc
index af11f73..58b272b 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -32,11 +32,11 @@
 #include <sstream>
 
 #include "arch/context.h"
+#include "art_field-inl.h"
 #include "base/mutex.h"
 #include "base/timing_logger.h"
 #include "base/to_str.h"
 #include "class_linker-inl.h"
-#include "class_linker.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
 #include "entrypoints/entrypoint_utils.h"
@@ -47,10 +47,8 @@
 #include "gc/heap.h"
 #include "gc/space/space.h"
 #include "handle_scope-inl.h"
-#include "handle_scope.h"
 #include "indirect_reference_table-inl.h"
 #include "jni_internal.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/class-inl.h"
@@ -173,7 +171,7 @@
     self->tlsPtr_.jpeer = nullptr;
     self->SetThreadName(self->GetThreadName(soa)->ToModifiedUtf8().c_str());
 
-    mirror::ArtField* priorityField = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority);
+    ArtField* priorityField = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority);
     self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer));
     Dbg::PostThreadStart(self);
 
@@ -190,7 +188,7 @@
 
 Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa,
                                   mirror::Object* thread_peer) {
-  mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer);
+  ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer);
   Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetLong(thread_peer)));
   // Sanity check that if we have a result it is either suspended or we hold the thread_list_lock_
   // to stop it from going away.
@@ -589,7 +587,7 @@
 }
 
 mirror::String* Thread::GetThreadName(const ScopedObjectAccessAlreadyRunnable& soa) const {
-  mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
+  ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
   return (tlsPtr_.opeer != nullptr) ? reinterpret_cast<mirror::String*>(f->GetObject(tlsPtr_.opeer)) : nullptr;
 }
 
@@ -794,7 +792,7 @@
         soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(thread->tlsPtr_.opeer);
 
     if (thread_group != nullptr) {
-      mirror::ArtField* group_name_field =
+      ArtField* group_name_field =
           soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name);
       mirror::String* group_name_string =
           reinterpret_cast<mirror::String*>(group_name_field->GetObject(thread_group));
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 5375dc0..7326865 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -582,7 +582,7 @@
 }
 
 void Trace::FieldRead(Thread* thread, mirror::Object* this_object,
-                       mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field)
+                       mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   UNUSED(thread, this_object, method, dex_pc, field);
   // We're not recorded to listen to this kind of event, so complain.
@@ -590,7 +590,7 @@
 }
 
 void Trace::FieldWritten(Thread* thread, mirror::Object* this_object,
-                          mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field,
+                          mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
                           const JValue& field_value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   UNUSED(thread, this_object, method, dex_pc, field, field_value);
diff --git a/runtime/trace.h b/runtime/trace.h
index 80f926f..d8bd428 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -33,10 +33,10 @@
 namespace art {
 
 namespace mirror {
-  class ArtField;
   class ArtMethod;
 }  // namespace mirror
 
+class ArtField;
 class Thread;
 
 enum TracingMode {
@@ -99,10 +99,10 @@
                   mirror::ArtMethod* method, uint32_t new_dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void FieldRead(Thread* thread, mirror::Object* this_object,
-                 mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field)
+                 mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void FieldWritten(Thread* thread, mirror::Object* this_object,
-                    mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field,
+                    mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
                     const JValue& field_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 24ecf6b..9792eca 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -16,9 +16,9 @@
 
 #include "transaction.h"
 
+#include "art_field-inl.h"
 #include "common_runtime_test.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 
@@ -181,47 +181,47 @@
   ASSERT_FALSE(soa.Self()->IsExceptionPending());
 
   // Lookup fields.
-  mirror::ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z");
+  ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z");
   ASSERT_TRUE(booleanField != nullptr);
   ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
   ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
 
-  mirror::ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B");
+  ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B");
   ASSERT_TRUE(byteField != nullptr);
   ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
   ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0);
 
-  mirror::ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C");
+  ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C");
   ASSERT_TRUE(charField != nullptr);
   ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
   ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u);
 
-  mirror::ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S");
+  ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S");
   ASSERT_TRUE(shortField != nullptr);
   ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
   ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0);
 
-  mirror::ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I");
+  ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I");
   ASSERT_TRUE(intField != nullptr);
   ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   ASSERT_EQ(intField->GetInt(h_klass.Get()), 0);
 
-  mirror::ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J");
+  ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J");
   ASSERT_TRUE(longField != nullptr);
   ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
   ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
 
-  mirror::ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
+  ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
   ASSERT_TRUE(floatField != nullptr);
   ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
   ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
 
-  mirror::ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
+  ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
   ASSERT_TRUE(doubleField != nullptr);
   ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
   ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
 
-  mirror::ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
+  ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
                                                                    "Ljava/lang/Object;");
   ASSERT_TRUE(objectField != nullptr);
   ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
@@ -283,47 +283,47 @@
   ASSERT_TRUE(h_instance.Get() != nullptr);
 
   // Lookup fields.
-  mirror::ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z");
+  ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z");
   ASSERT_TRUE(booleanField != nullptr);
   ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
   ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
 
-  mirror::ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B");
+  ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B");
   ASSERT_TRUE(byteField != nullptr);
   ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
   ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0);
 
-  mirror::ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C");
+  ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C");
   ASSERT_TRUE(charField != nullptr);
   ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
   ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u);
 
-  mirror::ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S");
+  ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S");
   ASSERT_TRUE(shortField != nullptr);
   ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
   ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0);
 
-  mirror::ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I");
+  ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I");
   ASSERT_TRUE(intField != nullptr);
   ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   ASSERT_EQ(intField->GetInt(h_instance.Get()), 0);
 
-  mirror::ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J");
+  ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J");
   ASSERT_TRUE(longField != nullptr);
   ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
   ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
 
-  mirror::ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
+  ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
   ASSERT_TRUE(floatField != nullptr);
   ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
   ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
 
-  mirror::ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
+  ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
   ASSERT_TRUE(doubleField != nullptr);
   ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
   ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
 
-  mirror::ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
+  ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
                                                                         "Ljava/lang/Object;");
   ASSERT_TRUE(objectField != nullptr);
   ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
@@ -381,63 +381,63 @@
   ASSERT_FALSE(soa.Self()->IsExceptionPending());
 
   // Lookup fields.
-  mirror::ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
+  ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
   ASSERT_TRUE(booleanArrayField != nullptr);
   mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray();
   ASSERT_TRUE(booleanArray != nullptr);
   ASSERT_EQ(booleanArray->GetLength(), 1);
   ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
 
-  mirror::ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
+  ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
   ASSERT_TRUE(byteArrayField != nullptr);
   mirror::ByteArray* byteArray = byteArrayField->GetObject(h_klass.Get())->AsByteArray();
   ASSERT_TRUE(byteArray != nullptr);
   ASSERT_EQ(byteArray->GetLength(), 1);
   ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
 
-  mirror::ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
+  ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
   ASSERT_TRUE(charArrayField != nullptr);
   mirror::CharArray* charArray = charArrayField->GetObject(h_klass.Get())->AsCharArray();
   ASSERT_TRUE(charArray != nullptr);
   ASSERT_EQ(charArray->GetLength(), 1);
   ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
 
-  mirror::ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
+  ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
   ASSERT_TRUE(shortArrayField != nullptr);
   mirror::ShortArray* shortArray = shortArrayField->GetObject(h_klass.Get())->AsShortArray();
   ASSERT_TRUE(shortArray != nullptr);
   ASSERT_EQ(shortArray->GetLength(), 1);
   ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
 
-  mirror::ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
+  ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
   ASSERT_TRUE(intArrayField != nullptr);
   mirror::IntArray* intArray = intArrayField->GetObject(h_klass.Get())->AsIntArray();
   ASSERT_TRUE(intArray != nullptr);
   ASSERT_EQ(intArray->GetLength(), 1);
   ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
 
-  mirror::ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
+  ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
   ASSERT_TRUE(longArrayField != nullptr);
   mirror::LongArray* longArray = longArrayField->GetObject(h_klass.Get())->AsLongArray();
   ASSERT_TRUE(longArray != nullptr);
   ASSERT_EQ(longArray->GetLength(), 1);
   ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
 
-  mirror::ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
+  ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
   ASSERT_TRUE(floatArrayField != nullptr);
   mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray();
   ASSERT_TRUE(floatArray != nullptr);
   ASSERT_EQ(floatArray->GetLength(), 1);
   ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
 
-  mirror::ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
+  ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
   ASSERT_TRUE(doubleArrayField != nullptr);
   mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray();
   ASSERT_TRUE(doubleArray != nullptr);
   ASSERT_EQ(doubleArray->GetLength(), 1);
   ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
 
-  mirror::ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField",
+  ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField",
                                                                            "[Ljava/lang/Object;");
   ASSERT_TRUE(objectArrayField != nullptr);
   mirror::ObjectArray<mirror::Object>* objectArray =
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 8a23ff7..f13da8b 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -25,10 +25,10 @@
 #include <unistd.h>
 #include <memory>
 
+#include "art_field-inl.h"
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "dex_file-inl.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
@@ -364,7 +364,7 @@
   return result;
 }
 
-std::string PrettyField(mirror::ArtField* f, bool with_type) {
+std::string PrettyField(ArtField* f, bool with_type) {
   if (f == NULL) {
     return "null";
   }
diff --git a/runtime/utils.h b/runtime/utils.h
index e6a6b1d..6dee5fe 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -33,10 +33,10 @@
 
 namespace art {
 
+class ArtField;
 class DexFile;
 
 namespace mirror {
-class ArtField;
 class ArtMethod;
 class Class;
 class Object;
@@ -343,7 +343,7 @@
 
 // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or
 // "int a.b.C.f" (depending on the value of 'with_type').
-std::string PrettyField(mirror::ArtField* f, bool with_type = true)
+std::string PrettyField(ArtField* f, bool with_type = true)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type = true);
 
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 833427e..623a3ec 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -146,7 +146,7 @@
   mirror::Class* java_lang_String = class_linker_->FindSystemClass(soa.Self(),
                                                                    "Ljava/lang/String;");
 
-  mirror::ArtField* f;
+  ArtField* f;
   f = java_lang_String->FindDeclaredInstanceField("count", "I");
   EXPECT_EQ("int java.lang.String.count", PrettyField(f));
   EXPECT_EQ("java.lang.String.count", PrettyField(f, false));
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9fc2658..065df05 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -18,6 +18,7 @@
 
 #include <iostream>
 
+#include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/mutex-inl.h"
 #include "class_linker.h"
@@ -30,7 +31,6 @@
 #include "indenter.h"
 #include "intern_table.h"
 #include "leb128.h"
-#include "mirror/art_field-inl.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
@@ -451,7 +451,7 @@
   Verify();
 }
 
-mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m,
+ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m,
                                                            uint32_t dex_pc) {
   Thread* self = Thread::Current();
   StackHandleScope<3> hs(self);
@@ -464,7 +464,7 @@
   return verifier.FindAccessedFieldAtDexPc(dex_pc);
 }
 
-mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) {
+ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) {
   CHECK(code_item_ != nullptr);  // This only makes sense for methods with code.
 
   // Strictly speaking, we ought to be able to get away with doing a subset of the full method
@@ -3788,7 +3788,7 @@
   }
 }
 
-mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) {
+ArtField* MethodVerifier::GetStaticField(int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
   // Check access to class
   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
@@ -3802,8 +3802,8 @@
     return nullptr;  // Can't resolve Class so no more to do here, will do checking at runtime.
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_,
-                                                          class_loader_);
+  ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_,
+                                                  class_loader_);
   if (field == nullptr) {
     VLOG(verifier) << "Unable to resolve static field " << field_idx << " ("
               << dex_file_->GetFieldName(field_id) << ") in "
@@ -3823,7 +3823,7 @@
   return field;
 }
 
-mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
+ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
   // Check access to class
   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
@@ -3837,8 +3837,8 @@
     return nullptr;  // Can't resolve Class so no more to do here
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_,
-                                                          class_loader_);
+  ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_,
+                                                  class_loader_);
   if (field == nullptr) {
     VLOG(verifier) << "Unable to resolve instance field " << field_idx << " ("
               << dex_file_->GetFieldName(field_id) << ") in "
@@ -3894,7 +3894,7 @@
 void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& insn_type,
                                          bool is_primitive, bool is_static) {
   uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
-  mirror::ArtField* field;
+  ArtField* field;
   if (is_static) {
     field = GetStaticField(field_idx);
   } else {
@@ -3914,12 +3914,8 @@
       }
     }
 
-    mirror::Class* field_type_class;
-    {
-      StackHandleScope<1> hs(self_);
-      HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field));
-      field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>();
-    }
+    mirror::Class* field_type_class =
+        can_load_classes_ ? field->GetType<true>() : field->GetType<false>();
     if (field_type_class != nullptr) {
       field_type = &reg_types_.FromClass(field->GetTypeDescriptor(), field_type_class,
                                          field_type_class->CannotBeAssignedFromOtherTypes());
@@ -3988,7 +3984,7 @@
   }
 }
 
-mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst,
+ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst,
                                                       RegisterLine* reg_line) {
   DCHECK(IsInstructionIGetQuickOrIPutQuick(inst->Opcode())) << inst->Opcode();
   const RegType& object_type = reg_line->GetRegisterType(this, inst->VRegB_22c());
@@ -3997,8 +3993,7 @@
     return nullptr;
   }
   uint32_t field_offset = static_cast<uint32_t>(inst->VRegC_22c());
-  mirror::ArtField* const f = mirror::ArtField::FindInstanceFieldWithOffset(object_type.GetClass(),
-                                                                            field_offset);
+  ArtField* const f = ArtField::FindInstanceFieldWithOffset(object_type.GetClass(), field_offset);
   DCHECK_EQ(f->GetOffset().Uint32Value(), field_offset);
   if (f == nullptr) {
     VLOG(verifier) << "Failed to find instance field at offset '" << field_offset
@@ -4012,7 +4007,7 @@
                                             bool is_primitive) {
   DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_);
 
-  mirror::ArtField* field = GetQuickFieldAccess(inst, work_line_.get());
+  ArtField* field = GetQuickFieldAccess(inst, work_line_.get());
   if (field == nullptr) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name();
     return;
@@ -4030,12 +4025,8 @@
   // Get the field type.
   const RegType* field_type;
   {
-    mirror::Class* field_type_class;
-    {
-      StackHandleScope<1> hs(Thread::Current());
-      HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field));
-      field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>();
-    }
+    mirror::Class* field_type_class = can_load_classes_ ? field->GetType<true>() :
+        field->GetType<false>();
 
     if (field_type_class != nullptr) {
       field_type = &reg_types_.FromClass(field->GetTypeDescriptor(), field_type_class,
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 8c0321e..cd414c2 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -191,7 +191,7 @@
 
   // Returns the accessed field corresponding to the quick instruction's field
   // offset at 'dex_pc' in method 'm'.
-  static mirror::ArtField* FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc)
+  static ArtField* FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns the invoked method corresponding to the quick instruction's vtable
@@ -250,7 +250,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   // Returns the access field of a quick field access (iget/iput-quick) or nullptr
   // if it cannot be found.
-  mirror::ArtField* GetQuickFieldAccess(const Instruction* inst, RegisterLine* reg_line)
+  ArtField* GetQuickFieldAccess(const Instruction* inst, RegisterLine* reg_line)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Is the method being verified a constructor?
@@ -301,7 +301,7 @@
 
   void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtField* FindAccessedFieldAtDexPc(uint32_t dex_pc)
+  ArtField* FindAccessedFieldAtDexPc(uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::ArtMethod* FindInvokedMethodAtDexPc(uint32_t dex_pc)
@@ -525,11 +525,11 @@
                   bool is_primitive) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Lookup instance field and fail for resolution violations
-  mirror::ArtField* GetInstanceField(const RegType& obj_type, int field_idx)
+  ArtField* GetInstanceField(const RegType& obj_type, int field_idx)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Lookup static field and fail for resolution violations
-  mirror::ArtField* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtField* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Perform verification of an iget/sget/iput/sput instruction.
   enum class FieldAccessType {  // private