/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "profile_compilation_info.h"

#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <zlib.h>

#include <algorithm>
#include <cerrno>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <random>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "android-base/file.h"
#include "android-base/properties.h"
#include "android-base/scopeguard.h"
#include "android-base/strings.h"
#include "android-base/unique_fd.h"
#include "base/arena_allocator.h"
#include "base/bit_utils.h"
#include "base/dumpable.h"
#include "base/file_utils.h"
#include "base/globals.h"
#include "base/logging.h"  // For VLOG.
#include "base/malloc_arena_pool.h"
#include "base/os.h"
#include "base/safe_map.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "base/zip_archive.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file_loader.h"

#ifdef ART_TARGET_ANDROID
#include "android-modules-utils/sdk_level.h"
#endif

namespace art {

const uint8_t ProfileCompilationInfo::kProfileMagic[] = { 'p', 'r', 'o', '\0' };
// Last profile version: New extensible profile format.
const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '1', '5', '\0' };
const uint8_t ProfileCompilationInfo::kProfileVersionForBootImage[] = { '0', '1', '6', '\0' };

static_assert(sizeof(ProfileCompilationInfo::kProfileVersion) == 4,
              "Invalid profile version size");
static_assert(sizeof(ProfileCompilationInfo::kProfileVersionForBootImage) == 4,
              "Invalid profile version size");

// The name of the profile entry in the dex metadata file.
// DO NOT CHANGE THIS! (it's similar to classes.dex in the apk files).
const char ProfileCompilationInfo::kDexMetadataProfileEntry[] = "primary.prof";

// A synthetic annotations that can be used to denote that no annotation should
// be associated with the profile samples. We use the empty string for the package name
// because that's an invalid package name and should never occur in practice.
const ProfileCompilationInfo::ProfileSampleAnnotation
  ProfileCompilationInfo::ProfileSampleAnnotation::kNone =
      ProfileCompilationInfo::ProfileSampleAnnotation("");

static constexpr char kSampleMetadataSeparator = ':';

// Note: This used to be PATH_MAX (usually 4096) but that seems excessive
// and we do not want to rely on that external constant anyway.
static constexpr uint16_t kMaxDexFileKeyLength = 1024;

// Extra descriptors are serialized with a `uint16_t` prefix. This defines the length limit.
static constexpr size_t kMaxExtraDescriptorLength = std::numeric_limits<uint16_t>::max();

// According to dex file specification, there can be more than 2^16 valid method indexes
// but bytecode uses only 16 bits, so higher method indexes are not very useful (though
// such methods could be reached through virtual or interface dispatch). Consequently,
// dex files with more than 2^16 method indexes are not really used and the profile file
// format does not support higher method indexes.
static constexpr uint32_t kMaxSupportedMethodIndex = 0xffffu;

// Debug flag to ignore checksums when testing if a method or a class is present in the profile.
// Used to facilitate testing profile guided compilation across a large number of apps
// using the same test profile.
static constexpr bool kDebugIgnoreChecksum = false;

static constexpr uint8_t kIsMissingTypesEncoding = 6;
static constexpr uint8_t kIsMegamorphicEncoding = 7;

static_assert(sizeof(ProfileCompilationInfo::kIndividualInlineCacheSize) == sizeof(uint8_t),
              "InlineCache::kIndividualInlineCacheSize does not have the expect type size");
static_assert(ProfileCompilationInfo::kIndividualInlineCacheSize < kIsMegamorphicEncoding,
              "InlineCache::kIndividualInlineCacheSize is larger than expected");
static_assert(ProfileCompilationInfo::kIndividualInlineCacheSize < kIsMissingTypesEncoding,
              "InlineCache::kIndividualInlineCacheSize is larger than expected");

static constexpr uint32_t kSizeWarningThresholdBytes = 500000U;
static constexpr uint32_t kSizeErrorThresholdBytes = 1500000U;

static constexpr uint32_t kSizeWarningThresholdBootBytes = 25000000U;
static constexpr uint32_t kSizeErrorThresholdBootBytes = 100000000U;

static bool ChecksumMatch(uint32_t dex_file_checksum, uint32_t checksum) {
  return kDebugIgnoreChecksum || dex_file_checksum == checksum;
}

namespace {

// Deflate the input buffer `in_buffer`. It returns a buffer of
// compressed data for the input buffer of `*compressed_data_size` size.
std::unique_ptr<uint8_t[]> DeflateBuffer(ArrayRef<const uint8_t> in_buffer,
                                         /*out*/ uint32_t* compressed_data_size) {
  z_stream strm;
  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  int init_ret = deflateInit(&strm, 1);
  if (init_ret != Z_OK) {
    return nullptr;
  }

  uint32_t out_size = dchecked_integral_cast<uint32_t>(deflateBound(&strm, in_buffer.size()));

  std::unique_ptr<uint8_t[]> compressed_buffer(new uint8_t[out_size]);
  strm.avail_in = in_buffer.size();
  strm.next_in = const_cast<uint8_t*>(in_buffer.data());
  strm.avail_out = out_size;
  strm.next_out = &compressed_buffer[0];
  int ret = deflate(&strm, Z_FINISH);
  if (ret == Z_STREAM_ERROR) {
    return nullptr;
  }
  *compressed_data_size = out_size - strm.avail_out;

  int end_ret = deflateEnd(&strm);
  if (end_ret != Z_OK) {
    return nullptr;
  }

  return compressed_buffer;
}

// Inflate the data from `in_buffer` into `out_buffer`. The `out_buffer.size()`
// is the expected output size of the buffer. It returns Z_STREAM_END on success.
// On error, it returns Z_STREAM_ERROR if the compressed data is inconsistent
// and Z_DATA_ERROR if the stream ended prematurely or the stream has extra data.
int InflateBuffer(ArrayRef<const uint8_t> in_buffer, /*out*/ ArrayRef<uint8_t> out_buffer) {
  /* allocate inflate state */
  z_stream strm;
  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  strm.avail_in = in_buffer.size();
  strm.next_in = const_cast<uint8_t*>(in_buffer.data());
  strm.avail_out = out_buffer.size();
  strm.next_out = out_buffer.data();

  int init_ret = inflateInit(&strm);
  if (init_ret != Z_OK) {
    return init_ret;
  }

  int ret = inflate(&strm, Z_NO_FLUSH);
  if (strm.avail_in != 0 || strm.avail_out != 0) {
    return Z_DATA_ERROR;
  }

  int end_ret = inflateEnd(&strm);
  if (end_ret != Z_OK) {
    return end_ret;
  }

  return ret;
}

}  // anonymous namespace

enum class ProfileCompilationInfo::ProfileLoadStatus : uint32_t {
  kSuccess,
  kIOError,
  kBadMagic,
  kVersionMismatch,
  kBadData,
  kMergeError,  // Merging failed. There are too many extra descriptors
                // or classes without TypeId referenced by a dex file.
};

enum class ProfileCompilationInfo::FileSectionType : uint32_t {
  // The values of section enumerators and data format for individual sections
  // must not be changed without changing the profile file version. New sections
  // can be added at the end and they shall be ignored by old versions of ART.

  // The list of the dex files included in the profile.
  // There must be exactly one dex file section and it must be first.
  kDexFiles = 0,

  // Extra descriptors for referencing classes that do not have a `dex::TypeId`
  // in the referencing dex file, such as classes from a different dex file
  // (even outside of the dex files in the profile) or array classes that were
  // used from other dex files or created through reflection.
  kExtraDescriptors = 1,

  // Classes included in the profile.
  kClasses = 2,

  // Methods included in the profile, their hotness flags and inline caches.
  kMethods = 3,

  // The aggregation counts of the profile, classes and methods. This section is
  // an optional reserved section not implemented on client yet.
  kAggregationCounts = 4,

  // The number of known sections.
  kNumberOfSections = 5
};

class ProfileCompilationInfo::FileSectionInfo {
 public:
  // Constructor for reading from a `ProfileSource`. Data shall be filled from the source.
  FileSectionInfo() {}

  // Constructor for writing to a file.
  FileSectionInfo(FileSectionType type,
                  uint32_t file_offset,
                  uint32_t file_size,
                  uint32_t inflated_size)
      : type_(type),
        file_offset_(file_offset),
        file_size_(file_size),
        inflated_size_(inflated_size) {}

  void SetFileOffset(uint32_t file_offset) {
    DCHECK_EQ(file_offset_, 0u);
    DCHECK_NE(file_offset, 0u);
    file_offset_ = file_offset;
  }

  FileSectionType GetType() const {
    return type_;
  }

  uint32_t GetFileOffset() const {
    return file_offset_;
  }

  uint32_t GetFileSize() const {
    return file_size_;
  }

  uint32_t GetInflatedSize() const {
    return inflated_size_;
  }

  uint32_t GetMemSize() const {
    return inflated_size_ != 0u ? inflated_size_ : file_size_;
  }

 private:
  FileSectionType type_;
  uint32_t file_offset_;
  uint32_t file_size_;
  uint32_t inflated_size_;  // If 0, do not inflate and use data from file directly.
};

// The file header.
class ProfileCompilationInfo::FileHeader {
 public:
  // Constructor for reading from a `ProfileSource`. Data shall be filled from the source.
  FileHeader() {
    DCHECK(!IsValid());
  }

  // Constructor for writing to a file.
  FileHeader(const uint8_t* version, uint32_t file_section_count)
      : file_section_count_(file_section_count) {
    static_assert(sizeof(magic_) == sizeof(kProfileMagic));
    static_assert(sizeof(version_) == sizeof(kProfileVersion));
    static_assert(sizeof(version_) == sizeof(kProfileVersionForBootImage));
    memcpy(magic_, kProfileMagic, sizeof(kProfileMagic));
    memcpy(version_, version, sizeof(version_));
    DCHECK_LE(file_section_count, kMaxFileSectionCount);
    DCHECK(IsValid());
  }

  bool IsValid() const {
    return memcmp(magic_, kProfileMagic, sizeof(kProfileMagic)) == 0 &&
           (memcmp(version_, kProfileVersion, kProfileVersionSize) == 0 ||
            memcmp(version_, kProfileVersionForBootImage, kProfileVersionSize) == 0) &&
           file_section_count_ != 0u &&  // The dex files section is mandatory.
           file_section_count_ <= kMaxFileSectionCount;
  }

  const uint8_t* GetVersion() const {
    DCHECK(IsValid());
    return version_;
  }

  ProfileLoadStatus InvalidHeaderMessage(/*out*/ std::string* error_msg) const;

  uint32_t GetFileSectionCount() const {
    DCHECK(IsValid());
    return file_section_count_;
  }

 private:
  // The upper bound for file section count is used to ensure that there
  // shall be no arithmetic overflow when calculating size of the header
  // with section information.
  static const uint32_t kMaxFileSectionCount;

  uint8_t magic_[4] = {0, 0, 0, 0};
  uint8_t version_[4] = {0, 0, 0, 0};
  uint32_t file_section_count_ = 0u;
};

const uint32_t ProfileCompilationInfo::FileHeader::kMaxFileSectionCount =
    (std::numeric_limits<uint32_t>::max() - sizeof(FileHeader)) / sizeof(FileSectionInfo);

ProfileCompilationInfo::ProfileLoadStatus
ProfileCompilationInfo::FileHeader::InvalidHeaderMessage(/*out*/ std::string* error_msg) const {
  if (memcmp(magic_, kProfileMagic, sizeof(kProfileMagic)) != 0) {
    *error_msg = "Profile missing magic.";
    return ProfileLoadStatus::kBadMagic;
  }
  if (memcmp(version_, kProfileVersion, sizeof(kProfileVersion)) != 0 &&
      memcmp(version_, kProfileVersion, sizeof(kProfileVersionForBootImage)) != 0) {
    *error_msg = "Profile version mismatch.";
    return ProfileLoadStatus::kVersionMismatch;
  }
  if (file_section_count_ == 0u) {
    *error_msg = "Missing mandatory dex files section.";
    return ProfileLoadStatus::kBadData;
  }
  DCHECK_GT(file_section_count_, kMaxFileSectionCount);
  *error_msg ="Too many sections.";
  return ProfileLoadStatus::kBadData;
}

/**
 * Encapsulate the source of profile data for loading.
 * The source can be either a plain file or a zip file.
 * For zip files, the profile entry will be extracted to
 * the memory map.
 */
class ProfileCompilationInfo::ProfileSource {
 public:
  /**
   * Create a profile source for the given fd. The ownership of the fd
   * remains to the caller; as this class will not attempt to close it at any
   * point.
   */
  static ProfileSource* Create(int32_t fd) {
    DCHECK_GT(fd, -1);
    return new ProfileSource(fd, MemMap::Invalid());
  }

  /**
   * Create a profile source backed by a memory map. The map can be null in
   * which case it will the treated as an empty source.
   */
  static ProfileSource* Create(MemMap&& mem_map) {
    return new ProfileSource(/*fd*/ -1, std::move(mem_map));
  }

  // Seek to the given offset in the source.
  bool Seek(off_t offset);

  /**
   * Read bytes from this source.
   * Reading will advance the current source position so subsequent
   * invocations will read from the las position.
   */
  ProfileLoadStatus Read(void* buffer,
                         size_t byte_count,
                         const std::string& debug_stage,
                         std::string* error);

  /** Return true if the source has 0 data. */
  bool HasEmptyContent() const;

 private:
  ProfileSource(int32_t fd, MemMap&& mem_map)
      : fd_(fd), mem_map_(std::move(mem_map)), mem_map_cur_(0) {}

  bool IsMemMap() const {
    return fd_ == -1;
  }

  int32_t fd_;  // The fd is not owned by this class.
  MemMap mem_map_;
  size_t mem_map_cur_;  // Current position in the map to read from.
};

// A helper structure to make sure we don't read past our buffers in the loops.
// Also used for writing but the buffer should be pre-sized correctly for that, so we
// DCHECK() we do not write beyond the end, rather than returning `false` on failure.
class ProfileCompilationInfo::SafeBuffer {
 public:
  SafeBuffer()
      : storage_(nullptr),
        ptr_current_(nullptr),
        ptr_end_(nullptr) {}

  explicit SafeBuffer(size_t size)
      : storage_(new uint8_t[size]),
        ptr_current_(storage_.get()),
        ptr_end_(ptr_current_ + size) {}

  // Reads an uint value and advances the current pointer.
  template <typename T>
  bool ReadUintAndAdvance(/*out*/ T* value) {
    static_assert(std::is_unsigned<T>::value, "Type is not unsigned");
    if (sizeof(T) > GetAvailableBytes()) {
      return false;
    }
    *value = 0;
    for (size_t i = 0; i < sizeof(T); i++) {
      *value += ptr_current_[i] << (i * kBitsPerByte);
    }
    ptr_current_ += sizeof(T);
    return true;
  }

  // Reads a length-prefixed string as `std::string_view` and advances the current pointer.
  // The length is `uint16_t`.
  bool ReadStringAndAdvance(/*out*/ std::string_view* value) {
    uint16_t length;
    if (!ReadUintAndAdvance(&length)) {
      return false;
    }
    if (length > GetAvailableBytes()) {
      return false;
    }
    const void* null_char = memchr(GetCurrentPtr(), 0, length);
    if (null_char != nullptr) {
      // Embedded nulls are invalid.
      return false;
    }
    *value = std::string_view(reinterpret_cast<const char*>(GetCurrentPtr()), length);
    Advance(length);
    return true;
  }

