diff options
| author | 2015-04-24 16:43:49 +0100 | |
|---|---|---|
| committer | 2015-04-24 16:43:49 +0100 | |
| commit | 4c0eb42259d790fddcd9978b66328dbb3ab65615 (patch) | |
| tree | 9d1ac505dfd4d0225f479d860b72a58747c8f6ce /compiler/driver/compiler_driver.h | |
| parent | 223f2f5b2a20ca8246da1523494900a2424d5956 (diff) | |
Ensure inlined static calls perform clinit checks in Optimizing.
Calls to static methods have implicit class initialization
(clinit) checks of the method's declaring class in
Optimizing. However, when such a static call is inlined,
the implicit clinit check vanishes, possibly leading to an
incorrect behavior.
To ensure that inlining static methods does not change the
behavior of a program, add explicit class initialization
checks (art::HClinitCheck) as well as load class
instructions (art::HLoadClass) as last input of static
calls (art::HInvokeStaticOrDirect) in Optimizing' control
flow graphs, when the declaring class is reachable and not
known to be already initialized. Then when considering the
inlining of a static method call, proceed only if the method
has no implicit clinit check requirement.
The added explicit clinit checks are already removed by the
art::PrepareForRegisterAllocation visitor. This CL also
extends this visitor to turn explicit clinit checks from
static invokes into implicit ones after the inlining step,
by removing the added art::HLoadClass nodes mentioned
hereinbefore.
Change-Id: I9ba452b8bd09ae1fdd9a3797ef556e3e7e19c651
Diffstat (limited to 'compiler/driver/compiler_driver.h')
| -rw-r--r-- | compiler/driver/compiler_driver.h | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index ce13a17792..742e2e5857 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -280,6 +280,18 @@ class CompilerDriver { ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Return whether the declaring class of `resolved_method` is + // available to `referrer_class`. If this is true, compute the type + // index of the declaring class in the referrer's dex file and + // return it through the out argument `storage_index`; otherwise + // return DexFile::kDexNoIndex through `storage_index`. + bool IsClassOfStaticMethodAvailableToReferrer(mirror::DexCache* dex_cache, + mirror::Class* referrer_class, + mirror::ArtMethod* resolved_method, + uint16_t method_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, ArtField* resolved_field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -455,6 +467,33 @@ class CompilerDriver { } private: + // Return whether the declaring class of `resolved_member` is + // available to `referrer_class` for read or write access using two + // Boolean values returned as a pair. If is true at least for read + // access, compute the type index of the declaring class in the + // referrer's dex file and return it through the out argument + // `storage_index`; otherwise return DexFile::kDexNoIndex through + // `storage_index`. + template <typename ArtMember> + std::pair<bool, bool> IsClassOfStaticMemberAvailableToReferrer(mirror::DexCache* dex_cache, + mirror::Class* referrer_class, + ArtMember* resolved_member, + uint16_t member_idx, + uint32_t* storage_index) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Can `referrer_class` access the resolved `member`? + // Dispatch call to mirror::Class::CanAccessResolvedField or + // mirror::Class::CanAccessResolvedMember depending on the value of + // ArtMember. + template <typename ArtMember> + static bool CanAccessResolvedMember(mirror::Class* referrer_class, + mirror::Class* access_to, + ArtMember* member, + mirror::DexCache* dex_cache, + uint32_t field_idx) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // These flags are internal to CompilerDriver for collecting INVOKE resolution statistics. // The only external contract is that unresolved method has flags 0 and resolved non-0. enum { |