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/art_field-inl.h b/runtime/art_field-inl.h
new file mode 100644
index 0000000..aeb1273
--- /dev/null
+++ b/runtime/art_field-inl.h
@@ -0,0 +1,335 @@
+/*
+ * 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_INL_H_
+#define ART_RUNTIME_ART_FIELD_INL_H_
+
+#include "art_field.h"
+
+#include "base/logging.h"
+#include "class_linker.h"
+#include "gc/accounting/card_table-inl.h"
+#include "jvalue.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 {
+
+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(mirror::Class* new_declaring_class) {
+  declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
+}
+
+inline uint32_t ArtField::GetAccessFlags() {
+  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
+  return access_flags_;
+}
+
+inline MemberOffset ArtField::GetOffset() {
+  DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
+  return MemberOffset(offset_);
+}
+
+inline MemberOffset ArtField::GetOffsetDuringLinking() {
+  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
+  return MemberOffset(offset_);
+}
+
+inline uint32_t ArtField::Get32(mirror::Object* object) {
+  DCHECK(object != nullptr) << PrettyField(this);
+  DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
+  if (UNLIKELY(IsVolatile())) {
+    return object->GetField32Volatile(GetOffset());
+  }
+  return object->GetField32(GetOffset());
+}
+
+template<bool kTransactionActive>
+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())) {
+    object->SetField32Volatile<kTransactionActive>(GetOffset(), new_value);
+  } else {
+    object->SetField32<kTransactionActive>(GetOffset(), new_value);
+  }
+}
+
+inline uint64_t ArtField::Get64(mirror::Object* object) {
+  DCHECK(object != NULL) << PrettyField(this);
+  DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
+  if (UNLIKELY(IsVolatile())) {
+    return object->GetField64Volatile(GetOffset());
+  }
+  return object->GetField64(GetOffset());
+}
+
+template<bool kTransactionActive>
+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())) {
+    object->SetField64Volatile<kTransactionActive>(GetOffset(), new_value);
+  } else {
+    object->SetField64<kTransactionActive>(GetOffset(), new_value);
+  }
+}
+
+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<mirror::Object>(GetOffset());
+  }
+  return object->GetFieldObject<mirror::Object>(GetOffset());
+}
+
+template<bool kTransactionActive>
+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())) {
+    object->SetFieldObjectVolatile<kTransactionActive>(GetOffset(), new_value);
+  } else {
+    object->SetFieldObject<kTransactionActive>(GetOffset(), new_value);
+  }
+}
+
+#define FIELD_GET(object, type) \
+  DCHECK_EQ(Primitive::kPrim ## type, GetTypeAsPrimitiveType()) << PrettyField(this); \
+  DCHECK(object != nullptr) << PrettyField(this); \
+  DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); \
+  if (UNLIKELY(IsVolatile())) { \
+    return object->GetField ## type ## Volatile(GetOffset()); \
+  } \
+  return object->GetField ## type(GetOffset());
+
+#define FIELD_SET(object, type, value) \
+  DCHECK_EQ(Primitive::kPrim ## type, GetTypeAsPrimitiveType()) << PrettyField(this); \
+  DCHECK(object != nullptr) << PrettyField(this); \
+  DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); \
+  if (UNLIKELY(IsVolatile())) { \
+    object->SetField ## type ## Volatile<kTransactionActive>(GetOffset(), value); \
+  } else { \
+    object->SetField ## type<kTransactionActive>(GetOffset(), value); \
+  }
+
+inline uint8_t ArtField::GetBoolean(mirror::Object* object) {
+  FIELD_GET(object, Boolean);
+}
+
+template<bool kTransactionActive>
+inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) {
+  FIELD_SET(object, Boolean, z);
+}
+
+inline int8_t ArtField::GetByte(mirror::Object* object) {
+  FIELD_GET(object, Byte);
+}
+
+template<bool kTransactionActive>
+inline void ArtField::SetByte(mirror::Object* object, int8_t b) {
+  FIELD_SET(object, Byte, b);
+}
+
+inline uint16_t ArtField::GetChar(mirror::Object* object) {
+  FIELD_GET(object, Char);
+}
+
+template<bool kTransactionActive>
+inline void ArtField::SetChar(mirror::Object* object, uint16_t c) {
+  FIELD_SET(object, Char, c);
+}
+
+inline int16_t ArtField::GetShort(mirror::Object* object) {
+  FIELD_GET(object, Short);
+}
+
+template<bool kTransactionActive>
+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(mirror::Object* object) {
+  if (kIsDebugBuild) {
+    Primitive::Type type = GetTypeAsPrimitiveType();
+    CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this);
+  }
+  return Get32(object);
+}
+
+template<bool kTransactionActive>
+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);
+  }
+  Set32<kTransactionActive>(object, i);
+}
+
+inline int64_t ArtField::GetLong(mirror::Object* object) {
+  if (kIsDebugBuild) {
+    Primitive::Type type = GetTypeAsPrimitiveType();
+    CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this);
+  }
+  return Get64(object);
+}
+
+template<bool kTransactionActive>
+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);
+  }
+  Set64<kTransactionActive>(object, j);
+}
+
+inline float ArtField::GetFloat(mirror::Object* object) {
+  DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this);
+  JValue bits;
+  bits.SetI(Get32(object));
+  return bits.GetF();
+}
+
+template<bool kTransactionActive>
+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(mirror::Object* object) {
+  DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this);
+  JValue bits;
+  bits.SetJ(Get64(object));
+  return bits.GetD();
+}
+
+template<bool kTransactionActive>
+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 mirror::Object* ArtField::GetObject(mirror::Object* object) {
+  DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this);
+  return GetObj(object);
+}
+
+template<bool kTransactionActive>
+inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) {
+  DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this);
+  SetObj<kTransactionActive>(object, l);
+}
+
+inline const char* ArtField::GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t field_index = GetDexFieldIndex();
+  if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) {
+    DCHECK(IsStatic());
+    DCHECK_LT(field_index, 2U);
+    return field_index == 0 ? "interfaces" : "throws";
+  }
+  const DexFile* dex_file = GetDexFile();
+  return dex_file->GetFieldName(dex_file->GetFieldId(field_index));
+}
+
+inline const char* ArtField::GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t field_index = GetDexFieldIndex();
+  if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) {
+    DCHECK(IsStatic());
+    DCHECK_LT(field_index, 2U);
+    // 0 == Class[] interfaces; 1 == Class[][] throws;
+    return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;";
+  }
+  const DexFile* dex_file = GetDexFile();
+  const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
+  return dex_file->GetFieldTypeDescriptor(field_id);
+}
+
+inline Primitive::Type ArtField::GetTypeAsPrimitiveType()
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return Primitive::GetType(GetTypeDescriptor()[0]);
+}
+
+inline bool ArtField::IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return GetTypeAsPrimitiveType() != Primitive::kPrimNot;
+}
+
+template <bool kResolve>
+inline mirror::Class* ArtField::GetType() {
+  const uint32_t field_index = GetDexFieldIndex();
+  auto* declaring_class = GetDeclaringClass();
+  if (UNLIKELY(declaring_class->IsProxyClass())) {
+    return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
+                                                                 GetTypeDescriptor());
+  }
+  auto* dex_cache = declaring_class->GetDexCache();
+  const DexFile* const dex_file = dex_cache->GetDexFile();
+  const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
+  mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_);
+  if (kResolve && UNLIKELY(type == nullptr)) {
+    type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, this);
+    CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
+  }
+  return type;
+}
+
+inline size_t ArtField::FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return Primitive::ComponentSize(GetTypeAsPrimitiveType());
+}
+
+inline mirror::DexCache* ArtField::GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return GetDeclaringClass()->GetDexCache();
+}
+
+inline const DexFile* ArtField::GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return GetDexCache()->GetDexFile();
+}
+
+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();
+  const auto* dex_file = dex_cache->GetDexFile();
+  const auto& field_id = dex_file->GetFieldId(dex_field_index);
+  auto* name = dex_cache->GetResolvedString(field_id.name_idx_);
+  if (resolve && name == nullptr) {
+    StackHandleScope<1> hs(self);
+    name = Runtime::Current()->GetClassLinker()->ResolveString(
+        *dex_file, field_id.name_idx_, hs.NewHandle(dex_cache));
+  }
+  return name;
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ART_FIELD_INL_H_