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