/*
 * Copyright 2014 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 "jit_compiler.h"

#include "android-base/stringprintf.h"
#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
#include "art_method-inl.h"
#include "base/logging.h"  // For VLOG
#include "base/string_view_cpp20.h"
#include "base/systrace.h"
#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "compiler.h"
#include "debug/elf_debug_writer.h"
#include "driver/compiler_options.h"
#include "export/jit_create.h"
#include "jit/debugger_interface.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "jit/jit_logger.h"

namespace art HIDDEN {
namespace jit {

JitCompiler* JitCompiler::Create() {
  return new JitCompiler();
}

void JitCompiler::SetDebuggableCompilerOption(bool value) {
  compiler_options_->SetDebuggable(value);
}

void JitCompiler::ParseCompilerOptions() {
  // Special case max code units for inlining, whose default is "unset" (implictly
  // meaning no limit). Do this before parsing the actual passed options.
  compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits);
  Runtime* runtime = Runtime::Current();
  {
    std::string error_msg;
    if (!compiler_options_->ParseCompilerOptions(runtime->GetCompilerOptions(),
                                                /*ignore_unrecognized=*/ true,
                                                &error_msg)) {
      LOG(FATAL) << error_msg;
      UNREACHABLE();
    }
  }
  // Set to appropriate JIT compiler type.
  compiler_options_->compiler_type_ = runtime->IsZygote()
      ? CompilerOptions::CompilerType::kSharedCodeJitCompiler
      : CompilerOptions::CompilerType::kJitCompiler;
  // JIT is never PIC, no matter what the runtime compiler options specify.
  compiler_options_->SetNonPic();

  // Set the appropriate read barrier option.
  compiler_options_->emit_read_barrier_ = gUseReadBarrier;

  // If the options don't provide whether we generate debuggable code, set
  // debuggability based on the runtime value.
  if (!compiler_options_->GetDebuggable()) {
    compiler_options_->SetDebuggable(runtime->IsJavaDebuggable());
  }

  compiler_options_->implicit_null_checks_ = runtime->GetImplicitNullChecks();
  compiler_options_->implicit_so_checks_ = runtime->GetImplicitStackOverflowChecks();
  compiler_options_->implicit_suspend_checks_ = runtime->GetImplicitSuspendChecks();

  const InstructionSet instruction_set = compiler_options_->GetInstructionSet();
  if (kRuntimeISA == InstructionSet::kArm) {
    DCHECK_EQ(instruction_set, InstructionSet::kThumb2);
  } else {
    DCHECK_EQ(instruction_set, kRuntimeISA);
  }
  std::unique_ptr<const InstructionSetFeatures> instruction_set_features;
  for (const std::string& option : runtime->GetCompilerOptions()) {
    VLOG(compiler) << "JIT compiler option " << option;
    std::string error_msg;
    if (StartsWith(option, "--instruction-set-variant=")) {
      const char* str = option.c_str() + strlen("--instruction-set-variant=");
      VLOG(compiler) << "JIT instruction set variant " << str;
      instruction_set_features = InstructionSetFeatures::FromVariantAndHwcap(
          instruction_set, str, &error_msg);
      if (instruction_set_features == nullptr) {
        LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
      }
    } else if (StartsWith(option, "--instruction-set-features=")) {
      const char* str = option.c_str() + strlen("--instruction-set-features=");
      VLOG(compiler) << "JIT instruction set features " << str;
      if (instruction_set_features == nullptr) {
        instruction_set_features = InstructionSetFeatures::FromVariant(
            instruction_set, "default", &error_msg);
        if (instruction_set_features == nullptr) {
          LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
        }
      }
      instruction_set_features =
          instruction_set_features->AddFeaturesFromString(str, &error_msg);
      if (instruction_set_features == nullptr) {
        LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
      }
    }
  }

  if (instruction_set_features == nullptr) {
    // '--instruction-set-features/--instruction-set-variant' were not used.
    // Use build-time defined features.
    instruction_set_features = InstructionSetFeatures::FromCppDefines();
  }
  compiler_options_->instruction_set_features_ = std::move(instruction_set_features);

  if (compiler_options_->GetGenerateDebugInfo()) {
    jit_logger_.reset(new JitLogger());
    jit_logger_->OpenLog();
  }
}

