Implement first kind of polymorphic inlining.

Add HClassTableGet to fetch an ArtMethod from the vtable or imt,
and compare it to the only method the profiling saw.

Change-Id: I76afd3689178f10e3be048aa3ac9a97c6f63295d
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 8f4d24f..d5d925a 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -167,6 +167,7 @@
   // Don't compile the method if we are supposed to be deoptimized.
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
   if (instrumentation->AreAllMethodsDeoptimized() || instrumentation->IsDeoptimized(method)) {
+    VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to deoptimization";
     return false;
   }
 
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 64b2c89..a6909d8 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -737,8 +737,16 @@
   if (ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
     return false;
   }
-  MutexLock mu(self, lock_);
+
+  // Compiling requires a profiling info object to notify compilation. Create
+  // one if it hasn't been done before.
   ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
+  if (info == nullptr) {
+    ProfilingInfo::Create(self, method, /* retry_allocation */ true);
+  }
+
+  MutexLock mu(self, lock_);
+  info = method->GetProfilingInfo(sizeof(void*));
   if (info == nullptr || info->IsMethodBeingCompiled()) {
     return false;
   }
diff --git a/runtime/jit/profiling_info.h b/runtime/jit/profiling_info.h
index ddaf02f..ab72373 100644
--- a/runtime/jit/profiling_info.h
+++ b/runtime/jit/profiling_info.h
@@ -68,8 +68,13 @@
     return !classes_[1].IsNull() && classes_[kIndividualCacheSize - 1].IsNull();
   }
 
- private:
+  mirror::Class* GetTypeAt(size_t i) const SHARED_REQUIRES(Locks::mutator_lock_) {
+    return classes_[i].Read();
+  }
+
   static constexpr uint16_t kIndividualCacheSize = 5;
+
+ private:
   uint32_t dex_pc_;
   GcRoot<mirror::Class> classes_[kIndividualCacheSize];
 
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index b49fc74..b97d994 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -457,6 +457,16 @@
   return nullptr;
 }
 
+ArtMethod* Class::FindDeclaredDirectMethodByName(const StringPiece& name, size_t pointer_size) {
+  for (auto& method : GetDirectMethods(pointer_size)) {
+    ArtMethod* const np_method = method.GetInterfaceMethodIfProxy(pointer_size);
+    if (name == np_method->GetName()) {
+      return &method;
+    }
+  }
+  return nullptr;
+}
+
 // TODO These should maybe be changed to be named FindOwnedVirtualMethod or something similar
 // because they do not only find 'declared' methods and will return copied methods. This behavior is
 // desired and correct but the naming can lead to confusion because in the java language declared
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 3017820..be5c668 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -922,6 +922,9 @@
   ArtMethod* FindDeclaredVirtualMethodByName(const StringPiece& name, size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
+  ArtMethod* FindDeclaredDirectMethodByName(const StringPiece& name, size_t pointer_size)
+      SHARED_REQUIRES(Locks::mutator_lock_);
+
   ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature,
                                size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_);