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