Keep resolved String in HLoadString.

For the following reasons:
- Avoids needing to do a lookup again in CodeGenerator::EmitJitRoots.
- Fixes races where we the string was GC'ed before CodeGenerator::EmitJitRoots.
- Makes it possible to do GVN on the same string but defined in different
  dex files.

Test: test-art-host, test-art-target
Change-Id: If2b5d3079f7555427b1b96ab04546b3373fcf921
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 402eeee..f00648f 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1378,28 +1378,21 @@
 
 void CodeGenerator::EmitJitRoots(uint8_t* code,
                                  Handle<mirror::ObjectArray<mirror::Object>> roots,
-                                 const uint8_t* roots_data,
-                                 Handle<mirror::DexCache> outer_dex_cache) {
+                                 const uint8_t* roots_data) {
   DCHECK_EQ(static_cast<size_t>(roots->GetLength()), GetNumberOfJitRoots());
-  StackHandleScope<1> hs(Thread::Current());
-  MutableHandle<mirror::DexCache> h_dex_cache(hs.NewHandle<mirror::DexCache>(nullptr));
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   size_t index = 0;
   for (auto& entry : jit_string_roots_) {
-    const DexFile& entry_dex_file = *entry.first.dex_file;
-    // Avoid the expensive FindDexCache call by checking if the string is
-    // in the compiled method's dex file.
-    h_dex_cache.Assign(IsSameDexFile(*outer_dex_cache->GetDexFile(), entry_dex_file)
-        ? outer_dex_cache.Get()
-        : class_linker->FindDexCache(hs.Self(), entry_dex_file));
-    mirror::String* string = class_linker->LookupString(
-        entry_dex_file, entry.first.string_index, h_dex_cache);
-    DCHECK(string != nullptr) << "JIT roots require strings to have been loaded";
+    // Update the `roots` with the string, and replace the address temporarily
+    // stored to the index in the table.
+    uint64_t address = entry.second;
+    roots->Set(index, reinterpret_cast<StackReference<mirror::String>*>(address)->AsMirrorPtr());
+    DCHECK(roots->Get(index) != nullptr);
+    entry.second = index;
     // Ensure the string is strongly interned. This is a requirement on how the JIT
     // handles strings. b/32995596
-    class_linker->GetInternTable()->InternStrong(string);
-    roots->Set(index, string);
-    entry.second = index;
+    class_linker->GetInternTable()->InternStrong(
+        reinterpret_cast<mirror::String*>(roots->Get(index)));
     ++index;
   }
   for (auto& entry : jit_class_roots_) {
@@ -1407,6 +1400,7 @@
     // stored to the index in the table.
     uint64_t address = entry.second;
     roots->Set(index, reinterpret_cast<StackReference<mirror::Class>*>(address)->AsMirrorPtr());
+    DCHECK(roots->Get(index) != nullptr);
     entry.second = index;
     ++index;
   }
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 2e2c3c0..6366b98 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -351,8 +351,7 @@
   // Also emits literal patches.
   void EmitJitRoots(uint8_t* code,
                     Handle<mirror::ObjectArray<mirror::Object>> roots,
-                    const uint8_t* roots_data,
-                    Handle<mirror::DexCache> outer_dex_cache)
+                    const uint8_t* roots_data)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool IsLeafMethod() const {
@@ -713,9 +712,9 @@
   const ArenaVector<HBasicBlock*>* block_order_;
 
   // Maps a StringReference (dex_file, string_index) to the index in the literal table.
-  // Entries are intially added with a 0 index, and `EmitJitRoots` will compute all the
-  // indices.
-  ArenaSafeMap<StringReference, uint32_t, StringReferenceValueComparator> jit_string_roots_;
+  // Entries are intially added with a pointer in the handle zone, and `EmitJitRoots`
+  // will compute all the indices.
+  ArenaSafeMap<StringReference, uint64_t, StringReferenceValueComparator> jit_string_roots_;
 
   // Maps a ClassReference (dex_file, type_index) to the index in the literal table.
   // Entries are intially added with a pointer in the handle zone, and `EmitJitRoots`
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 8a7f6d3..3009103 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -5937,7 +5937,9 @@
   }
 }
 