JitCompilerInterface* jit_create() {
  VLOG(jit) << "Create jit compiler";
  auto* const jit_compiler = JitCompiler::Create();
  CHECK(jit_compiler != nullptr);
  VLOG(jit) << "Done creating jit compiler";
  return jit_compiler;
}

void JitCompiler::TypesLoaded(mirror::Class** types, size_t count) {
  const CompilerOptions& compiler_options = GetCompilerOptions();
  if (compiler_options.GetGenerateDebugInfo()) {
    InstructionSet isa = compiler_options.GetInstructionSet();
    const InstructionSetFeatures* features = compiler_options.GetInstructionSetFeatures();
    const ArrayRef<mirror::Class*> types_array(types, count);
    std::vector<uint8_t> elf_file =
        debug::WriteDebugElfFileForClasses(isa, features, types_array);

    // NB: Don't allow packing since it would remove non-backtrace data.
    MutexLock mu(Thread::Current(), *Locks::jit_lock_);
    AddNativeDebugInfoForJit(/*code_ptr=*/ nullptr, elf_file, /*allow_packing=*/ false);
  }
}

bool JitCompiler::GenerateDebugInfo() {
  return GetCompilerOptions().GetGenerateDebugInfo();
}

std::vector<uint8_t> JitCompiler::PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files,
                                                    ArrayRef<const void*> removed_symbols,
                                                    bool compress,
                                                    /*out*/ size_t* num_symbols) {
  return debug::PackElfFileForJIT(elf_files, removed_symbols, compress, num_symbols);
}

JitCompiler::JitCompiler() {
  compiler_options_.reset(new CompilerOptions());
  ParseCompilerOptions();
  compiler_.reset(
      Compiler::Create(*compiler_options_, /*storage=*/ nullptr, Compiler::kOptimizing));
}

JitCompiler::~JitCompiler() {
  if (compiler_options_->GetGenerateDebugInfo()) {
    jit_logger_->CloseLog();
  }
}

bool JitCompiler::CompileMethod(
    Thread* self, JitMemoryRegion* region, ArtMethod* method, CompilationKind compilation_kind) {
  SCOPED_TRACE << "JIT compiling "
               << method->PrettyMethod()
               << " (kind=" << compilation_kind << ")";

  DCHECK(!method->IsProxyMethod());
  DCHECK(method->GetDeclaringClass()->IsResolved());

  TimingLogger logger(
      "JIT compiler timing logger", true, VLOG_IS_ON(jit), TimingLogger::TimingKind::kThreadCpu);
  self->AssertNoPendingException();
  Runtime* runtime = Runtime::Current();

  // Do the compilation.
  bool success = false;
  Jit* jit = runtime->GetJit();
  {
    TimingLogger::ScopedTiming t2(compilation_kind == CompilationKind::kOsr
                                      ? "Compiling OSR"
                                      : compilation_kind == CompilationKind::kOptimized
                                          ? "Compiling optimized"
                                          : "Compiling baseline",
                                  &logger);
    JitCodeCache* const code_cache = jit->GetCodeCache();
    metrics::AutoTimer timer{runtime->GetMetrics()->JitMethodCompileTotalTime()};
    success = compiler_->JitCompile(
        self, code_cache, region, method, compilation_kind, jit_logger_.get());
    uint64_t duration_us = timer.Stop();
    VLOG(jit) << "Compilation of " << method->PrettyMethod() << " took "
              << PrettyDuration(UsToNs(duration_us));
    runtime->GetMetrics()->JitMethodCompileCount()->AddOne();
    runtime->GetMetrics()->JitMethodCompileTotalTimeDelta()->Add(duration_us);
    runtime->GetMetrics()->JitMethodCompileCountDelta()->AddOne();
  }

  // If we don't have a new task following this compile,
  // trim maps to reduce memory usage.
  if (jit->GetThreadPool() == nullptr || jit->GetThreadPool()->GetTaskCount(self) == 0) {
    TimingLogger::ScopedTiming t2("TrimMaps", &logger);
    runtime->GetJitArenaPool()->TrimMaps();
  }

  jit->AddTimingLogger(logger);
  return success;
}

bool JitCompiler::IsBaselineCompiler() const {
  return compiler_options_->IsBaseline();
}

uint32_t JitCompiler::GetInlineMaxCodeUnits() const {
  return compiler_options_->GetInlineMaxCodeUnits();
}

}  // namespace jit
}  // namespace art