  // Compares the given data with the content at the current pointer.
  // If the contents are equal it advances the current pointer by data_size.
  bool CompareAndAdvance(const uint8_t* data, size_t data_size) {
    if (data_size > GetAvailableBytes()) {
      return false;
    }
    if (memcmp(ptr_current_, data, data_size) == 0) {
      ptr_current_ += data_size;
      return true;
    }
    return false;
  }

  void WriteAndAdvance(const void* data, size_t data_size) {
    DCHECK_LE(data_size, GetAvailableBytes());
    memcpy(ptr_current_, data, data_size);
    ptr_current_ += data_size;
  }

  template <typename T>
  void WriteUintAndAdvance(T value) {
    static_assert(std::is_integral_v<T>);
    WriteAndAdvance(&value, sizeof(value));
  }

  // Deflate a filled buffer. Replaces the internal buffer with a new one, also filled.
  bool Deflate() {
    DCHECK_EQ(GetAvailableBytes(), 0u);
    DCHECK_NE(Size(), 0u);
    ArrayRef<const uint8_t> in_buffer(Get(), Size());
    uint32_t output_size = 0;
    std::unique_ptr<uint8_t[]> compressed_buffer = DeflateBuffer(in_buffer, &output_size);
    if (compressed_buffer == nullptr) {
      return false;
    }
    storage_ = std::move(compressed_buffer);
    ptr_current_ = storage_.get() + output_size;
    ptr_end_ = ptr_current_;
    return true;
  }

  // Inflate an unread buffer. Replaces the internal buffer with a new one, also unread.
  bool Inflate(size_t uncompressed_data_size) {
    DCHECK(ptr_current_ == storage_.get());
    DCHECK_NE(Size(), 0u);
    ArrayRef<const uint8_t> in_buffer(Get(), Size());
    SafeBuffer uncompressed_buffer(uncompressed_data_size);
    ArrayRef<uint8_t> out_buffer(uncompressed_buffer.Get(), uncompressed_data_size);
    int ret = InflateBuffer(in_buffer, out_buffer);
    if (ret != Z_STREAM_END) {
      return false;
    }
    Swap(uncompressed_buffer);
    DCHECK(ptr_current_ == storage_.get());
    return true;
  }

  // Advances current pointer by data_size.
  void Advance(size_t data_size) {
    DCHECK_LE(data_size, GetAvailableBytes());
    ptr_current_ += data_size;
  }

  // Returns the count of unread bytes.
  size_t GetAvailableBytes() const {
    DCHECK_LE(static_cast<void*>(ptr_current_), static_cast<void*>(ptr_end_));
    return (ptr_end_ - ptr_current_) * sizeof(*ptr_current_);
  }

  // Returns the current pointer.
  uint8_t* GetCurrentPtr() {
    return ptr_current_;
  }

  // Get the underlying raw buffer.
  uint8_t* Get() {
    return storage_.get();
  }

  // Get the size of the raw buffer.
  size_t Size() const {
    return ptr_end_ - storage_.get();
  }

  void Swap(SafeBuffer& other) {
    std::swap(storage_, other.storage_);
    std::swap(ptr_current_, other.ptr_current_);
    std::swap(ptr_end_, other.ptr_end_);
  }

 private:
  std::unique_ptr<uint8_t[]> storage_;
  uint8_t* ptr_current_;
  uint8_t* ptr_end_;
};

ProfileCompilationInfo::ProfileCompilationInfo(ArenaPool* custom_arena_pool, bool for_boot_image)
    : default_arena_pool_(),
      allocator_(custom_arena_pool),
      info_(allocator_.Adapter(kArenaAllocProfile)),
      profile_key_map_(std::less<const std::string_view>(), allocator_.Adapter(kArenaAllocProfile)),
      extra_descriptors_(),
      extra_descriptors_indexes_(ExtraDescriptorHash(&extra_descriptors_),
                                 ExtraDescriptorEquals(&extra_descriptors_)) {
  memcpy(version_,
         for_boot_image ? kProfileVersionForBootImage : kProfileVersion,
         kProfileVersionSize);
}

ProfileCompilationInfo::ProfileCompilationInfo(ArenaPool* custom_arena_pool)
    : ProfileCompilationInfo(custom_arena_pool, /*for_boot_image=*/ false) { }

ProfileCompilationInfo::ProfileCompilationInfo()
    : ProfileCompilationInfo(/*for_boot_image=*/ false) { }

ProfileCompilationInfo::ProfileCompilationInfo(bool for_boot_image)
    : ProfileCompilationInfo(&default_arena_pool_, for_boot_image) { }

ProfileCompilationInfo::~ProfileCompilationInfo() {
  VLOG(profiler) << Dumpable<MemStats>(allocator_.GetMemStats());
}

void ProfileCompilationInfo::DexPcData::AddClass(const dex::TypeIndex& type_idx) {
  if (is_megamorphic || is_missing_types) {
    return;
  }

  // Perform an explicit lookup for the type instead of directly emplacing the
  // element. We do this because emplace() allocates the node before doing the
  // lookup and if it then finds an identical element, it shall deallocate the
  // node. For Arena allocations, that's essentially a leak.
  auto lb = classes.lower_bound(type_idx);
  if (lb != classes.end() && *lb == type_idx) {
    // The type index exists.
    return;
  }

  // Check if the adding the type will cause the cache to become megamorphic.
  if (classes.size() + 1 >= ProfileCompilationInfo::kIndividualInlineCacheSize) {
    is_megamorphic = true;
    classes.clear();
    return;
  }

  // The type does not exist and the inline cache will not be megamorphic.
  classes.emplace_hint(lb, type_idx);
}

// Transform the actual dex location into a key used to index the dex file in the profile.
// See ProfileCompilationInfo#GetProfileDexFileBaseKey as well.
std::string ProfileCompilationInfo::GetProfileDexFileAugmentedKey(
      const std::string& dex_location,
      const ProfileSampleAnnotation& annotation) {
  std::string base_key = GetProfileDexFileBaseKey(dex_location);
  return annotation == ProfileSampleAnnotation::kNone
      ? base_key
      : base_key + kSampleMetadataSeparator + annotation.GetOriginPackageName();;
}

// Transform the actual dex location into a base profile key (represented as relative paths).
// Note: this is OK because we don't store profiles of different apps into the same file.
// Apps with split apks don't cause trouble because each split has a different name and will not
// collide with other entries.
std::string_view ProfileCompilationInfo::GetProfileDexFileBaseKeyView(
    std::string_view dex_location) {
  DCHECK(!dex_location.empty());
  size_t last_sep_index = dex_location.find_last_of('/');
  if (last_sep_index == std::string::npos) {
    return dex_location;
  } else {
    DCHECK(last_sep_index < dex_location.size());
    return dex_location.substr(last_sep_index + 1);
  }
}

std::string ProfileCompilationInfo::GetProfileDexFileBaseKey(const std::string& dex_location) {
  // Note: Conversions between std::string and std::string_view.
  return std::string(GetProfileDexFileBaseKeyView(dex_location));
}

std::string_view ProfileCompilationInfo::GetBaseKeyViewFromAugmentedKey(
    std::string_view profile_key) {
  size_t pos = profile_key.rfind(kSampleMetadataSeparator);
  return (pos == std::string::npos) ? profile_key : profile_key.substr(0, pos);
}

std::string ProfileCompilationInfo::GetBaseKeyFromAugmentedKey(
    const std::string& profile_key) {
  // Note: Conversions between std::string and std::string_view.
  return std::string(GetBaseKeyViewFromAugmentedKey(profile_key));
}

std::string ProfileCompilationInfo::MigrateAnnotationInfo(
    const std::string& base_key,
    const std::string& augmented_key) {
  size_t pos = augmented_key.rfind(kSampleMetadataSeparator);
  return (pos == std::string::npos)
      ? base_key
      : base_key + augmented_key.substr(pos);
}

ProfileCompilationInfo::ProfileSampleAnnotation ProfileCompilationInfo::GetAnnotationFromKey(
     const std::string& augmented_key) {
  size_t pos = augmented_key.rfind(kSampleMetadataSeparator);
  return (pos == std::string::npos)
      ? ProfileSampleAnnotation::kNone
      : ProfileSampleAnnotation(augmented_key.substr(pos + 1));
}

bool ProfileCompilationInfo::AddMethods(const std::vector<ProfileMethodInfo>& methods,
                                        MethodHotness::Flag flags,
                                        const ProfileSampleAnnotation& annotation) {
  for (const ProfileMethodInfo& method : methods) {
    if (!AddMethod(method, flags, annotation)) {
      return false;
    }
  }
  return true;
}

dex::TypeIndex ProfileCompilationInfo::FindOrCreateTypeIndex(const DexFile& dex_file,
                                                             TypeReference class_ref) {
  DCHECK(class_ref.dex_file != nullptr);
  DCHECK_LT(class_ref.TypeIndex().index_, class_ref.dex_file->NumTypeIds());
  if (class_ref.dex_file == &dex_file) {
    // We can use the type index from the `class_ref` as it's a valid index in the `dex_file`.
    return class_ref.TypeIndex();
  }
  // Try to find a `TypeId` in the method's dex file.
  const char* descriptor = class_ref.dex_file->StringByTypeIdx(class_ref.TypeIndex());
  return FindOrCreateTypeIndex(dex_file, descriptor);
}

dex::TypeIndex ProfileCompilationInfo::FindOrCreateTypeIndex(const DexFile& dex_file,
                                                             const char* descriptor) {
  const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
  if (type_id != nullptr) {
    return dex_file.GetIndexForTypeId(*type_id);
  }
  // Try to find an existing extra descriptor.
  uint32_t num_type_ids = dex_file.NumTypeIds();
  uint32_t max_artificial_ids = DexFile::kDexNoIndex16 - num_type_ids;
  std::string_view descriptor_view(descriptor);
  // Check descriptor length for "extra descriptor". We are using `uint16_t` as prefix.
  if (UNLIKELY(descriptor_view.size() > kMaxExtraDescriptorLength)) {
    return dex::TypeIndex();  // Invalid.
  }
  auto it = extra_descriptors_indexes_.find(descriptor_view);
  if (it != extra_descriptors_indexes_.end()) {
    return (*it < max_artificial_ids) ? dex::TypeIndex(num_type_ids + *it) : dex::TypeIndex();
  }
  // Check if inserting the extra descriptor yields a valid artificial type index.
  if (UNLIKELY(extra_descriptors_.size() >= max_artificial_ids)) {
    return dex::TypeIndex();  // Invalid.
  }
  // Add the descriptor to extra descriptors and return the artificial type index.
  ExtraDescriptorIndex new_extra_descriptor_index = AddExtraDescriptor(descriptor_view);
  DCHECK_LT(new_extra_descriptor_index, max_artificial_ids);
  return dex::TypeIndex(num_type_ids + new_extra_descriptor_index);
}

bool ProfileCompilationInfo::AddClass(const DexFile& dex_file,
                                      const char* descriptor,
                                      const ProfileSampleAnnotation& annotation) {
  DexFileData* const data = GetOrAddDexFileData(&dex_file, annotation);
  if (data == nullptr) {  // checksum mismatch
    return false;
  }
  dex::TypeIndex type_index = FindOrCreateTypeIndex(dex_file, descriptor);
  if (!type_index.IsValid()) {
    return false;
  }
  data->class_set.insert(type_index);
  return true;
}

bool ProfileCompilationInfo::MergeWith(const std::string& filename) {
  std::string error;
#ifdef _WIN32
  int flags = O_RDONLY;
#else
  int flags = O_RDONLY | O_NOFOLLOW | O_CLOEXEC;
#endif
  ScopedFlock profile_file =
      LockedFile::Open(filename.c_str(), flags, /*block=*/false, &error);

  if (profile_file.get() == nullptr) {
    LOG(WARNING) << "Couldn't lock the profile file " << filename << ": " << error;
    return false;
  }

  int fd = profile_file->Fd();

  ProfileLoadStatus status = LoadInternal(fd, &error);
  if (status == ProfileLoadStatus::kSuccess) {
    return true;
  }

  LOG(WARNING) << "Could not load profile data from file " << filename << ": " << error;
  return false;
}

bool ProfileCompilationInfo::Load(const std::string& filename, bool clear_if_invalid) {
  ScopedTrace trace(__PRETTY_FUNCTION__);
  std::string error;

  if (!IsEmpty()) {
    return false;
  }

#ifdef _WIN32
  int flags = O_RDWR;
#else
  int flags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
#endif
  // There's no need to fsync profile data right away. We get many chances
  // to write it again in case something goes wrong. We can rely on a simple
  // close(), no sync, and let to the kernel decide when to write to disk.
  ScopedFlock profile_file =
      LockedFile::Open(filename.c_str(), flags, /*block=*/false, &error);

  if (profile_file.get() == nullptr) {
    if (clear_if_invalid && errno == ENOENT) {
      return true;
    }
    LOG(WARNING) << "Couldn't lock the profile file " << filename << ": " << error;
    return false;
  }

  int fd = profile_file->Fd();

  ProfileLoadStatus status = LoadInternal(fd, &error);
  if (status == ProfileLoadStatus::kSuccess) {
    return true;
  }

  if (clear_if_invalid &&
      ((status == ProfileLoadStatus::kBadMagic) ||
       (status == ProfileLoadStatus::kVersionMismatch) ||
       (status == ProfileLoadStatus::kBadData))) {
    LOG(WARNING) << "Clearing bad or obsolete profile data from file "
                 << filename << ": " << error;
    // When ART Service is enabled, this is the only place where we mutate a profile in place.
    // TODO(jiakaiz): Get rid of this.
    if (profile_file->ClearContent()) {
      return true;
    } else {
      PLOG(WARNING) << "Could not clear profile file: " << filename;
      return false;
    }
  }

  LOG(WARNING) << "Could not load profile data from file " << filename << ": " << error;
  return false;
}

bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_written) {
  ScopedTrace trace(__PRETTY_FUNCTION__);

#ifndef ART_TARGET_ANDROID
  return SaveFallback(filename, bytes_written);
#else
  // Prior to U, SELinux policy doesn't allow apps to create profile files.
  // Additionally, when installd is being used for dexopt, it acquires a flock when working on a
  // profile. It's unclear to us whether the flock means that the file at the fd shouldn't change or
  // that the file at the path shouldn't change, especially when the installd code is modified by
  // partners. Therefore, we fall back to using a flock as well just to be safe.
  if (!android::modules::sdklevel::IsAtLeastU() ||
      !android::base::GetBoolProperty("dalvik.vm.useartservice", /*default_value=*/false)) {
    return SaveFallback(filename, bytes_written);
  }

  std::string tmp_filename = filename + ".XXXXXX.tmp";
  // mkstemps creates the file with permissions 0600, which is the desired permissions, so there's
  // no need to chmod.
  android::base::unique_fd fd(mkostemps(tmp_filename.data(), /*suffixlen=*/4, O_CLOEXEC));
  if (fd.get() < 0) {
    PLOG(WARNING) << "Failed to create temp profile file for " << filename;
    return false;
  }

  // In case anything goes wrong.
  auto remove_tmp_file = android::base::make_scope_guard([&]() {
    if (unlink(tmp_filename.c_str()) != 0) {
      PLOG(WARNING) << "Failed to remove temp profile file " << tmp_filename;
    }
  });

  bool result = Save(fd.get());
  if (!result) {
    VLOG(profiler) << "Failed to save profile info to temp profile file " << tmp_filename;
    return false;
  }

  fd.reset();

  // Move the temp profile file to the final location.
  if (rename(tmp_filename.c_str(), filename.c_str()) != 0) {
    PLOG(WARNING) << "Failed to commit profile file " << filename;
    return false;
  }

  remove_tmp_file.Disable();

  int64_t size = OS::GetFileSizeBytes(filename.c_str());
  if (size != -1) {
    VLOG(profiler) << "Successfully saved profile info to " << filename << " Size: " << size;
    if (bytes_written != nullptr) {
      *bytes_written = static_cast<uint64_t>(size);
    }
  } else {
    VLOG(profiler) << "Saved profile info to " << filename
                   << " but failed to get size: " << strerror(errno);
  }

  return true;
#endif
}

