Always produce PIC code for AOT compilation.

Change sharpening to use PIC load kinds for AOT compilation
and add "Jit" to the direct addressing load kind names. Use
PIC code also for the Integer.valueOf() intrinsic codegen.
Remove all support for non-PIC linker patches.

The dex2oat --compile-pic option is retained for now but
ignored by the compiler.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Test: testrunner.py --target --optimizing
Bug: 77856493
Change-Id: I54d666f6522f160a1b6ece4045a15d19363acbb6
diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc
index aed04f9..f25ee9b 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -64,11 +64,11 @@
       ArrayRef<const uint8_t>(raw_cfi_info2),
   };
   const linker::LinkerPatch raw_patches1[] = {
-      linker::LinkerPatch::CodePatch(0u, nullptr, 1u),
+      linker::LinkerPatch::IntrinsicReferencePatch(0u, 0u, 0u),
       linker::LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 1u),
   };
   const linker::LinkerPatch raw_patches2[] = {
-      linker::LinkerPatch::CodePatch(0u, nullptr, 1u),
+      linker::LinkerPatch::IntrinsicReferencePatch(0u, 0u, 0u),
       linker::LinkerPatch::RelativeMethodPatch(4u, nullptr, 0u, 2u),
   };
   ArrayRef<const linker::LinkerPatch> patches[] = {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index b24b036..6eca304 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -255,7 +255,6 @@
       compiler_(Compiler::Create(this, compiler_kind)),
       compiler_kind_(compiler_kind),
       requires_constructor_barrier_lock_("constructor barrier lock"),
-      non_relative_linker_patch_count_(0u),
       image_classes_(std::move(image_classes)),
       number_of_soft_verifier_failures_(0),
       had_hard_verifier_failure_(false),
@@ -463,18 +462,7 @@
   }
 
   if (compiled_method != nullptr) {
-    // Count non-relative linker patches.
-    size_t non_relative_linker_patch_count = 0u;
-    for (const linker::LinkerPatch& patch : compiled_method->GetPatches()) {
-      if (!patch.IsPcRelative()) {
-        ++non_relative_linker_patch_count;
-      }
-    }
-    bool compile_pic = driver->GetCompilerOptions().GetCompilePic();  // Off by default
-    // When compiling with PIC, there should be zero non-relative linker patches
-    CHECK(!compile_pic || non_relative_linker_patch_count == 0u);
-
-    driver->AddCompiledMethod(method_ref, compiled_method, non_relative_linker_patch_count);
+    driver->AddCompiledMethod(method_ref, compiled_method);
   }
 
   if (self->IsExceptionPending()) {
@@ -2697,15 +2685,12 @@
 }
 
 void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref,
-                                       CompiledMethod* const compiled_method,
-                                       size_t non_relative_linker_patch_count) {
+                                       CompiledMethod* const compiled_method) {
   DCHECK(GetCompiledMethod(method_ref) == nullptr) << method_ref.PrettyMethod();
   MethodTable::InsertResult result = compiled_methods_.Insert(method_ref,
                                                               /*expected*/ nullptr,
                                                               compiled_method);
   CHECK(result == MethodTable::kInsertResultSuccess);
-  non_relative_linker_patch_count_.fetch_add(non_relative_linker_patch_count,
-                                             std::memory_order_relaxed);
   DCHECK(GetCompiledMethod(method_ref) != nullptr) << method_ref.PrettyMethod();
 }
 
@@ -2815,10 +2800,6 @@
   return is_system_class;
 }
 
-size_t CompilerDriver::GetNonRelativeLinkerPatchCount() const {
-  return non_relative_linker_patch_count_.load(std::memory_order_relaxed);
-}
-
 void CompilerDriver::SetRequiresConstructorBarrier(Thread* self,
                                                    const DexFile* dex_file,
                                                    uint16_t class_def_index,
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 3d3583c..343f67c 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -148,9 +148,7 @@
   CompiledMethod* GetCompiledMethod(MethodReference ref) const;
   size_t GetNonRelativeLinkerPatchCount() const;
   // Add a compiled method.
-  void AddCompiledMethod(const MethodReference& method_ref,
-                         CompiledMethod* const compiled_method,
-                         size_t non_relative_linker_patch_count);
+  void AddCompiledMethod(const MethodReference& method_ref, CompiledMethod* const compiled_method);
   CompiledMethod* RemoveCompiledMethod(const MethodReference& method_ref);
 
   void SetRequiresConstructorBarrier(Thread* self,
@@ -435,10 +433,6 @@
   // All method references that this compiler has compiled.
   MethodTable compiled_methods_;
 
-  // Number of non-relative patches in all compiled methods. These patches need space
-  // in the .oat_patches ELF section if requested in the compiler options.
-  Atomic<size_t> non_relative_linker_patch_count_;
-
   // Image classes to be updated by PreCompile().
   // TODO: Remove this member which is a non-const pointer to the CompilerOptions' data.
   //       Pass this explicitly to the PreCompile() which should be called directly from
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h
index b7beb7b..5e1615f 100644
--- a/compiler/linker/linker_patch.h
+++ b/compiler/linker/linker_patch.h
@@ -47,7 +47,6 @@
     kDataBimgRelRo,
     kMethodRelative,
     kMethodBssEntry,
-    kCall,                    // TODO: Remove. (Deprecated, non-PIC.)
     kCallRelative,
     kTypeRelative,
     kTypeBssEntry,
@@ -94,14 +93,6 @@
     return patch;
   }
 
-  static LinkerPatch CodePatch(size_t literal_offset,
-                               const DexFile* target_dex_file,
-                               uint32_t target_method_idx) {
-    LinkerPatch patch(literal_offset, Type::kCall, target_dex_file);
-    patch.method_idx_ = target_method_idx;
-    return patch;
-  }
-
   static LinkerPatch RelativeCodePatch(size_t literal_offset,
                                        const DexFile* target_dex_file,
                                        uint32_t target_method_idx) {
@@ -170,24 +161,6 @@
     return patch_type_;
   }
 
-  bool IsPcRelative() const {
-    switch (GetType()) {
-      case Type::kIntrinsicReference:
-      case Type::kDataBimgRelRo:
-      case Type::kMethodRelative:
-      case Type::kMethodBssEntry:
-      case Type::kCallRelative:
-      case Type::kTypeRelative:
-      case Type::kTypeBssEntry:
-      case Type::kStringRelative:
-      case Type::kStringBssEntry:
-      case Type::kBakerReadBarrierBranch:
-        return true;
-      default:
-        return false;
-    }
-  }
-
   uint32_t IntrinsicData() const {
     DCHECK(patch_type_ == Type::kIntrinsicReference);
     return intrinsic_data_;
@@ -201,7 +174,6 @@
   MethodReference TargetMethod() const {
     DCHECK(patch_type_ == Type::kMethodRelative ||
            patch_type_ == Type::kMethodBssEntry ||
-           patch_type_ == Type::kCall ||
            patch_type_ == Type::kCallRelative);
     return MethodReference(target_dex_file_, method_idx_);
   }
diff --git a/compiler/linker/linker_patch_test.cc b/compiler/linker/linker_patch_test.cc
index e87dc8d..997418c 100644
--- a/compiler/linker/linker_patch_test.cc
+++ b/compiler/linker/linker_patch_test.cc
@@ -25,10 +25,14 @@
   const DexFile* dex_file1 = reinterpret_cast<const DexFile*>(1);
   const DexFile* dex_file2 = reinterpret_cast<const DexFile*>(2);
   LinkerPatch patches[] = {
+      LinkerPatch::IntrinsicReferencePatch(16u, 3000u, 1000u),
+      LinkerPatch::IntrinsicReferencePatch(16u, 3001u, 1000u),
+      LinkerPatch::IntrinsicReferencePatch(16u, 3000u, 1001u),
+      LinkerPatch::IntrinsicReferencePatch(16u, 3001u, 1001u),
       LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3000u, 1000u),
       LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3001u, 1000u),
       LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3000u, 1001u),
