• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #ifndef ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_
18 #define ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_
19 
20 #include <set>
21 #include <vector>
22 
23 #include "atomic.h"
24 #include "base/arena_object.h"
25 #include "base/arena_containers.h"
26 #include "bit_memory_region.h"
27 #include "dex_cache_resolved_classes.h"
28 #include "dex_file.h"
29 #include "dex_file_types.h"
30 #include "method_reference.h"
31 #include "safe_map.h"
32 #include "type_reference.h"
33 
34 namespace art {
35 
36 /**
37  *  Convenient class to pass around profile information (including inline caches)
38  *  without the need to hold GC-able objects.
39  */
40 struct ProfileMethodInfo {
41   struct ProfileInlineCache {
ProfileInlineCacheProfileMethodInfo::ProfileInlineCache42     ProfileInlineCache(uint32_t pc,
43                        bool missing_types,
44                        const std::vector<TypeReference>& profile_classes)
45         : dex_pc(pc), is_missing_types(missing_types), classes(profile_classes) {}
46 
47     const uint32_t dex_pc;
48     const bool is_missing_types;
49     const std::vector<TypeReference> classes;
50   };
51 
ProfileMethodInfoProfileMethodInfo52   explicit ProfileMethodInfo(MethodReference reference) : ref(reference) {}
53 
ProfileMethodInfoProfileMethodInfo54   ProfileMethodInfo(MethodReference reference, const std::vector<ProfileInlineCache>& caches)
55       : ref(reference),
56         inline_caches(caches) {}
57 
58   MethodReference ref;
59   std::vector<ProfileInlineCache> inline_caches;
60 };
61 
62 /**
63  * Profile information in a format suitable to be queried by the compiler and
64  * performing profile guided compilation.
65  * It is a serialize-friendly format based on information collected by the
66  * interpreter (ProfileInfo).
67  * Currently it stores only the hot compiled methods.
68  */
69 class ProfileCompilationInfo {
70  public:
71   static const uint8_t kProfileMagic[];
72   static const uint8_t kProfileVersion[];
73 
74   // Data structures for encoding the offline representation of inline caches.
75   // This is exposed as public in order to make it available to dex2oat compilations
76   // (see compiler/optimizing/inliner.cc).
77 
78   // A dex location together with its checksum.
79   struct DexReference {
DexReferenceDexReference80     DexReference() : dex_checksum(0), num_method_ids(0) {}
81 
DexReferenceDexReference82     DexReference(const std::string& location, uint32_t checksum, uint32_t num_methods)
83         : dex_location(location), dex_checksum(checksum), num_method_ids(num_methods) {}
84 
85     bool operator==(const DexReference& other) const {
86       return dex_checksum == other.dex_checksum &&
87           dex_location == other.dex_location &&
88           num_method_ids == other.num_method_ids;
89     }
90 
MatchesDexDexReference91     bool MatchesDex(const DexFile* dex_file) const {
92       return dex_checksum == dex_file->GetLocationChecksum() &&
93            dex_location == GetProfileDexFileKey(dex_file->GetLocation());
94     }
95 
96     std::string dex_location;
97     uint32_t dex_checksum;
98     uint32_t num_method_ids;
99   };
100 
101   // Encodes a class reference in the profile.
102   // The owning dex file is encoded as the index (dex_profile_index) it has in the
103   // profile rather than as a full DexRefence(location,checksum).
104   // This avoids excessive string copying when managing the profile data.
105   // The dex_profile_index is an index in either of:
106   //  - OfflineProfileMethodInfo#dex_references vector (public use)
107   //  - DexFileData#profile_index (internal use).
108   // Note that the dex_profile_index is not necessary the multidex index.
109   // We cannot rely on the actual multidex index because a single profile may store
110   // data from multiple splits. This means that a profile may contain a classes2.dex from split-A
111   // and one from split-B.
112   struct ClassReference : public ValueObject {
ClassReferenceClassReference113     ClassReference(uint8_t dex_profile_idx, const dex::TypeIndex type_idx) :
114       dex_profile_index(dex_profile_idx), type_index(type_idx) {}
115 
116     bool operator==(const ClassReference& other) const {
117       return dex_profile_index == other.dex_profile_index && type_index == other.type_index;
118     }
119     bool operator<(const ClassReference& other) const {
120       return dex_profile_index == other.dex_profile_index
121           ? type_index < other.type_index
122           : dex_profile_index < other.dex_profile_index;
123     }
124 
125     uint8_t dex_profile_index;  // the index of the owning dex in the profile info
126     dex::TypeIndex type_index;  // the type index of the class
127   };
128 
129   // The set of classes that can be found at a given dex pc.
130   using ClassSet = ArenaSet<ClassReference>;
131 
132   // Encodes the actual inline cache for a given dex pc (whether or not the receiver is
133   // megamorphic and its possible types).
134   // If the receiver is megamorphic or is missing types the set of classes will be empty.
135   struct DexPcData : public ArenaObject<kArenaAllocProfile> {
DexPcDataDexPcData136     explicit DexPcData(ArenaAllocator* arena)
137         : is_missing_types(false),
138           is_megamorphic(false),
139           classes(std::less<ClassReference>(), arena->Adapter(kArenaAllocProfile)) {}
140     void AddClass(uint16_t dex_profile_idx, const dex::TypeIndex& type_idx);
SetIsMegamorphicDexPcData141     void SetIsMegamorphic() {
142       if (is_missing_types) return;
143       is_megamorphic = true;
144       classes.clear();
145     }
SetIsMissingTypesDexPcData146     void SetIsMissingTypes() {
147       is_megamorphic = false;
148       is_missing_types = true;
149       classes.clear();
150     }
151     bool operator==(const DexPcData& other) const {
152       return is_megamorphic == other.is_megamorphic &&
153           is_missing_types == other.is_missing_types &&
154           classes == other.classes;
155     }
156 
157     // Not all runtime types can be encoded in the profile. For example if the receiver
158     // type is in a dex file which is not tracked for profiling its type cannot be
159     // encoded. When types are missing this field will be set to true.
160     bool is_missing_types;
161     bool is_megamorphic;
162     ClassSet classes;
163   };
164 
165   // The inline cache map: DexPc -> DexPcData.
166   using InlineCacheMap = ArenaSafeMap<uint16_t, DexPcData>;
167 
168   // Maps a method dex index to its inline cache.
169   using MethodMap = ArenaSafeMap<uint16_t, InlineCacheMap>;
170 
171   // Profile method hotness information for a single method. Also includes a pointer to the inline
172   // cache map.
173   class MethodHotness {
174    public:
175     enum Flag {
176       kFlagHot = 0x1,
177       kFlagStartup = 0x2,
178       kFlagPostStartup = 0x4,
179     };
180 
IsHot()181     bool IsHot() const {
182       return (flags_ & kFlagHot) != 0;
183     }
184 
IsStartup()185     bool IsStartup() const {
186       return (flags_ & kFlagStartup) != 0;
187     }
188 
IsPostStartup()189     bool IsPostStartup() const {
190       return (flags_ & kFlagPostStartup) != 0;
191     }
192 
AddFlag(Flag flag)193     void AddFlag(Flag flag) {
194       flags_ |= flag;
195     }
196 
GetFlags()197     uint8_t GetFlags() const {
198       return flags_;
199     }
200 
IsInProfile()201     bool IsInProfile() const {
202       return flags_ != 0;
203     }
204 
205    private:
206     const InlineCacheMap* inline_cache_map_ = nullptr;
207     uint8_t flags_ = 0;
208 
GetInlineCacheMap()209     const InlineCacheMap* GetInlineCacheMap() const {
210       return inline_cache_map_;
211     }
212 
SetInlineCacheMap(const InlineCacheMap * info)213     void SetInlineCacheMap(const InlineCacheMap* info) {
214       inline_cache_map_ = info;
215     }
216 
217     friend class ProfileCompilationInfo;
218   };
219 
220   // Encodes the full set of inline caches for a given method.
221   // The dex_references vector is indexed according to the ClassReference::dex_profile_index.
222   // i.e. the dex file of any ClassReference present in the inline caches can be found at
223   // dex_references[ClassReference::dex_profile_index].
224   struct OfflineProfileMethodInfo {
OfflineProfileMethodInfoOfflineProfileMethodInfo225     explicit OfflineProfileMethodInfo(const InlineCacheMap* inline_cache_map)
226         : inline_caches(inline_cache_map) {}
227 
228     bool operator==(const OfflineProfileMethodInfo& other) const;
229 
230     const InlineCacheMap* const inline_caches;
231     std::vector<DexReference> dex_references;
232   };
233 
234   // Public methods to create, extend or query the profile.
235   ProfileCompilationInfo();
236   explicit ProfileCompilationInfo(ArenaPool* arena_pool);
237 
238   ~ProfileCompilationInfo();
239 
240   // Add the given methods to the current profile object.
241   bool AddMethods(const std::vector<ProfileMethodInfo>& methods);
242 
243   // Add the given classes to the current profile object.
244   bool AddClasses(const std::set<DexCacheResolvedClasses>& resolved_classes);
245 
246   // Add multiple type ids for classes in a single dex file. Iterator is for type_ids not
247   // class_defs.
248   template <class Iterator>
AddClassesForDex(const DexFile * dex_file,Iterator index_begin,Iterator index_end)249   bool AddClassesForDex(const DexFile* dex_file, Iterator index_begin, Iterator index_end) {
250     DexFileData* data = GetOrAddDexFileData(dex_file);
251     if (data == nullptr) {
252       return false;
253     }
254     data->class_set.insert(index_begin, index_end);
255     return true;
256   }
257 
258   // Add a method index to the profile (without inline caches). The method flags determine if it is
259   // hot, startup, or post startup, or a combination of the previous.
260   bool AddMethodIndex(MethodHotness::Flag flags,
261                       const std::string& dex_location,
262                       uint32_t checksum,
263                       uint16_t method_idx,
264                       uint32_t num_method_ids);
265   bool AddMethodIndex(MethodHotness::Flag flags, const MethodReference& ref);
266 
267   // Add a method to the profile using its online representation (containing runtime structures).
268   bool AddMethod(const ProfileMethodInfo& pmi);
269 
270   // Bulk add sampled methods and/or hot methods for a single dex, fast since it only has one
271   // GetOrAddDexFileData call.
272   template <class Iterator>
AddMethodsForDex(MethodHotness::Flag flags,const DexFile * dex_file,Iterator index_begin,Iterator index_end)273   bool AddMethodsForDex(MethodHotness::Flag flags,
274                         const DexFile* dex_file,
275                         Iterator index_begin,
276                         Iterator index_end) {
277     DexFileData* data = GetOrAddDexFileData(dex_file);
278     if (data == nullptr) {
279       return false;
280     }
281     for (Iterator it = index_begin; it != index_end; ++it) {
282       DCHECK_LT(*it, data->num_method_ids);
283       if (!data->AddMethod(flags, *it)) {
284         return false;
285       }
286     }
287     return true;
288   }
289 
290   // Add hotness flags for a simple method.
291   bool AddMethodHotness(const MethodReference& method_ref, const MethodHotness& hotness);
292 
293   // Load profile information from the given file descriptor.
294   // If the current profile is non-empty the load will fail.
295   bool Load(int fd);
296 
297   // Load profile information from the given file
298   // If the current profile is non-empty the load will fail.
299   // If clear_if_invalid is true and the file is invalid the method clears the
300   // the file and returns true.
301   bool Load(const std::string& filename, bool clear_if_invalid);
302 
303   // Merge the data from another ProfileCompilationInfo into the current object. Only merges
304   // classes if merge_classes is true. This is used for creating the boot profile since
305   // we don't want all of the classes to be image classes.
306   bool MergeWith(const ProfileCompilationInfo& info, bool merge_classes = true);
307 
308   // Save the profile data to the given file descriptor.
309   bool Save(int fd);
310 
311   // Save the current profile into the given file. The file will be cleared before saving.
312   bool Save(const std::string& filename, uint64_t* bytes_written);
313 
314   // Return the number of methods that were profiled.
315   uint32_t GetNumberOfMethods() const;
316 
317   // Return the number of resolved classes that were profiled.
318   uint32_t GetNumberOfResolvedClasses() const;
319 
320   // Returns the profile method info for a given method reference.
321   MethodHotness GetMethodHotness(const MethodReference& method_ref) const;
322   MethodHotness GetMethodHotness(const std::string& dex_location,
323                                  uint32_t dex_checksum,
324                                  uint16_t dex_method_index) const;
325 
326   // Return true if the class's type is present in the profiling info.
327   bool ContainsClass(const DexFile& dex_file, dex::TypeIndex type_idx) const;
328 
329   // Return the method data for the given location and index from the profiling info.
330   // If the method index is not found or the checksum doesn't match, null is returned.
331   // Note: the inline cache map is a pointer to the map stored in the profile and
332   // its allocation will go away if the profile goes out of scope.
333   std::unique_ptr<OfflineProfileMethodInfo> GetMethod(const std::string& dex_location,
334                                                       uint32_t dex_checksum,
335                                                       uint16_t dex_method_index) const;
336 
337   // Dump all the loaded profile info into a string and returns it.
338   // If dex_files is not null then the method indices will be resolved to their
339   // names.
340   // This is intended for testing and debugging.
341   std::string DumpInfo(const std::vector<std::unique_ptr<const DexFile>>* dex_files,
342                        bool print_full_dex_location = true) const;
343   std::string DumpInfo(const std::vector<const DexFile*>* dex_files,
344                        bool print_full_dex_location = true) const;
345 
346   // Return the classes and methods for a given dex file through out args. The out args are the set
347   // of class as well as the methods and their associated inline caches. Returns true if the dex
348   // file is register and has a matching checksum, false otherwise.
349   bool GetClassesAndMethods(const DexFile& dex_file,
350                             /*out*/std::set<dex::TypeIndex>* class_set,
351                             /*out*/std::set<uint16_t>* hot_method_set,
352                             /*out*/std::set<uint16_t>* startup_method_set,
353                             /*out*/std::set<uint16_t>* post_startup_method_method_set) const;
354 
355   // Perform an equality test with the `other` profile information.
356   bool Equals(const ProfileCompilationInfo& other);
357 
358   // Return the class descriptors for all of the classes in the profiles' class sets.
359   std::set<DexCacheResolvedClasses> GetResolvedClasses(
360       const std::vector<const DexFile*>& dex_files_) const;
361 
362   // Return the profile key associated with the given dex location.
363   static std::string GetProfileDexFileKey(const std::string& dex_location);
364 
365   // Generate a test profile which will contain a percentage of the total maximum
366   // number of methods and classes (method_ratio and class_ratio).
367   static bool GenerateTestProfile(int fd,
368                                   uint16_t number_of_dex_files,
369                                   uint16_t method_ratio,
370                                   uint16_t class_ratio,
371                                   uint32_t random_seed);
372 
373   // Generate a test profile which will randomly contain classes and methods from
374   // the provided list of dex files.
375   static bool GenerateTestProfile(int fd,
376                                   std::vector<std::unique_ptr<const DexFile>>& dex_files,
377                                   uint32_t random_seed);
378 
379   // Check that the given profile method info contain the same data.
380   static bool Equals(const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi1,
381                      const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi2);
382 
GetArena()383   ArenaAllocator* GetArena() { return &arena_; }
384 
385   // Return all of the class descriptors in the profile for a set of dex files.
386   std::unordered_set<std::string> GetClassDescriptors(const std::vector<const DexFile*>& dex_files);
387 
388  private:
389   enum ProfileLoadSatus {
390     kProfileLoadWouldOverwiteData,
391     kProfileLoadIOError,
392     kProfileLoadVersionMismatch,
393     kProfileLoadBadData,
394     kProfileLoadSuccess
395   };
396 
397   const uint32_t kProfileSizeWarningThresholdInBytes = 500000U;
398   const uint32_t kProfileSizeErrorThresholdInBytes = 1000000U;
399 
400   // Internal representation of the profile information belonging to a dex file.
401   // Note that we could do without profile_key (the key used to encode the dex
402   // file in the profile) and profile_index (the index of the dex file in the
403   // profile) fields in this struct because we can infer them from
404   // profile_key_map_ and info_. However, it makes the profiles logic much
405   // simpler if we have references here as well.
406   struct DexFileData : public DeletableArenaObject<kArenaAllocProfile> {
DexFileDataDexFileData407     DexFileData(ArenaAllocator* arena,
408                 const std::string& key,
409                 uint32_t location_checksum,
410                 uint16_t index,
411                 uint32_t num_methods)
412         : arena_(arena),
413           profile_key(key),
414           profile_index(index),
415           checksum(location_checksum),
416           method_map(std::less<uint16_t>(), arena->Adapter(kArenaAllocProfile)),
417           class_set(std::less<dex::TypeIndex>(), arena->Adapter(kArenaAllocProfile)),
418           num_method_ids(num_methods),
419           bitmap_storage(arena->Adapter(kArenaAllocProfile)) {
420       const size_t num_bits = num_method_ids * kBitmapIndexCount;
421       bitmap_storage.resize(RoundUp(num_bits, kBitsPerByte) / kBitsPerByte);
422       if (!bitmap_storage.empty()) {
423         method_bitmap =
424             BitMemoryRegion(MemoryRegion(&bitmap_storage[0], bitmap_storage.size()), 0, num_bits);
425       }
426     }
427 
428     bool operator==(const DexFileData& other) const {
429       return checksum == other.checksum && method_map == other.method_map;
430     }
431 
432     // Mark a method as executed at least once.
433     bool AddMethod(MethodHotness::Flag flags, size_t index);
434 
MergeBitmapDexFileData435     void MergeBitmap(const DexFileData& other) {
436       DCHECK_EQ(bitmap_storage.size(), other.bitmap_storage.size());
437       for (size_t i = 0; i < bitmap_storage.size(); ++i) {
438         bitmap_storage[i] |= other.bitmap_storage[i];
439       }
440     }
441 
442     MethodHotness GetHotnessInfo(uint32_t dex_method_index) const;
443 
444     // The arena used to allocate new inline cache maps.
445     ArenaAllocator* arena_;
446     // The profile key this data belongs to.
447     std::string profile_key;
448     // The profile index of this dex file (matches ClassReference#dex_profile_index).
449     uint8_t profile_index;
450     // The dex checksum.
451     uint32_t checksum;
452     // The methonds' profile information.
453     MethodMap method_map;
454     // The classes which have been profiled. Note that these don't necessarily include
455     // all the classes that can be found in the inline caches reference.
456     ArenaSet<dex::TypeIndex> class_set;
457     // Find the inline caches of the the given method index. Add an empty entry if
458     // no previous data is found.
459     InlineCacheMap* FindOrAddMethod(uint16_t method_index);
460     // Num method ids.
461     uint32_t num_method_ids;
462     ArenaVector<uint8_t> bitmap_storage;
463     BitMemoryRegion method_bitmap;
464 
465    private:
466     enum BitmapIndex {
467       kBitmapIndexStartup,
468       kBitmapIndexPostStartup,
469       kBitmapIndexCount,
470     };
471 
MethodBitIndexDexFileData472     size_t MethodBitIndex(bool startup, size_t index) const {
473       DCHECK_LT(index, num_method_ids);
474       // The format is [startup bitmap][post startup bitmap]
475       // This compresses better than ([startup bit][post statup bit])*
476 
477       return index + (startup
478           ? kBitmapIndexStartup * num_method_ids
479           : kBitmapIndexPostStartup * num_method_ids);
480     }
481   };
482 
483   // Return the profile data for the given profile key or null if the dex location
484   // already exists but has a different checksum
485   DexFileData* GetOrAddDexFileData(const std::string& profile_key,
486                                    uint32_t checksum,
487                                    uint32_t num_method_ids);
488 
GetOrAddDexFileData(const DexFile * dex_file)489   DexFileData* GetOrAddDexFileData(const DexFile* dex_file) {
490     return GetOrAddDexFileData(GetProfileDexFileKey(dex_file->GetLocation()),
491                                dex_file->GetLocationChecksum(),
492                                dex_file->NumMethodIds());
493   }
494 
495   // Add a method to the profile using its offline representation.
496   // This is mostly used to facilitate testing.
497   bool AddMethod(const std::string& dex_location,
498                  uint32_t dex_checksum,
499                  uint16_t method_index,
500                  uint32_t num_method_ids,
501                  const OfflineProfileMethodInfo& pmi);
502 
503   // Add a class index to the profile.
504   bool AddClassIndex(const std::string& dex_location,
505                      uint32_t checksum,
506                      dex::TypeIndex type_idx,
507                      uint32_t num_method_ids);
508 
509   // Add all classes from the given dex cache to the the profile.
510   bool AddResolvedClasses(const DexCacheResolvedClasses& classes);
511 
512   // Encode the known dex_files into a vector. The index of a dex_reference will
513   // be the same as the profile index of the dex file (used to encode the ClassReferences).
514   void DexFileToProfileIndex(/*out*/std::vector<DexReference>* dex_references) const;
515 
516   // Return the dex data associated with the given profile key or null if the profile
517   // doesn't contain the key.
518   const DexFileData* FindDexData(const std::string& profile_key,
519                                  uint32_t checksum,
520                                  bool verify_checksum = true) const;
521 
522   // Return the dex data associated with the given dex file or null if the profile doesn't contain
523   // the key or the checksum mismatches.
524   const DexFileData* FindDexData(const DexFile* dex_file) const;
525 
526   // Checks if the profile is empty.
527   bool IsEmpty() const;
528 
529   // Inflate the input buffer (in_buffer) of size in_size. It returns a buffer of
530   // compressed data for the input buffer of "compressed_data_size" size.
531   std::unique_ptr<uint8_t[]> DeflateBuffer(const uint8_t* in_buffer,
532                                            uint32_t in_size,
533                                            /*out*/uint32_t* compressed_data_size);
534 
535   // Inflate the input buffer(in_buffer) of size in_size. out_size is the expected output
536   // size of the buffer. It puts the output in out_buffer. It returns Z_STREAM_END on
537   // success. On error, it returns Z_STREAM_ERROR if the compressed data is inconsistent
538   // and Z_DATA_ERROR if the stream ended prematurely or the stream has extra data.
539   int InflateBuffer(const uint8_t* in_buffer,
540                     uint32_t in_size,
541                     uint32_t out_size,
542                     /*out*/uint8_t* out_buffer);
543 
544   // Parsing functionality.
545 
546   // The information present in the header of each profile line.
547   struct ProfileLineHeader {
548     std::string dex_location;
549     uint16_t class_set_size;
550     uint32_t method_region_size_bytes;
551     uint32_t checksum;
552     uint32_t num_method_ids;
553   };
554 
555   // A helper structure to make sure we don't read past our buffers in the loops.
556   struct SafeBuffer {
557    public:
SafeBufferSafeBuffer558     explicit SafeBuffer(size_t size) : storage_(new uint8_t[size]) {
559       ptr_current_ = storage_.get();
560       ptr_end_ = ptr_current_ + size;
561     }
562 
563     // Reads the content of the descriptor at the current position.
564     ProfileLoadSatus FillFromFd(int fd,
565                                 const std::string& source,
566                                 /*out*/std::string* error);
567 
568     ProfileLoadSatus FillFromBuffer(uint8_t* buffer_ptr,
569                                     const std::string& source,
570                                     /*out*/std::string* error);
571 
572     // Reads an uint value (high bits to low bits) and advances the current pointer
573     // with the number of bits read.
574     template <typename T> bool ReadUintAndAdvance(/*out*/ T* value);
575 
576     // Compares the given data with the content current pointer. If the contents are
577     // equal it advances the current pointer by data_size.
578     bool CompareAndAdvance(const uint8_t* data, size_t data_size);
579 
580     // Advances current pointer by data_size.
581     void Advance(size_t data_size);
582 
583     // Returns the count of unread bytes.
584     size_t CountUnreadBytes();
585 
586     // Returns the current pointer.
587     const uint8_t* GetCurrentPtr();
588 
589     // Get the underlying raw buffer.
GetSafeBuffer590     uint8_t* Get() { return storage_.get(); }
591 
592    private:
593     std::unique_ptr<uint8_t[]> storage_;
594     uint8_t* ptr_end_;
595     uint8_t* ptr_current_;
596   };
597 
598   // Entry point for profile loding functionality.
599   ProfileLoadSatus LoadInternal(int fd, std::string* error);
600 
601   // Read the profile header from the given fd and store the number of profile
602   // lines into number_of_dex_files.
603   ProfileLoadSatus ReadProfileHeader(int fd,
604                                      /*out*/uint8_t* number_of_dex_files,
605                                      /*out*/uint32_t* size_uncompressed_data,
606                                      /*out*/uint32_t* size_compressed_data,
607                                      /*out*/std::string* error);
608 
609   // Read the header of a profile line from the given fd.
610   ProfileLoadSatus ReadProfileLineHeader(SafeBuffer& buffer,
611                                          /*out*/ProfileLineHeader* line_header,
612                                          /*out*/std::string* error);
613 
614   // Read individual elements from the profile line header.
615   bool ReadProfileLineHeaderElements(SafeBuffer& buffer,
616                                      /*out*/uint16_t* dex_location_size,
617                                      /*out*/ProfileLineHeader* line_header,
618                                      /*out*/std::string* error);
619 
620   // Read a single profile line from the given fd.
621   ProfileLoadSatus ReadProfileLine(SafeBuffer& buffer,
622                                    uint8_t number_of_dex_files,
623                                    const ProfileLineHeader& line_header,
624                                    /*out*/std::string* error);
625 
626   // Read all the classes from the buffer into the profile `info_` structure.
627   bool ReadClasses(SafeBuffer& buffer,
628                    const ProfileLineHeader& line_header,
629                    /*out*/std::string* error);
630 
631   // Read all the methods from the buffer into the profile `info_` structure.
632   bool ReadMethods(SafeBuffer& buffer,
633                    uint8_t number_of_dex_files,
634                    const ProfileLineHeader& line_header,
635                    /*out*/std::string* error);
636 
637   // Read the inline cache encoding from line_bufer into inline_cache.
638   bool ReadInlineCache(SafeBuffer& buffer,
639                        uint8_t number_of_dex_files,
640                        /*out*/InlineCacheMap* inline_cache,
641                        /*out*/std::string* error);
642 
643   // Encode the inline cache into the given buffer.
644   void AddInlineCacheToBuffer(std::vector<uint8_t>* buffer,
645                               const InlineCacheMap& inline_cache);
646 
647   // Return the number of bytes needed to encode the profile information
648   // for the methods in dex_data.
649   uint32_t GetMethodsRegionSize(const DexFileData& dex_data);
650 
651   // Group `classes` by their owning dex profile index and put the result in
652   // `dex_to_classes_map`.
653   void GroupClassesByDex(
654       const ClassSet& classes,
655       /*out*/SafeMap<uint8_t, std::vector<dex::TypeIndex>>* dex_to_classes_map);
656 
657   // Find the data for the dex_pc in the inline cache. Adds an empty entry
658   // if no previous data exists.
659   DexPcData* FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc);
660 
661   friend class ProfileCompilationInfoTest;
662   friend class CompilerDriverProfileTest;
663   friend class ProfileAssistantTest;
664   friend class Dex2oatLayoutTest;
665 
666   ArenaPool default_arena_pool_;
667   ArenaAllocator arena_;
668 
669   // Vector containing the actual profile info.
670   // The vector index is the profile index of the dex data and
671   // matched DexFileData::profile_index.
672   ArenaVector<DexFileData*> info_;
673 
674   // Cache mapping profile keys to profile index.
675   // This is used to speed up searches since it avoids iterating
676   // over the info_ vector when searching by profile key.
677   ArenaSafeMap<const std::string, uint8_t> profile_key_map_;
678 };
679 
680 }  // namespace art
681 
682 #endif  // ART_RUNTIME_JIT_PROFILE_COMPILATION_INFO_H_
683