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

#include <type_traits>

#include "arch/instruction_set_features.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/callee_save_type.h"
#include "base/casts.h"
#include "base/enums.h"
#include "base/utils.h"
#include "class_linker.h"
#include "compiled_method-inl.h"
#include "dex/descriptors_names.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "jni/java_vm_ext.h"
#include "interpreter/interpreter.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache.h"
#include "mirror/object-inl.h"
#include "oat_quick_method_header.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "utils/atomic_dex_ref_map-inl.h"

namespace art {

CommonCompilerTest::CommonCompilerTest() {}
CommonCompilerTest::~CommonCompilerTest() {}

void CommonCompilerTest::MakeExecutable(ArtMethod* method) {
  CHECK(method != nullptr);

  const CompiledMethod* compiled_method = nullptr;
  if (!method->IsAbstract()) {
    mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
    const DexFile& dex_file = *dex_cache->GetDexFile();
    compiled_method =
        compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
                                                            method->GetDexMethodIndex()));
  }
  // If the code size is 0 it means the method was skipped due to profile guided compilation.
  if (compiled_method != nullptr && compiled_method->GetQuickCode().size() != 0u) {
    ArrayRef<const uint8_t> code = compiled_method->GetQuickCode();
    const uint32_t code_size = code.size();
    ArrayRef<const uint8_t> vmap_table = compiled_method->GetVmapTable();
    const uint32_t vmap_table_offset = vmap_table.empty() ? 0u
        : sizeof(OatQuickMethodHeader) + vmap_table.size();
    OatQuickMethodHeader method_header(vmap_table_offset);

    header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
    std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
    const size_t max_padding = GetInstructionSetAlignment(compiled_method->GetInstructionSet());
    const size_t size = vmap_table.size() + sizeof(method_header) + code_size;
    chunk->reserve(size + max_padding);
    chunk->resize(sizeof(method_header));
    static_assert(std::is_trivially_copyable<OatQuickMethodHeader>::value, "Cannot use memcpy");
    memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
    chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
    chunk->insert(chunk->end(), code.begin(), code.end());
    CHECK_EQ(chunk->size(), size);
    const void* unaligned_code_ptr = chunk->data() + (size - code_size);
    size_t offset = dchecked_integral_cast<size_t>(reinterpret_cast<uintptr_t>(unaligned_code_ptr));
    size_t padding = compiled_method->AlignCode(offset) - offset;
    // Make sure no resizing takes place.
    CHECK_GE(chunk->capacity(), chunk->size() + padding);
    chunk->insert(chunk->begin(), padding, 0);
    const void* code_ptr = reinterpret_cast<const uint8_t*>(unaligned_code_ptr) + padding;
    CHECK_EQ(code_ptr, static_cast<const void*>(chunk->data() + (chunk->size() - code_size)));
    MakeExecutable(code_ptr, code.size());
    const void* method_code = CompiledMethod::CodePointer(code_ptr,
                                                          compiled_method->GetInstructionSet());
    LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
    method->SetEntryPointFromQuickCompiledCode(method_code);
  } else {
    // No code? You must mean to go into the interpreter.
    // Or the generic JNI...
    class_linker_->SetEntryPointsToInterpreter(method);
  }
}

void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_length) {
  CHECK(code_start != nullptr);
  CHECK_NE(code_length, 0U);
  uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
  uintptr_t base = RoundDown(data, kPageSize);
  uintptr_t limit = RoundUp(data + code_length, kPageSize);
  uintptr_t len = limit - base;
  int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
  CHECK_EQ(result, 0);

  FlushInstructionCache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
}

void CommonCompilerTest::MakeExecutable(ObjPtr<mirror::ClassLoader> class_loader,
                                        const char* class_name) {
  std::string class_descriptor(DotToDescriptor(class_name));
  Thread* self = Thread::Current();
  StackHandleScope<1> hs(self);
  Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
  ObjPtr<mirror::Class> klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
  CHECK(klass != nullptr) << "Class not found " << class_name;
  PointerSize pointer_size = class_linker_->GetImagePointerSize();
  for (auto& m : klass->GetMethods(pointer_size)) {
    MakeExecutable(&m);
  }
}

// Get the set of image classes given to the compiler options in SetUp.
std::unique_ptr<HashSet<std::string>> CommonCompilerTest::GetImageClasses() {
  // Empty set: by default no classes are retained in the image.
  return std::make_unique<HashSet<std::string>>();
}

// Get ProfileCompilationInfo that should be passed to the driver.
ProfileCompilationInfo* CommonCompilerTest::GetProfileCompilationInfo() {
  // Null, profile information will not be taken into account.
  return nullptr;
}

