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/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-inl.h b/runtime/mirror/art_field-inl.h
deleted file mode 100644
index 986852f..0000000
--- a/runtime/mirror/art_field-inl.h
+++ /dev/null
@@ -1,342 +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_INL_H_
-#define ART_RUNTIME_MIRROR_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 "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);
- 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 uint32_t ArtField::GetAccessFlags() {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_));
-}
-
-inline MemberOffset ArtField::GetOffset() {
- DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
- return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_)));
-}
-
-inline MemberOffset ArtField::GetOffsetDuringLinking() {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_)));
-}
-
-inline uint32_t ArtField::Get32(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(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(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(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 Object* ArtField::GetObj(Object* object) {
- DCHECK(object != NULL) << PrettyField(this);
- DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted());
- if (UNLIKELY(IsVolatile())) {
- return object->GetFieldObjectVolatile<Object>(GetOffset());
- }
- return object->GetFieldObject<Object>(GetOffset());
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetObj(Object* object, 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(Object* object) {
- FIELD_GET(object, Boolean);
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetBoolean(Object* object, uint8_t z) {
- FIELD_SET(object, Boolean, z);
-}
-
-inline int8_t ArtField::GetByte(Object* object) {
- FIELD_GET(object, Byte);
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetByte(Object* object, int8_t b) {
- FIELD_SET(object, Byte, b);
-}
-
-inline uint16_t ArtField::GetChar(Object* object) {
- FIELD_GET(object, Char);
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetChar(Object* object, uint16_t c) {
- FIELD_SET(object, Char, c);
-}
-
-inline int16_t ArtField::GetShort(Object* object) {
- FIELD_GET(object, Short);
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetShort(Object* object, int16_t s) {
- FIELD_SET(object, Short, s);
-}
-
-#undef FIELD_GET
-#undef FIELD_SET
-
-inline int32_t ArtField::GetInt(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(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(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(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(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(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) {
- DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this);
- JValue bits;
- bits.SetJ(Get64(object));
- return bits.GetD();
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetDouble(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) {
- DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this);
- return GetObj(object);
-}
-
-template<bool kTransactionActive>
-inline void ArtField::SetObject(Object* object, 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 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 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 mirror
-} // namespace art
-
-#endif // ART_RUNTIME_MIRROR_ART_FIELD_INL_H_
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.