blob: ca204d8140c0c127e2b9b25f56e3df574b1e649e [file] [log] [blame]
Calin Juravle31f2c152015-10-23 17:56:15 +01001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Calin Juravle33083d62017-01-18 15:29:12 -080017#ifndef ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_
18#define ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_
Calin Juravle31f2c152015-10-23 17:56:15 +010019
20#include <set>
Calin Juravle4d77b6a2015-12-01 18:38:09 +000021#include <vector>
Calin Juravle31f2c152015-10-23 17:56:15 +010022
23#include "atomic.h"
Calin Juravlecc3171a2017-05-19 16:47:53 -070024#include "base/arena_object.h"
25#include "base/arena_containers.h"
Mathieu Chartierea650f32017-05-24 12:04:13 -070026#include "bit_memory_region.h"
Mathieu Chartierc5dd3192015-12-09 16:38:30 -080027#include "dex_cache_resolved_classes.h"
Calin Juravle31f2c152015-10-23 17:56:15 +010028#include "dex_file.h"
Andreas Gampea5b09a62016-11-17 15:21:22 -080029#include "dex_file_types.h"
Calin Juravle226501b2015-12-11 14:41:31 +000030#include "method_reference.h"
Calin Juravle31f2c152015-10-23 17:56:15 +010031#include "safe_map.h"
Mathieu Chartierdbddc222017-05-24 12:04:13 -070032#include "type_reference.h"
Calin Juravle31f2c152015-10-23 17:56:15 +010033
34namespace art {
35
Calin Juravle31f2c152015-10-23 17:56:15 +010036/**
Calin Juravle940eb0c2017-01-30 19:30:44 -080037 * Convenient class to pass around profile information (including inline caches)
38 * without the need to hold GC-able objects.
39 */
40struct ProfileMethodInfo {
Calin Juravle940eb0c2017-01-30 19:30:44 -080041 struct ProfileInlineCache {
Calin Juravle589e71e2017-03-03 16:05:05 -080042 ProfileInlineCache(uint32_t pc,
43 bool missing_types,
Mathieu Chartierdbddc222017-05-24 12:04:13 -070044 const std::vector<TypeReference>& profile_classes)
Calin Juravle589e71e2017-03-03 16:05:05 -080045 : dex_pc(pc), is_missing_types(missing_types), classes(profile_classes) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080046
47 const uint32_t dex_pc;
Calin Juravle589e71e2017-03-03 16:05:05 -080048 const bool is_missing_types;
Mathieu Chartierdbddc222017-05-24 12:04:13 -070049 const std::vector<TypeReference> classes;
Calin Juravle940eb0c2017-01-30 19:30:44 -080050 };
51
52 ProfileMethodInfo(const DexFile* dex, uint32_t method_index)
53 : dex_file(dex), dex_method_index(method_index) {}
54
55 ProfileMethodInfo(const DexFile* dex,
56 uint32_t method_index,
57 const std::vector<ProfileInlineCache>& caches)
Mathieu Chartierea650f32017-05-24 12:04:13 -070058 : dex_file(dex),
59 dex_method_index(method_index),
60 inline_caches(caches) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080061
62 const DexFile* dex_file;
63 const uint32_t dex_method_index;
64 const std::vector<ProfileInlineCache> inline_caches;
65};
66
67/**
Calin Juravle998c2162015-12-21 15:39:33 +020068 * Profile information in a format suitable to be queried by the compiler and
69 * performing profile guided compilation.
70 * It is a serialize-friendly format based on information collected by the
71 * interpreter (ProfileInfo).
Calin Juravle31f2c152015-10-23 17:56:15 +010072 * Currently it stores only the hot compiled methods.
73 */
Calin Juravle226501b2015-12-11 14:41:31 +000074class ProfileCompilationInfo {
75 public:
Calin Juravle64142952016-03-21 14:37:55 +000076 static const uint8_t kProfileMagic[];
77 static const uint8_t kProfileVersion[];
78
Calin Juravle940eb0c2017-01-30 19:30:44 -080079 // Data structures for encoding the offline representation of inline caches.
80 // This is exposed as public in order to make it available to dex2oat compilations
81 // (see compiler/optimizing/inliner.cc).
82
83 // A dex location together with its checksum.
84 struct DexReference {
Mathieu Chartierea650f32017-05-24 12:04:13 -070085 DexReference() : dex_checksum(0), num_method_ids(0) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080086
Mathieu Chartierea650f32017-05-24 12:04:13 -070087 DexReference(const std::string& location, uint32_t checksum, uint32_t num_methods)
88 : dex_location(location), dex_checksum(checksum), num_method_ids(num_methods) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080089
90 bool operator==(const DexReference& other) const {
Mathieu Chartierea650f32017-05-24 12:04:13 -070091 return dex_checksum == other.dex_checksum &&
92 dex_location == other.dex_location &&
93 num_method_ids == other.num_method_ids;
Calin Juravle940eb0c2017-01-30 19:30:44 -080094 }
95
Calin Juravlee0ac1152017-02-13 19:03:47 -080096 bool MatchesDex(const DexFile* dex_file) const {
97 return dex_checksum == dex_file->GetLocationChecksum() &&
98 dex_location == GetProfileDexFileKey(dex_file->GetLocation());
99 }
100
Calin Juravle940eb0c2017-01-30 19:30:44 -0800101 std::string dex_location;
102 uint32_t dex_checksum;
Mathieu Chartierea650f32017-05-24 12:04:13 -0700103 uint32_t num_method_ids;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800104 };
105
106 // Encodes a class reference in the profile.
107 // The owning dex file is encoded as the index (dex_profile_index) it has in the
108 // profile rather than as a full DexRefence(location,checksum).
109 // This avoids excessive string copying when managing the profile data.
110 // The dex_profile_index is an index in either of:
111 // - OfflineProfileMethodInfo#dex_references vector (public use)
112 // - DexFileData#profile_index (internal use).
113 // Note that the dex_profile_index is not necessary the multidex index.
114 // We cannot rely on the actual multidex index because a single profile may store
115 // data from multiple splits. This means that a profile may contain a classes2.dex from split-A
116 // and one from split-B.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700117 struct ClassReference : public ValueObject {
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700118 ClassReference(uint8_t dex_profile_idx, const dex::TypeIndex type_idx) :
Calin Juravle940eb0c2017-01-30 19:30:44 -0800119 dex_profile_index(dex_profile_idx), type_index(type_idx) {}
120
121 bool operator==(const ClassReference& other) const {
122 return dex_profile_index == other.dex_profile_index && type_index == other.type_index;
123 }
124 bool operator<(const ClassReference& other) const {
125 return dex_profile_index == other.dex_profile_index
126 ? type_index < other.type_index
127 : dex_profile_index < other.dex_profile_index;
128 }
129
130 uint8_t dex_profile_index; // the index of the owning dex in the profile info
131 dex::TypeIndex type_index; // the type index of the class
132 };
133
134 // The set of classes that can be found at a given dex pc.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700135 using ClassSet = ArenaSet<ClassReference>;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800136
137 // Encodes the actual inline cache for a given dex pc (whether or not the receiver is
138 // megamorphic and its possible types).
Calin Juravle589e71e2017-03-03 16:05:05 -0800139 // If the receiver is megamorphic or is missing types the set of classes will be empty.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700140 struct DexPcData : public ArenaObject<kArenaAllocProfile> {
141 explicit DexPcData(ArenaAllocator* arena)
142 : is_missing_types(false),
143 is_megamorphic(false),
144 classes(std::less<ClassReference>(), arena->Adapter(kArenaAllocProfile)) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -0800145 void AddClass(uint16_t dex_profile_idx, const dex::TypeIndex& type_idx);
Calin Juravle589e71e2017-03-03 16:05:05 -0800146 void SetIsMegamorphic() {
147 if (is_missing_types) return;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800148 is_megamorphic = true;
149 classes.clear();
150 }
Calin Juravle589e71e2017-03-03 16:05:05 -0800151 void SetIsMissingTypes() {
152 is_megamorphic = false;
153 is_missing_types = true;
154 classes.clear();
155 }
Calin Juravle940eb0c2017-01-30 19:30:44 -0800156 bool operator==(const DexPcData& other) const {
Calin Juravle589e71e2017-03-03 16:05:05 -0800157 return is_megamorphic == other.is_megamorphic &&
158 is_missing_types == other.is_missing_types &&
159 classes == other.classes;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800160 }
161
Calin Juravle589e71e2017-03-03 16:05:05 -0800162 // Not all runtime types can be encoded in the profile. For example if the receiver
163 // type is in a dex file which is not tracked for profiling its type cannot be
164 // encoded. When types are missing this field will be set to true.
165 bool is_missing_types;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800166 bool is_megamorphic;
167 ClassSet classes;
168 };
169
170 // The inline cache map: DexPc -> DexPcData.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700171 using InlineCacheMap = ArenaSafeMap<uint16_t, DexPcData>;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800172
Mathieu Chartier34067262017-04-06 13:55:46 -0700173 // Maps a method dex index to its inline cache.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700174 using MethodMap = ArenaSafeMap<uint16_t, InlineCacheMap>;
Mathieu Chartier34067262017-04-06 13:55:46 -0700175
Calin Juravle940eb0c2017-01-30 19:30:44 -0800176 // Encodes the full set of inline caches for a given method.
177 // The dex_references vector is indexed according to the ClassReference::dex_profile_index.
178 // i.e. the dex file of any ClassReference present in the inline caches can be found at
179 // dex_references[ClassReference::dex_profile_index].
180 struct OfflineProfileMethodInfo {
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700181 explicit OfflineProfileMethodInfo(const InlineCacheMap* inline_cache_map)
182 : inline_caches(inline_cache_map) {}
Calin Juravlecc3171a2017-05-19 16:47:53 -0700183
Calin Juravle940eb0c2017-01-30 19:30:44 -0800184 bool operator==(const OfflineProfileMethodInfo& other) const;
185
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700186 const InlineCacheMap* const inline_caches;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800187 std::vector<DexReference> dex_references;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800188 };
189
190 // Public methods to create, extend or query the profile.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700191 ProfileCompilationInfo();
192 explicit ProfileCompilationInfo(ArenaPool* arena_pool);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800193
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700194 ~ProfileCompilationInfo();
195
Calin Juravle67265462016-03-18 16:23:40 +0000196 // Add the given methods and classes to the current profile object.
Calin Juravle940eb0c2017-01-30 19:30:44 -0800197 bool AddMethodsAndClasses(const std::vector<ProfileMethodInfo>& methods,
Calin Juravle67265462016-03-18 16:23:40 +0000198 const std::set<DexCacheResolvedClasses>& resolved_classes);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800199
Mathieu Chartierea650f32017-05-24 12:04:13 -0700200 // Add a method index to the profile (without inline caches).
201 bool AddMethodIndex(const std::string& dex_location,
202 uint32_t checksum,
203 uint16_t method_idx,
204 uint32_t num_method_ids);
205
206 // Add a method to the profile using its online representation (containing runtime structures).
207 bool AddMethod(const ProfileMethodInfo& pmi);
208
209 // Add methods that have samples but are are not necessarily hot. These are partitioned into two
210 // possibly interesecting sets startup and post startup.
211 bool AddSampledMethods(bool startup, std::vector<MethodReference>& methods);
212 bool AddSampledMethod(bool startup,
213 const std::string& dex_location,
214 uint32_t checksum,
215 uint16_t method_idx,
216 uint32_t num_method_ids);
217
Calin Juravle940eb0c2017-01-30 19:30:44 -0800218 // Load profile information from the given file descriptor.
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700219 // If the current profile is non-empty the load will fail.
Calin Juravle2e2db782016-02-23 12:00:03 +0000220 bool Load(int fd);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800221
Calin Juravledcab1902017-05-12 19:18:47 -0700222 // Load profile information from the given file
223 // If the current profile is non-empty the load will fail.
224 // If clear_if_invalid is true and the file is invalid the method clears the
225 // the file and returns true.
226 bool Load(const std::string& filename, bool clear_if_invalid);
227
Calin Juravle67265462016-03-18 16:23:40 +0000228 // Merge the data from another ProfileCompilationInfo into the current object.
229 bool MergeWith(const ProfileCompilationInfo& info);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800230
231 // Save the profile data to the given file descriptor.
Calin Juravle2e2db782016-02-23 12:00:03 +0000232 bool Save(int fd);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800233
Calin Juravledcab1902017-05-12 19:18:47 -0700234 // Save the current profile into the given file. The file will be cleared before saving.
235 bool Save(const std::string& filename, uint64_t* bytes_written);
Calin Juravle67265462016-03-18 16:23:40 +0000236
Calin Juravle940eb0c2017-01-30 19:30:44 -0800237 // Return the number of methods that were profiled.
Calin Juravle998c2162015-12-21 15:39:33 +0200238 uint32_t GetNumberOfMethods() const;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800239
240 // Return the number of resolved classes that were profiled.
Calin Juravle67265462016-03-18 16:23:40 +0000241 uint32_t GetNumberOfResolvedClasses() const;
Calin Juravle226501b2015-12-11 14:41:31 +0000242
Mathieu Chartierea650f32017-05-24 12:04:13 -0700243 // Return true if the method reference is a hot or startup method in the profiling info.
244 bool IsStartupOrHotMethod(const MethodReference& method_ref) const;
245 bool IsStartupOrHotMethod(const std::string& dex_location,
246 uint32_t dex_checksum,
247 uint16_t dex_method_index) const;
248
Calin Juravle940eb0c2017-01-30 19:30:44 -0800249 // Return true if the method reference is present in the profiling info.
Calin Juravle226501b2015-12-11 14:41:31 +0000250 bool ContainsMethod(const MethodReference& method_ref) const;
251
Calin Juravle940eb0c2017-01-30 19:30:44 -0800252 // Return true if the class's type is present in the profiling info.
Andreas Gampea5b09a62016-11-17 15:21:22 -0800253 bool ContainsClass(const DexFile& dex_file, dex::TypeIndex type_idx) const;
Mathieu Chartiera8077802016-03-16 19:08:31 -0700254
Calin Juravlecc3171a2017-05-19 16:47:53 -0700255 // Return the method data for the given location and index from the profiling info.
256 // If the method index is not found or the checksum doesn't match, null is returned.
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700257 // Note: the inline cache map is a pointer to the map stored in the profile and
258 // its allocation will go away if the profile goes out of scope.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700259 std::unique_ptr<OfflineProfileMethodInfo> GetMethod(const std::string& dex_location,
260 uint32_t dex_checksum,
261 uint16_t dex_method_index) const;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800262
263 // Dump all the loaded profile info into a string and returns it.
Calin Juravle998c2162015-12-21 15:39:33 +0200264 // If dex_files is not null then the method indices will be resolved to their
265 // names.
Calin Juravle226501b2015-12-11 14:41:31 +0000266 // This is intended for testing and debugging.
David Sehrb18991b2017-02-08 20:58:10 -0800267 std::string DumpInfo(const std::vector<std::unique_ptr<const DexFile>>* dex_files,
268 bool print_full_dex_location = true) const;
Calin Juravle998c2162015-12-21 15:39:33 +0200269 std::string DumpInfo(const std::vector<const DexFile*>* dex_files,
270 bool print_full_dex_location = true) const;
Calin Juravle226501b2015-12-11 14:41:31 +0000271
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700272 // Return the classes and methods for a given dex file through out args. The out args are the set
Mathieu Chartier34067262017-04-06 13:55:46 -0700273 // of class as well as the methods and their associated inline caches. Returns true if the dex
274 // file is register and has a matching checksum, false otherwise.
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700275 bool GetClassesAndMethods(const DexFile& dex_file,
276 /*out*/std::set<dex::TypeIndex>* class_set,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700277 /*out*/std::set<uint16_t>* hot_method_set,
278 /*out*/std::set<uint16_t>* startup_method_set,
279 /*out*/std::set<uint16_t>* post_startup_method_method_set) const;
David Sehr7c80f2d2017-02-07 16:47:58 -0800280
Calin Juravle940eb0c2017-01-30 19:30:44 -0800281 // Perform an equality test with the `other` profile information.
Calin Juravle2e2db782016-02-23 12:00:03 +0000282 bool Equals(const ProfileCompilationInfo& other);
Calin Juravle67265462016-03-18 16:23:40 +0000283
Calin Juravle940eb0c2017-01-30 19:30:44 -0800284 // Return the class descriptors for all of the classes in the profiles' class sets.
Mathieu Chartier046854b2017-03-01 17:16:22 -0800285 std::set<DexCacheResolvedClasses> GetResolvedClasses(
Calin Juravle08556882017-05-26 16:40:45 -0700286 const std::vector<const DexFile*>& dex_files_) const;
Calin Juravle226501b2015-12-11 14:41:31 +0000287
Calin Juravle940eb0c2017-01-30 19:30:44 -0800288 // Return the profile key associated with the given dex location.
289 static std::string GetProfileDexFileKey(const std::string& dex_location);
290
291 // Generate a test profile which will contain a percentage of the total maximum
292 // number of methods and classes (method_ratio and class_ratio).
Calin Juravle7bcdb532016-06-07 16:14:47 +0100293 static bool GenerateTestProfile(int fd,
294 uint16_t number_of_dex_files,
295 uint16_t method_ratio,
Jeff Haof0a31f82017-03-27 15:50:37 -0700296 uint16_t class_ratio,
297 uint32_t random_seed);
298
299 // Generate a test profile which will randomly contain classes and methods from
300 // the provided list of dex files.
301 static bool GenerateTestProfile(int fd,
302 std::vector<std::unique_ptr<const DexFile>>& dex_files,
303 uint32_t random_seed);
Calin Juravle7bcdb532016-06-07 16:14:47 +0100304
Calin Juravle940eb0c2017-01-30 19:30:44 -0800305 // Check that the given profile method info contain the same data.
306 static bool Equals(const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi1,
307 const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi2);
308
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700309 ArenaAllocator* GetArena() { return &arena_; }
Calin Juravlecc3171a2017-05-19 16:47:53 -0700310
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700311 // Add a method index to the profile (without inline caches).
312 bool AddMethodIndex(const std::string& dex_location, uint32_t checksum, uint16_t method_idx);
313
Mathieu Chartierc5dd3192015-12-09 16:38:30 -0800314 private:
Calin Juravle64142952016-03-21 14:37:55 +0000315 enum ProfileLoadSatus {
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700316 kProfileLoadWouldOverwiteData,
Calin Juravle64142952016-03-21 14:37:55 +0000317 kProfileLoadIOError,
318 kProfileLoadVersionMismatch,
319 kProfileLoadBadData,
320 kProfileLoadSuccess
321 };
322
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700323 const uint32_t kProfileSizeWarningThresholdInBytes = 500000U;
324 const uint32_t kProfileSizeErrorThresholdInBytes = 1000000U;
325
Calin Juravle940eb0c2017-01-30 19:30:44 -0800326 // Internal representation of the profile information belonging to a dex file.
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700327 // Note that we could do without profile_key (the key used to encode the dex
328 // file in the profile) and profile_index (the index of the dex file in the
329 // profile) fields in this struct because we can infer them from
330 // profile_key_map_ and info_. However, it makes the profiles logic much
331 // simpler if we have references here as well.
Calin Juravle798ba162017-05-23 23:01:53 -0700332 struct DexFileData : public DeletableArenaObject<kArenaAllocProfile> {
Calin Juravlecc3171a2017-05-19 16:47:53 -0700333 DexFileData(ArenaAllocator* arena,
334 const std::string& key,
335 uint32_t location_checksum,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700336 uint16_t index,
337 uint32_t num_methods)
Calin Juravlecc3171a2017-05-19 16:47:53 -0700338 : arena_(arena),
339 profile_key(key),
340 profile_index(index),
341 checksum(location_checksum),
342 method_map(std::less<uint16_t>(), arena->Adapter(kArenaAllocProfile)),
Mathieu Chartierea650f32017-05-24 12:04:13 -0700343 class_set(std::less<dex::TypeIndex>(), arena->Adapter(kArenaAllocProfile)),
344 num_method_ids(num_methods),
345 bitmap_storage(arena->Adapter(kArenaAllocProfile)) {
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700346 const size_t num_bits = num_method_ids * kBitmapCount;
347 bitmap_storage.resize(RoundUp(num_bits, kBitsPerByte) / kBitsPerByte);
348 if (!bitmap_storage.empty()) {
349 method_bitmap =
350 BitMemoryRegion(MemoryRegion(&bitmap_storage[0], bitmap_storage.size()), 0, num_bits);
351 }
Mathieu Chartierea650f32017-05-24 12:04:13 -0700352 }
353
354 bool operator==(const DexFileData& other) const {
355 return checksum == other.checksum && method_map == other.method_map;
356 }
357
358 // Mark a method as executed at least once.
359 void AddSampledMethod(bool startup, size_t index) {
360 method_bitmap.StoreBit(MethodBitIndex(startup, index), true);
361 }
362
363 bool HasSampledMethod(bool startup, size_t index) const {
364 return method_bitmap.LoadBit(MethodBitIndex(startup, index));
365 }
Calin Juravlecc3171a2017-05-19 16:47:53 -0700366
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700367 void MergeBitmap(const DexFileData& other) {
368 DCHECK_EQ(bitmap_storage.size(), other.bitmap_storage.size());
369 for (size_t i = 0; i < bitmap_storage.size(); ++i) {
370 bitmap_storage[i] |= other.bitmap_storage[i];
371 }
372 }
373
Calin Juravlecc3171a2017-05-19 16:47:53 -0700374 // The arena used to allocate new inline cache maps.
375 ArenaAllocator* arena_;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700376 // The profile key this data belongs to.
377 std::string profile_key;
378 // The profile index of this dex file (matches ClassReference#dex_profile_index).
Calin Juravle940eb0c2017-01-30 19:30:44 -0800379 uint8_t profile_index;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700380 // The dex checksum.
Calin Juravle998c2162015-12-21 15:39:33 +0200381 uint32_t checksum;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700382 // The methonds' profile information.
Calin Juravle940eb0c2017-01-30 19:30:44 -0800383 MethodMap method_map;
384 // The classes which have been profiled. Note that these don't necessarily include
385 // all the classes that can be found in the inline caches reference.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700386 ArenaSet<dex::TypeIndex> class_set;
Calin Juravlecc3171a2017-05-19 16:47:53 -0700387 // Find the inline caches of the the given method index. Add an empty entry if
388 // no previous data is found.
389 InlineCacheMap* FindOrAddMethod(uint16_t method_index);
Mathieu Chartierea650f32017-05-24 12:04:13 -0700390 // Num method ids.
391 uint32_t num_method_ids;
392 ArenaVector<uint8_t> bitmap_storage;
393 BitMemoryRegion method_bitmap;
394
Mathieu Chartierea650f32017-05-24 12:04:13 -0700395 private:
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700396 enum BitmapIndex {
397 kBitmapStartup,
398 kBitmapPostStartup,
399 kBitmapCount,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700400 };
401
402 size_t MethodBitIndex(bool startup, size_t index) const {
403 DCHECK_LT(index, num_method_ids);
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700404 // The format is [startup bitmap][post startup bitmap]
405 // This compresses better than ([startup bit][post statup bit])*
406
407 return index + (startup
408 ? kBitmapStartup * num_method_ids
409 : kBitmapPostStartup * num_method_ids);
Mathieu Chartierea650f32017-05-24 12:04:13 -0700410 }
Calin Juravle998c2162015-12-21 15:39:33 +0200411 };
Calin Juravle226501b2015-12-11 14:41:31 +0000412
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700413 // Return the profile data for the given profile key or null if the dex location
Calin Juravle940eb0c2017-01-30 19:30:44 -0800414 // already exists but has a different checksum
Mathieu Chartierea650f32017-05-24 12:04:13 -0700415 DexFileData* GetOrAddDexFileData(const std::string& profile_key,
416 uint32_t checksum,
417 uint32_t num_method_ids);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800418
Mathieu Chartierea650f32017-05-24 12:04:13 -0700419 DexFileData* GetOrAddDexFileData(const DexFile* dex_file) {
420 return GetOrAddDexFileData(GetProfileDexFileKey(dex_file->GetLocation()),
421 dex_file->GetLocationChecksum(),
422 dex_file->NumMethodIds());
423 }
Calin Juravle940eb0c2017-01-30 19:30:44 -0800424
425 // Add a method to the profile using its offline representation.
426 // This is mostly used to facilitate testing.
427 bool AddMethod(const std::string& dex_location,
428 uint32_t dex_checksum,
429 uint16_t method_index,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700430 uint32_t num_method_ids,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800431 const OfflineProfileMethodInfo& pmi);
432
433 // Add a class index to the profile.
Mathieu Chartierea650f32017-05-24 12:04:13 -0700434 bool AddClassIndex(const std::string& dex_location,
435 uint32_t checksum,
436 dex::TypeIndex type_idx,
437 uint32_t num_method_ids);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800438
439 // Add all classes from the given dex cache to the the profile.
Calin Juravle99629622016-04-19 16:33:46 +0100440 bool AddResolvedClasses(const DexCacheResolvedClasses& classes);
Calin Juravle64142952016-03-21 14:37:55 +0000441
Calin Juravle940eb0c2017-01-30 19:30:44 -0800442 // Search for the given method in the profile.
443 // If found, its inline cache map is returned, otherwise the method returns null.
444 const InlineCacheMap* FindMethod(const std::string& dex_location,
445 uint32_t dex_checksum,
446 uint16_t dex_method_index) const;
447
448 // Encode the known dex_files into a vector. The index of a dex_reference will
449 // be the same as the profile index of the dex file (used to encode the ClassReferences).
450 void DexFileToProfileIndex(/*out*/std::vector<DexReference>* dex_references) const;
451
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700452 // Return the dex data associated with the given profile key or null if the profile
453 // doesn't contain the key.
454 const DexFileData* FindDexData(const std::string& profile_key) const;
455
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700456 // Checks if the profile is empty.
457 bool IsEmpty() const;
458
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700459 // Inflate the input buffer (in_buffer) of size in_size. It returns a buffer of
460 // compressed data for the input buffer of "compressed_data_size" size.
461 std::unique_ptr<uint8_t[]> DeflateBuffer(const uint8_t* in_buffer,
462 uint32_t in_size,
463 /*out*/uint32_t* compressed_data_size);
464
465 // Inflate the input buffer(in_buffer) of size in_size. out_size is the expected output
466 // size of the buffer. It puts the output in out_buffer. It returns Z_STREAM_END on
467 // success. On error, it returns Z_STREAM_ERROR if the compressed data is inconsistent
468 // and Z_DATA_ERROR if the stream ended prematurely or the stream has extra data.
469 int InflateBuffer(const uint8_t* in_buffer,
470 uint32_t in_size,
471 uint32_t out_size,
472 /*out*/uint8_t* out_buffer);
473
Calin Juravle64142952016-03-21 14:37:55 +0000474 // Parsing functionality.
475
Calin Juravle940eb0c2017-01-30 19:30:44 -0800476 // The information present in the header of each profile line.
Calin Juravle64142952016-03-21 14:37:55 +0000477 struct ProfileLineHeader {
478 std::string dex_location;
Calin Juravle64142952016-03-21 14:37:55 +0000479 uint16_t class_set_size;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800480 uint32_t method_region_size_bytes;
Calin Juravle64142952016-03-21 14:37:55 +0000481 uint32_t checksum;
Mathieu Chartierea650f32017-05-24 12:04:13 -0700482 uint32_t num_method_ids;
Calin Juravle64142952016-03-21 14:37:55 +0000483 };
484
485 // A helper structure to make sure we don't read past our buffers in the loops.
486 struct SafeBuffer {
487 public:
488 explicit SafeBuffer(size_t size) : storage_(new uint8_t[size]) {
489 ptr_current_ = storage_.get();
490 ptr_end_ = ptr_current_ + size;
491 }
492
493 // Reads the content of the descriptor at the current position.
494 ProfileLoadSatus FillFromFd(int fd,
495 const std::string& source,
496 /*out*/std::string* error);
497
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700498 ProfileLoadSatus FillFromBuffer(uint8_t* buffer_ptr,
499 const std::string& source,
500 /*out*/std::string* error);
501
Calin Juravle64142952016-03-21 14:37:55 +0000502 // Reads an uint value (high bits to low bits) and advances the current pointer
503 // with the number of bits read.
Calin Juravle940eb0c2017-01-30 19:30:44 -0800504 template <typename T> bool ReadUintAndAdvance(/*out*/ T* value);
Calin Juravle64142952016-03-21 14:37:55 +0000505
506 // Compares the given data with the content current pointer. If the contents are
507 // equal it advances the current pointer by data_size.
508 bool CompareAndAdvance(const uint8_t* data, size_t data_size);
509
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700510 // Advances current pointer by data_size.
511 void Advance(size_t data_size);
512
513 // Returns the count of unread bytes.
514 size_t CountUnreadBytes();
515
516 // Returns the current pointer.
517 const uint8_t* GetCurrentPtr();
Calin Juravle940eb0c2017-01-30 19:30:44 -0800518
Calin Juravle64142952016-03-21 14:37:55 +0000519 // Get the underlying raw buffer.
520 uint8_t* Get() { return storage_.get(); }
521
522 private:
Andreas Gampe7b8a2652016-11-11 17:11:25 -0800523 std::unique_ptr<uint8_t[]> storage_;
Calin Juravle64142952016-03-21 14:37:55 +0000524 uint8_t* ptr_end_;
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700525 uint8_t* ptr_current_;
Calin Juravle64142952016-03-21 14:37:55 +0000526 };
527
Calin Juravle940eb0c2017-01-30 19:30:44 -0800528 // Entry point for profile loding functionality.
Calin Juravle64142952016-03-21 14:37:55 +0000529 ProfileLoadSatus LoadInternal(int fd, std::string* error);
530
Calin Juravle940eb0c2017-01-30 19:30:44 -0800531 // Read the profile header from the given fd and store the number of profile
532 // lines into number_of_dex_files.
Calin Juravle64142952016-03-21 14:37:55 +0000533 ProfileLoadSatus ReadProfileHeader(int fd,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800534 /*out*/uint8_t* number_of_dex_files,
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700535 /*out*/uint32_t* size_uncompressed_data,
536 /*out*/uint32_t* size_compressed_data,
Calin Juravle64142952016-03-21 14:37:55 +0000537 /*out*/std::string* error);
538
Calin Juravle940eb0c2017-01-30 19:30:44 -0800539 // Read the header of a profile line from the given fd.
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700540 ProfileLoadSatus ReadProfileLineHeader(SafeBuffer& buffer,
Calin Juravle64142952016-03-21 14:37:55 +0000541 /*out*/ProfileLineHeader* line_header,
542 /*out*/std::string* error);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800543
544 // Read individual elements from the profile line header.
545 bool ReadProfileLineHeaderElements(SafeBuffer& buffer,
546 /*out*/uint16_t* dex_location_size,
547 /*out*/ProfileLineHeader* line_header,
548 /*out*/std::string* error);
549
550 // Read a single profile line from the given fd.
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700551 ProfileLoadSatus ReadProfileLine(SafeBuffer& buffer,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800552 uint8_t number_of_dex_files,
Calin Juravle64142952016-03-21 14:37:55 +0000553 const ProfileLineHeader& line_header,
554 /*out*/std::string* error);
555
Calin Juravle940eb0c2017-01-30 19:30:44 -0800556 // Read all the classes from the buffer into the profile `info_` structure.
557 bool ReadClasses(SafeBuffer& buffer,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800558 const ProfileLineHeader& line_header,
559 /*out*/std::string* error);
560
561 // Read all the methods from the buffer into the profile `info_` structure.
562 bool ReadMethods(SafeBuffer& buffer,
563 uint8_t number_of_dex_files,
564 const ProfileLineHeader& line_header,
565 /*out*/std::string* error);
566
567 // Read the inline cache encoding from line_bufer into inline_cache.
568 bool ReadInlineCache(SafeBuffer& buffer,
569 uint8_t number_of_dex_files,
570 /*out*/InlineCacheMap* inline_cache,
571 /*out*/std::string* error);
572
573 // Encode the inline cache into the given buffer.
574 void AddInlineCacheToBuffer(std::vector<uint8_t>* buffer,
575 const InlineCacheMap& inline_cache);
576
577 // Return the number of bytes needed to encode the profile information
578 // for the methods in dex_data.
579 uint32_t GetMethodsRegionSize(const DexFileData& dex_data);
580
581 // Group `classes` by their owning dex profile index and put the result in
582 // `dex_to_classes_map`.
583 void GroupClassesByDex(
584 const ClassSet& classes,
585 /*out*/SafeMap<uint8_t, std::vector<dex::TypeIndex>>* dex_to_classes_map);
Mathieu Chartierc5dd3192015-12-09 16:38:30 -0800586
Calin Juravlecc3171a2017-05-19 16:47:53 -0700587 // Find the data for the dex_pc in the inline cache. Adds an empty entry
588 // if no previous data exists.
589 DexPcData* FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc);
590
Calin Juravle877fd962016-01-05 14:29:29 +0000591 friend class ProfileCompilationInfoTest;
592 friend class CompilerDriverProfileTest;
593 friend class ProfileAssistantTest;
Jeff Hao41fba6a2016-11-28 11:53:33 -0800594 friend class Dex2oatLayoutTest;
Calin Juravle877fd962016-01-05 14:29:29 +0000595
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700596 ArenaPool default_arena_pool_;
597 ArenaAllocator arena_;
Calin Juravlecc3171a2017-05-19 16:47:53 -0700598
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700599 // Vector containing the actual profile info.
600 // The vector index is the profile index of the dex data and
601 // matched DexFileData::profile_index.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700602 ArenaVector<DexFileData*> info_;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700603
604 // Cache mapping profile keys to profile index.
605 // This is used to speed up searches since it avoids iterating
606 // over the info_ vector when searching by profile key.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700607 ArenaSafeMap<const std::string, uint8_t> profile_key_map_;
Calin Juravle226501b2015-12-11 14:41:31 +0000608};
609
Calin Juravle31f2c152015-10-23 17:56:15 +0100610} // namespace art
611
Calin Juravle33083d62017-01-18 15:29:12 -0800612#endif // ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_