Clear inline caches if a ProfilingInfo gets revived.

This avoids stalled class references.

Bug: 27398183
Bug: 23128949
Bug: 26846185
Change-Id: I9539215241708e26fef887e02201ce1feabc2d1a
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index e8a7189..e041a42 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -705,9 +705,17 @@
     auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(),
       [this] (ProfilingInfo* info) NO_THREAD_SAFETY_ANALYSIS {
         const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
+        // We have previously cleared the ProfilingInfo pointer in the ArtMethod in the hope
+        // that the compiled code would not get revived. As mutator threads run concurrently,
+        // they may have revived the compiled code, and now we are in the situation where
+        // a method has compiled code but no ProfilingInfo.
+        // We make sure compiled methods have a ProfilingInfo object. It is needed for
+        // code cache collection.
         if (ContainsPc(ptr) && info->GetMethod()->GetProfilingInfo(sizeof(void*)) == nullptr) {
-          // Make sure compiled methods have a ProfilingInfo object. It is needed for
-          // code cache collection.
+          // We clear the inline caches as classes in it might be stalled.
+          info->ClearInlineCaches();
+          // Do a fence to make sure the clearing is seen before attaching to the method.
+          QuasiAtomic::ThreadFenceRelease();
           info->GetMethod()->SetProfilingInfo(info);
         } else if (info->GetMethod()->GetProfilingInfo(sizeof(void*)) != info) {
           // No need for this ProfilingInfo object anymore.
diff --git a/runtime/jit/profiling_info.h b/runtime/jit/profiling_info.h
index d54f3df..a8c056c 100644
--- a/runtime/jit/profiling_info.h
+++ b/runtime/jit/profiling_info.h
@@ -134,13 +134,17 @@
     return saved_entry_point_;
   }
 
+  void ClearInlineCaches() {
+    memset(&cache_, 0, number_of_inline_caches_ * sizeof(InlineCache));
+  }
+
  private:
   ProfilingInfo(ArtMethod* method, const std::vector<uint32_t>& entries)
       : number_of_inline_caches_(entries.size()),
         method_(method),
         is_method_being_compiled_(false),
         saved_entry_point_(nullptr) {
-    memset(&cache_, 0, number_of_inline_caches_ * sizeof(InlineCache));
+    ClearInlineCaches();
     for (size_t i = 0; i < number_of_inline_caches_; ++i) {
       cache_[i].dex_pc_ = entries[i];
     }