diff options
author | 2024-07-17 21:14:29 +0000 | |
---|---|---|
committer | 2024-07-22 15:53:08 +0000 | |
commit | b2f1766aeb7b442a1cc821f8dcda44a06fab7f85 (patch) | |
tree | 14c20ac6fa8d81275bb0660f85e077868eecfcc6 | |
parent | 841e48f39dad0e560ec45df0d5ff805a74ddb3fe (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.cc | 10 | ||||
-rw-r--r-- | runtime/mirror/array-inl.h | 23 | ||||
-rw-r--r-- | runtime/mirror/array.h | 5 | ||||
-rw-r--r-- | runtime/mirror/class_flags.h | 8 | ||||
-rw-r--r-- | runtime/mirror/object-refvisitor-inl.h | 18 |
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); |