bool ProfileCompilationInfo::SaveFallback(const std::string& filename, uint64_t* bytes_written) {
  std::string error;
#ifdef _WIN32
  int flags = O_WRONLY | O_CREAT;
#else
  int flags = O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT;
#endif
  // There's no need to fsync profile data right away. We get many chances
  // to write it again in case something goes wrong. We can rely on a simple
  // close(), no sync, and let to the kernel decide when to write to disk.
  ScopedFlock profile_file =
      LockedFile::Open(filename.c_str(), flags, /*block=*/false, &error);
  if (profile_file.get() == nullptr) {
    LOG(WARNING) << "Couldn't lock the profile file " << filename << ": " << error;
    return false;
  }

  int fd = profile_file->Fd();

  // We need to clear the data because we don't support appending to the profiles yet.
  if (!profile_file->ClearContent()) {
    PLOG(WARNING) << "Could not clear profile file: " << filename;
    return false;
  }

  // This doesn't need locking because we are trying to lock the file for exclusive
  // access and fail immediately if we can't.
  bool result = Save(fd);
  if (result) {
    int64_t size = OS::GetFileSizeBytes(filename.c_str());
    if (size != -1) {
      VLOG(profiler)
        << "Successfully saved profile info to " << filename << " Size: "
        << size;
      if (bytes_written != nullptr) {
        *bytes_written = static_cast<uint64_t>(size);
      }
    } else {
      VLOG(profiler) << "Saved profile info to " << filename
                     << " but failed to get size: " << strerror(errno);
    }
  } else {
    VLOG(profiler) << "Failed to save profile info to " << filename;
  }
  return result;
}

// Returns true if all the bytes were successfully written to the file descriptor.
static bool WriteBuffer(int fd, const void* buffer, size_t byte_count) {
  while (byte_count > 0) {
    int bytes_written = TEMP_FAILURE_RETRY(write(fd, buffer, byte_count));
    if (bytes_written == -1) {
      return false;
    }
    byte_count -= bytes_written;  // Reduce the number of remaining bytes.
    reinterpret_cast<const uint8_t*&>(buffer) += bytes_written;  // Move the buffer forward.
  }
  return true;
}

/**
 * Serialization format:
 *
 * The file starts with a header and section information:
 *   FileHeader
 *   FileSectionInfo[]
 * The first FileSectionInfo must be for the DexFiles section.
 *
 * The rest of the file is allowed to contain different sections in any order,
 * at arbitrary offsets, with any gaps betweeen them and each section can be
 * either plaintext or separately zipped. However, we're writing sections
 * without any gaps with the following order and compression:
 *   DexFiles - mandatory, plaintext
 *   ExtraDescriptors - optional, zipped
 *   Classes - optional, zipped
 *   Methods - optional, zipped
 *   AggregationCounts - optional, zipped, server-side
 *
 * DexFiles:
 *    number_of_dex_files
 *    (checksum,num_type_ids,num_method_ids,profile_key)[number_of_dex_files]
 * where `profile_key` is a length-prefixed string, the length is `uint16_t`.
 *
 * ExtraDescriptors:
 *    number_of_extra_descriptors
 *    (extra_descriptor)[number_of_extra_descriptors]
 * where `extra_descriptor` is a length-prefixed string, the length is `uint16_t`.
 *
 * Classes contains records for any number of dex files, each consisting of:
 *    profile_index  // Index of the dex file in DexFiles section.
 *    number_of_classes
 *    type_index_diff[number_of_classes]
 * where instead of storing plain sorted type indexes, we store their differences
 * as smaller numbers are likely to compress better.
 *
 * Methods contains records for any number of dex files, each consisting of:
 *    profile_index  // Index of the dex file in DexFiles section.
 *    following_data_size  // For easy skipping of remaining data when dex file is filtered out.
 *    method_flags
 *    bitmap_data
 *    method_encoding[]  // Until the size indicated by `following_data_size`.
 * where `method_flags` is a union of flags recorded for methods in the referenced dex file,
 * `bitmap_data` contains `num_method_ids` bits for each bit set in `method_flags` other
 * than "hot" (the size of `bitmap_data` is rounded up to whole bytes) and `method_encoding[]`
 * contains data for hot methods. The `method_encoding` is:
 *    method_index_diff
 *    number_of_inline_caches
 *    inline_cache_encoding[number_of_inline_caches]
 * where differences in method indexes are used for better compression,
 * and the `inline_cache_encoding` is
 *    dex_pc
 *    (M|dex_map_size)
 *    type_index_diff[dex_map_size]
 * where `M` stands for special encodings indicating missing types (kIsMissingTypesEncoding)
 * or memamorphic call (kIsMegamorphicEncoding) which both imply `dex_map_size == 0`.
 **/
bool ProfileCompilationInfo::Save(int fd) {
  uint64_t start = NanoTime();
  ScopedTrace trace(__PRETTY_FUNCTION__);
  DCHECK_GE(fd, 0);

  // Collect uncompressed section sizes.
  // Use `uint64_t` and assume this cannot overflow as we would have run out of memory.
  uint64_t extra_descriptors_section_size = 0u;
  if (!extra_descriptors_.empty()) {
    extra_descriptors_section_size += sizeof(uint16_t);  // Number of descriptors.
    for (const std::string& descriptor : extra_descriptors_) {
      // Length-prefixed string, the length is `uint16_t`.
      extra_descriptors_section_size += sizeof(uint16_t) + descriptor.size();
    }
  }
  uint64_t dex_files_section_size = sizeof(ProfileIndexType);  // Number of dex files.
  uint64_t classes_section_size = 0u;
  uint64_t methods_section_size = 0u;
  DCHECK_LE(info_.size(), MaxProfileIndex());
  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    if (dex_data->profile_key.size() > kMaxDexFileKeyLength) {
      LOG(WARNING) << "DexFileKey exceeds allocated limit";
      return false;
    }
    dex_files_section_size +=
        3 * sizeof(uint32_t) +  // Checksum, num_type_ids, num_method_ids.
        // Length-prefixed string, the length is `uint16_t`.
        sizeof(uint16_t) + dex_data->profile_key.size();
    classes_section_size += dex_data->ClassesDataSize();
    methods_section_size += dex_data->MethodsDataSize();
  }

  const uint32_t file_section_count =
      /* dex files */ 1u +
      /* extra descriptors */ (extra_descriptors_section_size != 0u ? 1u : 0u) +
      /* classes */ (classes_section_size != 0u ? 1u : 0u) +
      /* methods */ (methods_section_size != 0u ? 1u : 0u);
  uint64_t header_and_infos_size =
      sizeof(FileHeader) + file_section_count * sizeof(FileSectionInfo);

  // Check size limit. Allow large profiles for non target builds for the case
  // where we are merging many profiles to generate a boot image profile.
  uint64_t total_uncompressed_size =
      header_and_infos_size +
      dex_files_section_size +
      extra_descriptors_section_size +
      classes_section_size +
      methods_section_size;
  VLOG(profiler) << "Required capacity: " << total_uncompressed_size << " bytes.";
  if (total_uncompressed_size > GetSizeErrorThresholdBytes()) {
    LOG(WARNING) << "Profile data size exceeds "
                 << GetSizeErrorThresholdBytes()
                 << " bytes. Profile will not be written to disk."
                 << " It requires " << total_uncompressed_size << " bytes.";
    return false;
  }

  // Start with an invalid file header and section infos.
  DCHECK_EQ(lseek(fd, 0, SEEK_CUR), 0);
  constexpr uint32_t kMaxNumberOfSections = enum_cast<uint32_t>(FileSectionType::kNumberOfSections);
  constexpr uint64_t kMaxHeaderAndInfosSize =
      sizeof(FileHeader) + kMaxNumberOfSections * sizeof(FileSectionInfo);
  DCHECK_LE(header_and_infos_size, kMaxHeaderAndInfosSize);
  std::array<uint8_t, kMaxHeaderAndInfosSize> placeholder;
  memset(placeholder.data(), 0, header_and_infos_size);
  if (!WriteBuffer(fd, placeholder.data(), header_and_infos_size)) {
    return false;
  }

  std::array<FileSectionInfo, kMaxNumberOfSections> section_infos;
  size_t section_index = 0u;
  uint32_t file_offset = header_and_infos_size;
  auto add_section_info = [&](FileSectionType type, uint32_t file_size, uint32_t inflated_size) {
    DCHECK_LT(section_index, section_infos.size());
    section_infos[section_index] = FileSectionInfo(type, file_offset, file_size, inflated_size);
    file_offset += file_size;
    section_index += 1u;
  };

  // Write the dex files section.
  {
    SafeBuffer buffer(dex_files_section_size);
    buffer.WriteUintAndAdvance(dchecked_integral_cast<ProfileIndexType>(info_.size()));
    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
      buffer.WriteUintAndAdvance(dex_data->checksum);
      buffer.WriteUintAndAdvance(dex_data->num_type_ids);
      buffer.WriteUintAndAdvance(dex_data->num_method_ids);
      buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(dex_data->profile_key.size()));
      buffer.WriteAndAdvance(dex_data->profile_key.c_str(), dex_data->profile_key.size());
    }
    DCHECK_EQ(buffer.GetAvailableBytes(), 0u);
    // Write the dex files section uncompressed.
    if (!WriteBuffer(fd, buffer.Get(), dex_files_section_size)) {
      return false;
    }
    add_section_info(FileSectionType::kDexFiles, dex_files_section_size, /*inflated_size=*/ 0u);
  }

  // Write the extra descriptors section.
  if (extra_descriptors_section_size != 0u) {
    SafeBuffer buffer(extra_descriptors_section_size);
    buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(extra_descriptors_.size()));
    for (const std::string& descriptor : extra_descriptors_) {
      buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(descriptor.size()));
      buffer.WriteAndAdvance(descriptor.c_str(), descriptor.size());
    }
    if (!buffer.Deflate()) {
      return false;
    }
    if (!WriteBuffer(fd, buffer.Get(), buffer.Size())) {
      return false;
    }
    add_section_info(
        FileSectionType::kExtraDescriptors, buffer.Size(), extra_descriptors_section_size);
  }

  // Write the classes section.
  if (classes_section_size != 0u) {
    SafeBuffer buffer(classes_section_size);
    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
      dex_data->WriteClasses(buffer);
    }
    if (!buffer.Deflate()) {
      return false;
    }
    if (!WriteBuffer(fd, buffer.Get(), buffer.Size())) {
      return false;
    }
    add_section_info(FileSectionType::kClasses, buffer.Size(), classes_section_size);
  }

  // Write the methods section.
  if (methods_section_size != 0u) {
    SafeBuffer buffer(methods_section_size);
    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
      dex_data->WriteMethods(buffer);
    }
    if (!buffer.Deflate()) {
      return false;
    }
    if (!WriteBuffer(fd, buffer.Get(), buffer.Size())) {
      return false;
    }
    add_section_info(FileSectionType::kMethods, buffer.Size(), methods_section_size);
  }

  if (file_offset > GetSizeWarningThresholdBytes()) {
    LOG(WARNING) << "Profile data size exceeds "
        << GetSizeWarningThresholdBytes()
        << " It has " << file_offset << " bytes";
  }

  // Write section infos.
  if (lseek64(fd, sizeof(FileHeader), SEEK_SET) != sizeof(FileHeader)) {
    return false;
  }
  SafeBuffer section_infos_buffer(section_index * 4u * sizeof(uint32_t));
  for (size_t i = 0; i != section_index; ++i) {
    const FileSectionInfo& info = section_infos[i];
    section_infos_buffer.WriteUintAndAdvance(enum_cast<uint32_t>(info.GetType()));
    section_infos_buffer.WriteUintAndAdvance(info.GetFileOffset());
    section_infos_buffer.WriteUintAndAdvance(info.GetFileSize());
    section_infos_buffer.WriteUintAndAdvance(info.GetInflatedSize());
  }
  DCHECK_EQ(section_infos_buffer.GetAvailableBytes(), 0u);
  if (!WriteBuffer(fd, section_infos_buffer.Get(), section_infos_buffer.Size())) {
    return false;
  }

  // Write header.
  FileHeader header(version_, section_index);
  if (lseek(fd, 0, SEEK_SET) != 0) {
    return false;
  }
  if (!WriteBuffer(fd, &header, sizeof(FileHeader))) {
    return false;
  }

  uint64_t total_time = NanoTime() - start;
  VLOG(profiler) << "Compressed from "
                 << std::to_string(total_uncompressed_size)
                 << " to "
                 << std::to_string(file_offset);
  VLOG(profiler) << "Time to save profile: " << std::to_string(total_time);
  return true;
}

ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::GetOrAddDexFileData(
    const std::string& profile_key,
    uint32_t checksum,
    uint32_t num_type_ids,
    uint32_t num_method_ids) {
  DCHECK_EQ(profile_key_map_.size(), info_.size());
  auto profile_index_it = profile_key_map_.lower_bound(profile_key);
  if (profile_index_it == profile_key_map_.end() || profile_index_it->first != profile_key) {
    // We did not find the key. Create a new DexFileData if we did not reach the limit.
    DCHECK_LE(profile_key_map_.size(), MaxProfileIndex());
    if (profile_key_map_.size() == MaxProfileIndex()) {
      // Allow only a limited number dex files to be profiled. This allows us to save bytes
      // when encoding. For regular profiles this 2^8, and for boot profiles is 2^16
      // (well above what we expect for normal applications).
      LOG(ERROR) << "Exceeded the maximum number of dex file. Something went wrong";
      return nullptr;
    }
    ProfileIndexType new_profile_index = dchecked_integral_cast<ProfileIndexType>(info_.size());
    std::unique_ptr<DexFileData> dex_file_data(new (&allocator_) DexFileData(
        &allocator_,
        profile_key,
        checksum,
        new_profile_index,
        num_type_ids,
        num_method_ids,
        IsForBootImage()));
    // Record the new data in `profile_key_map_` and `info_`.
    std::string_view new_key(dex_file_data->profile_key);
    profile_index_it = profile_key_map_.PutBefore(profile_index_it, new_key, new_profile_index);
    info_.push_back(std::move(dex_file_data));
    DCHECK_EQ(profile_key_map_.size(), info_.size());
  }

  ProfileIndexType profile_index = profile_index_it->second;
  DexFileData* result = info_[profile_index].get();

  // Check that the checksum matches.
  // This may different if for example the dex file was updated and we had a record of the old one.
  if (result->checksum != checksum) {
    LOG(WARNING) << "Checksum mismatch for dex " << profile_key;
    return nullptr;
  }

  // DCHECK that profile info map key is consistent with the one stored in the dex file data.
  // This should always be the case since since the cache map is managed by ProfileCompilationInfo.
  DCHECK_EQ(profile_key, result->profile_key);
  DCHECK_EQ(profile_index, result->profile_index);

  if (num_type_ids != result->num_type_ids || num_method_ids != result->num_method_ids) {
    // This should not happen... added to help investigating b/65812889.
    LOG(ERROR) << "num_type_ids or num_method_ids mismatch for dex " << profile_key
        << ", types: expected=" << num_type_ids << " v. actual=" << result->num_type_ids
        << ", methods: expected=" << num_method_ids << " actual=" << result->num_method_ids;
    return nullptr;
  }

  return result;
}

const ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::FindDexData(
      const std::string& profile_key,
      uint32_t checksum,
      bool verify_checksum) const {
  const auto profile_index_it = profile_key_map_.find(profile_key);
  if (profile_index_it == profile_key_map_.end()) {
    return nullptr;
  }

  ProfileIndexType profile_index = profile_index_it->second;
  const DexFileData* result = info_[profile_index].get();
  if (verify_checksum && !ChecksumMatch(result->checksum, checksum)) {
    return nullptr;
  }
  DCHECK_EQ(profile_key, result->profile_key);
  DCHECK_EQ(profile_index, result->profile_index);
  return result;
}

const ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::FindDexDataUsingAnnotations(
      const DexFile* dex_file,
      const ProfileSampleAnnotation& annotation) const {
  if (annotation == ProfileSampleAnnotation::kNone) {
    std::string_view profile_key = GetProfileDexFileBaseKeyView(dex_file->GetLocation());
    for (const std::unique_ptr<DexFileData>& dex_data : info_) {
      if (profile_key == GetBaseKeyViewFromAugmentedKey(dex_data->profile_key)) {
        if (!ChecksumMatch(dex_data->checksum, dex_file->GetLocationChecksum())) {
          return nullptr;
        }
        return dex_data.get();
      }
    }
  } else {
    std::string profile_key = GetProfileDexFileAugmentedKey(dex_file->GetLocation(), annotation);
    return FindDexData(profile_key, dex_file->GetLocationChecksum());
  }

  return nullptr;
}

void ProfileCompilationInfo::FindAllDexData(
    const DexFile* dex_file,
    /*out*/ std::vector<const ProfileCompilationInfo::DexFileData*>* result) const {
  std::string_view profile_key = GetProfileDexFileBaseKeyView(dex_file->GetLocation());
  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    if (profile_key == GetBaseKeyViewFromAugmentedKey(dex_data->profile_key)) {
      if (ChecksumMatch(dex_data->checksum, dex_file->GetLocationChecksum())) {
        result->push_back(dex_data.get());
      }
    }
  }
}

ProfileCompilationInfo::ExtraDescriptorIndex ProfileCompilationInfo::AddExtraDescriptor(
    std::string_view extra_descriptor) {
  DCHECK_LE(extra_descriptor.size(), kMaxExtraDescriptorLength);
  DCHECK(extra_descriptors_indexes_.find(extra_descriptor) == extra_descriptors_indexes_.end());
  ExtraDescriptorIndex new_extra_descriptor_index = extra_descriptors_.size();
  DCHECK_LE(new_extra_descriptor_index, kMaxExtraDescriptors);
  if (UNLIKELY(new_extra_descriptor_index == kMaxExtraDescriptors)) {
    return kMaxExtraDescriptors;  // Cannot add another extra descriptor.
  }
  // Add the extra descriptor and record the new index.
  extra_descriptors_.emplace_back(extra_descriptor);
  extra_descriptors_indexes_.insert(new_extra_descriptor_index);
  return new_extra_descriptor_index;
}

bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi,
                                       MethodHotness::Flag flags,
                                       const ProfileSampleAnnotation& annotation) {
  DexFileData* const data = GetOrAddDexFileData(pmi.ref.dex_file, annotation);
  if (data == nullptr) {  // checksum mismatch
    return false;
  }
  if (!data->AddMethod(flags, pmi.ref.index)) {
    return false;
  }
  if ((flags & MethodHotness::kFlagHot) == 0) {
    // The method is not hot, do not add inline caches.
    return true;
  }

  // Add inline caches.
  InlineCacheMap* inline_cache = data->FindOrAddHotMethod(pmi.ref.index);
  DCHECK(inline_cache != nullptr);

  for (const ProfileMethodInfo::ProfileInlineCache& cache : pmi.inline_caches) {
    if (cache.is_missing_types) {
      FindOrAddDexPc(inline_cache, cache.dex_pc)->SetIsMissingTypes();
      continue;
    }
    if  (cache.is_megamorphic) {
      FindOrAddDexPc(inline_cache, cache.dex_pc)->SetIsMegamorphic();
      continue;
    }
    for (const TypeReference& class_ref : cache.classes) {
      DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, cache.dex_pc);
      if (dex_pc_data->is_missing_types || dex_pc_data->is_megamorphic) {
        // Don't bother adding classes if we are missing types or already megamorphic.
        break;
      }
      dex::TypeIndex type_index = FindOrCreateTypeIndex(*pmi.ref.dex_file, class_ref);
      if (type_index.IsValid()) {
        dex_pc_data->AddClass(type_index);
      } else {
        // Could not create artificial type index.
        dex_pc_data->SetIsMissingTypes();
      }
    }
  }
  return true;
}

// TODO(calin): Fix this API. ProfileCompilationInfo::Load should be static and
// return a unique pointer to a ProfileCompilationInfo upon success.
bool ProfileCompilationInfo::Load(
    int fd, bool merge_classes, const ProfileLoadFilterFn& filter_fn) {
  std::string error;

  ProfileLoadStatus status = LoadInternal(fd, &error, merge_classes, filter_fn);

  if (status == ProfileLoadStatus::kSuccess) {
    return true;
  } else {
    LOG(WARNING) << "Error when reading profile: " << error;
    return false;
  }
}

bool ProfileCompilationInfo::VerifyProfileData(const std::vector<const DexFile*>& dex_files) {
  std::unordered_map<std::string_view, const DexFile*> key_to_dex_file;
  for (const DexFile* dex_file : dex_files) {
    key_to_dex_file.emplace(GetProfileDexFileBaseKeyView(dex_file->GetLocation()), dex_file);
  }
  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    // We need to remove any annotation from the key during verification.
    const auto it = key_to_dex_file.find(GetBaseKeyViewFromAugmentedKey(dex_data->profile_key));
    if (it == key_to_dex_file.end()) {
      // It is okay if profile contains data for additional dex files.
      continue;
    }
    const DexFile* dex_file = it->second;
    const std::string& dex_location = dex_file->GetLocation();
    if (!ChecksumMatch(dex_data->checksum, dex_file->GetLocationChecksum())) {
      LOG(ERROR) << "Dex checksum mismatch while verifying profile "
                 << "dex location " << dex_location << " (checksum="
                 << dex_file->GetLocationChecksum() << ", profile checksum="
                 << dex_data->checksum;
      return false;
    }

    if (dex_data->num_method_ids != dex_file->NumMethodIds() ||
        dex_data->num_type_ids != dex_file->NumTypeIds()) {
      LOG(ERROR) << "Number of type or method ids in dex file and profile don't match."
                 << "dex location " << dex_location
                 << " dex_file.NumTypeIds=" << dex_file->NumTypeIds()
                 << " .v dex_data.num_type_ids=" << dex_data->num_type_ids
                 << ", dex_file.NumMethodIds=" << dex_file->NumMethodIds()
                 << " v. dex_data.num_method_ids=" << dex_data->num_method_ids;
      return false;
    }

    // Class and method data should be valid. Verify only in debug builds.
    if (kIsDebugBuild) {
      // Verify method_encoding.
      for (const auto& method_it : dex_data->method_map) {
        CHECK_LT(method_it.first, dex_data->num_method_ids);

        // Verify class indices of inline caches.
        const InlineCacheMap &inline_cache_map = method_it.second;
        for (const auto& inline_cache_it : inline_cache_map) {
          const DexPcData& dex_pc_data = inline_cache_it.second;
          if (dex_pc_data.is_missing_types || dex_pc_data.is_megamorphic) {
            // No class indices to verify.
            CHECK(dex_pc_data.classes.empty());
            continue;
          }

          for (const dex::TypeIndex& type_index : dex_pc_data.classes) {
            if (type_index.index_ >= dex_data->num_type_ids) {
              CHECK_LT(type_index.index_ - dex_data->num_type_ids, extra_descriptors_.size());
            }
          }
        }
      }
      // Verify class_ids.
      for (const dex::TypeIndex& type_index : dex_data->class_set) {
        if (type_index.index_ >= dex_data->num_type_ids) {
          CHECK_LT(type_index.index_ - dex_data->num_type_ids, extra_descriptors_.size());
        }
      }
    }
  }
  return true;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::OpenSource(
    int32_t fd,
    /*out*/ std::unique_ptr<ProfileSource>* source,
    /*out*/ std::string* error) {
  if (IsProfileFile(fd)) {
    source->reset(ProfileSource::Create(fd));
    return ProfileLoadStatus::kSuccess;
  } else {
    std::unique_ptr<ZipArchive> zip_archive(
        ZipArchive::OpenFromFd(DupCloexec(fd), "profile", error));
    if (zip_archive.get() == nullptr) {
      *error = "Could not open the profile zip archive";
      return ProfileLoadStatus::kBadData;
    }
    std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(kDexMetadataProfileEntry, error));
    if (zip_entry == nullptr) {
      // Allow archives without the profile entry. In this case, create an empty profile.
      // This gives more flexible when ure-using archives that may miss the entry.
      // (e.g. dex metadata files)
      LOG(WARNING) << "Could not find entry " << kDexMetadataProfileEntry
          << " in the zip archive. Creating an empty profile.";
      source->reset(ProfileSource::Create(MemMap::Invalid()));
      return ProfileLoadStatus::kSuccess;
    }
    if (zip_entry->GetUncompressedLength() == 0) {
      *error = "Empty profile entry in the zip archive.";
      return ProfileLoadStatus::kBadData;
    }

    // TODO(calin) pass along file names to assist with debugging.
    MemMap map = zip_entry->MapDirectlyOrExtract(
        kDexMetadataProfileEntry, "profile file", error, alignof(ProfileSource));

    if (map.IsValid()) {
      source->reset(ProfileSource::Create(std::move(map)));
      return ProfileLoadStatus::kSuccess;
    } else {
      return ProfileLoadStatus::kBadData;
    }
  }
}

