blob: 5488a9e81ee09cc60bc5c11bc4673c485a8d78ef [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_containers.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070025#include "base/arena_object.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"
David Sehr9e734c72018-01-04 17:56:19 -080028#include "dex/dex_file.h"
29#include "dex/dex_file_types.h"
Calin Juravle226501b2015-12-11 14:41:31 +000030#include "method_reference.h"
Calin Juravle1e2de642018-01-18 01:08:23 -080031#include "mem_map.h"
Calin Juravle31f2c152015-10-23 17:56:15 +010032#include "safe_map.h"
Mathieu Chartierdbddc222017-05-24 12:04:13 -070033#include "type_reference.h"
Calin Juravle31f2c152015-10-23 17:56:15 +010034
35namespace art {
36
Calin Juravle31f2c152015-10-23 17:56:15 +010037/**
Calin Juravle940eb0c2017-01-30 19:30:44 -080038 * Convenient class to pass around profile information (including inline caches)
39 * without the need to hold GC-able objects.
40 */
41struct ProfileMethodInfo {
Calin Juravle940eb0c2017-01-30 19:30:44 -080042 struct ProfileInlineCache {
Calin Juravle589e71e2017-03-03 16:05:05 -080043 ProfileInlineCache(uint32_t pc,
44 bool missing_types,
Mathieu Chartierdbddc222017-05-24 12:04:13 -070045 const std::vector<TypeReference>& profile_classes)
Calin Juravle589e71e2017-03-03 16:05:05 -080046 : dex_pc(pc), is_missing_types(missing_types), classes(profile_classes) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080047
48 const uint32_t dex_pc;
Calin Juravle589e71e2017-03-03 16:05:05 -080049 const bool is_missing_types;
Mathieu Chartierdbddc222017-05-24 12:04:13 -070050 const std::vector<TypeReference> classes;
Calin Juravle940eb0c2017-01-30 19:30:44 -080051 };
52
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -070053 explicit ProfileMethodInfo(MethodReference reference) : ref(reference) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080054
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -070055 ProfileMethodInfo(MethodReference reference, const std::vector<ProfileInlineCache>& caches)
56 : ref(reference),
Mathieu Chartierea650f32017-05-24 12:04:13 -070057 inline_caches(caches) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080058
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -070059 MethodReference ref;
60 std::vector<ProfileInlineCache> inline_caches;
Calin Juravle940eb0c2017-01-30 19:30:44 -080061};
62
63/**
Calin Juravle998c2162015-12-21 15:39:33 +020064 * Profile information in a format suitable to be queried by the compiler and
65 * performing profile guided compilation.
66 * It is a serialize-friendly format based on information collected by the
67 * interpreter (ProfileInfo).
Calin Juravle31f2c152015-10-23 17:56:15 +010068 * Currently it stores only the hot compiled methods.
69 */
Calin Juravle226501b2015-12-11 14:41:31 +000070class ProfileCompilationInfo {
71 public:
Calin Juravle64142952016-03-21 14:37:55 +000072 static const uint8_t kProfileMagic[];
73 static const uint8_t kProfileVersion[];
74
Calin Juravle1e2de642018-01-18 01:08:23 -080075 static const char* kDexMetadataProfileEntry;
76
Calin Juravle940eb0c2017-01-30 19:30:44 -080077 // Data structures for encoding the offline representation of inline caches.
78 // This is exposed as public in order to make it available to dex2oat compilations
79 // (see compiler/optimizing/inliner.cc).
80
81 // A dex location together with its checksum.
82 struct DexReference {
Mathieu Chartierea650f32017-05-24 12:04:13 -070083 DexReference() : dex_checksum(0), num_method_ids(0) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080084
Mathieu Chartierea650f32017-05-24 12:04:13 -070085 DexReference(const std::string& location, uint32_t checksum, uint32_t num_methods)
86 : dex_location(location), dex_checksum(checksum), num_method_ids(num_methods) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -080087
88 bool operator==(const DexReference& other) const {
Mathieu Chartierea650f32017-05-24 12:04:13 -070089 return dex_checksum == other.dex_checksum &&
90 dex_location == other.dex_location &&
91 num_method_ids == other.num_method_ids;
Calin Juravle940eb0c2017-01-30 19:30:44 -080092 }
93
Calin Juravlee0ac1152017-02-13 19:03:47 -080094 bool MatchesDex(const DexFile* dex_file) const {
95 return dex_checksum == dex_file->GetLocationChecksum() &&
96 dex_location == GetProfileDexFileKey(dex_file->GetLocation());
97 }
98
Calin Juravle940eb0c2017-01-30 19:30:44 -080099 std::string dex_location;
100 uint32_t dex_checksum;
Mathieu Chartierea650f32017-05-24 12:04:13 -0700101 uint32_t num_method_ids;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800102 };
103
104 // Encodes a class reference in the profile.
105 // The owning dex file is encoded as the index (dex_profile_index) it has in the
106 // profile rather than as a full DexRefence(location,checksum).
107 // This avoids excessive string copying when managing the profile data.
108 // The dex_profile_index is an index in either of:
109 // - OfflineProfileMethodInfo#dex_references vector (public use)
110 // - DexFileData#profile_index (internal use).
111 // Note that the dex_profile_index is not necessary the multidex index.
112 // We cannot rely on the actual multidex index because a single profile may store
113 // data from multiple splits. This means that a profile may contain a classes2.dex from split-A
114 // and one from split-B.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700115 struct ClassReference : public ValueObject {
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700116 ClassReference(uint8_t dex_profile_idx, const dex::TypeIndex type_idx) :
Calin Juravle940eb0c2017-01-30 19:30:44 -0800117 dex_profile_index(dex_profile_idx), type_index(type_idx) {}
118
119 bool operator==(const ClassReference& other) const {
120 return dex_profile_index == other.dex_profile_index && type_index == other.type_index;
121 }
122 bool operator<(const ClassReference& other) const {
123 return dex_profile_index == other.dex_profile_index
124 ? type_index < other.type_index
125 : dex_profile_index < other.dex_profile_index;
126 }
127
128 uint8_t dex_profile_index; // the index of the owning dex in the profile info
129 dex::TypeIndex type_index; // the type index of the class
130 };
131
132 // The set of classes that can be found at a given dex pc.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700133 using ClassSet = ArenaSet<ClassReference>;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800134
135 // Encodes the actual inline cache for a given dex pc (whether or not the receiver is
136 // megamorphic and its possible types).
Calin Juravle589e71e2017-03-03 16:05:05 -0800137 // If the receiver is megamorphic or is missing types the set of classes will be empty.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700138 struct DexPcData : public ArenaObject<kArenaAllocProfile> {
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100139 explicit DexPcData(ArenaAllocator* allocator)
Calin Juravlecc3171a2017-05-19 16:47:53 -0700140 : is_missing_types(false),
141 is_megamorphic(false),
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100142 classes(std::less<ClassReference>(), allocator->Adapter(kArenaAllocProfile)) {}
Calin Juravle940eb0c2017-01-30 19:30:44 -0800143 void AddClass(uint16_t dex_profile_idx, const dex::TypeIndex& type_idx);
Calin Juravle589e71e2017-03-03 16:05:05 -0800144 void SetIsMegamorphic() {
145 if (is_missing_types) return;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800146 is_megamorphic = true;
147 classes.clear();
148 }
Calin Juravle589e71e2017-03-03 16:05:05 -0800149 void SetIsMissingTypes() {
150 is_megamorphic = false;
151 is_missing_types = true;
152 classes.clear();
153 }
Calin Juravle940eb0c2017-01-30 19:30:44 -0800154 bool operator==(const DexPcData& other) const {
Calin Juravle589e71e2017-03-03 16:05:05 -0800155 return is_megamorphic == other.is_megamorphic &&
156 is_missing_types == other.is_missing_types &&
157 classes == other.classes;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800158 }
159
Calin Juravle589e71e2017-03-03 16:05:05 -0800160 // Not all runtime types can be encoded in the profile. For example if the receiver
161 // type is in a dex file which is not tracked for profiling its type cannot be
162 // encoded. When types are missing this field will be set to true.
163 bool is_missing_types;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800164 bool is_megamorphic;
165 ClassSet classes;
166 };
167
168 // The inline cache map: DexPc -> DexPcData.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700169 using InlineCacheMap = ArenaSafeMap<uint16_t, DexPcData>;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800170
Mathieu Chartier34067262017-04-06 13:55:46 -0700171 // Maps a method dex index to its inline cache.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700172 using MethodMap = ArenaSafeMap<uint16_t, InlineCacheMap>;
Mathieu Chartier34067262017-04-06 13:55:46 -0700173
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700174 // Profile method hotness information for a single method. Also includes a pointer to the inline
175 // cache map.
176 class MethodHotness {
177 public:
178 enum Flag {
179 kFlagHot = 0x1,
180 kFlagStartup = 0x2,
181 kFlagPostStartup = 0x4,
182 };
183
184 bool IsHot() const {
185 return (flags_ & kFlagHot) != 0;
186 }
187
188 bool IsStartup() const {
189 return (flags_ & kFlagStartup) != 0;
190 }
191
192 bool IsPostStartup() const {
193 return (flags_ & kFlagPostStartup) != 0;
194 }
195
196 void AddFlag(Flag flag) {
197 flags_ |= flag;
198 }
199
Mathieu Chartier7c1be8b2017-06-15 13:56:05 -0700200 uint8_t GetFlags() const {
201 return flags_;
202 }
203
Mathieu Chartiere46f3a82017-06-19 19:54:12 -0700204 bool IsInProfile() const {
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700205 return flags_ != 0;
206 }
207
Mathieu Chartiere46f3a82017-06-19 19:54:12 -0700208 private:
209 const InlineCacheMap* inline_cache_map_ = nullptr;
210 uint8_t flags_ = 0;
211
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700212 const InlineCacheMap* GetInlineCacheMap() const {
213 return inline_cache_map_;
214 }
215
216 void SetInlineCacheMap(const InlineCacheMap* info) {
217 inline_cache_map_ = info;
218 }
219
Mathieu Chartiere46f3a82017-06-19 19:54:12 -0700220 friend class ProfileCompilationInfo;
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700221 };
222
Calin Juravle940eb0c2017-01-30 19:30:44 -0800223 // Encodes the full set of inline caches for a given method.
224 // The dex_references vector is indexed according to the ClassReference::dex_profile_index.
225 // i.e. the dex file of any ClassReference present in the inline caches can be found at
226 // dex_references[ClassReference::dex_profile_index].
227 struct OfflineProfileMethodInfo {
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700228 explicit OfflineProfileMethodInfo(const InlineCacheMap* inline_cache_map)
229 : inline_caches(inline_cache_map) {}
Calin Juravlecc3171a2017-05-19 16:47:53 -0700230
Calin Juravle940eb0c2017-01-30 19:30:44 -0800231 bool operator==(const OfflineProfileMethodInfo& other) const;
232
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700233 const InlineCacheMap* const inline_caches;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800234 std::vector<DexReference> dex_references;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800235 };
236
237 // Public methods to create, extend or query the profile.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700238 ProfileCompilationInfo();
239 explicit ProfileCompilationInfo(ArenaPool* arena_pool);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800240
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700241 ~ProfileCompilationInfo();
242
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700243 // Add the given methods to the current profile object.
Calin Juravleee9cb412018-02-13 20:32:35 -0800244 bool AddMethods(const std::vector<ProfileMethodInfo>& methods, MethodHotness::Flag flags);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800245
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700246 // Add the given classes to the current profile object.
247 bool AddClasses(const std::set<DexCacheResolvedClasses>& resolved_classes);
248
249 // Add multiple type ids for classes in a single dex file. Iterator is for type_ids not
250 // class_defs.
Mathieu Chartierfaf83202017-06-08 10:35:20 -0700251 template <class Iterator>
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700252 bool AddClassesForDex(const DexFile* dex_file, Iterator index_begin, Iterator index_end) {
253 DexFileData* data = GetOrAddDexFileData(dex_file);
254 if (data == nullptr) {
255 return false;
256 }
257 data->class_set.insert(index_begin, index_end);
258 return true;
259 }
Mathieu Chartierfc8b4222017-09-17 13:44:24 -0700260 // Add a single type id for a dex file.
261 bool AddClassForDex(const TypeReference& ref) {
262 DexFileData* data = GetOrAddDexFileData(ref.dex_file);
263 if (data == nullptr) {
264 return false;
265 }
266 data->class_set.insert(ref.TypeIndex());
267 return true;
268 }
269
Mathieu Chartierfaf83202017-06-08 10:35:20 -0700270
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700271 // Add a method index to the profile (without inline caches). The method flags determine if it is
272 // hot, startup, or post startup, or a combination of the previous.
273 bool AddMethodIndex(MethodHotness::Flag flags,
274 const std::string& dex_location,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700275 uint32_t checksum,
276 uint16_t method_idx,
277 uint32_t num_method_ids);
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700278 bool AddMethodIndex(MethodHotness::Flag flags, const MethodReference& ref);
Mathieu Chartierea650f32017-05-24 12:04:13 -0700279
280 // Add a method to the profile using its online representation (containing runtime structures).
Calin Juravleee9cb412018-02-13 20:32:35 -0800281 bool AddMethod(const ProfileMethodInfo& pmi, MethodHotness::Flag flags);
Mathieu Chartierea650f32017-05-24 12:04:13 -0700282
Mathieu Chartierdb40eac2017-06-09 18:34:11 -0700283 // Bulk add sampled methods and/or hot methods for a single dex, fast since it only has one
284 // GetOrAddDexFileData call.
Mathieu Chartierfaf83202017-06-08 10:35:20 -0700285 template <class Iterator>
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700286 bool AddMethodsForDex(MethodHotness::Flag flags,
287 const DexFile* dex_file,
288 Iterator index_begin,
289 Iterator index_end) {
290 DexFileData* data = GetOrAddDexFileData(dex_file);
291 if (data == nullptr) {
292 return false;
293 }
294 for (Iterator it = index_begin; it != index_end; ++it) {
295 DCHECK_LT(*it, data->num_method_ids);
Calin Juravle1ad1e3f2017-09-19 18:20:37 -0700296 if (!data->AddMethod(flags, *it)) {
297 return false;
298 }
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700299 }
300 return true;
301 }
Mathieu Chartierea650f32017-05-24 12:04:13 -0700302
Mathieu Chartier2f794552017-06-19 10:58:08 -0700303 // Add hotness flags for a simple method.
304 bool AddMethodHotness(const MethodReference& method_ref, const MethodHotness& hotness);
305
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700306 // Load or Merge profile information from the given file descriptor.
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700307 // If the current profile is non-empty the load will fail.
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700308 // If merge_classes is set to false, classes will not be merged/loaded.
Calin Juravled9f4d642018-01-24 20:33:00 -0800309 // If filter_fn is present, it will be used to filter out profile data belonging
310 // to dex file which do not comply with the filter
311 // (i.e. for which filter_fn(dex_location, dex_checksum) is false).
312 using ProfileLoadFilterFn = std::function<bool(const std::string&, uint32_t)>;
313 // Profile filter method which accepts all dex locations.
314 // This is convenient to use when we need to accept all locations without repeating the same
315 // lambda.
316 static bool ProfileFilterFnAcceptAll(const std::string& dex_location, uint32_t checksum);
317
318 bool Load(
319 int fd,
320 bool merge_classes = true,
321 const ProfileLoadFilterFn& filter_fn = ProfileFilterFnAcceptAll);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800322
Shubham Ajmera188b2bf2017-09-20 15:53:35 -0700323 // Verify integrity of the profile file with the provided dex files.
324 // If there exists a DexData object which maps to a dex_file, then it verifies that:
325 // - The checksums of the DexData and dex_file are equals.
326 // - No method id exceeds NumMethodIds corresponding to the dex_file.
327 // - No class id exceeds NumTypeIds corresponding to the dex_file.
328 // - For every inline_caches, class_ids does not exceed NumTypeIds corresponding to
329 // the dex_file they are in.
330 bool VerifyProfileData(const std::vector<const DexFile *> &dex_files);
331
Calin Juravledcab1902017-05-12 19:18:47 -0700332 // Load profile information from the given file
333 // If the current profile is non-empty the load will fail.
334 // If clear_if_invalid is true and the file is invalid the method clears the
335 // the file and returns true.
336 bool Load(const std::string& filename, bool clear_if_invalid);
337
Mathieu Chartier2f794552017-06-19 10:58:08 -0700338 // Merge the data from another ProfileCompilationInfo into the current object. Only merges
339 // classes if merge_classes is true. This is used for creating the boot profile since
340 // we don't want all of the classes to be image classes.
341 bool MergeWith(const ProfileCompilationInfo& info, bool merge_classes = true);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800342
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700343 // Merge profile information from the given file descriptor.
344 bool MergeWith(const std::string& filename);
345
Calin Juravle940eb0c2017-01-30 19:30:44 -0800346 // Save the profile data to the given file descriptor.
Calin Juravle2e2db782016-02-23 12:00:03 +0000347 bool Save(int fd);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800348
Calin Juravledcab1902017-05-12 19:18:47 -0700349 // Save the current profile into the given file. The file will be cleared before saving.
350 bool Save(const std::string& filename, uint64_t* bytes_written);
Calin Juravle67265462016-03-18 16:23:40 +0000351
Calin Juravle940eb0c2017-01-30 19:30:44 -0800352 // Return the number of methods that were profiled.
Calin Juravle998c2162015-12-21 15:39:33 +0200353 uint32_t GetNumberOfMethods() const;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800354
355 // Return the number of resolved classes that were profiled.
Calin Juravle67265462016-03-18 16:23:40 +0000356 uint32_t GetNumberOfResolvedClasses() const;
Calin Juravle226501b2015-12-11 14:41:31 +0000357
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700358 // Returns the profile method info for a given method reference.
359 MethodHotness GetMethodHotness(const MethodReference& method_ref) const;
360 MethodHotness GetMethodHotness(const std::string& dex_location,
361 uint32_t dex_checksum,
362 uint16_t dex_method_index) const;
Mathieu Chartierdb40eac2017-06-09 18:34:11 -0700363
Calin Juravle940eb0c2017-01-30 19:30:44 -0800364 // Return true if the class's type is present in the profiling info.
Andreas Gampea5b09a62016-11-17 15:21:22 -0800365 bool ContainsClass(const DexFile& dex_file, dex::TypeIndex type_idx) const;
Mathieu Chartiera8077802016-03-16 19:08:31 -0700366
Calin Juravlecc3171a2017-05-19 16:47:53 -0700367 // Return the method data for the given location and index from the profiling info.
368 // If the method index is not found or the checksum doesn't match, null is returned.
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700369 // Note: the inline cache map is a pointer to the map stored in the profile and
370 // its allocation will go away if the profile goes out of scope.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700371 std::unique_ptr<OfflineProfileMethodInfo> GetMethod(const std::string& dex_location,
372 uint32_t dex_checksum,
373 uint16_t dex_method_index) const;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800374
375 // Dump all the loaded profile info into a string and returns it.
Calin Juravle998c2162015-12-21 15:39:33 +0200376 // If dex_files is not null then the method indices will be resolved to their
377 // names.
Calin Juravle226501b2015-12-11 14:41:31 +0000378 // This is intended for testing and debugging.
David Sehrb18991b2017-02-08 20:58:10 -0800379 std::string DumpInfo(const std::vector<std::unique_ptr<const DexFile>>* dex_files,
380 bool print_full_dex_location = true) const;
Calin Juravle998c2162015-12-21 15:39:33 +0200381 std::string DumpInfo(const std::vector<const DexFile*>* dex_files,
382 bool print_full_dex_location = true) const;
Calin Juravle226501b2015-12-11 14:41:31 +0000383
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700384 // 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 -0700385 // of class as well as the methods and their associated inline caches. Returns true if the dex
386 // file is register and has a matching checksum, false otherwise.
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700387 bool GetClassesAndMethods(const DexFile& dex_file,
388 /*out*/std::set<dex::TypeIndex>* class_set,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700389 /*out*/std::set<uint16_t>* hot_method_set,
390 /*out*/std::set<uint16_t>* startup_method_set,
391 /*out*/std::set<uint16_t>* post_startup_method_method_set) const;
David Sehr7c80f2d2017-02-07 16:47:58 -0800392
Calin Juravle940eb0c2017-01-30 19:30:44 -0800393 // Perform an equality test with the `other` profile information.
Calin Juravle2e2db782016-02-23 12:00:03 +0000394 bool Equals(const ProfileCompilationInfo& other);
Calin Juravle67265462016-03-18 16:23:40 +0000395
Calin Juravle940eb0c2017-01-30 19:30:44 -0800396 // Return the class descriptors for all of the classes in the profiles' class sets.
Mathieu Chartier046854b2017-03-01 17:16:22 -0800397 std::set<DexCacheResolvedClasses> GetResolvedClasses(
Calin Juravle08556882017-05-26 16:40:45 -0700398 const std::vector<const DexFile*>& dex_files_) const;
Calin Juravle226501b2015-12-11 14:41:31 +0000399
Calin Juravle940eb0c2017-01-30 19:30:44 -0800400 // Return the profile key associated with the given dex location.
401 static std::string GetProfileDexFileKey(const std::string& dex_location);
402
403 // Generate a test profile which will contain a percentage of the total maximum
404 // number of methods and classes (method_ratio and class_ratio).
Calin Juravle7bcdb532016-06-07 16:14:47 +0100405 static bool GenerateTestProfile(int fd,
406 uint16_t number_of_dex_files,
407 uint16_t method_ratio,
Jeff Haof0a31f82017-03-27 15:50:37 -0700408 uint16_t class_ratio,
409 uint32_t random_seed);
410
411 // Generate a test profile which will randomly contain classes and methods from
412 // the provided list of dex files.
413 static bool GenerateTestProfile(int fd,
414 std::vector<std::unique_ptr<const DexFile>>& dex_files,
Shubham Ajmerad704f0b2017-07-26 16:33:35 -0700415 uint16_t method_percentage,
416 uint16_t class_percentage,
Jeff Haof0a31f82017-03-27 15:50:37 -0700417 uint32_t random_seed);
Calin Juravle7bcdb532016-06-07 16:14:47 +0100418
Calin Juravle940eb0c2017-01-30 19:30:44 -0800419 // Check that the given profile method info contain the same data.
420 static bool Equals(const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi1,
421 const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi2);
422
Vladimir Markoca6fff82017-10-03 14:49:14 +0100423 ArenaAllocator* GetAllocator() { return &allocator_; }
Calin Juravlecc3171a2017-05-19 16:47:53 -0700424
Mathieu Chartier4f342b02017-07-21 17:12:39 -0700425 // Return all of the class descriptors in the profile for a set of dex files.
426 std::unordered_set<std::string> GetClassDescriptors(const std::vector<const DexFile*>& dex_files);
427
Calin Juravle1e2de642018-01-18 01:08:23 -0800428 // Return true if the fd points to a profile file.
429 bool IsProfileFile(int fd);
430
Calin Juravle2dba0ab2018-01-22 19:22:24 -0800431 // Update the profile keys corresponding to the given dex files based on their current paths.
432 // This method allows fix-ups in the profile for dex files that might have been renamed.
433 // The new profile key will be constructed based on the current dex location.
434 //
435 // The matching [profile key <-> dex_file] is done based on the dex checksum and the number of
436 // methods ids. If neither is a match then the profile key is not updated.
437 //
438 // If the new profile key would collide with an existing key (for a different dex)
439 // the method returns false. Otherwise it returns true.
440 bool UpdateProfileKeys(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
441
Mathieu Chartierc5dd3192015-12-09 16:38:30 -0800442 private:
Calin Juravle36060d12018-01-19 16:28:38 -0800443 enum ProfileLoadStatus {
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700444 kProfileLoadWouldOverwiteData,
Calin Juravle64142952016-03-21 14:37:55 +0000445 kProfileLoadIOError,
446 kProfileLoadVersionMismatch,
447 kProfileLoadBadData,
448 kProfileLoadSuccess
449 };
450
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700451 const uint32_t kProfileSizeWarningThresholdInBytes = 500000U;
452 const uint32_t kProfileSizeErrorThresholdInBytes = 1000000U;
453
Calin Juravle940eb0c2017-01-30 19:30:44 -0800454 // Internal representation of the profile information belonging to a dex file.
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700455 // Note that we could do without profile_key (the key used to encode the dex
456 // file in the profile) and profile_index (the index of the dex file in the
457 // profile) fields in this struct because we can infer them from
458 // profile_key_map_ and info_. However, it makes the profiles logic much
459 // simpler if we have references here as well.
Calin Juravle798ba162017-05-23 23:01:53 -0700460 struct DexFileData : public DeletableArenaObject<kArenaAllocProfile> {
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100461 DexFileData(ArenaAllocator* allocator,
Calin Juravlecc3171a2017-05-19 16:47:53 -0700462 const std::string& key,
463 uint32_t location_checksum,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700464 uint16_t index,
465 uint32_t num_methods)
Vladimir Marko69d310e2017-10-09 14:12:23 +0100466 : allocator_(allocator),
Calin Juravlecc3171a2017-05-19 16:47:53 -0700467 profile_key(key),
468 profile_index(index),
469 checksum(location_checksum),
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100470 method_map(std::less<uint16_t>(), allocator->Adapter(kArenaAllocProfile)),
471 class_set(std::less<dex::TypeIndex>(), allocator->Adapter(kArenaAllocProfile)),
Mathieu Chartierea650f32017-05-24 12:04:13 -0700472 num_method_ids(num_methods),
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100473 bitmap_storage(allocator->Adapter(kArenaAllocProfile)) {
Calin Juravled9f4d642018-01-24 20:33:00 -0800474 bitmap_storage.resize(ComputeBitmapStorage(num_method_ids));
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700475 if (!bitmap_storage.empty()) {
476 method_bitmap =
Calin Juravled9f4d642018-01-24 20:33:00 -0800477 BitMemoryRegion(MemoryRegion(
478 &bitmap_storage[0], bitmap_storage.size()), 0, ComputeBitmapBits(num_method_ids));
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700479 }
Mathieu Chartierea650f32017-05-24 12:04:13 -0700480 }
481
Calin Juravled9f4d642018-01-24 20:33:00 -0800482 static size_t ComputeBitmapBits(uint32_t num_method_ids) {
483 return num_method_ids * kBitmapIndexCount;
484 }
485 static size_t ComputeBitmapStorage(uint32_t num_method_ids) {
486 return RoundUp(ComputeBitmapBits(num_method_ids), kBitsPerByte) / kBitsPerByte;
487 }
488
Mathieu Chartierea650f32017-05-24 12:04:13 -0700489 bool operator==(const DexFileData& other) const {
490 return checksum == other.checksum && method_map == other.method_map;
491 }
492
493 // Mark a method as executed at least once.
Calin Juravle1ad1e3f2017-09-19 18:20:37 -0700494 bool AddMethod(MethodHotness::Flag flags, size_t index);
Calin Juravlecc3171a2017-05-19 16:47:53 -0700495
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700496 void MergeBitmap(const DexFileData& other) {
497 DCHECK_EQ(bitmap_storage.size(), other.bitmap_storage.size());
498 for (size_t i = 0; i < bitmap_storage.size(); ++i) {
499 bitmap_storage[i] |= other.bitmap_storage[i];
500 }
501 }
502
Calin Juravleee9cb412018-02-13 20:32:35 -0800503 void SetMethodHotness(size_t index, MethodHotness::Flag flags);
Mathieu Chartiere46f3a82017-06-19 19:54:12 -0700504 MethodHotness GetHotnessInfo(uint32_t dex_method_index) const;
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700505
Vladimir Marko69d310e2017-10-09 14:12:23 +0100506 // The allocator used to allocate new inline cache maps.
507 ArenaAllocator* const allocator_;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700508 // The profile key this data belongs to.
509 std::string profile_key;
510 // The profile index of this dex file (matches ClassReference#dex_profile_index).
Calin Juravle940eb0c2017-01-30 19:30:44 -0800511 uint8_t profile_index;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700512 // The dex checksum.
Calin Juravle998c2162015-12-21 15:39:33 +0200513 uint32_t checksum;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700514 // The methonds' profile information.
Calin Juravle940eb0c2017-01-30 19:30:44 -0800515 MethodMap method_map;
516 // The classes which have been profiled. Note that these don't necessarily include
517 // all the classes that can be found in the inline caches reference.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700518 ArenaSet<dex::TypeIndex> class_set;
Calin Juravlecc3171a2017-05-19 16:47:53 -0700519 // Find the inline caches of the the given method index. Add an empty entry if
520 // no previous data is found.
521 InlineCacheMap* FindOrAddMethod(uint16_t method_index);
Mathieu Chartierea650f32017-05-24 12:04:13 -0700522 // Num method ids.
523 uint32_t num_method_ids;
524 ArenaVector<uint8_t> bitmap_storage;
525 BitMemoryRegion method_bitmap;
526
Mathieu Chartierea650f32017-05-24 12:04:13 -0700527 private:
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700528 enum BitmapIndex {
Mathieu Chartierdb40eac2017-06-09 18:34:11 -0700529 kBitmapIndexStartup,
530 kBitmapIndexPostStartup,
531 kBitmapIndexCount,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700532 };
533
534 size_t MethodBitIndex(bool startup, size_t index) const {
535 DCHECK_LT(index, num_method_ids);
Mathieu Chartiercebf99c2017-06-05 11:06:52 -0700536 // The format is [startup bitmap][post startup bitmap]
537 // This compresses better than ([startup bit][post statup bit])*
538
539 return index + (startup
Mathieu Chartierdb40eac2017-06-09 18:34:11 -0700540 ? kBitmapIndexStartup * num_method_ids
541 : kBitmapIndexPostStartup * num_method_ids);
Mathieu Chartierea650f32017-05-24 12:04:13 -0700542 }
Calin Juravle998c2162015-12-21 15:39:33 +0200543 };
Calin Juravle226501b2015-12-11 14:41:31 +0000544
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700545 // Return the profile data for the given profile key or null if the dex location
Calin Juravle940eb0c2017-01-30 19:30:44 -0800546 // already exists but has a different checksum
Mathieu Chartierea650f32017-05-24 12:04:13 -0700547 DexFileData* GetOrAddDexFileData(const std::string& profile_key,
548 uint32_t checksum,
549 uint32_t num_method_ids);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800550
Mathieu Chartierea650f32017-05-24 12:04:13 -0700551 DexFileData* GetOrAddDexFileData(const DexFile* dex_file) {
552 return GetOrAddDexFileData(GetProfileDexFileKey(dex_file->GetLocation()),
553 dex_file->GetLocationChecksum(),
554 dex_file->NumMethodIds());
555 }
Calin Juravle940eb0c2017-01-30 19:30:44 -0800556
557 // Add a method to the profile using its offline representation.
558 // This is mostly used to facilitate testing.
559 bool AddMethod(const std::string& dex_location,
560 uint32_t dex_checksum,
561 uint16_t method_index,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700562 uint32_t num_method_ids,
Calin Juravleee9cb412018-02-13 20:32:35 -0800563 const OfflineProfileMethodInfo& pmi,
564 MethodHotness::Flag flags);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800565
566 // Add a class index to the profile.
Mathieu Chartierea650f32017-05-24 12:04:13 -0700567 bool AddClassIndex(const std::string& dex_location,
568 uint32_t checksum,
569 dex::TypeIndex type_idx,
570 uint32_t num_method_ids);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800571
572 // Add all classes from the given dex cache to the the profile.
Calin Juravle99629622016-04-19 16:33:46 +0100573 bool AddResolvedClasses(const DexCacheResolvedClasses& classes);
Calin Juravle64142952016-03-21 14:37:55 +0000574
Calin Juravle940eb0c2017-01-30 19:30:44 -0800575 // Encode the known dex_files into a vector. The index of a dex_reference will
576 // be the same as the profile index of the dex file (used to encode the ClassReferences).
577 void DexFileToProfileIndex(/*out*/std::vector<DexReference>* dex_references) const;
578
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700579 // Return the dex data associated with the given profile key or null if the profile
580 // doesn't contain the key.
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700581 const DexFileData* FindDexData(const std::string& profile_key,
582 uint32_t checksum,
583 bool verify_checksum = true) const;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700584
Mathieu Chartierdb40eac2017-06-09 18:34:11 -0700585 // Return the dex data associated with the given dex file or null if the profile doesn't contain
586 // the key or the checksum mismatches.
587 const DexFileData* FindDexData(const DexFile* dex_file) const;
588
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700589 // Checks if the profile is empty.
590 bool IsEmpty() const;
591
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700592 // Inflate the input buffer (in_buffer) of size in_size. It returns a buffer of
593 // compressed data for the input buffer of "compressed_data_size" size.
594 std::unique_ptr<uint8_t[]> DeflateBuffer(const uint8_t* in_buffer,
595 uint32_t in_size,
596 /*out*/uint32_t* compressed_data_size);
597
598 // Inflate the input buffer(in_buffer) of size in_size. out_size is the expected output
599 // size of the buffer. It puts the output in out_buffer. It returns Z_STREAM_END on
600 // success. On error, it returns Z_STREAM_ERROR if the compressed data is inconsistent
601 // and Z_DATA_ERROR if the stream ended prematurely or the stream has extra data.
602 int InflateBuffer(const uint8_t* in_buffer,
603 uint32_t in_size,
604 uint32_t out_size,
605 /*out*/uint8_t* out_buffer);
606
Calin Juravle64142952016-03-21 14:37:55 +0000607 // Parsing functionality.
608
Calin Juravle940eb0c2017-01-30 19:30:44 -0800609 // The information present in the header of each profile line.
Calin Juravle64142952016-03-21 14:37:55 +0000610 struct ProfileLineHeader {
611 std::string dex_location;
Calin Juravle64142952016-03-21 14:37:55 +0000612 uint16_t class_set_size;
Calin Juravle940eb0c2017-01-30 19:30:44 -0800613 uint32_t method_region_size_bytes;
Calin Juravle64142952016-03-21 14:37:55 +0000614 uint32_t checksum;
Mathieu Chartierea650f32017-05-24 12:04:13 -0700615 uint32_t num_method_ids;
Calin Juravle64142952016-03-21 14:37:55 +0000616 };
617
Calin Juravle1e2de642018-01-18 01:08:23 -0800618 /**
619 * Encapsulate the source of profile data for loading.
620 * The source can be either a plain file or a zip file.
621 * For zip files, the profile entry will be extracted to
622 * the memory map.
623 */
624 class ProfileSource {
625 public:
626 /**
627 * Create a profile source for the given fd. The ownership of the fd
628 * remains to the caller; as this class will not attempt to close it at any
629 * point.
630 */
631 static ProfileSource* Create(int32_t fd) {
632 DCHECK_GT(fd, -1);
633 return new ProfileSource(fd, /*map*/ nullptr);
634 }
635
636 /**
637 * Create a profile source backed by a memory map. The map can be null in
638 * which case it will the treated as an empty source.
639 */
640 static ProfileSource* Create(std::unique_ptr<MemMap>&& mem_map) {
641 return new ProfileSource(/*fd*/ -1, std::move(mem_map));
642 }
643
644 /**
645 * Read bytes from this source.
646 * Reading will advance the current source position so subsequent
647 * invocations will read from the las position.
648 */
Calin Juravle36060d12018-01-19 16:28:38 -0800649 ProfileLoadStatus Read(uint8_t* buffer,
650 size_t byte_count,
651 const std::string& debug_stage,
652 std::string* error);
Calin Juravle1e2de642018-01-18 01:08:23 -0800653
654 /** Return true if the source has 0 data. */
655 bool HasEmptyContent() const;
656 /** Return true if all the information from this source has been read. */
657 bool HasConsumedAllData() const;
658
659 private:
660 ProfileSource(int32_t fd, std::unique_ptr<MemMap>&& mem_map)
661 : fd_(fd), mem_map_(std::move(mem_map)), mem_map_cur_(0) {}
662
663 bool IsMemMap() const { return fd_ == -1; }
664
665 int32_t fd_; // The fd is not owned by this class.
666 std::unique_ptr<MemMap> mem_map_;
667 size_t mem_map_cur_; // Current position in the map to read from.
668 };
669
Calin Juravle64142952016-03-21 14:37:55 +0000670 // A helper structure to make sure we don't read past our buffers in the loops.
671 struct SafeBuffer {
672 public:
673 explicit SafeBuffer(size_t size) : storage_(new uint8_t[size]) {
674 ptr_current_ = storage_.get();
675 ptr_end_ = ptr_current_ + size;
676 }
677
678 // Reads the content of the descriptor at the current position.
Calin Juravle36060d12018-01-19 16:28:38 -0800679 ProfileLoadStatus Fill(ProfileSource& source,
680 const std::string& debug_stage,
681 /*out*/std::string* error);
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700682
Calin Juravle64142952016-03-21 14:37:55 +0000683 // Reads an uint value (high bits to low bits) and advances the current pointer
684 // with the number of bits read.
Calin Juravle940eb0c2017-01-30 19:30:44 -0800685 template <typename T> bool ReadUintAndAdvance(/*out*/ T* value);
Calin Juravle64142952016-03-21 14:37:55 +0000686
687 // Compares the given data with the content current pointer. If the contents are
688 // equal it advances the current pointer by data_size.
689 bool CompareAndAdvance(const uint8_t* data, size_t data_size);
690
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700691 // Advances current pointer by data_size.
692 void Advance(size_t data_size);
693
694 // Returns the count of unread bytes.
695 size_t CountUnreadBytes();
696
697 // Returns the current pointer.
698 const uint8_t* GetCurrentPtr();
Calin Juravle940eb0c2017-01-30 19:30:44 -0800699
Calin Juravle64142952016-03-21 14:37:55 +0000700 // Get the underlying raw buffer.
701 uint8_t* Get() { return storage_.get(); }
702
703 private:
Andreas Gampe7b8a2652016-11-11 17:11:25 -0800704 std::unique_ptr<uint8_t[]> storage_;
Calin Juravle64142952016-03-21 14:37:55 +0000705 uint8_t* ptr_end_;
Shubham Ajmera4f0a15a2017-04-26 19:26:46 -0700706 uint8_t* ptr_current_;
Calin Juravle64142952016-03-21 14:37:55 +0000707 };
708
Calin Juravle36060d12018-01-19 16:28:38 -0800709 ProfileLoadStatus OpenSource(int32_t fd,
710 /*out*/ std::unique_ptr<ProfileSource>* source,
711 /*out*/ std::string* error);
Calin Juravle1e2de642018-01-18 01:08:23 -0800712
Calin Juravled9f4d642018-01-24 20:33:00 -0800713 // Entry point for profile loading functionality.
714 ProfileLoadStatus LoadInternal(
715 int32_t fd,
716 std::string* error,
717 bool merge_classes = true,
718 const ProfileLoadFilterFn& filter_fn = ProfileFilterFnAcceptAll);
Calin Juravle64142952016-03-21 14:37:55 +0000719
Calin Juravle940eb0c2017-01-30 19:30:44 -0800720 // Read the profile header from the given fd and store the number of profile
721 // lines into number_of_dex_files.
Calin Juravle36060d12018-01-19 16:28:38 -0800722 ProfileLoadStatus ReadProfileHeader(ProfileSource& source,
723 /*out*/uint8_t* number_of_dex_files,
724 /*out*/uint32_t* size_uncompressed_data,
725 /*out*/uint32_t* size_compressed_data,
726 /*out*/std::string* error);
Calin Juravle64142952016-03-21 14:37:55 +0000727
Calin Juravle940eb0c2017-01-30 19:30:44 -0800728 // Read the header of a profile line from the given fd.
Calin Juravle36060d12018-01-19 16:28:38 -0800729 ProfileLoadStatus ReadProfileLineHeader(SafeBuffer& buffer,
730 /*out*/ProfileLineHeader* line_header,
731 /*out*/std::string* error);
Calin Juravle940eb0c2017-01-30 19:30:44 -0800732
733 // Read individual elements from the profile line header.
734 bool ReadProfileLineHeaderElements(SafeBuffer& buffer,
735 /*out*/uint16_t* dex_location_size,
736 /*out*/ProfileLineHeader* line_header,
737 /*out*/std::string* error);
738
739 // Read a single profile line from the given fd.
Calin Juravle36060d12018-01-19 16:28:38 -0800740 ProfileLoadStatus ReadProfileLine(SafeBuffer& buffer,
741 uint8_t number_of_dex_files,
742 const ProfileLineHeader& line_header,
743 const SafeMap<uint8_t, uint8_t>& dex_profile_index_remap,
744 bool merge_classes,
745 /*out*/std::string* error);
Calin Juravle64142952016-03-21 14:37:55 +0000746
Calin Juravle940eb0c2017-01-30 19:30:44 -0800747 // Read all the classes from the buffer into the profile `info_` structure.
748 bool ReadClasses(SafeBuffer& buffer,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800749 const ProfileLineHeader& line_header,
750 /*out*/std::string* error);
751
752 // Read all the methods from the buffer into the profile `info_` structure.
753 bool ReadMethods(SafeBuffer& buffer,
754 uint8_t number_of_dex_files,
755 const ProfileLineHeader& line_header,
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700756 const SafeMap<uint8_t, uint8_t>& dex_profile_index_remap,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800757 /*out*/std::string* error);
758
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700759 // The method generates mapping of profile indices while merging a new profile
760 // data into current data. It returns true, if the mapping was successful.
761 bool RemapProfileIndex(const std::vector<ProfileLineHeader>& profile_line_headers,
Calin Juravled9f4d642018-01-24 20:33:00 -0800762 const ProfileLoadFilterFn& filter_fn,
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700763 /*out*/SafeMap<uint8_t, uint8_t>* dex_profile_index_remap);
764
Calin Juravle940eb0c2017-01-30 19:30:44 -0800765 // Read the inline cache encoding from line_bufer into inline_cache.
766 bool ReadInlineCache(SafeBuffer& buffer,
767 uint8_t number_of_dex_files,
Shubham Ajmeraafbbf182017-08-04 14:33:34 -0700768 const SafeMap<uint8_t, uint8_t>& dex_profile_index_remap,
Calin Juravle940eb0c2017-01-30 19:30:44 -0800769 /*out*/InlineCacheMap* inline_cache,
770 /*out*/std::string* error);
771
772 // Encode the inline cache into the given buffer.
773 void AddInlineCacheToBuffer(std::vector<uint8_t>* buffer,
774 const InlineCacheMap& inline_cache);
775
776 // Return the number of bytes needed to encode the profile information
777 // for the methods in dex_data.
778 uint32_t GetMethodsRegionSize(const DexFileData& dex_data);
779
780 // Group `classes` by their owning dex profile index and put the result in
781 // `dex_to_classes_map`.
782 void GroupClassesByDex(
783 const ClassSet& classes,
784 /*out*/SafeMap<uint8_t, std::vector<dex::TypeIndex>>* dex_to_classes_map);
Mathieu Chartierc5dd3192015-12-09 16:38:30 -0800785
Calin Juravlecc3171a2017-05-19 16:47:53 -0700786 // Find the data for the dex_pc in the inline cache. Adds an empty entry
787 // if no previous data exists.
788 DexPcData* FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc);
789
Calin Juravle877fd962016-01-05 14:29:29 +0000790 friend class ProfileCompilationInfoTest;
791 friend class CompilerDriverProfileTest;
792 friend class ProfileAssistantTest;
Jeff Hao41fba6a2016-11-28 11:53:33 -0800793 friend class Dex2oatLayoutTest;
Calin Juravle877fd962016-01-05 14:29:29 +0000794
Calin Juravlee6f87cc2017-05-24 17:41:05 -0700795 ArenaPool default_arena_pool_;
Vladimir Markoca6fff82017-10-03 14:49:14 +0100796 ArenaAllocator allocator_;
Calin Juravlecc3171a2017-05-19 16:47:53 -0700797
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700798 // Vector containing the actual profile info.
799 // The vector index is the profile index of the dex data and
800 // matched DexFileData::profile_index.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700801 ArenaVector<DexFileData*> info_;
Calin Juravlecea9e9d2017-03-23 19:04:59 -0700802
803 // Cache mapping profile keys to profile index.
804 // This is used to speed up searches since it avoids iterating
805 // over the info_ vector when searching by profile key.
Calin Juravlecc3171a2017-05-19 16:47:53 -0700806 ArenaSafeMap<const std::string, uint8_t> profile_key_map_;
Calin Juravle226501b2015-12-11 14:41:31 +0000807};
808
Calin Juravle31f2c152015-10-23 17:56:15 +0100809} // namespace art
810
Calin Juravle33083d62017-01-18 15:29:12 -0800811#endif // ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_