-      LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3001u, 1001u),  // Index 3.
+      LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3001u, 1001u),  // Index 7.
       LinkerPatch::RelativeMethodPatch(16u, dex_file2, 3000u, 1000u),
       LinkerPatch::RelativeMethodPatch(16u, dex_file2, 3001u, 1000u),
       LinkerPatch::RelativeMethodPatch(16u, dex_file2, 3000u, 1001u),
@@ -41,10 +45,6 @@
       LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3001u, 1000u),
       LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3000u, 1001u),
       LinkerPatch::MethodBssEntryPatch(16u, dex_file2, 3001u, 1001u),
-      LinkerPatch::CodePatch(16u, dex_file1, 1000u),
-      LinkerPatch::CodePatch(16u, dex_file1, 1001u),
-      LinkerPatch::CodePatch(16u, dex_file2, 1000u),
-      LinkerPatch::CodePatch(16u, dex_file2, 1001u),
       LinkerPatch::RelativeCodePatch(16u, dex_file1, 1000u),
       LinkerPatch::RelativeCodePatch(16u, dex_file1, 1001u),
       LinkerPatch::RelativeCodePatch(16u, dex_file2, 1000u),
@@ -86,6 +86,10 @@
       LinkerPatch::BakerReadBarrierBranchPatch(16u, 1u, 0u),
       LinkerPatch::BakerReadBarrierBranchPatch(16u, 1u, 1u),
 
+      LinkerPatch::IntrinsicReferencePatch(32u, 3000u, 1000u),
+      LinkerPatch::IntrinsicReferencePatch(32u, 3001u, 1000u),
+      LinkerPatch::IntrinsicReferencePatch(32u, 3000u, 1001u),
+      LinkerPatch::IntrinsicReferencePatch(32u, 3001u, 1001u),
       LinkerPatch::RelativeMethodPatch(32u, dex_file1, 3000u, 1000u),
       LinkerPatch::RelativeMethodPatch(32u, dex_file1, 3001u, 1000u),
       LinkerPatch::RelativeMethodPatch(32u, dex_file1, 3000u, 1001u),
@@ -102,10 +106,6 @@
       LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3001u, 1000u),
       LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3000u, 1001u),
       LinkerPatch::MethodBssEntryPatch(32u, dex_file2, 3001u, 1001u),
-      LinkerPatch::CodePatch(32u, dex_file1, 1000u),
-      LinkerPatch::CodePatch(32u, dex_file1, 1001u),
-      LinkerPatch::CodePatch(32u, dex_file2, 1000u),
-      LinkerPatch::CodePatch(32u, dex_file2, 1001u),
       LinkerPatch::RelativeCodePatch(32u, dex_file1, 1000u),
       LinkerPatch::RelativeCodePatch(32u, dex_file1, 1001u),
       LinkerPatch::RelativeCodePatch(32u, dex_file2, 1000u),
@@ -147,20 +147,20 @@
       LinkerPatch::BakerReadBarrierBranchPatch(32u, 1u, 0u),
       LinkerPatch::BakerReadBarrierBranchPatch(32u, 1u, 1u),
 
-      LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3001u, 1001u),  // Same as patch at index 3.
+      LinkerPatch::RelativeMethodPatch(16u, dex_file1, 3001u, 1001u),  // Same as patch at index 7.
   };
   constexpr size_t last_index = arraysize(patches) - 1u;
 
   for (size_t i = 0; i != arraysize(patches); ++i) {
     for (size_t j = 0; j != arraysize(patches); ++j) {
-      bool expected = (i != last_index ? i : 3u) == (j != last_index ? j : 3u);
+      bool expected = (i != last_index ? i : 7u) == (j != last_index ? j : 7u);
       EXPECT_EQ(expected, patches[i] == patches[j]) << i << " " << j;
     }
   }
 
   for (size_t i = 0; i != arraysize(patches); ++i) {
     for (size_t j = 0; j != arraysize(patches); ++j) {
-      bool expected = (i != last_index ? i : 3u) < (j != last_index ? j : 3u);
+      bool expected = (i != last_index ? i : 7u) < (j != last_index ? j : 7u);
       EXPECT_EQ(expected, patches[i] < patches[j]) << i << " " << j;
     }
   }
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index d1c83ce..1a8f187 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4555,10 +4555,6 @@
       EmitAddPlaceholder(add_label, XRegisterFrom(temp), XRegisterFrom(temp));
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      // Load method address from literal pool.
-      __ Ldr(XRegisterFrom(temp), DeduplicateUint64Literal(invoke->GetMethodAddress()));
-      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
       // Add ADRP with its PC-relative .data.bimg.rel.ro patch.
       uint32_t boot_image_offset = GetBootImageOffset(invoke);
@@ -4581,6 +4577,10 @@
       EmitLdrOffsetPlaceholder(ldr_label, XRegisterFrom(temp), XRegisterFrom(temp));
       break;
     }
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      // Load method address from literal pool.
+      __ Ldr(XRegisterFrom(temp), DeduplicateUint64Literal(invoke->GetMethodAddress()));
+      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
@@ -4812,8 +4812,7 @@
     // Add ADD with its PC-relative type patch.
     vixl::aarch64::Label* add_label = NewBootImageIntrinsicPatch(boot_image_reference, adrp_label);
     EmitAddPlaceholder(add_label, reg.X(), reg.X());
-  } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK(Runtime::Current()->IsAotCompiler());
+  } else if (Runtime::Current()->IsAotCompiler()) {
     // Add ADRP with its PC-relative .data.bimg.rel.ro patch.
     vixl::aarch64::Label* adrp_label = NewBootImageRelRoPatch(boot_image_reference);
     EmitAdrpPlaceholder(adrp_label, reg.X());
@@ -4821,6 +4820,7 @@
     vixl::aarch64::Label* ldr_label = NewBootImageRelRoPatch(boot_image_reference, adrp_label);
     EmitLdrOffsetPlaceholder(ldr_label, reg.W(), reg.X());
   } else {
+    DCHECK(Runtime::Current()->UseJitCompilation());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -5016,10 +5016,10 @@
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
   }
