Fix profile merges in profman
profman used ProfileCompilationInfo::Load() which was not preserving the
correct order of the dex files (in a multidex profile).
The CL fixes profman to use ProfileCompilationInfo::MergeWith which
guarantees the right dex order and redesigns profile storage to avoid
such mistakes in the future. Instead of keeping data in a map indexed by
the profile key, store it in a vector whose index match profile_index.
This way, any iteration over profile info becomes deterministic with
respect to the profile index of the dex files.
Test: m test-art-host-gtest-profile_assistant_test
m test-art-host-gtest-profile_compilation_info_test
profile YouTube.apk and compile it based on the reference profile
(failing before)
Bug: 36371709
Change-Id: Ideda1336e5aff59a7c5560429da645fe02c804c9
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index c3ac78f..87f7636 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -181,11 +181,16 @@
// Public methods to create, extend or query the profile.
+ ProfileCompilationInfo() {}
+ ProfileCompilationInfo(const ProfileCompilationInfo& pci);
+ ~ProfileCompilationInfo();
+
// Add the given methods and classes to the current profile object.
bool AddMethodsAndClasses(const std::vector<ProfileMethodInfo>& methods,
const std::set<DexCacheResolvedClasses>& resolved_classes);
// Load profile information from the given file descriptor.
+ // If the current profile is non-empty the load will fail.
bool Load(int fd);
// Merge the data from another ProfileCompilationInfo into the current object.
@@ -268,6 +273,7 @@
private:
enum ProfileLoadSatus {
+ kProfileLoadWouldOverwiteData,
kProfileLoadIOError,
kProfileLoadVersionMismatch,
kProfileLoadBadData,
@@ -278,14 +284,21 @@
using MethodMap = SafeMap<uint16_t, InlineCacheMap>;
// Internal representation of the profile information belonging to a dex file.
+ // Note that we could do without profile_key (the key used to encode the dex
+ // file in the profile) and profile_index (the index of the dex file in the
+ // profile) fields in this struct because we can infer them from
+ // profile_key_map_ and info_. However, it makes the profiles logic much
+ // simpler if we have references here as well.
struct DexFileData {
- DexFileData(uint32_t location_checksum, uint16_t index)
- : profile_index(index), checksum(location_checksum) {}
- // The profile index of this dex file (matches ClassReference#dex_profile_index)
+ DexFileData(const std::string& key, uint32_t location_checksum, uint16_t index)
+ : profile_key(key), profile_index(index), checksum(location_checksum) {}
+ // The profile key this data belongs to.
+ std::string profile_key;
+ // The profile index of this dex file (matches ClassReference#dex_profile_index).
uint8_t profile_index;
- // The dex checksum
+ // The dex checksum.
uint32_t checksum;
- // The methonds' profile information
+ // The methonds' profile information.
MethodMap method_map;
// The classes which have been profiled. Note that these don't necessarily include
// all the classes that can be found in the inline caches reference.
@@ -296,12 +309,9 @@
}
};
- // Maps dex file to their profile information.
- using DexFileToProfileInfoMap = SafeMap<const std::string, DexFileData>;
-
- // Return the profile data for the given dex location or null if the dex location
+ // Return the profile data for the given profile key or null if the dex location
// already exists but has a different checksum
- DexFileData* GetOrAddDexFileData(const std::string& dex_location, uint32_t checksum);
+ DexFileData* GetOrAddDexFileData(const std::string& profile_key, uint32_t checksum);
// Add a method index to the profile (without inline caches).
bool AddMethodIndex(const std::string& dex_location, uint32_t checksum, uint16_t method_idx);
@@ -332,6 +342,16 @@
// be the same as the profile index of the dex file (used to encode the ClassReferences).
void DexFileToProfileIndex(/*out*/std::vector<DexReference>* dex_references) const;
+ // Return the dex data associated with the given profile key or null if the profile
+ // doesn't contain the key.
+ const DexFileData* FindDexData(const std::string& profile_key) const;
+
+ // Clear all the profile data.
+ void ClearProfile();
+
+ // Checks if the profile is empty.
+ bool IsEmpty() const;
+
// Parsing functionality.
// The information present in the header of each profile line.
@@ -438,7 +458,15 @@
friend class ProfileAssistantTest;
friend class Dex2oatLayoutTest;
- DexFileToProfileInfoMap info_;
+ // Vector containing the actual profile info.
+ // The vector index is the profile index of the dex data and
+ // matched DexFileData::profile_index.
+ std::vector<DexFileData*> info_;
+
+ // Cache mapping profile keys to profile index.
+ // This is used to speed up searches since it avoids iterating
+ // over the info_ vector when searching by profile key.
+ SafeMap<const std::string, uint8_t> profile_key_map_;
};
} // namespace art