diff options
author | 2023-11-12 21:10:16 +0000 | |
---|---|---|
committer | 2023-11-17 11:02:27 +0000 | |
commit | cac08ecc868cc9b0b378cf380b1a18185708f4ca (patch) | |
tree | 50e2a527acf1f160c02279e16ca46b75ca658a62 | |
parent | d36e307dbf3e71f03aab1ccbcfdac35234d4e7a9 (diff) |
Put all cached boxed values into boot_image_live_objects.
Test: test.py
Change-Id: I16dc434207334aad4768e26704ce20dc98a31f6a
-rw-r--r-- | compiler/optimizing/intrinsic_objects.cc | 76 | ||||
-rw-r--r-- | compiler/optimizing/intrinsic_objects.h | 58 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 23 | ||||
-rw-r--r-- | dex2oat/linker/image_writer.cc | 22 | ||||
-rw-r--r-- | runtime/art_field.h | 6 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 32 | ||||
-rw-r--r-- | runtime/well_known_classes.h | 6 |
7 files changed, 139 insertions, 84 deletions
diff --git a/compiler/optimizing/intrinsic_objects.cc b/compiler/optimizing/intrinsic_objects.cc index d7042d22c8..7c430acbe4 100644 --- a/compiler/optimizing/intrinsic_objects.cc +++ b/compiler/optimizing/intrinsic_objects.cc @@ -29,16 +29,41 @@ namespace art HIDDEN { static constexpr size_t kIntrinsicObjectsOffset = enum_cast<size_t>(ImageHeader::kIntrinsicObjectsStart); -ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::LookupIntegerCache() { - ArtField* cache_field = WellKnownClasses::java_lang_Integer_IntegerCache_cache; - ObjPtr<mirror::Class> integer_cache_class = cache_field->GetDeclaringClass(); - DCHECK(integer_cache_class->IsInitialized()); - ObjPtr<mirror::ObjectArray<mirror::Object>> integer_cache = +template <typename T> +static void FillIntrinsicsObjects( + ArtField* cache_field, + ObjPtr<mirror::ObjectArray<mirror::Object>> live_objects, + int32_t expected_low, + int32_t expected_high, + T type_check, + size_t& index) + REQUIRES_SHARED(Locks::mutator_lock_) { + ObjPtr<mirror::ObjectArray<mirror::Object>> cache = ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast( - cache_field->GetObject(integer_cache_class)); - CHECK(integer_cache != nullptr); - DCHECK(IntrinsicVisitor::CheckIntegerCacheFields(integer_cache)); - return integer_cache; + cache_field->GetObject(cache_field->GetDeclaringClass())); + DCHECK_EQ(expected_high - expected_low + 1, cache->GetLength()); + for (int32_t i = 0, length = cache->GetLength(); i != length; ++i) { + live_objects->Set(index++, cache->Get(i)); + type_check(cache->Get(i), expected_low++); + } +} + +void IntrinsicObjects::FillIntrinsicObjects( + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, size_t start_index) { + DCHECK_EQ(start_index, ImageHeader::kIntrinsicObjectsStart); + size_t index = start_index; +#define FILL_OBJECTS(name, low, high, type, offset) \ + FillIntrinsicsObjects( \ + WellKnownClasses::java_lang_ ##name ##_ ##name ##Cache_cache, \ + boot_image_live_objects, \ + low, \ + high, \ + [](ObjPtr<mirror::Object> obj, int32_t expected) REQUIRES_SHARED(Locks::mutator_lock_) { \ + CHECK_EQ(expected, WellKnownClasses::java_lang_ ##name ##_value->Get ##name(obj)); \ + }, \ + index); + BOXED_TYPES(FILL_OBJECTS) +#undef FILL_OBJECTS } static bool HasIntrinsicObjects( @@ -50,43 +75,26 @@ static bool HasIntrinsicObjects( return length != kIntrinsicObjectsOffset; } -ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::GetIntegerValueOfCache( - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) { - if (!HasIntrinsicObjects(boot_image_live_objects)) { - return nullptr; // No intrinsic objects. - } - // No need for read barrier for boot image object or for verifying the value that was just stored. - ObjPtr<mirror::Object> result = - boot_image_live_objects->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>( - kIntrinsicObjectsOffset); - DCHECK(result != nullptr); - DCHECK(result->IsObjectArray()); - DCHECK(result->GetClass()->DescriptorEquals("[Ljava/lang/Integer;")); - return ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(result); -} - -ObjPtr<mirror::Object> IntrinsicObjects::GetIntegerValueOfObject( +ObjPtr<mirror::Object> IntrinsicObjects::GetValueOfObject( ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, + size_t start_index, uint32_t index) { DCHECK(HasIntrinsicObjects(boot_image_live_objects)); - DCHECK_LT(index, - static_cast<uint32_t>(GetIntegerValueOfCache(boot_image_live_objects)->GetLength())); - // No need for read barrier for boot image object or for verifying the value that was just stored. ObjPtr<mirror::Object> result = boot_image_live_objects->GetWithoutChecks<kVerifyNone, kWithoutReadBarrier>( - kIntrinsicObjectsOffset + /* skip the IntegerCache.cache */ 1u + index); + kIntrinsicObjectsOffset + start_index + index); DCHECK(result != nullptr); - DCHECK(result->GetClass()->DescriptorEquals("Ljava/lang/Integer;")); return result; } -MemberOffset IntrinsicObjects::GetIntegerValueOfArrayDataOffset( - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) { +MemberOffset IntrinsicObjects::GetValueOfArrayDataOffset( + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, + size_t start_index) { DCHECK(HasIntrinsicObjects(boot_image_live_objects)); MemberOffset result = - mirror::ObjectArray<mirror::Object>::OffsetOfElement(kIntrinsicObjectsOffset + 1u); - DCHECK_EQ(GetIntegerValueOfObject(boot_image_live_objects, 0u), + mirror::ObjectArray<mirror::Object>::OffsetOfElement(kIntrinsicObjectsOffset + start_index); + DCHECK_EQ(GetValueOfObject(boot_image_live_objects, start_index, 0u), (boot_image_live_objects ->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(result))); return result; diff --git a/compiler/optimizing/intrinsic_objects.h b/compiler/optimizing/intrinsic_objects.h index 1cc8f4dbc3..61f4825224 100644 --- a/compiler/optimizing/intrinsic_objects.h +++ b/compiler/optimizing/intrinsic_objects.h @@ -21,11 +21,12 @@ #include "base/bit_utils.h" #include "base/macros.h" #include "base/mutex.h" +#include "obj_ptr.h" +#include "offsets.h" namespace art HIDDEN { class ClassLinker; -template <class MirrorType> class ObjPtr; class MemberOffset; class Thread; @@ -34,6 +35,20 @@ class Object; template <class T> class ObjectArray; } // namespace mirror +#define BOXED_TYPES(V) \ + V(Byte, -128, 127, DataType::Type::kInt8, 0) \ + V(Short, -128, 127, DataType::Type::kInt16, kByteCacheLastIndex) \ + V(Character, 0, 127, DataType::Type::kUint16, kShortCacheLastIndex) \ + V(Integer, -128, 127, DataType::Type::kInt32, kCharacterCacheLastIndex) + +#define DEFINE_BOXED_CONSTANTS(name, low, high, primitive_type, start_index) \ + static constexpr size_t k ##name ##CacheLastIndex = start_index + (high - low + 1); \ + static constexpr size_t k ##name ##CacheFirstIndex = start_index; + BOXED_TYPES(DEFINE_BOXED_CONSTANTS) + + static constexpr size_t kNumberOfBoxedCaches = kIntegerCacheLastIndex; +#undef DEFINE_BOXED_CONSTANTS + class IntrinsicObjects { public: enum class PatchType { @@ -56,25 +71,44 @@ class IntrinsicObjects { return IndexField::Decode(intrinsic_data); } - // Functions for retrieving data for Integer.valueOf(). - EXPORT static ObjPtr<mirror::ObjectArray<mirror::Object>> LookupIntegerCache() - REQUIRES_SHARED(Locks::mutator_lock_); - EXPORT static ObjPtr<mirror::ObjectArray<mirror::Object>> GetIntegerValueOfCache( - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) - REQUIRES_SHARED(Locks::mutator_lock_); - EXPORT static ObjPtr<mirror::Object> GetIntegerValueOfObject( - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, - uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_); - EXPORT static MemberOffset GetIntegerValueOfArrayDataOffset( - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) + // Helpers returning addresses of objects, suitable for embedding in generated code. +#define DEFINE_BOXED_ACCESSES(name, _, __, ___, start_index) \ + static ObjPtr<mirror::Object> Get ##name ##ValueOfObject( \ + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, \ + uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_) { \ + return GetValueOfObject(boot_image_live_objects, k ##name ##CacheFirstIndex, index); \ + } \ + static MemberOffset Get ##name ##ValueOfArrayDataOffset( \ + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) \ + REQUIRES_SHARED(Locks::mutator_lock_) { \ + return GetValueOfArrayDataOffset(boot_image_live_objects, k ##name ##CacheFirstIndex); \ + } + BOXED_TYPES(DEFINE_BOXED_ACCESSES) +#undef DEFINED_BOXED_ACCESSES + + EXPORT static void FillIntrinsicObjects( + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, size_t start_index) REQUIRES_SHARED(Locks::mutator_lock_); + static size_t GetNumberOfIntrinsicObjects() { + return kNumberOfBoxedCaches; + } + private: static constexpr size_t kPatchTypeBits = MinimumBitsToStore(static_cast<uint32_t>(PatchType::kLast)); static constexpr size_t kIndexBits = BitSizeOf<uint32_t>() - kPatchTypeBits; using PatchTypeField = BitField<uint32_t, 0u, kPatchTypeBits>; using IndexField = BitField<uint32_t, kPatchTypeBits, kIndexBits>; + + EXPORT static ObjPtr<mirror::Object> GetValueOfObject( + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, + size_t start_index, + uint32_t index) REQUIRES_SHARED(Locks::mutator_lock_); + + EXPORT static MemberOffset GetValueOfArrayDataOffset( + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, + size_t start_index) REQUIRES_SHARED(Locks::mutator_lock_); }; } // namespace art diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 39d10b819d..e443a51889 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -115,11 +115,8 @@ bool IntrinsicVisitor::CheckIntegerCacheFields(ObjPtr<mirror::ObjectArray<mirror return true; } -static bool CheckIntegerCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_cache) +static bool CheckIntegerCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects) REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK(boot_image_cache != nullptr); - // Since we have a cache in the boot image, both java.lang.Integer and // java.lang.Integer$IntegerCache must be initialized in the boot image. ObjPtr<mirror::Class> cache_class = WellKnownClasses::java_lang_Integer_IntegerCache.Get(); @@ -127,12 +124,8 @@ static bool CheckIntegerCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_i ObjPtr<mirror::Class> integer_class = WellKnownClasses::java_lang_Integer.Get(); DCHECK(integer_class->IsInitialized()); - // Check that the current cache is the same as the `boot_image_cache`. - ObjPtr<mirror::ObjectArray<mirror::Object>> current_cache = GetIntegerCacheArray(cache_class); - if (current_cache != boot_image_cache) { - return false; // Messed up IntegerCache.cache. - } - if (!IntrinsicVisitor::CheckIntegerCacheFields(current_cache)) { + ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_cache = GetIntegerCacheArray(cache_class); + if (!IntrinsicVisitor::CheckIntegerCacheFields(boot_image_cache)) { return false; } @@ -220,13 +213,7 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, } else { ScopedObjectAccess soa(Thread::Current()); ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects = GetBootImageLiveObjects(); - ObjPtr<mirror::ObjectArray<mirror::Object>> cache = - IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects); - if (cache == nullptr) { - return; // No cache in the boot image. - } - DCHECK_IMPLIES(compiler_options.IsAotCompiler(), - CheckIntegerCache(boot_image_live_objects, cache)); + DCHECK_IMPLIES(compiler_options.IsAotCompiler(), CheckIntegerCache(boot_image_live_objects)); if (input->IsIntConstant()) { if (kIsDebugBuild) { @@ -314,8 +301,6 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I"); DCHECK(value_field != nullptr); info.value_offset = value_field->GetOffset().Uint32Value(); - DCHECK_EQ(info.length, dchecked_integral_cast<uint32_t>( - IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects)->GetLength())); if (invoke->InputAt(0)->IsIntConstant()) { int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue(); diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index fac273c4da..b1ed99712b 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -355,15 +355,13 @@ HashMap<mirror::Object*, uint32_t> MatchDirtyObjectPaths( static ObjPtr<mirror::ObjectArray<mirror::Object>> AllocateBootImageLiveObjects( Thread* self, Runtime* runtime) REQUIRES_SHARED(Locks::mutator_lock_) { ClassLinker* class_linker = runtime->GetClassLinker(); - // The objects used for the Integer.valueOf() intrinsic must remain live even if references + // The objects used for intrinsics must remain live even if references // to them are removed using reflection. Image roots are not accessible through reflection, // so the array we construct here shall keep them alive. StackHandleScope<1> hs(self); - Handle<mirror::ObjectArray<mirror::Object>> integer_cache = - hs.NewHandle(IntrinsicObjects::LookupIntegerCache()); size_t live_objects_size = enum_cast<size_t>(ImageHeader::kIntrinsicObjectsStart) + - ((integer_cache != nullptr) ? (/* cache */ 1u + integer_cache->GetLength()) : 0u); + IntrinsicObjects::GetNumberOfIntrinsicObjects(); ObjPtr<mirror::ObjectArray<mirror::Object>> live_objects = mirror::ObjectArray<mirror::Object>::Alloc( self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker), live_objects_size); @@ -387,21 +385,7 @@ static ObjPtr<mirror::ObjectArray<mirror::Object>> AllocateBootImageLiveObjects( set_entry(ImageHeader::kClearedJniWeakSentinel, runtime->GetSentinel().Read()); DCHECK_EQ(index, enum_cast<int32_t>(ImageHeader::kIntrinsicObjectsStart)); - if (integer_cache != nullptr) { - live_objects->Set(index++, integer_cache.Get()); - for (int32_t i = 0, length = integer_cache->GetLength(); i != length; ++i) { - live_objects->Set(index++, integer_cache->Get(i)); - } - } - CHECK_EQ(index, live_objects->GetLength()); - - if (kIsDebugBuild && integer_cache != nullptr) { - CHECK_EQ(integer_cache.Get(), IntrinsicObjects::GetIntegerValueOfCache(live_objects)); - for (int32_t i = 0, len = integer_cache->GetLength(); i != len; ++i) { - CHECK_EQ(integer_cache->GetWithoutChecks(i), - IntrinsicObjects::GetIntegerValueOfObject(live_objects, i)); - } - } + IntrinsicObjects::FillIntrinsicObjects(live_objects, index); return live_objects; } diff --git a/runtime/art_field.h b/runtime/art_field.h index c205920833..8a771af126 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -124,6 +124,9 @@ class ArtField final { void SetByte(ObjPtr<mirror::Object> object, int8_t b) REQUIRES_SHARED(Locks::mutator_lock_); uint16_t GetChar(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); + uint16_t GetCharacter(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_) { + return GetChar(object); + } template<bool kTransactionActive> void SetChar(ObjPtr<mirror::Object> object, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_); @@ -134,6 +137,9 @@ class ArtField final { void SetShort(ObjPtr<mirror::Object> object, int16_t s) REQUIRES_SHARED(Locks::mutator_lock_); int32_t GetInt(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); + int32_t GetInteger(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_) { + return GetInt(object); + } template<bool kTransactionActive> void SetInt(ObjPtr<mirror::Object> object, int32_t i) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 49074e8e7f..7c77af9479 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -168,6 +168,12 @@ ArtField* WellKnownClasses::java_lang_Short_ShortCache_cache; ArtField* WellKnownClasses::java_lang_Integer_IntegerCache_cache; ArtField* WellKnownClasses::java_lang_Long_LongCache_cache; +ArtField* WellKnownClasses::java_lang_Byte_value; +ArtField* WellKnownClasses::java_lang_Character_value; +ArtField* WellKnownClasses::java_lang_Short_value; +ArtField* WellKnownClasses::java_lang_Integer_value; +ArtField* WellKnownClasses::java_lang_Long_value; + static ObjPtr<mirror::Class> FindSystemClass(ClassLinker* class_linker, Thread* self, const char* descriptor) @@ -241,6 +247,15 @@ static ArtField* CacheBoxingCacheField(ClassLinker* class_linker, return CacheField(boxed_class, /*is_static=*/ true, "cache", cache_type); } +static ArtField* CacheValueInBoxField(ClassLinker* class_linker, + Thread* self, + const char* class_name, + const char* cache_type) + REQUIRES_SHARED(Locks::mutator_lock_) { + ObjPtr<mirror::Class> boxed_class = FindSystemClass(class_linker, self, class_name); + return CacheField(boxed_class, /*is_static=*/ false, "value", cache_type); +} + #define STRING_INIT_LIST(V) \ V(java_lang_String_init, "()V", newEmptyString, "newEmptyString", "()Ljava/lang/String;", NewEmptyString) \ V(java_lang_String_init_B, "([B)V", newStringFromBytes_B, "newStringFromBytes", "([B)Ljava/lang/String;", NewStringFromBytes_B) \ @@ -388,6 +403,17 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { java_lang_Long_LongCache_cache = CacheBoxingCacheField( class_linker, self, "Ljava/lang/Long$LongCache;", "[Ljava/lang/Long;"); + java_lang_Byte_value = CacheValueInBoxField( + class_linker, self, "Ljava/lang/Byte;", "B"); + java_lang_Character_value = CacheValueInBoxField( + class_linker, self, "Ljava/lang/Character;", "C"); + java_lang_Short_value = CacheValueInBoxField( + class_linker, self, "Ljava/lang/Short;", "S"); + java_lang_Integer_value = CacheValueInBoxField( + class_linker, self, "Ljava/lang/Integer;", "I"); + java_lang_Long_value = CacheValueInBoxField( + class_linker, self, "Ljava/lang/Long;", "J"); + StackHandleScope<42u> hs(self); Handle<mirror::Class> d_s_bdcl = hs.NewHandle(FindSystemClass(class_linker, self, "Ldalvik/system/BaseDexClassLoader;")); @@ -940,6 +966,12 @@ void WellKnownClasses::Clear() { java_lang_Short_ShortCache_cache = nullptr; java_lang_Integer_IntegerCache_cache = nullptr; java_lang_Long_LongCache_cache = nullptr; + + java_lang_Byte_value = nullptr; + java_lang_Character_value = nullptr; + java_lang_Short_value = nullptr; + java_lang_Integer_value = nullptr; + java_lang_Long_value = nullptr; } ObjPtr<mirror::Class> WellKnownClasses::ToClass(jclass global_jclass) { diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 6ef5f6d3d9..f717030d82 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -213,6 +213,12 @@ struct WellKnownClasses { static ArtField* java_lang_Integer_IntegerCache_cache; static ArtField* java_lang_Long_LongCache_cache; + static ArtField* java_lang_Byte_value; + static ArtField* java_lang_Character_value; + static ArtField* java_lang_Short_value; + static ArtField* java_lang_Integer_value; + static ArtField* java_lang_Long_value; + static constexpr ClassFromField<&dalvik_system_BaseDexClassLoader_pathList> dalvik_system_BaseDexClassLoader; static constexpr ClassFromMethod<&dalvik_system_DelegateLastClassLoader_init> |