// Copyright 2011 Google Inc. All Rights Reserved.

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>

#include <string>
#include <vector>

#include "class_linker.h"
#include "class_loader.h"
#include "compiler.h"
#include "file.h"
#include "image_writer.h"
#include "oat_writer.h"
#include "os.h"
#include "runtime.h"
#include "stringpiece.h"

namespace art {

static void usage() {
  fprintf(stderr,
          "Usage: dex2oat [options]...\n"
          "\n");
  fprintf(stderr,
          "  --dex-file=<dex-file>: specifies a .dex file to compile. At least one .dex\n"
          "      file must be specified. \n"
          "      Example: --dex-file=/system/framework/core.jar\n"
          "\n");
  fprintf(stderr,
          "  --image=<file.art>: specifies the required output image filename.\n"
          "      Example: --image=/data/art-cache/boot.art\n"
          "\n");
  // TODO: remove this by inferring from --image
  fprintf(stderr,
          "  --oat=<file.oat>: specifies the required oat filename.\n"
          "      Example: --image=/data/art-cache/boot.oat\n"
          "\n");
  fprintf(stderr,
          "  --base=<hex-address>: specifies the base address when creating a boot image.\n"
          "      Example: --base=0x50000000\n"
          "\n");
  fprintf(stderr,
          "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
          "      Example: --boot-image=/data/art-cache/boot.art\n"
          "\n");
  fprintf(stderr,
          "  --method may be used to limit compilation to a subset of methods.\n"
          "      Example: --method=Ljava/lang/Object;<init>()V\n"
          "\n");
  fprintf(stderr,
          "  --host-prefix may be used to translate host paths to target paths during\n"
          "      cross compilation.\n"
          "      Example: --host-prefix=out/target/product/crespo\n"
          "\n");
  fprintf(stderr,
          "  --runtime-arg <argument>: used to specify various arguments for the runtime,\n"
          "      such as initial heap size, maximum heap size, and verbose output.\n"
          "      Use a separate --runtime-arg switch for each argument.\n"
          "      Example: --runtime-arg -Xms256m\n"
          "\n");
  exit(EXIT_FAILURE);
}

class FileJanitor {
public:
  FileJanitor(const std::string& filename, int fd)
      : filename_(filename), fd_(fd), do_unlink_(true) {
  }

  void KeepFile() {
    do_unlink_ = false;
  }

