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/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(