@@ -5113,14 +5113,6 @@
       codegen_->EmitAddPlaceholder(add_label, out.X(), out.X());
       break;
     }
-    case HLoadClass::LoadKind::kBootImageAddress: {
-      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
-      DCHECK_NE(address, 0u);
-      __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
-      break;
-    }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
@@ -5153,6 +5145,13 @@
       generate_null_check = true;
       break;
     }
+    case HLoadClass::LoadKind::kJitBootImageAddress: {
+      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+      uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+      DCHECK_NE(address, 0u);
+      __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
+      break;
+    }
     case HLoadClass::LoadKind::kJitTableAddress: {
       __ Ldr(out, codegen_->DeduplicateJitClassLiteral(cls->GetDexFile(),
                                                        cls->GetTypeIndex(),
@@ -5239,10 +5238,10 @@
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
       break;
   }
@@ -5294,13 +5293,6 @@
       codegen_->EmitAddPlaceholder(add_label, out.X(), out.X());
       return;
     }
-    case HLoadString::LoadKind::kBootImageAddress: {
-      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;
-    }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       // Add ADRP with its PC-relative .data.bimg.rel.ro patch.
@@ -5339,6 +5331,12 @@
       codegen_->MaybeGenerateMarkingRegisterCheck(/* code */ __LINE__);
       return;
     }
+    case HLoadString::LoadKind::kJitBootImageAddress: {
+      uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+      DCHECK_NE(address, 0u);
+      __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
+      return;
+    }
     case HLoadString::LoadKind::kJitTableAddress: {
       __ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
                                                         load->GetStringIndex(),
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index deab239..5ae64dd 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -7374,10 +7374,10 @@
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
   }
@@ -7465,14 +7465,6 @@
       codegen_->EmitMovwMovtPlaceholder(labels, out);
       break;
     }
-    case HLoadClass::LoadKind::kBootImageAddress: {
-      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
-      DCHECK_NE(address, 0u);
-      __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
-      break;
-    }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
@@ -7489,6 +7481,13 @@
       generate_null_check = true;
       break;
     }
+    case HLoadClass::LoadKind::kJitBootImageAddress: {
+      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+      uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+      DCHECK_NE(address, 0u);
+      __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
+      break;
+    }
     case HLoadClass::LoadKind::kJitTableAddress: {
       __ Ldr(out, codegen_->DeduplicateJitClassLiteral(cls->GetDexFile(),
                                                        cls->GetTypeIndex(),
@@ -7649,10 +7648,10 @@
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
       break;
   }
@@ -7699,13 +7698,6 @@
       codegen_->EmitMovwMovtPlaceholder(labels, out);
       return;
     }
-    case HLoadString::LoadKind::kBootImageAddress: {
-      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;
-    }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
@@ -7729,6 +7721,12 @@
       codegen_->MaybeGenerateMarkingRegisterCheck(/* code */ 16);
       return;
     }
+    case HLoadString::LoadKind::kJitBootImageAddress: {
+      uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+      DCHECK_NE(address, 0u);
+      __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
+      return;
+    }
     case HLoadString::LoadKind::kJitTableAddress: {
       __ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
                                                         load->GetStringIndex(),
@@ -9336,9 +9334,6 @@
       EmitMovwMovtPlaceholder(labels, temp_reg);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      __ Mov(RegisterFrom(temp), Operand::From(invoke->GetMethodAddress()));
-      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
       uint32_t boot_image_offset = GetBootImageOffset(invoke);
       PcRelativePatchInfo* labels = NewBootImageRelRoPatch(boot_image_offset);
@@ -9355,6 +9350,9 @@
       GetAssembler()->LoadFromOffset(kLoadWord, temp_reg, temp_reg, /* offset*/ 0);
       break;
     }
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      __ Mov(RegisterFrom(temp), Operand::From(invoke->GetMethodAddress()));
+      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
@@ -9500,7 +9498,7 @@
 }
 
 VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateBootImageAddressLiteral(uint32_t address) {
-  return DeduplicateUint32Literal(dchecked_integral_cast<uint32_t>(address), &uint32_literals_);
+  return DeduplicateUint32Literal(address, &uint32_literals_);
 }
 
 VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateJitStringLiteral(
@@ -9532,13 +9530,13 @@
     CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
         NewBootImageIntrinsicPatch(boot_image_reference);
     EmitMovwMovtPlaceholder(labels, reg);
-  } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK(Runtime::Current()->IsAotCompiler());
+  } else if (Runtime::Current()->IsAotCompiler()) {
     CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
         NewBootImageRelRoPatch(boot_image_reference);
     EmitMovwMovtPlaceholder(labels, reg);
     __ Ldr(reg, MemOperand(reg, /* offset */ 0));
   } else {
+    DCHECK(Runtime::Current()->UseJitCompilation());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     uintptr_t address =
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index c7295e4..4aed2c0 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1758,13 +1758,13 @@
     PcRelativePatchInfo* info_low = NewBootImageIntrinsicPatch(boot_image_reference, info_high);
     EmitPcRelativeAddressPlaceholderHigh(info_high, TMP, /* base */ ZERO);
     __ Addiu(reg, TMP, /* placeholder */ 0x5678, &info_low->label);
-  } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK(Runtime::Current()->IsAotCompiler());
+  } else if (Runtime::Current()->IsAotCompiler()) {
     PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_reference);
     PcRelativePatchInfo* info_low = NewBootImageRelRoPatch(boot_image_reference, info_high);
     EmitPcRelativeAddressPlaceholderHigh(info_high, reg, /* base */ ZERO);
     __ Lw(reg, reg, /* placeholder */ 0x5678, &info_low->label);
   } else {
+    DCHECK(Runtime::Current()->UseJitCompilation());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -7879,10 +7879,10 @@
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
       break;
   }
@@ -7902,10 +7902,10 @@
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
   }
@@ -7982,9 +7982,6 @@
       __ Addiu(temp_reg, TMP, /* placeholder */ 0x5678, &info_low->label);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      __ LoadConst32(temp.AsRegister<Register>(), invoke->GetMethodAddress());
-      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
       uint32_t boot_image_offset = GetBootImageOffset(invoke);
       PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_offset);
@@ -8004,6 +8001,9 @@
       __ Lw(temp_reg, TMP, /* placeholder */ 0x5678, &info_low->label);
       break;
     }
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      __ LoadConst32(temp.AsRegister<Register>(), invoke->GetMethodAddress());
+      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
@@ -8114,14 +8114,14 @@
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kBootImageRelRo:
     case HLoadClass::LoadKind::kBssEntry:
