/*
 * 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 <inttypes.h>
#include <log/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <forward_list>
#include <fstream>
#include <iostream>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>

#if defined(__linux__)
#include <sched.h>
#if defined(__arm__)
#include <sys/personality.h>
#include <sys/utsname.h>
#endif  // __arm__
#endif

#include "android-base/parseint.h"
#include "android-base/scopeguard.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "android-base/unique_fd.h"
#include "aot_class_linker.h"
#include "arch/instruction_set_features.h"
#include "art_method-inl.h"
#include "base/callee_save_type.h"
#include "base/dumpable.h"
#include "base/fast_exit.h"
#include "base/file_utils.h"
#include "base/globals.h"
#include "base/leb128.h"
#include "base/macros.h"
#include "base/memory_tool.h"
#include "base/mutex.h"
#include "base/os.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "base/zip_archive.h"
#include "class_linker.h"
#include "class_loader_context.h"
#include "class_root-inl.h"
#include "cmdline_parser.h"
#include "compiler.h"
#include "compiler_callbacks.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "dex2oat_options.h"
#include "dexlayout.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "driver/compiler_options_map-inl.h"
#include "elf_file.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
#include "gc/verification.h"
#include "interpreter/unstarted_runtime.h"
#include "jni/java_vm_ext.h"
#include "linker/elf_writer.h"
#include "linker/elf_writer_quick.h"
#include "linker/image_writer.h"
#include "linker/multi_oat_relative_patcher.h"
#include "linker/oat_writer.h"
#include "mirror/class-alloc-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "oat.h"
#include "oat_file.h"
#include "oat_file_assistant.h"
#include "palette/palette.h"
#include "profile/profile_compilation_info.h"
#include "runtime.h"
#include "runtime_intrinsics.h"
#include "runtime_options.h"
#include "scoped_thread_state_change-inl.h"
#include "stream/buffered_output_stream.h"
#include "stream/file_output_stream.h"
#include "vdex_file.h"
#include "verifier/verifier_deps.h"
#include "well_known_classes.h"

namespace art {

namespace dex2oat {
  enum class ReturnCode : int {
    kNoFailure = 0,          // No failure, execution completed successfully.
    kOther = 1,              // Some other not closer specified error occurred.
    kCreateRuntime = 2,      // Dex2oat failed creating a runtime.
  };
}  // namespace dex2oat

using android::base::StringAppendV;
using android::base::StringPrintf;
using gc::space::ImageSpace;

static constexpr size_t kDefaultMinDexFilesForSwap = 2;
static constexpr size_t kDefaultMinDexFileCumulativeSizeForSwap = 20 * MB;

// Compiler filter override for very large apps.
static constexpr CompilerFilter::Filter kLargeAppFilter = CompilerFilter::kVerify;

static int original_argc;
static char** original_argv;

static std::string CommandLine() {
  std::vector<std::string> command;
  command.reserve(original_argc);
  for (int i = 0; i < original_argc; ++i) {
    command.push_back(original_argv[i]);
  }
  return android::base::Join(command, ' ');
}

// A stripped version. Remove some less essential parameters. If we see a "--zip-fd=" parameter, be
// even more aggressive. There won't be much reasonable data here for us in that case anyways (the
// locations are all staged).
static std::string StrippedCommandLine() {
  std::vector<std::string> command;

  // Do a pre-pass to look for zip-fd and the compiler filter.
  bool saw_zip_fd = false;
  bool saw_compiler_filter = false;
  for (int i = 0; i < original_argc; ++i) {
    if (android::base::StartsWith(original_argv[i], "--zip-fd=")) {
      saw_zip_fd = true;
    }
    if (android::base::StartsWith(original_argv[i], "--compiler-filter=")) {
      saw_compiler_filter = true;
    }
  }

  // Now filter out things.
  for (int i = 0; i < original_argc; ++i) {
    // All runtime-arg parameters are dropped.
    if (strcmp(original_argv[i], "--runtime-arg") == 0) {
      i++;  // Drop the next part, too.
      continue;
    }

    // Any instruction-setXXX is dropped.
    if (android::base::StartsWith(original_argv[i], "--instruction-set")) {
      continue;
    }

    // The boot image is dropped.
    if (android::base::StartsWith(original_argv[i], "--boot-image=")) {
      continue;
    }

    // The image format is dropped.
    if (android::base::StartsWith(original_argv[i], "--image-format=")) {
      continue;
    }

    // This should leave any dex-file and oat-file options, describing what we compiled.

    // However, we prefer to drop this when we saw --zip-fd.
    if (saw_zip_fd) {
      // Drop anything --zip-X, --dex-X, --oat-X, --swap-X, or --app-image-X
      if (android::base::StartsWith(original_argv[i], "--zip-") ||
          android::base::StartsWith(original_argv[i], "--dex-") ||
          android::base::StartsWith(original_argv[i], "--oat-") ||
          android::base::StartsWith(original_argv[i], "--swap-") ||
          android::base::StartsWith(original_argv[i], "--app-image-")) {
        continue;
      }
    }

    command.push_back(original_argv[i]);
  }

  if (!saw_compiler_filter) {
    command.push_back("--compiler-filter=" +
        CompilerFilter::NameOfFilter(CompilerFilter::kDefaultCompilerFilter));
  }

  // Construct the final output.
  if (command.size() <= 1U) {
    // It seems only "/apex/com.android.art/bin/dex2oat" is left, or not
    // even that. Use a pretty line.
    return "Starting dex2oat.";
  }
  return android::base::Join(command, ' ');
}

static void UsageErrorV(const char* fmt, va_list ap) {
  std::string error;
  StringAppendV(&error, fmt, ap);
  LOG(ERROR) << error;
}

static void UsageError(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  UsageErrorV(fmt, ap);
  va_end(ap);
}

NO_RETURN static void Usage(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  UsageErrorV(fmt, ap);
  va_end(ap);

  UsageError("Command: %s", CommandLine().c_str());

  UsageError("Usage: dex2oat [options]...");
  UsageError("");

  std::stringstream oss;
  VariableIndentationOutputStream vios(&oss);
  auto parser = CreateDex2oatArgumentParser();
  parser.DumpHelp(vios);
  UsageError(oss.str().c_str());
  std::cerr << "See log for usage error information\n";
  exit(EXIT_FAILURE);
}


// Set CPU affinity from a string containing a comma-separated list of numeric CPU identifiers.
static void SetCpuAffinity(const std::vector<int32_t>& cpu_list) {
#ifdef __linux__
  int cpu_count = sysconf(_SC_NPROCESSORS_CONF);
  cpu_set_t target_cpu_set;
  CPU_ZERO(&target_cpu_set);

  for (int32_t cpu : cpu_list) {
    if (cpu >= 0 && cpu < cpu_count) {
      CPU_SET(cpu, &target_cpu_set);
    } else {
      // Argument error is considered fatal, suggests misconfigured system properties.
      Usage("Invalid cpu \"d\" specified in --cpu-set argument (nprocessors = %d)",
            cpu, cpu_count);
    }
  }

  if (sched_setaffinity(getpid(), sizeof(target_cpu_set), &target_cpu_set) == -1) {
    // Failure to set affinity may be outside control of requestor, log warning rather than
    // treating as fatal.
    PLOG(WARNING) << "Failed to set CPU affinity.";
  }
#else
  LOG(WARNING) << "--cpu-set not supported on this platform.";
#endif  // __linux__
}



// The primary goal of the watchdog is to prevent stuck build servers
// during development when fatal aborts lead to a cascade of failures
// that result in a deadlock.
class WatchDog {
// WatchDog defines its own CHECK_PTHREAD_CALL to avoid using LOG which uses locks
#undef CHECK_PTHREAD_CALL
#define CHECK_WATCH_DOG_PTHREAD_CALL(call, args, what) \
  do { \
    int rc = call args; \
    if (rc != 0) { \
      errno = rc; \
      std::string message(# call); \
      message += " failed for "; \
      message += reason; \
      Fatal(message); \
    } \
  } while (false)

 public:
  explicit WatchDog(int64_t timeout_in_milliseconds)
      : timeout_in_milliseconds_(timeout_in_milliseconds),
        shutting_down_(false) {
    const char* reason = "dex2oat watch dog thread startup";
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_init, (&mutex_, nullptr), reason);
#ifndef __APPLE__
    pthread_condattr_t condattr;
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_condattr_init, (&condattr), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_condattr_setclock, (&condattr, CLOCK_MONOTONIC), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_init, (&cond_, &condattr), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_condattr_destroy, (&condattr), reason);
#endif
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_attr_init, (&attr_), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_create, (&pthread_, &attr_, &CallBack, this), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_attr_destroy, (&attr_), reason);
  }
  ~WatchDog() {
    const char* reason = "dex2oat watch dog thread shutdown";
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason);
    shutting_down_ = true;
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_signal, (&cond_), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason);

    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_join, (pthread_, nullptr), reason);

    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_destroy, (&cond_), reason);
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_destroy, (&mutex_), reason);
  }

  static void SetRuntime(Runtime* runtime) {
    const char* reason = "dex2oat watch dog set runtime";
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&runtime_mutex_), reason);
    runtime_ = runtime;
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&runtime_mutex_), reason);
  }

  // TODO: tune the multiplier for GC verification, the following is just to make the timeout
  //       large.
  static constexpr int64_t kWatchdogVerifyMultiplier =
      kVerifyObjectSupport > kVerifyObjectModeFast ? 100 : 1;

  // When setting timeouts, keep in mind that the build server may not be as fast as your
  // desktop. Debug builds are slower so they have larger timeouts.
  static constexpr int64_t kWatchdogSlowdownFactor = kIsDebugBuild ? 5U : 1U;

  // 9.5 minutes scaled by kSlowdownFactor. This is slightly smaller than the Package Manager
  // watchdog (PackageManagerService.WATCHDOG_TIMEOUT, 10 minutes), so that dex2oat will abort
  // itself before that watchdog would take down the system server.
  static constexpr int64_t kWatchDogTimeoutSeconds = kWatchdogSlowdownFactor * (9 * 60 + 30);

  static constexpr int64_t kDefaultWatchdogTimeoutInMS =
      kWatchdogVerifyMultiplier * kWatchDogTimeoutSeconds * 1000;

 private:
  static void* CallBack(void* arg) {
    WatchDog* self = reinterpret_cast<WatchDog*>(arg);
    ::art::SetThreadName("dex2oat watch dog");
    self->Wait();
    return nullptr;
  }

  NO_RETURN static void Fatal(const std::string& message) {
    // TODO: When we can guarantee it won't prevent shutdown in error cases, move to LOG. However,
    //       it's rather easy to hang in unwinding.
    //       LogLine also avoids ART logging lock issues, as it's really only a wrapper around
    //       logcat logging or stderr output.
    LogHelper::LogLineLowStack(__FILE__, __LINE__, LogSeverity::FATAL, message.c_str());

    // If we're on the host, try to dump all threads to get a sense of what's going on. This is
    // restricted to the host as the dump may itself go bad.
    // TODO: Use a double watchdog timeout, so we can enable this on-device.
    Runtime* runtime = GetRuntime();
    if (!kIsTargetBuild && runtime != nullptr) {
      runtime->AttachCurrentThread("Watchdog thread attached for dumping",
                                   true,
                                   nullptr,
                                   false);
      runtime->DumpForSigQuit(std::cerr);
    }
    exit(1);
  }

  void Wait() {
    timespec timeout_ts;
#if defined(__APPLE__)
    InitTimeSpec(true, CLOCK_REALTIME, timeout_in_milliseconds_, 0, &timeout_ts);
#else
    InitTimeSpec(true, CLOCK_MONOTONIC, timeout_in_milliseconds_, 0, &timeout_ts);
#endif
    const char* reason = "dex2oat watch dog thread waiting";
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason);
    while (!shutting_down_) {
      int rc = pthread_cond_timedwait(&cond_, &mutex_, &timeout_ts);
      if (rc == EINTR) {
        continue;
      } else if (rc == ETIMEDOUT) {
        Fatal(StringPrintf("dex2oat did not finish after %" PRId64 " milliseconds",
                           timeout_in_milliseconds_));
      } else if (rc != 0) {
        std::string message(StringPrintf("pthread_cond_timedwait failed: %s", strerror(rc)));
        Fatal(message);
      }
    }
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason);
  }

  static Runtime* GetRuntime() {
    const char* reason = "dex2oat watch dog get runtime";
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&runtime_mutex_), reason);
    Runtime* runtime = runtime_;
    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&runtime_mutex_), reason);
    return runtime;
  }

  static pthread_mutex_t runtime_mutex_;
  static Runtime* runtime_;

  // TODO: Switch to Mutex when we can guarantee it won't prevent shutdown in error cases.
  pthread_mutex_t mutex_;
  pthread_cond_t cond_;
  pthread_attr_t attr_;
  pthread_t pthread_;

  const int64_t timeout_in_milliseconds_;
  bool shutting_down_;
};

pthread_mutex_t WatchDog::runtime_mutex_ = PTHREAD_MUTEX_INITIALIZER;
Runtime* WatchDog::runtime_ = nullptr;

// Helper class for overriding `java.lang.ThreadLocal.nextHashCode`.
//
// The class ThreadLocal has a static field nextHashCode used for assigning hash codes to
// new ThreadLocal objects. Since the class and the object referenced by the field are
// in the boot image, they cannot be modified under normal rules for AOT compilation.
// However, since this is a private detail that's used only for assigning hash codes and
// everything should work fine with different hash codes, we override the field for the
// compilation, providing another object that the AOT class initialization can modify.
class ThreadLocalHashOverride {
 public:
  ThreadLocalHashOverride(bool apply, int32_t initial_value) {
    Thread* self = Thread::Current();
    ScopedObjectAccess soa(self);
    hs_.emplace(self);  // While holding the mutator lock.
    Runtime* runtime = Runtime::Current();
    klass_ = hs_->NewHandle(apply
        ? runtime->GetClassLinker()->LookupClass(self,
                                                 "Ljava/lang/ThreadLocal;",
                                                 /*class_loader=*/ nullptr)
        : nullptr);
    field_ = ((klass_ != nullptr) && klass_->IsVisiblyInitialized())
        ? klass_->FindDeclaredStaticField("nextHashCode",
                                          "Ljava/util/concurrent/atomic/AtomicInteger;")
        : nullptr;
    old_field_value_ =
        hs_->NewHandle(field_ != nullptr ? field_->GetObject(klass_.Get()) : nullptr);
    if (old_field_value_ != nullptr) {
      gc::AllocatorType allocator_type = runtime->GetHeap()->GetCurrentAllocator();
      StackHandleScope<1u> hs2(self);
      Handle<mirror::Object> new_field_value = hs2.NewHandle(
          old_field_value_->GetClass()->Alloc(self, allocator_type));
      PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
      ArtMethod* constructor = old_field_value_->GetClass()->FindConstructor("(I)V", pointer_size);
      CHECK(constructor != nullptr);
      uint32_t args[] = {
          reinterpret_cast32<uint32_t>(new_field_value.Get()),
          static_cast<uint32_t>(initial_value)
      };
      JValue result;
      constructor->Invoke(self, args, sizeof(args), &result, /*shorty=*/ "VI");
      CHECK(!self->IsExceptionPending());
      field_->SetObject</*kTransactionActive=*/ false>(klass_.Get(), new_field_value.Get());
    }
    if (apply && old_field_value_ == nullptr) {
      if ((klass_ != nullptr) && klass_->IsVisiblyInitialized()) {
        // This would mean that the implementation of ThreadLocal has changed
        // and the code above is no longer applicable.
        LOG(ERROR) << "Failed to override ThreadLocal.nextHashCode";
      } else {
        VLOG(compiler) << "ThreadLocal is not initialized in the primary boot image.";
      }
    }
  }

  ~ThreadLocalHashOverride() {
    ScopedObjectAccess soa(hs_->Self());
    if (old_field_value_ != nullptr) {
      // Allow the overriding object to be collected.
      field_->SetObject</*kTransactionActive=*/ false>(klass_.Get(), old_field_value_.Get());
    }
    hs_.reset();  // While holding the mutator lock.
  }

 private:
  std::optional<StackHandleScope<2u>> hs_;
  Handle<mirror::Class> klass_;
  ArtField* field_;
  Handle<mirror::Object> old_field_value_;
};

