Adjust profile version when the boot image profiling is switched on

The current profile version needs to be updated if the boot image
profiling was switched on dynamically. Otherwise we will not be able to
add new data to the file since we will have a version mismatch.

Test: manual & profile_compilation_info_test
Bug: 139884006
Change-Id: I85e9970c5e26d3f2144a644e7052f2b6a433e1db
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 9246c28..81f1406 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -2175,6 +2175,13 @@
   profile_key_map_.clear();
 }
 
+void ProfileCompilationInfo::ClearDataAndAdjustVersion(bool for_boot_image) {
+  ClearData();
+  memcpy(version_,
+         for_boot_image ? kProfileVersionForBootImage : kProfileVersion,
+         kProfileVersionSize);
+}
+
 bool ProfileCompilationInfo::IsForBootImage() const {
   return memcmp(version_, kProfileVersionForBootImage, sizeof(kProfileVersionForBootImage)) == 0;
 }
diff --git a/libprofile/profile/profile_compilation_info.h b/libprofile/profile/profile_compilation_info.h
index 7043584..09aefc7 100644
--- a/libprofile/profile/profile_compilation_info.h
+++ b/libprofile/profile/profile_compilation_info.h
@@ -530,6 +530,9 @@
   // Clears all the data from the profile.
   void ClearData();
 
+  // Clears all the data from the profile and adjust the object version.
+  void ClearDataAndAdjustVersion(bool for_boot_image);
+
   // Prepare the profile to store aggregation counters.
   // This will change the profile version and allocate extra storage for the counters.
   // It allocates 2 bytes for every possible method and class, so do not use in performance
diff --git a/libprofile/profile/profile_compilation_info_test.cc b/libprofile/profile/profile_compilation_info_test.cc
index 6390b39..a6ef146 100644
--- a/libprofile/profile/profile_compilation_info_test.cc
+++ b/libprofile/profile/profile_compilation_info_test.cc
@@ -1669,4 +1669,25 @@
   EXPECT_TRUE(info.GetMethodHotness(ref).IsInProfile());
   EXPECT_FALSE(info.GetMethodHotness(ref_checksum_missmatch).IsInProfile());
 }
+
+TEST_F(ProfileCompilationInfoTest, ClearDataAndAdjustVersionRegularToBoot) {
+  ProfileCompilationInfo info;
+
+  AddMethod(&info, dex1, /* method_idx= */ 0, Hotness::kFlagHot);
+
+  info.ClearDataAndAdjustVersion(/*for_boot_image=*/true);
+  ASSERT_TRUE(info.IsEmpty());
+  ASSERT_TRUE(info.IsForBootImage());
+}
+
+TEST_F(ProfileCompilationInfoTest, ClearDataAndAdjustVersionBootToRegular) {
+  ProfileCompilationInfo info(/*for_boot_image=*/true);
+
+  AddMethod(&info, dex1, /* method_idx= */ 0, Hotness::kFlagHot);
+
+  info.ClearDataAndAdjustVersion(/*for_boot_image=*/false);
+  ASSERT_TRUE(info.IsEmpty());
+  ASSERT_FALSE(info.IsForBootImage());
+}
+
 }  // namespace art
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 7f31f5c..be52051 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -560,12 +560,20 @@
       total_number_of_code_cache_queries_++;
     }
     {
-      ProfileCompilationInfo info(
-          Runtime::Current()->GetArenaPool(), options_.GetProfileBootClassPath());
+      ProfileCompilationInfo info(Runtime::Current()->GetArenaPool());
       if (!info.Load(filename, /*clear_if_invalid=*/ true)) {
         LOG(WARNING) << "Could not forcefully load profile " << filename;
         continue;
       }
+      if (options_.GetProfileBootClassPath() != info.IsForBootImage()) {
+        // If we enabled boot class path profiling but the profile is a regular one,
+        // (or the opposite), clear the profile. We do not support cross-version merges.
+        LOG(WARNING) << "Adjust profile version: for_boot_classpath="
+            << options_.GetProfileBootClassPath();
+        info.ClearDataAndAdjustVersion(options_.GetProfileBootClassPath());
+        // For saving to ensure we persist the new version.
+        force_save = true;
+      }
       uint64_t last_save_number_of_methods = info.GetNumberOfMethods();
       uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses();
       VLOG(profiler) << "last_save_number_of_methods=" << last_save_number_of_methods