+    case HLoadClass::LoadKind::kJitBootImageAddress:
       if (isR6) {
         break;
       }
       if (has_irreducible_loops) {
-        if (load_kind != HLoadClass::LoadKind::kBootImageAddress) {
+        if (load_kind != HLoadClass::LoadKind::kJitBootImageAddress) {
           codegen_->ClobberRA();
         }
         break;
@@ -8166,9 +8166,9 @@
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kBootImageRelRo:
     case HLoadClass::LoadKind::kBssEntry:
+    case HLoadClass::LoadKind::kJitBootImageAddress:
       base_or_current_method_reg =
           (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
       break;
@@ -8210,20 +8210,6 @@
       __ Addiu(out, out, /* placeholder */ 0x5678, &info_low->label);
       break;
     }
-    case HLoadClass::LoadKind::kBootImageAddress: {
-      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
-      DCHECK_NE(address, 0u);
-      if (isR6 || !has_irreducible_loops) {
-        __ LoadLiteral(out,
-                       base_or_current_method_reg,
-                       codegen_->DeduplicateBootImageAddressLiteral(address));
-      } else {
-        __ LoadConst32(out, address);
-      }
-      break;
-    }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
@@ -8254,6 +8240,19 @@
       generate_null_check = true;
       break;
     }
+    case HLoadClass::LoadKind::kJitBootImageAddress: {
+      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+      uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+      DCHECK_NE(address, 0u);
+      if (isR6 || !has_irreducible_loops) {
+        __ LoadLiteral(out,
+                       base_or_current_method_reg,
+                       codegen_->DeduplicateBootImageAddressLiteral(address));
+      } else {
+        __ LoadConst32(out, address);
+      }
+      break;
+    }
     case HLoadClass::LoadKind::kJitTableAddress: {
       CodeGeneratorMIPS::JitPatchInfo* info = codegen_->NewJitRootClassPatch(cls->GetDexFile(),
                                                                              cls->GetTypeIndex(),
@@ -8343,15 +8342,15 @@
   const bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops();
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageRelRo:
     case HLoadString::LoadKind::kBssEntry:
+    case HLoadString::LoadKind::kJitBootImageAddress:
       if (isR6) {
         break;
       }
       if (has_irreducible_loops) {
-        if (load_kind != HLoadString::LoadKind::kBootImageAddress) {
+        if (load_kind != HLoadString::LoadKind::kJitBootImageAddress) {
           codegen_->ClobberRA();
         }
         break;
@@ -8395,10 +8394,10 @@
   bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageRelRo:
     case HLoadString::LoadKind::kBssEntry:
+    case HLoadString::LoadKind::kJitBootImageAddress:
       base_or_current_method_reg =
           (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
       break;
@@ -8420,19 +8419,6 @@
       __ Addiu(out, out, /* placeholder */ 0x5678, &info_low->label);
       return;
     }
-    case HLoadString::LoadKind::kBootImageAddress: {
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(load->GetString().Get()));
-      DCHECK_NE(address, 0u);
-      if (isR6 || !has_irreducible_loops) {
-        __ LoadLiteral(out,
-                       base_or_current_method_reg,
-                       codegen_->DeduplicateBootImageAddressLiteral(address));
-      } else {
-        __ LoadConst32(out, address);
-      }
-      return;
-    }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       uint32_t boot_image_offset = codegen_->GetBootImageOffset(load);
@@ -8468,6 +8454,18 @@
       __ Bind(slow_path->GetExitLabel());
       return;
     }
+    case HLoadString::LoadKind::kJitBootImageAddress: {
+      uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+      DCHECK_NE(address, 0u);
+      if (isR6 || !has_irreducible_loops) {
+        __ LoadLiteral(out,
+                       base_or_current_method_reg,
+                       codegen_->DeduplicateBootImageAddressLiteral(address));
+      } else {
+        __ LoadConst32(out, address);
+      }
+      return;
+    }
     case HLoadString::LoadKind::kJitTableAddress: {
       CodeGeneratorMIPS::JitPatchInfo* info =
           codegen_->NewJitRootStringPatch(load->GetDexFile(),
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index ffde45e..7516913 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1657,14 +1657,14 @@
     PcRelativePatchInfo* info_low = NewBootImageIntrinsicPatch(boot_image_reference, info_high);
     EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
     __ Daddiu(reg, AT, /* placeholder */ 0x5678);
-  } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK(Runtime::Current()->IsAotCompiler());
+  } else if (Runtime::Current()->IsAotCompiler()) {
     PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_reference);
     PcRelativePatchInfo* info_low = NewBootImageRelRoPatch(boot_image_reference, info_high);
     EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
     // Note: Boot image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
     __ Lwu(reg, AT, /* placeholder */ 0x5678);
   } else {
+    DCHECK(Runtime::Current()->UseJitCompilation());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     uintptr_t address =
@@ -5995,10 +5995,10 @@
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
       break;
   }
@@ -6022,10 +6022,10 @@
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
   }
@@ -6073,11 +6073,6 @@
       __ Daddiu(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      __ LoadLiteral(temp.AsRegister<GpuRegister>(),
-                     kLoadDoubleword,
-                     DeduplicateUint64Literal(invoke->GetMethodAddress()));
-      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
       uint32_t boot_image_offset = GetBootImageOffset(invoke);
       PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_offset);
@@ -6096,6 +6091,11 @@
       __ Ld(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
       break;
     }
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      __ LoadLiteral(temp.AsRegister<GpuRegister>(),
+                     kLoadDoubleword,
+                     DeduplicateUint64Literal(invoke->GetMethodAddress()));
+      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
@@ -6264,16 +6264,6 @@
       __ Daddiu(out, AT, /* placeholder */ 0x5678);
       break;
     }
-    case HLoadClass::LoadKind::kBootImageAddress: {
-      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
-      DCHECK_NE(address, 0u);
-      __ LoadLiteral(out,
-                     kLoadUnsignedWord,
-                     codegen_->DeduplicateBootImageAddressLiteral(address));
-      break;
-    }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
@@ -6300,6 +6290,15 @@
       generate_null_check = true;
       break;
     }
+    case HLoadClass::LoadKind::kJitBootImageAddress: {
+      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+      uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+      DCHECK_NE(address, 0u);
+      __ LoadLiteral(out,
+                     kLoadUnsignedWord,
+                     codegen_->DeduplicateBootImageAddressLiteral(address));
+      break;
+    }
     case HLoadClass::LoadKind::kJitTableAddress:
       __ LoadLiteral(out,
                      kLoadUnsignedWord,
@@ -6415,15 +6414,6 @@
       __ Daddiu(out, AT, /* placeholder */ 0x5678);
       return;
     }
-    case HLoadString::LoadKind::kBootImageAddress: {
-      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));
-      return;
-    }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       uint32_t boot_image_offset = codegen_->GetBootImageOffset(load);
@@ -6455,6 +6445,14 @@
       __ Bind(slow_path->GetExitLabel());
       return;
     }
