Revert "Revert "ART: Key-Value Store in Oat header""

This reverts commit 452bee5da9811f62123978e142bd67b385e9ff82.

Heap-allocate a couple of objects in dex2oat to avoid large frame
size.

Includes fixes originally in 100596 and 100605.

Change-Id: Id51a44198c973c91f0a3f87b9d992a5dc110c6f8
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 72c34b4..0d40c8d 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -48,6 +48,7 @@
 #include "gc/space/image_space.h"
 #include "gc/space/space-inl.h"
 #include "image_writer.h"
+#include "implicit_check_options.h"
 #include "leb128.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
@@ -336,7 +337,10 @@
                                       bool dump_passes,
                                       TimingLogger& timings,
                                       CumulativeLogger& compiler_phases_timings,
-                                      std::string profile_file) {
+                                      std::string profile_file,
+                                      SafeMap<std::string, std::string>* key_value_store) {
+    CHECK(key_value_store != nullptr);
+
     // Handle and ClassLoader creation needs to come after Runtime::Create
     jobject class_loader = nullptr;
     Thread* self = Thread::Current();
@@ -356,18 +360,18 @@
     }
 
     std::unique_ptr<CompilerDriver> driver(new CompilerDriver(compiler_options_,
-                                                        verification_results_,
-                                                        method_inliner_map_,
-                                                        compiler_kind_,
-                                                        instruction_set_,
-                                                        instruction_set_features_,
-                                                        image,
-                                                        image_classes.release(),
-                                                        thread_count_,
-                                                        dump_stats,
-                                                        dump_passes,
-                                                        &compiler_phases_timings,
-                                                        profile_file));
+                                                              verification_results_,
+                                                              method_inliner_map_,
+                                                              compiler_kind_,
+                                                              instruction_set_,
+                                                              instruction_set_features_,
+                                                              image,
+                                                              image_classes.release(),
+                                                              thread_count_,
+                                                              dump_stats,
+                                                              dump_passes,
+                                                              &compiler_phases_timings,
+                                                              profile_file));
 
     driver->GetCompiler()->SetBitcodeFileName(*driver.get(), bitcode_filename);
 
@@ -386,11 +390,15 @@
       image_file_location = image_space->GetImageFilename();
     }
 
+    if (!image_file_location.empty()) {
+      key_value_store->Put(OatHeader::kImageLocationKey, image_file_location);
+    }
+
     OatWriter oat_writer(dex_files, image_file_location_oat_checksum,
                          image_file_location_oat_data_begin,
-                         image_file_location,
                          driver.get(),
-                         &timings);
+                         &timings,
+                         key_value_store);
 
     t2.NewTiming("Writing ELF");
     if (!driver->WriteElf(android_root, is_host, dex_files, &oat_writer, oat_file)) {
@@ -1168,31 +1176,32 @@
     Usage("Unknown --compiler-filter value %s", compiler_filter_string);
   }
 
-  CheckExplicitCheckOptions(instruction_set, &explicit_null_checks, &explicit_so_checks,
-                            &explicit_suspend_checks);
+  ImplicitCheckOptions::CheckISASupport(instruction_set, &explicit_null_checks, &explicit_so_checks,
+                                        &explicit_suspend_checks);
 
   if (!explicit_include_patch_information) {
     include_patch_information =
         (compiler_kind == Compiler::kQuick && CompilerOptions::kDefaultIncludePatchInformation);
   }
 
-  CompilerOptions compiler_options(compiler_filter,
-                                   huge_method_threshold,
-                                   large_method_threshold,
-                                   small_method_threshold,
-                                   tiny_method_threshold,
-                                   num_dex_methods_threshold,
-                                   generate_gdb_information,
-                                   include_patch_information,
-                                   top_k_profile_threshold,
-                                   include_debug_symbols,
-                                   explicit_null_checks,
-                                   explicit_so_checks,
-                                   explicit_suspend_checks
+  std::unique_ptr<CompilerOptions> compiler_options(new CompilerOptions(compiler_filter,
+                                                                        huge_method_threshold,
+                                                                        large_method_threshold,
+                                                                        small_method_threshold,
+                                                                        tiny_method_threshold,
+                                                                        num_dex_methods_threshold,
+                                                                        generate_gdb_information,
+                                                                        include_patch_information,
+                                                                        top_k_profile_threshold,
+                                                                        include_debug_symbols,
+                                                                        explicit_null_checks,
+                                                                        explicit_so_checks,
+                                                                        explicit_suspend_checks
 #ifdef ART_SEA_IR_MODE
-                                   , compiler_options.sea_ir_ = true;
+                                                                        , compiler_options.sea_ir_ =
+                                                                              true;
 #endif
-                                   );  // NOLINT(whitespace/parens)
+  ));  // NOLINT(whitespace/parens)
 
   // Done with usage checks, enable watchdog if requested
   WatchDog watch_dog(watch_dog_enabled);
@@ -1237,9 +1246,10 @@
     runtime_options.push_back(std::make_pair(runtime_args[i], nullptr));
   }
 
