summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/intrinsic_objects.cc14
-rw-r--r--compiler/optimizing/intrinsic_objects.h4
-rw-r--r--compiler/optimizing/intrinsics.cc78
-rw-r--r--dex2oat/linker/image_writer.cc2
-rw-r--r--runtime/class_linker.cc6
-rw-r--r--runtime/well_known_classes.cc32
-rw-r--r--runtime/well_known_classes.h20
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