-void InstructionCodeGeneratorARM::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorARM::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   LocationSummary* locations = load->GetLocations();
   Location out_loc = locations->Out();
   Register out = out_loc.AsRegister<Register>();
@@ -5962,8 +5964,9 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK_NE(load->GetAddress(), 0u);
-      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
       __ LoadLiteral(out, codegen_->DeduplicateBootImageAddressLiteral(address));
       return;  // No dex cache slow path.
     }
@@ -5987,7 +5990,8 @@
     }
     case HLoadString::LoadKind::kJitTableAddress: {
       __ LoadLiteral(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
-                                                                load->GetStringIndex()));
+                                                                load->GetStringIndex(),
+                                                                load->GetString()));
       // /* GcRoot<mirror::String> */ out = *out
       GenerateGcRootFieldLoad(load, out_loc, out, /* offset */ 0, kCompilerReadBarrierOption);
       return;
@@ -7317,8 +7321,10 @@
 }
 
 Literal* CodeGeneratorARM::DeduplicateJitStringLiteral(const DexFile& dex_file,
-                                                       dex::StringIndex string_index) {
-  jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u);
+                                                       dex::StringIndex string_index,
+                                                       Handle<mirror::String> handle) {
+  jit_string_roots_.Overwrite(StringReference(&dex_file, string_index),
+                              reinterpret_cast64<uint64_t>(handle.GetReference()));
   return jit_string_patches_.GetOrCreate(
       StringReference(&dex_file, string_index),
       [this]() { return __ NewLiteral<uint32_t>(/* placeholder */ 0u); });
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 6435851..d5968e0 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -489,7 +489,9 @@
                                              dex::StringIndex string_index);
   Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, dex::TypeIndex type_index);
   Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
-  Literal* DeduplicateJitStringLiteral(const DexFile& dex_file, dex::StringIndex string_index);
+  Literal* DeduplicateJitStringLiteral(const DexFile& dex_file,
+                                       dex::StringIndex string_index,
+                                       Handle<mirror::String> handle);
   Literal* DeduplicateJitClassLiteral(const DexFile& dex_file,
                                       dex::TypeIndex type_index,
                                       uint64_t address);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 5c33fe1..4b6a9be 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4137,8 +4137,9 @@
 }
 
 vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateJitStringLiteral(
-    const DexFile& dex_file, dex::StringIndex string_index) {
-  jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u);
+    const DexFile& dex_file, dex::StringIndex string_index, Handle<mirror::String> handle) {
+  jit_string_roots_.Overwrite(StringReference(&dex_file, string_index),
+                              reinterpret_cast64<uint64_t>(handle.GetReference()));
   return jit_string_patches_.GetOrCreate(
       StringReference(&dex_file, string_index),
       [this]() { return __ CreateLiteralDestroyedWithPool<uint32_t>(/* placeholder */ 0u); });
@@ -4527,7 +4528,9 @@
   }
 }
 
-void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   Register out = OutputRegister(load);
   Location out_loc = load->GetLocations()->Out();
 
