Add new profile saver options: save without jit & profile AOT code

--Xps-save-without-jit-notifications
The hotness for system server code is increased in AOT-ed code. The flow
does not call into JIT and as such notifications are not triggered.
Instead of relying on the JIT system, make use of a simple back off
strategy to save the profile.

--Xps-profile-aot-code
Starts the profile saver even if the oat file is speed compiled.

Test: m test-art-host
      boot a device with system server profiling enabled.
Bug: 73313191

Change-Id: I66ec422a76bc9244349da7a5d18a3df5bcc9ccb7
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index 5a25a6c..48da755 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -643,6 +643,16 @@
       return Result::SuccessNoValue();
     }
 
+    if (option == "profile-aot-code") {
+      existing.profile_aot_code_ = true;
+      return Result::SuccessNoValue();
+    }
+
+    if (option == "save-without-jit-notifications") {
+      existing.wait_for_jit_notifications_to_save_ = false;
+      return Result::SuccessNoValue();
+    }
+
     // The rest of these options are always the wildcard from '-Xps-*'
     std::string suffix = RemovePrefix(option);
 
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 6d27cfe..4b8b891 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -252,6 +252,13 @@
   void SetSaveProfilingInfo(bool save_profiling_info) {
     profile_saver_options_.SetEnabled(save_profiling_info);
   }
+  void SetWaitForJitNotificationsToSaveProfile(bool value) {
+    profile_saver_options_.SetWaitForJitNotificationsToSave(value);
+  }
+  void SetProfileAOTCode(bool value) {
+    profile_saver_options_.SetProfileAOTCode(value);
+  }
+
   void SetJitAtFirstUse() {
     use_jit_compilation_ = true;
     compile_threshold_ = 0;
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 618fde8..efa8a4d 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -131,6 +131,11 @@
   }
   FetchAndCacheResolvedClassesAndMethods(/*startup*/ true);
 
+
+  // When we save without waiting for JIT notifications we use a simple
+  // exponential back off policy bounded by max_wait_without_jit.
+  uint32_t max_wait_without_jit = options_.GetMinSavePeriodMs() * 16;
+  uint64_t cur_wait_without_jit = options_.GetMinSavePeriodMs();
   // Loop for the profiled methods.
   while (!ShuttingDown(self)) {
     uint64_t sleep_start = NanoTime();
@@ -138,7 +143,14 @@
       uint64_t sleep_time = 0;
       {
         MutexLock mu(self, wait_lock_);
-        period_condition_.Wait(self);
+        if (options_.GetWaitForJitNotificationsToSave()) {
+          period_condition_.Wait(self);
+        } else {
+          period_condition_.TimedWait(self, cur_wait_without_jit, 0);
+          if (cur_wait_without_jit < max_wait_without_jit) {
+            cur_wait_without_jit *= 2;
+          }
+        }
         sleep_time = NanoTime() - sleep_start;
       }
       // Check if the thread was woken up for shutdown.
@@ -597,7 +609,13 @@
   return nullptr;
 }
 
-static bool ShouldProfileLocation(const std::string& location) {
+static bool ShouldProfileLocation(const std::string& location, bool profile_aot_code) {
+  if (profile_aot_code) {
+    // If we have to profile all the code, irrespective of its compilation state, return true
+    // right away.
+    return true;
+  }
+
   OatFileManager& oat_manager = Runtime::Current()->GetOatFileManager();
   const OatFile* oat_file = oat_manager.FindOpenedOatFileFromDexLocation(location);
   if (oat_file == nullptr) {
@@ -629,7 +647,7 @@
 
   std::vector<std::string> code_paths_to_profile;
   for (const std::string& location : code_paths) {
-    if (ShouldProfileLocation(location))  {
+    if (ShouldProfileLocation(location, options.GetProfileAOTCode()))  {
       code_paths_to_profile.push_back(location);
     }
   }
diff --git a/runtime/jit/profile_saver_options.h b/runtime/jit/profile_saver_options.h
index d1e14e2..18f7899 100644
--- a/runtime/jit/profile_saver_options.h
+++ b/runtime/jit/profile_saver_options.h
@@ -41,7 +41,9 @@
     min_notification_before_wake_(kMinNotificationBeforeWake),
     max_notification_before_wake_(kMaxNotificationBeforeWake),
     profile_path_(""),
-    profile_boot_class_path_(false) {}
+    profile_boot_class_path_(false),
+    profile_aot_code_(false),
+    wait_for_jit_notifications_to_save_(true) {}
 
   ProfileSaverOptions(
       bool enabled,
@@ -53,7 +55,9 @@
       uint32_t min_notification_before_wake,
       uint32_t max_notification_before_wake,
       const std::string& profile_path,
-      bool profile_boot_class_path)
+      bool profile_boot_class_path,
+      bool profile_aot_code = false,
+      bool wait_for_jit_notifications_to_save = true)
   : enabled_(enabled),
     min_save_period_ms_(min_save_period_ms),
     save_resolved_classes_delay_ms_(save_resolved_classes_delay_ms),
@@ -63,7 +67,9 @@
     min_notification_before_wake_(min_notification_before_wake),
     max_notification_before_wake_(max_notification_before_wake),
     profile_path_(profile_path),
-    profile_boot_class_path_(profile_boot_class_path) {}
+    profile_boot_class_path_(profile_boot_class_path),
+    profile_aot_code_(profile_aot_code),
+    wait_for_jit_notifications_to_save_(wait_for_jit_notifications_to_save) {}
 
   bool IsEnabled() const {
     return enabled_;
@@ -103,6 +109,18 @@
   bool GetProfileBootClassPath() const {
     return profile_boot_class_path_;
   }
+  bool GetProfileAOTCode() const {
+    return profile_aot_code_;
+  }
+  void SetProfileAOTCode(bool value) {
+    profile_aot_code_ = value;
+  }
+  bool GetWaitForJitNotificationsToSave() const {
+    return wait_for_jit_notifications_to_save_;
+  }
+  void SetWaitForJitNotificationsToSave(bool value) {
+    wait_for_jit_notifications_to_save_ = value;
+  }
 
   friend std::ostream & operator<<(std::ostream &os, const ProfileSaverOptions& pso) {
     os << "enabled_" << pso.enabled_
@@ -113,7 +131,9 @@
         << ", min_classes_to_save_" << pso.min_classes_to_save_
         << ", min_notification_before_wake_" << pso.min_notification_before_wake_
         << ", max_notification_before_wake_" << pso.max_notification_before_wake_
-        << ", profile_boot_class_path_" << pso.profile_boot_class_path_;
+        << ", profile_boot_class_path_" << pso.profile_boot_class_path_
+        << ", profile_aot_code_" << pso.profile_aot_code_
+        << ", wait_for_jit_notifications_to_save_" << pso.wait_for_jit_notifications_to_save_;
     return os;
   }
 
@@ -129,6 +149,8 @@
   uint32_t max_notification_before_wake_;
   std::string profile_path_;
   bool profile_boot_class_path_;
+  bool profile_aot_code_;
+  bool wait_for_jit_notifications_to_save_;
 };
 
 }  // namespace art