summaryrefslogtreecommitdiffstats
path: root/compiler/driver
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2014-10-16 15:41:48 +0100
committerVladimir Marko <vmarko@google.com>2014-10-27 10:04:25 +0000
commit66c6d7bdfdd535e6ecf4461bba3804f1a7794fcd (patch)
tree178908b5c657241305f99aa44949427c18d1900a /compiler/driver
parent1ef3495abfa2a858b3cc7a1844383c8e7dff0b60 (diff)
downloadart-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.h40
-rw-r--r--compiler/driver/compiler_driver.cc12
-rw-r--r--compiler/driver/compiler_driver.h24
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);