Enable devirtualization for abstract and sub-class methods.
If we know the type of a receiver in the verifier we record devirtualization
data. Currently we only use this data to avoid virtual method dispatch when
we know the receiver of a method isn't a sub-class. This change allows
devirtualization of virtual and interface methods when we know the receiver's
type and the method the we'd find via dispatch is either known within boot or
has a reference from the current dex file.
Pass the receiver through to the method resolution trampoline as
devirtualization may mean the dex method index needs to be made more accurate
for the receiver.
Tidy up method devirtualization and related statistics.
Push the devirtualization map lookup into a less common case to avoid
taking its lock.
Make MethodReference a struct rather than a typedef of a pair, so the members
can have more meaningful names than first and second.
Rough statistics show that we devirtualize using this change around 2.5% of
the time, whilst some apps like GMS core devirtualize over 3.4% of the time.
Change-Id: Ieed3471dbedfc4cc881d652631b67176bb37d394
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index ab7e3cc..755d089 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -187,7 +187,8 @@
static const std::vector<uint8_t>* GetDexGcMap(CompilerDriver::MethodReference ref)
LOCKS_EXCLUDED(dex_gc_maps_lock_);
- static const CompilerDriver::MethodReference* GetDevirtMap(CompilerDriver::MethodReference ref, uint32_t pc)
+ static const CompilerDriver::MethodReference* GetDevirtMap(const CompilerDriver::MethodReference& ref,
+ uint32_t dex_pc)
LOCKS_EXCLUDED(devirt_maps_lock_);
// Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
@@ -574,7 +575,8 @@
InstructionFlags* CurrentInsnFlags();
// All the GC maps that the verifier has created
- typedef SafeMap<const CompilerDriver::MethodReference, const std::vector<uint8_t>*> DexGcMapTable;
+ typedef SafeMap<const CompilerDriver::MethodReference, const std::vector<uint8_t>*,
+ CompilerDriver::MethodReferenceComparator> DexGcMapTable;
static Mutex* dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
static DexGcMapTable* dex_gc_maps_ GUARDED_BY(dex_gc_maps_lock_);
static void SetDexGcMap(CompilerDriver::MethodReference ref, const std::vector<uint8_t>& dex_gc_map)
@@ -583,8 +585,8 @@
// Devirtualization map.
typedef SafeMap<const uint32_t, CompilerDriver::MethodReference> PcToConreteMethod;
- typedef SafeMap<const CompilerDriver::MethodReference, const PcToConreteMethod*>
- DevirtualizationMapTable;
+ typedef SafeMap<const CompilerDriver::MethodReference, const PcToConreteMethod*,
+ CompilerDriver::MethodReferenceComparator> DevirtualizationMapTable;
MethodVerifier::PcToConreteMethod* GenerateDevirtMap()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);