class OatKeyValueStore : public SafeMap<std::string, std::string> {
 public:
  using SafeMap::Put;

  iterator Put(const std::string& k, bool v) {
    return SafeMap::Put(k, v ? OatHeader::kTrueValue : OatHeader::kFalseValue);
  }
};

class Dex2Oat final {
 public:
  explicit Dex2Oat(TimingLogger* timings)
      : compiler_kind_(Compiler::kOptimizing),
        // Take the default set of instruction features from the build.
        key_value_store_(nullptr),
        verification_results_(nullptr),
        runtime_(nullptr),
        thread_count_(sysconf(_SC_NPROCESSORS_CONF)),
        start_ns_(NanoTime()),
        start_cputime_ns_(ProcessCpuNanoTime()),
        strip_(false),
        oat_fd_(-1),
        input_vdex_fd_(-1),
        output_vdex_fd_(-1),
        input_vdex_file_(nullptr),
        dm_fd_(-1),
        zip_fd_(-1),
        image_fd_(-1),
        have_multi_image_arg_(false),
        image_base_(0U),
        image_storage_mode_(ImageHeader::kStorageModeUncompressed),
        passes_to_run_filename_(nullptr),
        dirty_image_objects_filename_(nullptr),
        dirty_image_objects_fd_(-1),
        is_host_(false),
        elf_writers_(),
        oat_writers_(),
        rodata_(),
        image_writer_(nullptr),
        driver_(nullptr),
        opened_dex_files_maps_(),
        opened_dex_files_(),
        avoid_storing_invocation_(false),
        swap_fd_(File::kInvalidFd),
        app_image_fd_(File::kInvalidFd),
        timings_(timings),
        force_determinism_(false),
        check_linkage_conditions_(false),
        crash_on_linkage_violation_(false),
        compile_individually_(false),
        profile_load_attempted_(false),
        should_report_dex2oat_compilation_(false) {}

  ~Dex2Oat() {
    // Log completion time before deleting the runtime_, because this accesses
    // the runtime.
    LogCompletionTime();

    if (!kIsDebugBuild && !(kRunningOnMemoryTool && kMemoryToolDetectsLeaks)) {
      // We want to just exit on non-debug builds, not bringing the runtime down
      // in an orderly fashion. So release the following fields.
      if (!compiler_options_->GetDumpStats()) {
        // The --dump-stats get logged when the optimizing compiler gets destroyed, so we can't
        // release the driver_.
        driver_.release();              // NOLINT
      }
      image_writer_.release();          // NOLINT
      for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files_) {
        dex_file.release();             // NOLINT
      }
      new std::vector<MemMap>(std::move(opened_dex_files_maps_));  // Leak MemMaps.
      for (std::unique_ptr<File>& vdex_file : vdex_files_) {
        vdex_file.release();            // NOLINT
      }
      for (std::unique_ptr<File>& oat_file : oat_files_) {
        oat_file.release();             // NOLINT
      }
      runtime_.release();               // NOLINT
      verification_results_.release();  // NOLINT
      key_value_store_.release();       // NOLINT
    }