bool ProfileCompilationInfo::ProfileSource::Seek(off_t offset) {
  DCHECK_GE(offset, 0);
  if (IsMemMap()) {
    if (offset > static_cast<int64_t>(mem_map_.Size())) {
      return false;
    }
    mem_map_cur_ = offset;
    return true;
  } else {
    if (lseek64(fd_, offset, SEEK_SET) != offset) {
      return false;
    }
    return true;
  }
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ProfileSource::Read(
    void* buffer,
    size_t byte_count,
    const std::string& debug_stage,
    std::string* error) {
  if (IsMemMap()) {
    DCHECK_LE(mem_map_cur_, mem_map_.Size());
    if (byte_count > mem_map_.Size() - mem_map_cur_) {
      return ProfileLoadStatus::kBadData;
    }
    memcpy(buffer, mem_map_.Begin() + mem_map_cur_, byte_count);
    mem_map_cur_ += byte_count;
  } else {
    while (byte_count > 0) {
      int bytes_read = TEMP_FAILURE_RETRY(read(fd_, buffer, byte_count));;
      if (bytes_read == 0) {
        *error += "Profile EOF reached prematurely for " + debug_stage;
        return ProfileLoadStatus::kBadData;
      } else if (bytes_read < 0) {
        *error += "Profile IO error for " + debug_stage + strerror(errno);
        return ProfileLoadStatus::kIOError;
      }
      byte_count -= bytes_read;
      reinterpret_cast<uint8_t*&>(buffer) += bytes_read;
    }
  }
  return ProfileLoadStatus::kSuccess;
}


bool ProfileCompilationInfo::ProfileSource::HasEmptyContent() const {
  if (IsMemMap()) {
    return !mem_map_.IsValid() || mem_map_.Size() == 0;
  } else {
    struct stat stat_buffer;
    if (fstat(fd_, &stat_buffer) != 0) {
      return false;
    }
    return stat_buffer.st_size == 0;
  }
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadSectionData(
    ProfileSource& source,
    const FileSectionInfo& section_info,
    /*out*/ SafeBuffer* buffer,
    /*out*/ std::string* error) {
  DCHECK_EQ(buffer->Size(), 0u);
  if (!source.Seek(section_info.GetFileOffset())) {
    *error = "Failed to seek to section data.";
    return ProfileLoadStatus::kIOError;
  }
  SafeBuffer temp_buffer(section_info.GetFileSize());
  ProfileLoadStatus status = source.Read(
      temp_buffer.GetCurrentPtr(), temp_buffer.GetAvailableBytes(), "ReadSectionData", error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }
  if (section_info.GetInflatedSize() != 0u &&
      !temp_buffer.Inflate(section_info.GetInflatedSize())) {
    *error += "Error uncompressing section data.";
    return ProfileLoadStatus::kBadData;
  }
  buffer->Swap(temp_buffer);
  return ProfileLoadStatus::kSuccess;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadDexFilesSection(
    ProfileSource& source,
    const FileSectionInfo& section_info,
    const ProfileLoadFilterFn& filter_fn,
    /*out*/ dchecked_vector<ProfileIndexType>* dex_profile_index_remap,
    /*out*/ std::string* error) {
  DCHECK(section_info.GetType() == FileSectionType::kDexFiles);
  SafeBuffer buffer;
  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }

  ProfileIndexType num_dex_files;
  if (!buffer.ReadUintAndAdvance(&num_dex_files)) {
    *error = "Error reading number of dex files.";
    return ProfileLoadStatus::kBadData;
  }
  if (num_dex_files >= MaxProfileIndex()) {
    *error = "Too many dex files.";
    return ProfileLoadStatus::kBadData;
  }

  DCHECK(dex_profile_index_remap->empty());
  for (ProfileIndexType i = 0u; i != num_dex_files; ++i) {
    uint32_t checksum, num_type_ids, num_method_ids;
    if (!buffer.ReadUintAndAdvance(&checksum) ||
        !buffer.ReadUintAndAdvance(&num_type_ids) ||
        !buffer.ReadUintAndAdvance(&num_method_ids)) {
      *error = "Error reading dex file data.";
      return ProfileLoadStatus::kBadData;
    }
    std::string_view profile_key_view;
    if (!buffer.ReadStringAndAdvance(&profile_key_view)) {
      *error += "Missing terminating null character for profile key.";
      return ProfileLoadStatus::kBadData;
    }
    if (profile_key_view.size() == 0u || profile_key_view.size() > kMaxDexFileKeyLength) {
      *error = "ProfileKey has an invalid size: " + std::to_string(profile_key_view.size());
      return ProfileLoadStatus::kBadData;
    }
    std::string profile_key(profile_key_view);
    if (!filter_fn(profile_key, checksum)) {
      // Do not load data for this key. Store invalid index to `dex_profile_index_remap`.
      VLOG(compiler) << "Profile: Filtered out " << profile_key << " 0x" << std::hex << checksum;
      dex_profile_index_remap->push_back(MaxProfileIndex());
      continue;
    }
    DexFileData* data = GetOrAddDexFileData(profile_key, checksum, num_type_ids, num_method_ids);
    if (data == nullptr) {
      if (UNLIKELY(profile_key_map_.size() == MaxProfileIndex()) &&
          profile_key_map_.find(profile_key) == profile_key_map_.end()) {
        *error = "Too many dex files.";
      } else {
        *error = "Checksum, NumTypeIds, or NumMethodIds mismatch for " + profile_key;
      }
      return ProfileLoadStatus::kBadData;
    }
    dex_profile_index_remap->push_back(data->profile_index);
  }
  if (buffer.GetAvailableBytes() != 0u) {
    *error = "Unexpected data at end of dex files section.";
    return ProfileLoadStatus::kBadData;
  }
  return ProfileLoadStatus::kSuccess;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadExtraDescriptorsSection(
    ProfileSource& source,
    const FileSectionInfo& section_info,
    /*out*/ dchecked_vector<ExtraDescriptorIndex>* extra_descriptors_remap,
    /*out*/ std::string* error) {
  DCHECK(section_info.GetType() == FileSectionType::kExtraDescriptors);
  SafeBuffer buffer;
  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }

  uint16_t num_extra_descriptors;
  if (!buffer.ReadUintAndAdvance(&num_extra_descriptors)) {
    *error = "Error reading number of extra descriptors.";
    return ProfileLoadStatus::kBadData;
  }

  // Note: We allow multiple extra descriptors sections in a single profile file
  // but that can lead to `kMergeError` if there are too many extra descriptors.
  // Other sections can reference only extra descriptors from preceding sections.
  extra_descriptors_remap->reserve(
      std::min<size_t>(extra_descriptors_remap->size() + num_extra_descriptors,
                       std::numeric_limits<uint16_t>::max()));
  for (uint16_t i = 0; i != num_extra_descriptors; ++i) {
    std::string_view extra_descriptor;
    if (!buffer.ReadStringAndAdvance(&extra_descriptor)) {
      *error += "Missing terminating null character for extra descriptor.";
      return ProfileLoadStatus::kBadData;
    }
    if (!IsValidDescriptor(std::string(extra_descriptor).c_str())) {
      *error += "Invalid extra descriptor.";
      return ProfileLoadStatus::kBadData;
    }
    // Try to match an existing extra descriptor.
    auto it = extra_descriptors_indexes_.find(extra_descriptor);
    if (it != extra_descriptors_indexes_.end()) {
      extra_descriptors_remap->push_back(*it);
      continue;
    }
    // Try to insert a new extra descriptor.
    ExtraDescriptorIndex extra_descriptor_index = AddExtraDescriptor(extra_descriptor);
    if (extra_descriptor_index == kMaxExtraDescriptors) {
      *error = "Too many extra descriptors.";
      return ProfileLoadStatus::kMergeError;
    }
    extra_descriptors_remap->push_back(extra_descriptor_index);
  }
  return ProfileLoadStatus::kSuccess;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadClassesSection(
    ProfileSource& source,
    const FileSectionInfo& section_info,
    const dchecked_vector<ProfileIndexType>& dex_profile_index_remap,
    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
    /*out*/ std::string* error) {
  DCHECK(section_info.GetType() == FileSectionType::kClasses);
  SafeBuffer buffer;
  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }

  while (buffer.GetAvailableBytes() != 0u) {
    ProfileIndexType profile_index;
    if (!buffer.ReadUintAndAdvance(&profile_index)) {
      *error = "Error profile index in classes section.";
      return ProfileLoadStatus::kBadData;
    }
    if (profile_index >= dex_profile_index_remap.size()) {
      *error = "Invalid profile index in classes section.";
      return ProfileLoadStatus::kBadData;
    }
    profile_index = dex_profile_index_remap[profile_index];
    if (profile_index == MaxProfileIndex()) {
      status = DexFileData::SkipClasses(buffer, error);
    } else {
      status = info_[profile_index]->ReadClasses(buffer, extra_descriptors_remap, error);
    }
    if (status != ProfileLoadStatus::kSuccess) {
      return status;
    }
  }
  return ProfileLoadStatus::kSuccess;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::ReadMethodsSection(
    ProfileSource& source,
    const FileSectionInfo& section_info,
    const dchecked_vector<ProfileIndexType>& dex_profile_index_remap,
    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
    /*out*/ std::string* error) {
  DCHECK(section_info.GetType() == FileSectionType::kMethods);
  SafeBuffer buffer;
  ProfileLoadStatus status = ReadSectionData(source, section_info, &buffer, error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }

  while (buffer.GetAvailableBytes() != 0u) {
    ProfileIndexType profile_index;
    if (!buffer.ReadUintAndAdvance(&profile_index)) {
      *error = "Error profile index in methods section.";
      return ProfileLoadStatus::kBadData;
    }
    if (profile_index >= dex_profile_index_remap.size()) {
      *error = "Invalid profile index in methods section.";
      return ProfileLoadStatus::kBadData;
    }
    profile_index = dex_profile_index_remap[profile_index];
    if (profile_index == MaxProfileIndex()) {
      status = DexFileData::SkipMethods(buffer, error);
    } else {
      status = info_[profile_index]->ReadMethods(buffer, extra_descriptors_remap, error);
    }
    if (status != ProfileLoadStatus::kSuccess) {
      return status;
    }
  }
  return ProfileLoadStatus::kSuccess;
}

// TODO(calin): fail fast if the dex checksums don't match.
ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::LoadInternal(
    int32_t fd,
    std::string* error,
    bool merge_classes,
    const ProfileLoadFilterFn& filter_fn) {
  ScopedTrace trace(__PRETTY_FUNCTION__);
  DCHECK_GE(fd, 0);

  std::unique_ptr<ProfileSource> source;
  ProfileLoadStatus status = OpenSource(fd, &source, error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }

  // We allow empty profile files.
  // Profiles may be created by ActivityManager or installd before we manage to
  // process them in the runtime or profman.
  if (source->HasEmptyContent()) {
    return ProfileLoadStatus::kSuccess;
  }

  // Read file header.
  FileHeader header;
  status = source->Read(&header, sizeof(FileHeader), "ReadProfileHeader", error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }
  if (!header.IsValid()) {
    return header.InvalidHeaderMessage(error);
  }
  if (memcmp(header.GetVersion(), version_, kProfileVersionSize) != 0) {
    *error = IsForBootImage() ? "Expected boot profile, got app profile."
                              : "Expected app profile, got boot profile.";
    return ProfileLoadStatus::kVersionMismatch;
  }

  // Check if there are too many section infos.
  uint32_t section_count = header.GetFileSectionCount();
  uint32_t uncompressed_data_size = sizeof(FileHeader) + section_count * sizeof(FileSectionInfo);
  if (uncompressed_data_size > GetSizeErrorThresholdBytes()) {
    LOG(WARNING) << "Profile data size exceeds " << GetSizeErrorThresholdBytes()
               << " bytes. It has " << uncompressed_data_size << " bytes.";
    return ProfileLoadStatus::kBadData;
  }

  // Read section infos.
  dchecked_vector<FileSectionInfo> section_infos(section_count);
  status = source->Read(
      section_infos.data(), section_count * sizeof(FileSectionInfo), "ReadSectionInfos", error);
  if (status != ProfileLoadStatus::kSuccess) {
    return status;
  }

  // Finish uncompressed data size calculation.
  for (const FileSectionInfo& section_info : section_infos) {
    uint32_t mem_size = section_info.GetMemSize();
    if (UNLIKELY(mem_size > std::numeric_limits<uint32_t>::max() - uncompressed_data_size)) {
      *error = "Total memory size overflow.";
      return ProfileLoadStatus::kBadData;
    }
    uncompressed_data_size += mem_size;
  }

  // Allow large profiles for non target builds for the case where we are merging many profiles
  // to generate a boot image profile.
  if (uncompressed_data_size > GetSizeErrorThresholdBytes()) {
    LOG(WARNING) << "Profile data size exceeds "
               << GetSizeErrorThresholdBytes()
               << " bytes. It has " << uncompressed_data_size << " bytes.";
    return ProfileLoadStatus::kBadData;
  }
  if (uncompressed_data_size > GetSizeWarningThresholdBytes()) {
    LOG(WARNING) << "Profile data size exceeds "
                 << GetSizeWarningThresholdBytes()
                 << " bytes. It has " << uncompressed_data_size << " bytes.";
  }

  // Process the mandatory dex files section.
  DCHECK_NE(section_count, 0u);  // Checked by `header.IsValid()` above.
  const FileSectionInfo& dex_files_section_info = section_infos[0];
  if (dex_files_section_info.GetType() != FileSectionType::kDexFiles) {
    *error = "First section is not dex files section.";
    return ProfileLoadStatus::kBadData;
  }
  dchecked_vector<ProfileIndexType> dex_profile_index_remap;
  status = ReadDexFilesSection(
      *source, dex_files_section_info, filter_fn, &dex_profile_index_remap, error);
  if (status != ProfileLoadStatus::kSuccess) {
    DCHECK(!error->empty());
    return status;
  }

  // Process all other sections.
  dchecked_vector<ExtraDescriptorIndex> extra_descriptors_remap;
  for (uint32_t i = 1u; i != section_count; ++i) {
    const FileSectionInfo& section_info = section_infos[i];
    DCHECK(status == ProfileLoadStatus::kSuccess);
    switch (section_info.GetType()) {
      case FileSectionType::kDexFiles:
        *error = "Unsupported additional dex files section.";
        status = ProfileLoadStatus::kBadData;
        break;
      case FileSectionType::kExtraDescriptors:
        status = ReadExtraDescriptorsSection(
            *source, section_info, &extra_descriptors_remap, error);
        break;
      case FileSectionType::kClasses:
        // Skip if all dex files were filtered out.
        if (!info_.empty() && merge_classes) {
          status = ReadClassesSection(
              *source, section_info, dex_profile_index_remap, extra_descriptors_remap, error);
        }
        break;
      case FileSectionType::kMethods:
        // Skip if all dex files were filtered out.
        if (!info_.empty()) {
          status = ReadMethodsSection(
              *source, section_info, dex_profile_index_remap, extra_descriptors_remap, error);
        }
        break;
      case FileSectionType::kAggregationCounts:
        // This section is only used on server side.
        break;
      default:
        // Unknown section. Skip it. New versions of ART are allowed
        // to add sections that shall be ignored by old versions.
        break;
    }
    if (status != ProfileLoadStatus::kSuccess) {
      DCHECK(!error->empty());
      return status;
    }
  }

  return ProfileLoadStatus::kSuccess;
}

bool ProfileCompilationInfo::MergeWith(const ProfileCompilationInfo& other,
                                       bool merge_classes) {
  if (!SameVersion(other)) {
    LOG(WARNING) << "Cannot merge different profile versions";
    return false;
  }

  // First verify that all checksums match. This will avoid adding garbage to
  // the current profile info.
  // Note that the number of elements should be very small, so this should not
  // be a performance issue.
  for (const std::unique_ptr<DexFileData>& other_dex_data : other.info_) {
    // verify_checksum is false because we want to differentiate between a missing dex data and
    // a mismatched checksum.
    const DexFileData* dex_data = FindDexData(other_dex_data->profile_key,
                                              /* checksum= */ 0u,
                                              /* verify_checksum= */ false);
    if ((dex_data != nullptr) && (dex_data->checksum != other_dex_data->checksum)) {
      LOG(WARNING) << "Checksum mismatch for dex " << other_dex_data->profile_key;
      return false;
    }
  }
  // All checksums match. Import the data.

  // The other profile might have a different indexing of dex files.
  // That is because each dex files gets a 'dex_profile_index' on a first come first served basis.
  // That means that the order in with the methods are added to the profile matters for the
  // actual indices.
  // The reason we cannot rely on the actual multidex index is that a single profile may store
  // data from multiple splits. This means that a profile may contain a classes2.dex from split-A
  // and one from split-B.

  // First, build a mapping from other_dex_profile_index to this_dex_profile_index.
  dchecked_vector<ProfileIndexType> dex_profile_index_remap;
  dex_profile_index_remap.reserve(other.info_.size());
  for (const std::unique_ptr<DexFileData>& other_dex_data : other.info_) {
    const DexFileData* dex_data = GetOrAddDexFileData(other_dex_data->profile_key,
                                                      other_dex_data->checksum,
                                                      other_dex_data->num_type_ids,
                                                      other_dex_data->num_method_ids);
    if (dex_data == nullptr) {
      // Could happen if we exceed the number of allowed dex files or there is
      // a mismatch in `num_type_ids` or `num_method_ids`.
      return false;
    }
    DCHECK_EQ(other_dex_data->profile_index, dex_profile_index_remap.size());
    dex_profile_index_remap.push_back(dex_data->profile_index);
  }

  // Then merge extra descriptors.
  dchecked_vector<ExtraDescriptorIndex> extra_descriptors_remap;
  extra_descriptors_remap.reserve(other.extra_descriptors_.size());
  for (const std::string& other_extra_descriptor : other.extra_descriptors_) {
    auto it = extra_descriptors_indexes_.find(std::string_view(other_extra_descriptor));
    if (it != extra_descriptors_indexes_.end()) {
      extra_descriptors_remap.push_back(*it);
    } else {
      ExtraDescriptorIndex extra_descriptor_index = AddExtraDescriptor(other_extra_descriptor);
      if (extra_descriptor_index == kMaxExtraDescriptors) {
        // Too many extra descriptors.
        return false;
      }
      extra_descriptors_remap.push_back(extra_descriptor_index);
    }
  }

  // Merge the actual profile data.
  for (const std::unique_ptr<DexFileData>& other_dex_data : other.info_) {
    DexFileData* dex_data = info_[dex_profile_index_remap[other_dex_data->profile_index]].get();
    DCHECK_EQ(dex_data, FindDexData(other_dex_data->profile_key, other_dex_data->checksum));

    // Merge the classes.
    uint32_t num_type_ids = dex_data->num_type_ids;
    DCHECK_EQ(num_type_ids, other_dex_data->num_type_ids);
    if (merge_classes) {
      // Classes are ordered by the `TypeIndex`, so we have the classes with a `TypeId`
      // in the dex file first, followed by classes using extra descriptors.
      auto it = other_dex_data->class_set.lower_bound(dex::TypeIndex(num_type_ids));
      dex_data->class_set.insert(other_dex_data->class_set.begin(), it);
      for (auto end = other_dex_data->class_set.end(); it != end; ++it) {
        ExtraDescriptorIndex new_extra_descriptor_index =
            extra_descriptors_remap[it->index_ - num_type_ids];
        if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
          // Cannot represent the type with new extra descriptor index.
          return false;
        }
        dex_data->class_set.insert(dex::TypeIndex(num_type_ids + new_extra_descriptor_index));
      }
    }

    // Merge the methods and the inline caches.
    for (const auto& other_method_it : other_dex_data->method_map) {
      uint16_t other_method_index = other_method_it.first;
      InlineCacheMap* inline_cache = dex_data->FindOrAddHotMethod(other_method_index);
      if (inline_cache == nullptr) {
        return false;
      }
      const auto& other_inline_cache = other_method_it.second;
      for (const auto& other_ic_it : other_inline_cache) {
        uint16_t other_dex_pc = other_ic_it.first;
        const ArenaSet<dex::TypeIndex>& other_class_set = other_ic_it.second.classes;
        DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, other_dex_pc);
        if (other_ic_it.second.is_missing_types) {
          dex_pc_data->SetIsMissingTypes();
        } else if (other_ic_it.second.is_megamorphic) {
          dex_pc_data->SetIsMegamorphic();
        } else {
          for (dex::TypeIndex type_index : other_class_set) {
            if (type_index.index_ >= num_type_ids) {
              ExtraDescriptorIndex new_extra_descriptor_index =
                  extra_descriptors_remap[type_index.index_ - num_type_ids];
              if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
                // Cannot represent the type with new extra descriptor index.
                return false;
              }
              type_index = dex::TypeIndex(num_type_ids + new_extra_descriptor_index);
            }
            dex_pc_data->AddClass(type_index);
          }
        }
      }
    }

    // Merge the method bitmaps.
    dex_data->MergeBitmap(*other_dex_data);
  }

  return true;
}

