/*
 * 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 <memory>
#include <set>

#include "boot_image_profile.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
#include "profile/profile_compilation_info.h"

namespace art {

using Hotness = ProfileCompilationInfo::MethodHotness;

void GenerateBootImageProfile(
    const std::vector<std::unique_ptr<const DexFile>>& dex_files,
    const std::vector<std::unique_ptr<const ProfileCompilationInfo>>& profiles,
    const BootImageOptions& options,
    bool verbose,
    ProfileCompilationInfo* out_profile) {
  for (const std::unique_ptr<const ProfileCompilationInfo>& profile : profiles) {
    // Avoid merging classes since we may want to only add classes that fit a certain criteria.
    // If we merged the classes, every single class in each profile would be in the out_profile,
    // but we want to only included classes that are in at least a few profiles.
    out_profile->MergeWith(*profile, /*merge_classes*/ false);
  }

  // Image classes that were added because they are commonly used.
  size_t class_count = 0;
  // Image classes that were only added because they were clean.
  size_t clean_class_count = 0;
  // Total clean classes.
  size_t clean_count = 0;
  // Total dirty classes.
  size_t dirty_count = 0;

  for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
    // Inferred classes are classes inferred from method samples.
    std::set<std::pair<const ProfileCompilationInfo*, dex::TypeIndex>> inferred_classes;
    for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) {
      MethodReference ref(dex_file.get(), i);
      // This counter is how many profiles contain the method as sampled or hot.
      size_t counter = 0;
      for (const std::unique_ptr<const ProfileCompilationInfo>& profile : profiles) {
        Hotness hotness = profile->GetMethodHotness(ref);
        if (hotness.IsInProfile()) {
          ++counter;
          out_profile->AddMethodHotness(ref, hotness);
          inferred_classes.emplace(profile.get(), ref.GetMethodId().class_idx_);
        }
      }
      // If the counter is greater or equal to the compile threshold, mark the method as hot.
      // Note that all hot methods are also marked as hot in the out profile during the merging
      // process.
      if (counter >= options.compiled_method_threshold) {
        Hotness hotness;
        hotness.AddFlag(Hotness::kFlagHot);
        out_profile->AddMethodHotness(ref, hotness);
      }
    }
    // Walk all of the classes and add them to the profile if they meet the requirements.
    for (ClassAccessor accessor : dex_file->GetClasses()) {
      TypeReference ref(dex_file.get(), accessor.GetClassIdx());
      bool is_clean = true;
      auto method_visitor = [&](const ClassAccessor::Method& method) {
        const uint32_t flags = method.GetAccessFlags();
        if ((flags & kAccNative) != 0) {
          // Native method will get dirtied.
          is_clean = false;
        }
        if ((flags & kAccConstructor) != 0 && (flags & kAccStatic) != 0) {
          // Class initializer, may get dirtied (not sure).
          is_clean = false;
        }
      };
      accessor.VisitFieldsAndMethods(
          [&](const ClassAccessor::Field& field) {
            if (!field.IsFinal()) {
              // Not final static field will probably dirty the class.
              is_clean = false;
            }
          },
          /*instance_fields*/ VoidFunctor(),
          method_visitor,
          method_visitor);

      ++(is_clean ? clean_count : dirty_count);
      // This counter is how many profiles contain the class.
      size_t counter = 0;
      for (const std::unique_ptr<const ProfileCompilationInfo>& profile : profiles) {
        auto it = inferred_classes.find(std::make_pair(profile.get(), ref.TypeIndex()));
        if (it != inferred_classes.end() ||
            profile->ContainsClass(*ref.dex_file, ref.TypeIndex())) {
          ++counter;
        }
      }
      if (counter == 0) {
        continue;
      }
      if (counter >= options.image_class_theshold) {
        ++class_count;
        out_profile->AddClassForDex(ref);
      } else if (is_clean && counter >= options.image_class_clean_theshold) {
        ++clean_class_count;
        out_profile->AddClassForDex(ref);
      }
    }
  }
  if (verbose) {
    LOG(INFO) << "Image classes " << class_count + clean_class_count
              << " added because clean " << clean_class_count
              << " total clean " << clean_count << " total dirty " << dirty_count;
  }
}

}  // namespace art
