Implement Integer.valueOf() intrinsic for boot image.

And generate only one "boot image live objects" array rather
than one per boot*.art file.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Test: testrunner.py --target --optimizing
Bug: 71526895
Change-Id: I23af7f47fea5150805f801cd2512f2d152ee5b73
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h
index 7b35fd9..b7beb7b 100644
--- a/compiler/linker/linker_patch.h
+++ b/compiler/linker/linker_patch.h
@@ -40,19 +40,31 @@
   // which is ridiculous given we have only a handful of values here. If we
   // choose to squeeze the Type into fewer than 8 bits, we'll have to declare
   // patch_type_ as an uintN_t and do explicit static_cast<>s.
+  //
+  // Note: Actual patching is instruction_set-dependent.
   enum class Type : uint8_t {
-    kDataBimgRelRo,           // NOTE: Actual patching is instruction_set-dependent.
-    kMethodRelative,          // NOTE: Actual patching is instruction_set-dependent.
-    kMethodBssEntry,          // NOTE: Actual patching is instruction_set-dependent.
-    kCall,
-    kCallRelative,            // NOTE: Actual patching is instruction_set-dependent.
-    kTypeRelative,            // NOTE: Actual patching is instruction_set-dependent.
-    kTypeBssEntry,            // NOTE: Actual patching is instruction_set-dependent.
-    kStringRelative,          // NOTE: Actual patching is instruction_set-dependent.
-    kStringBssEntry,          // NOTE: Actual patching is instruction_set-dependent.
-    kBakerReadBarrierBranch,  // NOTE: Actual patching is instruction_set-dependent.
+    kIntrinsicReference,      // Boot image reference for an intrinsic, see IntrinsicObjects.
+    kDataBimgRelRo,
+    kMethodRelative,
+    kMethodBssEntry,
+    kCall,                    // TODO: Remove. (Deprecated, non-PIC.)
+    kCallRelative,
+    kTypeRelative,
+    kTypeBssEntry,
+    kStringRelative,
+    kStringBssEntry,
+    kBakerReadBarrierBranch,
   };
 
+  static LinkerPatch IntrinsicReferencePatch(size_t literal_offset,
+                                             uint32_t pc_insn_offset,
+                                             uint32_t intrinsic_data) {
+    LinkerPatch patch(literal_offset, Type::kIntrinsicReference, /* target_dex_file */ nullptr);
+    patch.intrinsic_data_ = intrinsic_data;
+    patch.pc_insn_offset_ = pc_insn_offset;
+    return patch;
+  }
+
   static LinkerPatch DataBimgRelRoPatch(size_t literal_offset,
                                         uint32_t pc_insn_offset,
                                         uint32_t boot_image_offset) {
@@ -160,6 +172,7 @@
 
   bool IsPcRelative() const {
     switch (GetType()) {
+      case Type::kIntrinsicReference:
       case Type::kDataBimgRelRo:
       case Type::kMethodRelative:
       case Type::kMethodBssEntry:
@@ -175,6 +188,11 @@
     }
   }
 
+  uint32_t IntrinsicData() const {
+    DCHECK(patch_type_ == Type::kIntrinsicReference);
+    return intrinsic_data_;
+  }
+
   uint32_t BootImageOffset() const {
     DCHECK(patch_type_ == Type::kDataBimgRelRo);
     return boot_image_offset_;
@@ -213,7 +231,8 @@
   }
 
   uint32_t PcInsnOffset() const {
-    DCHECK(patch_type_ == Type::kDataBimgRelRo ||
+    DCHECK(patch_type_ == Type::kIntrinsicReference ||
+           patch_type_ == Type::kDataBimgRelRo ||
            patch_type_ == Type::kMethodRelative ||
            patch_type_ == Type::kMethodBssEntry ||
            patch_type_ == Type::kTypeRelative ||
@@ -255,10 +274,12 @@
     uint32_t method_idx_;         // Method index for Call/Method patches.
     uint32_t type_idx_;           // Type index for Type patches.
     uint32_t string_idx_;         // String index for String patches.
+    uint32_t intrinsic_data_;     // Data for IntrinsicObjects.
     uint32_t baker_custom_value1_;
     static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators");
     static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators");
     static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators");
+    static_assert(sizeof(intrinsic_data_) == sizeof(cmp1_), "needed by relational operators");
     static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators");
   };
   union {