-  VerificationResults verification_results(&compiler_options);
+  std::unique_ptr<VerificationResults> verification_results(new VerificationResults(
+                                                               compiler_options.get()));
   DexFileToMethodInlinerMap method_inliner_map;
-  CompilerCallbacksImpl callbacks(&verification_results, &method_inliner_map);
+  CompilerCallbacksImpl callbacks(verification_results.get(), &method_inliner_map);
   runtime_options.push_back(std::make_pair("compilercallbacks", &callbacks));
   runtime_options.push_back(
       std::make_pair("imageinstructionset",
@@ -1248,11 +1258,11 @@
   Dex2Oat* p_dex2oat;
   if (!Dex2Oat::Create(&p_dex2oat,
                        runtime_options,
-                       compiler_options,
+                       *compiler_options,
                        compiler_kind,
                        instruction_set,
                        instruction_set_features,
-                       &verification_results,
+                       verification_results.get(),
                        &method_inliner_map,
                        thread_count)) {
     LOG(ERROR) << "Failed to create dex2oat";
@@ -1263,24 +1273,15 @@
   // TODO: Not sure whether it's a good idea to allow anything else but the runtime option in
   // this case at all, as we'll have to throw away produced code for a mismatch.
   if (!has_explicit_checks_options) {
-    bool cross_compiling = true;
-    switch (kRuntimeISA) {
-      case kArm:
-      case kThumb2:
-        cross_compiling = instruction_set != kArm && instruction_set != kThumb2;
-        break;
-      default:
-        cross_compiling = instruction_set != kRuntimeISA;
-        break;
-    }
-    if (!cross_compiling) {
-      Runtime* runtime = Runtime::Current();
-      compiler_options.SetExplicitNullChecks(runtime->ExplicitNullChecks());
-      compiler_options.SetExplicitStackOverflowChecks(runtime->ExplicitStackOverflowChecks());
-      compiler_options.SetExplicitSuspendChecks(runtime->ExplicitSuspendChecks());
+    if (ImplicitCheckOptions::CheckForCompiling(kRuntimeISA, instruction_set, &explicit_null_checks,
+                                                &explicit_so_checks, &explicit_suspend_checks)) {
+      compiler_options->SetExplicitNullChecks(explicit_null_checks);
+      compiler_options->SetExplicitStackOverflowChecks(explicit_so_checks);
+      compiler_options->SetExplicitSuspendChecks(explicit_suspend_checks);
     }
   }
 
+
   // 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.
   Thread* self = Thread::Current();
@@ -1366,32 +1367,58 @@
    * If we're not in interpret-only or verify-none mode, go ahead and compile small applications.
    * Don't bother to check if we're doing the image.
    */
-  if (!image && compiler_options.IsCompilationEnabled()) {
+  if (!image && compiler_options->IsCompilationEnabled()) {
     size_t num_methods = 0;
     for (size_t i = 0; i != dex_files.size(); ++i) {
       const DexFile* dex_file = dex_files[i];
       CHECK(dex_file != nullptr);
       num_methods += dex_file->NumMethodIds();
     }
-    if (num_methods <= compiler_options.GetNumDexMethodsThreshold()) {
-      compiler_options.SetCompilerFilter(CompilerOptions::kSpeed);
+    if (num_methods <= compiler_options->GetNumDexMethodsThreshold()) {
+      compiler_options->SetCompilerFilter(CompilerOptions::kSpeed);
       VLOG(compiler) << "Below method threshold, compiling anyways";
     }
   }
 
+  // Fill some values into the key-value store for the oat header.
+  std::unique_ptr<SafeMap<std::string, std::string> > key_value_store(
+      new SafeMap<std::string, std::string>());
+
+  // Insert implicit check options.
+  key_value_store->Put(ImplicitCheckOptions::kImplicitChecksOatHeaderKey,
+                      ImplicitCheckOptions::Serialize(compiler_options->GetExplicitNullChecks(),
+                                                      compiler_options->
+                                                          GetExplicitStackOverflowChecks(),
+                                                      compiler_options->
+                                                          GetExplicitSuspendChecks()));
+
+  // Insert some compiler things.
+  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());
+  oss.str("");  // Reset.
+  oss << kRuntimeISA;
+  key_value_store->Put(OatHeader::kDex2OatHostKey, oss.str());
+
   std::unique_ptr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
-                                                                  android_root,
-                                                                  is_host,
-                                                                  dex_files,
-                                                                  oat_file.get(),
-                                                                  bitcode_filename,
-                                                                  image,
-                                                                  image_classes,
-                                                                  dump_stats,
-                                                                  dump_passes,
-                                                                  timings,
-                                                                  compiler_phases_timings,
-                                                                  profile_file));
+                                                                        android_root,
+                                                                        is_host,
+                                                                        dex_files,
+                                                                        oat_file.get(),
+                                                                        bitcode_filename,
+                                                                        image,
+                                                                        image_classes,
+                                                                        dump_stats,
+                                                                        dump_passes,
+                                                                        timings,
+                                                                        compiler_phases_timings,
+                                                                        profile_file,
+                                                                        key_value_store.get()));
 
   if (compiler.get() == nullptr) {
     LOG(ERROR) << "Failed to create oat file: " << oat_location;