void CommonCompilerTest::SetUp() {
  CommonRuntimeTest::SetUp();
  {
    ScopedObjectAccess soa(Thread::Current());

    runtime_->SetInstructionSet(instruction_set_);
    for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
      CalleeSaveType type = CalleeSaveType(i);
      if (!runtime_->HasCalleeSaveMethod(type)) {
        runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(), type);
      }
    }

    CreateCompilerDriver();
  }
  // Note: We cannot use MemMap because some tests tear down the Runtime and destroy
  // the gMaps, so when destroying the MemMap, the test would crash.
  inaccessible_page_ = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  CHECK(inaccessible_page_ != MAP_FAILED) << strerror(errno);
}

void CommonCompilerTest::ApplyInstructionSet() {
  // Copy local instruction_set_ and instruction_set_features_ to *compiler_options_;
  CHECK(instruction_set_features_ != nullptr);
  if (instruction_set_ == InstructionSet::kThumb2) {
    CHECK_EQ(InstructionSet::kArm, instruction_set_features_->GetInstructionSet());
  } else {
    CHECK_EQ(instruction_set_, instruction_set_features_->GetInstructionSet());
  }
  compiler_options_->instruction_set_ = instruction_set_;
  compiler_options_->instruction_set_features_ =
      InstructionSetFeatures::FromBitmap(instruction_set_, instruction_set_features_->AsBitmap());
  CHECK(compiler_options_->instruction_set_features_->Equals(instruction_set_features_.get()));
}

void CommonCompilerTest::OverrideInstructionSetFeatures(InstructionSet instruction_set,
                                                        const std::string& variant) {
  instruction_set_ = instruction_set;
  std::string error_msg;
  instruction_set_features_ =
      InstructionSetFeatures::FromVariant(instruction_set, variant, &error_msg);
  CHECK(instruction_set_features_ != nullptr) << error_msg;

  if (compiler_options_ != nullptr) {
    ApplyInstructionSet();
  }
}

void CommonCompilerTest::CreateCompilerDriver() {
  ApplyInstructionSet();

  compiler_options_->image_type_ = CompilerOptions::ImageType::kBootImage;
  compiler_options_->compile_pic_ = false;  // Non-PIC boot image is a test configuration.
  compiler_options_->SetCompilerFilter(GetCompilerFilter());
  compiler_options_->image_classes_.swap(*GetImageClasses());
  compiler_options_->profile_compilation_info_ = GetProfileCompilationInfo();
  compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
                                            compiler_kind_,
                                            number_of_threads_,
                                            /* swap_fd= */ -1));
}

void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
  CommonRuntimeTest::SetUpRuntimeOptions(options);

  compiler_options_.reset(new CompilerOptions);
  verification_results_.reset(new VerificationResults(compiler_options_.get()));
  QuickCompilerCallbacks* callbacks =
      new QuickCompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileApp);
  callbacks->SetVerificationResults(verification_results_.get());
  callbacks_.reset(callbacks);
}

Compiler::Kind CommonCompilerTest::GetCompilerKind() const {
  return compiler_kind_;
}

void CommonCompilerTest::SetCompilerKind(Compiler::Kind compiler_kind) {
  compiler_kind_ = compiler_kind;
}

void CommonCompilerTest::TearDown() {
  compiler_driver_.reset();
  callbacks_.reset();
  verification_results_.reset();
  compiler_options_.reset();
  image_reservation_.Reset();
  if (inaccessible_page_ != nullptr) {
    munmap(inaccessible_page_, kPageSize);
    inaccessible_page_ = nullptr;
  }

  CommonRuntimeTest::TearDown();
}

void CommonCompilerTest::CompileClass(mirror::ClassLoader* class_loader, const char* class_name) {
  std::string class_descriptor(DotToDescriptor(class_name));
  Thread* self = Thread::Current();
  StackHandleScope<1> hs(self);
  Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
  ObjPtr<mirror::Class> klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
  CHECK(klass != nullptr) << "Class not found " << class_name;
  auto pointer_size = class_linker_->GetImagePointerSize();
  for (auto& m : klass->GetMethods(pointer_size)) {
    CompileMethod(&m);
  }
}