ProfileCompilationInfo::MethodHotness ProfileCompilationInfo::GetMethodHotness(
    const MethodReference& method_ref,
    const ProfileSampleAnnotation& annotation) const {
  const DexFileData* dex_data = FindDexDataUsingAnnotations(method_ref.dex_file, annotation);
  return dex_data != nullptr
      ? dex_data->GetHotnessInfo(method_ref.index)
      : MethodHotness();
}

bool ProfileCompilationInfo::ContainsClass(const DexFile& dex_file,
                                           dex::TypeIndex type_idx,
                                           const ProfileSampleAnnotation& annotation) const {
  const DexFileData* dex_data = FindDexDataUsingAnnotations(&dex_file, annotation);
  return (dex_data != nullptr) && dex_data->ContainsClass(type_idx);
}

uint32_t ProfileCompilationInfo::GetNumberOfMethods() const {
  uint32_t total = 0;
  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    total += dex_data->method_map.size();
  }
  return total;
}

uint32_t ProfileCompilationInfo::GetNumberOfResolvedClasses() const {
  uint32_t total = 0;
  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    total += dex_data->class_set.size();
  }
  return total;
}

std::string ProfileCompilationInfo::DumpInfo(const std::vector<const DexFile*>& dex_files,
                                             bool print_full_dex_location) const {
  std::ostringstream os;

  os << "ProfileInfo [";

  for (size_t k = 0; k <  kProfileVersionSize - 1; k++) {
    // Iterate to 'kProfileVersionSize - 1' because the version_ ends with '\0'
    // which we don't want to print.
    os << static_cast<char>(version_[k]);
  }
  os << "]\n";

  if (info_.empty()) {
    os << "-empty-";
    return os.str();
  }

  if (!extra_descriptors_.empty()) {
    os << "\nextra descriptors:";
    for (const std::string& str : extra_descriptors_) {
      os << "\n\t" << str;
    }
    os << "\n";
  }

  const std::string kFirstDexFileKeySubstitute = "!classes.dex";

  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    os << "\n";
    if (print_full_dex_location) {
      os << dex_data->profile_key;
    } else {
      // Replace the (empty) multidex suffix of the first key with a substitute for easier reading.
      std::string multidex_suffix = DexFileLoader::GetMultiDexSuffix(
          GetBaseKeyFromAugmentedKey(dex_data->profile_key));
      os << (multidex_suffix.empty() ? kFirstDexFileKeySubstitute : multidex_suffix);
    }
    os << " [index=" << static_cast<uint32_t>(dex_data->profile_index) << "]";
    os << " [checksum=" << std::hex << dex_data->checksum << "]" << std::dec;
    os << " [num_type_ids=" << dex_data->num_type_ids << "]";
    os << " [num_method_ids=" << dex_data->num_method_ids << "]";
    const DexFile* dex_file = nullptr;
    for (const DexFile* current : dex_files) {
      if (GetBaseKeyViewFromAugmentedKey(dex_data->profile_key) ==
          GetProfileDexFileBaseKeyView(current->GetLocation()) &&
          ChecksumMatch(dex_data->checksum, current->GetLocationChecksum())) {
        dex_file = current;
        break;
      }
    }
    os << "\n\thot methods: ";
    for (const auto& method_it : dex_data->method_map) {
      if (dex_file != nullptr) {
        os << "\n\t\t" << dex_file->PrettyMethod(method_it.first, true);
      } else {
        os << method_it.first;
      }

      os << "[";
      for (const auto& inline_cache_it : method_it.second) {
        os << "{" << std::hex << inline_cache_it.first << std::dec << ":";
        if (inline_cache_it.second.is_missing_types) {
          os << "MT";
        } else if (inline_cache_it.second.is_megamorphic) {
          os << "MM";
        } else {
          const char* separator = "";
          for (dex::TypeIndex type_index : inline_cache_it.second.classes) {
            os << separator << type_index.index_;
            separator = ",";
          }
        }
        os << "}";
      }
      os << "], ";
    }
    bool startup = true;
    while (true) {
      os << "\n\t" << (startup ? "startup methods: " : "post startup methods: ");
      for (uint32_t method_idx = 0; method_idx < dex_data->num_method_ids; ++method_idx) {
        MethodHotness hotness_info(dex_data->GetHotnessInfo(method_idx));
        if (startup ? hotness_info.IsStartup() : hotness_info.IsPostStartup()) {
          if (dex_file != nullptr) {
            os << "\n\t\t" << dex_file->PrettyMethod(method_idx, true);
          } else {
            os << method_idx << ", ";
          }
        }
      }
      if (startup == false) {
        break;
      }
      startup = false;
    }
    os << "\n\tclasses: ";
    for (dex::TypeIndex type_index : dex_data->class_set) {
      if (dex_file != nullptr) {
        os << "\n\t\t" << PrettyDescriptor(GetTypeDescriptor(dex_file, type_index));
      } else {
        os << type_index.index_ << ",";
      }
    }
  }
  return os.str();
}

bool ProfileCompilationInfo::GetClassesAndMethods(
    const DexFile& dex_file,
    /*out*/std::set<dex::TypeIndex>* class_set,
    /*out*/std::set<uint16_t>* hot_method_set,
    /*out*/std::set<uint16_t>* startup_method_set,
    /*out*/std::set<uint16_t>* post_startup_method_method_set,
    const ProfileSampleAnnotation& annotation) const {
  std::set<std::string> ret;
  const DexFileData* dex_data = FindDexDataUsingAnnotations(&dex_file, annotation);
  if (dex_data == nullptr) {
    return false;
  }
  for (const auto& it : dex_data->method_map) {
    hot_method_set->insert(it.first);
  }
  for (uint32_t method_idx = 0; method_idx < dex_data->num_method_ids; ++method_idx) {
    MethodHotness hotness = dex_data->GetHotnessInfo(method_idx);
    if (hotness.IsStartup()) {
      startup_method_set->insert(method_idx);
    }
    if (hotness.IsPostStartup()) {
      post_startup_method_method_set->insert(method_idx);
    }
  }
  for (const dex::TypeIndex& type_index : dex_data->class_set) {
    class_set->insert(type_index);
  }
  return true;
}

const ArenaSet<dex::TypeIndex>* ProfileCompilationInfo::GetClasses(
    const DexFile& dex_file,
    const ProfileSampleAnnotation& annotation) const {
  const DexFileData* dex_data = FindDexDataUsingAnnotations(&dex_file, annotation);
  if (dex_data == nullptr) {
    return nullptr;
  }
  return &dex_data->class_set;
}

bool ProfileCompilationInfo::SameVersion(const ProfileCompilationInfo& other) const {
  return memcmp(version_, other.version_, kProfileVersionSize) == 0;
}

bool ProfileCompilationInfo::Equals(const ProfileCompilationInfo& other) {
  // No need to compare profile_key_map_. That's only a cache for fast search.
  // All the information is already in the info_ vector.
  if (!SameVersion(other)) {
    return false;
  }
  if (info_.size() != other.info_.size()) {
    return false;
  }
  for (size_t i = 0; i < info_.size(); i++) {
    const DexFileData& dex_data = *info_[i];
    const DexFileData& other_dex_data = *other.info_[i];
    if (!(dex_data == other_dex_data)) {
      return false;
    }
  }

  return true;
}

// Naive implementation to generate a random profile file suitable for testing.
bool ProfileCompilationInfo::GenerateTestProfile(int fd,
                                                 uint16_t number_of_dex_files,
                                                 uint16_t method_percentage,
                                                 uint16_t class_percentage,
                                                 uint32_t random_seed) {
  const std::string base_dex_location = "base.apk";
  ProfileCompilationInfo info;
  // The limits are defined by the dex specification.
  const uint16_t max_methods = std::numeric_limits<uint16_t>::max();
  const uint16_t max_classes = std::numeric_limits<uint16_t>::max();
  uint16_t number_of_methods = max_methods * method_percentage / 100;
  uint16_t number_of_classes = max_classes * class_percentage / 100;

  std::srand(random_seed);

  // Make sure we generate more samples with a low index value.
  // This makes it more likely to hit valid method/class indices in small apps.
  const uint16_t kFavorFirstN = 10000;
  const uint16_t kFavorSplit = 2;

  for (uint16_t i = 0; i < number_of_dex_files; i++) {
    std::string dex_location = DexFileLoader::GetMultiDexLocation(i, base_dex_location.c_str());
    std::string profile_key = info.GetProfileDexFileBaseKey(dex_location);

    DexFileData* const data =
        info.GetOrAddDexFileData(profile_key, /*checksum=*/ 0, max_classes, max_methods);
    for (uint16_t m = 0; m < number_of_methods; m++) {
      uint16_t method_idx = rand() % max_methods;
      if (m < (number_of_methods / kFavorSplit)) {
        method_idx %= kFavorFirstN;
      }
      // Alternate between startup and post startup.
      uint32_t flags = MethodHotness::kFlagHot;
      flags |= ((m & 1) != 0) ? MethodHotness::kFlagPostStartup : MethodHotness::kFlagStartup;
      data->AddMethod(static_cast<MethodHotness::Flag>(flags), method_idx);
    }

    for (uint16_t c = 0; c < number_of_classes; c++) {
      uint16_t type_idx = rand() % max_classes;
      if (c < (number_of_classes / kFavorSplit)) {
        type_idx %= kFavorFirstN;
      }
      data->class_set.insert(dex::TypeIndex(type_idx));
    }
  }
  return info.Save(fd);
}

// Naive implementation to generate a random profile file suitable for testing.
// Description of random selection:
// * Select a random starting point S.
// * For every index i, add (S+i) % (N - total number of methods/classes) to profile with the
//   probably of 1/(N - i - number of methods/classes needed to add in profile).
bool ProfileCompilationInfo::GenerateTestProfile(
    int fd,
    std::vector<std::unique_ptr<const DexFile>>& dex_files,
    uint16_t method_percentage,
    uint16_t class_percentage,
    uint32_t random_seed) {
  ProfileCompilationInfo info;
  std::default_random_engine rng(random_seed);
  auto create_shuffled_range = [&rng](uint32_t take, uint32_t out_of) {
    CHECK_LE(take, out_of);
    std::vector<uint32_t> vec(out_of);
    std::iota(vec.begin(), vec.end(), 0u);
    std::shuffle(vec.begin(), vec.end(), rng);
    vec.erase(vec.begin() + take, vec.end());
    std::sort(vec.begin(), vec.end());
    return vec;
  };
  for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    const std::string& dex_location = dex_file->GetLocation();
    std::string profile_key = info.GetProfileDexFileBaseKey(dex_location);
    uint32_t checksum = dex_file->GetLocationChecksum();

    uint32_t number_of_classes = dex_file->NumClassDefs();
    uint32_t classes_required_in_profile = (number_of_classes * class_percentage) / 100;

    DexFileData* const data = info.GetOrAddDexFileData(
          profile_key, checksum, dex_file->NumTypeIds(), dex_file->NumMethodIds());
    for (uint32_t class_index : create_shuffled_range(classes_required_in_profile,
                                                      number_of_classes)) {
      data->class_set.insert(dex_file->GetClassDef(class_index).class_idx_);
    }

    uint32_t number_of_methods = dex_file->NumMethodIds();
    uint32_t methods_required_in_profile = (number_of_methods * method_percentage) / 100;
    for (uint32_t method_index : create_shuffled_range(methods_required_in_profile,
                                                       number_of_methods)) {
      // Alternate between startup and post startup.
      uint32_t flags = MethodHotness::kFlagHot;
      flags |= ((method_index & 1) != 0)
                   ? MethodHotness::kFlagPostStartup
                   : MethodHotness::kFlagStartup;
      data->AddMethod(static_cast<MethodHotness::Flag>(flags), method_index);
    }
  }
  return info.Save(fd);
}

bool ProfileCompilationInfo::IsEmpty() const {
  DCHECK_EQ(info_.size(), profile_key_map_.size());
  // Note that this doesn't look at the bitmap region, so we will return true
  // when the profile contains only non-hot methods. This is generally ok
  // as for speed-profile to be useful we do need hot methods and resolved classes.
  return GetNumberOfMethods() == 0 && GetNumberOfResolvedClasses() == 0;
}

ProfileCompilationInfo::InlineCacheMap*
ProfileCompilationInfo::DexFileData::FindOrAddHotMethod(uint16_t method_index) {
  if (method_index >= num_method_ids) {
    LOG(ERROR) << "Invalid method index " << method_index << ". num_method_ids=" << num_method_ids;
    return nullptr;
  }
  return &(method_map.FindOrAdd(
      method_index,
      InlineCacheMap(std::less<uint16_t>(), allocator_->Adapter(kArenaAllocProfile)))->second);
}

// Mark a method as executed at least once.
bool ProfileCompilationInfo::DexFileData::AddMethod(MethodHotness::Flag flags, size_t index) {
  if (index >= num_method_ids || index > kMaxSupportedMethodIndex) {
    LOG(ERROR) << "Invalid method index " << index << ". num_method_ids=" << num_method_ids
        << ", max: " << kMaxSupportedMethodIndex;
    return false;
  }

  SetMethodHotness(index, flags);

  if ((flags & MethodHotness::kFlagHot) != 0) {
    ProfileCompilationInfo::InlineCacheMap* result = FindOrAddHotMethod(index);
    DCHECK(result != nullptr);
  }
  return true;
}

void ProfileCompilationInfo::DexFileData::SetMethodHotness(size_t index,
                                                           MethodHotness::Flag flags) {
  DCHECK_LT(index, num_method_ids);
  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
    if ((flags & flag) != 0) {
      method_bitmap.StoreBit(MethodFlagBitmapIndex(
          static_cast<MethodHotness::Flag>(flag), index), /*value=*/ true);
    }
    return true;
  });
}

ProfileCompilationInfo::MethodHotness ProfileCompilationInfo::DexFileData::GetHotnessInfo(
    uint32_t dex_method_index) const {
  MethodHotness ret;
  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
    if (method_bitmap.LoadBit(MethodFlagBitmapIndex(
            static_cast<MethodHotness::Flag>(flag), dex_method_index))) {
      ret.AddFlag(static_cast<MethodHotness::Flag>(flag));
    }
    return true;
  });
  auto it = method_map.find(dex_method_index);
  if (it != method_map.end()) {
    ret.SetInlineCacheMap(&it->second);
    ret.AddFlag(MethodHotness::kFlagHot);
  }
  return ret;
}

