diff options
author | 2023-11-10 09:41:33 +0000 | |
---|---|---|
committer | 2023-11-16 12:14:25 +0000 | |
commit | fe307811eea419ac99148a824b7e02db378625a3 (patch) | |
tree | 19766ef079f8144a2bda08f55cff2e6aeb93dc50 /compiler | |
parent | 6ad23882ac8b455c4b6068c37d1e5ebbc5aaa42f (diff) |
Harcode IntegerCache range.
Let JIT assume these ranges. They are checked at AOT time when
generating the boot image and when compiling applications.
Test: test.py
Change-Id: Ib2240d150bab366a3c17e0015503f728a98ae2ea
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/intrinsic_objects.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 102 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 2 |
3 files changed, 60 insertions, 46 deletions
diff --git a/compiler/optimizing/intrinsic_objects.cc b/compiler/optimizing/intrinsic_objects.cc index d9f54429e2..d7042d22c8 100644 --- a/compiler/optimizing/intrinsic_objects.cc +++ b/compiler/optimizing/intrinsic_objects.cc @@ -20,6 +20,7 @@ #include "base/casts.h" #include "base/logging.h" #include "image.h" +#include "intrinsics.h" #include "obj_ptr-inl.h" #include "well_known_classes.h" @@ -36,6 +37,7 @@ ObjPtr<mirror::ObjectArray<mirror::Object>> IntrinsicObjects::LookupIntegerCache ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast( cache_field->GetObject(integer_cache_class)); CHECK(integer_cache != nullptr); + DCHECK(IntrinsicVisitor::CheckIntegerCacheFields(integer_cache)); return integer_cache; } diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 0849c4fa89..39d10b819d 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -57,6 +57,11 @@ static const char kLowFieldName[] = "low"; static const char kHighFieldName[] = "high"; static const char kValueFieldName[] = "value"; +static constexpr int32_t kIntegerCacheLow = -128; +static constexpr int32_t kIntegerCacheHigh = 127; +static constexpr int32_t kIntegerCacheLength = kIntegerCacheHigh - kIntegerCacheLow + 1; + + static ObjPtr<mirror::ObjectArray<mirror::Object>> GetBootImageLiveObjects() REQUIRES_SHARED(Locks::mutator_lock_) { gc::Heap* heap = Runtime::Current()->GetHeap(); @@ -84,6 +89,32 @@ static int32_t GetIntegerCacheField(ObjPtr<mirror::Class> cache_class, const cha return field->GetInt(cache_class); } +bool IntrinsicVisitor::CheckIntegerCacheFields(ObjPtr<mirror::ObjectArray<mirror::Object>> cache) { + ObjPtr<mirror::Class> cache_class = WellKnownClasses::java_lang_Integer_IntegerCache.Get(); + // Check that the range matches the boot image cache length. + int32_t low = GetIntegerCacheField(cache_class, kLowFieldName); + int32_t high = GetIntegerCacheField(cache_class, kHighFieldName); + if (low != kIntegerCacheLow || high != kIntegerCacheHigh) { + return false; + } + if (cache->GetLength() != high - low + 1) { + return false; + } + + // Check that the elements match the values we expect. + ObjPtr<mirror::Class> integer_class = WellKnownClasses::java_lang_Integer.Get(); + DCHECK(integer_class->IsInitialized()); + ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I"); + DCHECK(value_field != nullptr); + for (int32_t i = 0, len = cache->GetLength(); i != len; ++i) { + ObjPtr<mirror::Object> current_object = cache->Get(i); + if (value_field->GetInt(current_object) != low + i) { + return false; + } + } + return true; +} + 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_) { @@ -101,12 +132,8 @@ static bool CheckIntegerCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_i if (current_cache != boot_image_cache) { return false; // Messed up IntegerCache.cache. } - - // Check that the range matches the boot image cache length. - int32_t low = GetIntegerCacheField(cache_class, kLowFieldName); - int32_t high = GetIntegerCacheField(cache_class, kHighFieldName); - if (boot_image_cache->GetLength() != high - low + 1) { - return false; // Messed up IntegerCache.low or IntegerCache.high. + if (!IntrinsicVisitor::CheckIntegerCacheFields(current_cache)) { + return false; } // Check that the elements match the boot image intrinsic objects and check their values as well. @@ -122,7 +149,7 @@ static bool CheckIntegerCache(ObjPtr<mirror::ObjectArray<mirror::Object>> boot_i if (boot_image_object != current_object) { return false; // Messed up IntegerCache.cache[i] } - if (value_field->GetInt(boot_image_object) != low + i) { + if (value_field->GetInt(boot_image_object) != kIntegerCacheLow + i) { return false; // Messed up IntegerCache.cache[i].value. } } @@ -166,9 +193,11 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, 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); + int32_t low = kIntegerCacheLow; + int32_t high = kIntegerCacheHigh; if (kIsDebugBuild) { + CHECK_EQ(low, GetIntegerCacheField(cache_class, kLowFieldName)); + CHECK_EQ(high, GetIntegerCacheField(cache_class, kHighFieldName)); ObjPtr<mirror::ObjectArray<mirror::Object>> current_cache = GetIntegerCacheArray(cache_class); CHECK(current_cache != nullptr); CHECK_EQ(current_cache->GetLength(), high - low + 1); @@ -196,29 +225,25 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, if (cache == nullptr) { return; // No cache in the boot image. } - if (compiler_options.IsJitCompiler()) { - 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(boot_image_live_objects, cache)); - if (input->IsIntConstant()) { - int32_t value = input->AsIntConstant()->GetValue(); - // Retrieve the `value` from the lowest cached Integer. + DCHECK_IMPLIES(compiler_options.IsAotCompiler(), + CheckIntegerCache(boot_image_live_objects, cache)); + + if (input->IsIntConstant()) { + if (kIsDebugBuild) { + // Check the `value` from the lowest cached Integer. ObjPtr<mirror::Object> low_integer = IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, 0u); ObjPtr<mirror::Class> integer_class = low_integer->GetClass<kVerifyNone, kWithoutReadBarrier>(); ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I"); DCHECK(value_field != nullptr); - int32_t low = value_field->GetInt(low_integer); - if (static_cast<uint32_t>(value) - static_cast<uint32_t>(low) < - static_cast<uint32_t>(cache->GetLength())) { - // No call, we shall use direct pointer to the Integer object. Note that we cannot - // do this for JIT as the "low" can change through reflection before emitting the code. + DCHECK_EQ(kIntegerCacheLow, value_field->GetInt(low_integer)); + } + int32_t value = input->AsIntConstant()->GetValue(); + if (static_cast<uint32_t>(value) - static_cast<uint32_t>(kIntegerCacheLow) < + static_cast<uint32_t>(kIntegerCacheLength)) { + // No call, we shall use direct pointer to the Integer object. call_kind = LocationSummary::kNoCall; - } } } } @@ -235,12 +260,6 @@ void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke, } } -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); -} - inline IntrinsicVisitor::IntegerValueOfInfo::IntegerValueOfInfo() : value_offset(0), low(0), @@ -261,6 +280,8 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo ScopedObjectAccess soa(Thread::Current()); IntegerValueOfInfo info; + info.low = kIntegerCacheLow; + info.length = kIntegerCacheLength; if (compiler_options.IsBootImage()) { ObjPtr<mirror::Class> integer_class = invoke->GetResolvedMethod()->GetDeclaringClass(); DCHECK(integer_class->DescriptorEquals(kIntegerDescriptor)); @@ -268,9 +289,8 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo DCHECK(value_field != nullptr); info.value_offset = value_field->GetOffset().Uint32Value(); 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); + DCHECK_EQ(info.low, GetIntegerCacheField(cache_class, kLowFieldName)); + DCHECK_EQ(kIntegerCacheHigh, GetIntegerCacheField(cache_class, kHighFieldName)); if (invoke->InputAt(0)->IsIntConstant()) { int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue(); @@ -294,18 +314,8 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I"); DCHECK(value_field != nullptr); info.value_offset = value_field->GetOffset().Uint32Value(); - 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(); - } 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()); - } - // Do not look at `IntegerCache.high`, use the immutable length of the cache array instead. - info.length = dchecked_integral_cast<uint32_t>( - IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects)->GetLength()); + 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/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 177eedb363..fbcc613e8c 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -132,6 +132,8 @@ class IntrinsicVisitor : public ValueObject { static IntegerValueOfInfo ComputeIntegerValueOfInfo( HInvoke* invoke, const CompilerOptions& compiler_options); + static bool CheckIntegerCacheFields(ObjPtr<mirror::ObjectArray<mirror::Object>> cache) + REQUIRES_SHARED(Locks::mutator_lock_); static MemberOffset GetReferenceDisableIntrinsicOffset(); static MemberOffset GetReferenceSlowPathEnabledOffset(); |