+    case HLoadString::LoadKind::kJitBootImageAddress: {
+      uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+      DCHECK_NE(address, 0u);
+      __ LoadLiteral(out,
+                     kLoadUnsignedWord,
+                     codegen_->DeduplicateBootImageAddressLiteral(address));
+      return;
+    }
     case HLoadString::LoadKind::kJitTableAddress:
       __ LoadLiteral(out,
                      kLoadUnsignedWord,
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 1c0d283..30436ee 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4828,9 +4828,6 @@
       RecordBootImageMethodPatch(invoke);
       break;
     }
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      __ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
-      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
       Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
                                                                 temp.AsRegister<Register>());
@@ -4847,6 +4844,9 @@
       RecordMethodBssEntryPatch(invoke);
       break;
     }
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      __ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
+      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
@@ -4979,8 +4979,7 @@
         invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()).AsRegister<Register>();
     __ leal(reg, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
     RecordBootImageIntrinsicPatch(method_address, boot_image_reference);
-  } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK(Runtime::Current()->IsAotCompiler());
+  } else if (Runtime::Current()->IsAotCompiler()) {
     DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
     HX86ComputeBaseMethodAddress* method_address =
         invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
@@ -4990,6 +4989,7 @@
     __ movl(reg, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
     RecordBootImageRelRoPatch(method_address, boot_image_reference);
   } else {
+    DCHECK(Runtime::Current()->UseJitCompilation());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -6447,10 +6447,10 @@
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
   }
@@ -6549,14 +6549,6 @@
       codegen_->RecordBootImageTypePatch(cls);
       break;
     }
-    case HLoadClass::LoadKind::kBootImageAddress: {
-      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
-      DCHECK_NE(address, 0u);
-      __ movl(out, Immediate(address));
-      break;
-    }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       Register method_address = locations->InAt(0).AsRegister<Register>();
@@ -6573,6 +6565,13 @@
       generate_null_check = true;
       break;
     }
+    case HLoadClass::LoadKind::kJitBootImageAddress: {
+      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+      uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+      DCHECK_NE(address, 0u);
+      __ movl(out, Immediate(address));
+      break;
+    }
     case HLoadClass::LoadKind::kJitTableAddress: {
       Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
       Label* fixup_label = codegen_->NewJitRootClassPatch(
@@ -6686,10 +6685,10 @@
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
       break;
   }
@@ -6748,13 +6747,6 @@
       codegen_->RecordBootImageStringPatch(load);
       return;
     }
-    case HLoadString::LoadKind::kBootImageAddress: {
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(load->GetString().Get()));
-      DCHECK_NE(address, 0u);
-      __ movl(out, Immediate(address));
-      return;
-    }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       Register method_address = locations->InAt(0).AsRegister<Register>();
@@ -6776,6 +6768,12 @@
       __ Bind(slow_path->GetExitLabel());
       return;
     }
+    case HLoadString::LoadKind::kJitBootImageAddress: {
+      uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+      DCHECK_NE(address, 0u);
+      __ movl(out, Immediate(address));
+      return;
+    }
     case HLoadString::LoadKind::kJitTableAddress: {
       Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
       Label* fixup_label = codegen_->NewJitRootStringPatch(
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 3073be6..0d7837e 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -996,9 +996,6 @@
               Address::Absolute(kDummy32BitOffset, /* no_rip */ false));
       RecordBootImageMethodPatch(invoke);
       break;
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
-      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
       // Note: Boot image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
       __ movl(temp.AsRegister<CpuRegister>(),
@@ -1012,6 +1009,9 @@
       RecordMethodBssEntryPatch(invoke);
       break;
     }
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
+      break;
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
       GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
       return;  // No code pointer retrieval; the runtime performs the call directly.
@@ -1117,11 +1117,11 @@
   if (GetCompilerOptions().IsBootImage()) {
     __ leal(reg, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
     RecordBootImageIntrinsicPatch(boot_image_reference);
-  } else if (GetCompilerOptions().GetCompilePic()) {
-    DCHECK(Runtime::Current()->IsAotCompiler());
+  } else if (Runtime::Current()->IsAotCompiler()) {
     __ movl(reg, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
     RecordBootImageRelRoPatch(boot_image_reference);
   } else {
+    DCHECK(Runtime::Current()->UseJitCompilation());
     gc::Heap* heap = Runtime::Current()->GetHeap();
     DCHECK(!heap->GetBootImageSpaces().empty());
     const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -5793,10 +5793,10 @@
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadClass::LoadKind::kJitBootImageAddress:
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
       break;
   }
@@ -5889,14 +5889,6 @@
       __ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
       codegen_->RecordBootImageTypePatch(cls);
       break;
-    case HLoadClass::LoadKind::kBootImageAddress: {
-      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
-      DCHECK_NE(address, 0u);
-      __ movl(out, Immediate(static_cast<int32_t>(address)));  // Zero-extended.
-      break;
-    }
     case HLoadClass::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       __ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
@@ -5912,6 +5904,13 @@
       generate_null_check = true;
       break;
     }
+    case HLoadClass::LoadKind::kJitBootImageAddress: {
+      DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+      uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+      DCHECK_NE(address, 0u);
+      __ movl(out, Immediate(static_cast<int32_t>(address)));  // Zero-extended.
+      break;
+    }
     case HLoadClass::LoadKind::kJitTableAddress: {
       Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
                                           /* no_rip */ true);
@@ -5989,10 +5988,10 @@
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
+    case HLoadString::LoadKind::kJitBootImageAddress:
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
       break;
   }
@@ -6044,13 +6043,6 @@
       codegen_->RecordBootImageStringPatch(load);
       return;
     }
-    case HLoadString::LoadKind::kBootImageAddress: {
-      uint32_t address = dchecked_integral_cast<uint32_t>(
-          reinterpret_cast<uintptr_t>(load->GetString().Get()));
-      DCHECK_NE(address, 0u);
-      __ movl(out, Immediate(static_cast<int32_t>(address)));  // Zero-extended.
-      return;
-    }
     case HLoadString::LoadKind::kBootImageRelRo: {
       DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
       __ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
@@ -6070,6 +6062,12 @@
       __ Bind(slow_path->GetExitLabel());
       return;
     }
+    case HLoadString::LoadKind::kJitBootImageAddress: {
+      uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+      DCHECK_NE(address, 0u);
+      __ movl(out, Immediate(static_cast<int32_t>(address)));  // Zero-extended.
+      return;
+    }
     case HLoadString::LoadKind::kJitTableAddress: {
       Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
                                           /* no_rip */ true);
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 50ce755..8f822cc 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2930,12 +2930,12 @@
       return os << "Recursive";
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
       return os << "BootImageLinkTimePcRelative";
-    case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
-      return os << "DirectAddress";
     case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo:
       return os << "BootImageRelRo";
     case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
       return os << "BssEntry";
+    case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+      return os << "JitDirectAddress";
     case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
       return os << "RuntimeCall";
     default:
