Refactor arm assembly tests.

Another step in preparation to move to the LLVM toolchain.

Bug: 147817558
Test: m test-art-host-gtest
Change-Id: Ie5be337165d8f24e04740de0486144fa6a62f063
diff --git a/compiler/debug/dwarf/dwarf_test.h b/compiler/debug/dwarf/dwarf_test.h
index 1b32745..caa7437 100644
--- a/compiler/debug/dwarf/dwarf_test.h
+++ b/compiler/debug/dwarf/dwarf_test.h
@@ -86,8 +86,8 @@
 
     // Read the elf file back using objdump.
     std::vector<std::string> lines;
-    std::string cmd = GetAndroidHostToolsDir();
-    cmd = cmd + "objdump " + args + " " + file.GetFilename() + " 2>&1";
+    std::string cmd = GetAndroidTool("objdump");
+    cmd = cmd + " " + args + " " + file.GetFilename() + " 2>&1";
     FILE* output = popen(cmd.data(), "r");
     char buffer[1024];
     const char* line;
diff --git a/compiler/utils/assembler_test_base.h b/compiler/utils/assembler_test_base.h
index 7eb3d04..1567367 100644
--- a/compiler/utils/assembler_test_base.h
+++ b/compiler/utils/assembler_test_base.h
@@ -35,12 +35,6 @@
 
 namespace art {
 
-// Location of prebuilt tools (e.g. objdump).
-// The path needs to be updated when the prebuilt tools are updated.
-// TODO: Consider moving this logic to the build system.
-static constexpr char kPrebuiltToolsPath[] =
-    "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/bin/";
-
 // If you want to take a look at the differences between the ART assembler and clang,
 // set this flag to true. The disassembled files will then remain in the tmp directory.
 static constexpr bool kKeepDisassembledFiles = false;
@@ -137,29 +131,49 @@
   virtual InstructionSet GetIsa() = 0;
 
   std::string FindTool(const std::string& tool_name) {
-    return GetRootPath() + kPrebuiltToolsPath + tool_name;
+    return CommonArtTest::GetAndroidTool(tool_name.c_str(), GetIsa());
   }
 
   virtual std::vector<std::string> GetAssemblerCommand() {
-    return {FindTool("as"), Is64BitInstructionSet(GetIsa()) ? "--64" : "--32"};
+    switch (GetIsa()) {
+      case InstructionSet::kX86:
+        return {FindTool("as"), "--32"};
+      case InstructionSet::kX86_64:
+        return {FindTool("as"), "--64"};
+      default:
+        return {FindTool("as")};
+    }
   }
 
   virtual std::vector<std::string> GetDisassemblerCommand() {
-    return {FindTool("objdump"), "--disassemble", "--no-show-raw-insn"};
+    switch (GetIsa()) {
+      case InstructionSet::kThumb2:
+        return {FindTool("objdump"), "--disassemble", "-M", "force-thumb"};
+      default:
+        return {FindTool("objdump"), "--disassemble", "--no-show-raw-insn"};
+    }
   }
 
- private:
   bool Assemble(const std::string& asm_file, const std::string& obj_file) {
     std::vector<std::string> args = GetAssemblerCommand();
     args.insert(args.end(), {"-o", obj_file, asm_file});
     std::string output;
-    return CommonArtTestImpl::ForkAndExec(args, [](){ return true; }, &output).StandardSuccess();
+    bool ok = CommonArtTestImpl::ForkAndExec(args, [](){ return true; }, &output).StandardSuccess();
+    if (!ok) {
+      LOG(ERROR) << "Assembler error:\n" << output;
+    }
+    return ok;
   }
 
   bool Disassemble(const std::string& obj_file, std::string* output) {
     std::vector<std::string> args = GetDisassemblerCommand();
     args.insert(args.end(), {obj_file});
-    return CommonArtTestImpl::ForkAndExec(args, [](){ return true; }, output).StandardSuccess();
+    bool ok = CommonArtTestImpl::ForkAndExec(args, [](){ return true; }, output).StandardSuccess();
+    if (!ok) {
+      LOG(ERROR) << "Disassembler error:\n" << *output;
+    }
+    *output = Replace(*output, "\t", " ");
+    return ok;
   }
 
   std::vector<uint8_t> ReadFile(const std::string& filename) {
@@ -219,9 +233,16 @@
     return getcwd(temp, 1024) ? std::string(temp) + "/" : std::string("");
   }
 
-  std::string& Replace(std::string& str, const std::string& from, const std::string& to) {
-    auto it = str.find(from);
-    return (it != std::string::npos) ? str.replace(it, it + from.size(), to) : str;
+  std::string Replace(const std::string& str, const std::string& from, const std::string& to) {
+    std::string output;
+    size_t pos = 0;
+    for (auto match = str.find(from); match != str.npos; match = str.find(from, pos)) {
+      output += str.substr(pos, match - pos);
+      output += to;
+      pos = match + from.size();
+    }
+    output += str.substr(pos, str.size() - pos);
+    return output;
   }
 
   std::optional<ScratchDir> scratch_dir_;
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 4e1518b..72dfef1 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -25,6 +25,7 @@
 
 #include "jni/quick/calling_convention.h"
 #include "utils/arm/jni_macro_assembler_arm_vixl.h"
+#include "utils/assembler_test_base.h"
 
 #include "base/hex_dump.h"
 #include "base/malloc_arena_pool.h"
@@ -36,170 +37,54 @@
 // Include results file (generated manually)
 #include "assembler_thumb_test_expected.cc.inc"
 
-#ifndef ART_TARGET_ANDROID
-// This controls whether the results are printed to the
-// screen or compared against the expected output.
-// To generate new expected output, set this to true and
-// copy the output into the .cc.inc file in the form
-// of the other results.
-//
-// When this is false, the results are not printed to the
-// output, but are compared against the expected results
-// in the .cc.inc file.
-static constexpr bool kPrintResults = false;
-#endif
-
-void SetAndroidData() {
-  const char* data = getenv("ANDROID_DATA");
-  if (data == nullptr) {
-    setenv("ANDROID_DATA", "/tmp", 1);
-  }
-}
-
-int CompareIgnoringSpace(const char* s1, const char* s2) {
-  while (*s1 != '\0') {
-    while (isspace(*s1)) ++s1;
-    while (isspace(*s2)) ++s2;
-    if (*s1 == '\0' || *s1 != *s2) {
-      break;
-    }
-    ++s1;
-    ++s2;
-  }
-  return *s1 - *s2;
-}
-
-void InitResults() {
-  if (test_results.empty()) {
-    setup_results();
-  }
-}
-
-std::string GetToolsDir() {
-#ifndef ART_TARGET_ANDROID
-  // This will only work on the host.  There is no as, objcopy or objdump on the device.
-  static std::string toolsdir;
-
-  if (toolsdir.empty()) {
-    setup_results();
-    toolsdir = CommonRuntimeTest::GetAndroidTargetToolsDir(InstructionSet::kThumb2);
-    SetAndroidData();
-  }
-
-  return toolsdir;
-#else
-  return std::string();
-#endif
-}
-
-void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const char* const* results) {
-#ifndef ART_TARGET_ANDROID
-  static std::string toolsdir = GetToolsDir();
-
-  ScratchFile file;
-
-  const char* filename = file.GetFilename().c_str();
-
-  std::ofstream out(filename);
-  if (out) {
-    out << ".section \".text\"\n";
-    out << ".syntax unified\n";
-    out << ".arch armv7-a\n";
-    out << ".thumb\n";
-    out << ".thumb_func\n";
-    out << ".type " << testname << ", #function\n";
-    out << ".global " << testname << "\n";
-    out << testname << ":\n";
-    out << ".fnstart\n";
-
-    for (uint32_t i = 0 ; i < code.size(); ++i) {
-      out << ".byte " << (static_cast<int>(code[i]) & 0xff) << "\n";
-    }
-    out << ".fnend\n";
-    out << ".size " << testname << ", .-" << testname << "\n";
-  }
-  out.close();
-
-  char cmd[1024];
-
-  // Assemble the .S
-  snprintf(cmd, sizeof(cmd), "%sas %s -o %s.o", toolsdir.c_str(), filename, filename);
-  int cmd_result = system(cmd);
-  ASSERT_EQ(cmd_result, 0) << cmd << strerror(errno);
-
-  // Disassemble.
-  snprintf(cmd, sizeof(cmd), "%sobjdump -D -M force-thumb --section=.text %s.o  | grep '^  *[0-9a-f][0-9a-f]*:'",
-    toolsdir.c_str(), filename);
-  if (kPrintResults) {
-    // Print the results only, don't check. This is used to generate new output for inserting
-    // into the .inc file, so let's add the appropriate prefix/suffix needed in the C++ code.
-    strcat(cmd, " | sed '-es/^/  \"/' | sed '-es/$/\\\\n\",/'");
-    int cmd_result3 = system(cmd);
-    ASSERT_EQ(cmd_result3, 0) << strerror(errno);
-  } else {
-    // Check the results match the appropriate results in the .inc file.
-    FILE *fp = popen(cmd, "r");
-    ASSERT_TRUE(fp != nullptr);
-
-    uint32_t lineindex = 0;
-
-    while (!feof(fp)) {
-      char testline[256];
-      char *s = fgets(testline, sizeof(testline), fp);
-      if (s == nullptr) {
-        break;
-      }
-      if (CompareIgnoringSpace(results[lineindex], testline) != 0) {
-        LOG(FATAL) << "Output is not as expected at line: " << lineindex
-          << results[lineindex] << "/" << testline << ", test name: " << testname;
-      }
-      ++lineindex;
-    }
-    // Check that we are at the end.
-    ASSERT_TRUE(results[lineindex] == nullptr);
-    fclose(fp);
-  }
-
-  char buf[FILENAME_MAX];
-  snprintf(buf, sizeof(buf), "%s.o", filename);
-  unlink(buf);
-#endif  // ART_TARGET_ANDROID
-}
-
-class ArmVIXLAssemblerTest : public ::testing::Test {
+class ArmVIXLAssemblerTest : public AssemblerTestBase {
  public:
   ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { }
 
+ protected:
+  InstructionSet GetIsa() override { return InstructionSet::kThumb2; }
+
+  void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const std::string& expected) {
+#ifndef ART_TARGET_ANDROID
+    std::string obj_file = scratch_dir_->GetPath() + testname + ".o";
+    WriteElf</*IsElf64=*/false>(obj_file, InstructionSet::kThumb2, code);
+    std::string disassembly;
+    ASSERT_TRUE(Disassemble(obj_file, &disassembly));
+
+    std::string expected2 = "\n" +
+        obj_file + ":     file format elf32-littlearm\n\n\n"
+        "Disassembly of section .text:\n\n"
+        "00000000 <.text>:\n" +
+        expected;
+    EXPECT_EQ(expected2, disassembly);
+    if (expected2 != disassembly) {
+      std::string out = "  \"" + Replace(disassembly, "\n", "\\n\"\n  \"") + "\"";
+      printf("C++ formatted disassembler output for %s:\n%s\n", testname, out.c_str());
+    }
+#endif  // ART_TARGET_ANDROID
+  }
+
+#define __ assembler.
+
+  void EmitAndCheck(const char* testname, const char* expected) {
+    __ FinalizeCode();
+    size_t cs = __ CodeSize();
+    std::vector<uint8_t> managed_code(cs);
+    MemoryRegion code(&managed_code[0], managed_code.size());
+    __ FinalizeInstructions(code);
+
+    DumpAndCheck(managed_code, testname, expected);
+  }
+
+#undef __
+
+#define __ assembler.
+
   MallocArenaPool pool;
   ArenaAllocator allocator;
   ArmVIXLJNIMacroAssembler assembler;
 };
 
-#define __ assembler->
-
-void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname,
-                  const char* const* results) {
-  __ FinalizeCode();
-  size_t cs = __ CodeSize();
-  std::vector<uint8_t> managed_code(cs);
-  MemoryRegion code(&managed_code[0], managed_code.size());
-  __ FinalizeInstructions(code);
-
-  DumpAndCheck(managed_code, testname, results);
-}
-
-void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname) {
-  InitResults();
-  std::map<std::string, const char* const*>::iterator results = test_results.find(testname);
-  ASSERT_NE(results, test_results.end());
-
-  EmitAndCheck(assembler, testname, results->second);
-}
-
-#undef __
-
-#define __ assembler.
-
 TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) {
   // Run the test only with Baker read barriers, as the expected
   // generated code contains a Marking Register refresh instruction.
@@ -296,7 +181,7 @@
   __ DecreaseFrameSize(32);
   __ RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true);
 
