Handle allocation failure in AddPreResolvedStringsArray

Might fail on 32 bits if the address space is fragmented.

Regression test is infeasible to add.

Bug: 134652205
Test: test-art-host

(cherry picked from commit 4bdafc488c19f0bd1f8cc711b7db1ea9c68e5cd3)

Merged-In: I8a254a27275be4e0ff39fdb72715771f4f77cf36
Change-Id: I8a254a27275be4e0ff39fdb72715771f4f77cf36
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 78f5dc5..8893d67 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -680,9 +680,10 @@
 
   for (const DexFile* dex_file : dex_files) {
     dex_cache.Assign(class_linker->FindDexCache(soa.Self(), *dex_file));
+    bool added_preresolved_string_array = false;
     if (only_startup_strings) {
       // When resolving startup strings, create the preresolved strings array.
-      dex_cache->AddPreResolvedStringsArray();
+      added_preresolved_string_array = dex_cache->AddPreResolvedStringsArray();
     }
     TimingLogger::ScopedTiming t("Resolve const-string Strings", timings);
 
@@ -709,7 +710,7 @@
         if (profile_compilation_info != nullptr && !is_startup_clinit) {
           ProfileCompilationInfo::MethodHotness hotness =
               profile_compilation_info->GetMethodHotness(method.GetReference());
-          if (only_startup_strings ? !hotness.IsStartup() : !hotness.IsInProfile()) {
+          if (added_preresolved_string_array ? !hotness.IsStartup() : !hotness.IsInProfile()) {
             continue;
           }
         }
@@ -727,7 +728,7 @@
                   : inst->VRegB_31c());
               ObjPtr<mirror::String> string = class_linker->ResolveString(string_index, dex_cache);
               CHECK(string != nullptr) << "Could not allocate a string when forcing determinism";
-              if (only_startup_strings) {
+              if (added_preresolved_string_array) {
                 dex_cache->GetPreResolvedStrings()[string_index.index_] =
                     GcRoot<mirror::String>(string);
               }
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 7e79ebe..f97f521 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -172,19 +172,25 @@
                   dex_file->NumCallSiteIds());
 }
 
-void DexCache::AddPreResolvedStringsArray() {
+bool DexCache::AddPreResolvedStringsArray() {
   DCHECK_EQ(NumPreResolvedStrings(), 0u);
   Thread* const self = Thread::Current();
   LinearAlloc* linear_alloc = Runtime::Current()->GetLinearAlloc();
   const size_t num_strings = GetDexFile()->NumStringIds();
-  SetField32<false>(NumPreResolvedStringsOffset(), num_strings);
   GcRoot<mirror::String>* strings =
       linear_alloc->AllocArray<GcRoot<mirror::String>>(self, num_strings);
+  if (strings == nullptr) {
+    // Failed to allocate pre-resolved string array (probably due to address fragmentation), bail.
+    return false;
+  }
+  SetField32<false>(NumPreResolvedStringsOffset(), num_strings);
+
   CHECK(strings != nullptr);
   SetPreResolvedStrings(strings);
   for (size_t i = 0; i < GetDexFile()->NumStringIds(); ++i) {
     CHECK(GetPreResolvedStrings()[i].Read() == nullptr);
   }
+  return true;
 }
 
 void DexCache::Init(const DexFile* dex_file,
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index e399a8c..b41443e 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -473,7 +473,8 @@
   uint32_t MethodSlotIndex(uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_);
   uint32_t MethodTypeSlotIndex(dex::ProtoIndex proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void AddPreResolvedStringsArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  // Returns true if we succeeded in adding the pre-resolved string array.
+  bool AddPreResolvedStringsArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
  private:
   void Init(const DexFile* dex_file,