@@ -2967,8 +2967,8 @@
     return false;
   }
   switch (GetLoadKind()) {
-    case LoadKind::kBootImageAddress:
     case LoadKind::kBootImageRelRo:
+    case LoadKind::kJitBootImageAddress:
     case LoadKind::kJitTableAddress: {
       ScopedObjectAccess soa(Thread::Current());
       return GetClass().Get() == other_load_class->GetClass().Get();
@@ -2985,12 +2985,12 @@
       return os << "ReferrersClass";
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
       return os << "BootImageLinkTimePcRelative";
-    case HLoadClass::LoadKind::kBootImageAddress:
-      return os << "BootImageAddress";
     case HLoadClass::LoadKind::kBootImageRelRo:
       return os << "BootImageRelRo";
     case HLoadClass::LoadKind::kBssEntry:
       return os << "BssEntry";
+    case HLoadClass::LoadKind::kJitBootImageAddress:
+      return os << "JitBootImageAddress";
     case HLoadClass::LoadKind::kJitTableAddress:
       return os << "JitTableAddress";
     case HLoadClass::LoadKind::kRuntimeCall:
@@ -3010,8 +3010,8 @@
     return false;
   }
   switch (GetLoadKind()) {
-    case LoadKind::kBootImageAddress:
     case LoadKind::kBootImageRelRo:
+    case LoadKind::kJitBootImageAddress:
     case LoadKind::kJitTableAddress: {
       ScopedObjectAccess soa(Thread::Current());
       return GetString().Get() == other_load_string->GetString().Get();
@@ -3025,12 +3025,12 @@
   switch (rhs) {
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
       return os << "BootImageLinkTimePcRelative";
-    case HLoadString::LoadKind::kBootImageAddress:
-      return os << "BootImageAddress";
     case HLoadString::LoadKind::kBootImageRelRo:
       return os << "BootImageRelRo";
     case HLoadString::LoadKind::kBssEntry:
       return os << "BssEntry";
+    case HLoadString::LoadKind::kJitBootImageAddress:
+      return os << "JitBootImageAddress";
     case HLoadString::LoadKind::kJitTableAddress:
       return os << "JitTableAddress";
     case HLoadString::LoadKind::kRuntimeCall:
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index cd8d07a..16a7417 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4439,18 +4439,18 @@
     // Used for boot image methods referenced by boot image code.
     kBootImageLinkTimePcRelative,
 
-    // Use ArtMethod* at a known address, embed the direct address in the code.
-    // Used for app->boot calls with non-relocatable image and for JIT-compiled calls.
-    kDirectAddress,
-
     // Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
     // Used for app->boot calls with relocatable image.
     kBootImageRelRo,
 
     // Load from an entry in the .bss section using a PC-relative load.
-    // Used for classes outside boot image when .bss is accessible with a PC-relative load.
+    // Used for methods outside boot image referenced by AOT-compiled app and boot image code.
     kBssEntry,
 
+    // Use ArtMethod* at a known address, embed the direct address in the code.
+    // Used for for JIT-compiled calls.
+    kJitDirectAddress,
+
     // Make a runtime call to resolve and call the method. This is the last-resort-kind
     // used when other kinds are unimplemented on a particular architecture.
     kRuntimeCall,
@@ -4576,7 +4576,7 @@
   bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
   bool NeedsDexCacheOfDeclaringClass() const OVERRIDE;
   bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
-  bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; }
+  bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kJitDirectAddress; }
   bool HasPcRelativeMethodLoadKind() const {
     return GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative ||
            GetMethodLoadKind() == MethodLoadKind::kBootImageRelRo ||
@@ -6155,18 +6155,18 @@
     // Used for boot image classes referenced by boot image code.
     kBootImageLinkTimePcRelative,
 
-    // Use a known boot image Class* address, embedded in the code by the codegen.
-    // Used for boot image classes referenced by apps in JIT- and AOT-compiled code (non-PIC).
-    kBootImageAddress,
-
     // Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
-    // Used for boot image classes referenced by apps in AOT-compiled code (PIC).
+    // Used for boot image classes referenced by apps in AOT-compiled code.
     kBootImageRelRo,
 
     // Load from an entry in the .bss section using a PC-relative load.
-    // Used for classes outside boot image when .bss is accessible with a PC-relative load.
+    // Used for classes outside boot image referenced by AOT-compiled app and boot image code.
     kBssEntry,
 
+    // Use a known boot image Class* address, embedded in the code by the codegen.
+    // Used for boot image classes referenced by apps in JIT-compiled code.
+    kJitBootImageAddress,
+
     // Load from the root table associated with the JIT compiled method.
     kJitTableAddress,
 
@@ -6248,8 +6248,6 @@
     return NeedsAccessCheck() ||
            MustGenerateClinitCheck() ||
            // If the class is in the boot image, the lookup in the runtime call cannot throw.
-           // This keeps CanThrow() consistent between non-PIC (using kBootImageAddress) and
-           // PIC and subsequently avoids a DCE behavior dependency on the PIC option.
            ((GetLoadKind() == LoadKind::kRuntimeCall ||
              GetLoadKind() == LoadKind::kBssEntry) &&
             !IsInBootImage());
@@ -6366,9 +6364,9 @@
   // The special input is used for PC-relative loads on some architectures,
   // including literal pool loads, which are PC-relative too.
   DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
-         GetLoadKind() == LoadKind::kBootImageAddress ||
          GetLoadKind() == LoadKind::kBootImageRelRo ||
-         GetLoadKind() == LoadKind::kBssEntry) << GetLoadKind();
+         GetLoadKind() == LoadKind::kBssEntry ||
+         GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
   DCHECK(special_input_.GetInstruction() == nullptr);
   special_input_ = HUserRecord<HInstruction*>(special_input);
   special_input->AddUseAt(this, 0);
@@ -6382,18 +6380,18 @@
     // Used for boot image strings referenced by boot image code.
     kBootImageLinkTimePcRelative,
 
-    // Use a known boot image String* address, embedded in the code by the codegen.
-    // Used for boot image strings referenced by apps in JIT- and AOT-compiled code (non-PIC).
-    kBootImageAddress,
-
     // Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
-    // Used for boot image strings referenced by apps in AOT-compiled code (PIC).
+    // Used for boot image strings referenced by apps in AOT-compiled code.
     kBootImageRelRo,
 
     // Load from an entry in the .bss section using a PC-relative load.
-    // Used for strings outside boot image when .bss is accessible with a PC-relative load.
+    // Used for strings outside boot image referenced by AOT-compiled app and boot image code.
     kBssEntry,
 
+    // Use a known boot image String* address, embedded in the code by the codegen.
+    // Used for boot image strings referenced by apps in JIT-compiled code.
+    kJitBootImageAddress,
+
     // Load from the root table associated with the JIT compiled method.
     kJitTableAddress,
 
@@ -6459,8 +6457,8 @@
   bool NeedsEnvironment() const OVERRIDE {
     LoadKind load_kind = GetLoadKind();
     if (load_kind == LoadKind::kBootImageLinkTimePcRelative ||
-        load_kind == LoadKind::kBootImageAddress ||
         load_kind == LoadKind::kBootImageRelRo ||
+        load_kind == LoadKind::kJitBootImageAddress ||
         load_kind == LoadKind::kJitTableAddress) {
       return false;
     }
@@ -6533,9 +6531,9 @@
   // The special input is used for PC-relative loads on some architectures,
   // including literal pool loads, which are PC-relative too.
   DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
-         GetLoadKind() == LoadKind::kBootImageAddress ||
          GetLoadKind() == LoadKind::kBootImageRelRo ||
-         GetLoadKind() == LoadKind::kBssEntry) << GetLoadKind();
+         GetLoadKind() == LoadKind::kBssEntry ||
+         GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
   // HLoadString::GetInputRecords() returns an empty array at this point,
   // so use the GetInputRecords() from the base class to set the input record.
   DCHECK(special_input_.GetInstruction() == nullptr);
diff --git a/compiler/optimizing/pc_relative_fixups_mips.cc b/compiler/optimizing/pc_relative_fixups_mips.cc
index f18ecc1..a7e97a1 100644
--- a/compiler/optimizing/pc_relative_fixups_mips.cc
+++ b/compiler/optimizing/pc_relative_fixups_mips.cc
@@ -74,9 +74,9 @@
     HLoadClass::LoadKind load_kind = load_class->GetLoadKind();
     switch (load_kind) {
       case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
-      case HLoadClass::LoadKind::kBootImageAddress:
       case HLoadClass::LoadKind::kBootImageRelRo:
       case HLoadClass::LoadKind::kBssEntry:
+      case HLoadClass::LoadKind::kJitBootImageAddress:
         // Add a base register for PC-relative literals on R2.
         InitializePCRelativeBasePointer();
         load_class->AddSpecialInput(base_);
@@ -90,9 +90,9 @@
     HLoadString::LoadKind load_kind = load_string->GetLoadKind();
     switch (load_kind) {
       case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
-      case HLoadString::LoadKind::kBootImageAddress:
       case HLoadString::LoadKind::kBootImageRelRo:
       case HLoadString::LoadKind::kBssEntry:
+      case HLoadString::LoadKind::kJitBootImageAddress:
         // Add a base register for PC-relative literals on R2.
         InitializePCRelativeBasePointer();
         load_string->AddSpecialInput(base_);
diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc
index 05ec765..41f2f77 100644
--- a/compiler/optimizing/pc_relative_fixups_x86.cc
+++ b/compiler/optimizing/pc_relative_fixups_x86.cc
@@ -17,6 +17,7 @@
 #include "pc_relative_fixups_x86.h"
 #include "code_generator_x86.h"
 #include "intrinsics_x86.h"
+#include "runtime.h"
 
 namespace art {
 namespace x86 {
@@ -238,7 +239,7 @@
       case Intrinsics::kIntegerValueOf:
         // This intrinsic can be call free if it loads the address of the boot image object.
         // If we're compiling PIC, we need the address base for loading from .data.bimg.rel.ro.
-        if (!codegen_->GetCompilerOptions().GetCompilePic()) {
+        if (Runtime::Current()->UseJitCompilation()) {
           break;
         }
         FALLTHROUGH_INTENDED;
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 27482ac..5c2f57e 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -63,10 +63,6 @@
   return false;
 }
 
-static bool AOTCanEmbedMethod(ArtMethod* method, const CompilerOptions& options) {
-  return IsInBootImage(method) && !options.GetCompilePic();
-}
-
 static bool BootImageAOTCanEmbedMethod(ArtMethod* method, const CompilerOptions& compiler_options) {
   DCHECK(compiler_options.IsBootImage());
   ScopedObjectAccess soa(Thread::Current());
@@ -120,11 +116,10 @@
       method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
     }
     code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
-  } else if (Runtime::Current()->UseJitCompilation() ||
-             AOTCanEmbedMethod(callee, compiler_options)) {
+  } else if (Runtime::Current()->UseJitCompilation()) {
     // JIT or on-device AOT compilation referencing a boot image method.
     // Use the method address directly.
-    method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress;
+    method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress;
     method_load_data = reinterpret_cast<uintptr_t>(callee);
     code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
   } else if (IsInBootImage(callee)) {
@@ -199,8 +194,7 @@
       if (runtime->UseJitCompilation()) {
         DCHECK(!compiler_options.GetCompilePic());
         if (is_in_boot_image) {
-          // TODO: Use direct pointers for all non-moving spaces, not just boot image. Bug: 29530787
-          desired_load_kind = HLoadClass::LoadKind::kBootImageAddress;
+          desired_load_kind = HLoadClass::LoadKind::kJitBootImageAddress;
         } else if (klass != nullptr) {
           desired_load_kind = HLoadClass::LoadKind::kJitTableAddress;
         } else {
@@ -212,11 +206,7 @@
         }
       } else if (is_in_boot_image) {
         // AOT app compilation, boot image class.
-        if (codegen->GetCompilerOptions().GetCompilePic()) {
-          desired_load_kind = HLoadClass::LoadKind::kBootImageRelRo;
-        } else {
-          desired_load_kind = HLoadClass::LoadKind::kBootImageAddress;
-        }
+        desired_load_kind = HLoadClass::LoadKind::kBootImageRelRo;
       } else {
         // Not JIT and the klass is not in boot image.
         desired_load_kind = HLoadClass::LoadKind::kBssEntry;
@@ -348,7 +338,7 @@
       string = class_linker->LookupString(string_index, dex_cache.Get());
       if (string != nullptr) {
         if (runtime->GetHeap()->ObjectIsInBootImageSpace(string)) {
-          desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
+          desired_load_kind = HLoadString::LoadKind::kJitBootImageAddress;
         } else {
           desired_load_kind = HLoadString::LoadKind::kJitTableAddress;
         }
@@ -359,11 +349,7 @@
       // AOT app compilation. Try to lookup the string without allocating if not found.
       string = class_linker->LookupString(string_index, dex_cache.Get());
       if (string != nullptr && runtime->GetHeap()->ObjectIsInBootImageSpace(string)) {
-        if (codegen->GetCompilerOptions().GetCompilePic()) {
-          desired_load_kind = HLoadString::LoadKind::kBootImageRelRo;
-        } else {
-          desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
-        }
+        desired_load_kind = HLoadString::LoadKind::kBootImageRelRo;
       } else {
         desired_load_kind = HLoadString::LoadKind::kBssEntry;
       }
diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc
index dd0fcfe..0497d4f 100644
--- a/dex2oat/linker/arm64/relative_patcher_arm64.cc
+++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc
@@ -57,7 +57,6 @@
 
 inline bool IsAdrpPatch(const LinkerPatch& patch) {
   switch (patch.GetType()) {
-    case LinkerPatch::Type::kCall:
     case LinkerPatch::Type::kCallRelative:
     case LinkerPatch::Type::kBakerReadBarrierBranch:
       return false;
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 09a0d37..e99bc35 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -442,7 +442,6 @@
     size_type_bss_mappings_(0u),
     size_string_bss_mappings_(0u),
     relative_patcher_(nullptr),
-    absolute_patch_locations_(),
     profile_compilation_info_(info),
     compact_dex_level_(compact_dex_level) {
   // If we have a profile, always use at least the default compact dex level. The reason behind
@@ -1344,15 +1343,6 @@
       // Update offsets. (Checksum is updated when writing.)
       offset_ += sizeof(*method_header);  // Method header is prepended before code.
       offset_ += code_size;
-      // Record absolute patch locations.
-      if (!compiled_method->GetPatches().empty()) {
-        uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
-        for (const LinkerPatch& patch : compiled_method->GetPatches()) {
-          if (!patch.IsPcRelative()) {
-            writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
-          }
-        }
-      }
     }
 
     // Exclude quickened dex methods (code_size == 0) since they have no native code.
@@ -1406,10 +1396,7 @@
         executable_offset_(writer->oat_header_->GetExecutableOffset()),
         debuggable_(compiler_options.GetDebuggable()),
         native_debuggable_(compiler_options.GetNativeDebuggable()),
-        generate_debug_info_(compiler_options.GenerateAnyDebugInfo()) {
-    writer->absolute_patch_locations_.reserve(
-        writer->GetCompilerDriver()->GetNonRelativeLinkerPatchCount());
-  }
+        generate_debug_info_(compiler_options.GenerateAnyDebugInfo()) {}
 
   struct CodeOffsetsKeyComparator {
     bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const {
@@ -1868,11 +1855,6 @@
                                                                    target_offset);
               break;
             }
-            case LinkerPatch::Type::kCall: {
-              uint32_t target_offset = GetTargetOffset(patch);
-              PatchCodeAddress(&patched_code_, literal_offset, target_offset);
-              break;
-            }
             case LinkerPatch::Type::kMethodRelative: {
               uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch));
               writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
@@ -2051,26 +2033,6 @@
     data[2] = (address >> 16) & 0xffu;
     data[3] = (address >> 24) & 0xffu;
   }
-
-  void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    uint32_t address = target_offset;
-    if (writer_->GetCompilerOptions().IsBootImage()) {
-      size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_);
-      // TODO: Clean up offset types.
-      // The target_offset must be treated as signed for cross-oat patching.
-      const void* target = reinterpret_cast<const void*>(
-          writer_->image_writer_->GetOatDataBegin(oat_index) +
-          static_cast<int32_t>(target_offset));
-      address = PointerToLowMemUInt32(target);
-    }
-    DCHECK_LE(offset + 4, code->size());
-    uint8_t* data = &(*code)[offset];
-    data[0] = address & 0xffu;
-    data[1] = (address >> 8) & 0xffu;
-    data[2] = (address >> 16) & 0xffu;
-    data[3] = (address >> 24) & 0xffu;
-  }
 };
 
 class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index 298859b..1618810 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -533,9 +533,6 @@
   // The helper for processing relative patches is external so that we can patch across oat files.
   MultiOatRelativePatcher* relative_patcher_;
 
-  // The locations of absolute patches relative to the start of the executable section.
-  dchecked_vector<uintptr_t> absolute_patch_locations_;
-
   // Profile info used to generate new layout of files.
   ProfileCompilationInfo* profile_compilation_info_;
 
diff --git a/libartbase/base/casts.h b/libartbase/base/casts.h
index cbd5b67..76ff679 100644
--- a/libartbase/base/casts.h
+++ b/libartbase/base/casts.h
@@ -165,6 +165,29 @@
   return static_cast<Dest>(reinterpret_cast<uintptr_t>(ptr));
 }
 
+// A version of reinterpret_cast<>() between pointers and int32_t/uint32_t that enforces
+// zero-extension and checks that the values are converted without loss of precision.
+
+template <typename Dest, typename Source>
+inline Dest reinterpret_cast32(Source source) {
+  // This is the overload for casting from int32_t/uint32_t to a pointer.
+  static_assert(std::is_same<Source, int32_t>::value || std::is_same<Source, uint32_t>::value,
+                "Source must be int32_t or uint32_t.");
+  static_assert(std::is_pointer<Dest>::value, "Dest must be a pointer.");
+  // Check that we don't lose any non-0 bits here.
+  static_assert(sizeof(uintptr_t) >= sizeof(Source), "Expecting at least 32-bit pointers.");
+  return reinterpret_cast<Dest>(static_cast<uintptr_t>(static_cast<uint32_t>(source)));
+}
+
+template <typename Dest, typename Source>
+inline Dest reinterpret_cast32(Source* ptr) {
+  // This is the overload for casting from a pointer to int32_t/uint32_t.
+  static_assert(std::is_same<Dest, int32_t>::value || std::is_same<Dest, uint32_t>::value,
+                "Dest must be int32_t or uint32_t.");
+  static_assert(sizeof(uintptr_t) >= sizeof(Dest), "Expecting at least 32-bit pointers.");
+  return static_cast<Dest>(dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)));
+}
+
 }  // namespace art
 
 #endif  // ART_LIBARTBASE_BASE_CASTS_H_
diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java
index 17707e1..746887f 100644
--- a/test/552-checker-sharpening/src/Main.java
+++ b/test/552-checker-sharpening/src/Main.java
@@ -140,8 +140,7 @@
   }
 
   /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$getBootImageString() builder (after)
