summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lokesh Gidra <lokeshgidra@google.com> 2024-07-17 21:14:29 +0000
committer Lokesh Gidra <lokeshgidra@google.com> 2024-07-22 15:53:08 +0000
commitb2f1766aeb7b442a1cc821f8dcda44a06fab7f85 (patch)
tree14c20ac6fa8d81275bb0660f85e077868eecfcc6
parent841e48f39dad0e560ec45df0d5ff805a74ddb3fe (diff)
Embed component-size shift in class-flags
This helps by eliminating the need to dereference component_type_ reference in Class each time we need to compute the array's size. Bug: 304325190 Test: art/test/testrunner/testrunner.py --host Change-Id: I745b794066fa24787800f0e0baaf5c4188842bc1
-rw-r--r--runtime/class_linker.cc10
-rw-r--r--runtime/mirror/array-inl.h23
-rw-r--r--runtime/mirror/array.h5
-rw-r--r--runtime/mirror/class_flags.h8
-rw-r--r--runtime/mirror/object-refvisitor-inl.h18
5 files changed, 37 insertions, 27 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 585e2b3818..d0fdcf0c25 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2825,9 +2825,13 @@ void ClassLinker::FinishArrayClassSetup(ObjPtr<mirror::Class> array_class) {
array_class->SetVTable(java_lang_Object->GetVTable());
array_class->SetPrimitiveType(Primitive::kPrimNot);
ObjPtr<mirror::Class> component_type = array_class->GetComponentType();
- array_class->SetClassFlags(component_type->IsPrimitive()
- ? mirror::kClassFlagNoReferenceFields
- : mirror::kClassFlagObjectArray);
+ DCHECK_LT(component_type->GetPrimitiveTypeSizeShift(), 4u);
+ uint32_t class_flags =
+ component_type->GetPrimitiveTypeSizeShift() << mirror::kArrayComponentSizeShiftShift;
+ class_flags |= component_type->IsPrimitive()
+ ? (mirror::kClassFlagNoReferenceFields | mirror::kClassFlagPrimitiveArray)
+ : mirror::kClassFlagObjectArray;
+ array_class->SetClassFlags(class_flags);
array_class->SetClassLoader(component_type->GetClassLoader());
array_class->SetStatusForPrimitiveOrArray(ClassStatus::kLoaded);
array_class->PopulateEmbeddedVTable(image_pointer_size_);
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 830a7e5fb6..40c1c2e6b4 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -37,24 +37,23 @@ inline uint32_t Array::ClassSize(PointerSize pointer_size) {
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
}
-template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, bool kIsObjArray>
-inline size_t Array::SizeOf() {
- // When we are certain that this is a object array, then don't fetch shift
- // from component_type_ as that doesn't work well with userfaultfd GC as the
- // component-type class may be allocated at a higher address than the array.
- size_t component_size_shift = kIsObjArray ?
- Primitive::ComponentSizeShift(Primitive::kPrimNot) :
- GetClass<kVerifyFlags, kReadBarrierOption>()
- ->template GetComponentSizeShift<kReadBarrierOption>();
- // Don't need to check this since we already check this in GetClass.
- int32_t component_count =
- GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
+template <VerifyObjectFlags kVerifyFlags>
+inline size_t Array::SizeOf(size_t component_size_shift) {
+ int32_t component_count = GetLength<kVerifyFlags>();
// This is safe from overflow because the array was already allocated.
size_t header_size = DataOffset(1U << component_size_shift).SizeValue();
size_t data_size = component_count << component_size_shift;
return header_size + data_size;
}
+template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
+inline size_t Array::SizeOf() {
+ size_t component_size_shift = GetClass<kVerifyFlags, kReadBarrierOption>()
+ ->template GetComponentSizeShift<kReadBarrierOption>();
+ // Don't need to check this since we already check this in GetClass.
+ return SizeOf<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(component_size_shift);
+}
+
template<VerifyObjectFlags kVerifyFlags>
inline bool Array::CheckIsValidIndex(int32_t index) {
if (UNLIKELY(static_cast<uint32_t>(index) >=
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 565faa90b1..7a0976ab48 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -59,9 +59,10 @@ class MANAGED Array : public Object {
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
+ template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ size_t SizeOf(size_t component_size_shift) REQUIRES_SHARED(Locks::mutator_lock_);
template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- ReadBarrierOption kReadBarrierOption = kWithoutReadBarrier,
- bool kIsObjArray = false>
+ ReadBarrierOption kReadBarrierOption = kWithoutReadBarrier>
size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE int32_t GetLength() REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/class_flags.h b/runtime/mirror/class_flags.h
index 26a87c9546..b3d38b0ba8 100644
--- a/runtime/mirror/class_flags.h
+++ b/runtime/mirror/class_flags.h
@@ -61,6 +61,14 @@ static constexpr uint32_t kClassFlagPhantomReference = 0x00000400;
// Class is a record class. See doc at java.lang.Class#isRecord().
static constexpr uint32_t kClassFlagRecord = 0x00000800;
+// Class is a primitive array class.
+static constexpr uint32_t kClassFlagPrimitiveArray = 0x00001000;
+
+// NOTE: The most significant 2 bits are used to store the component size shift
+// for arrays (both primitive and object). See Primitive::ComponentSizeShift()
+// for size shift of different types.
+static constexpr uint32_t kArrayComponentSizeShiftShift = 30;
+
// Combination of flags to figure out if the class is either the weak/soft/phantom/finalizer
// reference class.
static constexpr uint32_t kClassFlagReference =
diff --git a/runtime/mirror/object-refvisitor-inl.h b/runtime/mirror/object-refvisitor-inl.h
index 7010263c71..72aff4b686 100644
--- a/runtime/mirror/object-refvisitor-inl.h
+++ b/runtime/mirror/object-refvisitor-inl.h
@@ -89,7 +89,7 @@ inline void Object::VisitReferences(const Visitor& visitor,
return;
}
- if (class_flags == kClassFlagObjectArray) {
+ if ((class_flags & kClassFlagObjectArray) != 0) {
DCHECK((klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor);
return;
@@ -147,13 +147,11 @@ inline size_t Object::VisitRefsForCompaction(const Visitor& visitor,
} else if ((class_flags & kClassFlagNoReferenceFields) != 0) {
if ((class_flags & kClassFlagString) != 0) {
size = kFetchObjSize ? static_cast<String*>(this)->SizeOf<kSizeOfFlags>() : 0;
- } else if (klass->IsArrayClass<kVerifyFlags>()) {
- // TODO: We can optimize this by implementing a SizeOf() version which takes
- // component-size-shift as an argument, thereby avoiding multiple loads of
- // component_type.
- size = kFetchObjSize
- ? static_cast<Array*>(this)->SizeOf<kSizeOfFlags, kReadBarrierOption>()
- : 0;
+ } else if ((class_flags & kClassFlagPrimitiveArray) != 0) {
+ ObjPtr<Array> arr = ObjPtr<Array>::DownCast(this);
+ size = kFetchObjSize ?
+ arr->SizeOf<kSizeOfFlags>(class_flags >> kArrayComponentSizeShiftShift) :
+ 0;
} else {
// Only possibility left is of a normal klass instance with no references.
size = kFetchObjSize ? klass->GetObjectSize<kSizeOfFlags>() : 0;
@@ -164,11 +162,11 @@ inline size_t Object::VisitRefsForCompaction(const Visitor& visitor,
as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
visitor);
size = kFetchObjSize ? as_klass->SizeOf<kSizeOfFlags>() : 0;
- } else if (class_flags == kClassFlagObjectArray) {
+ } else if ((class_flags & kClassFlagObjectArray) != 0) {
ObjPtr<ObjectArray<Object>> obj_arr = ObjPtr<ObjectArray<Object>>::DownCast(this);
obj_arr->VisitReferences(visitor, begin, end);
size = kFetchObjSize ?
- obj_arr->SizeOf<kSizeOfFlags, kReadBarrierOption, /*kIsObjArray*/ true>() :
+ obj_arr->SizeOf<kSizeOfFlags>(class_flags >> kArrayComponentSizeShiftShift) :
0;
} else if ((class_flags & kClassFlagReference) != 0) {
VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);