  ~FileJanitor() {
    if (fd_ != -1) {
      int rc = TEMP_FAILURE_RETRY(flock(fd_, LOCK_UN));
      if (rc == -1) {
        PLOG(ERROR) << "Failed to unlock " << filename_;
      }
    }
    if (do_unlink_) {
      int rc = TEMP_FAILURE_RETRY(unlink(filename_.c_str()));
      if (rc == -1) {
        PLOG(ERROR) << "Failed to unlink " << filename_;
      }
    }
  }

private:
  std::string filename_;
  int fd_;
  bool do_unlink_;
};

int dex2oat(int argc, char** argv) {
  // Skip over argv[0].
  argv++;
  argc--;

  if (argc == 0) {
    fprintf(stderr, "no arguments specified\n");
    usage();
  }

  std::vector<const char*> dex_filenames;
  std::vector<const char*> method_names;
  std::string oat_filename;
  const char* image_filename = NULL;
  std::string boot_image_option;
  uintptr_t image_base = 0;
  std::string host_prefix;
  std::vector<const char*> runtime_args;

  for (int i = 0; i < argc; i++) {
    const StringPiece option(argv[i]);
    if (false) {
      LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
    }
    if (option.starts_with("--dex-file=")) {
      dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
    } else if (option.starts_with("--method=")) {
      method_names.push_back(option.substr(strlen("--method=")).data());
    } else if (option.starts_with("--oat=")) {
      oat_filename = option.substr(strlen("--oat=")).data();
    } else if (option.starts_with("--image=")) {
      image_filename = option.substr(strlen("--image=")).data();
    } else if (option.starts_with("--base=")) {
      const char* image_base_str = option.substr(strlen("--base=")).data();
      char* end;
      image_base = strtoul(image_base_str, &end, 16);
      if (end == image_base_str || *end != '\0') {
        fprintf(stderr, "Failed to parse hexadecimal value for option %s\n", option.data());
        usage();
      }
    } else if (option.starts_with("--boot-image=")) {
      const char* boot_image_filename = option.substr(strlen("--boot-image=")).data();
      boot_image_option.clear();
      boot_image_option += "-Ximage:";
      boot_image_option += boot_image_filename;
    } else if (option.starts_with("--host-prefix=")) {
      host_prefix = option.substr(strlen("--host-prefix=")).data();
    } else if (option == "--runtime-arg") {
      if (++i >= argc) {
        fprintf(stderr, "Missing required argument for --runtime-arg\n");
        usage();
      }
      runtime_args.push_back(argv[i]);
    } else {
      fprintf(stderr, "unknown argument %s\n", option.data());
      usage();
    }
  }

  if (oat_filename == NULL) {
    fprintf(stderr, "--oat file name not specified\n");
    return EXIT_FAILURE;
  }

  if (image_filename == NULL && boot_image_option.empty()) {
    fprintf(stderr, "Either --image or --boot-image must be specified\n");
    return EXIT_FAILURE;
  }

  if (dex_filenames.empty()) {
    fprintf(stderr, "no --dex-file values specified\n");
    return EXIT_FAILURE;
  }

  if (boot_image_option.empty()) {
    if (image_base == 0) {
      fprintf(stderr, "non-zero --base not specified\n");
      return EXIT_FAILURE;
    }
  }

  // Create the output file if we can, or open it read-only if we weren't first.
  bool did_create = true;
  int fd = open(oat_filename.c_str(), O_EXCL | O_CREAT | O_TRUNC | O_RDWR, 0666);
  if (fd == -1) {
    if (errno != EEXIST) {
      PLOG(ERROR) << "Unable to create oat file " << oat_filename;
      return EXIT_FAILURE;
    }
    did_create = false;
    fd = open(oat_filename.c_str(), O_RDONLY);
    if (fd == -1) {
      PLOG(ERROR) << "Unable to open oat file for reading " << oat_filename;
      return EXIT_FAILURE;
    }
  }

  // Handles removing the file on failure and unlocking on both failure and success.
  FileJanitor file_janitor(oat_filename, fd);

  // If we won the creation race, block trying to take the lock (since we're going to be doing
  // the work, we need the lock). If we lost the creation race, spin trying to take the lock
  // non-blocking until we fail -- at which point we know the other guy has the lock -- and then
  // block trying to take the now-taken lock.
  if (did_create) {
    LOG(INFO) << "This process created " << oat_filename;
    while (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX)) != 0) {
      // Try again.
    }
    LOG(INFO) << "This process created and locked " << oat_filename;
  } else {
    LOG(INFO) << "Another process has already created " << oat_filename;
    while (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) == 0) {
      // Give up the lock and hope the creator has taken the lock next time round.
      int rc = TEMP_FAILURE_RETRY(flock(fd, LOCK_UN));
      if (rc == -1) {
        PLOG(FATAL) << "Failed to unlock " << oat_filename;
      }
    }
    // Now a non-blocking attempt to take the lock has failed, we know the other guy has the
    // lock, so block waiting to take it.
    LOG(INFO) << "Another process is already working on " << oat_filename;
    if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX)) != 0) {
      PLOG(ERROR) << "Waiter unable to wait for creator to finish " << oat_filename;
      return EXIT_FAILURE;
    }
    // We have the lock and the creator has finished.
    // TODO: check the creator did a good job by checking the header.
    LOG(INFO) << "Another process finished working on " << oat_filename;
    // Job done.
    file_janitor.KeepFile();
    return EXIT_SUCCESS;
  }

  // If we get this far, we won the creation race and have locked the file.
  UniquePtr<File> oat_file(OS::FileFromFd(oat_filename.c_str(), fd));

  LOG(INFO) << "dex2oat: " << oat_file->name();

  Runtime::Options options;
  options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
  std::string boot_class_path_string;
  if (boot_image_option.empty()) {
    boot_class_path_string += "-Xbootclasspath:";
    for (size_t i = 0; i < dex_filenames.size()-1; i++) {
      boot_class_path_string += dex_filenames[i];
      boot_class_path_string += ":";
    }
    boot_class_path_string += dex_filenames[dex_filenames.size()-1];
    options.push_back(std::make_pair(boot_class_path_string.c_str(), reinterpret_cast<void*>(NULL)));
  } else {
    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
  }
  if (!host_prefix.empty()) {
    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
  }
  for (size_t i = 0; i < runtime_args.size(); i++) {
    options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
  }
  UniquePtr<Runtime> runtime(Runtime::Create(options, false));
  if (runtime.get() == NULL) {
    LOG(ERROR) << "Could not create runtime";
    return EXIT_FAILURE;
  }
  ClassLinker* class_linker = runtime->GetClassLinker();

  // If we have an existing boot image, position new space after its oat file
  if (Heap::GetSpaces().size() > 1) {
    Space* last_image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2];
    CHECK(last_image_space != NULL);
    CHECK(last_image_space->IsImageSpace());
    CHECK(!Heap::GetSpaces()[Heap::GetSpaces().size()-1]->IsImageSpace());
    byte* oat_limit_addr = last_image_space->GetImageHeader().GetOatLimitAddr();
    image_base = RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), kPageSize);
  }

  // ClassLoader creation needs to come after Runtime::Create
  SirtRef<ClassLoader> class_loader(NULL);
  if (!boot_image_option.empty()) {
    std::vector<const DexFile*> dex_files;
    DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
    for (size_t i = 0; i < dex_files.size(); i++) {
      class_linker->RegisterDexFile(*dex_files[i]);
    }
    class_loader.reset(PathClassLoader::AllocCompileTime(dex_files));
  }

  // if we loaded an existing image, we will reuse values from the image roots.
  if (!runtime->HasJniStubArray()) {
    runtime->SetJniStubArray(JniCompiler::CreateJniStub(kThumb2));
  }
  if (!runtime->HasAbstractMethodErrorStubArray()) {
    runtime->SetAbstractMethodErrorStubArray(Compiler::CreateAbstractMethodErrorStub(kThumb2));
  }
  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
    Runtime::TrampolineType type = Runtime::TrampolineType(i);
    if (!runtime->HasResolutionStubArray(type)) {
      runtime->SetResolutionStubArray(Compiler::CreateResolutionStub(kThumb2, type), type);
    }
  }
  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
    Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
    if (!runtime->HasCalleeSaveMethod(type)) {
      runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(kThumb2, type), type);
    }
  }
  Compiler compiler(kThumb2, image_filename != NULL);
  if (method_names.empty()) {
    compiler.CompileAll(class_loader.get());
  } else {
    for (size_t i = 0; i < method_names.size(); i++) {
      // names are actually class_descriptor + name + signature.
      // example: Ljava/lang/Object;<init>()V
      StringPiece method_name = method_names[i];
      size_t end_of_class_descriptor = method_name.find(';');
      if (end_of_class_descriptor == method_name.npos) {
        LOG(ERROR) << "Could not find class descriptor in method " << method_name << "'";
        return EXIT_FAILURE;
      }
      end_of_class_descriptor++;  // want to include ;
      std::string class_descriptor = method_name.substr(0, end_of_class_descriptor).ToString();
      size_t end_of_name = method_name.find('(', end_of_class_descriptor);
      if (end_of_name == method_name.npos) {
        LOG(ERROR) << "Could not find start of method signature in method '" << method_name << "'";
        return EXIT_FAILURE;
      }
      std::string name = method_name.substr(end_of_class_descriptor,
                                            end_of_name - end_of_class_descriptor).ToString();
      std::string signature = method_name.substr(end_of_name).ToString();

      Class* klass = class_linker->FindClass(class_descriptor, class_loader.get());
      if (klass == NULL) {
        LOG(ERROR) << "Could not find class for descriptor '" << class_descriptor
            << "' in method '" << method_name << "'";
        return EXIT_FAILURE;
      }
      Method* method = klass->FindDirectMethod(name, signature);
      if (method == NULL) {
          method = klass->FindVirtualMethod(name, signature);
      }
      if (method == NULL) {
        LOG(ERROR) << "Could not find method '" << method_name << "' with signature '"
            << signature << "' in class '" << class_descriptor << "' for method argument '"
            << method_name << "'";
        return EXIT_FAILURE;
      }
      compiler.CompileOne(method);
    }
  }

  if (!OatWriter::Create(oat_file.get(), class_loader.get(), compiler)) {
    LOG(ERROR) << "Failed to create oat file " << oat_file->name();
    return EXIT_FAILURE;
  }

  if (image_filename == NULL) {
    file_janitor.KeepFile();
    LOG(INFO) << "Oat file written successfully " << oat_file->name();
    return EXIT_SUCCESS;
  }
  CHECK(compiler.IsImage());

  ImageWriter image_writer;
  if (!image_writer.Write(image_filename, image_base, oat_file->name(), host_prefix)) {
    LOG(ERROR) << "Failed to create image file " << image_filename;
    return EXIT_FAILURE;
  }

  // We wrote the file successfully, and want to keep it.
  LOG(INFO) << "Image written successfully " << image_filename;
  file_janitor.KeepFile();
  return EXIT_SUCCESS;
}

} // namespace art

int main(int argc, char** argv) {
  return art::dex2oat(argc, argv);
}