@@ -4550,8 +4553,10 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK(load->GetAddress() != 0u && IsUint<32>(load->GetAddress()));
-      __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(load->GetAddress()));
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
+      __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBssEntry: {
@@ -4582,7 +4587,8 @@
     }
     case HLoadString::LoadKind::kJitTableAddress: {
       __ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
-                                                        load->GetStringIndex()));
+                                                        load->GetStringIndex(),
+                                                        load->GetString()));
       GenerateGcRootFieldLoad(load,
                               out_loc,
                               out.X(),
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 8f33b6b..d6a5f9d 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -567,7 +567,8 @@
                                                                     dex::TypeIndex type_index);
   vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageAddressLiteral(uint64_t address);
   vixl::aarch64::Literal<uint32_t>* DeduplicateJitStringLiteral(const DexFile& dex_file,
-                                                                dex::StringIndex string_index);
+                                                                dex::StringIndex string_index,
+                                                                Handle<mirror::String> handle);
   vixl::aarch64::Literal<uint32_t>* DeduplicateJitClassLiteral(const DexFile& dex_file,
                                                                dex::TypeIndex string_index,
                                                                uint64_t address);
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 00ad3e3..b1f6d59 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -6022,7 +6022,9 @@
   }
 }
 
-void InstructionCodeGeneratorARMVIXL::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorARMVIXL::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   LocationSummary* locations = load->GetLocations();
   Location out_loc = locations->Out();
   vixl32::Register out = OutputRegister(load);
@@ -6042,8 +6044,9 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK_NE(load->GetAddress(), 0u);
-      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
       __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
       return;  // No dex cache slow path.
     }
@@ -6063,7 +6066,8 @@
     }
     case HLoadString::LoadKind::kJitTableAddress: {
       __ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
-                                                        load->GetStringIndex()));
+                                                        load->GetStringIndex(),
+                                                        load->GetString()));
       // /* GcRoot<mirror::String> */ out = *out
       GenerateGcRootFieldLoad(load, out_loc, out, /* offset */ 0, kCompilerReadBarrierOption);
       return;
@@ -7444,9 +7448,12 @@
   return DeduplicateUint32Literal(address, &uint32_literals_);
 }
 
-VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateJitStringLiteral(const DexFile& dex_file,
-                                                       dex::StringIndex string_index) {
-  jit_string_roots_.Overwrite(StringReference(&dex_file, string_index), /* placeholder */ 0u);
+VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateJitStringLiteral(
+    const DexFile& dex_file,
+    dex::StringIndex string_index,
+    Handle<mirror::String> handle) {
+  jit_string_roots_.Overwrite(StringReference(&dex_file, string_index),
+                              reinterpret_cast64<uint64_t>(handle.GetReference()));
   return jit_string_patches_.GetOrCreate(
       StringReference(&dex_file, string_index),
       [this]() {
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 297d63c..200a463 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -573,7 +573,8 @@
   VIXLUInt32Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
   VIXLUInt32Literal* DeduplicateDexCacheAddressLiteral(uint32_t address);
   VIXLUInt32Literal* DeduplicateJitStringLiteral(const DexFile& dex_file,
-                                                 dex::StringIndex string_index);
+                                                 dex::StringIndex string_index,
+                                                 Handle<mirror::String> handle);
   VIXLUInt32Literal* DeduplicateJitClassLiteral(const DexFile& dex_file,
                                                 dex::TypeIndex type_index,
                                                 uint64_t address);
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 01e0dac..9af03e8 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -5625,7 +5625,9 @@
   }
 }
 
-void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   HLoadString::LoadKind load_kind = load->GetLoadKind();
   LocationSummary* locations = load->GetLocations();
   Location out_loc = locations->Out();
@@ -5660,8 +5662,9 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK_NE(load->GetAddress(), 0u);
-      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
       __ LoadLiteral(out,
                      base_or_current_method_reg,
                      codegen_->DeduplicateBootImageAddressLiteral(address));
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 36690c0..046d59c 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -3628,7 +3628,9 @@
   }
 }
 
-void InstructionCodeGeneratorMIPS64::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorMIPS64::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   HLoadString::LoadKind load_kind = load->GetLoadKind();
   LocationSummary* locations = load->GetLocations();
   Location out_loc = locations->Out();