-  EmitAndCheck(&assembler, "VixlJniHelpers");
+  EmitAndCheck("VixlJniHelpers", VixlJniHelpersResults);
 }
 
 #undef __
@@ -339,7 +224,7 @@
   __ LoadFromOffset(kLoadUnsignedByte, R2, R4, 12);
   __ LoadFromOffset(kLoadSignedHalfword, R2, R4, 12);
 
-  EmitAndCheck(&assembler, "VixlLoadFromOffset");
+  EmitAndCheck("VixlLoadFromOffset", VixlLoadFromOffsetResults);
 }
 
 TEST_F(ArmVIXLAssemblerTest, VixlStoreToOffset) {
@@ -370,7 +255,7 @@
 
   __ StoreToOffset(kStoreByte, R2, R4, 12);
 
-  EmitAndCheck(&assembler, "VixlStoreToOffset");
+  EmitAndCheck("VixlStoreToOffset", VixlStoreToOffsetResults);
 }
 
 #undef __
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index b7a6058..efe62c6 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -1,267 +1,258 @@
-const char* const VixlJniHelpersResults[] = {
-  "   0:	e92d 4de0 	stmdb	sp!, {r5, r6, r7, r8, sl, fp, lr}\n",
-  "   4:	ed2d 8a10 	vpush	{s16-s31}\n",
-  "   8:	b089      	sub	sp, #36	; 0x24\n",
-  "   a:	9000      	str	r0, [sp, #0]\n",
-  "   c:	9121      	str	r1, [sp, #132]	; 0x84\n",
-  "   e:	ed8d 0a22 	vstr	s0, [sp, #136]	; 0x88\n",
-  "  12:	9223      	str	r2, [sp, #140]	; 0x8c\n",
-  "  14:	9324      	str	r3, [sp, #144]	; 0x90\n",
-  "  16:	b088      	sub	sp, #32\n",
-  "  18:	f5ad 5d80 	sub.w	sp, sp, #4096	; 0x1000\n",
-  "  1c:	9808      	ldr	r0, [sp, #32]\n",
-  "  1e:	981f      	ldr	r0, [sp, #124]	; 0x7c\n",
-  "  20:	9821      	ldr	r0, [sp, #132]	; 0x84\n",
-  "  22:	98ff      	ldr	r0, [sp, #1020]	; 0x3fc\n",
-  "  24:	f8dd 0400 	ldr.w	r0, [sp, #1024]	; 0x400\n",
-  "  28:	f8dd cffc 	ldr.w	ip, [sp, #4092]	; 0xffc\n",
-  "  2c:	f50d 5c80 	add.w	ip, sp, #4096	; 0x1000\n",
-  "  30:	f8dc c000 	ldr.w	ip, [ip]\n",
-  "  34:	f8d9 c200 	ldr.w	ip, [r9, #512]	; 0x200\n",
-  "  38:	f8dc 0080 	ldr.w	r0, [ip, #128]	; 0x80\n",
-  "  3c:	9008      	str	r0, [sp, #32]\n",
-  "  3e:	901f      	str	r0, [sp, #124]	; 0x7c\n",
-  "  40:	9021      	str	r0, [sp, #132]	; 0x84\n",
-  "  42:	90ff      	str	r0, [sp, #1020]	; 0x3fc\n",
-  "  44:	f8cd 0400 	str.w	r0, [sp, #1024]	; 0x400\n",
-  "  48:	f8cd cffc 	str.w	ip, [sp, #4092]	; 0xffc\n",
-  "  4c:	f84d 5d04 	str.w	r5, [sp, #-4]!\n",
-  "  50:	f50d 5580 	add.w	r5, sp, #4096	; 0x1000\n",
-  "  54:	f8c5 c004 	str.w	ip, [r5, #4]\n",
-  "  58:	f85d 5b04 	ldr.w	r5, [sp], #4\n",
-  "  5c:	f04f 0cff 	mov.w	ip, #255	; 0xff\n",
-  "  60:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  64:	f06f 4c7f 	mvn.w	ip, #4278190080	; 0xff000000\n",
-  "  68:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  6c:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  70:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  74:	900c      	str	r0, [sp, #48]	; 0x30\n",
-  "  76:	f8dd c030 	ldr.w	ip, [sp, #48]	; 0x30\n",
-  "  7a:	f8cd c034 	str.w	ip, [sp, #52]	; 0x34\n",
-  "  7e:	f50d 5c80 	add.w	ip, sp, #4096	; 0x1000\n",
-  "  82:	f8c9 c200 	str.w	ip, [r9, #512]	; 0x200\n",
-  "  86:	f8c9 d200 	str.w	sp, [r9, #512]	; 0x200\n",
-  "  8a:	f8d0 e030 	ldr.w	lr, [r0, #48]	; 0x30\n",
-  "  8e:	47f0      	blx	lr\n",
-  "  90:	f8dd c02c 	ldr.w	ip, [sp, #44]	; 0x2c\n",
-  "  94:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  98:	f8d9 c200 	ldr.w	ip, [r9, #512]	; 0x200\n",
-  "  9c:	f8cd c02c 	str.w	ip, [sp, #44]	; 0x2c\n",
-  "  a0:	f8dd c02c 	ldr.w	ip, [sp, #44]	; 0x2c\n",
-  "  a4:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  a8:	4648      	mov	r0, r9\n",
-  "  aa:	f8cd 9030 	str.w	r9, [sp, #48]	; 0x30\n",
-  "  ae:	4604      	mov	r4, r0\n",
-  "  b0:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  b4:	bf18      	it	ne\n",
-  "  b6:	f10d 0c30 	addne.w	ip, sp, #48	; 0x30\n",
-  "  ba:	f10d 0c30 	add.w	ip, sp, #48	; 0x30\n",
-  "  be:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  c2:	bf0c      	ite	eq\n",
-  "  c4:	2000      	moveq	r0, #0\n",
-  "  c6:	a80c      	addne	r0, sp, #48	; 0x30\n",
-  "  c8:	f8dd c040 	ldr.w	ip, [sp, #64]	; 0x40\n",
-  "  cc:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  d0:	bf18      	it	ne\n",
-  "  d2:	f10d 0c40 	addne.w	ip, sp, #64	; 0x40\n",
-  "  d6:	f8cd c030 	str.w	ip, [sp, #48]	; 0x30\n",
-  "  da:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  de:	bf0c      	ite	eq\n",
-  "  e0:	2000      	moveq	r0, #0\n",
-  "  e2:	4668      	movne	r0, sp\n",
-  "  e4:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  e8:	bf0c      	ite	eq\n",
-  "  ea:	2000      	moveq	r0, #0\n",
-  "  ec:	f20d 4001 	addwne	r0, sp, #1025	; 0x401\n",
-  "  f0:	f1bc 0f00 	cmp.w	ip, #0\n",
-  "  f4:	bf18      	it	ne\n",
-  "  f6:	f20d 4c01 	addwne	ip, sp, #1025	; 0x401\n",
-  "  fa:	f8d9 c0a4 	ldr.w	ip, [r9, #164]	; 0xa4\n",
-  "  fe:	f1bc 0f00 	cmp.w	ip, #0\n",
-  " 102:	d171      	bne.n	1e8 <VixlJniHelpers+0x1e8>\n",
-  " 104:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 108:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 10c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 110:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 114:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 118:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 11c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 120:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 124:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 128:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 12c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 130:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 134:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 138:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 13c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 140:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 144:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 148:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 14c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 150:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 154:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 158:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 15c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 160:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 164:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 168:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 16c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 170:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 174:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 178:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 17c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 180:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 184:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 188:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 18c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 190:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 194:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 198:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 19c:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1a0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1a4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1a8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1ac:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1b0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1b4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1b8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1bc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1c0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1c4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1c8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1cc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1d0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1d4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1d8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1dc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1e0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1e4:	f000 b802 	b.w	1ec <VixlJniHelpers+0x1ec>\n",
-  " 1e8:	f000 b81b 	b.w	222 <VixlJniHelpers+0x222>\n",
-  " 1ec:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1f0:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1f4:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1f8:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 1fc:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 200:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 204:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 208:	f8cd c7ff 	str.w	ip, [sp, #2047]	; 0x7ff\n",
-  " 20c:	f50d 5d80 	add.w	sp, sp, #4096	; 0x1000\n",
-  " 210:	b008      	add	sp, #32\n",
-  " 212:	b009      	add	sp, #36	; 0x24\n",
-  " 214:	ecbd 8a10 	vpop	{s16-s31}\n",
-  " 218:	e8bd 4de0 	ldmia.w	sp!, {r5, r6, r7, r8, sl, fp, lr}\n",
-  " 21c:	f8d9 8034 	ldr.w	r8, [r9, #52]	; 0x34\n",
-  " 220:	4770      	bx	lr\n",
-  " 222:	4660      	mov	r0, ip\n",
-  " 224:	f8d9 e2e8 	ldr.w	lr, [r9, #744]	; 0x2e8\n",
-  " 228:	47f0      	blx	lr\n",
-  nullptr
+const char* const VixlJniHelpersResults = {
+  "   0: e92d 4de0  stmdb sp!, {r5, r6, r7, r8, sl, fp, lr}\n"
+  "   4: ed2d 8a10  vpush {s16-s31}\n"
+  "   8: b089       sub sp, #36 ; 0x24\n"
+  "   a: 9000       str r0, [sp, #0]\n"
+  "   c: 9121       str r1, [sp, #132] ; 0x84\n"
+  "   e: ed8d 0a22  vstr s0, [sp, #136] ; 0x88\n"
+  "  12: 9223       str r2, [sp, #140] ; 0x8c\n"
+  "  14: 9324       str r3, [sp, #144] ; 0x90\n"
+  "  16: b088       sub sp, #32\n"
+  "  18: f5ad 5d80  sub.w sp, sp, #4096 ; 0x1000\n"
+  "  1c: 9808       ldr r0, [sp, #32]\n"
+  "  1e: 981f       ldr r0, [sp, #124] ; 0x7c\n"
+  "  20: 9821       ldr r0, [sp, #132] ; 0x84\n"
+  "  22: 98ff       ldr r0, [sp, #1020] ; 0x3fc\n"
+  "  24: f8dd 0400  ldr.w r0, [sp, #1024] ; 0x400\n"
+  "  28: f8dd cffc  ldr.w ip, [sp, #4092] ; 0xffc\n"
+  "  2c: f50d 5c80  add.w ip, sp, #4096 ; 0x1000\n"
+  "  30: f8dc c000  ldr.w ip, [ip]\n"
+  "  34: f8d9 c200  ldr.w ip, [r9, #512] ; 0x200\n"
+  "  38: f8dc 0080  ldr.w r0, [ip, #128] ; 0x80\n"
+  "  3c: 9008       str r0, [sp, #32]\n"
+  "  3e: 901f       str r0, [sp, #124] ; 0x7c\n"
+  "  40: 9021       str r0, [sp, #132] ; 0x84\n"
+  "  42: 90ff       str r0, [sp, #1020] ; 0x3fc\n"
+  "  44: f8cd 0400  str.w r0, [sp, #1024] ; 0x400\n"
+  "  48: f8cd cffc  str.w ip, [sp, #4092] ; 0xffc\n"
+  "  4c: f84d 5d04  str.w r5, [sp, #-4]!\n"
+  "  50: f50d 5580  add.w r5, sp, #4096 ; 0x1000\n"
+  "  54: f8c5 c004  str.w ip, [r5, #4]\n"
+  "  58: f85d 5b04  ldr.w r5, [sp], #4\n"
+  "  5c: f04f 0cff  mov.w ip, #255 ; 0xff\n"
+  "  60: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  64: f06f 4c7f  mvn.w ip, #4278190080 ; 0xff000000\n"
+  "  68: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  6c: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  70: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  74: 900c       str r0, [sp, #48] ; 0x30\n"
+  "  76: f8dd c030  ldr.w ip, [sp, #48] ; 0x30\n"
+  "  7a: f8cd c034  str.w ip, [sp, #52] ; 0x34\n"
+  "  7e: f50d 5c80  add.w ip, sp, #4096 ; 0x1000\n"
+  "  82: f8c9 c200  str.w ip, [r9, #512] ; 0x200\n"
+  "  86: f8c9 d200  str.w sp, [r9, #512] ; 0x200\n"
+  "  8a: f8d0 e030  ldr.w lr, [r0, #48] ; 0x30\n"
+  "  8e: 47f0       blx lr\n"
+  "  90: f8dd c02c  ldr.w ip, [sp, #44] ; 0x2c\n"
+  "  94: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  98: f8d9 c200  ldr.w ip, [r9, #512] ; 0x200\n"
+  "  9c: f8cd c02c  str.w ip, [sp, #44] ; 0x2c\n"
+  "  a0: f8dd c02c  ldr.w ip, [sp, #44] ; 0x2c\n"
+  "  a4: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  a8: 4648       mov r0, r9\n"
+  "  aa: f8cd 9030  str.w r9, [sp, #48] ; 0x30\n"
+  "  ae: 4604       mov r4, r0\n"
+  "  b0: f1bc 0f00  cmp.w ip, #0\n"
+  "  b4: bf18       it ne\n"
+  "  b6: f10d 0c30  addne.w ip, sp, #48 ; 0x30\n"
+  "  ba: f10d 0c30  add.w ip, sp, #48 ; 0x30\n"
+  "  be: f1bc 0f00  cmp.w ip, #0\n"
+  "  c2: bf0c       ite eq\n"
+  "  c4: 2000       moveq r0, #0\n"
+  "  c6: a80c       addne r0, sp, #48 ; 0x30\n"
+  "  c8: f8dd c040  ldr.w ip, [sp, #64] ; 0x40\n"
+  "  cc: f1bc 0f00  cmp.w ip, #0\n"
+  "  d0: bf18       it ne\n"
+  "  d2: f10d 0c40  addne.w ip, sp, #64 ; 0x40\n"
+  "  d6: f8cd c030  str.w ip, [sp, #48] ; 0x30\n"
+  "  da: f1bc 0f00  cmp.w ip, #0\n"
+  "  de: bf0c       ite eq\n"
+  "  e0: 2000       moveq r0, #0\n"
+  "  e2: 4668       movne r0, sp\n"
+  "  e4: f1bc 0f00  cmp.w ip, #0\n"
+  "  e8: bf0c       ite eq\n"
+  "  ea: 2000       moveq r0, #0\n"
+  "  ec: f20d 4001  addwne r0, sp, #1025 ; 0x401\n"
+  "  f0: f1bc 0f00  cmp.w ip, #0\n"
+  "  f4: bf18       it ne\n"
+  "  f6: f20d 4c01  addwne ip, sp, #1025 ; 0x401\n"
+  "  fa: f8d9 c0a4  ldr.w ip, [r9, #164] ; 0xa4\n"
+  "  fe: f1bc 0f00  cmp.w ip, #0\n"
+  " 102: d171       bne.n 0x1e8\n"
+  " 104: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 108: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 10c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 110: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 114: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 118: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 11c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 120: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 124: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 128: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 12c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 130: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 134: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 138: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 13c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 140: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 144: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 148: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 14c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 150: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 154: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 158: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 15c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 160: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 164: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 168: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 16c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 170: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 174: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 178: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 17c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 180: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 184: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 188: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 18c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 190: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 194: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 198: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 19c: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1a0: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1a4: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1a8: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1ac: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1b0: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1b4: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1b8: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1bc: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1c0: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1c4: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1c8: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1cc: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1d0: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1d4: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1d8: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1dc: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1e0: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1e4: f000 b802  b.w 0x1ec\n"
+  " 1e8: f000 b81b  b.w 0x222\n"
+  " 1ec: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1f0: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1f4: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1f8: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 1fc: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 200: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 204: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 208: f8cd c7ff  str.w ip, [sp, #2047] ; 0x7ff\n"
+  " 20c: f50d 5d80  add.w sp, sp, #4096 ; 0x1000\n"
+  " 210: b008       add sp, #32\n"
+  " 212: b009       add sp, #36 ; 0x24\n"
+  " 214: ecbd 8a10  vpop {s16-s31}\n"
+  " 218: e8bd 4de0  ldmia.w sp!, {r5, r6, r7, r8, sl, fp, lr}\n"
+  " 21c: f8d9 8034  ldr.w r8, [r9, #52] ; 0x34\n"
+  " 220: 4770       bx lr\n"
+  " 222: 4660       mov r0, ip\n"
+  " 224: f8d9 e2e8  ldr.w lr, [r9, #744] ; 0x2e8\n"
+  " 228: 47f0       blx lr\n"
 };
 
-const char* const VixlLoadFromOffsetResults[] = {
-  "   0:  68e2        ldr r2, [r4, #12]\n",
-  "   2:  f8d4 2fff   ldr.w r2, [r4, #4095] ; 0xfff\n",
-  "   6:  f504 5280   add.w r2, r4, #4096 ; 0x1000\n",
-  "   a:  6812        ldr r2, [r2, #0]\n",
-  "   c:  f504 1280   add.w r2, r4, #1048576  ; 0x100000\n",
-  "  10:  f8d2 20a4   ldr.w r2, [r2, #164]  ; 0xa4\n",
-  "  14:  f44f 5280   mov.w r2, #4096 ; 0x1000\n",
-  "  18:  f2c0 0210   movt  r2, #16\n",
-  "  1c:  4422        add r2, r4\n",
-  "  1e:  6812        ldr r2, [r2, #0]\n",
-  "  20:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  24:  f2c0 0c10   movt  ip, #16\n",
-  "  28:  4464        add r4, ip\n",
-  "  2a:  6824        ldr r4, [r4, #0]\n",
-  "  2c:  89a2        ldrh  r2, [r4, #12]\n",
-  "  2e:  f8b4 2fff   ldrh.w  r2, [r4, #4095] ; 0xfff\n",
-  "  32:  f504 5280   add.w r2, r4, #4096 ; 0x1000\n",
-  "  36:  8812        ldrh  r2, [r2, #0]\n",
-  "  38:  f504 1280   add.w r2, r4, #1048576  ; 0x100000\n",
-  "  3c:  f8b2 20a4   ldrh.w  r2, [r2, #164]  ; 0xa4\n",
-  "  40:  f44f 5280   mov.w r2, #4096 ; 0x1000\n",
-  "  44:  f2c0 0210   movt  r2, #16\n",
-  "  48:  4422        add r2, r4\n",
-  "  4a:  8812        ldrh  r2, [r2, #0]\n",
-  "  4c:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  50:  f2c0 0c10   movt  ip, #16\n",
-  "  54:  4464        add r4, ip\n",
-  "  56:  8824        ldrh  r4, [r4, #0]\n",
-  "  58:  e9d4 2303   ldrd  r2, r3, [r4, #12]\n",
-  "  5c:  e9d4 23ff   ldrd  r2, r3, [r4, #1020] ; 0x3fc\n",
-  "  60:  f504 6280   add.w r2, r4, #1024 ; 0x400\n",
-  "  64:  e9d2 2300   ldrd  r2, r3, [r2]\n",
-  "  68:  f504 2280   add.w r2, r4, #262144 ; 0x40000\n",
-  "  6c:  e9d2 2329   ldrd  r2, r3, [r2, #164]  ; 0xa4\n",
-  "  70:  f44f 6280   mov.w r2, #1024 ; 0x400\n",
-  "  74:  f2c0 0204   movt  r2, #4\n",
-  "  78:  4422        add r2, r4\n",
-  "  7a:  e9d2 2300   ldrd  r2, r3, [r2]\n",
-  "  7e:  f44f 6c80   mov.w ip, #1024 ; 0x400\n",
-  "  82:  f2c0 0c04   movt  ip, #4\n",
-  "  86:  4464        add r4, ip\n",
-  "  88:  e9d4 4500   ldrd  r4, r5, [r4]\n",
-  "  8c:  f8dc 000c   ldr.w r0, [ip, #12]\n",
-  "  90:  f5a4 1280   sub.w r2, r4, #1048576  ; 0x100000\n",
-  "  94:  f8d2 20a4   ldr.w r2, [r2, #164]  ; 0xa4\n",
-  "  98:  f994 200c   ldrsb.w r2, [r4, #12]\n",
-  "  9c:  7b22        ldrb  r2, [r4, #12]\n",
-  "  9e:  f9b4 200c   ldrsh.w r2, [r4, #12]\n",
-  nullptr
-};
-const char* const VixlStoreToOffsetResults[] = {
-  "   0:  60e2        str r2, [r4, #12]\n",
-  "   2:  f8c4 2fff   str.w r2, [r4, #4095] ; 0xfff\n",
-  "   6:  f504 5c80   add.w ip, r4, #4096 ; 0x1000\n",
-  "   a:  f8cc 2000   str.w r2, [ip]\n",
-  "   e:  f504 1c80   add.w ip, r4, #1048576  ; 0x100000\n",
-  "  12:  f8cc 20a4   str.w r2, [ip, #164]  ; 0xa4\n",
-  "  16:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  1a:  f2c0 0c10   movt  ip, #16\n",
-  "  1e:  44a4        add ip, r4\n",
-  "  20:  f8cc 2000   str.w r2, [ip]\n",
-  "  24:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  28:  f2c0 0c10   movt  ip, #16\n",
-  "  2c:  44a4        add ip, r4\n",
-  "  2e:  f8cc 4000   str.w r4, [ip]\n",
-  "  32:  81a2        strh  r2, [r4, #12]\n",
-  "  34:  f8a4 2fff   strh.w  r2, [r4, #4095] ; 0xfff\n",
-  "  38:  f504 5c80   add.w ip, r4, #4096 ; 0x1000\n",
-  "  3c:  f8ac 2000   strh.w  r2, [ip]\n",
-  "  40:  f504 1c80   add.w ip, r4, #1048576  ; 0x100000\n",
-  "  44:  f8ac 20a4   strh.w  r2, [ip, #164]  ; 0xa4\n",
-  "  48:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  4c:  f2c0 0c10   movt  ip, #16\n",
-  "  50:  44a4        add ip, r4\n",
-  "  52:  f8ac 2000   strh.w  r2, [ip]\n",
-  "  56:  f44f 5c80   mov.w ip, #4096 ; 0x1000\n",
-  "  5a:  f2c0 0c10   movt  ip, #16\n",
-  "  5e:  44a4        add ip, r4\n",
-  "  60:  f8ac 4000   strh.w  r4, [ip]\n",
-  "  64:  e9c4 2303   strd  r2, r3, [r4, #12]\n",
-  "  68:  e9c4 23ff   strd  r2, r3, [r4, #1020] ; 0x3fc\n",
-  "  6c:  f504 6c80   add.w ip, r4, #1024 ; 0x400\n",
-  "  70:  e9cc 2300   strd  r2, r3, [ip]\n",
-  "  74:  f504 2c80   add.w ip, r4, #262144 ; 0x40000\n",
-  "  78:  e9cc 2329   strd  r2, r3, [ip, #164]  ; 0xa4\n",
-  "  7c:  f44f 6c80   mov.w ip, #1024 ; 0x400\n",
-  "  80:  f2c0 0c04   movt  ip, #4\n",
-  "  84:  44a4        add ip, r4\n",
-  "  86:  e9cc 2300   strd  r2, r3, [ip]\n",
-  "  8a:  f44f 6c80   mov.w ip, #1024 ; 0x400\n",
-  "  8e:  f2c0 0c04   movt  ip, #4\n",
-  "  92:  44a4        add ip, r4\n",
-  "  94:  e9cc 4500   strd  r4, r5, [ip]\n",
-  "  98:  f8cc 000c   str.w r0, [ip, #12]\n",
-  "  9c:  f5a4 1c80   sub.w ip, r4, #1048576  ; 0x100000\n",
-  "  a0:  f8cc 20a4   str.w r2, [ip, #164]  ; 0xa4\n",
-  "  a4:  7322        strb  r2, [r4, #12]\n",
-  nullptr
+const char* const VixlLoadFromOffsetResults = {
+  "   0: 68e2       ldr r2, [r4, #12]\n"
+  "   2: f8d4 2fff  ldr.w r2, [r4, #4095] ; 0xfff\n"
+  "   6: f504 5280  add.w r2, r4, #4096 ; 0x1000\n"
+  "   a: 6812       ldr r2, [r2, #0]\n"
+  "   c: f504 1280  add.w r2, r4, #1048576 ; 0x100000\n"
+  "  10: f8d2 20a4  ldr.w r2, [r2, #164] ; 0xa4\n"
+  "  14: f44f 5280  mov.w r2, #4096 ; 0x1000\n"
+  "  18: f2c0 0210  movt r2, #16\n"
+  "  1c: 4422       add r2, r4\n"
+  "  1e: 6812       ldr r2, [r2, #0]\n"
+  "  20: f44f 5c80  mov.w ip, #4096 ; 0x1000\n"
+  "  24: f2c0 0c10  movt ip, #16\n"
+  "  28: 4464       add r4, ip\n"
+  "  2a: 6824       ldr r4, [r4, #0]\n"
+  "  2c: 89a2       ldrh r2, [r4, #12]\n"
+  "  2e: f8b4 2fff  ldrh.w r2, [r4, #4095] ; 0xfff\n"
+  "  32: f504 5280  add.w r2, r4, #4096 ; 0x1000\n"
+  "  36: 8812       ldrh r2, [r2, #0]\n"
+  "  38: f504 1280  add.w r2, r4, #1048576 ; 0x100000\n"
+  "  3c: f8b2 20a4  ldrh.w r2, [r2, #164] ; 0xa4\n"
+  "  40: f44f 5280  mov.w r2, #4096 ; 0x1000\n"
+  "  44: f2c0 0210  movt r2, #16\n"
+  "  48: 4422       add r2, r4\n"
+  "  4a: 8812       ldrh r2, [r2, #0]\n"
+  "  4c: f44f 5c80  mov.w ip, #4096 ; 0x1000\n"
+  "  50: f2c0 0c10  movt ip, #16\n"
+  "  54: 4464       add r4, ip\n"
+  "  56: 8824       ldrh r4, [r4, #0]\n"
+  "  58: e9d4 2303  ldrd r2, r3, [r4, #12]\n"
+  "  5c: e9d4 23ff  ldrd r2, r3, [r4, #1020] ; 0x3fc\n"
+  "  60: f504 6280  add.w r2, r4, #1024 ; 0x400\n"
+  "  64: e9d2 2300  ldrd r2, r3, [r2]\n"
+  "  68: f504 2280  add.w r2, r4, #262144 ; 0x40000\n"
+  "  6c: e9d2 2329  ldrd r2, r3, [r2, #164] ; 0xa4\n"
+  "  70: f44f 6280  mov.w r2, #1024 ; 0x400\n"
+  "  74: f2c0 0204  movt r2, #4\n"
+  "  78: 4422       add r2, r4\n"
+  "  7a: e9d2 2300  ldrd r2, r3, [r2]\n"
+  "  7e: f44f 6c80  mov.w ip, #1024 ; 0x400\n"
+  "  82: f2c0 0c04  movt ip, #4\n"
+  "  86: 4464       add r4, ip\n"
+  "  88: e9d4 4500  ldrd r4, r5, [r4]\n"
+  "  8c: f8dc 000c  ldr.w r0, [ip, #12]\n"
+  "  90: f5a4 1280  sub.w r2, r4, #1048576 ; 0x100000\n"
+  "  94: f8d2 20a4  ldr.w r2, [r2, #164] ; 0xa4\n"
+  "  98: f994 200c  ldrsb.w r2, [r4, #12]\n"
+  "  9c: 7b22       ldrb r2, [r4, #12]\n"
+  "  9e: f9b4 200c  ldrsh.w r2, [r4, #12]\n"
 };
 
-std::map<std::string, const char* const*> test_results;
-void setup_results() {
-    test_results["VixlJniHelpers"] = VixlJniHelpersResults;
-    test_results["VixlStoreToOffset"] = VixlStoreToOffsetResults;
-    test_results["VixlLoadFromOffset"] = VixlLoadFromOffsetResults;
-}
+const char* const VixlStoreToOffsetResults = {
+  "   0: 60e2       str r2, [r4, #12]\n"
+  "   2: f8c4 2fff  str.w r2, [r4, #4095] ; 0xfff\n"
+  "   6: f504 5c80  add.w ip, r4, #4096 ; 0x1000\n"
+  "   a: f8cc 2000  str.w r2, [ip]\n"
+  "   e: f504 1c80  add.w ip, r4, #1048576 ; 0x100000\n"
+  "  12: f8cc 20a4  str.w r2, [ip, #164] ; 0xa4\n"
+  "  16: f44f 5c80  mov.w ip, #4096 ; 0x1000\n"
+  "  1a: f2c0 0c10  movt ip, #16\n"
+  "  1e: 44a4       add ip, r4\n"
+  "  20: f8cc 2000  str.w r2, [ip]\n"
+  "  24: f44f 5c80  mov.w ip, #4096 ; 0x1000\n"
+  "  28: f2c0 0c10  movt ip, #16\n"
+  "  2c: 44a4       add ip, r4\n"
+  "  2e: f8cc 4000  str.w r4, [ip]\n"
+  "  32: 81a2       strh r2, [r4, #12]\n"
+  "  34: f8a4 2fff  strh.w r2, [r4, #4095] ; 0xfff\n"
+  "  38: f504 5c80  add.w ip, r4, #4096 ; 0x1000\n"
+  "  3c: f8ac 2000  strh.w r2, [ip]\n"
+  "  40: f504 1c80  add.w ip, r4, #1048576 ; 0x100000\n"
+  "  44: f8ac 20a4  strh.w r2, [ip, #164] ; 0xa4\n"
+  "  48: f44f 5c80  mov.w ip, #4096 ; 0x1000\n"
+  "  4c: f2c0 0c10  movt ip, #16\n"
+  "  50: 44a4       add ip, r4\n"
+  "  52: f8ac 2000  strh.w r2, [ip]\n"
+  "  56: f44f 5c80  mov.w ip, #4096 ; 0x1000\n"
+  "  5a: f2c0 0c10  movt ip, #16\n"
+  "  5e: 44a4       add ip, r4\n"
+  "  60: f8ac 4000  strh.w r4, [ip]\n"
+  "  64: e9c4 2303  strd r2, r3, [r4, #12]\n"
+  "  68: e9c4 23ff  strd r2, r3, [r4, #1020] ; 0x3fc\n"
+  "  6c: f504 6c80  add.w ip, r4, #1024 ; 0x400\n"
+  "  70: e9cc 2300  strd r2, r3, [ip]\n"
+  "  74: f504 2c80  add.w ip, r4, #262144 ; 0x40000\n"
+  "  78: e9cc 2329  strd r2, r3, [ip, #164] ; 0xa4\n"
+  "  7c: f44f 6c80  mov.w ip, #1024 ; 0x400\n"
+  "  80: f2c0 0c04  movt ip, #4\n"
+  "  84: 44a4       add ip, r4\n"
+  "  86: e9cc 2300  strd r2, r3, [ip]\n"
+  "  8a: f44f 6c80  mov.w ip, #1024 ; 0x400\n"
+  "  8e: f2c0 0c04  movt ip, #4\n"
+  "  92: 44a4       add ip, r4\n"
+  "  94: e9cc 4500  strd r4, r5, [ip]\n"
+  "  98: f8cc 000c  str.w r0, [ip, #12]\n"
+  "  9c: f5a4 1c80  sub.w ip, r4, #1048576 ; 0x100000\n"
+  "  a0: f8cc 20a4  str.w r2, [ip, #164] ; 0xa4\n"
+  "  a4: 7322       strb r2, [r4, #12]\n"
+};
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index 043d35e..c6a593c 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -141,49 +141,69 @@
   CHECK_EQ(0, unlink_result);
 }
 
-void CommonArtTestImpl::SetUpAndroidRootEnvVars() {
-  if (IsHost()) {
-    // Look at how we were invoked to extract reasonable default paths.
-    std::string argv;
-    if (android::base::ReadFileToString("/proc/self/cmdline", &argv)) {
-      // /proc/self/cmdline is the programs 'argv' with elements delimited by '\0'.
-      std::filesystem::path path(argv.substr(0, argv.find('\0')));
-      path = std::filesystem::absolute(path);
-      // Walk up until we find the one of the well-known directories.
-      for (; path.parent_path() != path; path = path.parent_path()) {
-        // We are running tests from out/host/linux-x86 on developer machine.
-        if (path.filename() == std::filesystem::path("linux-x86")) {
-          char* cwd = getcwd(nullptr, 0);
-          setenv("ANDROID_BUILD_TOP", cwd, /*overwrite=*/ 0);  // No-op if already set.
-          free(cwd);
-          setenv("ANDROID_HOST_OUT", path.c_str(), /*overwrite=*/ 0);  // No-op if already set.
-          break;
-        }
-        // We are running tests from testcases (extracted from zip) on tradefed.
-        if (path.filename() == std::filesystem::path("testcases")) {
-          path.append("art_common");
-          bool ok = chdir(path.c_str()) == 0;
-          CHECK(ok);
-          setenv("ANDROID_BUILD_TOP", path.c_str(), /*overwrite=*/ 0);  // No-op if already set.
-          path.append("out/host/linux-x86");
-          setenv("ANDROID_HOST_OUT", path.c_str(), /*overwrite=*/ 0);  // No-op if already set.
-          break;
-        }
+std::string CommonArtTestImpl::GetAndroidBuildTop() {
+  CHECK(IsHost());
+  std::string android_build_top;
+
+  // Look at how we were invoked to find the expected directory.
+  std::string argv;
+  if (android::base::ReadFileToString("/proc/self/cmdline", &argv)) {
+    // /proc/self/cmdline is the programs 'argv' with elements delimited by '\0'.
+    std::filesystem::path path(argv.substr(0, argv.find('\0')));
+    path = std::filesystem::absolute(path);
+    // Walk up until we find the one of the well-known directories.
+    for (; path.parent_path() != path; path = path.parent_path()) {
+      // We are running tests from out/host/linux-x86 on developer machine.
+      if (path.filename() == std::filesystem::path("linux-x86")) {
+        android_build_top = path.parent_path().parent_path().parent_path();
+        break;
+      }
+      // We are running tests from testcases (extracted from zip) on tradefed.
+      if (path.filename() == std::filesystem::path("testcases")) {
+        android_build_top = path.append("art_common");
+        break;
       }
     }
-    const char* android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
-    DCHECK(android_build_top_from_env != nullptr);
-    DCHECK(std::filesystem::exists(android_build_top_from_env)) << android_build_top_from_env;
-    const char* android_host_out_from_env = getenv("ANDROID_HOST_OUT");
-    DCHECK(android_host_out_from_env != nullptr);
-    DCHECK(std::filesystem::exists(android_host_out_from_env)) << android_host_out_from_env;
+  }
+  CHECK(!android_build_top.empty());
+
+  // Check that the expected directory matches the environment variable.
+  const char* android_build_top_from_env = getenv("ANDROID_BUILD_TOP");
+  if (android_build_top_from_env != nullptr) {
+    CHECK_EQ(android_build_top, android_build_top_from_env);
+  } else {
+    setenv("ANDROID_BUILD_TOP", android_build_top.c_str(), /*overwrite=*/0);
+  }
+  if (android_build_top.back() != '/') {
+    android_build_top += '/';
+  }
+  return android_build_top;
+}
+
+std::string CommonArtTestImpl::GetAndroidHostOut() {
+  CHECK(IsHost());
+  std::string android_host_out = GetAndroidBuildTop() + "out/host/linux-x86";
+
+  // Check that the expected directory matches the environment variable.
+  const char* android_host_out_from_env = getenv("ANDROID_HOST_OUT");
+  if (android_host_out_from_env != nullptr) {
+    CHECK_EQ(android_host_out, android_host_out_from_env);
+  } else {
+    setenv("ANDROID_HOST_OUT", android_host_out.c_str(), /*overwrite=*/0);
+  }
+  return android_host_out;
+}
+
+void CommonArtTestImpl::SetUpAndroidRootEnvVars() {
+  if (IsHost()) {
+    std::string android_host_out = GetAndroidHostOut();
 
     // Environment variable ANDROID_ROOT is set on the device, but not
     // necessarily on the host.
     const char* android_root_from_env = getenv("ANDROID_ROOT");
     if (android_root_from_env == nullptr) {
       // Use ANDROID_HOST_OUT for ANDROID_ROOT.
-      setenv("ANDROID_ROOT", android_host_out_from_env, 1);
+      setenv("ANDROID_ROOT", android_host_out.c_str(), 1);
       android_root_from_env = getenv("ANDROID_ROOT");
     }
 
@@ -193,7 +213,7 @@
     const char* android_i18n_root_from_env = getenv("ANDROID_I18N_ROOT");
     if (android_i18n_root_from_env == nullptr) {
       // Use ${ANDROID_I18N_OUT}/com.android.i18n for ANDROID_I18N_ROOT.
-      std::string android_i18n_root = android_host_out_from_env;
+      std::string android_i18n_root = android_host_out.c_str();
       android_i18n_root += "/com.android.i18n";
       setenv("ANDROID_I18N_ROOT", android_i18n_root.c_str(), 1);
     }
@@ -204,7 +224,7 @@
     const char* android_art_root_from_env = getenv("ANDROID_ART_ROOT");
     if (android_art_root_from_env == nullptr) {
       // Use ${ANDROID_HOST_OUT}/com.android.art for ANDROID_ART_ROOT.
-      std::string android_art_root = android_host_out_from_env;
+      std::string android_art_root = android_host_out.c_str();
       android_art_root += "/com.android.art";
       setenv("ANDROID_ART_ROOT", android_art_root.c_str(), 1);
     }
@@ -215,7 +235,7 @@
     const char* android_tzdata_root_from_env = getenv("ANDROID_TZDATA_ROOT");
     if (android_tzdata_root_from_env == nullptr) {
       // Use ${ANDROID_HOST_OUT}/com.android.tzdata for ANDROID_TZDATA_ROOT.
-      std::string android_tzdata_root = android_host_out_from_env;
+      std::string android_tzdata_root = android_host_out.c_str();
       android_tzdata_root += "/com.android.tzdata";
       setenv("ANDROID_TZDATA_ROOT", android_tzdata_root.c_str(), 1);
     }
@@ -278,59 +298,30 @@
   }
 }
 
-std::string CommonArtTestImpl::GetAndroidBuildTop() {
-  std::string root;
-  const char* android_build_top = getenv("ANDROID_BUILD_TOP");
-  if (android_build_top != nullptr) {
-    root = android_build_top;
-  } else {
-    // Not set by build server, so default to current directory
-    char* cwd = getcwd(nullptr, 0);
-    setenv("ANDROID_BUILD_TOP", cwd, 1);
-    root = cwd;
-    free(cwd);
+// Get prebuilt binary tool.
+// The paths need to be updated when Android prebuilts update.
+std::string CommonArtTestImpl::GetAndroidTool(const char* name, InstructionSet isa) {
+  std::string path = GetAndroidBuildTop() + "prebuilts/gcc/linux-x86/";
+  switch (isa) {
+    case InstructionSet::kX86:
+    case InstructionSet::kX86_64:
+      path += "host/x86_64-linux-glibc2.17-4.8/x86_64-linux/bin/";
+      break;
+    case InstructionSet::kArm:
+    case InstructionSet::kThumb2:
+      path += "arm/arm-linux-androideabi-4.9/arm-linux-androideabi/bin/";
+      break;
+    case InstructionSet::kArm64:
+      path += "aarch64/aarch64-linux-android-4.9/aarch64-linux-android/bin/";
+      break;
+    default:
+      LOG(FATAL) << "Unknown ISA: " << isa;
+      break;
   }
-  CHECK(!root.empty());
-  if (root.back() != '/') {
-    root += '/';
-  }
-  return root;
-}
-
-// Helper - find directory with the following format:
-// ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
-std::string CommonArtTestImpl::GetAndroidToolsDir(const std::string& subdir1,
-                                                  const std::string& subdir2,
-                                                  const std::string& subdir3) {
-  std::string toolsdir = GetAndroidBuildTop() + subdir1;
-  std::string founddir;
-  DIR* dir;
-  if ((dir = opendir(toolsdir.c_str())) != nullptr) {
-    float maxversion = 0;
-    struct dirent* entry;
-    while ((entry = readdir(dir)) != nullptr) {
-      std::string format = subdir2 + "-%f";
-      float version;
-      if (std::sscanf(entry->d_name, format.c_str(), &version) == 1) {
-        if (version > maxversion) {
-          maxversion = version;
-          founddir = toolsdir + "/" + entry->d_name + "/" + subdir3 + "/bin/";
-        }
-      }
-    }
-    closedir(dir);
-  }
-
-  if (founddir.empty()) {
-    ADD_FAILURE() << "Cannot find Android tools directory.";
-  }
-  return founddir;
-}
-
-std::string CommonArtTestImpl::GetAndroidHostToolsDir() {
-  return GetAndroidToolsDir("prebuilts/gcc/linux-x86/host",
-                            "x86_64-linux-glibc2.17",
-                            "x86_64-linux");
+  CHECK(OS::DirectoryExists(path.c_str())) << path;
+  path += name;
+  CHECK(OS::FileExists(path.c_str())) << path;
+  return path;
 }
 
 std::string CommonArtTestImpl::GetCoreArtLocation() {
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index fe045ca..b4e0c5a 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -194,9 +194,6 @@
   static std::string GetClassPathOption(const char* option,
                                         const std::vector<std::string>& class_path);
 
-  // Returns bin directory which contains host's prebuild tools.
-  static std::string GetAndroidHostToolsDir();
-
   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
   std::string GetTestDexFileName(const char* name) const;
 
@@ -249,6 +246,9 @@
                                        const PostForkFn& post_fork,
                                        std::string* output);
 
+  // Helper - find prebuilt tool (e.g. objdump).
+  static std::string GetAndroidTool(const char* name, InstructionSet isa = InstructionSet::kX86_64);
+
  protected:
   static bool IsHost() {
     return !kIsTargetBuild;
@@ -257,11 +257,8 @@
   // Returns ${ANDROID_BUILD_TOP}. Ensure it has tailing /.
   static std::string GetAndroidBuildTop();
 
-  // Helper - find directory with the following format:
-  // ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
-  static std::string GetAndroidToolsDir(const std::string& subdir1,
-                                        const std::string& subdir2,
-                                        const std::string& subdir3);
+  // Returns ${ANDROID_HOST_OUT}.
+  static std::string GetAndroidHostOut();
 
   // File location to boot.art, e.g. /apex/com.android.art/javalib/boot.art
   static std::string GetCoreArtLocation();
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index c4e83b9..1d37a42 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -80,29 +80,6 @@
   runtime_.reset();
 }
 
-std::string CommonRuntimeTestImpl::GetAndroidTargetToolsDir(InstructionSet isa) {
-  switch (isa) {
-    case InstructionSet::kArm:
-    case InstructionSet::kThumb2:
-      return GetAndroidToolsDir("prebuilts/gcc/linux-x86/arm",
-                                "arm-linux-androideabi",
-                                "arm-linux-androideabi");
-    case InstructionSet::kArm64:
-      return GetAndroidToolsDir("prebuilts/gcc/linux-x86/aarch64",
-                                "aarch64-linux-android",
-                                "aarch64-linux-android");
-    case InstructionSet::kX86:
-    case InstructionSet::kX86_64:
-      return GetAndroidToolsDir("prebuilts/gcc/linux-x86/x86",
-                                "x86_64-linux-android",
-                                "x86_64-linux-android");
-    default:
-      break;
-  }
-  ADD_FAILURE() << "Invalid isa " << isa;
-  return "";
-}
-
 void CommonRuntimeTestImpl::SetUp() {
   CommonArtTestImpl::SetUp();
 
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 797846e..47031a3 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -75,8 +75,6 @@
   CommonRuntimeTestImpl();
   virtual ~CommonRuntimeTestImpl();
 
-  static std::string GetAndroidTargetToolsDir(InstructionSet isa);
-
   // A helper function to fill the heap.
   static void FillHeap(Thread* self,
                        ClassLinker* class_linker,
diff --git a/runtime/prebuilt_tools_test.cc b/runtime/prebuilt_tools_test.cc
index 158d9d6..15b115a 100644
--- a/runtime/prebuilt_tools_test.cc
+++ b/runtime/prebuilt_tools_test.cc
@@ -26,39 +26,24 @@
 #ifndef ART_TARGET_ANDROID
 
 class PrebuiltToolsTest : public CommonRuntimeTest {
-};
-
-static void CheckToolsExist(const std::string& tools_dir) {
-  const char* tools[] = { "as", "objcopy", "objdump" };
-  for (const char* tool : tools) {
-    struct stat exec_st;
-    std::string exec_path = tools_dir + tool;
-    if (stat(exec_path.c_str(), &exec_st) != 0) {
-      ADD_FAILURE() << "Cannot find " << tool << " in " << tools_dir;
+ public:
+  static void CheckToolsExist(InstructionSet isa) {
+    const char* tools[] = { "as", "objcopy", "objdump" };
+    for (const char* tool : tools) {
+      std::string path = GetAndroidTool(tool, isa);
+      ASSERT_TRUE(OS::FileExists(path.c_str())) << path;
     }
   }
-}
+};
 
 TEST_F(PrebuiltToolsTest, CheckHostTools) {
-  std::string tools_dir = GetAndroidHostToolsDir();
-  if (tools_dir.empty()) {
-    ADD_FAILURE() << "Cannot find Android tools directory for host";
-  } else {
-    CheckToolsExist(tools_dir);
-  }
+  CheckToolsExist(InstructionSet::kX86);
+  CheckToolsExist(InstructionSet::kX86_64);
 }
 
 TEST_F(PrebuiltToolsTest, CheckTargetTools) {
-  // Other prebuilts are missing from the build server's repo manifest.
-  InstructionSet isas[] = { InstructionSet::kThumb2 };
-  for (InstructionSet isa : isas) {
-    std::string tools_dir = GetAndroidTargetToolsDir(isa);
-    if (tools_dir.empty()) {
-      ADD_FAILURE() << "Cannot find Android tools directory for " << isa;
-    } else {
-      CheckToolsExist(tools_dir);
-    }
-  }
+  CheckToolsExist(InstructionSet::kThumb2);
+  CheckToolsExist(InstructionSet::kArm64);
 }
 
 #endif  // ART_TARGET_ANDROID