diff options
author | Vladimir Marko <vmarko@google.com> | 2014-10-16 15:41:48 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2014-10-27 10:04:25 +0000 |
commit | 66c6d7bdfdd535e6ecf4461bba3804f1a7794fcd (patch) | |
tree | 178908b5c657241305f99aa44949427c18d1900a /compiler/driver | |
parent | 1ef3495abfa2a858b3cc7a1844383c8e7dff0b60 (diff) | |
download | art-66c6d7bdfdd535e6ecf4461bba3804f1a7794fcd.zip art-66c6d7bdfdd535e6ecf4461bba3804f1a7794fcd.tar.gz art-66c6d7bdfdd535e6ecf4461bba3804f1a7794fcd.tar.bz2 |
Rewrite class initialization check elimination.
Split the notion of type being in dex cache away from the
class being initialized. Include static invokes in the class
initialization elimination pass.
Change-Id: Ie3760d8fd55b987f9507f32ef51456a57d79e3fb
Diffstat (limited to 'compiler/driver')
-rw-r--r-- | compiler/driver/compiler_driver-inl.h | 40 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 12 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 24 |
3 files changed, 49 insertions, 27 deletions
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 3325568..1805d59 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -93,6 +93,10 @@ inline bool CompilerDriver::IsFieldVolatile(mirror::ArtField* field) { return field->IsVolatile(); } +inline MemberOffset CompilerDriver::GetFieldOffset(mirror::ArtField* field) { + return field->GetOffset(); +} + inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, mirror::ArtField* resolved_field, uint16_t field_idx) { @@ -107,16 +111,12 @@ inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( inline std::pair<bool, bool> CompilerDriver::IsFastStaticField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, - mirror::ArtField* resolved_field, uint16_t field_idx, MemberOffset* field_offset, - uint32_t* storage_index, bool* is_referrers_class, bool* is_initialized) { + mirror::ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) { DCHECK(resolved_field->IsStatic()); if (LIKELY(referrer_class != nullptr)) { mirror::Class* fields_class = resolved_field->GetDeclaringClass(); if (fields_class == referrer_class) { - *field_offset = resolved_field->GetOffset(); *storage_index = fields_class->GetDexTypeIndex(); - *is_referrers_class = true; // implies no worrying about class initialization - *is_initialized = true; return std::make_pair(true, true); } if (referrer_class->CanAccessResolvedField(fields_class, resolved_field, @@ -148,23 +148,30 @@ inline std::pair<bool, bool> CompilerDriver::IsFastStaticField( } } if (storage_idx != DexFile::kDexNoIndex) { - *field_offset = resolved_field->GetOffset(); *storage_index = storage_idx; - *is_referrers_class = false; - *is_initialized = fields_class->IsInitialized() && - CanAssumeTypeIsPresentInDexCache(*dex_file, storage_idx); return std::make_pair(true, !resolved_field->IsFinal()); } } } // Conservative defaults. - *field_offset = MemberOffset(0u); *storage_index = DexFile::kDexNoIndex; - *is_referrers_class = false; - *is_initialized = false; return std::make_pair(false, false); } +inline bool CompilerDriver::IsStaticFieldInReferrerClass(mirror::Class* referrer_class, + mirror::ArtField* resolved_field) { + DCHECK(resolved_field->IsStatic()); + mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + return referrer_class == fields_class; +} + +inline bool CompilerDriver::IsStaticFieldsClassInitialized(mirror::Class* referrer_class, + mirror::ArtField* resolved_field) { + DCHECK(resolved_field->IsStatic()); + mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + return fields_class == referrer_class || fields_class->IsInitialized(); +} + inline mirror::ArtMethod* CompilerDriver::ResolveMethod( ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, @@ -312,14 +319,13 @@ inline int CompilerDriver::IsFastInvoke( return stats_flags; } -inline bool CompilerDriver::NeedsClassInitialization(mirror::Class* referrer_class, - mirror::ArtMethod* resolved_method) { +inline bool CompilerDriver::IsMethodsClassInitialized(mirror::Class* referrer_class, + mirror::ArtMethod* resolved_method) { if (!resolved_method->IsStatic()) { - return false; + return true; } mirror::Class* methods_class = resolved_method->GetDeclaringClass(); - // NOTE: Unlike in IsFastStaticField(), we don't check CanAssumeTypeIsPresentInDexCache() here. - return methods_class != referrer_class && !methods_class->IsInitialized(); + return methods_class == referrer_class || methods_class->IsInitialized(); } } // namespace art diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index a60c5bc..eb5739f 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1094,11 +1094,17 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila if (resolved_field != nullptr && referrer_class != nullptr) { *is_volatile = IsFieldVolatile(resolved_field); std::pair<bool, bool> fast_path = IsFastStaticField( - dex_cache, referrer_class, resolved_field, field_idx, field_offset, - storage_index, is_referrers_class, is_initialized); + dex_cache, referrer_class, resolved_field, field_idx, storage_index); result = is_put ? fast_path.second : fast_path.first; } - if (!result) { + if (result) { + *field_offset = GetFieldOffset(resolved_field); + *is_referrers_class = IsStaticFieldInReferrerClass(referrer_class, resolved_field); + // *is_referrers_class == true implies no worrying about class initialization. + *is_initialized = (*is_referrers_class) || + (IsStaticFieldsClassInitialized(referrer_class, resolved_field) && + CanAssumeTypeIsPresentInDexCache(*mUnit->GetDexFile(), *storage_index)); + } else { // Conservative defaults. *is_volatile = true; *field_offset = MemberOffset(static_cast<size_t>(-1)); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 0796f48..6764aef 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -233,6 +233,7 @@ class CompilerDriver { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsFieldVolatile(mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + MemberOffset GetFieldOffset(mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Can we fast-path an IGET/IPUT access to an instance field? If yes, compute the field offset. std::pair<bool, bool> IsFastInstanceField( @@ -240,13 +241,20 @@ class CompilerDriver { mirror::ArtField* resolved_field, uint16_t field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Can we fast-path an SGET/SPUT access to a static field? If yes, compute the field offset, - // the type index of the declaring class in the referrer's dex file and whether the declaring - // class is the referrer's class or at least can be assumed to be initialized. + // Can we fast-path an SGET/SPUT access to a static field? If yes, compute the type index + // of the declaring class in the referrer's dex file. std::pair<bool, bool> IsFastStaticField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, - mirror::ArtField* resolved_field, uint16_t field_idx, MemberOffset* field_offset, - uint32_t* storage_index, bool* is_referrers_class, bool* is_initialized) + mirror::ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Is static field's in referrer's class? + bool IsStaticFieldInReferrerClass(mirror::Class* referrer_class, mirror::ArtField* resolved_field) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Is static field's class initialized? + bool IsStaticFieldsClassInitialized(mirror::Class* referrer_class, + mirror::ArtField* resolved_field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a method. Returns nullptr on failure, including incompatible class change. @@ -277,8 +285,10 @@ class CompilerDriver { uintptr_t* direct_code, uintptr_t* direct_method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Does invokation of the resolved method need class initialization? - bool NeedsClassInitialization(mirror::Class* referrer_class, mirror::ArtMethod* resolved_method) + // Is method's class initialized for an invoke? + // For static invokes to determine whether we need to consider potential call to <clinit>(). + // For non-static invokes, assuming a non-null reference, the class is always initialized. + bool IsMethodsClassInitialized(mirror::Class* referrer_class, mirror::ArtMethod* resolved_method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void ProcessedInstanceField(bool resolved); |