Merge "Speed up relative_patcher_arm64_test."
diff --git a/dex2oat/linker/arm/relative_patcher_thumb2_test.cc b/dex2oat/linker/arm/relative_patcher_thumb2_test.cc
index 3d7277a..b93e091 100644
--- a/dex2oat/linker/arm/relative_patcher_thumb2_test.cc
+++ b/dex2oat/linker/arm/relative_patcher_thumb2_test.cc
@@ -827,26 +827,38 @@
   }
 }
 
-#define TEST_BAKER_FIELD_WIDE(offset, ref_reg)    \
-  TEST_F(Thumb2RelativePatcherTest,               \
-    BakerOffsetWide##offset##_##ref_reg) {        \
-    TestBakerFieldWide(offset, ref_reg);          \
+TEST_F(Thumb2RelativePatcherTest, BakerOffsetWide) {
+  struct TestCase {
+    uint32_t offset;
+    uint32_t ref_reg;
+  };
+  static const TestCase test_cases[] = {
+      { 0u, 0u },
+      { 8u, 3u },
+      { 28u, 7u },
+      { 0xffcu, 11u },
+  };
+  for (const TestCase& test_case : test_cases) {
+    Reset();
+    TestBakerFieldWide(test_case.offset, test_case.ref_reg);
   }
+}
 
-TEST_BAKER_FIELD_WIDE(/* offset */ 0, /* ref_reg */ 0)
-TEST_BAKER_FIELD_WIDE(/* offset */ 8, /* ref_reg */ 3)
-TEST_BAKER_FIELD_WIDE(/* offset */ 28, /* ref_reg */ 7)
-TEST_BAKER_FIELD_WIDE(/* offset */ 0xffc, /* ref_reg */ 11)
-
-#define TEST_BAKER_FIELD_NARROW(offset, ref_reg)  \
-  TEST_F(Thumb2RelativePatcherTest,               \
-    BakerOffsetNarrow##offset##_##ref_reg) {      \
-    TestBakerFieldNarrow(offset, ref_reg);        \
+TEST_F(Thumb2RelativePatcherTest, BakerOffsetNarrow) {
+  struct TestCase {
+    uint32_t offset;
+    uint32_t ref_reg;
+  };
+  static const TestCase test_cases[] = {
+      { 0, 0u },
+      { 8, 3u },
+      { 28, 7u },
+  };
+  for (const TestCase& test_case : test_cases) {
+    Reset();
+    TestBakerFieldNarrow(test_case.offset, test_case.ref_reg);
   }
-
-TEST_BAKER_FIELD_NARROW(/* offset */ 0, /* ref_reg */ 0)
-TEST_BAKER_FIELD_NARROW(/* offset */ 8, /* ref_reg */ 3)
-TEST_BAKER_FIELD_NARROW(/* offset */ 28, /* ref_reg */ 7)
+}
 
 TEST_F(Thumb2RelativePatcherTest, BakerOffsetThunkInTheMiddle) {
   // One thunk in the middle with maximum distance branches to it from both sides.
diff --git a/dex2oat/linker/arm64/relative_patcher_arm64_test.cc b/dex2oat/linker/arm64/relative_patcher_arm64_test.cc
index 9e3bb97..0fc4610 100644
--- a/dex2oat/linker/arm64/relative_patcher_arm64_test.cc
+++ b/dex2oat/linker/arm64/relative_patcher_arm64_test.cc
@@ -783,174 +783,242 @@
   EXPECT_TRUE(CheckThunk(thunk_offset));
 }
 
-TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry1) {
-  TestNopsAdrpLdr(0u, 0x12345678u, 0x1234u);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry2) {
-  TestNopsAdrpLdr(0u, -0x12345678u, 0x4444u);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry3) {
-  TestNopsAdrpLdr(0u, 0x12345000u, 0x3ffcu);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry4) {
-  TestNopsAdrpLdr(0u, 0x12345000u, 0x4000u);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringReference1) {
-  TestNopsAdrpAdd(0u, 0x12345678u);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringReference2) {
-  TestNopsAdrpAdd(0u, -0x12345678u);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringReference3) {
-  TestNopsAdrpAdd(0u, 0x12345000u);
-}
-
-TEST_F(Arm64RelativePatcherTestDefault, StringReference4) {
-  TestNopsAdrpAdd(0u, 0x12345ffcu);
-}
-
-#define TEST_FOR_OFFSETS(test, disp1, disp2) \
-  test(0xff4u, disp1) test(0xff8u, disp1) test(0xffcu, disp1) test(0x1000u, disp1) \
-  test(0xff4u, disp2) test(0xff8u, disp2) test(0xffcu, disp2) test(0x1000u, disp2)
-
-#define DEFAULT_LDUR_LDR_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry ## adrp_offset ## Ldur ## disp) { \
-    bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu); \
-    TestAdrpLdurLdr(adrp_offset, has_thunk, 0x12345678u, disp); \
+TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry) {
+  struct TestCase {
+    uint32_t bss_begin;
+    uint32_t string_entry_offset;
+  };
+  static const TestCase test_cases[] = {
+      { 0x12345678u, 0x1234u },
+      { -0x12345678u, 0x4444u },
+      { 0x12345000u, 0x3ffcu },
+      { 0x12345000u, 0x4000u }
+  };
+  for (const TestCase& test_case : test_cases) {
+    Reset();
+    TestNopsAdrpLdr(/*num_nops=*/ 0u, test_case.bss_begin, test_case.string_entry_offset);
   }
+}
 
