Revert "Revert "Store resolved Strings for AOT code in .bss.""

Fixed oat_test to keep dex files alive. Fixed mips build.
Rewritten the .bss GC root visiting and added write barrier
to the artResolveStringFromCode().

Test: build aosp_mips-eng
Test: m ART_DEFAULT_GC_TYPE=SS test-art-target-host-gtest-oat_test
Test: Run ART test suite on host and Nexus 9.
Bug: 20323084
Bug: 30627598

This reverts commit 5f926055cb88089d8ca27243f35a9dfd89d981f0.

Change-Id: I07fa2278d82b8eb64964c9a4b66cb93726ccda6b
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 54ec7c1..44c26ed 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -300,7 +300,10 @@
     vdex_dex_files_offset_(0u),
     vdex_verifier_deps_offset_(0u),
     oat_size_(0u),
+    bss_start_(0u),
     bss_size_(0u),
+    bss_roots_offset_(0u),
+    bss_string_entries_(),
     oat_data_offset_(0u),
     oat_header_(nullptr),
     size_vdex_header_(0),
@@ -554,15 +557,8 @@
   oat_size_ = offset;
 
   if (!HasBootImage()) {
-    // Allocate space for app dex cache arrays in the .bss section.
-    size_t bss_start = RoundUp(oat_size_, kPageSize);
-    PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
-    bss_size_ = 0u;
-    for (const DexFile* dex_file : *dex_files_) {
-      dex_cache_arrays_offsets_.Put(dex_file, bss_start + bss_size_);
-      DexCacheArraysLayout layout(pointer_size, dex_file);
-      bss_size_ += layout.Size();
-    }
+    TimingLogger::ScopedTiming split("InitBssLayout", timings_);
+    InitBssLayout(instruction_set);
   }
 
   CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
@@ -805,6 +801,10 @@
             if (!patch.IsPcRelative()) {
               writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
             }
+            if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
+              StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
+              writer_->bss_string_entries_.Overwrite(ref, /* placeholder */ 0u);
+            }
           }
         }
       }
@@ -1115,6 +1115,15 @@
                                                                      target_offset);
                 break;
               }
+              case LinkerPatch::Type::kStringBssEntry: {
+                StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
+                uint32_t target_offset = writer_->bss_string_entries_.Get(ref);
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
               case LinkerPatch::Type::kTypeRelative: {
                 uint32_t target_offset = GetTargetObjectOffset(GetTargetType(patch));
                 writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
@@ -1500,7 +1509,7 @@
   offset = RoundUp(offset, kPageSize);
   oat_header_->SetExecutableOffset(offset);
   size_executable_offset_alignment_ = offset - old_offset;
-  if (compiler_driver_->IsBootImage()) {
+  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
     InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
 
     #define DO_TRAMPOLINE(field, fn_name) \
@@ -1548,6 +1557,29 @@
   return offset;
 }
 
+void OatWriter::InitBssLayout(InstructionSet instruction_set) {
+  DCHECK(!HasBootImage());
+
+  // Allocate space for app dex cache arrays in the .bss section.
+  bss_start_ = RoundUp(oat_size_, kPageSize);
+  PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
+  bss_size_ = 0u;
+  for (const DexFile* dex_file : *dex_files_) {
+    dex_cache_arrays_offsets_.Put(dex_file, bss_start_ + bss_size_);
+    DexCacheArraysLayout layout(pointer_size, dex_file);
+    bss_size_ += layout.Size();
+  }
+
+  bss_roots_offset_ = bss_size_;
+
+  // Prepare offsets for .bss String entries.
+  for (auto& entry : bss_string_entries_) {
+    DCHECK_EQ(entry.second, 0u);
+    entry.second = bss_start_ + bss_size_;
+    bss_size_ += sizeof(GcRoot<mirror::String>);
+  }
+}
+
 bool OatWriter::WriteRodata(OutputStream* out) {
   CHECK(write_state_ == WriteState::kWriteRoData);
 
@@ -1736,7 +1768,7 @@
 
   oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum);
   oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin);
-  if (compiler_driver_->IsBootImage()) {
+  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
     CHECK_EQ(image_patch_delta, 0);
     CHECK_EQ(oat_header_->GetImagePatchDelta(), 0);
   } else {
@@ -1826,7 +1858,7 @@
 }
 
 size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset) {
-  if (compiler_driver_->IsBootImage()) {
+  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
     InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
 
     #define DO_TRAMPOLINE(field) \