void CommonCompilerTest::CompileMethod(ArtMethod* method) {
  CHECK(method != nullptr);
  TimingLogger timings("CommonCompilerTest::CompileMethod", false, false);
  TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
  {
    Thread* self = Thread::Current();
    jobject class_loader = self->GetJniEnv()->GetVm()->AddGlobalRef(self, method->GetClassLoader());

    DCHECK(!Runtime::Current()->IsStarted());
    const DexFile* dex_file = method->GetDexFile();
    uint16_t class_def_idx = method->GetClassDefIndex();
    uint32_t method_idx = method->GetDexMethodIndex();
    uint32_t access_flags = method->GetAccessFlags();
    InvokeType invoke_type = method->GetInvokeType();
    StackHandleScope<2> hs(self);
    Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
    Handle<mirror::ClassLoader> h_class_loader = hs.NewHandle(
        self->DecodeJObject(class_loader)->AsClassLoader());
    const dex::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());

    std::vector<const DexFile*> dex_files;
    dex_files.push_back(dex_file);

    // Go to native so that we don't block GC during compilation.
    ScopedThreadSuspension sts(self, kNative);

    compiler_driver_->InitializeThreadPools();

    compiler_driver_->PreCompile(class_loader,
                                 dex_files,
                                 &timings,
                                 &compiler_options_->image_classes_,
                                 verification_results_.get());

    // Verification results in the `callback_` should not be used during compilation.
    down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults(
        reinterpret_cast<VerificationResults*>(inaccessible_page_));
    compiler_options_->verification_results_ = verification_results_.get();
    compiler_driver_->CompileOne(self,
                                 class_loader,
                                 *dex_file,
                                 class_def_idx,
                                 method_idx,
                                 access_flags,
                                 invoke_type,
                                 code_item,
                                 dex_cache,
                                 h_class_loader);
    compiler_options_->verification_results_ = nullptr;
    down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults(
        verification_results_.get());

    compiler_driver_->FreeThreadPools();

    self->GetJniEnv()->DeleteGlobalRef(class_loader);
  }
  TimingLogger::ScopedTiming t2("MakeExecutable", &timings);
  MakeExecutable(method);
}

void CommonCompilerTest::CompileDirectMethod(Handle<mirror::ClassLoader> class_loader,
                                             const char* class_name, const char* method_name,
                                             const char* signature) {
  std::string class_descriptor(DotToDescriptor(class_name));
  Thread* self = Thread::Current();
  ObjPtr<mirror::Class> klass =
      class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
  CHECK(klass != nullptr) << "Class not found " << class_name;
  auto pointer_size = class_linker_->GetImagePointerSize();
  ArtMethod* method = klass->FindClassMethod(method_name, signature, pointer_size);
  CHECK(method != nullptr && method->IsDirect()) << "Direct method not found: "
      << class_name << "." << method_name << signature;
  CompileMethod(method);
}

void CommonCompilerTest::CompileVirtualMethod(Handle<mirror::ClassLoader> class_loader,
                                              const char* class_name, const char* method_name,
                                              const char* signature) {
  std::string class_descriptor(DotToDescriptor(class_name));
  Thread* self = Thread::Current();
  ObjPtr<mirror::Class> klass =
      class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
  CHECK(klass != nullptr) << "Class not found " << class_name;
  auto pointer_size = class_linker_->GetImagePointerSize();
  ArtMethod* method = klass->FindClassMethod(method_name, signature, pointer_size);
  CHECK(method != nullptr && !method->IsDirect()) << "Virtual method not found: "
      << class_name << "." << method_name << signature;
  CompileMethod(method);
}

void CommonCompilerTest::ReserveImageSpace() {
  // Reserve where the image will be loaded up front so that other parts of test set up don't
  // accidentally end up colliding with the fixed memory address when we need to load the image.
  std::string error_msg;
  MemMap::Init();
  image_reservation_ = MemMap::MapAnonymous("image reservation",
                                            reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS),
                                            (size_t)120 * 1024 * 1024,  // 120MB
                                            PROT_NONE,
                                            false /* no need for 4gb flag with fixed mmap */,
                                            /*reuse=*/ false,
                                            /*reservation=*/ nullptr,
                                            &error_msg);
  CHECK(image_reservation_.IsValid()) << error_msg;
}

void CommonCompilerTest::CompileAll(jobject class_loader,
                                    const std::vector<const DexFile*>& dex_files,
                                    TimingLogger* timings) {
  TimingLogger::ScopedTiming t(__FUNCTION__, timings);
  SetDexFilesForOatFile(dex_files);

  compiler_driver_->InitializeThreadPools();

  compiler_driver_->PreCompile(class_loader,
                               dex_files,
                               timings,
                               &compiler_options_->image_classes_,
                               verification_results_.get());

  // Verification results in the `callback_` should not be used during compilation.
  down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults(
      reinterpret_cast<VerificationResults*>(inaccessible_page_));
  compiler_options_->verification_results_ = verification_results_.get();
  compiler_driver_->CompileAll(class_loader, dex_files, timings);
  compiler_options_->verification_results_ = nullptr;
  down_cast<QuickCompilerCallbacks*>(callbacks_.get())->SetVerificationResults(
      verification_results_.get());

  compiler_driver_->FreeThreadPools();
}

void CommonCompilerTest::UnreserveImageSpace() {
  image_reservation_.Reset();
}

void CommonCompilerTest::SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files) {
  compiler_options_->dex_files_for_oat_file_ = dex_files;
  compiler_driver_->compiled_classes_.AddDexFiles(dex_files);
  compiler_driver_->dex_to_dex_compiler_.SetDexFiles(dex_files);
}

void CommonCompilerTest::ClearBootImageOption() {
  compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;
}

}  // namespace art