-TEST_FOR_OFFSETS(DEFAULT_LDUR_LDR_TEST, 0x1234, 0x1238)
-
-#define DENVER64_LDUR_LDR_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDenver64, StringBssEntry ## adrp_offset ## Ldur ## disp) { \
-    TestAdrpLdurLdr(adrp_offset, false, 0x12345678u, disp); \
+TEST_F(Arm64RelativePatcherTestDefault, StringReference) {
+  for (uint32_t string_offset : { 0x12345678u, -0x12345678u, 0x12345000u, 0x12345ffcu}) {
+    Reset();
+    TestNopsAdrpAdd(/*num_nops=*/ 0u, string_offset);
   }
+}
 
-TEST_FOR_OFFSETS(DENVER64_LDUR_LDR_TEST, 0x1234, 0x1238)
+template <typename Test>
+void TestForAdrpOffsets(Test test, std::initializer_list<uint32_t> args) {
+  for (uint32_t adrp_offset : { 0xff4u, 0xff8u, 0xffcu, 0x1000u }) {
+    for (uint32_t arg : args) {
+      test(adrp_offset, arg);
+    }
+  }
+}
+
+TEST_F(Arm64RelativePatcherTestDefault, StringBssEntryLdur) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_entry_offset) {
+        Reset();
+        bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu);
+        TestAdrpLdurLdr(adrp_offset, has_thunk, /*bss_begin=*/ 0x12345678u, string_entry_offset);
+      },
+      { 0x1234u, 0x1238u });
+}
+
+TEST_F(Arm64RelativePatcherTestDenver64, StringBssEntryLdur) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_entry_offset) {
+        Reset();
+        TestAdrpLdurLdr(adrp_offset,
+                        /*has_thunk=*/ false,
+                        /*bss_begin=*/ 0x12345678u,
+                        string_entry_offset);
+      },
+      { 0x1234u, 0x1238u });
+}
 
 // LDR <Wt>, <label> is always aligned. We should never have to use a fixup.
-#define LDRW_PCREL_LDR_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry ## adrp_offset ## WPcRel ## disp) { \
-    TestAdrpLdrPcRelLdr(kLdrWPcRelInsn, disp, adrp_offset, false, 0x12345678u, 0x1234u); \
-  }
-
-TEST_FOR_OFFSETS(LDRW_PCREL_LDR_TEST, 0x1234, 0x1238)
+TEST_F(Arm64RelativePatcherTestDefault, StringBssEntryWPcRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t pcrel_disp) {
+        Reset();
+        TestAdrpLdrPcRelLdr(kLdrWPcRelInsn,
+                            pcrel_disp,
+                            adrp_offset,
+                            /*has_thunk=*/ false,
+                            /*bss_begin=*/ 0x12345678u,
+                            /*string_entry_offset=*/ 0x1234u);
+      },
+      { 0x1234u, 0x1238u });
+}
 
 // LDR <Xt>, <label> is aligned when offset + displacement is a multiple of 8.
