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/compiler/image_test.cc b/compiler/image_test.cc
index d52ec0a..6b26980 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -25,6 +25,7 @@
 #include "compiler/image_writer.h"
 #include "compiler/oat_writer.h"
 #include "gc/space/image_space.h"
+#include "implicit_check_options.h"
 #include "lock_word.h"
 #include "mirror/object-inl.h"
 #include "signal_catcher.h"
@@ -77,8 +78,11 @@
 
       t.NewTiming("WriteElf");
       ScopedObjectAccess soa(Thread::Current());
-      OatWriter oat_writer(class_linker->GetBootClassPath(),
-                           0, 0, "", compiler_driver_.get(), &timings);
+      SafeMap<std::string, std::string> key_value_store;
+      key_value_store.Put(ImplicitCheckOptions::kImplicitChecksOatHeaderKey,
+                          ImplicitCheckOptions::Serialize(true, true, true));
+      OatWriter oat_writer(class_linker->GetBootClassPath(), 0, 0, compiler_driver_.get(), &timings,
+                           &key_value_store);
       bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(),
                                                 !kIsTargetBuild,
                                                 class_linker->GetBootClassPath(),
@@ -138,6 +142,9 @@
   std::string image("-Ximage:");
   image.append(image_location.GetFilename());
   options.push_back(std::make_pair(image.c_str(), reinterpret_cast<void*>(NULL)));
+  // Turn off implicit checks for this runtime, as we compiled the image with them off.
+  std::string explicit_checks("-implicit-checks:none");
+  options.push_back(std::make_pair(explicit_checks.c_str(), reinterpret_cast<void*>(NULL)));
 
   if (!Runtime::Create(options, false)) {
     LOG(FATAL) << "Failed to create runtime";
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 254faac..d2ee0ed 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -18,6 +18,7 @@
 #include "compiler/compiler.h"
 #include "compiler/oat_writer.h"
 #include "entrypoints/quick/quick_entrypoints.h"
+#include "implicit_check_options.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -111,12 +112,16 @@
 
   ScopedObjectAccess soa(Thread::Current());
   ScratchFile tmp;
+  SafeMap<std::string, std::string> key_value_store;
+  key_value_store.Put(OatHeader::kImageLocationKey, "lue.art");
+  key_value_store.Put(ImplicitCheckOptions::kImplicitChecksOatHeaderKey,
+                      ImplicitCheckOptions::Serialize(true, true, true));
   OatWriter oat_writer(class_linker->GetBootClassPath(),
                        42U,
                        4096U,
-                       "lue.art",
                        compiler_driver_.get(),
-                       &timings);
+                       &timings,
+                       &key_value_store);
   bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(),
                                             !kIsTargetBuild,
                                             class_linker->GetBootClassPath(),
@@ -136,7 +141,7 @@
   ASSERT_EQ(1U, oat_header.GetDexFileCount());  // core
   ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
   ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
-  ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
+  ASSERT_EQ("lue.art", std::string(oat_header.GetStoreValueByKey(OatHeader::kImageLocationKey)));
 
   const DexFile* dex_file = java_lang_dex_file_;
   uint32_t dex_file_checksum = dex_file->GetLocationChecksum();
@@ -189,20 +194,20 @@
     std::vector<const DexFile*> dex_files;
     uint32_t image_file_location_oat_checksum = 0;
     uint32_t image_file_location_oat_begin = 0;
-    const std::string image_file_location;
-    OatHeader oat_header(instruction_set,
-                         instruction_set_features,
-                         &dex_files,
-                         image_file_location_oat_checksum,
-                         image_file_location_oat_begin,
-                         image_file_location);
-    ASSERT_TRUE(oat_header.IsValid());
+    OatHeader* oat_header = OatHeader::Create(instruction_set,
+                                              instruction_set_features,
+                                              &dex_files,
+                                              image_file_location_oat_checksum,
+                                              image_file_location_oat_begin,
+                                              nullptr);
+    ASSERT_NE(oat_header, nullptr);
+    ASSERT_TRUE(oat_header->IsValid());
 
-    char* magic = const_cast<char*>(oat_header.GetMagic());
+    char* magic = const_cast<char*>(oat_header->GetMagic());
     strcpy(magic, "");  // bad magic
-    ASSERT_FALSE(oat_header.IsValid());
+    ASSERT_FALSE(oat_header->IsValid());
     strcpy(magic, "oat\n000");  // bad version
-    ASSERT_FALSE(oat_header.IsValid());
+    ASSERT_FALSE(oat_header->IsValid());
 }
 
 }  // namespace art
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 4b6d501..73f4ba1 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -49,19 +49,19 @@
 OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
                      uint32_t image_file_location_oat_checksum,
                      uintptr_t image_file_location_oat_begin,
-                     const std::string& image_file_location,
                      const CompilerDriver* compiler,
-                     TimingLogger* timings)
+                     TimingLogger* timings,
+                     SafeMap<std::string, std::string>* key_value_store)
   : compiler_driver_(compiler),
     dex_files_(&dex_files),
     image_file_location_oat_checksum_(image_file_location_oat_checksum),
     image_file_location_oat_begin_(image_file_location_oat_begin),
