Cache method lowering info in mir graph.

This should enable easy inlining checks. It should also
improve compilation time of methods that call the same
methods over and over - it is exactly such methods that
tend to exceed our 100ms time limit.

Change-Id: If01cd18e039071a74a1444570283c153429c9cd4
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 817da17..26210c9 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -44,7 +44,6 @@
 class MethodVerifier;
 }  // namespace verifier
 
-class AOTCompilationStats;
 class CompilerOptions;
 class DexCompilationUnit;
 class DexFileToMethodInlinerMap;
@@ -256,8 +255,37 @@
       uint32_t* storage_index, bool* is_referrers_class, bool* is_initialized)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Resolve a method. Returns nullptr on failure, including incompatible class change.
+  mirror::ArtMethod* ResolveMethod(
+      ScopedObjectAccess& soa, const SirtRef<mirror::DexCache>& dex_cache,
+      const SirtRef<mirror::ClassLoader>& class_loader, const DexCompilationUnit* mUnit,
+      uint32_t method_idx, InvokeType invoke_type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Get declaration location of a resolved field.
+  void GetResolvedMethodDexFileLocation(
+      mirror::ArtMethod* resolved_method, const DexFile** declaring_dex_file,
+      uint16_t* declaring_class_idx, uint16_t* declaring_method_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Get declaration location of a resolved field.
+  uint16_t GetResolvedMethodVTableIndex(
+      mirror::ArtMethod* resolved_method, InvokeType type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Can we fast-path an INVOKE? If no, returns 0. If yes, returns a non-zero opaque flags value
+  // for ProcessedInvoke() and computes the necessary lowering info.
+  int IsFastInvoke(
+      ScopedObjectAccess& soa, const SirtRef<mirror::DexCache>& dex_cache,
+      const SirtRef<mirror::ClassLoader>& class_loader, const DexCompilationUnit* mUnit,
+      mirror::Class* referrer_class, mirror::ArtMethod* resolved_method, InvokeType* invoke_type,
+      MethodReference* target_method, const MethodReference* devirt_target,
+      uintptr_t* direct_code, uintptr_t* direct_method)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   void ProcessedInstanceField(bool resolved);
   void ProcessedStaticField(bool resolved, bool local);
+  void ProcessedInvoke(InvokeType invoke_type, int flags);
 
   // Can we fast path instance field access in a verified accessor?
   // If yes, computes field's offset and volatility and whether the method is static or not.
@@ -594,16 +622,37 @@
   bool SkipCompilation(const std::string& method_name);
 
  private:
-  // Compute constant code and method pointers when possible
+  // 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 {
+    kBitMethodResolved = 0,
+    kBitVirtualMadeDirect,
+    kBitPreciseTypeDevirtualization,
+    kBitDirectCallToBoot,
+    kBitDirectMethodToBoot
+  };
+  static constexpr int kFlagMethodResolved              = 1 << kBitMethodResolved;
+  static constexpr int kFlagVirtualMadeDirect           = 1 << kBitVirtualMadeDirect;
+  static constexpr int kFlagPreciseTypeDevirtualization = 1 << kBitPreciseTypeDevirtualization;
+  static constexpr int kFlagDirectCallToBoot            = 1 << kBitDirectCallToBoot;
+  static constexpr int kFlagDirectMethodToBoot          = 1 << kBitDirectMethodToBoot;
+  static constexpr int kFlagsMethodResolvedVirtualMadeDirect =
+      kFlagMethodResolved | kFlagVirtualMadeDirect;
+  static constexpr int kFlagsMethodResolvedPreciseTypeDevirtualization =
+      kFlagsMethodResolvedVirtualMadeDirect | kFlagPreciseTypeDevirtualization;
+
+ public:  // TODO make private or eliminate.
+  // Compute constant code and method pointers when possible.
   void GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType sharp_type,
                                      bool no_guarantee_of_dex_cache_entry,
                                      mirror::Class* referrer_class,
                                      mirror::ArtMethod* method,
-                                     bool update_stats,
+                                     int* stats_flags,
                                      MethodReference* target_method,
                                      uintptr_t* direct_code, uintptr_t* direct_method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+ private:
   void PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files,
                   ThreadPool* thread_pool, TimingLogger* timings)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
@@ -688,6 +737,7 @@
   size_t thread_count_;
   uint64_t start_ns_;
 
+  class AOTCompilationStats;
   UniquePtr<AOTCompilationStats> stats_;
 
   bool dump_stats_;