-#define LDRX_PCREL_LDR_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry ## adrp_offset ## XPcRel ## disp) { \
-    bool unaligned = !IsAligned<8u>((adrp_offset) + 4u + static_cast<uint32_t>(disp)); \
-    bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu) && unaligned; \
-    TestAdrpLdrPcRelLdr(kLdrXPcRelInsn, disp, adrp_offset, has_thunk, 0x12345678u, 0x1234u); \
-  }
-
-TEST_FOR_OFFSETS(LDRX_PCREL_LDR_TEST, 0x1234, 0x1238)
+TEST_F(Arm64RelativePatcherTestDefault, StringBssEntryXPcRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t pcrel_disp) {
+        Reset();
+        bool unaligned = !IsAligned<8u>((adrp_offset) + 4u + static_cast<uint32_t>(pcrel_disp));
+        bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu) && unaligned;
+        TestAdrpLdrPcRelLdr(kLdrXPcRelInsn,
+                            pcrel_disp,
+                            adrp_offset,
+                            has_thunk,
+                            /*bss_begin=*/ 0x12345678u,
+                            /*string_entry_offset=*/ 0x1234u);
+      },
+      { 0x1234u, 0x1238u });
+}
 
 // LDR <Wt>, [SP, #<pimm>] and LDR <Xt>, [SP, #<pimm>] are always aligned. No fixup needed.
-#define LDRW_SPREL_LDR_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry ## adrp_offset ## WSpRel ## disp) { \
-    TestAdrpLdrSpRelLdr(kLdrWSpRelInsn, (disp) >> 2, adrp_offset, false, 0x12345678u, 0x1234u); \
-  }
+TEST_F(Arm64RelativePatcherTestDefault, StringBssEntryWSpRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t disp) {
+        Reset();
+        TestAdrpLdrSpRelLdr(kLdrWSpRelInsn,
+                            /*sprel_disp_in_load_units=*/ disp >> 2,
+                            adrp_offset,
+                            /*has_thunk=*/ false,
+                            /*bss_begin=*/ 0x12345678u,
+                            /*string_entry_offset=*/ 0x1234u);
+      },
+      { 0u, 4u });
+}
 
-TEST_FOR_OFFSETS(LDRW_SPREL_LDR_TEST, 0, 4)
+TEST_F(Arm64RelativePatcherTestDefault, StringBssEntryXSpRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t disp) {
+        Reset();
+        TestAdrpLdrSpRelLdr(kLdrXSpRelInsn,
+                            /*sprel_disp_in_load_units=*/ (disp) >> 3,
+                            adrp_offset,
+                            /*has_thunk=*/ false,
+                            /*bss_begin=*/ 0x12345678u,
+                            /*string_entry_offset=*/ 0x1234u);
+      },
+      { 0u, 8u });
+}
 
-#define LDRX_SPREL_LDR_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringBssEntry ## adrp_offset ## XSpRel ## disp) { \
-    TestAdrpLdrSpRelLdr(kLdrXSpRelInsn, (disp) >> 3, adrp_offset, false, 0x12345678u, 0x1234u); \
-  }
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceLdur) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_offset) {
+        Reset();
+        bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu);
+        TestAdrpLdurAdd(adrp_offset, has_thunk, string_offset);
+      },
+      { 0x12345678u, 0xffffc840u });
+}
 
-TEST_FOR_OFFSETS(LDRX_SPREL_LDR_TEST, 0, 8)
+TEST_F(Arm64RelativePatcherTestDenver64, StringReferenceLdur) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_offset) {
+        Reset();
+        TestAdrpLdurAdd(adrp_offset, /*has_thunk=*/ false, string_offset);
+      },
+      { 0x12345678u, 0xffffc840U });
+}
 
-#define DEFAULT_LDUR_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## Ldur ## disp) { \
-    bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu); \
-    TestAdrpLdurAdd(adrp_offset, has_thunk, disp); \
-  }
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceSubX3X2) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_offset) {
+        Reset();
+        /* SUB unrelated to "ADRP x0, addr". */ \
+        uint32_t sub = kSubXInsn | (100 << 10) | (2u << 5) | 3u;  /* SUB x3, x2, #100 */
+        TestAdrpInsn2Add(sub, adrp_offset, /*has_thunk=*/ false, string_offset);
+      },
+      { 0x12345678u, 0xffffc840u });
+}
 
-TEST_FOR_OFFSETS(DEFAULT_LDUR_ADD_TEST, 0x12345678, 0xffffc840)
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceSubsX3X0) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_offset) {
+        Reset();
+        /* SUBS that uses the result of "ADRP x0, addr". */ \
+        uint32_t subs = kSubsXInsn | (100 << 10) | (0u << 5) | 3u;  /* SUBS x3, x0, #100 */
+        TestAdrpInsn2Add(subs, adrp_offset, /*has_thunk=*/ false, string_offset);
+      },
+      { 0x12345678u, 0xffffc840u });
+}
 
