Merge "Use GC critical section for profile saver" am: ff120c2ad8 am: 2d582600da
am: 3ceb2583c6

Change-Id: I55ffc52b317a94b800de0107cd0c6eef118fc328
diff --git a/runtime/gc/collector_type.h b/runtime/gc/collector_type.h
index f0e1029..8979e74 100644
--- a/runtime/gc/collector_type.h
+++ b/runtime/gc/collector_type.h
@@ -61,6 +61,8 @@
   kCollectorTypeAddRemoveSystemWeakHolder,
   // Fake collector type for GetObjectsAllocated
   kCollectorTypeGetObjectsAllocated,
+  // Fake collector type for ScopedGCCriticalSection
+  kCollectorTypeCriticalSection,
 };
 std::ostream& operator<<(std::ostream& os, const CollectorType& collector_type);
 
diff --git a/runtime/gc/gc_cause.cc b/runtime/gc/gc_cause.cc
index 2bbc86e..39b5e39 100644
--- a/runtime/gc/gc_cause.cc
+++ b/runtime/gc/gc_cause.cc
@@ -42,6 +42,7 @@
     case kGcCauseAddRemoveSystemWeakHolder: return "SystemWeakHolder";
     case kGcCauseHprof: return "Hprof";
     case kGcCauseGetObjectsAllocated: return "ObjectsAllocated";
+    case kGcCauseProfileSaver: return "ProfileSaver";
   }
   LOG(FATAL) << "Unreachable";
   UNREACHABLE();
diff --git a/runtime/gc/gc_cause.h b/runtime/gc/gc_cause.h
index b8cf3c4..b2b3a91 100644
--- a/runtime/gc/gc_cause.h
+++ b/runtime/gc/gc_cause.h
@@ -61,6 +61,8 @@
   kGcCauseHprof,
   // Not a real GC cause, used to prevent GetObjectsAllocated running in the middle of GC.
   kGcCauseGetObjectsAllocated,
+  // GC cause for the profile saver.
+  kGcCauseProfileSaver,
 };
 
 const char* PrettyCause(GcCause cause);
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 1e6f7a8..2dba9b7 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -28,10 +28,12 @@
 #include "base/systrace.h"
 #include "base/time_utils.h"
 #include "compiler_filter.h"
+#include "gc/collector_type.h"
+#include "gc/gc_cause.h"
+#include "gc/scoped_gc_critical_section.h"
 #include "oat_file_manager.h"
 #include "scoped_thread_state_change-inl.h"
 
-
 namespace art {
 
 ProfileSaver* ProfileSaver::instance_ = nullptr;
@@ -208,20 +210,27 @@
   // Resolve any new registered locations.
   ResolveTrackedLocations();
 
-  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  std::set<DexCacheResolvedClasses> resolved_classes =
-      class_linker->GetResolvedClasses(/*ignore boot classes*/ true);
-
+  Thread* const self = Thread::Current();
   std::vector<MethodReference> methods;
+  std::set<DexCacheResolvedClasses> resolved_classes;
   {
-    ScopedTrace trace2("Get hot methods");
-    GetMethodsVisitor visitor(&methods, options_.GetStartupMethodSamples());
-    ScopedObjectAccess soa(Thread::Current());
-    class_linker->VisitClasses(&visitor);
-    VLOG(profiler) << "Methods with samples greater than "
-                   << options_.GetStartupMethodSamples() << " = " << methods.size();
+    ScopedObjectAccess soa(self);
+    gc::ScopedGCCriticalSection sgcs(self,
+                                     gc::kGcCauseProfileSaver,
+                                     gc::kCollectorTypeCriticalSection);
+
+    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+    resolved_classes = class_linker->GetResolvedClasses(/*ignore boot classes*/ true);
+
+    {
+      ScopedTrace trace2("Get hot methods");
+      GetMethodsVisitor visitor(&methods, options_.GetStartupMethodSamples());
+      class_linker->VisitClasses(&visitor);
+      VLOG(profiler) << "Methods with samples greater than "
+                     << options_.GetStartupMethodSamples() << " = " << methods.size();
+    }
   }
-  MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
+  MutexLock mu(self, *Locks::profiler_lock_);
   uint64_t total_number_of_profile_entries_cached = 0;
 
   for (const auto& it : tracked_dex_base_locations_) {