ART: Resolve <clinit> strings in compiler driver

Resolve strings for <clinit> in classes that fail initialization.
This will move the data from the zygote heap into the image heap,
creating clean memory.

Increases the image size by XXX. However, at the same time decreases
the zygote heap by the same amount.

Bug: 34956610
Test: m
Test: m test-art-host
Test: Device boots
Change-Id: I5be41da8424d5de65c02a2aed1ac4d6113741876
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 24439ae..a5e4cb0 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2365,9 +2365,9 @@
               }
 
               if (!success) {
-                // On failure, still intern strings references for static fields, as these will be
-                // created in the zygote. This is separated from the transaction code just above
-                // as we will allocate strings, so must be allowed to suspend.
+                // On failure, still intern strings of static fields and seen in <clinit>, as these
+                // will be created in the zygote. This is separated from the transaction code just
+                // above as we will allocate strings, so must be allowed to suspend.
                 InternStrings(klass, class_loader);
               }
             }
@@ -2396,6 +2396,7 @@
     const DexFile::ClassDef* class_def = klass->GetClassDef();
     ClassLinker* class_linker = manager_->GetClassLinker();
 
+    // Check encoded final field values for strings and intern.
     annotations::RuntimeEncodedStaticFieldValueIterator value_it(*dex_file,
                                                                  &h_dex_cache,
                                                                  &class_loader,
@@ -2409,6 +2410,29 @@
         CHECK(resolved != nullptr);
       }
     }
+
+    // Intern strings seen in <clinit>.
+    ArtMethod* clinit = klass->FindClassInitializer(class_linker->GetImagePointerSize());
+    if (clinit != nullptr) {
+      const DexFile::CodeItem* code_item = clinit->GetCodeItem();
+      DCHECK(code_item != nullptr);
+      const Instruction* inst = Instruction::At(code_item->insns_);
+
+      const uint32_t insns_size = code_item->insns_size_in_code_units_;
+      for (uint32_t dex_pc = 0; dex_pc < insns_size;) {
+        if (inst->Opcode() == Instruction::CONST_STRING) {
+          ObjPtr<mirror::String> s = class_linker->ResolveString(
+              *dex_file, dex::StringIndex(inst->VRegB_21c()), h_dex_cache);
+          CHECK(s != nullptr);
+        } else if (inst->Opcode() == Instruction::CONST_STRING_JUMBO) {
+          ObjPtr<mirror::String> s = class_linker->ResolveString(
+              *dex_file, dex::StringIndex(inst->VRegB_31c()), h_dex_cache);
+          CHECK(s != nullptr);
+        }
+        dex_pc += inst->SizeInCodeUnits();
+        inst = inst->Next();
+      }
+    }
   }
 
   const ParallelCompilationManager* const manager_;