-#define DENVER64_LDUR_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDenver64, StringReference ## adrp_offset ## Ldur ## disp) { \
-    TestAdrpLdurAdd(adrp_offset, false, disp); \
-  }
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceAddX0X0) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_offset) {
+        Reset();
+        /* ADD that uses the result register of "ADRP x0, addr" as both source and destination. */
+        uint32_t add = kSubXInsn | (100 << 10) | (0u << 5) | 0u;  /* ADD x0, x0, #100 */
+        TestAdrpInsn2Add(add, adrp_offset, /*has_thunk=*/ false, string_offset);
+      },
+      { 0x12345678u, 0xffffc840 });
+}
 
-TEST_FOR_OFFSETS(DENVER64_LDUR_ADD_TEST, 0x12345678, 0xffffc840)
-
-#define DEFAULT_SUBX3X2_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## SubX3X2 ## disp) { \
-    /* SUB unrelated to "ADRP x0, addr". */ \
-    uint32_t sub = kSubXInsn | (100 << 10) | (2u << 5) | 3u;  /* SUB x3, x2, #100 */ \
-    TestAdrpInsn2Add(sub, adrp_offset, false, disp); \
-  }
-
-TEST_FOR_OFFSETS(DEFAULT_SUBX3X2_ADD_TEST, 0x12345678, 0xffffc840)
-
-#define DEFAULT_SUBSX3X0_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## SubsX3X0 ## disp) { \
-    /* SUBS that uses the result of "ADRP x0, addr". */ \
-    uint32_t subs = kSubsXInsn | (100 << 10) | (0u << 5) | 3u;  /* SUBS x3, x0, #100 */ \
-    TestAdrpInsn2Add(subs, adrp_offset, false, disp); \
-  }
-
-TEST_FOR_OFFSETS(DEFAULT_SUBSX3X0_ADD_TEST, 0x12345678, 0xffffc840)
-
-#define DEFAULT_ADDX0X0_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## AddX0X0 ## disp) { \
-    /* ADD that uses the result register of "ADRP x0, addr" as both source and destination. */ \
-    uint32_t add = kSubXInsn | (100 << 10) | (0u << 5) | 0u;  /* ADD x0, x0, #100 */ \
-    TestAdrpInsn2Add(add, adrp_offset, false, disp); \
-  }
-
-TEST_FOR_OFFSETS(DEFAULT_ADDX0X0_ADD_TEST, 0x12345678, 0xffffc840)
-
-#define DEFAULT_ADDSX0X2_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## AddsX0X2 ## disp) { \
-    /* ADDS that does not use the result of "ADRP x0, addr" but overwrites that register. */ \
-    uint32_t adds = kAddsXInsn | (100 << 10) | (2u << 5) | 0u;  /* ADDS x0, x2, #100 */ \
-    bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu); \
-    TestAdrpInsn2Add(adds, adrp_offset, has_thunk, disp); \
-  }
-
-TEST_FOR_OFFSETS(DEFAULT_ADDSX0X2_ADD_TEST, 0x12345678, 0xffffc840)
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceAddsX0X2) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t string_offset) {
+        Reset();
+        /* ADDS that does not use the result of "ADRP x0, addr" but overwrites that register. */
+        uint32_t adds = kAddsXInsn | (100 << 10) | (2u << 5) | 0u;  /* ADDS x0, x2, #100 */
+        bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu);
+        TestAdrpInsn2Add(adds, adrp_offset, has_thunk, string_offset);
+      },
+      { 0x12345678u, 0xffffc840u });
+}
 
 // LDR <Wt>, <label> is always aligned. We should never have to use a fixup.
-#define LDRW_PCREL_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## WPcRel ## disp) { \
-    TestAdrpLdrPcRelAdd(kLdrWPcRelInsn, disp, adrp_offset, false, 0x12345678u); \
-  }
-
-TEST_FOR_OFFSETS(LDRW_PCREL_ADD_TEST, 0x1234, 0x1238)
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceWPcRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t pcrel_disp) {
+        Reset();
+        TestAdrpLdrPcRelAdd(kLdrWPcRelInsn,
+                            pcrel_disp,
+                            adrp_offset,
+                            /*has_thunk=*/ false,
+                            /*string_offset=*/ 0x12345678u);
+      },
+      { 0x1234u, 0x1238u });
+}
 
 // LDR <Xt>, <label> is aligned when offset + displacement is a multiple of 8.
