diff options
-rw-r--r-- | compiler/optimizing/intrinsic_objects.cc | 14 | ||||
-rw-r--r-- | compiler/optimizing/intrinsic_objects.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 78 | ||||
-rw-r--r-- | dex2oat/linker/image_writer.cc | 2 | ||||
-rw-r--r-- | runtime/class_linker.cc | 6 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 32 | ||||
-rw-r--r-- | runtime/well_known_classes.h | 20 |
7 files changed, 87 insertions, 69 deletions
diff --git a/compiler/optimizing/intrinsic_objects.cc b/compiler/optimizing/intrinsic_objects.cc index 7e542117a9..b1b864e7ba 100644 --- a/compiler/optimizing/intrinsic_objects.cc +++ b/compiler/optimizing/intrinsic_objects.cc @@ -27,16 +27,10 @@ namespace art HIDDEN { static constexpr size_t kIntrinsicObjectsOffset = enum_cast<size_t>(ImageHeader::kIntrinsicObjectsStart); -ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::LookupIntegerCache( - Thread* self, ClassLinker* class_linker) { - ObjPtr<mirror::Class> integer_cache_class = class_linker->LookupClass( - self, "Ljava/lang/Integer$IntegerCache;", /* class_loader= */ nullptr); - if (integer_cache_class == nullptr || !integer_cache_class->IsInitialized()) { - return nullptr; - } - ArtField* cache_field = - integer_cache_class->FindDeclaredStaticField("cache", "[Ljava/lang/Integer;"); - CHECK(cache_field != nullptr); +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 = ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast( cache_field->GetObject(integer_cache_class)); diff --git a/compiler/optimizing/intrinsic_objects.h b/compiler/optimizing/intrinsic_objects.h index d750f2934b..1cc8f4dbc3 100644 --- a/compiler/optimizing/intrinsic_objects.h +++ b/compiler/optimizing/intrinsic_objects.h @@ -57,8 +57,8 @@ class IntrinsicObjects { } // Functions for retrieving data for Integer.valueOf(). - EXPORT static ObjPtr<mirror::ObjectArray<mirror::Object>> LookupIntegerCache( - Thread* self, ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_); + 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_); diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index b3615e6110..0849c4fa89 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -32,7 +32,7 @@ #include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" #include "thread-current-inl.h" -#include "well_known_classes.h" +#include "well_known_classes-inl.h" namespace art HIDDEN { @@ -53,7 +53,6 @@ std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic) { static const char kIntegerCacheDescriptor[] = "Ljava/lang/Integer$IntegerCache;"; static const char kIntegerDescriptor[] = "Ljava/lang/Integer;"; -static const char kIntegerArrayDescriptor[] = "[Ljava/lang/Integer;"; static const char kLowFieldName[] = "low"; static const char kHighFieldName[] = "high"; static const char kValueFieldName[] = "value"; @@ -72,21 +71,9 @@ static ObjPtr<mirror::ObjectArray<mirror::Object>> GetBootImageLiveObjects() return boot_image_live_objects; } -static ObjPtr<mirror::Class> LookupInitializedClass(Thread* self, - ClassLinker* class_linker, - const char* descriptor) - REQUIRES_SHARED(Locks::mutator_lock_) { - ObjPtr<mirror::Class> klass = - class_linker->LookupClass(self, descriptor, /* class_loader= */ nullptr); - DCHECK(klass != nullptr); - DCHECK(klass->IsInitialized()); - return klass; -} - static ObjPtr<mirror::ObjectArray<mirror::Object>> GetIntegerCacheArray( ObjPtr<mirror::Class> cache_class) REQUIRES_SHARED(Locks::mutator_lock_) { - ArtField* cache_field = cache_class->FindDeclaredStaticField("cache", kIntegerArrayDescriptor); - DCHECK(cache_field != nullptr); + ArtField* cache_field = WellKnownClasses::java_lang_Integer_IntegerCache_cache; return ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(cache_field->GetObject(cache_class)); } @@ -97,19 +84,17 @@ static int32_t GetIntegerCacheField(ObjPtr<mirror::Class> cache_class, const cha return field->GetInt(cache_class); } -static bool CheckIntegerCache(Thread* self, - ClassLinker* class_linker, - ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, +static bool CheckIntegerCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects, ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_cache) 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 = - LookupInitializedClass(self, class_linker, kIntegerCacheDescriptor); - ObjPtr<mirror::Class> integer_class = - LookupInitializedClass(self, class_linker, kIntegerDescriptor); + ObjPtr<mirror::Class> cache_class = WellKnownClasses::java_lang_Integer_IntegerCache.Get(); + DCHECK(cache_class->IsInitialized()); + 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); @@ -176,23 +161,11 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, !compiler_options.IsImageClass(kIntegerDescriptor)) { return; } - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Thread* self = Thread::Current(); - ScopedObjectAccess soa(self); - ObjPtr<mirror::Class> cache_class = class_linker->LookupClass( - self, kIntegerCacheDescriptor, /* class_loader= */ nullptr); - DCHECK(cache_class != nullptr); - if (UNLIKELY(!cache_class->IsInitialized())) { - LOG(WARNING) << "Image class " << cache_class->PrettyDescriptor() << " is uninitialized."; - return; - } - ObjPtr<mirror::Class> integer_class = - class_linker->LookupClass(self, kIntegerDescriptor, /* class_loader= */ nullptr); - DCHECK(integer_class != nullptr); - if (UNLIKELY(!integer_class->IsInitialized())) { - LOG(WARNING) << "Image class " << integer_class->PrettyDescriptor() << " is uninitialized."; - return; - } + ScopedObjectAccess soa(Thread::Current()); + ObjPtr<mirror::Class> cache_class = WellKnownClasses::java_lang_Integer_IntegerCache.Get(); + DCHECK(cache_class->IsInitialized()); + ObjPtr<mirror::Class> integer_class = WellKnownClasses::java_lang_Integer.Get(); + DCHECK(integer_class->IsInitialized()); int32_t low = GetIntegerCacheField(cache_class, kLowFieldName); int32_t high = GetIntegerCacheField(cache_class, kHighFieldName); if (kIsDebugBuild) { @@ -216,9 +189,7 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, } } } else { - Runtime* runtime = Runtime::Current(); - Thread* self = Thread::Current(); - ScopedObjectAccess soa(self); + 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); @@ -226,12 +197,12 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, return; // No cache in the boot image. } if (compiler_options.IsJitCompiler()) { - if (!CheckIntegerCache(self, runtime->GetClassLinker(), boot_image_live_objects, cache)) { + if (!CheckIntegerCache(boot_image_live_objects, cache)) { return; // The cache was somehow messed up, probably by using reflection. } } else { DCHECK(compiler_options.IsAotCompiler()); - DCHECK(CheckIntegerCache(self, runtime->GetClassLinker(), boot_image_live_objects, cache)); + DCHECK(CheckIntegerCache(boot_image_live_objects, cache)); if (input->IsIntConstant()) { int32_t value = input->AsIntConstant()->GetValue(); // Retrieve the `value` from the lowest cached Integer. @@ -264,10 +235,9 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, } } -static int32_t GetIntegerCacheLowFromIntegerCache(Thread* self, ClassLinker* class_linker) - REQUIRES_SHARED(Locks::mutator_lock_) { - ObjPtr<mirror::Class> cache_class = - LookupInitializedClass(self, class_linker, kIntegerCacheDescriptor); +static int32_t GetIntegerCacheLowFromIntegerCache() REQUIRES_SHARED(Locks::mutator_lock_) { + ObjPtr<mirror::Class> cache_class = WellKnownClasses::java_lang_Integer_IntegerCache.Get(); + DCHECK(cache_class->IsInitialized()); return GetIntegerCacheField(cache_class, kLowFieldName); } @@ -289,10 +259,7 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo // we need to provide data that shall not lead to a crash even if the fields were // modified through reflection since ComputeIntegerValueOfLocations() when JITting. - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Thread* self = Thread::Current(); - ScopedObjectAccess soa(self); - + ScopedObjectAccess soa(Thread::Current()); IntegerValueOfInfo info; if (compiler_options.IsBootImage()) { ObjPtr<mirror::Class> integer_class = invoke->GetResolvedMethod()->GetDeclaringClass(); @@ -300,8 +267,7 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I"); DCHECK(value_field != nullptr); info.value_offset = value_field->GetOffset().Uint32Value(); - ObjPtr<mirror::Class> cache_class = - LookupInitializedClass(self, class_linker, kIntegerCacheDescriptor); + ObjPtr<mirror::Class> cache_class = WellKnownClasses::java_lang_Integer_IntegerCache.Get(); info.low = GetIntegerCacheField(cache_class, kLowFieldName); int32_t high = GetIntegerCacheField(cache_class, kHighFieldName); info.length = dchecked_integral_cast<uint32_t>(high - info.low + 1); @@ -331,11 +297,11 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo if (compiler_options.IsJitCompiler()) { // Use the current `IntegerCache.low` for JIT to avoid truly surprising behavior if the // code messes up the `value` field in the lowest cached Integer using reflection. - info.low = GetIntegerCacheLowFromIntegerCache(self, class_linker); + info.low = GetIntegerCacheLowFromIntegerCache(); } else { // For app AOT, the `low_integer->value` should be the same as `IntegerCache.low`. info.low = value_field->GetInt(low_integer); - DCHECK_EQ(info.low, GetIntegerCacheLowFromIntegerCache(self, class_linker)); + DCHECK_EQ(info.low, GetIntegerCacheLowFromIntegerCache()); } // Do not look at `IntegerCache.high`, use the immutable length of the cache array instead. info.length = dchecked_integral_cast<uint32_t>( diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index 155ac72d19..fac273c4da 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -360,7 +360,7 @@ static ObjPtr<mirror::ObjectArray<mirror::Object>> AllocateBootImageLiveObjects( // 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(self, class_linker)); + hs.NewHandle(IntrinsicObjects::LookupIntegerCache()); size_t live_objects_size = enum_cast<size_t>(ImageHeader::kIntrinsicObjectsStart) + ((integer_cache != nullptr) ? (/* cache */ 1u + integer_cache->GetLength()) : 0u); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index c9ee20e585..d8383222cf 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1217,6 +1217,12 @@ void ClassLinker::RunRootClinits(Thread* self) { // Initialize empty arrays needed by `StackOverflowError`. WellKnownClasses::java_util_Collections_EMPTY_LIST, WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT, + // Initialize boxing caches needed by the compiler. + WellKnownClasses::java_lang_Byte_ByteCache_cache, + WellKnownClasses::java_lang_Character_CharacterCache_cache, + WellKnownClasses::java_lang_Integer_IntegerCache_cache, + WellKnownClasses::java_lang_Long_LongCache_cache, + WellKnownClasses::java_lang_Short_ShortCache_cache, }; for (ArtField* field : fields_of_classes_to_initialize) { EnsureRootInitialized(this, self, field->GetDeclaringClass()); diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index cdc254ab8a..49074e8e7f 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -162,6 +162,12 @@ ArtField* WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length; ArtField* WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset; ArtField* WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type; +ArtField* WellKnownClasses::java_lang_Byte_ByteCache_cache; +ArtField* WellKnownClasses::java_lang_Character_CharacterCache_cache; +ArtField* WellKnownClasses::java_lang_Short_ShortCache_cache; +ArtField* WellKnownClasses::java_lang_Integer_IntegerCache_cache; +ArtField* WellKnownClasses::java_lang_Long_LongCache_cache; + static ObjPtr<mirror::Class> FindSystemClass(ClassLinker* class_linker, Thread* self, const char* descriptor) @@ -226,6 +232,15 @@ static ArtMethod* CachePrimitiveBoxingMethod(ClassLinker* class_linker, return CacheMethod(boxed_class, /*is_static=*/ true, "valueOf", signature.c_str(), pointer_size); } +static ArtField* CacheBoxingCacheField(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=*/ true, "cache", 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) \ @@ -362,6 +377,17 @@ void WellKnownClasses::InitFieldsAndMethodsOnly(JNIEnv* env) { java_lang_Short_valueOf = CachePrimitiveBoxingMethod(class_linker, self, 'S', "Ljava/lang/Short;"); + java_lang_Byte_ByteCache_cache = CacheBoxingCacheField( + class_linker, self, "Ljava/lang/Byte$ByteCache;", "[Ljava/lang/Byte;"); + java_lang_Character_CharacterCache_cache = CacheBoxingCacheField( + class_linker, self, "Ljava/lang/Character$CharacterCache;", "[Ljava/lang/Character;"); + java_lang_Short_ShortCache_cache = CacheBoxingCacheField( + class_linker, self, "Ljava/lang/Short$ShortCache;", "[Ljava/lang/Short;"); + java_lang_Integer_IntegerCache_cache = CacheBoxingCacheField( + class_linker, self, "Ljava/lang/Integer$IntegerCache;", "[Ljava/lang/Integer;"); + java_lang_Long_LongCache_cache = CacheBoxingCacheField( + class_linker, self, "Ljava/lang/Long$LongCache;", "[Ljava/lang/Long;"); + StackHandleScope<42u> hs(self); Handle<mirror::Class> d_s_bdcl = hs.NewHandle(FindSystemClass(class_linker, self, "Ldalvik/system/BaseDexClassLoader;")); @@ -908,6 +934,12 @@ void WellKnownClasses::Clear() { org_apache_harmony_dalvik_ddmc_Chunk_length = nullptr; org_apache_harmony_dalvik_ddmc_Chunk_offset = nullptr; org_apache_harmony_dalvik_ddmc_Chunk_type = nullptr; + + java_lang_Byte_ByteCache_cache = nullptr; + java_lang_Character_CharacterCache_cache = nullptr; + java_lang_Short_ShortCache_cache = nullptr; + java_lang_Integer_IntegerCache_cache = nullptr; + java_lang_Long_LongCache_cache = nullptr; } ObjPtr<mirror::Class> WellKnownClasses::ToClass(jclass global_jclass) { diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 444f9e139f..6ef5f6d3d9 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -207,6 +207,12 @@ struct WellKnownClasses { static ArtField* org_apache_harmony_dalvik_ddmc_Chunk_offset; static ArtField* org_apache_harmony_dalvik_ddmc_Chunk_type; + static ArtField* java_lang_Byte_ByteCache_cache; + static ArtField* java_lang_Character_CharacterCache_cache; + static ArtField* java_lang_Short_ShortCache_cache; + static ArtField* java_lang_Integer_IntegerCache_cache; + static ArtField* java_lang_Long_LongCache_cache; + static constexpr ClassFromField<&dalvik_system_BaseDexClassLoader_pathList> dalvik_system_BaseDexClassLoader; static constexpr ClassFromMethod<&dalvik_system_DelegateLastClassLoader_init> @@ -243,6 +249,20 @@ struct WellKnownClasses { static constexpr ClassFromField<&java_util_Collections_EMPTY_LIST> java_util_Collections; static constexpr ClassFromField<&libcore_util_EmptyArray_STACK_TRACE_ELEMENT> libcore_util_EmptyArray; + + static constexpr ClassFromField<&java_lang_Byte_ByteCache_cache> java_lang_Byte_ByteCache; + static constexpr ClassFromField<&java_lang_Character_CharacterCache_cache> + java_lang_Character_CharacterCache; + static constexpr ClassFromField<&java_lang_Short_ShortCache_cache> java_lang_Short_ShortCache; + static constexpr ClassFromField<&java_lang_Integer_IntegerCache_cache> + java_lang_Integer_IntegerCache; + static constexpr ClassFromField<&java_lang_Long_LongCache_cache> java_lang_Long_LongCache; + + static constexpr ClassFromMethod<&java_lang_Byte_valueOf> java_lang_Byte; + static constexpr ClassFromMethod<&java_lang_Character_valueOf> java_lang_Character; + static constexpr ClassFromMethod<&java_lang_Short_valueOf> java_lang_Short; + static constexpr ClassFromMethod<&java_lang_Integer_valueOf> java_lang_Integer; + static constexpr ClassFromMethod<&java_lang_Long_valueOf> java_lang_Long; }; } // namespace art |