@@ -3650,8 +3652,9 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK_NE(load->GetAddress(), 0u);
-      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
       __ LoadLiteral(out,
                      kLoadUnsignedWord,
                      codegen_->DeduplicateBootImageAddressLiteral(address));
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 0abe855..f13b60a 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -6232,15 +6232,19 @@
 }
 
 Label* CodeGeneratorX86::NewJitRootStringPatch(const DexFile& dex_file,
-                                               dex::StringIndex dex_index) {
-  jit_string_roots_.Overwrite(StringReference(&dex_file, dex_index), /* placeholder */ 0u);
+                                               dex::StringIndex dex_index,
+                                               Handle<mirror::String> handle) {
+  jit_string_roots_.Overwrite(
+      StringReference(&dex_file, dex_index), reinterpret_cast64<uint64_t>(handle.GetReference()));
   // Add a patch entry and return the label.
   jit_string_patches_.emplace_back(dex_file, dex_index.index_);
   PatchInfo<Label>* info = &jit_string_patches_.back();
   return &info->label;
 }
 
-void InstructionCodeGeneratorX86::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorX86::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   LocationSummary* locations = load->GetLocations();
   Location out_loc = locations->Out();
   Register out = out_loc.AsRegister<Register>();
@@ -6258,8 +6262,9 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK_NE(load->GetAddress(), 0u);
-      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
       __ movl(out, Immediate(address));
       codegen_->RecordSimplePatch();
       return;  // No dex cache slow path.
@@ -6280,7 +6285,7 @@
     case HLoadString::LoadKind::kJitTableAddress: {
       Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
       Label* fixup_label = codegen_->NewJitRootStringPatch(
-          load->GetDexFile(), load->GetStringIndex());
+          load->GetDexFile(), load->GetStringIndex(), load->GetString());
       // /* GcRoot<mirror::String> */ out = *address
       GenerateGcRootFieldLoad(load, out_loc, address, fixup_label, kCompilerReadBarrierOption);
       return;
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 1af6850..dd1628c 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -415,7 +415,9 @@
   void RecordTypePatch(HLoadClass* load_class);
   Label* NewStringBssEntryPatch(HLoadString* load_string);
   Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file, uint32_t element_offset);
-  Label* NewJitRootStringPatch(const DexFile& dex_file, dex::StringIndex dex_index);
+  Label* NewJitRootStringPatch(const DexFile& dex_file,
+                               dex::StringIndex dex_index,
+                               Handle<mirror::String> handle);
   Label* NewJitRootClassPatch(const DexFile& dex_file, dex::TypeIndex dex_index, uint64_t address);
 
   void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 903844f..89f4ae0 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -5631,15 +5631,19 @@
 }
 
 Label* CodeGeneratorX86_64::NewJitRootStringPatch(const DexFile& dex_file,
-                                                  dex::StringIndex dex_index) {
-  jit_string_roots_.Overwrite(StringReference(&dex_file, dex_index), /* placeholder */ 0u);
+                                                  dex::StringIndex dex_index,
+                                                  Handle<mirror::String> handle) {
+  jit_string_roots_.Overwrite(
+      StringReference(&dex_file, dex_index), reinterpret_cast64<uint64_t>(handle.GetReference()));
   // Add a patch entry and return the label.
   jit_string_patches_.emplace_back(dex_file, dex_index.index_);
   PatchInfo<Label>* info = &jit_string_patches_.back();
   return &info->label;
 }
 