-#define LDRX_PCREL_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## XPcRel ## disp) { \
-    bool unaligned = !IsAligned<8u>((adrp_offset) + 4u + static_cast<uint32_t>(disp)); \
-    bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu) && unaligned; \
-    TestAdrpLdrPcRelAdd(kLdrXPcRelInsn, disp, adrp_offset, has_thunk, 0x12345678u); \
-  }
-
-TEST_FOR_OFFSETS(LDRX_PCREL_ADD_TEST, 0x1234, 0x1238)
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceXPcRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t pcrel_disp) {
+        Reset();
+        bool unaligned = !IsAligned<8u>((adrp_offset) + 4u + static_cast<uint32_t>(pcrel_disp));
+        bool has_thunk = ((adrp_offset) == 0xff8u || (adrp_offset) == 0xffcu) && unaligned;
+        TestAdrpLdrPcRelAdd(kLdrXPcRelInsn,
+                            pcrel_disp,
+                            adrp_offset,
+                            has_thunk,
+                            /*string_offset=*/ 0x12345678u);
+      },
+      { 0x1234u, 0x1238u });
+}
 
 // LDR <Wt>, [SP, #<pimm>] and LDR <Xt>, [SP, #<pimm>] are always aligned. No fixup needed.
-#define LDRW_SPREL_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## WSpRel ## disp) { \
-    TestAdrpLdrSpRelAdd(kLdrWSpRelInsn, (disp) >> 2, adrp_offset, false, 0x12345678u); \
-  }
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceWSpRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t disp) {
+        Reset();
+        TestAdrpLdrSpRelAdd(kLdrWSpRelInsn,
+                            /*sprel_disp_in_load_units=*/ (disp) >> 2,
+                            adrp_offset,
+                            /*has_thunk=*/ false,
+                            /*string_offset=*/ 0x12345678u);
+      },
+      { 0u, 4u });
+}
 
-TEST_FOR_OFFSETS(LDRW_SPREL_ADD_TEST, 0, 4)
-
-#define LDRX_SPREL_ADD_TEST(adrp_offset, disp) \
-  TEST_F(Arm64RelativePatcherTestDefault, StringReference ## adrp_offset ## XSpRel ## disp) { \
-    TestAdrpLdrSpRelAdd(kLdrXSpRelInsn, (disp) >> 3, adrp_offset, false, 0x12345678u); \
-  }
-
-TEST_FOR_OFFSETS(LDRX_SPREL_ADD_TEST, 0, 8)
+TEST_F(Arm64RelativePatcherTestDefault, StringReferenceXSpRel) {
+  TestForAdrpOffsets(
+      [&](uint32_t adrp_offset, uint32_t disp) {
+        Reset();
+        TestAdrpLdrSpRelAdd(kLdrXSpRelInsn,
+                            /*sprel_disp_in_load_units=*/ (disp) >> 3,
+                            adrp_offset,
+                            /*has_thunk=*/ false,
+                            /*string_offset=*/ 0x12345678u);
+      },
+      { 0u, 8u });
+}
 
 void Arm64RelativePatcherTest::TestBakerField(uint32_t offset, uint32_t ref_reg) {
   uint32_t valid_regs[] = {
@@ -1039,15 +1107,22 @@
   }
 }
 