// To simplify the implementation we use the MethodHotness flag values as indexes into the internal
// bitmap representation. As such, they should never change unless the profile version is updated
// and the implementation changed accordingly.
static_assert(ProfileCompilationInfo::MethodHotness::kFlagFirst == 1 << 0);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagHot == 1 << 0);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagStartup == 1 << 1);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagPostStartup == 1 << 2);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagLastRegular == 1 << 2);
static_assert(ProfileCompilationInfo::MethodHotness::kFlag32bit == 1 << 3);
static_assert(ProfileCompilationInfo::MethodHotness::kFlag64bit == 1 << 4);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagSensitiveThread == 1 << 5);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagAmStartup == 1 << 6);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagAmPostStartup == 1 << 7);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagBoot == 1 << 8);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagPostBoot == 1 << 9);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagStartupBin == 1 << 10);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagStartupMaxBin == 1 << 15);
static_assert(ProfileCompilationInfo::MethodHotness::kFlagLastBoot == 1 << 15);

uint16_t ProfileCompilationInfo::DexFileData::GetUsedBitmapFlags() const {
  uint32_t used_flags = 0u;
  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
    size_t index = FlagBitmapIndex(static_cast<MethodHotness::Flag>(flag));
    if (method_bitmap.HasSomeBitSet(index * num_method_ids, num_method_ids)) {
      used_flags |= flag;
    }
    return true;
  });
  return dchecked_integral_cast<uint16_t>(used_flags);
}

ProfileCompilationInfo::DexPcData*
ProfileCompilationInfo::FindOrAddDexPc(InlineCacheMap* inline_cache, uint32_t dex_pc) {
  return &(inline_cache->FindOrAdd(dex_pc, DexPcData(inline_cache->get_allocator()))->second);
}

HashSet<std::string> ProfileCompilationInfo::GetClassDescriptors(
    const std::vector<const DexFile*>& dex_files,
    const ProfileSampleAnnotation& annotation) {
  HashSet<std::string> ret;
  for (const DexFile* dex_file : dex_files) {
    const DexFileData* data = FindDexDataUsingAnnotations(dex_file, annotation);
    if (data != nullptr) {
      for (dex::TypeIndex type_idx : data->class_set) {
        ret.insert(GetTypeDescriptor(dex_file, type_idx));
      }
    } else {
      VLOG(compiler) << "Failed to find profile data for " << dex_file->GetLocation();
    }
  }
  return ret;
}

bool ProfileCompilationInfo::IsProfileFile(int fd) {
  // First check if it's an empty file as we allow empty profile files.
  // Profiles may be created by ActivityManager or installd before we manage to
  // process them in the runtime or profman.
  struct stat stat_buffer;
  if (fstat(fd, &stat_buffer) != 0) {
    return false;
  }

  if (stat_buffer.st_size == 0) {
    return true;
  }

  // The files is not empty. Check if it contains the profile magic.
  size_t byte_count = sizeof(kProfileMagic);
  uint8_t buffer[sizeof(kProfileMagic)];
  if (!android::base::ReadFullyAtOffset(fd, buffer, byte_count, /*offset=*/ 0)) {
    return false;
  }

  // Reset the offset to prepare the file for reading.
  off_t rc =  TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET));
  if (rc == static_cast<off_t>(-1)) {
    PLOG(ERROR) << "Failed to reset the offset";
    return false;
  }

  return memcmp(buffer, kProfileMagic, byte_count) == 0;
}

bool ProfileCompilationInfo::UpdateProfileKeys(
    const std::vector<std::unique_ptr<const DexFile>>& dex_files, /*out*/ bool* matched) {
  // This check aligns with when dex2oat falls back from "speed-profile" to "verify".
  //
  // ART Service relies on the exit code of profman, which is determined by the value of `matched`,
  // to judge whether it should re-dexopt for "speed-profile". Therefore, a misalignment will cause
  // repeated dexopt.
  if (IsEmpty()) {
    *matched = false;
    return true;
  }
  DCHECK(!info_.empty());

  *matched = true;

  // A map from the old base key to the new base key.
  std::unordered_map<std::string, std::string> old_key_to_new_key;

  // A map from the new base key to all matching old base keys (an invert of the map above), for
  // detecting duplicate keys.
  std::unordered_map<std::string, std::unordered_set<std::string>> new_key_to_old_keys;

  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    std::string old_base_key = GetBaseKeyFromAugmentedKey(dex_data->profile_key);
    bool found = false;
    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
      if (dex_data->checksum == dex_file->GetLocationChecksum() &&
          dex_data->num_type_ids == dex_file->NumTypeIds() &&
          dex_data->num_method_ids == dex_file->NumMethodIds()) {
        std::string new_base_key = GetProfileDexFileBaseKey(dex_file->GetLocation());
        old_key_to_new_key[old_base_key] = new_base_key;
        new_key_to_old_keys[new_base_key].insert(old_base_key);
        found = true;
        break;
      }
    }
    if (!found) {
      *matched = false;
      // Keep the old key.
      old_key_to_new_key[old_base_key] = old_base_key;
      new_key_to_old_keys[old_base_key].insert(old_base_key);
    }
  }

  for (const auto& [new_key, old_keys] : new_key_to_old_keys) {
    if (old_keys.size() > 1) {
      LOG(ERROR) << "Cannot update multiple profile keys [" << android::base::Join(old_keys, ", ")
                 << "] to the same new key '" << new_key << "'";
      return false;
    }
  }

  // Check passed. Now perform the actual mutation.
  profile_key_map_.clear();

  for (const std::unique_ptr<DexFileData>& dex_data : info_) {
    std::string old_base_key = GetBaseKeyFromAugmentedKey(dex_data->profile_key);
    const std::string& new_base_key = old_key_to_new_key[old_base_key];
    DCHECK(!new_base_key.empty());
    // Retain the annotation (if any) during the renaming by re-attaching the info from the old key.
    dex_data->profile_key = MigrateAnnotationInfo(new_base_key, dex_data->profile_key);
    profile_key_map_.Put(dex_data->profile_key, dex_data->profile_index);
  }

  return true;
}

bool ProfileCompilationInfo::ProfileFilterFnAcceptAll(
    const std::string& dex_location ATTRIBUTE_UNUSED,
    uint32_t checksum ATTRIBUTE_UNUSED) {
  return true;
}

void ProfileCompilationInfo::ClearData() {
  profile_key_map_.clear();
  info_.clear();
  extra_descriptors_indexes_.clear();
  extra_descriptors_.clear();
}

void ProfileCompilationInfo::ClearDataAndAdjustVersion(bool for_boot_image) {
  ClearData();
  memcpy(version_,
         for_boot_image ? kProfileVersionForBootImage : kProfileVersion,
         kProfileVersionSize);
}

bool ProfileCompilationInfo::IsForBootImage() const {
  return memcmp(version_, kProfileVersionForBootImage, sizeof(kProfileVersionForBootImage)) == 0;
}

const uint8_t* ProfileCompilationInfo::GetVersion() const {
  return version_;
}

bool ProfileCompilationInfo::DexFileData::ContainsClass(dex::TypeIndex type_index) const {
  return class_set.find(type_index) != class_set.end();
}

uint32_t ProfileCompilationInfo::DexFileData::ClassesDataSize() const {
  return class_set.empty()
      ? 0u
      : sizeof(ProfileIndexType) +            // Which dex file.
        sizeof(uint16_t) +                    // Number of classes.
        sizeof(uint16_t) * class_set.size();  // Type index diffs.
}

void ProfileCompilationInfo::DexFileData::WriteClasses(SafeBuffer& buffer) const {
  if (class_set.empty()) {
    return;
  }
  buffer.WriteUintAndAdvance(profile_index);
  buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(class_set.size()));
  WriteClassSet(buffer, class_set);
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::ReadClasses(
    SafeBuffer& buffer,
    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
    std::string* error) {
  uint16_t classes_size;
  if (!buffer.ReadUintAndAdvance(&classes_size)) {
    *error = "Error reading classes size.";
    return ProfileLoadStatus::kBadData;
  }
  uint16_t num_valid_type_indexes = dchecked_integral_cast<uint16_t>(
      std::min<size_t>(num_type_ids + extra_descriptors_remap.size(), DexFile::kDexNoIndex16));
  uint16_t type_index = 0u;
  for (size_t i = 0; i != classes_size; ++i) {
    uint16_t type_index_diff;
    if (!buffer.ReadUintAndAdvance(&type_index_diff)) {
      *error = "Error reading class type index diff.";
      return ProfileLoadStatus::kBadData;
    }
    if (type_index_diff == 0u && i != 0u) {
      *error = "Duplicate type index.";
      return ProfileLoadStatus::kBadData;
    }
    if (type_index_diff >= num_valid_type_indexes - type_index) {
      *error = "Invalid type index.";
      return ProfileLoadStatus::kBadData;
    }
    type_index += type_index_diff;
    if (type_index >= num_type_ids) {
      uint32_t new_extra_descriptor_index = extra_descriptors_remap[type_index - num_type_ids];
      if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
        *error = "Remapped type index out of range.";
        return ProfileLoadStatus::kMergeError;
      }
      class_set.insert(dex::TypeIndex(num_type_ids + new_extra_descriptor_index));
    } else {
      class_set.insert(dex::TypeIndex(type_index));
    }
  }
  return ProfileLoadStatus::kSuccess;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::SkipClasses(
    SafeBuffer& buffer,
    std::string* error) {
  uint16_t classes_size;
  if (!buffer.ReadUintAndAdvance(&classes_size)) {
    *error = "Error reading classes size to skip.";
    return ProfileLoadStatus::kBadData;
  }
  size_t following_data_size = static_cast<size_t>(classes_size) * sizeof(uint16_t);
  if (following_data_size > buffer.GetAvailableBytes()) {
    *error = "Classes data size to skip exceeds remaining data.";
    return ProfileLoadStatus::kBadData;
  }
  buffer.Advance(following_data_size);
  return ProfileLoadStatus::kSuccess;
}

uint32_t ProfileCompilationInfo::DexFileData::MethodsDataSize(
    /*out*/ uint16_t* method_flags,
    /*out*/ size_t* saved_bitmap_bit_size) const {
  uint16_t local_method_flags = GetUsedBitmapFlags();
  size_t local_saved_bitmap_bit_size = POPCOUNT(local_method_flags) * num_method_ids;
  if (!method_map.empty()) {
    local_method_flags |= enum_cast<uint16_t>(MethodHotness::kFlagHot);
  }
  size_t size = 0u;
  if (local_method_flags != 0u) {
    size_t num_hot_methods = method_map.size();
    size_t num_dex_pc_entries = 0u;
    size_t num_class_entries = 0u;
    for (const auto& method_entry : method_map) {
      const InlineCacheMap& inline_cache_map = method_entry.second;
      num_dex_pc_entries += inline_cache_map.size();
      for (const auto& inline_cache_entry : inline_cache_map) {
        const DexPcData& dex_pc_data = inline_cache_entry.second;
        num_class_entries += dex_pc_data.classes.size();
      }
    }

    constexpr size_t kPerHotMethodSize =
        sizeof(uint16_t) +  // Method index diff.
        sizeof(uint16_t);   // Inline cache size.
    constexpr size_t kPerDexPcEntrySize =
        sizeof(uint16_t) +  // Dex PC.
        sizeof(uint8_t);    // Number of inline cache classes.
    constexpr size_t kPerClassEntrySize =
        sizeof(uint16_t);   // Type index diff.

    size_t saved_bitmap_byte_size = BitsToBytesRoundUp(local_saved_bitmap_bit_size);
    size = sizeof(ProfileIndexType) +                 // Which dex file.
           sizeof(uint32_t) +                         // Total size of following data.
           sizeof(uint16_t) +                         // Method flags.
           saved_bitmap_byte_size +                   // Bitmap data.
           num_hot_methods * kPerHotMethodSize +      // Data for hot methods.
           num_dex_pc_entries * kPerDexPcEntrySize +  // Data for dex pc entries.
           num_class_entries * kPerClassEntrySize;    // Data for inline cache class entries.
  }
  if (method_flags != nullptr) {
    *method_flags = local_method_flags;
  }
  if (saved_bitmap_bit_size != nullptr) {
    *saved_bitmap_bit_size = local_saved_bitmap_bit_size;
  }
  return size;
}