-void InstructionCodeGeneratorX86_64::VisitLoadString(HLoadString* load) {
+// NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
+// move.
+void InstructionCodeGeneratorX86_64::VisitLoadString(HLoadString* load) NO_THREAD_SAFETY_ANALYSIS {
   LocationSummary* locations = load->GetLocations();
   Location out_loc = locations->Out();
   CpuRegister out = out_loc.AsRegister<CpuRegister>();
@@ -5651,8 +5655,9 @@
       return;  // No dex cache slow path.
     }
     case HLoadString::LoadKind::kBootImageAddress: {
-      DCHECK_NE(load->GetAddress(), 0u);
-      uint32_t address = dchecked_integral_cast<uint32_t>(load->GetAddress());
+      uint32_t address = dchecked_integral_cast<uint32_t>(
+          reinterpret_cast<uintptr_t>(load->GetString().Get()));
+      DCHECK_NE(address, 0u);
       __ movl(out, Immediate(address));  // Zero-extended.
       codegen_->RecordSimplePatch();
       return;  // No dex cache slow path.
@@ -5673,8 +5678,8 @@
     case HLoadString::LoadKind::kJitTableAddress: {
       Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
                                           /* no_rip */ true);
-      Label* fixup_label =
-          codegen_->NewJitRootStringPatch(load->GetDexFile(), load->GetStringIndex());
+      Label* fixup_label = codegen_->NewJitRootStringPatch(
+          load->GetDexFile(), load->GetStringIndex(), load->GetString());
       // /* GcRoot<mirror::String> */ out = *address
       GenerateGcRootFieldLoad(load, out_loc, address, fixup_label, kCompilerReadBarrierOption);
       return;
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index f827e79..32d006c 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -412,7 +412,9 @@
   void RecordTypePatch(HLoadClass* load_class);
   Label* NewStringBssEntryPatch(HLoadString* load_string);
   Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file, uint32_t element_offset);
-  Label* NewJitRootStringPatch(const DexFile& dex_file, dex::StringIndex dex_index);
+  Label* NewJitRootStringPatch(const DexFile& dex_file,
+                               dex::StringIndex dex_index,
+                               Handle<mirror::String> handle);
   Label* NewJitRootClassPatch(const DexFile& dex_file, dex::TypeIndex dex_index, uint64_t address);
 
   void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index a599c2a..d45fa11 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2498,6 +2498,17 @@
   }
 }
 
+// Helper for InstructionDataEquals to fetch the mirror String out
+// from a kJitTableAddress LoadString kind.
+// NO_THREAD_SAFETY_ANALYSIS because even though we're accessing
+// mirrors, they are stored in a variable size handle scope which is always
+// visited during a pause. Also, the only caller of this helper
+// only uses the mirror for pointer comparison.
+static inline mirror::String* AsMirrorInternal(Handle<mirror::String> handle)
+    NO_THREAD_SAFETY_ANALYSIS {
+  return handle.Get();
+}
+
 bool HLoadString::InstructionDataEquals(const HInstruction* other) const {
   const HLoadString* other_load_string = other->AsLoadString();
   // TODO: To allow GVN for HLoadString from different dex files, we should compare the strings
@@ -2506,16 +2517,16 @@
       GetPackedFields() != other_load_string->GetPackedFields()) {
     return false;
   }
-  LoadKind load_kind = GetLoadKind();
-  if (HasAddress(load_kind)) {
-    return GetAddress() == other_load_string->GetAddress();
-  } else {
-    DCHECK(HasStringReference(load_kind)) << load_kind;
-    return IsSameDexFile(GetDexFile(), other_load_string->GetDexFile());
+  switch (GetLoadKind()) {
+    case LoadKind::kBootImageAddress:
+    case LoadKind::kJitTableAddress:
+      return AsMirrorInternal(GetString()) == AsMirrorInternal(other_load_string->GetString());
+    default:
+      return IsSameDexFile(GetDexFile(), other_load_string->GetDexFile());
   }
 }
 