-#define TEST_BAKER_FIELD(offset, ref_reg)     \
-  TEST_F(Arm64RelativePatcherTestDefault,     \
-    BakerOffset##offset##_##ref_reg) {        \
-    TestBakerField(offset, ref_reg);          \
+TEST_F(Arm64RelativePatcherTestDefault, BakerOffset) {
+  struct TestCase {
+    uint32_t offset;
+    uint32_t ref_reg;
+  };
+  static const TestCase test_cases[] = {
+      { 0u, 0u },
+      { 8u, 15u},
+      { 0x3ffcu, 29u },
+  };
+  for (const TestCase& test_case : test_cases) {
+    Reset();
+    TestBakerField(test_case.offset, test_case.ref_reg);
   }
+}
 
-TEST_BAKER_FIELD(/* offset */ 0, /* ref_reg */ 0)
-TEST_BAKER_FIELD(/* offset */ 8, /* ref_reg */ 15)
-TEST_BAKER_FIELD(/* offset */ 0x3ffc, /* ref_reg */ 29)
 
 TEST_F(Arm64RelativePatcherTestDefault, BakerOffsetThunkInTheMiddle) {
   // One thunk in the middle with maximum distance branches to it from both sides.
diff --git a/dex2oat/linker/relative_patcher_test.h b/dex2oat/linker/relative_patcher_test.h
index 9725570..56ff0ef 100644
--- a/dex2oat/linker/relative_patcher_test.h
+++ b/dex2oat/linker/relative_patcher_test.h
@@ -50,7 +50,7 @@
         compiled_methods_(),
         patched_code_(),
         output_(),
-        out_("test output stream", &output_) {
+        out_(nullptr) {
     // Override CommonCompilerTest's defaults.
     instruction_set_ = instruction_set;
     number_of_threads_ = 1u;
@@ -61,10 +61,7 @@
     OverrideInstructionSetFeatures(instruction_set_, variant_);
     CommonCompilerTest::SetUp();
 
-    patcher_ = RelativePatcher::Create(compiler_options_->GetInstructionSet(),
-                                       compiler_options_->GetInstructionSetFeatures(),
-                                       &thunk_provider_,
-                                       &method_offset_map_);
+    Reset();
   }
 
   void TearDown() override {
@@ -73,6 +70,24 @@
     CommonCompilerTest::TearDown();
   }
 
+  // Reset the helper to start another test. Creating and tearing down the Runtime is expensive,
+  // so we merge related tests together.
+  void Reset() {
+    thunk_provider_.Reset();
+    method_offset_map_.map.clear();
+    patcher_ = RelativePatcher::Create(compiler_options_->GetInstructionSet(),
+                                       compiler_options_->GetInstructionSetFeatures(),
+                                       &thunk_provider_,
+                                       &method_offset_map_);
+    bss_begin_ = 0u;
+    string_index_to_offset_map_.clear();
+    compiled_method_refs_.clear();
+    compiled_methods_.clear();
+    patched_code_.clear();
+    output_.clear();
+    out_.reset(new VectorOutputStream("test output stream", &output_));
+  }
+
   MethodReference MethodRef(uint32_t method_idx) {
     CHECK_NE(method_idx, 0u);
     return MethodReference(nullptr, method_idx);
@@ -127,7 +142,7 @@
     DCHECK(output_.empty());
     uint8_t dummy_trampoline[kTrampolineSize];
     memset(dummy_trampoline, 0, sizeof(dummy_trampoline));
-    out_.WriteFully(dummy_trampoline, kTrampolineSize);
+    out_->WriteFully(dummy_trampoline, kTrampolineSize);
     offset = kTrampolineSize;
     static const uint8_t kPadding[] = {
         0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
@@ -135,14 +150,14 @@
     uint8_t dummy_header[sizeof(OatQuickMethodHeader)];
     memset(dummy_header, 0, sizeof(dummy_header));
     for (auto& compiled_method : compiled_methods_) {
-      offset = patcher_->WriteThunks(&out_, offset);
+      offset = patcher_->WriteThunks(out_.get(), offset);
 
       uint32_t alignment_size = CodeAlignmentSize(offset);
       CHECK_LE(alignment_size, sizeof(kPadding));
-      out_.WriteFully(kPadding, alignment_size);
+      out_->WriteFully(kPadding, alignment_size);
       offset += alignment_size;
 
-      out_.WriteFully(dummy_header, sizeof(OatQuickMethodHeader));
+      out_->WriteFully(dummy_header, sizeof(OatQuickMethodHeader));
       offset += sizeof(OatQuickMethodHeader);
       ArrayRef<const uint8_t> code = compiled_method->GetQuickCode();
       if (!compiled_method->GetPatches().empty()) {
@@ -179,10 +194,10 @@
           }
         }
       }
-      out_.WriteFully(&code[0], code.size());
+      out_->WriteFully(&code[0], code.size());
       offset += code.size();
     }
-    offset = patcher_->WriteThunks(&out_, offset);
+    offset = patcher_->WriteThunks(out_.get(), offset);
     CHECK_EQ(offset, output_size);
     CHECK_EQ(output_.size(), output_size);
   }
@@ -270,6 +285,10 @@
       *debug_name = value.GetDebugName();
     }
 
+    void Reset() {
+      thunk_map_.clear();
+    }
+
    private:
     class ThunkKey {
      public:
@@ -342,7 +361,7 @@
   std::vector<std::unique_ptr<CompiledMethod>> compiled_methods_;
   std::vector<uint8_t> patched_code_;
   std::vector<uint8_t> output_;
-  VectorOutputStream out_;
+  std::unique_ptr<VectorOutputStream> out_;
 };
 
 }  // namespace linker