-    image_file_location_(image_file_location),
+    key_value_store_(key_value_store),
     oat_header_(NULL),
     size_dex_file_alignment_(0),
     size_executable_offset_alignment_(0),
     size_oat_header_(0),
-    size_oat_header_image_file_location_(0),
+    size_oat_header_key_value_store_(0),
     size_dex_file_(0),
     size_interpreter_to_interpreter_bridge_(0),
     size_interpreter_to_compiled_code_bridge_(0),
@@ -89,6 +89,8 @@
     size_oat_class_status_(0),
     size_oat_class_method_bitmaps_(0),
     size_oat_class_method_offsets_(0) {
+  CHECK(key_value_store != nullptr);
+
   size_t offset;
   {
     TimingLogger::ScopedTiming split("InitOatHeader", timings);
@@ -121,7 +123,8 @@
   size_ = offset;
 
   CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
-  CHECK(image_file_location.empty() == compiler->IsImage());
+  CHECK_EQ(compiler->IsImage(),
+           key_value_store_->find(OatHeader::kImageLocationKey) == key_value_store_->end());
 }
 
 OatWriter::~OatWriter() {
@@ -716,16 +719,14 @@
 }
 
 size_t OatWriter::InitOatHeader() {
-  // create the OatHeader
-  oat_header_ = new OatHeader(compiler_driver_->GetInstructionSet(),
-                              compiler_driver_->GetInstructionSetFeatures(),
-                              dex_files_,
-                              image_file_location_oat_checksum_,
-                              image_file_location_oat_begin_,
-                              image_file_location_);
-  size_t offset = sizeof(*oat_header_);
-  offset += image_file_location_.size();
-  return offset;
+  oat_header_ = OatHeader::Create(compiler_driver_->GetInstructionSet(),
+                                  compiler_driver_->GetInstructionSetFeatures(),
+                                  dex_files_,
+                                  image_file_location_oat_checksum_,
+                                  image_file_location_oat_begin_,
+                                  key_value_store_);
+
+  return oat_header_->GetHeaderSize();
 }
 
 size_t OatWriter::InitOatDexFiles(size_t offset) {
@@ -864,17 +865,13 @@
 bool OatWriter::Write(OutputStream* out) {
   const size_t file_offset = out->Seek(0, kSeekCurrent);
 
-  if (!out->WriteFully(oat_header_, sizeof(*oat_header_))) {
+  size_t header_size = oat_header_->GetHeaderSize();
+  if (!out->WriteFully(oat_header_, header_size)) {
     PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation();
     return false;
   }
-  size_oat_header_ += sizeof(*oat_header_);
-
-  if (!out->WriteFully(image_file_location_.data(), image_file_location_.size())) {
-    PLOG(ERROR) << "Failed to write oat header image file location to " << out->GetLocation();
-    return false;
-  }
-  size_oat_header_image_file_location_ += image_file_location_.size();
+  size_oat_header_ += sizeof(OatHeader);
+  size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader);
 
   if (!WriteTables(out, file_offset)) {
     LOG(ERROR) << "Failed to write oat tables to " << out->GetLocation();
@@ -909,7 +906,7 @@
     DO_STAT(size_dex_file_alignment_);
     DO_STAT(size_executable_offset_alignment_);
     DO_STAT(size_oat_header_);
-    DO_STAT(size_oat_header_image_file_location_);
+    DO_STAT(size_oat_header_key_value_store_);
     DO_STAT(size_dex_file_);
     DO_STAT(size_interpreter_to_interpreter_bridge_);
     DO_STAT(size_interpreter_to_compiled_code_bridge_);
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index dbecb95..3d34956 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -79,9 +79,9 @@
   OatWriter(const std::vector<const DexFile*>& dex_files,
             uint32_t image_file_location_oat_checksum,
             uintptr_t image_file_location_oat_begin,
-            const std::string& image_file_location,
             const CompilerDriver* compiler,
-            TimingLogger* timings);
+            TimingLogger* timings,
+            SafeMap<std::string, std::string>* key_value_store);
 
   const OatHeader& GetOatHeader() const {
     return *oat_header_;
@@ -253,9 +253,9 @@
   // dependencies on the image.
   uint32_t image_file_location_oat_checksum_;
   uintptr_t image_file_location_oat_begin_;
-  std::string image_file_location_;
 
   // data to write
+  SafeMap<std::string, std::string>* key_value_store_;
   OatHeader* oat_header_;
   std::vector<OatDexFile*> oat_dex_files_;
   std::vector<OatClass*> oat_classes_;
@@ -274,7 +274,7 @@
   uint32_t size_dex_file_alignment_;
   uint32_t size_executable_offset_alignment_;
   uint32_t size_oat_header_;
-  uint32_t size_oat_header_image_file_location_;
+  uint32_t size_oat_header_key_value_store_;
   uint32_t size_dex_file_;
   uint32_t size_interpreter_to_interpreter_bridge_;
   uint32_t size_interpreter_to_compiled_code_bridge_;