Add missing profman arg for compiled_method_threshold

The arg is --boot-image-sampled-method-threshold, this value
specifies how many profiles a non-hot method should be before it gets
marked as hot in the boot profile. This is useful if we want to do
things like compiling all executed methods for the boot image.

Bug: 37966211
Test: test-art-host-gtest-profile_assistant_test

Change-Id: Ib882df1856d555048a4a19343c233232ee848e8a
diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc
index 75f8ec9..c78d34e 100644
--- a/profman/profile_assistant_test.cc
+++ b/profman/profile_assistant_test.cc
@@ -639,10 +639,13 @@
   // Method that doesn't add the class since its only in one profile. Should still show up in the
   // boot profile.
   const std::string kOtherMethod = "Ljava/util/HashMap;-><init>()V";
+  // Method that gets marked as hot since it's in multiple profiles.
+  const std::string kMultiMethod = "Ljava/util/ArrayList;->clear()V";
 
   // Thresholds for this test.
   static const size_t kDirtyThreshold = 3;
   static const size_t kCleanThreshold = 2;
+  static const size_t kMethodThreshold = 2;
 
   // Create a bunch of boot profiles.
   std::string dex1 =
@@ -659,6 +662,7 @@
       kCleanClass + "\n" +
       kDirtyClass + "\n" +
       "P" + kHotMethod + "\n" +
+      "P" + kMultiMethod + "\n" +
       kUncommonDirtyClass;
   profiles.emplace_back(ScratchFile());
   EXPECT_TRUE(CreateProfile(dex2, profiles.back().GetFilename(), core_dex));
@@ -667,6 +671,7 @@
   std::string dex3 =
       "S" + kHotMethod + "\n" +
       "P" + kOtherMethod + "\n" +
+      "P" + kMultiMethod + "\n" +
       kDirtyClass + "\n";
   profiles.emplace_back(ScratchFile());
   EXPECT_TRUE(CreateProfile(dex3, profiles.back().GetFilename(), core_dex));
@@ -678,6 +683,7 @@
   args.push_back("--generate-boot-image-profile");
   args.push_back("--boot-image-class-threshold=" + std::to_string(kDirtyThreshold));
   args.push_back("--boot-image-clean-class-threshold=" + std::to_string(kCleanThreshold));
+  args.push_back("--boot-image-sampled-method-threshold=" + std::to_string(kMethodThreshold));
   args.push_back("--reference-profile-file=" + out_profile.GetFilename());
   args.push_back("--apk=" + core_dex);
   args.push_back("--dex-location=" + core_dex);
@@ -708,11 +714,18 @@
   // Aggregated methods hotness information.
   EXPECT_NE(output_file_contents.find("HSP" + kHotMethod), std::string::npos)
       << output_file_contents;
-  EXPECT_NE(output_file_contents.find(kOtherMethod), std::string::npos)
+  EXPECT_NE(output_file_contents.find("P" + kOtherMethod), std::string::npos)
       << output_file_contents;
   // Not inferred class, method is only in one profile.
   EXPECT_EQ(output_file_contents.find("Ljava/util/HashMap;\n"), std::string::npos)
       << output_file_contents;
+  // Test the sampled methods that became hot.
+  // Other method is in only one profile, it should not become hot.
+  EXPECT_EQ(output_file_contents.find("HP" + kOtherMethod), std::string::npos)
+      << output_file_contents;
+  // Multi method is in at least two profiles, it should become hot.
+  EXPECT_NE(output_file_contents.find("HP" + kMultiMethod), std::string::npos)
+      << output_file_contents;
 }
 
 TEST_F(ProfileAssistantTest, TestProfileCreationOneNotMatched) {
diff --git a/profman/profman.cc b/profman/profman.cc
index 94e81c7..6c8ca56 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -142,6 +142,9 @@
   UsageError("      occurrences to include a class in the boot image profile. A clean class is a");
   UsageError("      class that doesn't have any static fields or native methods and is likely to");
   UsageError("      remain clean in the image. Default is 3.");
+  UsageError("  --boot-image-sampled-method-threshold=<value>: minimum number of profiles a");
+  UsageError("      non-hot method needs to be in order to be hot in the output profile. The");
+  UsageError("      default is max int.");
   UsageError("");
 
   exit(EXIT_FAILURE);
@@ -225,6 +228,11 @@
                         "--boot-image-clean-class-threshold",
                         &boot_image_options_.image_class_clean_theshold,
                         Usage);
+      } else if (option.starts_with("--boot-image-sampled-method-threshold=")) {
+        ParseUintOption(option,
+                        "--boot-image-sampled-method-threshold",
+                        &boot_image_options_.compiled_method_threshold,
+                        Usage);
       } else if (option.starts_with("--profile-file=")) {
         profile_files_.push_back(option.substr(strlen("--profile-file=")).ToString());
       } else if (option.starts_with("--profile-file-fd=")) {