    // Remind the user if they passed testing only flags.
    if (!kIsTargetBuild && force_allow_oj_inlines_) {
      LOG(ERROR) << "Inlines allowed from core-oj! FOR TESTING USE ONLY! DO NOT DISTRIBUTE"
                  << " BINARIES BUILT WITH THIS OPTION!";
    }
  }

  struct ParserOptions {
    std::vector<std::string> oat_symbols;
    std::string boot_image_filename;
    int64_t watch_dog_timeout_in_ms = -1;
    bool watch_dog_enabled = true;
    bool requested_specific_compiler = false;
    std::string error_msg;
  };

  void ParseBase(const std::string& option) {
    char* end;
    image_base_ = strtoul(option.c_str(), &end, 16);
    if (end == option.c_str() || *end != '\0') {
      Usage("Failed to parse hexadecimal value for option %s", option.data());
    }
  }

  bool VerifyProfileData() {
    return profile_compilation_info_->VerifyProfileData(compiler_options_->dex_files_for_oat_file_);
  }

  void ParseInstructionSetVariant(const std::string& option, ParserOptions* parser_options) {
    if (kIsTargetBuild) {
      compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariantAndHwcap(
          compiler_options_->instruction_set_, option, &parser_options->error_msg);
    } else {
      compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariant(
          compiler_options_->instruction_set_, option, &parser_options->error_msg);
    }
    if (compiler_options_->instruction_set_features_ == nullptr) {
      Usage("%s", parser_options->error_msg.c_str());
    }
  }

  void ParseInstructionSetFeatures(const std::string& option, ParserOptions* parser_options) {
    if (compiler_options_->instruction_set_features_ == nullptr) {
      compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariant(
          compiler_options_->instruction_set_, "default", &parser_options->error_msg);
      if (compiler_options_->instruction_set_features_ == nullptr) {
        Usage("Problem initializing default instruction set features variant: %s",
              parser_options->error_msg.c_str());
      }
    }
    compiler_options_->instruction_set_features_ =
        compiler_options_->instruction_set_features_->AddFeaturesFromString(
            option, &parser_options->error_msg);
    if (compiler_options_->instruction_set_features_ == nullptr) {
      Usage("Error parsing '%s': %s", option.c_str(), parser_options->error_msg.c_str());
    }
  }

  void ProcessOptions(ParserOptions* parser_options) {
    compiler_options_->compiler_type_ = CompilerOptions::CompilerType::kAotCompiler;
    compiler_options_->compile_pic_ = true;  // All AOT compilation is PIC.

    if (android_root_.empty()) {
      const char* android_root_env_var = getenv("ANDROID_ROOT");
      if (android_root_env_var == nullptr) {
        Usage("--android-root unspecified and ANDROID_ROOT not set");
      }
      android_root_ += android_root_env_var;
    }

    if (!parser_options->boot_image_filename.empty()) {
      boot_image_filename_ = parser_options->boot_image_filename;
    }

    DCHECK(compiler_options_->image_type_ == CompilerOptions::ImageType::kNone);
    if (!image_filenames_.empty() || image_fd_ != -1) {
      // If no boot image is provided, then dex2oat is compiling the primary boot image,
      // otherwise it is compiling the boot image extension.
      compiler_options_->image_type_ = boot_image_filename_.empty()
          ? CompilerOptions::ImageType::kBootImage
          : CompilerOptions::ImageType::kBootImageExtension;
    }
    if (app_image_fd_ != -1 || !app_image_file_name_.empty()) {
      if (compiler_options_->IsBootImage() || compiler_options_->IsBootImageExtension()) {
        Usage("Can't have both (--image or --image-fd) and (--app-image-fd or --app-image-file)");
      }
      compiler_options_->image_type_ = CompilerOptions::ImageType::kAppImage;
    }

    if (!image_filenames_.empty() && image_fd_ != -1) {
      Usage("Can't have both --image and --image-fd");
    }

    if (oat_filenames_.empty() && oat_fd_ == -1) {
      Usage("Output must be supplied with either --oat-file or --oat-fd");
    }

    if (input_vdex_fd_ != -1 && !input_vdex_.empty()) {
      Usage("Can't have both --input-vdex-fd and --input-vdex");
    }

    if (output_vdex_fd_ != -1 && !output_vdex_.empty()) {
      Usage("Can't have both --output-vdex-fd and --output-vdex");
    }

    if (!oat_filenames_.empty() && oat_fd_ != -1) {
      Usage("--oat-file should not be used with --oat-fd");
    }

    if ((output_vdex_fd_ == -1) != (oat_fd_ == -1)) {
      Usage("VDEX and OAT output must be specified either with one --oat-file "
            "or with --oat-fd and --output-vdex-fd file descriptors");
    }

    if ((image_fd_ != -1) && (oat_fd_ == -1)) {
      Usage("--image-fd must be used with --oat_fd and --output_vdex_fd");
    }

    if (!parser_options->oat_symbols.empty() && oat_fd_ != -1) {
      Usage("--oat-symbols should not be used with --oat-fd");
    }

    if (!parser_options->oat_symbols.empty() && is_host_) {
      Usage("--oat-symbols should not be used with --host");
    }

    if (output_vdex_fd_ != -1 && !image_filenames_.empty()) {
      Usage("--output-vdex-fd should not be used with --image");
    }

    if (oat_fd_ != -1 && !image_filenames_.empty()) {
      Usage("--oat-fd should not be used with --image");
    }

    if (!parser_options->oat_symbols.empty() &&
        parser_options->oat_symbols.size() != oat_filenames_.size()) {
      Usage("--oat-file arguments do not match --oat-symbols arguments");
    }

    if (!image_filenames_.empty() && image_filenames_.size() != oat_filenames_.size()) {
      Usage("--oat-file arguments do not match --image arguments");
    }

    if (!IsBootImage() && boot_image_filename_.empty()) {
      DCHECK(!IsBootImageExtension());
      boot_image_filename_ =
          GetDefaultBootImageLocation(android_root_, /*deny_art_apex_data_files=*/false);
    }

    if (dex_filenames_.empty() && zip_fd_ == -1) {
      Usage("Input must be supplied with either --dex-file or --zip-fd");
    }

    if (!dex_filenames_.empty() && zip_fd_ != -1) {
      Usage("--dex-file should not be used with --zip-fd");
    }

    if (!dex_filenames_.empty() && !zip_location_.empty()) {
      Usage("--dex-file should not be used with --zip-location");
    }

    if (dex_locations_.empty()) {
      dex_locations_ = dex_filenames_;
    } else if (dex_locations_.size() != dex_filenames_.size()) {
      Usage("--dex-location arguments do not match --dex-file arguments");
    }

    if (!dex_filenames_.empty() && !oat_filenames_.empty()) {
      if (oat_filenames_.size() != 1 && oat_filenames_.size() != dex_filenames_.size()) {
        Usage("--oat-file arguments must be singular or match --dex-file arguments");
      }
    }

    if (!dex_fds_.empty() && dex_fds_.size() != dex_filenames_.size()) {
      Usage("--dex-fd arguments do not match --dex-file arguments");
    }

    if (zip_fd_ != -1 && zip_location_.empty()) {
      Usage("--zip-location should be supplied with --zip-fd");
    }

    if (boot_image_filename_.empty()) {
      if (image_base_ == 0) {
        Usage("Non-zero --base not specified for boot image");
      }
    } else {
      if (image_base_ != 0) {
        Usage("Non-zero --base specified for app image or boot image extension");
      }
    }

    if (have_multi_image_arg_) {
      if (!IsImage()) {
        Usage("--multi-image or --single-image specified for non-image compilation");
      }
    } else {
      // Use the default, i.e. multi-image for boot image and boot image extension.
      // This shall pass the checks below.
      compiler_options_->multi_image_ = IsBootImage() || IsBootImageExtension();
    }
    // On target we support generating a single image for the primary boot image.
    if (!kIsTargetBuild) {
      if (IsBootImage() && !compiler_options_->multi_image_) {
        Usage("--single-image specified for primary boot image on host");
      }
    }
    if (IsAppImage() && compiler_options_->multi_image_) {
      Usage("--multi-image specified for app image");
    }

    if (image_fd_ != -1 && compiler_options_->multi_image_) {
      Usage("--single-image not specified for --image-fd");
    }

    const bool have_profile_file = !profile_files_.empty();
    const bool have_profile_fd = !profile_file_fds_.empty();
    if (have_profile_file && have_profile_fd) {
      Usage("Profile files should not be specified with both --profile-file-fd and --profile-file");
    }

    if (!parser_options->oat_symbols.empty()) {
      oat_unstripped_ = std::move(parser_options->oat_symbols);
    }

    if (compiler_options_->instruction_set_features_ == nullptr) {
      // '--instruction-set-features/--instruction-set-variant' were not used.
      // Use features for the 'default' variant.
      compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariant(
          compiler_options_->instruction_set_, "default", &parser_options->error_msg);
      if (compiler_options_->instruction_set_features_ == nullptr) {
        Usage("Problem initializing default instruction set features variant: %s",
              parser_options->error_msg.c_str());
      }
    }

    if (compiler_options_->instruction_set_ == kRuntimeISA) {
      std::unique_ptr<const InstructionSetFeatures> runtime_features(
          InstructionSetFeatures::FromCppDefines());
      if (!compiler_options_->GetInstructionSetFeatures()->Equals(runtime_features.get())) {
        LOG(WARNING) << "Mismatch between dex2oat instruction set features to use ("
            << *compiler_options_->GetInstructionSetFeatures()
            << ") and those from CPP defines (" << *runtime_features
            << ") for the command line:\n" << CommandLine();
      }
    }

    if (dirty_image_objects_filename_ != nullptr && dirty_image_objects_fd_ != -1) {
      Usage("--dirty-image-objects and --dirty-image-objects-fd should not be both specified");
    }

    if (!preloaded_classes_files_.empty() && !preloaded_classes_fds_.empty()) {
      Usage("--preloaded-classes and --preloaded-classes-fds should not be both specified");
    }

    if (!cpu_set_.empty()) {
      SetCpuAffinity(cpu_set_);
    }

    if (compiler_options_->inline_max_code_units_ == CompilerOptions::kUnsetInlineMaxCodeUnits) {
      compiler_options_->inline_max_code_units_ = CompilerOptions::kDefaultInlineMaxCodeUnits;
    }

    // Checks are all explicit until we know the architecture.
    // Set the compilation target's implicit checks options.
    switch (compiler_options_->GetInstructionSet()) {
      case InstructionSet::kArm64:
        // TODO: Implicit suspend checks are currently disabled to facilitate search
        // for unrelated memory use regressions. Bug: 213757852.
        compiler_options_->implicit_suspend_checks_ = false;
        FALLTHROUGH_INTENDED;
      case InstructionSet::kArm:
      case InstructionSet::kThumb2:
      case InstructionSet::kX86:
      case InstructionSet::kX86_64:
        compiler_options_->implicit_null_checks_ = true;
        compiler_options_->implicit_so_checks_ = true;
        break;

      default:
        // Defaults are correct.
        break;
    }

    // Done with usage checks, enable watchdog if requested
    if (parser_options->watch_dog_enabled) {
      int64_t timeout = parser_options->watch_dog_timeout_in_ms > 0
                            ? parser_options->watch_dog_timeout_in_ms
                            : WatchDog::kDefaultWatchdogTimeoutInMS;
      watchdog_.reset(new WatchDog(timeout));
    }

    // Fill some values into the key-value store for the oat header.
    key_value_store_.reset(new OatKeyValueStore());

    // Automatically force determinism for the boot image and boot image extensions in a host build.
    if (!kIsTargetBuild && (IsBootImage() || IsBootImageExtension())) {
      force_determinism_ = true;
    }
    compiler_options_->force_determinism_ = force_determinism_;

    compiler_options_->check_linkage_conditions_ = check_linkage_conditions_;
    compiler_options_->crash_on_linkage_violation_ = crash_on_linkage_violation_;

    if (passes_to_run_filename_ != nullptr) {
      passes_to_run_ = ReadCommentedInputFromFile<std::vector<std::string>>(
          passes_to_run_filename_,
          nullptr);         // No post-processing.
      if (passes_to_run_.get() == nullptr) {
        Usage("Failed to read list of passes to run.");
      }
    }

    // Prune profile specifications of the boot image location.
    std::vector<std::string> boot_images =
        android::base::Split(boot_image_filename_, {ImageSpace::kComponentSeparator});
    bool boot_image_filename_pruned = false;
    for (std::string& boot_image : boot_images) {
      size_t profile_separator_pos = boot_image.find(ImageSpace::kProfileSeparator);
      if (profile_separator_pos != std::string::npos) {
        boot_image.resize(profile_separator_pos);
        boot_image_filename_pruned = true;
      }
    }
    if (boot_image_filename_pruned) {
      std::string new_boot_image_filename =
          android::base::Join(boot_images, ImageSpace::kComponentSeparator);
      VLOG(compiler) << "Pruning profile specifications of the boot image location. Before: "
                     << boot_image_filename_ << ", After: " << new_boot_image_filename;
      boot_image_filename_ = std::move(new_boot_image_filename);
    }

    compiler_options_->passes_to_run_ = passes_to_run_.get();
  }

  void ExpandOatAndImageFilenames() {
    ArrayRef<const std::string> locations(dex_locations_);
    if (!compiler_options_->multi_image_) {
      locations = locations.SubArray(/*pos=*/ 0u, /*length=*/ 1u);
    }
    if (image_fd_ == -1) {
      if (image_filenames_[0].rfind('/') == std::string::npos) {
        Usage("Unusable boot image filename %s", image_filenames_[0].c_str());
      }
      image_filenames_ = ImageSpace::ExpandMultiImageLocations(
          locations, image_filenames_[0], IsBootImageExtension());

      if (oat_filenames_[0].rfind('/') == std::string::npos) {
        Usage("Unusable boot image oat filename %s", oat_filenames_[0].c_str());
      }
      oat_filenames_ = ImageSpace::ExpandMultiImageLocations(
          locations, oat_filenames_[0], IsBootImageExtension());
    } else {
      DCHECK(!compiler_options_->multi_image_);
      std::vector<std::string> oat_locations = ImageSpace::ExpandMultiImageLocations(
          locations, oat_location_, IsBootImageExtension());
      DCHECK_EQ(1u, oat_locations.size());
      oat_location_ = oat_locations[0];
    }

    if (!oat_unstripped_.empty()) {
      if (oat_unstripped_[0].rfind('/') == std::string::npos) {
        Usage("Unusable boot image symbol filename %s", oat_unstripped_[0].c_str());
      }
      oat_unstripped_ = ImageSpace::ExpandMultiImageLocations(
           locations, oat_unstripped_[0], IsBootImageExtension());
    }
  }

  void InsertCompileOptions(int argc, char** argv) {
    if (!avoid_storing_invocation_) {
      std::ostringstream oss;
      for (int i = 0; i < argc; ++i) {
        if (i > 0) {
          oss << ' ';
        }
        oss << argv[i];
      }
      key_value_store_->Put(OatHeader::kDex2OatCmdLineKey, oss.str());
    }
    key_value_store_->Put(OatHeader::kDebuggableKey, compiler_options_->debuggable_);
    key_value_store_->Put(OatHeader::kNativeDebuggableKey,
                          compiler_options_->GetNativeDebuggable());
    key_value_store_->Put(OatHeader::kCompilerFilter,
                          CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
    key_value_store_->Put(OatHeader::kConcurrentCopying, gUseReadBarrier);
    if (invocation_file_.get() != -1) {
      std::ostringstream oss;
      for (int i = 0; i < argc; ++i) {
        if (i > 0) {
          oss << std::endl;
        }
        oss << argv[i];
      }
      std::string invocation(oss.str());
      if (TEMP_FAILURE_RETRY(write(invocation_file_.get(),
                                   invocation.c_str(),
                                   invocation.size())) == -1) {
        Usage("Unable to write invocation file");
      }
    }
  }

  // This simple forward is here so the string specializations below don't look out of place.
  template <typename T, typename U>
  void AssignIfExists(Dex2oatArgumentMap& map,
                      const Dex2oatArgumentMap::Key<T>& key,
                      U* out) {
    map.AssignIfExists(key, out);
  }

  // Specializations to handle const char* vs std::string.
  void AssignIfExists(Dex2oatArgumentMap& map,
                      const Dex2oatArgumentMap::Key<std::string>& key,
                      const char** out) {
    if (map.Exists(key)) {
      char_backing_storage_.push_front(std::move(*map.Get(key)));
      *out = char_backing_storage_.front().c_str();
    }
  }
  void AssignIfExists(Dex2oatArgumentMap& map,
                      const Dex2oatArgumentMap::Key<std::vector<std::string>>& key,
                      std::vector<const char*>* out) {
    if (map.Exists(key)) {
      for (auto& val : *map.Get(key)) {
        char_backing_storage_.push_front(std::move(val));
        out->push_back(char_backing_storage_.front().c_str());
      }
    }
  }

  template <typename T>
  void AssignTrueIfExists(Dex2oatArgumentMap& map,
                          const Dex2oatArgumentMap::Key<T>& key,
                          bool* out) {
    if (map.Exists(key)) {
      *out = true;
    }
  }

  void AssignIfExists(Dex2oatArgumentMap& map,
                      const Dex2oatArgumentMap::Key<std::string>& key,
                      std::vector<std::string>* out) {
    DCHECK(out->empty());
    if (map.Exists(key)) {
      out->push_back(*map.Get(key));
    }
  }

  // Parse the arguments from the command line. In case of an unrecognized option or impossible
  // values/combinations, a usage error will be displayed and exit() is called. Thus, if the method
  // returns, arguments have been successfully parsed.
  void ParseArgs(int argc, char** argv) {
    original_argc = argc;
    original_argv = argv;

    Locks::Init();
    InitLogging(argv, Runtime::Abort);

    compiler_options_.reset(new CompilerOptions());

    using M = Dex2oatArgumentMap;
    std::string error_msg;
    std::unique_ptr<M> args_uptr = M::Parse(argc, const_cast<const char**>(argv), &error_msg);
    if (args_uptr == nullptr) {
      Usage("Failed to parse command line: %s", error_msg.c_str());
      UNREACHABLE();
    }

    M& args = *args_uptr;

    std::unique_ptr<ParserOptions> parser_options(new ParserOptions());

    AssignIfExists(args, M::CompactDexLevel, &compact_dex_level_);
    AssignIfExists(args, M::DexFiles, &dex_filenames_);
    AssignIfExists(args, M::DexLocations, &dex_locations_);
    AssignIfExists(args, M::DexFds, &dex_fds_);
    AssignIfExists(args, M::OatFile, &oat_filenames_);
    AssignIfExists(args, M::OatSymbols, &parser_options->oat_symbols);
    AssignTrueIfExists(args, M::Strip, &strip_);
    AssignIfExists(args, M::ImageFilename, &image_filenames_);
    AssignIfExists(args, M::ImageFd, &image_fd_);
    AssignIfExists(args, M::ZipFd, &zip_fd_);
    AssignIfExists(args, M::ZipLocation, &zip_location_);
    AssignIfExists(args, M::InputVdexFd, &input_vdex_fd_);
    AssignIfExists(args, M::OutputVdexFd, &output_vdex_fd_);
    AssignIfExists(args, M::InputVdex, &input_vdex_);
    AssignIfExists(args, M::OutputVdex, &output_vdex_);
    AssignIfExists(args, M::DmFd, &dm_fd_);
    AssignIfExists(args, M::DmFile, &dm_file_location_);
    AssignIfExists(args, M::OatFd, &oat_fd_);
    AssignIfExists(args, M::OatLocation, &oat_location_);
    AssignIfExists(args, M::Watchdog, &parser_options->watch_dog_enabled);
    AssignIfExists(args, M::WatchdogTimeout, &parser_options->watch_dog_timeout_in_ms);
    AssignIfExists(args, M::Threads, &thread_count_);
    AssignIfExists(args, M::CpuSet, &cpu_set_);
    AssignIfExists(args, M::Passes, &passes_to_run_filename_);
    AssignIfExists(args, M::BootImage, &parser_options->boot_image_filename);
    AssignIfExists(args, M::AndroidRoot, &android_root_);
    AssignIfExists(args, M::Profile, &profile_files_);
    AssignIfExists(args, M::ProfileFd, &profile_file_fds_);
    AssignIfExists(args, M::PreloadedClasses, &preloaded_classes_files_);
    AssignIfExists(args, M::PreloadedClassesFds, &preloaded_classes_fds_);
    AssignIfExists(args, M::RuntimeOptions, &runtime_args_);
    AssignIfExists(args, M::SwapFile, &swap_file_name_);
    AssignIfExists(args, M::SwapFileFd, &swap_fd_);
    AssignIfExists(args, M::SwapDexSizeThreshold, &min_dex_file_cumulative_size_for_swap_);
    AssignIfExists(args, M::SwapDexCountThreshold, &min_dex_files_for_swap_);
    AssignIfExists(args, M::VeryLargeAppThreshold, &very_large_threshold_);
    AssignIfExists(args, M::AppImageFile, &app_image_file_name_);
    AssignIfExists(args, M::AppImageFileFd, &app_image_fd_);
    AssignIfExists(args, M::NoInlineFrom, &no_inline_from_string_);
    AssignIfExists(args, M::ClasspathDir, &classpath_dir_);
    AssignIfExists(args, M::DirtyImageObjects, &dirty_image_objects_filename_);
    AssignIfExists(args, M::DirtyImageObjectsFd, &dirty_image_objects_fd_);
    AssignIfExists(args, M::ImageFormat, &image_storage_mode_);
    AssignIfExists(args, M::CompilationReason, &compilation_reason_);
    AssignTrueIfExists(args, M::CheckLinkageConditions, &check_linkage_conditions_);
    AssignTrueIfExists(args, M::CrashOnLinkageViolation, &crash_on_linkage_violation_);
    AssignTrueIfExists(args, M::ForceAllowOjInlines, &force_allow_oj_inlines_);
    AssignIfExists(args, M::PublicSdk, &public_sdk_);
    AssignIfExists(args, M::ApexVersions, &apex_versions_argument_);

    AssignIfExists(args, M::Backend, &compiler_kind_);
    parser_options->requested_specific_compiler = args.Exists(M::Backend);

    AssignIfExists(args, M::TargetInstructionSet, &compiler_options_->instruction_set_);
    // arm actually means thumb2.
    if (compiler_options_->instruction_set_ == InstructionSet::kArm) {
      compiler_options_->instruction_set_ = InstructionSet::kThumb2;
    }

    AssignTrueIfExists(args, M::Host, &is_host_);
    AssignTrueIfExists(args, M::AvoidStoringInvocation, &avoid_storing_invocation_);
    if (args.Exists(M::InvocationFile)) {
      invocation_file_.reset(open(args.Get(M::InvocationFile)->c_str(),
                                  O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC,
                                  S_IRUSR|S_IWUSR));
      if (invocation_file_.get() == -1) {
        int err = errno;
        Usage("Unable to open invocation file '%s' for writing due to %s.",
              args.Get(M::InvocationFile)->c_str(), strerror(err));
      }
    }
    AssignIfExists(args, M::CopyDexFiles, &copy_dex_files_);

    AssignTrueIfExists(args, M::MultiImage, &have_multi_image_arg_);
    AssignIfExists(args, M::MultiImage, &compiler_options_->multi_image_);

    if (args.Exists(M::ForceDeterminism)) {
      force_determinism_ = true;
    }
    AssignTrueIfExists(args, M::CompileIndividually, &compile_individually_);

    if (args.Exists(M::Base)) {
      ParseBase(*args.Get(M::Base));
    }
    if (args.Exists(M::TargetInstructionSetVariant)) {
      ParseInstructionSetVariant(*args.Get(M::TargetInstructionSetVariant), parser_options.get());
    }
    if (args.Exists(M::TargetInstructionSetFeatures)) {
      ParseInstructionSetFeatures(*args.Get(M::TargetInstructionSetFeatures), parser_options.get());
    }
    if (args.Exists(M::ClassLoaderContext)) {
      std::string class_loader_context_arg = *args.Get(M::ClassLoaderContext);
      class_loader_context_ = ClassLoaderContext::Create(class_loader_context_arg);
      if (class_loader_context_ == nullptr) {
        Usage("Option --class-loader-context has an incorrect format: %s",
              class_loader_context_arg.c_str());
      }
      if (args.Exists(M::ClassLoaderContextFds)) {
        std::string str_fds_arg = *args.Get(M::ClassLoaderContextFds);
        std::vector<std::string> str_fds = android::base::Split(str_fds_arg, ":");
        for (const std::string& str_fd : str_fds) {
          class_loader_context_fds_.push_back(std::stoi(str_fd, nullptr, 0));
          if (class_loader_context_fds_.back() < 0) {
            Usage("Option --class-loader-context-fds has incorrect format: %s",
                str_fds_arg.c_str());
          }
        }
      }
      if (args.Exists(M::StoredClassLoaderContext)) {
        const std::string stored_context_arg = *args.Get(M::StoredClassLoaderContext);
        stored_class_loader_context_ = ClassLoaderContext::Create(stored_context_arg);
        if (stored_class_loader_context_ == nullptr) {
          Usage("Option --stored-class-loader-context has an incorrect format: %s",
                stored_context_arg.c_str());
        } else if (class_loader_context_->VerifyClassLoaderContextMatch(
            stored_context_arg,
            /*verify_names*/ false,
            /*verify_checksums*/ false) != ClassLoaderContext::VerificationResult::kVerifies) {
          Usage(
              "Option --stored-class-loader-context '%s' mismatches --class-loader-context '%s'",
              stored_context_arg.c_str(),
              class_loader_context_arg.c_str());
        }
      }
    } else if (args.Exists(M::StoredClassLoaderContext)) {
      Usage("Option --stored-class-loader-context should only be used if "
            "--class-loader-context is also specified");
    }

    if (args.Exists(M::UpdatableBcpPackagesFile)) {
      LOG(WARNING)
          << "Option --updatable-bcp-packages-file is deprecated and no longer takes effect";
    }

    if (args.Exists(M::UpdatableBcpPackagesFd)) {
      LOG(WARNING) << "Option --updatable-bcp-packages-fd is deprecated and no longer takes effect";
    }

    if (args.Exists(M::ForceJitZygote)) {
      if (!parser_options->boot_image_filename.empty()) {
        Usage("Option --boot-image and --force-jit-zygote cannot be specified together");
      }
      parser_options->boot_image_filename = GetJitZygoteBootImageLocation();
    }

    // If we have a profile, change the default compiler filter to speed-profile
    // before reading compiler options.
    static_assert(CompilerFilter::kDefaultCompilerFilter == CompilerFilter::kSpeed);
    DCHECK_EQ(compiler_options_->GetCompilerFilter(), CompilerFilter::kSpeed);
    if (HasProfileInput()) {
      compiler_options_->SetCompilerFilter(CompilerFilter::kSpeedProfile);
    }

    if (!ReadCompilerOptions(args, compiler_options_.get(), &error_msg)) {
      Usage(error_msg.c_str());
    }

    if (!compiler_options_->GetDumpCfgFileName().empty() && thread_count_ != 1) {
      LOG(INFO) << "Since we are dumping the CFG to " << compiler_options_->GetDumpCfgFileName()
                << ", we override thread number to 1 to have determinism. It was " << thread_count_
                << ".";
      thread_count_ = 1;
    }

    // For debuggable apps, we do not want to generate compact dex as class
    // redefinition will want a proper dex file.
    if (compiler_options_->GetDebuggable()) {
      compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone;
    }

    PaletteShouldReportDex2oatCompilation(&should_report_dex2oat_compilation_);
    AssignTrueIfExists(args, M::ForcePaletteCompilationHooks, &should_report_dex2oat_compilation_);

    ProcessOptions(parser_options.get());
  }

  // Check whether the oat output files are writable, and open them for later. Also open a swap
  // file, if a name is given.
  bool OpenFile() {
    // Prune non-existent dex files now so that we don't create empty oat files for multi-image.
    PruneNonExistentDexFiles();

    // Expand oat and image filenames for boot image and boot image extension.
    // This is mostly for multi-image but single-image also needs some processing.
    if (IsBootImage() || IsBootImageExtension()) {
      ExpandOatAndImageFilenames();
    }

    // OAT and VDEX file handling
    if (oat_fd_ == -1) {
      DCHECK(!oat_filenames_.empty());
      for (const std::string& oat_filename : oat_filenames_) {
        std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_filename.c_str()));
        if (oat_file == nullptr) {
          PLOG(ERROR) << "Failed to create oat file: " << oat_filename;
          return false;
        }
        if (fchmod(oat_file->Fd(), 0644) != 0) {
          PLOG(ERROR) << "Failed to make oat file world readable: " << oat_filename;
          oat_file->Erase();
          return false;
        }
        oat_files_.push_back(std::move(oat_file));
        DCHECK_EQ(input_vdex_fd_, -1);
        if (!input_vdex_.empty()) {
          std::string error_msg;
          input_vdex_file_ = VdexFile::Open(input_vdex_,
                                            /* writable */ false,
                                            /* low_4gb */ false,
                                            &error_msg);
        }

        DCHECK_EQ(output_vdex_fd_, -1);
        std::string vdex_filename = output_vdex_.empty()
            ? ReplaceFileExtension(oat_filename, "vdex")
            : output_vdex_;
        if (vdex_filename == input_vdex_ && output_vdex_.empty()) {
          use_existing_vdex_ = true;
          std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_filename.c_str()));
          vdex_files_.push_back(std::move(vdex_file));
        } else {
          std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_filename.c_str()));
          if (vdex_file == nullptr) {
            PLOG(ERROR) << "Failed to open vdex file: " << vdex_filename;
            return false;
          }
          if (fchmod(vdex_file->Fd(), 0644) != 0) {
            PLOG(ERROR) << "Failed to make vdex file world readable: " << vdex_filename;
            vdex_file->Erase();
            return false;
          }
          vdex_files_.push_back(std::move(vdex_file));
        }
      }
    } else {
      std::unique_ptr<File> oat_file(
          new File(DupCloexec(oat_fd_), oat_location_, /* check_usage */ true));
      if (!oat_file->IsOpened()) {
        PLOG(ERROR) << "Failed to create oat file: " << oat_location_;
        return false;
      }
      if (oat_file->SetLength(0) != 0) {
        PLOG(WARNING) << "Truncating oat file " << oat_location_ << " failed.";
        oat_file->Erase();
        return false;
      }
      oat_files_.push_back(std::move(oat_file));

      if (input_vdex_fd_ != -1) {
        struct stat s;
        int rc = TEMP_FAILURE_RETRY(fstat(input_vdex_fd_, &s));
        if (rc == -1) {
          PLOG(WARNING) << "Failed getting length of vdex file";
        } else {
          std::string error_msg;
          input_vdex_file_ = VdexFile::Open(input_vdex_fd_,
                                            s.st_size,
                                            "vdex",
                                            /* writable */ false,
                                            /* low_4gb */ false,
                                            &error_msg);
          // If there's any problem with the passed vdex, just warn and proceed
          // without it.
          if (input_vdex_file_ == nullptr) {
            PLOG(WARNING) << "Failed opening vdex file: " << error_msg;
          }
        }
      }

      DCHECK_NE(output_vdex_fd_, -1);
      std::string vdex_location = ReplaceFileExtension(oat_location_, "vdex");
      if (input_vdex_file_ != nullptr && output_vdex_fd_ == input_vdex_fd_) {
        use_existing_vdex_ = true;
      }

      std::unique_ptr<File> vdex_file(new File(DupCloexec(output_vdex_fd_),
                                               vdex_location,
                                               /* check_usage= */ true,
                                               /* read_only_mode= */ use_existing_vdex_));
      if (!vdex_file->IsOpened()) {
        PLOG(ERROR) << "Failed to create vdex file: " << vdex_location;
        return false;
      }

      if (!use_existing_vdex_) {
        if (vdex_file->SetLength(0) != 0) {
          PLOG(ERROR) << "Truncating vdex file " << vdex_location << " failed.";
          vdex_file->Erase();
          return false;
        }
      }
      vdex_files_.push_back(std::move(vdex_file));

      oat_filenames_.push_back(oat_location_);
    }

    if (dm_fd_ != -1 || !dm_file_location_.empty()) {
      std::string error_msg;
      if (dm_fd_ != -1) {
        dm_file_.reset(ZipArchive::OpenFromFd(dm_fd_, "DexMetadata", &error_msg));
      } else {
        dm_file_.reset(ZipArchive::Open(dm_file_location_.c_str(), &error_msg));
      }
      if (dm_file_ == nullptr) {
        LOG(WARNING) << "Could not open DexMetadata archive " << error_msg;
      }
    }

    // If we have a dm file and a vdex file, we (arbitrarily) pick the vdex file.
    // In theory the files should be the same.
    if (dm_file_ != nullptr) {
      if (input_vdex_file_ == nullptr) {
        input_vdex_file_ = VdexFile::OpenFromDm(dm_file_location_, *dm_file_);
        if (input_vdex_file_ != nullptr) {
          VLOG(verifier) << "Doing fast verification with vdex from DexMetadata archive";
        }
      } else {
        LOG(INFO) << "Ignoring vdex file in dex metadata due to vdex file already being passed";
      }
    }

    // Swap file handling
    //
    // If the swap fd is not -1, we assume this is the file descriptor of an open but unlinked file
    // that we can use for swap.
    //
    // If the swap fd is -1 and we have a swap-file string, open the given file as a swap file. We
    // will immediately unlink to satisfy the swap fd assumption.
    if (swap_fd_ == -1 && !swap_file_name_.empty()) {
      std::unique_ptr<File> swap_file(OS::CreateEmptyFile(swap_file_name_.c_str()));
      if (swap_file.get() == nullptr) {
        PLOG(ERROR) << "Failed to create swap file: " << swap_file_name_;
        return false;
      }
      swap_fd_ = swap_file->Release();
      unlink(swap_file_name_.c_str());
    }

    return true;
  }

  void EraseOutputFiles() {
    for (auto& files : { &vdex_files_, &oat_files_ }) {
      for (size_t i = 0; i < files->size(); ++i) {
        auto& file = (*files)[i];
        if (file != nullptr) {
          if (!file->ReadOnlyMode()) {
            file->Erase();
          }
          file.reset();
        }
      }
    }
  }

  void LoadClassProfileDescriptors() {
    if (!IsImage()) {
      return;
    }
    if (DoProfileGuidedOptimizations()) {
      // TODO: The following comment looks outdated or misplaced.
      // Filter out class path classes since we don't want to include these in the image.
      HashSet<std::string> image_classes = profile_compilation_info_->GetClassDescriptors(
          compiler_options_->dex_files_for_oat_file_);
      VLOG(compiler) << "Loaded " << image_classes.size()
                     << " image class descriptors from profile";
      if (VLOG_IS_ON(compiler)) {
        for (const std::string& s : image_classes) {
          LOG(INFO) << "Image class " << s;
        }
      }
      compiler_options_->image_classes_.swap(image_classes);
    }
  }

  // Set up the environment for compilation. Includes starting the runtime and loading/opening the
  // boot class path.
  dex2oat::ReturnCode Setup() {
    TimingLogger::ScopedTiming t("dex2oat Setup", timings_);

    if (!PrepareDirtyObjects()) {
      return dex2oat::ReturnCode::kOther;
    }

    if (!PreparePreloadedClasses()) {
      return dex2oat::ReturnCode::kOther;
    }

    callbacks_.reset(new QuickCompilerCallbacks(
        // For class verification purposes, boot image extension is the same as boot image.
        (IsBootImage() || IsBootImageExtension())
            ? CompilerCallbacks::CallbackMode::kCompileBootImage
            : CompilerCallbacks::CallbackMode::kCompileApp));

    RuntimeArgumentMap runtime_options;
    if (!PrepareRuntimeOptions(&runtime_options, callbacks_.get())) {
      return dex2oat::ReturnCode::kOther;
    }

    CreateOatWriters();
    if (!AddDexFileSources()) {
      return dex2oat::ReturnCode::kOther;
    }

    {
      TimingLogger::ScopedTiming t_dex("Writing and opening dex files", timings_);
      for (size_t i = 0, size = oat_writers_.size(); i != size; ++i) {
        // Unzip or copy dex files straight to the oat file.
        std::vector<MemMap> opened_dex_files_map;
        std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
        // No need to verify the dex file when we have a vdex file, which means it was already
        // verified.
        const bool verify =
            (input_vdex_file_ == nullptr) && !compiler_options_->AssumeDexFilesAreVerified();
        if (!oat_writers_[i]->WriteAndOpenDexFiles(
            vdex_files_[i].get(),
            verify,
            use_existing_vdex_,
            copy_dex_files_,
            &opened_dex_files_map,
            &opened_dex_files)) {
          return dex2oat::ReturnCode::kOther;
        }
        dex_files_per_oat_file_.push_back(MakeNonOwningPointerVector(opened_dex_files));
        if (opened_dex_files_map.empty()) {
          DCHECK(opened_dex_files.empty());
        } else {
          for (MemMap& map : opened_dex_files_map) {
            opened_dex_files_maps_.push_back(std::move(map));
          }
          for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
            dex_file_oat_index_map_.insert(std::make_pair(dex_file.get(), i));
            opened_dex_files_.push_back(std::move(dex_file));
          }
        }
      }
    }

    compiler_options_->dex_files_for_oat_file_ = MakeNonOwningPointerVector(opened_dex_files_);
    const std::vector<const DexFile*>& dex_files = compiler_options_->dex_files_for_oat_file_;

    if (!ValidateInputVdexChecksums()) {
       return dex2oat::ReturnCode::kOther;
    }

    // Check if we need to downgrade the compiler-filter for size reasons.
    // Note: This does not affect the compiler filter already stored in the key-value
    //       store which is used for determining whether the oat file is up to date,
    //       together with the boot class path locations and checksums stored below.
    CompilerFilter::Filter original_compiler_filter = compiler_options_->GetCompilerFilter();
    if (!IsBootImage() && !IsBootImageExtension() && IsVeryLarge(dex_files)) {
      // Disable app image to make sure dex2oat unloading is enabled.
      compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;

      // If we need to downgrade the compiler-filter for size reasons, do that early before we read
      // it below for creating verification callbacks.
      if (!CompilerFilter::IsAsGoodAs(kLargeAppFilter, compiler_options_->GetCompilerFilter())) {
        LOG(INFO) << "Very large app, downgrading to verify.";
        compiler_options_->SetCompilerFilter(kLargeAppFilter);
      }
    }

    if (CompilerFilter::IsAnyCompilationEnabled(compiler_options_->GetCompilerFilter()) ||
        IsImage()) {
      // Only modes with compilation or image generation require verification results.
      verification_results_.reset(new VerificationResults());
      callbacks_->SetVerificationResults(verification_results_.get());
    }

    if (IsBootImage() || IsBootImageExtension()) {
      // For boot image or boot image extension, pass opened dex files to the Runtime::Create().
      // Note: Runtime acquires ownership of these dex files.
      runtime_options.Set(RuntimeArgumentMap::BootClassPathDexList, &opened_dex_files_);
    }
    if (!CreateRuntime(std::move(runtime_options))) {
      return dex2oat::ReturnCode::kCreateRuntime;
    }
    if (runtime_->GetHeap()->GetBootImageSpaces().empty() &&
        (IsBootImageExtension() || IsAppImage())) {
      LOG(WARNING) << "Cannot create "
                   << (IsBootImageExtension() ? "boot image extension" : "app image")
                   << " without a primary boot image.";
      compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;
    }
    ArrayRef<const DexFile* const> bcp_dex_files(runtime_->GetClassLinker()->GetBootClassPath());
    if (IsBootImage() || IsBootImageExtension()) {
      // Check boot class path dex files and, if compiling an extension, the images it depends on.
      if ((IsBootImage() && bcp_dex_files.size() != dex_files.size()) ||
          (IsBootImageExtension() && bcp_dex_files.size() <= dex_files.size())) {
        LOG(ERROR) << "Unexpected number of boot class path dex files for boot image or extension, "
            << bcp_dex_files.size() << (IsBootImage() ? " != " : " <= ") << dex_files.size();
        return dex2oat::ReturnCode::kOther;
      }
      if (!std::equal(dex_files.begin(), dex_files.end(), bcp_dex_files.end() - dex_files.size())) {
        LOG(ERROR) << "Boot class path dex files do not end with the compiled dex files.";
        return dex2oat::ReturnCode::kOther;
      }
      size_t bcp_df_pos = 0u;
      size_t bcp_df_end = bcp_dex_files.size();
      for (const std::string& bcp_location : runtime_->GetBootClassPathLocations()) {
        if (bcp_df_pos == bcp_df_end || bcp_dex_files[bcp_df_pos]->GetLocation() != bcp_location) {
          LOG(ERROR) << "Missing dex file for boot class component " << bcp_location;
          return dex2oat::ReturnCode::kOther;
        }
        CHECK(!DexFileLoader::IsMultiDexLocation(bcp_dex_files[bcp_df_pos]->GetLocation().c_str()));
        ++bcp_df_pos;
        while (bcp_df_pos != bcp_df_end &&
            DexFileLoader::IsMultiDexLocation(bcp_dex_files[bcp_df_pos]->GetLocation().c_str())) {
          ++bcp_df_pos;
        }
      }
      if (bcp_df_pos != bcp_df_end) {
        LOG(ERROR) << "Unexpected dex file in boot class path "
            << bcp_dex_files[bcp_df_pos]->GetLocation();
        return dex2oat::ReturnCode::kOther;
      }
      auto lacks_image = [](const DexFile* df) {
        if (kIsDebugBuild && df->GetOatDexFile() != nullptr) {
          const OatFile* oat_file = df->GetOatDexFile()->GetOatFile();
          CHECK(oat_file != nullptr);
          const auto& image_spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
          CHECK(std::any_of(image_spaces.begin(),
                            image_spaces.end(),
                            [=](const ImageSpace* space) {
                              return oat_file == space->GetOatFile();
                            }));
        }
        return df->GetOatDexFile() == nullptr;
      };
      if (std::any_of(bcp_dex_files.begin(), bcp_dex_files.end() - dex_files.size(), lacks_image)) {
        LOG(ERROR) << "Missing required boot image(s) for boot image extension.";
        return dex2oat::ReturnCode::kOther;
      }
    }

    if (!compilation_reason_.empty()) {
      key_value_store_->Put(OatHeader::kCompilationReasonKey, compilation_reason_);
    }

    Runtime* runtime = Runtime::Current();

    if (IsBootImage()) {
      // If we're compiling the boot image, store the boot classpath into the Key-Value store.
      // We use this when loading the boot image.
      key_value_store_->Put(OatHeader::kBootClassPathKey, android::base::Join(dex_locations_, ':'));
    } else if (IsBootImageExtension()) {
      // Validate the boot class path and record the dependency on the loaded boot images.
      TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
      std::string full_bcp = android::base::Join(runtime->GetBootClassPathLocations(), ':');
      std::string extension_part = ":" + android::base::Join(dex_locations_, ':');
      if (!android::base::EndsWith(full_bcp, extension_part)) {
        LOG(ERROR) << "Full boot class path does not end with extension parts, full: " << full_bcp
            << ", extension: " << extension_part.substr(1u);
        return dex2oat::ReturnCode::kOther;
      }
      std::string bcp_dependency = full_bcp.substr(0u, full_bcp.size() - extension_part.size());
      key_value_store_->Put(OatHeader::kBootClassPathKey, bcp_dependency);
      ArrayRef<const DexFile* const> bcp_dex_files_dependency =
          bcp_dex_files.SubArray(/*pos=*/ 0u, bcp_dex_files.size() - dex_files.size());
      ArrayRef<ImageSpace* const> image_spaces(runtime->GetHeap()->GetBootImageSpaces());
      key_value_store_->Put(
          OatHeader::kBootClassPathChecksumsKey,
          gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces, bcp_dex_files_dependency));
    } else {
      if (CompilerFilter::DependsOnImageChecksum(original_compiler_filter)) {
        TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
        key_value_store_->Put(OatHeader::kBootClassPathKey,
                              android::base::Join(runtime->GetBootClassPathLocations(), ':'));
        ArrayRef<ImageSpace* const> image_spaces(runtime->GetHeap()->GetBootImageSpaces());
        key_value_store_->Put(
            OatHeader::kBootClassPathChecksumsKey,
            gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces, bcp_dex_files));
      }

      // Open dex files for class path.

      if (class_loader_context_ == nullptr) {
        // If no context was specified use the default one (which is an empty PathClassLoader).
        class_loader_context_ = ClassLoaderContext::Default();
      }

      DCHECK_EQ(oat_writers_.size(), 1u);

      // Note: Ideally we would reject context where the source dex files are also
      // specified in the classpath (as it doesn't make sense). However this is currently
      // needed for non-prebuild tests and benchmarks which expects on the fly compilation.
      // Also, for secondary dex files we do not have control on the actual classpath.
      // Instead of aborting, remove all the source location from the context classpaths.
      if (class_loader_context_->RemoveLocationsFromClassPaths(
            oat_writers_[0]->GetSourceLocations())) {
        LOG(WARNING) << "The source files to be compiled are also in the classpath.";
      }

      // We need to open the dex files before encoding the context in the oat file.
      // (because the encoding adds the dex checksum...)
      // TODO(calin): consider redesigning this so we don't have to open the dex files before
      // creating the actual class loader.
      if (!class_loader_context_->OpenDexFiles(classpath_dir_,
                                               class_loader_context_fds_)) {
        // Do not abort if we couldn't open files from the classpath. They might be
        // apks without dex files and right now are opening flow will fail them.
        LOG(WARNING) << "Failed to open classpath dex files";
      }

      // Store the class loader context in the oat header.
      // TODO: deprecate this since store_class_loader_context should be enough to cover the users
      // of classpath_dir as well.
      std::string class_path_key =
          class_loader_context_->EncodeContextForOatFile(classpath_dir_,
                                                         stored_class_loader_context_.get());
      key_value_store_->Put(OatHeader::kClassPathKey, class_path_key);
    }

    if (IsBootImage() ||
        IsBootImageExtension() ||
        CompilerFilter::DependsOnImageChecksum(original_compiler_filter)) {
      std::string versions =
          apex_versions_argument_.empty() ? runtime->GetApexVersions() : apex_versions_argument_;
      key_value_store_->Put(OatHeader::kApexVersionsKey, versions);
    }

    // Now that we have adjusted whether we generate an image, encode it in the
    // key/value store.
    key_value_store_->Put(OatHeader::kRequiresImage, compiler_options_->IsGeneratingImage());

    // Now that we have finalized key_value_store_, start writing the .rodata section.
    // Among other things, this creates type lookup tables that speed up the compilation.
    {
      TimingLogger::ScopedTiming t_dex("Starting .rodata", timings_);
      rodata_.reserve(oat_writers_.size());
      for (size_t i = 0, size = oat_writers_.size(); i != size; ++i) {
        rodata_.push_back(elf_writers_[i]->StartRoData());
        if (!oat_writers_[i]->StartRoData(dex_files_per_oat_file_[i],
                                          rodata_.back(),
                                          (i == 0u) ? key_value_store_.get() : nullptr)) {
          return dex2oat::ReturnCode::kOther;
        }
      }
    }

    // We had to postpone the swap decision till now, as this is the point when we actually
    // know about the dex files we're going to use.

    // Make sure that we didn't create the driver, yet.
    CHECK(driver_ == nullptr);
    // If we use a swap file, ensure we are above the threshold to make it necessary.
    if (swap_fd_ != -1) {
      if (!UseSwap(IsBootImage() || IsBootImageExtension(), dex_files)) {
        close(swap_fd_);
        swap_fd_ = -1;
        VLOG(compiler) << "Decided to run without swap.";
      } else {
        LOG(INFO) << "Large app, accepted running with swap.";
      }
    }
    // Note that dex2oat won't close the swap_fd_. The compiler driver's swap space will do that.

    if (!IsBootImage() && !IsBootImageExtension()) {
      constexpr bool kSaveDexInput = false;
      if (kSaveDexInput) {
        SaveDexInput();
      }
    }

    // Setup VerifierDeps for compilation and report if we fail to parse the data.
    // When we do profile guided optimizations, the compiler currently needs to run
    // full verification.
    if (!DoProfileGuidedOptimizations() && input_vdex_file_ != nullptr) {
      std::unique_ptr<verifier::VerifierDeps> verifier_deps(
          new verifier::VerifierDeps(dex_files, /*output_only=*/ false));
      if (!verifier_deps->ParseStoredData(dex_files, input_vdex_file_->GetVerifierDepsData())) {
        return dex2oat::ReturnCode::kOther;
      }
      // We can do fast verification.
      callbacks_->SetVerifierDeps(verifier_deps.release());
    } else {
      // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate
      // the results for all the dex files, not just the results for the current dex file.
      callbacks_->SetVerifierDeps(new verifier::VerifierDeps(dex_files));
    }

    return dex2oat::ReturnCode::kNoFailure;
  }

  // Validates that the input vdex checksums match the source dex checksums.
  // Note that this is only effective and relevant if the input_vdex_file does not
  // contain a dex section (e.g. when they come from .dm files).
  // If the input vdex does contain dex files, the dex files will be opened from there
  // and so this check is redundant.
  bool ValidateInputVdexChecksums() {
    if (input_vdex_file_ == nullptr) {
      // Nothing to validate
      return true;
    }
    if (input_vdex_file_->GetNumberOfDexFiles()
          != compiler_options_->dex_files_for_oat_file_.size()) {
      LOG(ERROR) << "Vdex file contains a different number of dex files than the source. "
          << " vdex_num=" << input_vdex_file_->GetNumberOfDexFiles()
          << " dex_source_num=" << compiler_options_->dex_files_for_oat_file_.size();
      return false;
    }

    for (size_t i = 0; i < compiler_options_->dex_files_for_oat_file_.size(); i++) {
      uint32_t dex_source_checksum =
          compiler_options_->dex_files_for_oat_file_[i]->GetLocationChecksum();
      uint32_t vdex_checksum = input_vdex_file_->GetLocationChecksum(i);
      if (dex_source_checksum != vdex_checksum) {
        LOG(ERROR) << "Vdex file checksum different than source dex checksum for position " << i
          << std::hex
          << " vdex_checksum=0x" << vdex_checksum
          << " dex_source_checksum=0x" << dex_source_checksum
          << std::dec;
        return false;
      }
    }
    return true;
  }

  // If we need to keep the oat file open for the image writer.
  bool ShouldKeepOatFileOpen() const {
    return IsImage() && oat_fd_ != File::kInvalidFd;
  }

  // Doesn't return the class loader since it's not meant to be used for image compilation.
  void CompileDexFilesIndividually() {
    CHECK(!IsImage()) << "Not supported with image";
    for (const DexFile* dex_file : compiler_options_->dex_files_for_oat_file_) {
      std::vector<const DexFile*> dex_files(1u, dex_file);
      VLOG(compiler) << "Compiling " << dex_file->GetLocation();
      jobject class_loader = CompileDexFiles(dex_files);
      CHECK(class_loader != nullptr);
      ScopedObjectAccess soa(Thread::Current());
      // Unload class loader to free RAM.
      jweak weak_class_loader = soa.Env()->GetVm()->AddWeakGlobalRef(
          soa.Self(),
          soa.Decode<mirror::ClassLoader>(class_loader));
      soa.Env()->GetVm()->DeleteGlobalRef(soa.Self(), class_loader);
      runtime_->GetHeap()->CollectGarbage(/* clear_soft_references */ true);
      ObjPtr<mirror::ClassLoader> decoded_weak = soa.Decode<mirror::ClassLoader>(weak_class_loader);
      if (decoded_weak != nullptr) {
        LOG(FATAL) << "Failed to unload class loader, path from root set: "
                   << runtime_->GetHeap()->GetVerification()->FirstPathFromRootSet(decoded_weak);
      }
      VLOG(compiler) << "Unloaded classloader";
    }
  }

  bool ShouldCompileDexFilesIndividually() const {
    // Compile individually if we are allowed to, and
    // 1. not building an image, and
    // 2. not verifying a vdex file, and
    // 3. using multidex, and
    // 4. not doing any AOT compilation.
    // This means extract, no-vdex verify, and quicken, will use the individual compilation
    // mode (to reduce RAM used by the compiler).
    return compile_individually_ &&
           (!IsImage() && !use_existing_vdex_ &&
            compiler_options_->dex_files_for_oat_file_.size() > 1 &&
            !CompilerFilter::IsAotCompilationEnabled(compiler_options_->GetCompilerFilter()));
  }

  uint32_t GetCombinedChecksums() const {
    uint32_t combined_checksums = 0u;
    for (const DexFile* dex_file : compiler_options_->GetDexFilesForOatFile()) {
      combined_checksums ^= dex_file->GetLocationChecksum();
    }
    return combined_checksums;
  }

  // Set up and create the compiler driver and then invoke it to compile all the dex files.
  jobject Compile() REQUIRES(!Locks::mutator_lock_) {
    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();

    TimingLogger::ScopedTiming t("dex2oat Compile", timings_);

    // Find the dex files we should not inline from.
    std::vector<std::string> no_inline_filters;
    Split(no_inline_from_string_, ',', &no_inline_filters);

    // For now, on the host always have core-oj removed.
    const std::string core_oj = "core-oj";
    if (!kIsTargetBuild && !ContainsElement(no_inline_filters, core_oj)) {
      if (force_allow_oj_inlines_) {
        LOG(ERROR) << "Inlines allowed from core-oj! FOR TESTING USE ONLY! DO NOT DISTRIBUTE"
                   << " BINARIES BUILT WITH THIS OPTION!";
      } else {
        no_inline_filters.push_back(core_oj);
      }
    }

    if (!no_inline_filters.empty()) {
      std::vector<const DexFile*> class_path_files;
      if (!IsBootImage() && !IsBootImageExtension()) {
        // The class loader context is used only for apps.
        class_path_files = class_loader_context_->FlattenOpenedDexFiles();
      }

      const std::vector<const DexFile*>& dex_files = compiler_options_->dex_files_for_oat_file_;
      std::vector<const DexFile*> no_inline_from_dex_files;
      const std::vector<const DexFile*>* dex_file_vectors[] = {
          &class_linker->GetBootClassPath(),
          &class_path_files,
          &dex_files
      };
      for (const std::vector<const DexFile*>* dex_file_vector : dex_file_vectors) {
        for (const DexFile* dex_file : *dex_file_vector) {
          for (const std::string& filter : no_inline_filters) {
            // Use dex_file->GetLocation() rather than dex_file->GetBaseLocation(). This
            // allows tests to specify <test-dexfile>!classes2.dex if needed but if the
            // base location passes the StartsWith() test, so do all extra locations.
            std::string dex_location = dex_file->GetLocation();
            if (filter.find('/') == std::string::npos) {
              // The filter does not contain the path. Remove the path from dex_location as well.
              size_t last_slash = dex_file->GetLocation().rfind('/');
              if (last_slash != std::string::npos) {
                dex_location = dex_location.substr(last_slash + 1);
              }
            }

            if (android::base::StartsWith(dex_location, filter.c_str())) {
              VLOG(compiler) << "Disabling inlining from " << dex_file->GetLocation();
              no_inline_from_dex_files.push_back(dex_file);
              break;
            }
          }
        }
      }
      if (!no_inline_from_dex_files.empty()) {
        compiler_options_->no_inline_from_.swap(no_inline_from_dex_files);
      }
    }
    compiler_options_->profile_compilation_info_ = profile_compilation_info_.get();

    driver_.reset(new CompilerDriver(compiler_options_.get(),
                                     verification_results_.get(),
                                     compiler_kind_,
                                     thread_count_,
                                     swap_fd_));

    driver_->PrepareDexFilesForOatFile(timings_);

    if (!IsBootImage() && !IsBootImageExtension()) {
      driver_->SetClasspathDexFiles(class_loader_context_->FlattenOpenedDexFiles());
    }

    const bool compile_individually = ShouldCompileDexFilesIndividually();
    if (compile_individually) {
      // Set the compiler driver in the callbacks so that we can avoid re-verification. This not
      // only helps performance but also prevents reverifying quickened bytecodes. Attempting
      // verify quickened bytecode causes verification failures.
      // Only set the compiler filter if we are doing separate compilation since there is a bit
      // of overhead when checking if a class was previously verified.
      callbacks_->SetDoesClassUnloading(true, driver_.get());
    }

    // Setup vdex for compilation.
    const std::vector<const DexFile*>& dex_files = compiler_options_->dex_files_for_oat_file_;
    // To allow initialization of classes that construct ThreadLocal objects in class initializer,
    // re-initialize the ThreadLocal.nextHashCode to a new object that's not in the boot image.
    ThreadLocalHashOverride thread_local_hash_override(
        /*apply=*/ !IsBootImage(), /*initial_value=*/ 123456789u ^ GetCombinedChecksums());

    // Invoke the compilation.
    if (compile_individually) {
      CompileDexFilesIndividually();
      // Return a null classloader since we already freed released it.
      return nullptr;
    }
    return CompileDexFiles(dex_files);
  }

  // Create the class loader, use it to compile, and return.
  jobject CompileDexFiles(const std::vector<const DexFile*>& dex_files) {
    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();

    jobject class_loader = nullptr;
    if (!IsBootImage() && !IsBootImageExtension()) {
      class_loader =
          class_loader_context_->CreateClassLoader(compiler_options_->GetDexFilesForOatFile());
    }
    if (!IsBootImage()) {
      callbacks_->SetDexFiles(&dex_files);

      // We need to set this after we create the class loader so that the runtime can access
      // the hidden fields of the well known class loaders.
      if (!public_sdk_.empty()) {
        std::string error_msg;
        std::unique_ptr<SdkChecker> sdk_checker(SdkChecker::Create(public_sdk_, &error_msg));
        if (sdk_checker != nullptr) {
          AotClassLinker* aot_class_linker = down_cast<AotClassLinker*>(class_linker);
          aot_class_linker->SetSdkChecker(std::move(sdk_checker));
        } else {
          LOG(FATAL) << "Failed to create SdkChecker with dex files "
              << public_sdk_ << " Error: " << error_msg;
          UNREACHABLE();
        }
      }
    }

    // Register dex caches and key them to the class loader so that they only unload when the
    // class loader unloads.
    for (const auto& dex_file : dex_files) {
      ScopedObjectAccess soa(Thread::Current());
      // Registering the dex cache adds a strong root in the class loader that prevents the dex
      // cache from being unloaded early.
      ObjPtr<mirror::DexCache> dex_cache = class_linker->RegisterDexFile(
          *dex_file,
          soa.Decode<mirror::ClassLoader>(class_loader));
      if (dex_cache == nullptr) {
        soa.Self()->AssertPendingException();
        LOG(FATAL) << "Failed to register dex file " << dex_file->GetLocation() << " "
                   << soa.Self()->GetException()->Dump();
      }
    }
    driver_->InitializeThreadPools();
    driver_->PreCompile(class_loader,
                        dex_files,
                        timings_,
                        &compiler_options_->image_classes_);
    callbacks_->SetVerificationResults(nullptr);  // Should not be needed anymore.
    driver_->CompileAll(class_loader, dex_files, timings_);
    driver_->FreeThreadPools();
    return class_loader;
  }

  // Notes on the interleaving of creating the images and oat files to
  // ensure the references between the two are correct.
  //
  // Currently we have a memory layout that looks something like this:
  //
  // +--------------+
  // | images       |
  // +--------------+
  // | oat files    |
  // +--------------+
  // | alloc spaces |
  // +--------------+
  //
  // There are several constraints on the loading of the images and oat files.
  //
  // 1. The images are expected to be loaded at an absolute address and
  // contain Objects with absolute pointers within the images.
  //
  // 2. There are absolute pointers from Methods in the images to their
  // code in the oat files.
  //
  // 3. There are absolute pointers from the code in the oat files to Methods
  // in the images.
  //
  // 4. There are absolute pointers from code in the oat files to other code
  // in the oat files.
  //
  // To get this all correct, we go through several steps.
  //
  // 1. We prepare offsets for all data in the oat files and calculate
  // the oat data size and code size. During this stage, we also set
  // oat code offsets in methods for use by the image writer.
  //
  // 2. We prepare offsets for the objects in the images and calculate
  // the image sizes.
  //
  // 3. We create the oat files. Originally this was just our own proprietary
  // file but now it is contained within an ELF dynamic object (aka an .so
  // file). Since we know the image sizes and oat data sizes and code sizes we
  // can prepare the ELF headers and we then know the ELF memory segment
  // layout and we can now resolve all references. The compiler provides
  // LinkerPatch information in each CompiledMethod and we resolve these,
  // using the layout information and image object locations provided by
  // image writer, as we're writing the method code.
  //
  // 4. We create the image files. They need to know where the oat files
  // will be loaded after itself. Originally oat files were simply
  // memory mapped so we could predict where their contents were based
  // on the file size. Now that they are ELF files, we need to inspect
  // the ELF files to understand the in memory segment layout including
  // where the oat header is located within.
  // TODO: We could just remember this information from step 3.
  //
  // 5. We fixup the ELF program headers so that dlopen will try to
  // load the .so at the desired location at runtime by offsetting the
  // Elf32_Phdr.p_vaddr values by the desired base address.
  // TODO: Do this in step 3. We already know the layout there.
  //
  // Steps 1.-3. are done by the CreateOatFile() above, steps 4.-5.
  // are done by the CreateImageFile() below.

  // Write out the generated code part. Calls the OatWriter and ElfBuilder. Also prepares the
  // ImageWriter, if necessary.
  // Note: Flushing (and closing) the file is the caller's responsibility, except for the failure
  //       case (when the file will be explicitly erased).
  bool WriteOutputFiles(jobject class_loader) {
    TimingLogger::ScopedTiming t("dex2oat Oat", timings_);

    // Sync the data to the file, in case we did dex2dex transformations.
    for (MemMap& map : opened_dex_files_maps_) {
      if (!map.Sync()) {
        PLOG(ERROR) << "Failed to Sync() dex2dex output. Map: " << map.GetName();
        return false;
      }
    }

    if (IsImage()) {
      if (!IsBootImage()) {
        DCHECK_EQ(image_base_, 0u);
        gc::Heap* const heap = Runtime::Current()->GetHeap();
        image_base_ = heap->GetBootImagesStartAddress() + heap->GetBootImagesSize();
      }
      VLOG(compiler) << "Image base=" << reinterpret_cast<void*>(image_base_);

      image_writer_.reset(new linker::ImageWriter(*compiler_options_,
                                                  image_base_,
                                                  image_storage_mode_,
                                                  oat_filenames_,
                                                  dex_file_oat_index_map_,
                                                  class_loader,
                                                  dirty_image_objects_.get()));

      // We need to prepare method offsets in the image address space for resolving linker patches.
      TimingLogger::ScopedTiming t2("dex2oat Prepare image address space", timings_);
      if (!image_writer_->PrepareImageAddressSpace(timings_)) {
        LOG(ERROR) << "Failed to prepare image address space.";
        return false;
      }
    }

    // Initialize the writers with the compiler driver, image writer, and their
    // dex files. The writers were created without those being there yet.
    for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
      std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];
      std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i];
      oat_writer->Initialize(driver_.get(), image_writer_.get(), dex_files);
    }

    if (!use_existing_vdex_) {
      TimingLogger::ScopedTiming t2("dex2oat Write VDEX", timings_);
      DCHECK(IsBootImage() || IsBootImageExtension() || oat_files_.size() == 1u);
      verifier::VerifierDeps* verifier_deps = callbacks_->GetVerifierDeps();
      for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
        File* vdex_file = vdex_files_[i].get();
        if (!oat_writers_[i]->FinishVdexFile(vdex_file, verifier_deps)) {
          LOG(ERROR) << "Failed to finish VDEX file " << vdex_file->GetPath();
          return false;
        }
      }
    }

    {
      TimingLogger::ScopedTiming t2("dex2oat Write ELF", timings_);
      linker::MultiOatRelativePatcher patcher(compiler_options_->GetInstructionSet(),
                                              compiler_options_->GetInstructionSetFeatures(),
                                              driver_->GetCompiledMethodStorage());
      for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
        std::unique_ptr<linker::ElfWriter>& elf_writer = elf_writers_[i];
        std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];

        oat_writer->PrepareLayout(&patcher);
        elf_writer->PrepareDynamicSection(oat_writer->GetOatHeader().GetExecutableOffset(),
                                          oat_writer->GetCodeSize(),
                                          oat_writer->GetDataBimgRelRoSize(),
                                          oat_writer->GetBssSize(),
                                          oat_writer->GetBssMethodsOffset(),
                                          oat_writer->GetBssRootsOffset(),
                                          oat_writer->GetVdexSize());
        if (IsImage()) {
          // Update oat layout.
          DCHECK(image_writer_ != nullptr);
          DCHECK_LT(i, oat_filenames_.size());
          image_writer_->UpdateOatFileLayout(i,
                                             elf_writer->GetLoadedSize(),
                                             oat_writer->GetOatDataOffset(),
                                             oat_writer->GetOatSize());
        }
      }

      for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
        std::unique_ptr<File>& oat_file = oat_files_[i];
        std::unique_ptr<linker::ElfWriter>& elf_writer = elf_writers_[i];
        std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];

        // We need to mirror the layout of the ELF file in the compressed debug-info.
        // Therefore PrepareDebugInfo() relies on the SetLoadedSectionSizes() call further above.
        debug::DebugInfo debug_info = oat_writer->GetDebugInfo();  // Keep the variable alive.
        elf_writer->PrepareDebugInfo(debug_info);  // Processes the data on background thread.

        OutputStream* rodata = rodata_[i];
        DCHECK(rodata != nullptr);
        if (!oat_writer->WriteRodata(rodata)) {
          LOG(ERROR) << "Failed to write .rodata section to the ELF file " << oat_file->GetPath();
          return false;
        }
        elf_writer->EndRoData(rodata);
        rodata = nullptr;

        OutputStream* text = elf_writer->StartText();
        if (!oat_writer->WriteCode(text)) {
          LOG(ERROR) << "Failed to write .text section to the ELF file " << oat_file->GetPath();
          return false;
        }
        elf_writer->EndText(text);

        if (oat_writer->GetDataBimgRelRoSize() != 0u) {
          OutputStream* data_bimg_rel_ro = elf_writer->StartDataBimgRelRo();
          if (!oat_writer->WriteDataBimgRelRo(data_bimg_rel_ro)) {
            LOG(ERROR) << "Failed to write .data.bimg.rel.ro section to the ELF file "
                << oat_file->GetPath();
            return false;
          }
          elf_writer->EndDataBimgRelRo(data_bimg_rel_ro);
        }

        if (!oat_writer->WriteHeader(elf_writer->GetStream())) {
          LOG(ERROR) << "Failed to write oat header to the ELF file " << oat_file->GetPath();
          return false;
        }

        if (IsImage()) {
          // Update oat header information.
          DCHECK(image_writer_ != nullptr);
          DCHECK_LT(i, oat_filenames_.size());
          image_writer_->UpdateOatFileHeader(i, oat_writer->GetOatHeader());
        }

        elf_writer->WriteDynamicSection();
        elf_writer->WriteDebugInfo(oat_writer->GetDebugInfo());

        if (!elf_writer->End()) {
          LOG(ERROR) << "Failed to write ELF file " << oat_file->GetPath();
          return false;
        }

        if (!FlushOutputFile(&vdex_files_[i]) || !FlushOutputFile(&oat_files_[i])) {
          return false;
        }

        VLOG(compiler) << "Oat file written successfully: " << oat_filenames_[i];

        oat_writer.reset();
        // We may still need the ELF writer later for stripping.
      }
    }

    return true;
  }

  // If we are compiling an image, invoke the image creation routine. Else just skip.
  bool HandleImage() {
    if (IsImage()) {
      TimingLogger::ScopedTiming t("dex2oat ImageWriter", timings_);
      if (!CreateImageFile()) {
        return false;
      }
      VLOG(compiler) << "Images written successfully";
    }
    return true;
  }

  // Copy the full oat files to symbols directory and then strip the originals.
  bool CopyOatFilesToSymbolsDirectoryAndStrip() {
    for (size_t i = 0; i < oat_unstripped_.size(); ++i) {
      // If we don't want to strip in place, copy from stripped location to unstripped location.
      // We need to strip after image creation because FixupElf needs to use .strtab.
      if (oat_unstripped_[i] != oat_filenames_[i]) {
        DCHECK(oat_files_[i].get() != nullptr && oat_files_[i]->IsOpened());

        TimingLogger::ScopedTiming t("dex2oat OatFile copy", timings_);
        std::unique_ptr<File>& in = oat_files_[i];
        int64_t in_length = in->GetLength();
        if (in_length < 0) {
          PLOG(ERROR) << "Failed to get the length of oat file: " << in->GetPath();
          return false;
        }
        std::unique_ptr<File> out(OS::CreateEmptyFile(oat_unstripped_[i].c_str()));
        if (out == nullptr) {
          PLOG(ERROR) << "Failed to open oat file for writing: " << oat_unstripped_[i];
          return false;
        }
        if (!out->Copy(in.get(), 0, in_length)) {
          PLOG(ERROR) << "Failed to copy oat file to file: " << out->GetPath();
          return false;
        }
        if (out->FlushCloseOrErase() != 0) {
          PLOG(ERROR) << "Failed to flush and close copied oat file: " << oat_unstripped_[i];
          return false;
        }
        VLOG(compiler) << "Oat file copied successfully (unstripped): " << oat_unstripped_[i];

        if (strip_) {
          TimingLogger::ScopedTiming t2("dex2oat OatFile strip", timings_);
          if (!elf_writers_[i]->StripDebugInfo()) {
            PLOG(ERROR) << "Failed strip oat file: " << in->GetPath();
            return false;
          }
        }
      }
    }
    return true;
  }

  bool FlushOutputFile(std::unique_ptr<File>* file) {
    if ((file->get() != nullptr) && !file->get()->ReadOnlyMode()) {
      if (file->get()->Flush() != 0) {
        PLOG(ERROR) << "Failed to flush output file: " << file->get()->GetPath();
        return false;
      }
    }
    return true;
  }

  bool FlushCloseOutputFile(File* file) {
    if ((file != nullptr) && !file->ReadOnlyMode()) {
      if (file->FlushCloseOrErase() != 0) {
        PLOG(ERROR) << "Failed to flush and close output file: " << file->GetPath();
        return false;
      }
    }
    return true;
  }

  bool FlushOutputFiles() {
    TimingLogger::ScopedTiming t2("dex2oat Flush Output Files", timings_);
    for (auto& files : { &vdex_files_, &oat_files_ }) {
      for (size_t i = 0; i < files->size(); ++i) {
        if (!FlushOutputFile(&(*files)[i])) {
          return false;
        }
      }
    }
    return true;
  }

  bool FlushCloseOutputFiles() {
    bool result = true;
    for (auto& files : { &vdex_files_, &oat_files_ }) {
      for (size_t i = 0; i < files->size(); ++i) {
        result &= FlushCloseOutputFile((*files)[i].get());
      }
    }
    return result;
  }

  void DumpTiming() {
    if (compiler_options_->GetDumpTimings() ||
        (kIsDebugBuild && timings_->GetTotalNs() > MsToNs(1000))) {
      LOG(INFO) << Dumpable<TimingLogger>(*timings_);
    }
  }

  bool IsImage() const {
    return IsAppImage() || IsBootImage() || IsBootImageExtension();
  }

  bool IsAppImage() const {
    return compiler_options_->IsAppImage();
  }

  bool IsBootImage() const {
    return compiler_options_->IsBootImage();
  }

  bool IsBootImageExtension() const {
    return compiler_options_->IsBootImageExtension();
  }

  bool IsHost() const {
    return is_host_;
  }

  bool HasProfileInput() const { return !profile_file_fds_.empty() || !profile_files_.empty(); }

  // Must be called after the profile is loaded.
  bool DoProfileGuidedOptimizations() const {
    DCHECK(!HasProfileInput() || profile_load_attempted_)
        << "The profile has to be loaded before we can decided "
        << "if we do profile guided optimizations";
    return profile_compilation_info_ != nullptr && !profile_compilation_info_->IsEmpty();
  }

  bool DoGenerateCompactDex() const {
    return compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone;
  }

  bool DoDexLayoutOptimizations() const {
    // Only run dexlayout when being asked to generate compact dex. We do this
    // to avoid having multiple arguments being passed to dex2oat and the main
    // user of dex2oat (installd) will have the same reasons for
    // disabling/enabling compact dex and dex layout.
    return DoGenerateCompactDex();
  }

  bool DoOatLayoutOptimizations() const {
    return DoProfileGuidedOptimizations();
  }

  bool LoadProfile() {
    DCHECK(HasProfileInput());
    profile_load_attempted_ = true;
    // TODO(calin): We should be using the runtime arena pool (instead of the
    // default profile arena). However the setup logic is messy and needs
    // cleaning up before that (e.g. the oat writers are created before the
    // runtime).
    bool for_boot_image = IsBootImage() || IsBootImageExtension();
    profile_compilation_info_.reset(new ProfileCompilationInfo(for_boot_image));

    // Cleanup profile compilation info if we encounter any error when reading profiles.
    auto cleanup = android::base::ScopeGuard([&]() { profile_compilation_info_.reset(nullptr); });

    // Dex2oat only uses the reference profile and that is not updated concurrently by the app or
    // other processes. So we don't need to lock (as we have to do in profman or when writing the
    // profile info).
    std::vector<std::unique_ptr<File>> profile_files;
    if (!profile_file_fds_.empty()) {
      for (int fd : profile_file_fds_) {
        profile_files.push_back(std::make_unique<File>(DupCloexec(fd),
                                                       "profile",
                                                       /*check_usage=*/ false,
                                                       /*read_only_mode=*/ true));
      }
    } else {
      for (const std::string& file : profile_files_) {
        profile_files.emplace_back(OS::OpenFileForReading(file.c_str()));
        if (profile_files.back().get() == nullptr) {
          PLOG(ERROR) << "Cannot open profiles";
          return false;
        }
      }
    }

    std::map<std::string, uint32_t> old_profile_keys, new_profile_keys;
    auto filter_fn = [&](const std::string& profile_key, uint32_t checksum) {
      auto it = old_profile_keys.find(profile_key);
      if (it != old_profile_keys.end() && it->second != checksum) {
        // Filter out this entry. We have already loaded data for the same profile key with a
        // different checksum from an earlier profile file.
        return false;
      }
      // Insert the new profile key and checksum.
      // Note: If the profile contains the same key with different checksums, this insertion fails
      // but we still return `true` and let the `ProfileCompilationInfo::Load()` report an error.
      new_profile_keys.insert(std::make_pair(profile_key, checksum));
      return true;
    };
    for (const std::unique_ptr<File>& profile_file : profile_files) {
      if (!profile_compilation_info_->Load(profile_file->Fd(),
                                           /*merge_classes=*/ true,
                                           filter_fn)) {
        return false;
      }
      old_profile_keys.merge(new_profile_keys);
      new_profile_keys.clear();
    }

    cleanup.Disable();
    return true;
  }

  // If we're asked to speed-profile the app but we have no profile, or the profile
  // is empty, change the filter to verify, and the image_type to none.
  // A speed-profile compilation without profile data is equivalent to verify and
  // this change will increase the precision of the telemetry data.
  void UpdateCompilerOptionsBasedOnProfile() {
    if (!DoProfileGuidedOptimizations() &&
        compiler_options_->GetCompilerFilter() == CompilerFilter::kSpeedProfile) {
      VLOG(compiler) << "Changing compiler filter to verify from speed-profile "
          << "because of empty or non existing profile";

      compiler_options_->SetCompilerFilter(CompilerFilter::kVerify);

      // Note that we could reset the image_type to CompilerOptions::ImageType::kNone
      // to prevent an app image generation.
      // However, if we were pass an image file we would essentially leave the image
      // file empty (possibly triggering some harmless errors when we try to load it).
      //
      // Letting the image_type_ be determined by whether or not we passed an image
      // file will at least write the appropriate header making it an empty but valid
      // image.
    }
  }

  class ScopedDex2oatReporting {
   public:
    explicit ScopedDex2oatReporting(const Dex2Oat& dex2oat) :
        should_report_(dex2oat.should_report_dex2oat_compilation_) {
      if (should_report_) {
        if (dex2oat.zip_fd_ != -1) {
          zip_dup_fd_.reset(DupCloexecOrError(dex2oat.zip_fd_));
          if (zip_dup_fd_ < 0) {
            return;
          }
        }
        int image_fd = dex2oat.IsAppImage() ? dex2oat.app_image_fd_ : dex2oat.image_fd_;
        if (image_fd != -1) {
          image_dup_fd_.reset(DupCloexecOrError(image_fd));
          if (image_dup_fd_ < 0) {
            return;
          }
        }
        oat_dup_fd_.reset(DupCloexecOrError(dex2oat.oat_fd_));
        if (oat_dup_fd_ < 0) {
          return;
        }
        vdex_dup_fd_.reset(DupCloexecOrError(dex2oat.output_vdex_fd_));
        if (vdex_dup_fd_ < 0) {
          return;
        }
        PaletteNotifyStartDex2oatCompilation(zip_dup_fd_,
                                             image_dup_fd_,
                                             oat_dup_fd_,
                                             vdex_dup_fd_);
      }
      error_reporting_ = false;
    }

    ~ScopedDex2oatReporting() {
      if (!error_reporting_) {
        if (should_report_) {
          PaletteNotifyEndDex2oatCompilation(zip_dup_fd_,
                                             image_dup_fd_,
                                             oat_dup_fd_,
                                             vdex_dup_fd_);
        }
      }
    }

    bool ErrorReporting() const { return error_reporting_; }

   private:
    int DupCloexecOrError(int fd) {
      int dup_fd = DupCloexec(fd);
      if (dup_fd < 0) {
        LOG(ERROR) << "Error dup'ing a file descriptor " << strerror(errno);
        error_reporting_ = true;
      }
      return dup_fd;
    }
    android::base::unique_fd oat_dup_fd_;
    android::base::unique_fd vdex_dup_fd_;
    android::base::unique_fd zip_dup_fd_;
    android::base::unique_fd image_dup_fd_;
    bool error_reporting_ = false;
    bool should_report_;
  };

 private:
  bool UseSwap(bool is_image, const std::vector<const DexFile*>& dex_files) {
    if (is_image) {
      // Don't use swap, we know generation should succeed, and we don't want to slow it down.
      return false;
    }
    if (dex_files.size() < min_dex_files_for_swap_) {
      // If there are less dex files than the threshold, assume it's gonna be fine.
      return false;
    }
    size_t dex_files_size = 0;
    for (const auto* dex_file : dex_files) {
      dex_files_size += dex_file->GetHeader().file_size_;
    }
    return dex_files_size >= min_dex_file_cumulative_size_for_swap_;
  }

  bool IsVeryLarge(const std::vector<const DexFile*>& dex_files) {
    size_t dex_files_size = 0;
    for (const auto* dex_file : dex_files) {
      dex_files_size += dex_file->GetHeader().file_size_;
    }
    return dex_files_size >= very_large_threshold_;
  }

  bool PrepareDirtyObjects() {
    if (dirty_image_objects_fd_ != -1) {
      dirty_image_objects_ = ReadCommentedInputFromFd<HashSet<std::string>>(
          dirty_image_objects_fd_,
          nullptr);
      // Close since we won't need it again.
      close(dirty_image_objects_fd_);
      dirty_image_objects_fd_ = -1;
      if (dirty_image_objects_ == nullptr) {
        LOG(ERROR) << "Failed to create list of dirty objects from fd " << dirty_image_objects_fd_;
        return false;
      }
    } else if (dirty_image_objects_filename_ != nullptr) {
      dirty_image_objects_ = ReadCommentedInputFromFile<HashSet<std::string>>(
          dirty_image_objects_filename_,
          nullptr);
      if (dirty_image_objects_ == nullptr) {
        LOG(ERROR) << "Failed to create list of dirty objects from '"
            << dirty_image_objects_filename_ << "'";
        return false;
      }
    }
    return true;
  }

  bool PreparePreloadedClasses() {
    if (!preloaded_classes_fds_.empty()) {
      for (int fd : preloaded_classes_fds_) {
        if (!ReadCommentedInputFromFd(fd, nullptr, &compiler_options_->preloaded_classes_)) {
          return false;
        }
      }
    } else {
      for (const std::string& file : preloaded_classes_files_) {
        if (!ReadCommentedInputFromFile(
                file.c_str(), nullptr, &compiler_options_->preloaded_classes_)) {
          return false;
        }
      }
    }
    return true;
  }

  void PruneNonExistentDexFiles() {
    DCHECK_EQ(dex_filenames_.size(), dex_locations_.size());
    size_t kept = 0u;
    for (size_t i = 0, size = dex_filenames_.size(); i != size; ++i) {
      // Keep if the file exist, or is passed as FD.
      if (!OS::FileExists(dex_filenames_[i].c_str()) && i >= dex_fds_.size()) {
        LOG(WARNING) << "Skipping non-existent dex file '" << dex_filenames_[i] << "'";
      } else {
        if (kept != i) {
          dex_filenames_[kept] = dex_filenames_[i];
          dex_locations_[kept] = dex_locations_[i];
        }
        ++kept;
      }
    }
    dex_filenames_.resize(kept);
    dex_locations_.resize(kept);
  }

  bool AddDexFileSources() {
    TimingLogger::ScopedTiming t2("AddDexFileSources", timings_);
    if (input_vdex_file_ != nullptr && input_vdex_file_->HasDexSection()) {
      DCHECK_EQ(oat_writers_.size(), 1u);
      const std::string& name = zip_location_.empty() ? dex_locations_[0] : zip_location_;
      DCHECK(!name.empty());
      if (!oat_writers_[0]->AddVdexDexFilesSource(*input_vdex_file_.get(), name.c_str())) {
        return false;
      }
    } else if (zip_fd_ != -1) {
      DCHECK_EQ(oat_writers_.size(), 1u);
      if (!oat_writers_[0]->AddDexFileSource(File(zip_fd_, /* check_usage */ false),
                                             zip_location_.c_str())) {
        return false;
      }
    } else {
      DCHECK_EQ(dex_filenames_.size(), dex_locations_.size());
      DCHECK_GE(oat_writers_.size(), 1u);

      bool use_dex_fds = !dex_fds_.empty();
      if (use_dex_fds) {
        DCHECK_EQ(dex_fds_.size(), dex_filenames_.size());
      }

      bool is_multi_image = oat_writers_.size() > 1u;
      if (is_multi_image) {
        DCHECK_EQ(oat_writers_.size(), dex_filenames_.size());
      }

      for (size_t i = 0; i != dex_filenames_.size(); ++i) {
        int oat_index = is_multi_image ? i : 0;
        auto oat_writer = oat_writers_[oat_index].get();

        if (use_dex_fds) {
          if (!oat_writer->AddDexFileSource(File(dex_fds_[i], /* check_usage */ false),
                                            dex_locations_[i].c_str())) {
            return false;
          }
        } else {
          if (!oat_writer->AddDexFileSource(dex_filenames_[i].c_str(),
                                            dex_locations_[i].c_str())) {
            return false;
          }
        }
      }
    }
    return true;
  }

  void CreateOatWriters() {
    TimingLogger::ScopedTiming t2("CreateOatWriters", timings_);
    elf_writers_.reserve(oat_files_.size());
    oat_writers_.reserve(oat_files_.size());
    for (const std::unique_ptr<File>& oat_file : oat_files_) {
      elf_writers_.emplace_back(linker::CreateElfWriterQuick(*compiler_options_, oat_file.get()));
      elf_writers_.back()->Start();
      bool do_oat_writer_layout = DoDexLayoutOptimizations() || DoOatLayoutOptimizations();
      oat_writers_.emplace_back(new linker::OatWriter(
          *compiler_options_,
          verification_results_.get(),
          timings_,
          do_oat_writer_layout ? profile_compilation_info_.get() : nullptr,
          compact_dex_level_));
    }
  }

  void SaveDexInput() {
    const std::vector<const DexFile*>& dex_files = compiler_options_->dex_files_for_oat_file_;
    for (size_t i = 0, size = dex_files.size(); i != size; ++i) {
      const DexFile* dex_file = dex_files[i];
      std::string tmp_file_name(StringPrintf("/data/local/tmp/dex2oat.%d.%zd.dex",
                                             getpid(), i));
      std::unique_ptr<File> tmp_file(OS::CreateEmptyFile(tmp_file_name.c_str()));
      if (tmp_file.get() == nullptr) {
        PLOG(ERROR) << "Failed to open file " << tmp_file_name
            << ". Try: adb shell chmod 777 /data/local/tmp";
        continue;
      }
      // This is just dumping files for debugging. Ignore errors, and leave remnants.
      UNUSED(tmp_file->WriteFully(dex_file->Begin(), dex_file->Size()));
      UNUSED(tmp_file->Flush());
      UNUSED(tmp_file->Close());
      LOG(INFO) << "Wrote input to " << tmp_file_name;
    }
  }

  bool PrepareRuntimeOptions(RuntimeArgumentMap* runtime_options,
                             QuickCompilerCallbacks* callbacks) {
    RuntimeOptions raw_options;
    if (IsBootImage()) {
      std::string boot_class_path = "-Xbootclasspath:";
      boot_class_path += android::base::Join(dex_filenames_, ':');
      raw_options.push_back(std::make_pair(boot_class_path, nullptr));
      std::string boot_class_path_locations = "-Xbootclasspath-locations:";
      boot_class_path_locations += android::base::Join(dex_locations_, ':');
      raw_options.push_back(std::make_pair(boot_class_path_locations, nullptr));
    } else {
      std::string boot_image_option = "-Ximage:";
      boot_image_option += boot_image_filename_;
      raw_options.push_back(std::make_pair(boot_image_option, nullptr));
    }
    for (size_t i = 0; i < runtime_args_.size(); i++) {
      raw_options.push_back(std::make_pair(runtime_args_[i], nullptr));
    }

    raw_options.push_back(std::make_pair("compilercallbacks", callbacks));
    raw_options.push_back(
        std::make_pair("imageinstructionset",
                       GetInstructionSetString(compiler_options_->GetInstructionSet())));

    // Never allow implicit image compilation.
    raw_options.push_back(std::make_pair("-Xnoimage-dex2oat", nullptr));
    // Disable libsigchain. We don't don't need it during compilation and it prevents us
    // from getting a statically linked version of dex2oat (because of dlsym and RTLD_NEXT).
    raw_options.push_back(std::make_pair("-Xno-sig-chain", nullptr));
    // Disable Hspace compaction to save heap size virtual space.
    // Only need disable Hspace for OOM becasue background collector is equal to
    // foreground collector by default for dex2oat.
    raw_options.push_back(std::make_pair("-XX:DisableHSpaceCompactForOOM", nullptr));

    if (!Runtime::ParseOptions(raw_options, false, runtime_options)) {
      LOG(ERROR) << "Failed to parse runtime options";
      return false;
    }
    return true;
  }

  // Create a runtime necessary for compilation.
  bool CreateRuntime(RuntimeArgumentMap&& runtime_options) {
    // To make identity hashcode deterministic, set a seed based on the dex file checksums.
    // That makes the seed also most likely different for different inputs, for example
    // for primary boot image and different extensions that could be loaded together.
    mirror::Object::SetHashCodeSeed(987654321u ^ GetCombinedChecksums());

    TimingLogger::ScopedTiming t_runtime("Create runtime", timings_);
    if (!Runtime::Create(std::move(runtime_options))) {
      LOG(ERROR) << "Failed to create runtime";
      return false;
    }

    // Runtime::Init will rename this thread to be "main". Prefer "dex2oat" so that "top" and
    // "ps -a" don't change to non-descript "main."
    SetThreadName(kIsDebugBuild ? "dex2oatd" : "dex2oat");

    runtime_.reset(Runtime::Current());
    runtime_->SetInstructionSet(compiler_options_->GetInstructionSet());
    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);
      }
    }

    // Initialize maps for unstarted runtime. This needs to be here, as running clinits needs this
    // set up.
    interpreter::UnstartedRuntime::Initialize();

    Thread* self = Thread::Current();
    runtime_->GetClassLinker()->RunEarlyRootClinits(self);
    WellKnownClasses::Init(self->GetJniEnv());
    runtime_->RunRootClinits(self);

    // Runtime::Create acquired the mutator_lock_ that is normally given away when we
    // Runtime::Start, give it away now so that we don't starve GC.
    self->TransitionFromRunnableToSuspended(ThreadState::kNative);

    // Now that we are in native state, initialize well known classes and
    // intrinsics if we don't have a boot image.
    if (IsBootImage() || runtime_->GetHeap()->GetBootImageSpaces().empty()) {
      InitializeIntrinsics();
    }

    WatchDog::SetRuntime(runtime_.get());

    return true;
  }

  // Let the ImageWriter write the image files. If we do not compile PIC, also fix up the oat files.
  bool CreateImageFile()
      REQUIRES(!Locks::mutator_lock_) {
    CHECK(image_writer_ != nullptr);
    if (IsAppImage()) {
      DCHECK(image_filenames_.empty());
      if (app_image_fd_ != -1) {
        image_filenames_.push_back(StringPrintf("FileDescriptor[%d]", app_image_fd_));
      } else {
        image_filenames_.push_back(app_image_file_name_);
      }
    }
    if (image_fd_ != -1) {
      DCHECK(image_filenames_.empty());
      image_filenames_.push_back(StringPrintf("FileDescriptor[%d]", image_fd_));
    }
    if (!image_writer_->Write(IsAppImage() ? app_image_fd_ : image_fd_,
                              image_filenames_,
                              IsAppImage() ? 1u : dex_locations_.size())) {
      LOG(ERROR) << "Failure during image file creation";
      return false;
    }

    // We need the OatDataBegin entries.
    dchecked_vector<uintptr_t> oat_data_begins;
    for (size_t i = 0, size = oat_filenames_.size(); i != size; ++i) {
      oat_data_begins.push_back(image_writer_->GetOatDataBegin(i));
    }
    // Destroy ImageWriter.
    image_writer_.reset();

    return true;
  }

  template <typename T>
  static bool ReadCommentedInputFromFile(
      const char* input_filename, std::function<std::string(const char*)>* process, T* output) {
    auto input_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(input_filename, "r"), fclose};
    if (!input_file) {
      LOG(ERROR) << "Failed to open input file " << input_filename;
      return false;
    }
    ReadCommentedInputStream<T>(input_file.get(), process, output);
    return true;
  }

  template <typename T>
  static bool ReadCommentedInputFromFd(
      int input_fd, std::function<std::string(const char*)>* process, T* output) {
    auto input_file = std::unique_ptr<FILE, decltype(&fclose)>{fdopen(input_fd, "r"), fclose};
    if (!input_file) {
      LOG(ERROR) << "Failed to re-open input fd from /prof/self/fd/" << input_fd;
      return false;
    }
    ReadCommentedInputStream<T>(input_file.get(), process, output);
    return true;
  }

  // Read lines from the given file, dropping comments and empty lines. Post-process each line with
  // the given function.
  template <typename T>
  static std::unique_ptr<T> ReadCommentedInputFromFile(
      const char* input_filename, std::function<std::string(const char*)>* process) {
    std::unique_ptr<T> output(new T());
    ReadCommentedInputFromFile(input_filename, process, output.get());
    return output;
  }

  // Read lines from the given fd, dropping comments and empty lines. Post-process each line with
  // the given function.
  template <typename T>
  static std::unique_ptr<T> ReadCommentedInputFromFd(
      int input_fd, std::function<std::string(const char*)>* process) {
    std::unique_ptr<T> output(new T());
    ReadCommentedInputFromFd(input_fd, process, output.get());
    return output;
  }

  // Read lines from the given stream, dropping comments and empty lines. Post-process each line
  // with the given function.
  template <typename T> static void ReadCommentedInputStream(
      std::FILE* in_stream,
      std::function<std::string(const char*)>* process,
      T* output) {
    char* line = nullptr;
    size_t line_alloc = 0;
    ssize_t len = 0;
    while ((len = getline(&line, &line_alloc, in_stream)) > 0) {
      if (line[0] == '\0' || line[0] == '#' || line[0] == '\n') {
        continue;
      }
      if (line[len - 1] == '\n') {
        line[len - 1] = '\0';
      }
      if (process != nullptr) {
        std::string descriptor((*process)(line));
        output->insert(output->end(), descriptor);
      } else {
        output->insert(output->end(), line);
      }
    }
    free(line);
  }

  void LogCompletionTime() {
    // Note: when creation of a runtime fails, e.g., when trying to compile an app but when there
    //       is no image, there won't be a Runtime::Current().
    // Note: driver creation can fail when loading an invalid dex file.
    LOG(INFO) << "dex2oat took "
              << PrettyDuration(NanoTime() - start_ns_)
              << " (" << PrettyDuration(ProcessCpuNanoTime() - start_cputime_ns_) << " cpu)"
              << " (threads: " << thread_count_ << ") "
              << ((Runtime::Current() != nullptr && driver_ != nullptr) ?
                  driver_->GetMemoryUsageString(kIsDebugBuild || VLOG_IS_ON(compiler)) :
                  "");
  }

  std::string StripIsaFrom(const char* image_filename, InstructionSet isa) {
    std::string res(image_filename);
    size_t last_slash = res.rfind('/');
    if (last_slash == std::string::npos || last_slash == 0) {
      return res;
    }
    size_t penultimate_slash = res.rfind('/', last_slash - 1);
    if (penultimate_slash == std::string::npos) {
      return res;
    }
    // Check that the string in-between is the expected one.
    if (res.substr(penultimate_slash + 1, last_slash - penultimate_slash - 1) !=
            GetInstructionSetString(isa)) {
      LOG(WARNING) << "Unexpected string when trying to strip isa: " << res;
      return res;
    }
    return res.substr(0, penultimate_slash) + res.substr(last_slash);
  }

  std::unique_ptr<CompilerOptions> compiler_options_;
  Compiler::Kind compiler_kind_;

  std::unique_ptr<OatKeyValueStore> key_value_store_;

  std::unique_ptr<VerificationResults> verification_results_;

  std::unique_ptr<QuickCompilerCallbacks> callbacks_;

  std::unique_ptr<Runtime> runtime_;

  // The spec describing how the class loader should be setup for compilation.
  std::unique_ptr<ClassLoaderContext> class_loader_context_;

  // Optional list of file descriptors corresponding to dex file locations in
  // flattened `class_loader_context_`.
  std::vector<int> class_loader_context_fds_;

  // The class loader context stored in the oat file. May be equal to class_loader_context_.
  std::unique_ptr<ClassLoaderContext> stored_class_loader_context_;

  size_t thread_count_;
  std::vector<int32_t> cpu_set_;
  uint64_t start_ns_;
  uint64_t start_cputime_ns_;
  std::unique_ptr<WatchDog> watchdog_;
  std::vector<std::unique_ptr<File>> oat_files_;
  std::vector<std::unique_ptr<File>> vdex_files_;
  std::string oat_location_;
  std::vector<std::string> oat_filenames_;
  std::vector<std::string> oat_unstripped_;
  bool strip_;
  int oat_fd_;
  int input_vdex_fd_;
  int output_vdex_fd_;
  std::string input_vdex_;
  std::string output_vdex_;
  std::unique_ptr<VdexFile> input_vdex_file_;
  int dm_fd_;
  std::string dm_file_location_;
  std::unique_ptr<ZipArchive> dm_file_;
  std::vector<std::string> dex_filenames_;
  std::vector<std::string> dex_locations_;
  std::vector<int> dex_fds_;
  int zip_fd_;
  std::string zip_location_;
  std::string boot_image_filename_;
  std::vector<const char*> runtime_args_;
  std::vector<std::string> image_filenames_;
  int image_fd_;
  bool have_multi_image_arg_;
  uintptr_t image_base_;
  ImageHeader::StorageMode image_storage_mode_;
  const char* passes_to_run_filename_;
  const char* dirty_image_objects_filename_;
  int dirty_image_objects_fd_;
  std::unique_ptr<HashSet<std::string>> dirty_image_objects_;
  std::unique_ptr<std::vector<std::string>> passes_to_run_;
  bool is_host_;
  std::string android_root_;
  std::string no_inline_from_string_;
  bool force_allow_oj_inlines_ = false;
  CompactDexLevel compact_dex_level_ = kDefaultCompactDexLevel;

  std::vector<std::unique_ptr<linker::ElfWriter>> elf_writers_;
  std::vector<std::unique_ptr<linker::OatWriter>> oat_writers_;
  std::vector<OutputStream*> rodata_;
  std::vector<std::unique_ptr<OutputStream>> vdex_out_;
  std::unique_ptr<linker::ImageWriter> image_writer_;
  std::unique_ptr<CompilerDriver> driver_;

  std::vector<MemMap> opened_dex_files_maps_;
  std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;

  bool avoid_storing_invocation_;
  android::base::unique_fd invocation_file_;
  std::string swap_file_name_;
  int swap_fd_;
  size_t min_dex_files_for_swap_ = kDefaultMinDexFilesForSwap;
  size_t min_dex_file_cumulative_size_for_swap_ = kDefaultMinDexFileCumulativeSizeForSwap;
  size_t very_large_threshold_ = std::numeric_limits<size_t>::max();
  std::string app_image_file_name_;
  int app_image_fd_;
  std::vector<std::string> profile_files_;
  std::vector<int> profile_file_fds_;
  std::vector<std::string> preloaded_classes_files_;
  std::vector<int> preloaded_classes_fds_;
  std::unique_ptr<ProfileCompilationInfo> profile_compilation_info_;
  TimingLogger* timings_;
  std::vector<std::vector<const DexFile*>> dex_files_per_oat_file_;
  HashMap<const DexFile*, size_t> dex_file_oat_index_map_;

  // Backing storage.
  std::forward_list<std::string> char_backing_storage_;

  // See CompilerOptions.force_determinism_.
  bool force_determinism_;
  // See CompilerOptions.crash_on_linkage_violation_.
  bool check_linkage_conditions_;
  // See CompilerOptions.crash_on_linkage_violation_.
  bool crash_on_linkage_violation_;

  // Directory of relative classpaths.
  std::string classpath_dir_;

  // Whether the given input vdex is also the output.
  bool use_existing_vdex_ = false;

  // By default, copy the dex to the vdex file only if dex files are
  // compressed in APK.
  linker::CopyOption copy_dex_files_ = linker::CopyOption::kOnlyIfCompressed;

  // The reason for invoking the compiler.
  std::string compilation_reason_;

  // Whether to force individual compilation.
  bool compile_individually_;

  // The classpath that determines if a given symbol should be resolved at compile time or not.
  std::string public_sdk_;

  // The apex versions of jars in the boot classpath. Set through command line
  // argument.
  std::string apex_versions_argument_;

  // Whether or we attempted to load the profile (if given).
  bool profile_load_attempted_;

  // Whether PaletteNotify{Start,End}Dex2oatCompilation should be called.
  bool should_report_dex2oat_compilation_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
};