-void HLoadString::SetLoadKindInternal(LoadKind load_kind) {
+void HLoadString::SetLoadKind(LoadKind load_kind) {
   // Once sharpened, the load kind should not be changed again.
   DCHECK_EQ(GetLoadKind(), LoadKind::kDexCacheViaMethod);
   SetPackedField<LoadKindField>(load_kind);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 8c64d25..6a3ccc7 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -5761,39 +5761,31 @@
               uint32_t dex_pc)
       : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
         special_input_(HUserRecord<HInstruction*>(current_method)),
-        string_index_(string_index) {
+        string_index_(string_index),
+        dex_file_(dex_file) {
     SetPackedField<LoadKindField>(LoadKind::kDexCacheViaMethod);
-    load_data_.dex_file_ = &dex_file;
   }
 
-  void SetLoadKindWithAddress(LoadKind load_kind, uint64_t address) {
-    DCHECK(HasAddress(load_kind));
-    load_data_.address = address;
-    SetLoadKindInternal(load_kind);
-  }
-
-  void SetLoadKindWithStringReference(LoadKind load_kind,
-                                      const DexFile& dex_file,
-                                      dex::StringIndex string_index) {
-    DCHECK(HasStringReference(load_kind));
-    load_data_.dex_file_ = &dex_file;
-    string_index_ = string_index;
-    SetLoadKindInternal(load_kind);
-  }
+  void SetLoadKind(LoadKind load_kind);
 
   LoadKind GetLoadKind() const {
     return GetPackedField<LoadKindField>();
   }
 
-  const DexFile& GetDexFile() const;
+  const DexFile& GetDexFile() const {
+    return dex_file_;
+  }
 
   dex::StringIndex GetStringIndex() const {
     return string_index_;
   }
 
-  uint64_t GetAddress() const {
-    DCHECK(HasAddress(GetLoadKind()));
-    return load_data_.address;
+  Handle<mirror::String> GetString() const {
+    return string_;
+  }
+
+  void SetString(Handle<mirror::String> str) {
+    string_ = str;
   }
 
   bool CanBeMoved() const OVERRIDE { return true; }
@@ -5848,18 +5840,6 @@
   static_assert(kNumberOfLoadStringPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
   using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
 
-  static bool HasStringReference(LoadKind load_kind) {
-    return load_kind == LoadKind::kBootImageLinkTimeAddress ||
-        load_kind == LoadKind::kBootImageLinkTimePcRelative ||
-        load_kind == LoadKind::kBssEntry ||
-        load_kind == LoadKind::kDexCacheViaMethod ||
-        load_kind == LoadKind::kJitTableAddress;
-  }
-
-  static bool HasAddress(LoadKind load_kind) {
-    return load_kind == LoadKind::kBootImageAddress;
-  }
-
   void SetLoadKindInternal(LoadKind load_kind);
 
   // The special input is the HCurrentMethod for kDexCacheViaMethod.
@@ -5867,26 +5847,16 @@
   // for PC-relative loads, i.e. kDexCachePcRelative or kBootImageLinkTimePcRelative.
   HUserRecord<HInstruction*> special_input_;
 
-  // String index serves also as the hash code and it's also needed for slow-paths,
-  // so it must not be overwritten with other load data.
   dex::StringIndex string_index_;
+  const DexFile& dex_file_;
 
-  union {
-    const DexFile* dex_file_;            // For string reference.
-    uint64_t address;  // Up to 64-bit, needed for kDexCacheAddress on 64-bit targets.
-  } load_data_;
+  Handle<mirror::String> string_;
 
   DISALLOW_COPY_AND_ASSIGN(HLoadString);
 };
 std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs);
 
 // Note: defined outside class to see operator<<(., HLoadString::LoadKind).
-inline const DexFile& HLoadString::GetDexFile() const {
-  DCHECK(HasStringReference(GetLoadKind())) << GetLoadKind();
-  return *load_data_.dex_file_;
-}
-
-// Note: defined outside class to see operator<<(., HLoadString::LoadKind).
 inline void HLoadString::AddSpecialInput(HInstruction* special_input) {
   // The special input is used for PC-relative loads on some architectures,
   // including literal pool loads, which are PC-relative too.
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 4bf5b08..297500b 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -1205,7 +1205,7 @@
   }
   MaybeRecordStat(MethodCompilationStat::kCompiled);
   codegen->BuildStackMaps(MemoryRegion(stack_map_data, stack_map_size), *code_item);
-  codegen->EmitJitRoots(code_allocator.GetData(), roots, roots_data, dex_cache);
+  codegen->EmitJitRoots(code_allocator.GetData(), roots, roots_data);
 
   const void* code = code_cache->CommitCode(
       self,
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index ca26c30..dc8ee23 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -275,7 +275,6 @@
   dex::StringIndex string_index = load_string->GetStringIndex();
 
   HLoadString::LoadKind desired_load_kind = HLoadString::LoadKind::kDexCacheViaMethod;
-  uint64_t address = 0u;  // String or dex cache element address.
   {
     Runtime* runtime = Runtime::Current();
     ClassLinker* class_linker = runtime->GetClassLinker();
@@ -284,12 +283,13 @@
     Handle<mirror::DexCache> dex_cache = IsSameDexFile(dex_file, *compilation_unit_.GetDexFile())
         ? compilation_unit_.GetDexCache()
         : hs.NewHandle(class_linker->FindDexCache(soa.Self(), dex_file));
+    mirror::String* string = nullptr;
 
     if (codegen_->GetCompilerOptions().IsBootImage()) {
       // Compiling boot image. Resolve the string and allocate it if needed, to ensure
       // the string will be added to the boot image.
       DCHECK(!runtime->UseJitCompilation());
-      mirror::String* string = class_linker->ResolveString(dex_file, string_index, dex_cache);
+      string = class_linker->ResolveString(dex_file, string_index, dex_cache);
       CHECK(string != nullptr);
       if (compiler_driver_->GetSupportBootImageFixup()) {
         DCHECK(ContainsElement(compiler_driver_->GetDexFilesForOatFile(), &dex_file));
@@ -303,43 +303,32 @@
     } else if (runtime->UseJitCompilation()) {
       // TODO: Make sure we don't set the "compile PIC" flag for JIT as that's bogus.
       // DCHECK(!codegen_->GetCompilerOptions().GetCompilePic());
-      mirror::String* string = class_linker->LookupString(dex_file, string_index, dex_cache);
+      string = class_linker->LookupString(dex_file, string_index, dex_cache);
       if (string != nullptr) {
         if (runtime->GetHeap()->ObjectIsInBootImageSpace(string)) {
           desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
-          address = reinterpret_cast64<uint64_t>(string);
         } else {
           desired_load_kind = HLoadString::LoadKind::kJitTableAddress;
         }
       }
     } else {
       // AOT app compilation. Try to lookup the string without allocating if not found.
-      mirror::String* string = class_linker->LookupString(dex_file, string_index, dex_cache);
+      string = class_linker->LookupString(dex_file, string_index, dex_cache);
       if (string != nullptr &&
           runtime->GetHeap()->ObjectIsInBootImageSpace(string) &&
           !codegen_->GetCompilerOptions().GetCompilePic()) {
         desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
-        address = reinterpret_cast64<uint64_t>(string);
       } else {
         desired_load_kind = HLoadString::LoadKind::kBssEntry;
       }
     }
+    if (string != nullptr) {
+      load_string->SetString(handles_->NewHandle(string));
+    }
   }
 
   HLoadString::LoadKind load_kind = codegen_->GetSupportedLoadStringKind(desired_load_kind);
-  switch (load_kind) {
-    case HLoadString::LoadKind::kBootImageLinkTimeAddress:
-    case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
-    case HLoadString::LoadKind::kBssEntry:
-    case HLoadString::LoadKind::kDexCacheViaMethod:
-    case HLoadString::LoadKind::kJitTableAddress:
-      load_string->SetLoadKindWithStringReference(load_kind, dex_file, string_index);
-      break;
-    case HLoadString::LoadKind::kBootImageAddress:
-      DCHECK_NE(address, 0u);
-      load_string->SetLoadKindWithAddress(load_kind, address);
-      break;
-  }
+  load_string->SetLoadKind(load_kind);
 }
 
 }  // namespace art