/*
 * Copyright (C) 2017 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 "boot_image_profile.h"

#include <memory>
#include <set>

#include "android-base/file.h"
#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
#include "profile/profile_compilation_info.h"
#include "inline_cache_format_util.h"

namespace art {

using Hotness = ProfileCompilationInfo::MethodHotness;

static const std::string kMethodSep = "->";  // NOLINT [runtime/string] [4]
static const std::string kPackageUseDelim = "@";  // NOLINT [runtime/string] [4]
static constexpr char kMethodFlagStringHot = 'H';
static constexpr char kMethodFlagStringStartup = 'S';
static constexpr char kMethodFlagStringPostStartup = 'P';

// Returns the type descriptor of the given reference.
static std::string GetTypeDescriptor(const TypeReference& ref) {
  const dex::TypeId& type_id = ref.dex_file->GetTypeId(ref.TypeIndex());
  return ref.dex_file->GetTypeDescriptor(type_id);
}

// Returns the method representation used in the text format of the boot image profile.
static std::string BootImageRepresentation(const MethodReference& ref) {
  const DexFile* dex_file = ref.dex_file;
  const dex::MethodId& id = ref.GetMethodId();
  std::string signature_string(dex_file->GetMethodSignature(id).ToString());
  std::string type_string(dex_file->GetTypeDescriptor(dex_file->GetTypeId(id.class_idx_)));
  std::string method_name(dex_file->GetMethodName(id));
  return type_string +
        kMethodSep +
        method_name +
        signature_string;
}

// Returns the class representation used in the text format of the boot image profile.
static std::string BootImageRepresentation(const TypeReference& ref) {
  return GetTypeDescriptor(ref);
}

// Returns the class representation used in preloaded classes.
static std::string PreloadedClassesRepresentation(const TypeReference& ref) {
  std::string descriptor = GetTypeDescriptor(ref);
  return DescriptorToDot(descriptor.c_str());
}

// Formats the list of packages from the item metadata as a debug string.
static std::string GetPackageUseString(const FlattenProfileData::ItemMetadata& metadata) {
  std::string result;
  for (const auto& it : metadata.GetAnnotations()) {
    result += it.GetOriginPackageName() + ",";
  }

  return metadata.GetAnnotations().empty()
      ? result
      : result.substr(0, result.size() - 1);
}

// Converts a method representation to its final profile format.
static std::string MethodToProfileFormat(
    const std::string& method,
    const FlattenProfileData::ItemMetadata& metadata,
    bool output_package_use) {
  std::string flags_string;
  if (metadata.HasFlagSet(Hotness::kFlagHot)) {
    flags_string += kMethodFlagStringHot;
  }
  if (metadata.HasFlagSet(Hotness::kFlagStartup)) {
    flags_string += kMethodFlagStringStartup;
  }
  if (metadata.HasFlagSet(Hotness::kFlagPostStartup)) {
    flags_string += kMethodFlagStringPostStartup;
  }
  std::string extra;
  if (output_package_use) {
    extra = kPackageUseDelim + GetPackageUseString(metadata);
  }

  std::string inline_cache_string = GetInlineCacheLine(metadata.GetInlineCache());
  return flags_string + method + extra + inline_cache_string;
}

// Converts a class representation to its final profile or preloaded classes format.
static std::string ClassToProfileFormat(
    const std::string& classString,
    const FlattenProfileData::ItemMetadata& metadata,
    bool output_package_use) {
  std::string extra;
  if (output_package_use) {
    extra = kPackageUseDelim + GetPackageUseString(metadata);
  }

  return classString + extra;
}

// Tries to asses if the given type reference is a clean class.
static bool MaybeIsClassClean(const TypeReference& ref) {
  const dex::ClassDef* class_def = ref.dex_file->FindClassDef(ref.TypeIndex());
  if (class_def == nullptr) {
    return false;
  }

  ClassAccessor accessor(*ref.dex_file, *class_def);
  for (auto& it : accessor.GetStaticFields()) {
    if (!it.IsFinal()) {
      // Not final static field will probably dirty the class.
      return false;
    }
  }
  for (auto& it : accessor.GetMethods()) {
    uint32_t flags = it.GetAccessFlags();
    if ((flags & kAccNative) != 0) {
      // Native method will get dirtied.
      return false;
    }
    if ((flags & kAccConstructor) != 0 && (flags & kAccStatic) != 0) {
      // Class initializer, may get dirtied (not sure).
      return false;
    }
  }

  return true;
}

// Returns true iff the item should be included in the profile.
// (i.e. it passes the given aggregation thresholds)
static bool IncludeItemInProfile(uint32_t max_aggregation_count,
                                 uint32_t item_threshold,
                                 const FlattenProfileData::ItemMetadata& metadata,
                                 const BootImageOptions& options) {
  CHECK_NE(max_aggregation_count, 0u);
  float item_percent = metadata.GetAnnotations().size() / static_cast<float>(max_aggregation_count);
  for (const auto& annotIt : metadata.GetAnnotations()) {
    const auto&thresholdIt =
        options.special_packages_thresholds.find(annotIt.GetOriginPackageName());
    if (thresholdIt != options.special_packages_thresholds.end()) {
      if (item_percent >= (thresholdIt->second / 100.f)) {
        return true;
      }
    }
  }
  return item_percent >= (item_threshold / 100.f);
}

// Returns true iff a method with the given metada should be included in the profile.
static bool IncludeMethodInProfile(uint32_t max_aggregation_count,
                                   const FlattenProfileData::ItemMetadata& metadata,
                                   const BootImageOptions& options) {
  return IncludeItemInProfile(max_aggregation_count, options.method_threshold, metadata, options);
}

// Returns true iff a class with the given metada should be included in the profile.
static bool IncludeClassInProfile(const TypeReference& type_ref,
                                  uint32_t max_aggregation_count,
                                  const FlattenProfileData::ItemMetadata& metadata,
                                  const BootImageOptions& options) {
  uint32_t threshold = MaybeIsClassClean(type_ref)
      ? options.image_class_clean_threshold
      : options.image_class_threshold;
  return IncludeItemInProfile(max_aggregation_count, threshold, metadata, options);
}

// Returns true iff a class with the given metada should be included in the list of
// prelaoded classes.
static bool IncludeInPreloadedClasses(const std::string& class_name,
                                      uint32_t max_aggregation_count,
                                      const FlattenProfileData::ItemMetadata& metadata,
                                      const BootImageOptions& options) {
  bool denylisted = options.preloaded_classes_denylist.find(class_name) !=
      options.preloaded_classes_denylist.end();
  return !denylisted && IncludeItemInProfile(
      max_aggregation_count, options.preloaded_class_threshold, metadata, options);
}

bool GenerateBootImageProfile(
    const std::vector<std::unique_ptr<const DexFile>>& dex_files,
    const std::vector<std::string>& profile_files,
    const BootImageOptions& options,
    const std::string& boot_profile_out_path,
    const std::string& preloaded_classes_out_path) {
  if (boot_profile_out_path.empty()) {
    LOG(ERROR) << "No output file specified";
    return false;
  }

  bool generate_preloaded_classes = !preloaded_classes_out_path.empty();

  std::unique_ptr<FlattenProfileData> flattend_data(new FlattenProfileData());
  for (const std::string& profile_file : profile_files) {
    ProfileCompilationInfo profile(/*for_boot_image=*/ true);
    if (!profile.Load(profile_file, /*clear_if_invalid=*/ false)) {
      LOG(ERROR) << "Profile is not a valid: " << profile_file;
      return false;
    }
    std::unique_ptr<FlattenProfileData> currentData = profile.ExtractProfileData(dex_files);
    flattend_data->MergeData(*currentData);
  }

  // We want the output sorted by the method/class name.
  // So we use an intermediate map for that.
  // There's no attempt to optimize this as it's not part of any critical path,
  // and mostly executed on hosts.
  SafeMap<std::string, FlattenProfileData::ItemMetadata> profile_methods;
  SafeMap<std::string, FlattenProfileData::ItemMetadata> profile_classes;
  SafeMap<std::string, FlattenProfileData::ItemMetadata> preloaded_classes;

  for (const auto& it : flattend_data->GetMethodData()) {
    if (IncludeMethodInProfile(flattend_data->GetMaxAggregationForMethods(), it.second, options)) {
      FlattenProfileData::ItemMetadata metadata(it.second);
      if (options.upgrade_startup_to_hot
          && ((metadata.GetFlags() & Hotness::Flag::kFlagStartup) != 0)) {
        metadata.AddFlag(Hotness::Flag::kFlagHot);
      }
      profile_methods.Put(BootImageRepresentation(it.first), metadata);
    }
  }

  for (const auto& it : flattend_data->GetClassData()) {
    const TypeReference& type_ref = it.first;
    const FlattenProfileData::ItemMetadata& metadata = it.second;
    if (IncludeClassInProfile(type_ref,
            flattend_data->GetMaxAggregationForClasses(),
            metadata,
            options)) {
      profile_classes.Put(BootImageRepresentation(it.first), it.second);
    }
    std::string preloaded_class_representation = PreloadedClassesRepresentation(it.first);
    if (generate_preloaded_classes && IncludeInPreloadedClasses(
            preloaded_class_representation,
            flattend_data->GetMaxAggregationForClasses(),
            metadata,
            options)) {
      preloaded_classes.Put(preloaded_class_representation, it.second);
    }
  }

  // Create the output content
  std::string profile_content;
  std::string preloaded_content;
  for (const auto& it : profile_classes) {
    profile_content += ClassToProfileFormat(it.first, it.second, options.append_package_use_list)
        + "\n";
  }
  for (const auto& it : profile_methods) {
    profile_content += MethodToProfileFormat(it.first, it.second, options.append_package_use_list)
        + "\n";
  }

  if (generate_preloaded_classes) {
    for (const auto& it : preloaded_classes) {
      preloaded_content +=
          ClassToProfileFormat(it.first, it.second, options.append_package_use_list) + "\n";
    }
  }

  return android::base::WriteStringToFile(profile_content, boot_profile_out_path)
      && (!generate_preloaded_classes
          || android::base::WriteStringToFile(preloaded_content, preloaded_classes_out_path));
}

}  // namespace art