static void b13564922() {
#if defined(__linux__) && defined(__arm__)
  int major, minor;
  struct utsname uts;
  if (uname(&uts) != -1 &&
      sscanf(uts.release, "%d.%d", &major, &minor) == 2 &&
      ((major < 3) || ((major == 3) && (minor < 4)))) {
    // Kernels before 3.4 don't handle the ASLR well and we can run out of address
    // space (http://b/13564922). Work around the issue by inhibiting further mmap() randomization.
    int old_personality = personality(0xffffffff);
    if ((old_personality & ADDR_NO_RANDOMIZE) == 0) {
      int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
      if (new_personality == -1) {
        LOG(WARNING) << "personality(. | ADDR_NO_RANDOMIZE) failed.";
      }
    }
  }
#endif
}

class ScopedGlobalRef {
 public:
  explicit ScopedGlobalRef(jobject obj) : obj_(obj) {}
  ~ScopedGlobalRef() {
    if (obj_ != nullptr) {
      ScopedObjectAccess soa(Thread::Current());
      soa.Env()->GetVm()->DeleteGlobalRef(soa.Self(), obj_);
    }
  }

 private:
  jobject obj_;
};

static dex2oat::ReturnCode DoCompilation(Dex2Oat& dex2oat) REQUIRES(!Locks::mutator_lock_) {
  Locks::mutator_lock_->AssertNotHeld(Thread::Current());
  dex2oat.LoadClassProfileDescriptors();
  jobject class_loader = dex2oat.Compile();
  // Keep the class loader that was used for compilation live for the rest of the compilation
  // process.
  ScopedGlobalRef global_ref(class_loader);

  if (!dex2oat.WriteOutputFiles(class_loader)) {
    dex2oat.EraseOutputFiles();
    return dex2oat::ReturnCode::kOther;
  }

  // Flush output files.  Keep them open as we might still modify them later (strip them).
  if (!dex2oat.FlushOutputFiles()) {
    dex2oat.EraseOutputFiles();
    return dex2oat::ReturnCode::kOther;
  }

  // Creates the boot.art and patches the oat files.
  if (!dex2oat.HandleImage()) {
    return dex2oat::ReturnCode::kOther;
  }

  // When given --host, finish early without stripping.
  if (dex2oat.IsHost()) {
    if (!dex2oat.FlushCloseOutputFiles()) {
      return dex2oat::ReturnCode::kOther;
    }
    dex2oat.DumpTiming();
    return dex2oat::ReturnCode::kNoFailure;
  }

  // Copy stripped to unstripped location, if necessary. This will implicitly flush & close the
  // stripped versions. If this is given, we expect to be able to open writable files by name.
  if (!dex2oat.CopyOatFilesToSymbolsDirectoryAndStrip()) {
    return dex2oat::ReturnCode::kOther;
  }

  // FlushClose again, as stripping might have re-opened the oat files.
  if (!dex2oat.FlushCloseOutputFiles()) {
    return dex2oat::ReturnCode::kOther;
  }

  dex2oat.DumpTiming();
  return dex2oat::ReturnCode::kNoFailure;
}

