Clear the profile if we fail to add new methods or classes

We may fail to add new data in the profile if it contains outdated data
(e.g. if the dex files we profiled were updated in the meantime). If this
happens, clear the profile to ensure we don't keep around useless data.

Test: m test-art-host, 595-profiling-saving
Bug: 77839992
Bug: 79200824

Change-Id: I238d56ba4eeec96a3464e42f164d0e798f555ec4
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 0e0c3c5..748e24e 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -96,9 +96,7 @@
 
 ProfileCompilationInfo::~ProfileCompilationInfo() {
   VLOG(profiler) << Dumpable<MemStats>(allocator_.GetMemStats());
-  for (DexFileData* data : info_) {
-    delete data;
-  }
+  ClearData();
 }
 
 void ProfileCompilationInfo::DexPcData::AddClass(uint16_t dex_profile_idx,
@@ -2106,4 +2104,12 @@
   return true;
 }
 
+void ProfileCompilationInfo::ClearData() {
+  for (DexFileData* data : info_) {
+    delete data;
+  }
+  info_.clear();
+  profile_key_map_.clear();
+}
+
 }  // namespace art
diff --git a/libprofile/profile/profile_compilation_info.h b/libprofile/profile/profile_compilation_info.h
index 32c796c..e28c5f1 100644
--- a/libprofile/profile/profile_compilation_info.h
+++ b/libprofile/profile/profile_compilation_info.h
@@ -445,6 +445,9 @@
   // Checks if the profile is empty.
   bool IsEmpty() const;
 
+  // Clears all the data from the profile.
+  void ClearData();
+
  private:
   enum ProfileLoadStatus {
     kProfileLoadWouldOverwiteData,
diff --git a/libprofile/profile/profile_compilation_info_test.cc b/libprofile/profile/profile_compilation_info_test.cc
index b0f9649..b3262a7 100644
--- a/libprofile/profile/profile_compilation_info_test.cc
+++ b/libprofile/profile/profile_compilation_info_test.cc
@@ -1339,4 +1339,33 @@
   ASSERT_TRUE(loaded_info.Equals(expected_info));
 }
 
+
+TEST_F(ProfileCompilationInfoTest, ClearData) {
+  ProfileCompilationInfo info;
+  for (uint16_t i = 0; i < 10; i++) {
+    ASSERT_TRUE(AddMethod("dex_location1", /* checksum */ 1, /* method_idx */ i, &info));
+  }
+  ASSERT_FALSE(IsEmpty(info));
+  info.ClearData();
+  ASSERT_TRUE(IsEmpty(info));
+}
+
+TEST_F(ProfileCompilationInfoTest, ClearDataAndSave) {
+  ProfileCompilationInfo info;
+  for (uint16_t i = 0; i < 10; i++) {
+    ASSERT_TRUE(AddMethod("dex_location1", /* checksum */ 1, /* method_idx */ i, &info));
+  }
+  info.ClearData();
+
+  ScratchFile profile;
+  ASSERT_TRUE(info.Save(GetFd(profile)));
+  ASSERT_EQ(0, profile.GetFile()->Flush());
+
+  // Check that we get back what we saved.
+  ProfileCompilationInfo loaded_info;
+  ASSERT_TRUE(profile.GetFile()->ResetOffset());
+  ASSERT_TRUE(loaded_info.Load(GetFd(profile)));
+  ASSERT_TRUE(loaded_info.Equals(info));
+}
+
 }  // namespace art
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index 618fde8..d6230f8 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -516,10 +516,24 @@
       uint64_t last_save_number_of_methods = info.GetNumberOfMethods();
       uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses();
 
-      info.AddMethods(profile_methods, ProfileCompilationInfo::MethodHotness::kFlagPostStartup);
+      // Try to add the method data. Note this may fail is the profile loaded from disk contains
+      // outdated data (e.g. the previous profiled dex files might have been updated).
+      // If this happens we clear the profile data and for the save to ensure the file is cleared.
+      if (!info.AddMethods(profile_methods,
+              ProfileCompilationInfo::MethodHotness::kFlagPostStartup)) {
+        LOG(WARNING) << "Could not add methods to the existing profiler. "
+            << "Clearing the profile data.";
+        info.ClearData();
+        force_save = true;
+      }
+
       auto profile_cache_it = profile_cache_.find(filename);
       if (profile_cache_it != profile_cache_.end()) {
-        info.MergeWith(*(profile_cache_it->second));
+        if (!info.MergeWith(*(profile_cache_it->second))) {
+          LOG(WARNING) << "Could not merge the profile. Clearing the profile data.";
+          info.ClearData();
+          force_save = true;
+        }
       }
 
       int64_t delta_number_of_methods =