void ProfileCompilationInfo::DexFileData::WriteMethods(SafeBuffer& buffer) const {
  uint16_t method_flags;
  size_t saved_bitmap_bit_size;
  uint32_t methods_data_size = MethodsDataSize(&method_flags, &saved_bitmap_bit_size);
  if (methods_data_size == 0u) {
    return;  // No data to write.
  }
  DCHECK_GE(buffer.GetAvailableBytes(), methods_data_size);
  uint32_t expected_available_bytes_at_end = buffer.GetAvailableBytes() - methods_data_size;

  // Write the profile index.
  buffer.WriteUintAndAdvance(profile_index);
  // Write the total size of the following methods data (without the profile index
  // and the total size itself) for easy skipping when the dex file is filtered out.
  uint32_t following_data_size = methods_data_size - sizeof(ProfileIndexType) - sizeof(uint32_t);
  buffer.WriteUintAndAdvance(following_data_size);
  // Write the used method flags.
  buffer.WriteUintAndAdvance(method_flags);

  // Write the bitmap data.
  size_t saved_bitmap_byte_size = BitsToBytesRoundUp(saved_bitmap_bit_size);
  DCHECK_LE(saved_bitmap_byte_size, buffer.GetAvailableBytes());
  BitMemoryRegion saved_bitmap(buffer.GetCurrentPtr(), /*bit_start=*/ 0, saved_bitmap_bit_size);
  size_t saved_bitmap_index = 0u;
  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
    if ((method_flags & flag) != 0u) {
      size_t index = FlagBitmapIndex(static_cast<MethodHotness::Flag>(flag));
      BitMemoryRegion src = method_bitmap.Subregion(index * num_method_ids, num_method_ids);
      saved_bitmap.Subregion(saved_bitmap_index * num_method_ids, num_method_ids).CopyBits(src);
      ++saved_bitmap_index;
    }
    return true;
  });
  DCHECK_EQ(saved_bitmap_index * num_method_ids, saved_bitmap_bit_size);
  // Clear the padding bits.
  size_t padding_bit_size = saved_bitmap_byte_size * kBitsPerByte - saved_bitmap_bit_size;
  BitMemoryRegion padding_region(buffer.GetCurrentPtr(), saved_bitmap_bit_size, padding_bit_size);
  padding_region.StoreBits(/*bit_offset=*/ 0u, /*value=*/ 0u, /*bit_length=*/ padding_bit_size);
  buffer.Advance(saved_bitmap_byte_size);

  uint16_t last_method_index = 0;
  for (const auto& method_entry : method_map) {
    uint16_t method_index = method_entry.first;
    const InlineCacheMap& inline_cache_map = method_entry.second;

    // Store the difference between the method indices for better compression.
    // The SafeMap is ordered by method_id, so the difference will always be non negative.
    DCHECK_GE(method_index, last_method_index);
    uint16_t diff_with_last_method_index = method_index - last_method_index;
    last_method_index = method_index;
    buffer.WriteUintAndAdvance(diff_with_last_method_index);

    // Add inline cache map size.
    buffer.WriteUintAndAdvance(dchecked_integral_cast<uint16_t>(inline_cache_map.size()));

    // Add inline cache entries.
    for (const auto& inline_cache_entry : inline_cache_map) {
      uint16_t dex_pc = inline_cache_entry.first;
      const DexPcData& dex_pc_data = inline_cache_entry.second;
      const ArenaSet<dex::TypeIndex>& classes = dex_pc_data.classes;

      // Add the dex pc.
      buffer.WriteUintAndAdvance(dex_pc);

      // Add the megamorphic/missing_types encoding if needed and continue.
      // In either cases we don't add any classes to the profiles and so there's
      // no point to continue.
      // TODO: in case we miss types there is still value to add the rest of the
      // classes. (This requires changing profile version or using a new section type.)
      if (dex_pc_data.is_missing_types) {
        // At this point the megamorphic flag should not be set.
        DCHECK(!dex_pc_data.is_megamorphic);
        DCHECK_EQ(classes.size(), 0u);
        buffer.WriteUintAndAdvance(kIsMissingTypesEncoding);
        continue;
      } else if (dex_pc_data.is_megamorphic) {
        DCHECK_EQ(classes.size(), 0u);
        buffer.WriteUintAndAdvance(kIsMegamorphicEncoding);
        continue;
      }

      DCHECK_LT(classes.size(), ProfileCompilationInfo::kIndividualInlineCacheSize);
      DCHECK_NE(classes.size(), 0u) << "InlineCache contains a dex_pc with 0 classes";

      // Add the number of classes for the dex PC.
      buffer.WriteUintAndAdvance(dchecked_integral_cast<uint8_t>(classes.size()));
      // Store the class set.
      WriteClassSet(buffer, classes);
    }
  }

  // Check if we've written the right number of bytes.
  DCHECK_EQ(buffer.GetAvailableBytes(), expected_available_bytes_at_end);
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::ReadMethods(
    SafeBuffer& buffer,
    const dchecked_vector<ExtraDescriptorIndex>& extra_descriptors_remap,
    std::string* error) {
  uint32_t following_data_size;
  if (!buffer.ReadUintAndAdvance(&following_data_size)) {
    *error = "Error reading methods data size.";
    return ProfileLoadStatus::kBadData;
  }
  if (following_data_size > buffer.GetAvailableBytes()) {
    *error = "Methods data size exceeds available data size.";
    return ProfileLoadStatus::kBadData;
  }
  uint32_t expected_available_bytes_at_end = buffer.GetAvailableBytes() - following_data_size;

  // Read method flags.
  uint16_t method_flags;
  if (!buffer.ReadUintAndAdvance(&method_flags)) {
    *error = "Error reading method flags.";
    return ProfileLoadStatus::kBadData;
  }
  if (!is_for_boot_image && method_flags >= (MethodHotness::kFlagLastRegular << 1)) {
    // The profile we're loading contains data for boot image.
    *error = "Method flags contain boot image profile flags for non-boot image profile.";
    return ProfileLoadStatus::kBadData;
  }

  // Read method bitmap.
  size_t saved_bitmap_bit_size = POPCOUNT(method_flags & ~MethodHotness::kFlagHot) * num_method_ids;
  size_t saved_bitmap_byte_size = BitsToBytesRoundUp(saved_bitmap_bit_size);
  if (sizeof(uint16_t) + saved_bitmap_byte_size > following_data_size) {
    *error = "Insufficient available data for method bitmap.";
    return ProfileLoadStatus::kBadData;
  }
  BitMemoryRegion saved_bitmap(buffer.GetCurrentPtr(), /*bit_start=*/ 0, saved_bitmap_bit_size);
  size_t saved_bitmap_index = 0u;
  ForMethodBitmapHotnessFlags([&](MethodHotness::Flag flag) {
    if ((method_flags & flag) != 0u) {
      size_t index = FlagBitmapIndex(static_cast<MethodHotness::Flag>(flag));
      BitMemoryRegion src =
          saved_bitmap.Subregion(saved_bitmap_index * num_method_ids, num_method_ids);
      method_bitmap.Subregion(index * num_method_ids, num_method_ids).OrBits(src);
      ++saved_bitmap_index;
    }
    return true;
  });
  buffer.Advance(saved_bitmap_byte_size);

  // Load hot methods.
  if ((method_flags & MethodHotness::kFlagHot) != 0u) {
    uint32_t num_valid_method_indexes =
        std::min<uint32_t>(kMaxSupportedMethodIndex + 1u, num_method_ids);
    uint16_t num_valid_type_indexes = dchecked_integral_cast<uint16_t>(
        std::min<size_t>(num_type_ids + extra_descriptors_remap.size(), DexFile::kDexNoIndex16));
    uint16_t method_index = 0;
    bool first_diff = true;
    while (buffer.GetAvailableBytes() > expected_available_bytes_at_end) {
      uint16_t diff_with_last_method_index;
      if (!buffer.ReadUintAndAdvance(&diff_with_last_method_index)) {
        *error = "Error reading method index diff.";
        return ProfileLoadStatus::kBadData;
      }
      if (diff_with_last_method_index == 0u && !first_diff) {
        *error = "Duplicate method index.";
        return ProfileLoadStatus::kBadData;
      }
      first_diff = false;
      if (diff_with_last_method_index >= num_valid_method_indexes - method_index) {
        *error = "Invalid method index.";
        return ProfileLoadStatus::kBadData;
      }
      method_index += diff_with_last_method_index;
      InlineCacheMap* inline_cache = FindOrAddHotMethod(method_index);
      DCHECK(inline_cache != nullptr);

      // Load inline cache map size.
      uint16_t inline_cache_size;
      if (!buffer.ReadUintAndAdvance(&inline_cache_size)) {
        *error = "Error reading inline cache size.";
        return ProfileLoadStatus::kBadData;
      }
      for (uint16_t ic_index = 0; ic_index != inline_cache_size; ++ic_index) {
        // Load dex pc.
        uint16_t dex_pc;
        if (!buffer.ReadUintAndAdvance(&dex_pc)) {
          *error = "Error reading inline cache dex pc.";
          return ProfileLoadStatus::kBadData;
        }
        DexPcData* dex_pc_data = FindOrAddDexPc(inline_cache, dex_pc);
        DCHECK(dex_pc_data != nullptr);

        // Load inline cache classes.
        uint8_t inline_cache_classes_size;
        if (!buffer.ReadUintAndAdvance(&inline_cache_classes_size)) {
          *error = "Error reading inline cache classes size.";
          return ProfileLoadStatus::kBadData;
        }
        if (inline_cache_classes_size == kIsMissingTypesEncoding) {
          dex_pc_data->SetIsMissingTypes();
        } else if (inline_cache_classes_size == kIsMegamorphicEncoding) {
          dex_pc_data->SetIsMegamorphic();
        } else if (inline_cache_classes_size >= kIndividualInlineCacheSize) {
          *error = "Inline cache size too large.";
          return ProfileLoadStatus::kBadData;
        } else {
          uint16_t type_index = 0u;
          for (size_t i = 0; i != inline_cache_classes_size; ++i) {
            uint16_t type_index_diff;
            if (!buffer.ReadUintAndAdvance(&type_index_diff)) {
              *error = "Error reading inline cache type index diff.";
              return ProfileLoadStatus::kBadData;
            }
            if (type_index_diff == 0u && i != 0u) {
              *error = "Duplicate inline cache type index.";
              return ProfileLoadStatus::kBadData;
            }
            if (type_index_diff >= num_valid_type_indexes - type_index) {
              *error = "Invalid inline cache type index.";
              return ProfileLoadStatus::kBadData;
            }
            type_index += type_index_diff;
            if (type_index >= num_type_ids) {
              ExtraDescriptorIndex new_extra_descriptor_index =
                  extra_descriptors_remap[type_index - num_type_ids];
              if (new_extra_descriptor_index >= DexFile::kDexNoIndex16 - num_type_ids) {
                *error = "Remapped inline cache type index out of range.";
                return ProfileLoadStatus::kMergeError;
              }
              dex_pc_data->AddClass(dex::TypeIndex(num_type_ids + new_extra_descriptor_index));
            } else {
              dex_pc_data->AddClass(dex::TypeIndex(type_index));
            }
          }
        }
      }
    }
  }

  if (buffer.GetAvailableBytes() != expected_available_bytes_at_end) {
    *error = "Methods data did not end at expected position.";
    return ProfileLoadStatus::kBadData;
  }

  return ProfileLoadStatus::kSuccess;
}

ProfileCompilationInfo::ProfileLoadStatus ProfileCompilationInfo::DexFileData::SkipMethods(
    SafeBuffer& buffer,
    std::string* error) {
  uint32_t following_data_size;
  if (!buffer.ReadUintAndAdvance(&following_data_size)) {
    *error = "Error reading methods data size to skip.";
    return ProfileLoadStatus::kBadData;
  }
  if (following_data_size > buffer.GetAvailableBytes()) {
    *error = "Methods data size to skip exceeds remaining data.";
    return ProfileLoadStatus::kBadData;
  }
  buffer.Advance(following_data_size);
  return ProfileLoadStatus::kSuccess;
}

void ProfileCompilationInfo::DexFileData::WriteClassSet(
    SafeBuffer& buffer,
    const ArenaSet<dex::TypeIndex>& class_set) {
  // Store the difference between the type indexes for better compression.
  uint16_t last_type_index = 0u;
  for (const dex::TypeIndex& type_index : class_set) {
    DCHECK_GE(type_index.index_, last_type_index);
    uint16_t diff_with_last_type_index = type_index.index_ - last_type_index;
    last_type_index = type_index.index_;
    buffer.WriteUintAndAdvance(diff_with_last_type_index);
  }
}

size_t ProfileCompilationInfo::GetSizeWarningThresholdBytes() const {
  return IsForBootImage() ?  kSizeWarningThresholdBootBytes : kSizeWarningThresholdBytes;
}

size_t ProfileCompilationInfo::GetSizeErrorThresholdBytes() const {
  return IsForBootImage() ?  kSizeErrorThresholdBootBytes : kSizeErrorThresholdBytes;
}

std::ostream& operator<<(std::ostream& stream,
                         ProfileCompilationInfo::DexReferenceDumper dumper) {
  stream << "[profile_key=" << dumper.GetProfileKey()
         << ",dex_checksum=" << std::hex << dumper.GetDexChecksum() << std::dec
         << ",num_type_ids=" << dumper.GetNumTypeIds()
         << ",num_method_ids=" << dumper.GetNumMethodIds()
         << "]";
  return stream;
}

FlattenProfileData::FlattenProfileData() :
    max_aggregation_for_methods_(0),
    max_aggregation_for_classes_(0) {
}

FlattenProfileData::ItemMetadata::ItemMetadata() :
    flags_(0) {
}

FlattenProfileData::ItemMetadata::ItemMetadata(const ItemMetadata& other) :
    flags_(other.flags_),
    annotations_(other.annotations_) {
}

std::unique_ptr<FlattenProfileData> ProfileCompilationInfo::ExtractProfileData(
    const std::vector<std::unique_ptr<const DexFile>>& dex_files) const {

  std::unique_ptr<FlattenProfileData> result(new FlattenProfileData());

  auto create_metadata_fn = []() { return FlattenProfileData::ItemMetadata(); };

  // Iterate through all the dex files, find the methods/classes associated with each of them,
  // and add them to the flatten result.
  for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
    // Find all the dex data for the given dex file.
    // We may have multiple dex data if the methods or classes were added using
    // different annotations.
    std::vector<const DexFileData*> all_dex_data;
    FindAllDexData(dex_file.get(), &all_dex_data);
    for (const DexFileData* dex_data : all_dex_data) {
      // Extract the annotation from the key as we want to store it in the flatten result.
      ProfileSampleAnnotation annotation = GetAnnotationFromKey(dex_data->profile_key);

      // Check which methods from the current dex files are in the profile.
      for (uint32_t method_idx = 0; method_idx < dex_data->num_method_ids; ++method_idx) {
        MethodHotness hotness = dex_data->GetHotnessInfo(method_idx);
        if (!hotness.IsInProfile()) {
          // Not in the profile, continue.
          continue;
        }
        // The method is in the profile, create metadata item for it and added to the result.
        MethodReference ref(dex_file.get(), method_idx);
        FlattenProfileData::ItemMetadata& metadata =
            result->method_metadata_.GetOrCreate(ref, create_metadata_fn);
        metadata.flags_ |= hotness.flags_;
        metadata.annotations_.push_back(annotation);
        // Update the max aggregation counter for methods.
        // This is essentially a cache, to avoid traversing all the methods just to find out
        // this value.
        result->max_aggregation_for_methods_ = std::max(
            result->max_aggregation_for_methods_,
            static_cast<uint32_t>(metadata.annotations_.size()));
      }

      // Check which classes from the current dex files are in the profile.
      for (const dex::TypeIndex& type_index : dex_data->class_set) {
        if (type_index.index_ >= dex_file->NumTypeIds()) {
          // Not a valid `dex::TypeIndex` for `TypeReference`.
          // TODO: Rewrite the API to use descriptors or the `ProfileCompilationInfo` directly
          // instead of the `FlattenProfileData` helper class.
          continue;
        }
        TypeReference ref(dex_file.get(), type_index);
        FlattenProfileData::ItemMetadata& metadata =
            result->class_metadata_.GetOrCreate(ref, create_metadata_fn);
        metadata.annotations_.push_back(annotation);
        // Update the max aggregation counter for classes.
        result->max_aggregation_for_classes_ = std::max(
            result->max_aggregation_for_classes_,
            static_cast<uint32_t>(metadata.annotations_.size()));
      }
    }
  }

  return result;
}

void FlattenProfileData::MergeData(const FlattenProfileData& other) {
  auto create_metadata_fn = []() { return FlattenProfileData::ItemMetadata(); };
  for (const auto& it : other.method_metadata_) {
    const MethodReference& otherRef = it.first;
    const FlattenProfileData::ItemMetadata otherData = it.second;
    const std::list<ProfileCompilationInfo::ProfileSampleAnnotation>& other_annotations =
        otherData.GetAnnotations();

    FlattenProfileData::ItemMetadata& metadata =
        method_metadata_.GetOrCreate(otherRef, create_metadata_fn);
    metadata.flags_ |= otherData.GetFlags();
    metadata.annotations_.insert(
        metadata.annotations_.end(), other_annotations.begin(), other_annotations.end());

    max_aggregation_for_methods_ = std::max(
          max_aggregation_for_methods_,
          static_cast<uint32_t>(metadata.annotations_.size()));
  }
  for (const auto& it : other.class_metadata_) {
    const TypeReference& otherRef = it.first;
    const FlattenProfileData::ItemMetadata otherData = it.second;
    const std::list<ProfileCompilationInfo::ProfileSampleAnnotation>& other_annotations =
        otherData.GetAnnotations();

    FlattenProfileData::ItemMetadata& metadata =
        class_metadata_.GetOrCreate(otherRef, create_metadata_fn);
    metadata.flags_ |= otherData.GetFlags();
    metadata.annotations_.insert(
        metadata.annotations_.end(), other_annotations.begin(), other_annotations.end());

    max_aggregation_for_classes_ = std::max(
          max_aggregation_for_classes_,
          static_cast<uint32_t>(metadata.annotations_.size()));
  }
}

}  // namespace art
