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/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));