-  // Note: load kind depends on PIC/non-PIC
-  /// CHECK:                LoadString load_kind:{{BootImageAddress|BootImageRelRo}}
+  /// CHECK:                LoadString load_kind:BootImageRelRo
 
   public static String $noinline$getBootImageString() {
     // Prevent inlining to avoid the string comparison being optimized away.
@@ -168,8 +167,7 @@
   }
 
   /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.Class Main.$noinline$getStringClass() builder (after)
-  // Note: load kind depends on PIC/non-PIC
-  /// CHECK:                LoadClass load_kind:{{BootImageAddress|BootImageRelRo}} class_name:java.lang.String
+  /// CHECK:                LoadClass load_kind:BootImageRelRo class_name:java.lang.String
 
   public static Class<?> $noinline$getStringClass() {
     // Prevent inlining to avoid the string comparison being optimized away.
@@ -199,8 +197,7 @@
   /// CHECK:                InvokeStaticOrDirect method_load_kind:RuntimeCall
 
   /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$toHexString(int) sharpening (after)
-  // Note: load kind depends on PIC/non-PIC
-  /// CHECK:                InvokeStaticOrDirect method_load_kind:{{BootImageRelRo|DirectAddress}}
+  /// CHECK:                InvokeStaticOrDirect method_load_kind:BootImageRelRo
   public static String $noinline$toHexString(int value) {
     return Integer.toString(value, 16);
   }