static dex2oat::ReturnCode Dex2oat(int argc, char** argv) {
  b13564922();

  TimingLogger timings("compiler", false, false);

  // Allocate `dex2oat` on the heap instead of on the stack, as Clang
  // might produce a stack frame too large for this function or for
  // functions inlining it (such as main), that would not fit the
  // requirements of the `-Wframe-larger-than` option.
  std::unique_ptr<Dex2Oat> dex2oat = std::make_unique<Dex2Oat>(&timings);

  // Parse arguments. Argument mistakes will lead to exit(EXIT_FAILURE) in UsageError.
  dex2oat->ParseArgs(argc, argv);

  art::MemMap::Init();  // For ZipEntry::ExtractToMemMap, vdex and profiles.

  // If needed, process profile information for profile guided compilation.
  // This operation involves I/O.
  if (dex2oat->HasProfileInput()) {
    if (!dex2oat->LoadProfile()) {
      LOG(ERROR) << "Failed to process profile file";
      return dex2oat::ReturnCode::kOther;
    }
  }

  // Check if we need to update any of the compiler options (such as the filter)
  // and do it before anything else (so that the other operations have a true
  // view of the state).
  dex2oat->UpdateCompilerOptionsBasedOnProfile();

  // Insert the compiler options in the key value store.
  // We have to do this after we altered any incoming arguments
  // (such as the compiler filter).
  dex2oat->InsertCompileOptions(argc, argv);

  // Check early that the result of compilation can be written
  if (!dex2oat->OpenFile()) {
    // Flush close so that the File Guard checks don't fail the assertions.
    dex2oat->FlushCloseOutputFiles();
    return dex2oat::ReturnCode::kOther;
  }

  // Print the complete line when any of the following is true:
  //   1) Debug build
  //   2) Compiling an image
  //   3) Compiling with --host
  //   4) Compiling on the host (not a target build)
  // Otherwise, print a stripped command line.
  if (kIsDebugBuild ||
      dex2oat->IsBootImage() || dex2oat->IsBootImageExtension() ||
      dex2oat->IsHost() ||
      !kIsTargetBuild) {
    LOG(INFO) << CommandLine();
  } else {
    LOG(INFO) << StrippedCommandLine();
  }

  Dex2Oat::ScopedDex2oatReporting sdr(*dex2oat.get());

  if (sdr.ErrorReporting()) {
    dex2oat->EraseOutputFiles();
    return dex2oat::ReturnCode::kOther;
  }

  dex2oat::ReturnCode setup_code = dex2oat->Setup();
  if (setup_code != dex2oat::ReturnCode::kNoFailure) {
    dex2oat->EraseOutputFiles();
    return setup_code;
  }

  // TODO: Due to the cyclic dependencies, profile loading and verifying are
  // being done separately. Refactor and place the two next to each other.
  // If verification fails, we don't abort the compilation and instead log an
  // error.
  // TODO(b/62602192, b/65260586): We should consider aborting compilation when
  // the profile verification fails.
  // Note: If dex2oat fails, installd will remove the oat files causing the app
  // to fallback to apk with possible in-memory extraction. We want to avoid
  // that, and thus we're lenient towards profile corruptions.
  if (dex2oat->DoProfileGuidedOptimizations()) {
    dex2oat->VerifyProfileData();
  }

  // Helps debugging on device. Can be used to determine which dalvikvm instance invoked a dex2oat
  // instance. Used by tools/bisection_search/bisection_search.py.
  VLOG(compiler) << "Running dex2oat (parent PID = " << getppid() << ")";

  dex2oat::ReturnCode result = DoCompilation(*dex2oat);

  return result;
}
}  // namespace art

int main(int argc, char** argv) {
  int result = static_cast<int>(art::Dex2oat(argc, argv));
  // Everything was done, do an explicit exit here to avoid running Runtime destructors that take
  // time (bug 10645725) unless we're a debug or instrumented build or running on a memory tool.
  // Note: The Dex2Oat class should not destruct the runtime in this case.
  if (!art::kIsDebugBuild && !art::kIsPGOInstrumentation && !art::kRunningOnMemoryTool) {
    art::FastExit(result);
  }
  return result;
}
