Merge "Use the alternate 32-bit base address for asan build only."
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index d376f29..c319b1a 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -119,8 +119,8 @@
 ART_GTEST_dex_to_dex_decompiler_test_DEX_DEPS := VerifierDeps DexToDexDecompiler
 
 # The elf writer test has dependencies on core.oat.
-ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_optimizing_no-pic_64) $(HOST_CORE_IMAGE_optimizing_no-pic_32)
-ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_optimizing_no-pic_64) $(TARGET_CORE_IMAGE_optimizing_no-pic_32)
+ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_DEFAULT_64) $(HOST_CORE_IMAGE_DEFAULT_32)
+ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_DEFAULT_64) $(TARGET_CORE_IMAGE_DEFAULT_32)
 
 ART_GTEST_dex2oat_environment_tests_HOST_DEPS := \
   $(HOST_CORE_IMAGE_optimizing_pic_64) \
@@ -158,63 +158,63 @@
   $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS)
 
 # TODO: document why this is needed.
-ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_optimizing_no-pic_64) $(HOST_CORE_IMAGE_optimizing_no-pic_32)
+ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_DEFAULT_64) $(HOST_CORE_IMAGE_DEFAULT_32)
 
 # The dexdump test requires an image and the dexdump utility.
 # TODO: rename into dexdump when migration completes
 ART_GTEST_dexdump_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
+  $(HOST_CORE_IMAGE_DEFAULT_64) \
+  $(HOST_CORE_IMAGE_DEFAULT_32) \
   $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_dexdump_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
+  $(TARGET_CORE_IMAGE_DEFAULT_64) \
+  $(TARGET_CORE_IMAGE_DEFAULT_32) \
   dexdump2
 
 # The dexlayout test requires an image and the dexlayout utility.
 # TODO: rename into dexdump when migration completes
 ART_GTEST_dexlayout_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
+  $(HOST_CORE_IMAGE_DEFAULT_64) \
+  $(HOST_CORE_IMAGE_DEFAULT_32) \
   $(HOST_OUT_EXECUTABLES)/dexlayout \
   $(HOST_OUT_EXECUTABLES)/dexdump2
 ART_GTEST_dexlayout_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
+  $(TARGET_CORE_IMAGE_DEFAULT_64) \
+  $(TARGET_CORE_IMAGE_DEFAULT_32) \
   dexlayout \
   dexdump2
 
 # The dexlist test requires an image and the dexlist utility.
 ART_GTEST_dexlist_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
+  $(HOST_CORE_IMAGE_DEFAULT_64) \
+  $(HOST_CORE_IMAGE_DEFAULT_32) \
   $(HOST_OUT_EXECUTABLES)/dexlist
 ART_GTEST_dexlist_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
+  $(TARGET_CORE_IMAGE_DEFAULT_64) \
+  $(TARGET_CORE_IMAGE_DEFAULT_32) \
   dexlist
 
 # The imgdiag test has dependencies on core.oat since it needs to load it during the test.
 # For the host, also add the installed tool (in the base size, that should suffice). For the
 # target, just the module is fine, the sync will happen late enough.
 ART_GTEST_imgdiag_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
+  $(HOST_CORE_IMAGE_DEFAULT_64) \
+  $(HOST_CORE_IMAGE_DEFAULT_32) \
   $(HOST_OUT_EXECUTABLES)/imgdiagd
 ART_GTEST_imgdiag_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
+  $(TARGET_CORE_IMAGE_DEFAULT_64) \
+  $(TARGET_CORE_IMAGE_DEFAULT_32) \
   imgdiagd
 
 # Oatdump test requires an image and oatfile to dump.
 ART_GTEST_oatdump_test_HOST_DEPS := \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_64) \
-  $(HOST_CORE_IMAGE_optimizing_no-pic_32) \
+  $(HOST_CORE_IMAGE_DEFAULT_64) \
+  $(HOST_CORE_IMAGE_DEFAULT_32) \
   $(HOST_OUT_EXECUTABLES)/oatdumpd \
   $(HOST_OUT_EXECUTABLES)/oatdumpds
 ART_GTEST_oatdump_test_TARGET_DEPS := \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_64) \
-  $(TARGET_CORE_IMAGE_optimizing_no-pic_32) \
+  $(TARGET_CORE_IMAGE_DEFAULT_64) \
+  $(TARGET_CORE_IMAGE_DEFAULT_32) \
   oatdump
 
 # Profile assistant tests requires profman utility.
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index e297b4f..0086660 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -281,3 +281,10 @@
 valgrind-test-art-host-dex2oat-target: $(valgrindTARGET_CORE_IMG_OUTS)
 
 valgrind-test-art-host-dex2oat: valgrind-test-art-host-dex2oat-host valgrind-test-art-host-dex2oat-target
+
+# Define a default core image that can be used for things like gtests that
+# need some image to run, but don't otherwise care which image is used.
+HOST_CORE_IMAGE_DEFAULT_32 := $(HOST_CORE_IMAGE_optimizing_pic_32)
+HOST_CORE_IMAGE_DEFAULT_64 := $(HOST_CORE_IMAGE_optimizing_pic_64)
+TARGET_CORE_IMAGE_DEFAULT_32 := $(TARGET_CORE_IMAGE_optimizing_pic_32)
+TARGET_CORE_IMAGE_DEFAULT_64 := $(TARGET_CORE_IMAGE_optimizing_pic_64)
diff --git a/cmdline/cmdline.h b/cmdline/cmdline.h
index f4540ff..98010d7 100644
--- a/cmdline/cmdline.h
+++ b/cmdline/cmdline.h
@@ -267,7 +267,7 @@
       std::string file_name;
       if (!LocationToFilename(boot_image_location, instruction_set_, &file_name)) {
         *error_msg = android::base::StringPrintf("No corresponding file for location '%s' exists",
-                                                 file_name.c_str());
+                                                 boot_image_location.c_str());
         return false;
       }
 
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index 9669c4a..fa2d78d 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -41,7 +41,6 @@
                                                                  symbol_name, \
                                                                  build_map)); \
     EXPECT_NE(nullptr, addr); \
-    EXPECT_LT(static_cast<uintptr_t>(ART_BASE_ADDRESS), reinterpret_cast<uintptr_t>(addr)); \
     if ((expected_value) == nullptr) { \
       (expected_value) = addr; \
     }                        \
@@ -60,7 +59,7 @@
   void* dl_oatlastword = nullptr;
 
   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
-  ASSERT_TRUE(file.get() != nullptr);
+  ASSERT_TRUE(file.get() != nullptr) << elf_filename;
   {
     std::string error_msg;
     std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
@@ -86,17 +85,22 @@
     EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", true);
   }
   {
+    uint8_t* base = reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS);
     std::string error_msg;
     std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
                                               false,
                                               true,
                                               /*low_4gb*/false,
-                                              &error_msg));
+                                              &error_msg,
+                                              base));
     CHECK(ef.get() != nullptr) << error_msg;
     CHECK(ef->Load(file.get(), false, /*low_4gb*/false, &error_msg)) << error_msg;
-    EXPECT_EQ(dl_oatdata, ef->FindDynamicSymbolAddress("oatdata"));
-    EXPECT_EQ(dl_oatexec, ef->FindDynamicSymbolAddress("oatexec"));
-    EXPECT_EQ(dl_oatlastword, ef->FindDynamicSymbolAddress("oatlastword"));
+    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatdata) + reinterpret_cast<uintptr_t>(base),
+        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata")));
+    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatexec) + reinterpret_cast<uintptr_t>(base),
+        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec")));
+    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatlastword) + reinterpret_cast<uintptr_t>(base),
+        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword")));
   }
 }
 
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index bac16cd..8dd423f 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -58,6 +58,9 @@
 
 namespace art {
 
+// If true, we record the static and direct invokes in the invoke infos.
+static constexpr bool kEnableDexLayoutOptimizations = false;
+
 // Return whether a location is consistent with a type.
 static bool CheckType(Primitive::Type type, Location location) {
   if (location.IsFpuRegister()
@@ -801,7 +804,18 @@
                                        outer_environment_size,
                                        inlining_depth);
 
-  EmitEnvironment(instruction->GetEnvironment(), slow_path);
+  HEnvironment* const environment = instruction->GetEnvironment();
+  EmitEnvironment(environment, slow_path);
+  // Record invoke info, the common case for the trampoline is super and static invokes. Only
+  // record these to reduce oat file size.
+  if (kEnableDexLayoutOptimizations) {
+    if (environment != nullptr &&
+        instruction->IsInvoke() &&
+        instruction->IsInvokeStaticOrDirect()) {
+      HInvoke* const invoke = instruction->AsInvoke();
+      stack_map_stream_.AddInvoke(invoke->GetInvokeType(), invoke->GetDexMethodIndex());
+    }
+  }
   stack_map_stream_.EndStackMapEntry();
 
   HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
@@ -818,7 +832,6 @@
     EmitEnvironment(instruction->GetEnvironment(), slow_path);
     stack_map_stream_.EndStackMapEntry();
     if (kIsDebugBuild) {
-      HEnvironment* environment = instruction->GetEnvironment();
       for (size_t i = 0, environment_size = environment->Size(); i < environment_size; ++i) {
         HInstruction* in_environment = environment->GetInstructionAt(i);
         if (in_environment != nullptr) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 09612c8d..b779aed 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -5262,7 +5262,7 @@
         // Branch cases into compressed and uncompressed for each index's type.
         uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
         NearLabel done, not_compressed;
-        __ testl(Address(obj, count_offset), Immediate(1));
+        __ testb(Address(obj, count_offset), Immediate(1));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
         static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
                       "Expecting 0=compressed, 1=uncompressed");
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 0879992..179bf6d 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4720,7 +4720,7 @@
         // Branch cases into compressed and uncompressed for each index's type.
         uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
         NearLabel done, not_compressed;
-        __ testl(Address(obj, count_offset), Immediate(1));
+        __ testb(Address(obj, count_offset), Immediate(1));
         codegen_->MaybeRecordImplicitNullCheck(instruction);
         static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
                       "Expecting 0=compressed, 1=uncompressed");
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 1bcc8e1..eeae96e 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -41,12 +41,12 @@
   current_entry_.inlining_depth = inlining_depth;
   current_entry_.inline_infos_start_index = inline_infos_.size();
   current_entry_.stack_mask_index = 0;
+  current_entry_.dex_method_index = DexFile::kDexNoIndex;
   current_entry_.dex_register_entry.num_dex_registers = num_dex_registers;
   current_entry_.dex_register_entry.locations_start_index = dex_register_locations_.size();
   current_entry_.dex_register_entry.live_dex_registers_mask = (num_dex_registers != 0)
       ? ArenaBitVector::Create(allocator_, num_dex_registers, true, kArenaAllocStackMapStream)
       : nullptr;
-
   if (sp_mask != nullptr) {
     stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
   }
@@ -99,6 +99,11 @@
   current_dex_register_++;
 }
 
+void StackMapStream::AddInvoke(InvokeType invoke_type, uint32_t dex_method_index) {
+  current_entry_.invoke_type = invoke_type;
+  current_entry_.dex_method_index = dex_method_index;
+}
+
 void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
                                           uint32_t dex_pc,
                                           uint32_t num_dex_registers,
@@ -166,6 +171,7 @@
       encoding.inline_info.num_entries,
       encoding.register_mask.num_entries,
       encoding.stack_mask.num_entries);
+  ComputeInvokeInfoEncoding(&encoding);
   DCHECK_EQ(code_info_encoding_.size(), 0u);
   encoding.Compress(&code_info_encoding_);
   encoding.ComputeTableOffsets();
@@ -212,6 +218,24 @@
   return size;
 }
 
+void StackMapStream::ComputeInvokeInfoEncoding(CodeInfoEncoding* encoding) {
+  DCHECK(encoding != nullptr);
+  uint32_t native_pc_max = 0;
+  uint16_t method_index_max = 0;
+  size_t invoke_infos_count = 0;
+  size_t invoke_type_max = 0;
+  for (const StackMapEntry& entry : stack_maps_) {
+    if (entry.dex_method_index != DexFile::kDexNoIndex) {
+      native_pc_max = std::max(native_pc_max, entry.native_pc_code_offset.CompressedValue());
+      method_index_max = std::max(method_index_max, static_cast<uint16_t>(entry.dex_method_index));
+      invoke_type_max = std::max(invoke_type_max, static_cast<size_t>(entry.invoke_type));
+      ++invoke_infos_count;
+    }
+  }
+  encoding->invoke_info.num_entries = invoke_infos_count;
+  encoding->invoke_info.encoding.SetFromSizes(native_pc_max, invoke_type_max, method_index_max);
+}
+
 void StackMapStream::ComputeInlineInfoEncoding(InlineInfoEncoding* encoding,
                                                size_t dex_register_maps_bytes) {
   uint32_t method_index_max = 0;
@@ -304,6 +328,7 @@
   ArenaBitVector empty_bitmask(allocator_, 0, /* expandable */ false, kArenaAllocStackMapStream);
   uintptr_t next_dex_register_map_offset = 0;
   uintptr_t next_inline_info_index = 0;
+  size_t invoke_info_idx = 0;
   for (size_t i = 0, e = stack_maps_.size(); i < e; ++i) {
     StackMap stack_map = code_info.GetStackMapAt(i, encoding);
     StackMapEntry entry = stack_maps_[i];
@@ -318,6 +343,14 @@
                                             dex_register_locations_region);
     stack_map.SetDexRegisterMapOffset(encoding.stack_map.encoding, offset);
 
+    if (entry.dex_method_index != DexFile::kDexNoIndex) {
+      InvokeInfo invoke_info(code_info.GetInvokeInfo(encoding, invoke_info_idx));
+      invoke_info.SetNativePcCodeOffset(encoding.invoke_info.encoding, entry.native_pc_code_offset);
+      invoke_info.SetInvokeType(encoding.invoke_info.encoding, entry.invoke_type);
+      invoke_info.SetMethodIndex(encoding.invoke_info.encoding, entry.dex_method_index);
+      ++invoke_info_idx;
+    }
+
     // Set the inlining info.
     if (entry.inlining_depth != 0) {
       InlineInfo inline_info = code_info.GetInlineInfo(next_inline_info_index, encoding);
@@ -528,6 +561,7 @@
   CodeInfo code_info(region);
   CodeInfoEncoding encoding = code_info.ExtractEncoding();
   DCHECK_EQ(code_info.GetNumberOfStackMaps(encoding), stack_maps_.size());
+  size_t invoke_info_index = 0;
   for (size_t s = 0; s < stack_maps_.size(); ++s) {
     const StackMap stack_map = code_info.GetStackMapAt(s, encoding);
     const StackMapEncoding& stack_map_encoding = encoding.stack_map.encoding;
@@ -552,7 +586,14 @@
         DCHECK_EQ(stack_mask.LoadBit(b), 0u);
       }
     }
-
+    if (entry.dex_method_index != DexFile::kDexNoIndex) {
+      InvokeInfo invoke_info = code_info.GetInvokeInfo(encoding, invoke_info_index);
+      DCHECK_EQ(invoke_info.GetNativePcOffset(encoding.invoke_info.encoding, instruction_set_),
+                entry.native_pc_code_offset.Uint32Value(instruction_set_));
+      DCHECK_EQ(invoke_info.GetInvokeType(encoding.invoke_info.encoding), entry.invoke_type);
+      DCHECK_EQ(invoke_info.GetMethodIndex(encoding.invoke_info.encoding), entry.dex_method_index);
+      invoke_info_index++;
+    }
     CheckDexRegisterMap(code_info,
                         code_info.GetDexRegisterMapOf(
                             stack_map, encoding, entry.dex_register_entry.num_dex_registers),
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index bba3d51..4225a87 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -118,6 +118,8 @@
     uint32_t register_mask_index;
     DexRegisterMapEntry dex_register_entry;
     size_t dex_register_map_index;
+    InvokeType invoke_type;
+    uint32_t dex_method_index;
   };
 
   struct InlineInfoEntry {
@@ -138,6 +140,8 @@
 
   void AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value);
 
+  void AddInvoke(InvokeType type, uint32_t dex_method_index);
+
   void BeginInlineInfoEntry(ArtMethod* method,
                             uint32_t dex_pc,
                             uint32_t num_dex_registers,
@@ -184,6 +188,14 @@
   bool DexRegisterMapEntryEquals(const DexRegisterMapEntry& a, const DexRegisterMapEntry& b) const;
 
   // Fill in the corresponding entries of a register map.
+  void ComputeInvokeInfoEncoding(CodeInfoEncoding* encoding);
+
+  // Returns the index of an entry with the same dex register map as the current_entry,
+  // or kNoSameDexMapFound if no such entry exists.
+  size_t FindEntryWithTheSameDexMap();
+  bool HaveTheSameDexMaps(const StackMapEntry& a, const StackMapEntry& b) const;
+
+  // Fill in the corresponding entries of a register map.
   void FillInDexRegisterMap(DexRegisterMap dex_register_map,
                             uint32_t num_dex_registers,
                             const BitVector& live_dex_registers_mask,
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 0416951..330f7f2 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -934,7 +934,6 @@
   EXPECT_EQ(offset_mips64.Uint32Value(kMips64), kMips64InstructionAlignment);
 }
 
-
 TEST(StackMapTest, TestDeduplicateStackMask) {
   ArenaPool pool;
   ArenaAllocator arena(&pool);
@@ -963,4 +962,48 @@
             stack_map2.GetStackMaskIndex(encoding.stack_map.encoding));
 }
 
+TEST(StackMapTest, TestInvokeInfo) {
+  ArenaPool pool;
+  ArenaAllocator arena(&pool);
+  StackMapStream stream(&arena, kRuntimeISA);
+
+  ArenaBitVector sp_mask(&arena, 0, true);
+  sp_mask.SetBit(1);
+  stream.BeginStackMapEntry(0, 4, 0x3, &sp_mask, 0, 0);
+  stream.AddInvoke(kSuper, 1);
+  stream.EndStackMapEntry();
+  stream.BeginStackMapEntry(0, 8, 0x3, &sp_mask, 0, 0);
+  stream.AddInvoke(kStatic, 3);
+  stream.EndStackMapEntry();
+  stream.BeginStackMapEntry(0, 16, 0x3, &sp_mask, 0, 0);
+  stream.AddInvoke(kDirect, 65535);
+  stream.EndStackMapEntry();
+
+  const size_t size = stream.PrepareForFillIn();
+  MemoryRegion region(arena.Alloc(size, kArenaAllocMisc), size);
+  stream.FillIn(region);
+
+  CodeInfo code_info(region);
+  CodeInfoEncoding encoding = code_info.ExtractEncoding();
+  ASSERT_EQ(3u, code_info.GetNumberOfStackMaps(encoding));
+
+  InvokeInfo invoke1(code_info.GetInvokeInfoForNativePcOffset(4, encoding));
+  InvokeInfo invoke2(code_info.GetInvokeInfoForNativePcOffset(8, encoding));
+  InvokeInfo invoke3(code_info.GetInvokeInfoForNativePcOffset(16, encoding));
+  InvokeInfo invoke_invalid(code_info.GetInvokeInfoForNativePcOffset(12, encoding));
+  EXPECT_FALSE(invoke_invalid.IsValid());  // No entry for that index.
+  EXPECT_TRUE(invoke1.IsValid());
+  EXPECT_TRUE(invoke2.IsValid());
+  EXPECT_TRUE(invoke3.IsValid());
+  EXPECT_EQ(invoke1.GetInvokeType(encoding.invoke_info.encoding), kSuper);
+  EXPECT_EQ(invoke1.GetMethodIndex(encoding.invoke_info.encoding), 1u);
+  EXPECT_EQ(invoke1.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 4u);
+  EXPECT_EQ(invoke2.GetInvokeType(encoding.invoke_info.encoding), kStatic);
+  EXPECT_EQ(invoke2.GetMethodIndex(encoding.invoke_info.encoding), 3u);
+  EXPECT_EQ(invoke2.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 8u);
+  EXPECT_EQ(invoke3.GetInvokeType(encoding.invoke_info.encoding), kDirect);
+  EXPECT_EQ(invoke3.GetMethodIndex(encoding.invoke_info.encoding), 65535u);
+  EXPECT_EQ(invoke3.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA), 16u);
+}
+
 }  // namespace art
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 5dcdd9e..6881f75 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -400,9 +400,9 @@
 
 TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
   // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
-  // hold true on some x86 systems when read barriers are enabled;
-  // disable this test while we investigate (b/29259363).
-  TEST_DISABLED_FOR_READ_BARRIER_ON_X86();
+  // hold true on some x86 systems; disable this test while we
+  // investigate (b/29259363).
+  TEST_DISABLED_FOR_X86();
 
   RunTest(false /* use_fd */,
           false /* expect_use */);
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index ff05733..a289433 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -1306,7 +1306,7 @@
     has_modrm = true;
     reg_is_opcode = true;
     store = true;
-    immediate_bytes = ((instr[1] & 0x38) == 0) ? 1 : 0;
+    immediate_bytes = ((instr[1] & 0x38) == 0) ? (instr[0] == 0xF7 ? 4 : 1) : 0;
     break;
   case 0xFF:
     {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 9a3b28b..4413286 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -587,6 +587,7 @@
       kByteKindCodeInfoLocationCatalog,
       kByteKindCodeInfoDexRegisterMap,
       kByteKindCodeInfoEncoding,
+      kByteKindCodeInfoInvokeInfo,
       kByteKindCodeInfoStackMasks,
       kByteKindCodeInfoRegisterMasks,
       kByteKindStackMapNativePc,
@@ -637,6 +638,7 @@
         Dump(os, "CodeInfoDexRegisterMap          ", bits[kByteKindCodeInfoDexRegisterMap], sum);
         Dump(os, "CodeInfoStackMasks              ", bits[kByteKindCodeInfoStackMasks], sum);
         Dump(os, "CodeInfoRegisterMasks           ", bits[kByteKindCodeInfoRegisterMasks], sum);
+        Dump(os, "CodeInfoInvokeInfo              ", bits[kByteKindCodeInfoInvokeInfo], sum);
         // Stack map section.
         const int64_t stack_map_bits = std::accumulate(bits + kByteKindStackMapFirst,
                                                        bits + kByteKindStackMapLast + 1,
@@ -1592,10 +1594,8 @@
         CodeInfoEncoding encoding(helper.GetEncoding());
         StackMapEncoding stack_map_encoding(encoding.stack_map.encoding);
         const size_t num_stack_maps = encoding.stack_map.num_entries;
-        std::vector<uint8_t> size_vector;
-        encoding.Compress(&size_vector);
         if (stats_.AddBitsIfUnique(Stats::kByteKindCodeInfoEncoding,
-                                   size_vector.size() * kBitsPerByte,
+                                   encoding.HeaderSize() * kBitsPerByte,
                                    oat_method.GetVmapTable())) {
           // Stack maps
           stats_.AddBits(
@@ -1627,6 +1627,13 @@
               Stats::kByteKindCodeInfoRegisterMasks,
               encoding.register_mask.encoding.BitSize() * encoding.register_mask.num_entries);
 
+          // Invoke infos
+          if (encoding.invoke_info.num_entries > 0u) {
+            stats_.AddBits(
+                Stats::kByteKindCodeInfoInvokeInfo,
+                encoding.invoke_info.encoding.BitSize() * encoding.invoke_info.num_entries);
+          }
+
           // Location catalog
           const size_t location_catalog_bytes =
               helper.GetCodeInfo().GetDexRegisterLocationCatalogSize(encoding);
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index fc82264..78ba6e7 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -625,9 +625,9 @@
   if (IsHost()) {
     const char* host_dir = getenv("ANDROID_HOST_OUT");
     CHECK(host_dir != nullptr);
-    location = StringPrintf("%s/framework/core-npic.%s", host_dir, suffix);
+    location = StringPrintf("%s/framework/core.%s", host_dir, suffix);
   } else {
-    location = StringPrintf("/data/art-test/core-npic.%s", suffix);
+    location = StringPrintf("/data/art-test/core.%s", suffix);
   }
 
   return location;
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 17e3729..d7abe2a 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -223,9 +223,9 @@
     return; \
   }
 
-#define TEST_DISABLED_FOR_READ_BARRIER_ON_X86() \
-  if (kUseReadBarrier && kRuntimeISA == kX86) { \
-    printf("WARNING: TEST DISABLED FOR READ BARRIER ON X86\n"); \
+#define TEST_DISABLED_FOR_X86() \
+  if (kRuntimeISA == kX86) { \
+    printf("WARNING: TEST DISABLED FOR X86\n"); \
     return; \
   }
 
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index a95f94c..d39ea35 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -299,6 +299,7 @@
   return result.GetL();
 }
 
+template <bool kTransactionActive>
 bool ProcessAnnotationValue(Handle<mirror::Class> klass,
                             const uint8_t** annotation_ptr,
                             DexFile::AnnotationValue* annotation_value,
@@ -409,22 +410,21 @@
         }
         PointerSize pointer_size = class_linker->GetImagePointerSize();
         set_object = true;
-        DCHECK(!Runtime::Current()->IsActiveTransaction());
         if (method->IsConstructor()) {
           if (pointer_size == PointerSize::k64) {
             element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k64,
-                                                                      false>(self, method);
+                kTransactionActive>(self, method);
           } else {
             element_object = mirror::Constructor::CreateFromArtMethod<PointerSize::k32,
-                                                                      false>(self, method);
+                kTransactionActive>(self, method);
           }
         } else {
           if (pointer_size == PointerSize::k64) {
             element_object = mirror::Method::CreateFromArtMethod<PointerSize::k64,
-                                                                 false>(self, method);
+                kTransactionActive>(self, method);
           } else {
             element_object = mirror::Method::CreateFromArtMethod<PointerSize::k32,
-                                                                 false>(self, method);
+                kTransactionActive>(self, method);
           }
         }
         if (element_object == nullptr) {
@@ -449,9 +449,11 @@
         set_object = true;
         PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
         if (pointer_size == PointerSize::k64) {
-          element_object = mirror::Field::CreateFromArtField<PointerSize::k64>(self, field, true);
+          element_object = mirror::Field::CreateFromArtField<PointerSize::k64,
+              kTransactionActive>(self, field, true);
         } else {
-          element_object = mirror::Field::CreateFromArtField<PointerSize::k32>(self, field, true);
+          element_object = mirror::Field::CreateFromArtField<PointerSize::k32,
+              kTransactionActive>(self, field, true);
         }
         if (element_object == nullptr) {
           return false;
@@ -497,45 +499,49 @@
         }
         DexFile::AnnotationValue new_annotation_value;
         for (uint32_t i = 0; i < size; ++i) {
-          if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value,
-                                      component_type, DexFile::kPrimitivesOrObjects)) {
+          if (!ProcessAnnotationValue<kTransactionActive>(klass,
+                                                          &annotation,
+                                                          &new_annotation_value,
+                                                          component_type,
+                                                          DexFile::kPrimitivesOrObjects)) {
             return false;
           }
           if (!component_type->IsPrimitive()) {
             mirror::Object* obj = new_annotation_value.value_.GetL();
-            new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj);
+            new_array->AsObjectArray<mirror::Object>()->
+                SetWithoutChecks<kTransactionActive>(i, obj);
           } else {
             switch (new_annotation_value.type_) {
               case DexFile::kDexAnnotationByte:
-                new_array->AsByteArray()->SetWithoutChecks<false>(
+                new_array->AsByteArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetB());
                 break;
               case DexFile::kDexAnnotationShort:
-                new_array->AsShortArray()->SetWithoutChecks<false>(
+                new_array->AsShortArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetS());
                 break;
               case DexFile::kDexAnnotationChar:
-                new_array->AsCharArray()->SetWithoutChecks<false>(
+                new_array->AsCharArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetC());
                 break;
               case DexFile::kDexAnnotationInt:
-                new_array->AsIntArray()->SetWithoutChecks<false>(
+                new_array->AsIntArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetI());
                 break;
               case DexFile::kDexAnnotationLong:
-                new_array->AsLongArray()->SetWithoutChecks<false>(
+                new_array->AsLongArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetJ());
                 break;
               case DexFile::kDexAnnotationFloat:
-                new_array->AsFloatArray()->SetWithoutChecks<false>(
+                new_array->AsFloatArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetF());
                 break;
               case DexFile::kDexAnnotationDouble:
-                new_array->AsDoubleArray()->SetWithoutChecks<false>(
+                new_array->AsDoubleArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetD());
                 break;
               case DexFile::kDexAnnotationBoolean:
-                new_array->AsBooleanArray()->SetWithoutChecks<false>(
+                new_array->AsBooleanArray()->SetWithoutChecks<kTransactionActive>(
                     i, new_annotation_value.value_.GetZ());
                 break;
               default:
@@ -611,8 +617,11 @@
       annotation_method->GetReturnType(true /* resolve */)));
 
   DexFile::AnnotationValue annotation_value;
-  if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return,
-                              DexFile::kAllObjects)) {
+  if (!ProcessAnnotationValue<false>(klass,
+                                     annotation,
+                                     &annotation_value,
+                                     method_return,
+                                     DexFile::kAllObjects)) {
     return nullptr;
   }
   Handle<mirror::Object> value_object(hs.NewHandle(annotation_value.value_.GetL()));
@@ -716,8 +725,18 @@
     return nullptr;
   }
   DexFile::AnnotationValue annotation_value;
-  if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class,
-                              DexFile::kAllObjects)) {
+  bool result = Runtime::Current()->IsActiveTransaction()
+      ? ProcessAnnotationValue<true>(klass,
+                                     &annotation,
+                                     &annotation_value,
+                                     array_class,
+                                     DexFile::kAllObjects)
+      : ProcessAnnotationValue<false>(klass,
+                                      &annotation,
+                                      &annotation_value,
+                                      array_class,
+                                      DexFile::kAllObjects);
+  if (!result) {
     return nullptr;
   }
   if (annotation_value.type_ != expected_type) {
@@ -949,8 +968,11 @@
   StackHandleScope<2> hs(Thread::Current());
   Handle<mirror::Class> h_klass(hs.NewHandle(klass));
   Handle<mirror::Class> return_type(hs.NewHandle(method->GetReturnType(true /* resolve */)));
-  if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type,
-                              DexFile::kAllObjects)) {
+  if (!ProcessAnnotationValue<false>(h_klass,
+                                     &annotation,
+                                     &annotation_value,
+                                     return_type,
+                                     DexFile::kAllObjects)) {
     return nullptr;
   }
   return annotation_value.value_.GetL();
@@ -1201,8 +1223,11 @@
     return nullptr;
   }
   DexFile::AnnotationValue annotation_value;
-  if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
-                              ScopedNullHandle<mirror::Class>(), DexFile::kAllRaw)) {
+  if (!ProcessAnnotationValue<false>(klass,
+                                     &annotation,
+                                     &annotation_value,
+                                     ScopedNullHandle<mirror::Class>(),
+                                     DexFile::kAllRaw)) {
     return nullptr;
   }
   if (annotation_value.type_ != DexFile::kDexAnnotationMethod) {
@@ -1252,9 +1277,11 @@
     return false;
   }
   DexFile::AnnotationValue annotation_value;
-  if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
-                              ScopedNullHandle<mirror::Class>(),
-                                           DexFile::kAllObjects)) {
+  if (!ProcessAnnotationValue<false>(klass,
+                                     &annotation,
+                                     &annotation_value,
+                                     ScopedNullHandle<mirror::Class>(),
+                                     DexFile::kAllObjects)) {
     return false;
   }
   if (annotation_value.type_ != DexFile::kDexAnnotationNull &&
@@ -1283,8 +1310,11 @@
     return false;
   }
   DexFile::AnnotationValue annotation_value;
-  if (!ProcessAnnotationValue(klass, &annotation, &annotation_value,
-                              ScopedNullHandle<mirror::Class>(), DexFile::kAllRaw)) {
+  if (!ProcessAnnotationValue<false>(klass,
+                                     &annotation,
+                                     &annotation_value,
+                                     ScopedNullHandle<mirror::Class>(),
+                                     DexFile::kAllRaw)) {
     return false;
   }
   if (annotation_value.type_ != DexFile::kDexAnnotationInt) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index c2bca53..4c3990a 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -358,6 +358,29 @@
     }
   }
 
+  static bool GetInvokeType(ArtMethod** sp, InvokeType* invoke_type, uint32_t* dex_method_index)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK((*sp)->IsCalleeSaveMethod());
+    const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, Runtime::kSaveRefsAndArgs);
+    ArtMethod** caller_sp = reinterpret_cast<ArtMethod**>(
+        reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
+    uintptr_t outer_pc = QuickArgumentVisitor::GetCallingPc(sp);
+    const OatQuickMethodHeader* current_code = (*caller_sp)->GetOatQuickMethodHeader(outer_pc);
+    if (!current_code->IsOptimized()) {
+      return false;
+    }
+    uintptr_t outer_pc_offset = current_code->NativeQuickPcOffset(outer_pc);
+    CodeInfo code_info = current_code->GetOptimizedCodeInfo();
+    CodeInfoEncoding encoding = code_info.ExtractEncoding();
+    InvokeInfo invoke(code_info.GetInvokeInfoForNativePcOffset(outer_pc_offset, encoding));
+    if (invoke.IsValid()) {
+      *invoke_type = static_cast<InvokeType>(invoke.GetInvokeType(encoding.invoke_info.encoding));
+      *dex_method_index = invoke.GetMethodIndex(encoding.invoke_info.encoding);
+      return true;
+    }
+    return false;
+  }
+
   // For the given quick ref and args quick frame, return the caller's PC.
   static uintptr_t GetCallingPc(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK((*sp)->IsCalleeSaveMethod());
@@ -977,60 +1000,87 @@
   ArtMethod* caller = nullptr;
   if (!called_method_known_on_entry) {
     caller = QuickArgumentVisitor::GetCallingMethod(sp);
-    uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
-    const DexFile::CodeItem* code;
     called_method.dex_file = caller->GetDexFile();
-    code = caller->GetCodeItem();
-    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-    Instruction::Code instr_code = instr->Opcode();
-    bool is_range;
-    switch (instr_code) {
-      case Instruction::INVOKE_DIRECT:
-        invoke_type = kDirect;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_DIRECT_RANGE:
-        invoke_type = kDirect;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_STATIC:
-        invoke_type = kStatic;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_STATIC_RANGE:
-        invoke_type = kStatic;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_SUPER:
-        invoke_type = kSuper;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_SUPER_RANGE:
-        invoke_type = kSuper;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_VIRTUAL:
-        invoke_type = kVirtual;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_VIRTUAL_RANGE:
-        invoke_type = kVirtual;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_INTERFACE:
-        invoke_type = kInterface;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_INTERFACE_RANGE:
-        invoke_type = kInterface;
-        is_range = true;
-        break;
-      default:
-        LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr);
-        UNREACHABLE();
+
+    InvokeType stack_map_invoke_type;
+    uint32_t stack_map_dex_method_idx;
+    const bool found_stack_map = QuickArgumentVisitor::GetInvokeType(sp,
+                                                                     &stack_map_invoke_type,
+                                                                     &stack_map_dex_method_idx);
+    // For debug builds, we make sure both of the paths are consistent by also looking at the dex
+    // code.
+    if (!found_stack_map || kIsDebugBuild) {
+      uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
+      const DexFile::CodeItem* code;
+      code = caller->GetCodeItem();
+      CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+      const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+      Instruction::Code instr_code = instr->Opcode();
+      bool is_range;
+      switch (instr_code) {
+        case Instruction::INVOKE_DIRECT:
+          invoke_type = kDirect;
+          is_range = false;
+          break;
+        case Instruction::INVOKE_DIRECT_RANGE:
+          invoke_type = kDirect;
+          is_range = true;
+          break;
+        case Instruction::INVOKE_STATIC:
+          invoke_type = kStatic;
+          is_range = false;
+          break;
+        case Instruction::INVOKE_STATIC_RANGE:
+          invoke_type = kStatic;
+          is_range = true;
+          break;
+        case Instruction::INVOKE_SUPER:
+          invoke_type = kSuper;
+          is_range = false;
+          break;
+        case Instruction::INVOKE_SUPER_RANGE:
+          invoke_type = kSuper;
+          is_range = true;
+          break;
+        case Instruction::INVOKE_VIRTUAL:
+          invoke_type = kVirtual;
+          is_range = false;
+          break;
+        case Instruction::INVOKE_VIRTUAL_RANGE:
+          invoke_type = kVirtual;
+          is_range = true;
+          break;
+        case Instruction::INVOKE_INTERFACE:
+          invoke_type = kInterface;
+          is_range = false;
+          break;
+        case Instruction::INVOKE_INTERFACE_RANGE:
+          invoke_type = kInterface;
+          is_range = true;
+          break;
+        default:
+          LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr);
+          UNREACHABLE();
+      }
+      called_method.dex_method_index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
+      // Check that the invoke matches what we expected, note that this path only happens for debug
+      // builds.
+      if (found_stack_map) {
+        DCHECK_EQ(stack_map_invoke_type, invoke_type);
+        if (invoke_type != kSuper) {
+          // Super may be sharpened.
+          DCHECK_EQ(stack_map_dex_method_idx, called_method.dex_method_index)
+              << called_method.dex_file->PrettyMethod(stack_map_dex_method_idx) << " "
+              << called_method.dex_file->PrettyMethod(called_method.dex_method_index);
+        }
+      } else {
+        VLOG(oat) << "Accessed dex file for invoke " << invoke_type << " "
+                  << called_method.dex_method_index;
+      }
+    } else {
+      invoke_type = stack_map_invoke_type;
+      called_method.dex_method_index = stack_map_dex_method_idx;
     }
-    called_method.dex_method_index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
   } else {
     invoke_type = kStatic;
     called_method.dex_file = called->GetDexFile();
diff --git a/runtime/gc/collector_type.h b/runtime/gc/collector_type.h
index 7014357..eef4fba 100644
--- a/runtime/gc/collector_type.h
+++ b/runtime/gc/collector_type.h
@@ -55,6 +55,8 @@
   kCollectorTypeClassLinker,
   // JIT Code cache fake collector.
   kCollectorTypeJitCodeCache,
+  // Hprof fake collector.
+  kCollectorTypeHprof,
   // Fake collector for installing/removing a system-weak holder.
   kCollectorTypeAddRemoveSystemWeakHolder,
 };
diff --git a/runtime/gc/gc_cause.cc b/runtime/gc/gc_cause.cc
index 7ff845d..9e34346 100644
--- a/runtime/gc/gc_cause.cc
+++ b/runtime/gc/gc_cause.cc
@@ -39,6 +39,7 @@
     case kGcCauseClassLinker: return "ClassLinker";
     case kGcCauseJitCodeCache: return "JitCodeCache";
     case kGcCauseAddRemoveSystemWeakHolder: return "SystemWeakHolder";
+    case kGcCauseHprof: return "Hprof";
   }
   LOG(FATAL) << "Unreachable";
   UNREACHABLE();
diff --git a/runtime/gc/gc_cause.h b/runtime/gc/gc_cause.h
index f54f0e4..9b285b1 100644
--- a/runtime/gc/gc_cause.h
+++ b/runtime/gc/gc_cause.h
@@ -53,6 +53,8 @@
   kGcCauseJitCodeCache,
   // Not a real GC cause, used to add or remove system-weak holders.
   kGcCauseAddRemoveSystemWeakHolder,
+  // Not a real GC cause, used to hprof running in the middle of GC.
+  kGcCauseHprof,
 };
 
 const char* PrettyCause(GcCause cause);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 6d0ab75..c933d04 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -189,6 +189,7 @@
       disable_thread_flip_count_(0),
       thread_flip_running_(false),
       collector_type_running_(kCollectorTypeNone),
+      thread_running_gc_(nullptr),
       last_gc_type_(collector::kGcTypeNone),
       next_gc_type_(collector::kGcTypePartial),
       capacity_(capacity),
@@ -988,7 +989,9 @@
     // Continuous spaces don't necessarily have bitmaps.
     accounting::ContinuousSpaceBitmap* live_bitmap = continuous_space->GetLiveBitmap();
     accounting::ContinuousSpaceBitmap* mark_bitmap = continuous_space->GetMarkBitmap();
-    if (live_bitmap != nullptr) {
+    // The region space bitmap is not added since VisitObjects visits the region space objects with
+    // special handling.
+    if (live_bitmap != nullptr && !space->IsRegionSpace()) {
       CHECK(mark_bitmap != nullptr);
       live_bitmap_->AddContinuousSpaceBitmap(live_bitmap);
       mark_bitmap_->AddContinuousSpaceBitmap(mark_bitmap);
@@ -1029,7 +1032,7 @@
     // Continuous spaces don't necessarily have bitmaps.
     accounting::ContinuousSpaceBitmap* live_bitmap = continuous_space->GetLiveBitmap();
     accounting::ContinuousSpaceBitmap* mark_bitmap = continuous_space->GetMarkBitmap();
-    if (live_bitmap != nullptr) {
+    if (live_bitmap != nullptr && !space->IsRegionSpace()) {
       DCHECK(mark_bitmap != nullptr);
       live_bitmap_->RemoveContinuousSpaceBitmap(live_bitmap);
       mark_bitmap_->RemoveContinuousSpaceBitmap(mark_bitmap);
@@ -1385,6 +1388,7 @@
   // Ensure there is only one GC at a time.
   WaitForGcToCompleteLocked(cause, self);
   collector_type_running_ = collector_type;
+  thread_running_gc_ = self;
 }
 
 void Heap::TrimSpaces(Thread* self) {
@@ -2784,6 +2788,7 @@
   }
   // Reset.
   running_collection_is_blocking_ = false;
+  thread_running_gc_ = nullptr;
   // Wake anyone who may have been waiting for the GC to complete.
   gc_complete_cond_->Broadcast(self);
 }
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index a4d300b..0d56213 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -736,7 +736,9 @@
 
   bool IsMovingGCDisabled(Thread* self) REQUIRES(!*gc_complete_lock_) {
     MutexLock mu(self, *gc_complete_lock_);
-    return disable_moving_gc_count_ > 0;
+    // If we are in a GC critical section or the disable moving GC count is non zero then moving
+    // GC is guaranteed to not start.
+    return disable_moving_gc_count_ > 0 || thread_running_gc_ == self;
   }
 
   // Request an asynchronous trim.
@@ -1189,6 +1191,9 @@
   // True while the garbage collector is running.
   volatile CollectorType collector_type_running_ GUARDED_BY(gc_complete_lock_);
 
+  // The thread currently running the GC.
+  volatile Thread* thread_running_gc_ GUARDED_BY(gc_complete_lock_);
+
   // Last Gc type we ran. Used by WaitForConcurrentGc to know which Gc was waited on.
   volatile collector::GcType last_gc_type_ GUARDED_BY(gc_complete_lock_);
   collector::GcType next_gc_type_;
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 133502e..e59c4bb 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -50,6 +50,7 @@
 #include "gc_root.h"
 #include "gc/accounting/heap_bitmap.h"
 #include "gc/allocation_record.h"
+#include "gc/scoped_gc_critical_section.h"
 #include "gc/heap.h"
 #include "gc/space/space.h"
 #include "globals.h"
@@ -463,6 +464,7 @@
     }
 
     bool okay;
+    visited_objects_.clear();
     if (direct_to_ddms_) {
       if (kDirectStream) {
         okay = DumpToDdmsDirect(overall_size, max_length, CHUNK_TYPE("HPDS"));
@@ -911,6 +913,9 @@
   // bits.
   std::unordered_set<uint64_t> simple_roots_;
 
+  // To make sure we don't dump the same object multiple times. b/34967844
+  std::unordered_set<mirror::Object*> visited_objects_;
+
   friend class GcRootVisitor;
   DISALLOW_COPY_AND_ASSIGN(Hprof);
 };
@@ -1093,6 +1098,7 @@
   if (obj->IsClass() && obj->AsClass()->IsRetired()) {
     return;
   }
+  DCHECK(visited_objects_.insert(obj).second) << "Already visited " << obj;
 
   ++total_objects_;
 
@@ -1444,22 +1450,15 @@
 // Otherwise, "filename" is used to create an output file.
 void DumpHeap(const char* filename, int fd, bool direct_to_ddms) {
   CHECK(filename != nullptr);
-
   Thread* self = Thread::Current();
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  if (heap->IsGcConcurrentAndMoving()) {
-    // Need to take a heap dump while GC isn't running. See the
-    // comment in Heap::VisitObjects().
-    heap->IncrementDisableMovingGC(self);
-  }
-  {
-    ScopedSuspendAll ssa(__FUNCTION__, true /* long suspend */);
-    Hprof hprof(filename, fd, direct_to_ddms);
-    hprof.Dump();
-  }
-  if (heap->IsGcConcurrentAndMoving()) {
-    heap->DecrementDisableMovingGC(self);
-  }
+  // Need to take a heap dump while GC isn't running. See the comment in Heap::VisitObjects().
+  // Also we need the critical section to avoid visiting the same object twice. See b/34967844
+  gc::ScopedGCCriticalSection gcs(self,
+                                  gc::kGcCauseHprof,
+                                  gc::kCollectorTypeHprof);
+  ScopedSuspendAll ssa(__FUNCTION__, true /* long suspend */);
+  Hprof hprof(filename, fd, direct_to_ddms);
+  hprof.Dump();
 }
 
 }  // namespace hprof
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 66f14b9..4a321e6 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -175,56 +175,61 @@
   return param->AsString();
 }
 
-void UnstartedRuntime::UnstartedClassForName(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+void UnstartedRuntime::UnstartedClassForNameCommon(Thread* self,
+                                                   ShadowFrame* shadow_frame,
+                                                   JValue* result,
+                                                   size_t arg_offset,
+                                                   bool long_form,
+                                                   const char* caller) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
   if (class_name == nullptr) {
     return;
   }
+  bool initialize_class;
+  mirror::ClassLoader* class_loader;
+  if (long_form) {
+    initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
+    class_loader = down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
+  } else {
+    initialize_class = true;
+    // TODO: This is really only correct for the boot classpath, and for robustness we should
+    //       check the caller.
+    class_loader = nullptr;
+  }
+
+  ScopedObjectAccessUnchecked soa(self);
+  if (class_loader != nullptr && !ClassLinker::IsBootClassLoader(soa, class_loader)) {
+    AbortTransactionOrFail(self,
+                           "Only the boot classloader is supported: %s",
+                           mirror::Object::PrettyTypeOf(class_loader).c_str());
+    return;
+  }
+
   StackHandleScope<1> hs(self);
   Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
   UnstartedRuntimeFindClass(self,
                             h_class_name,
                             ScopedNullHandle<mirror::ClassLoader>(),
                             result,
-                            "Class.forName",
-                            true,
+                            caller,
+                            initialize_class,
                             false);
   CheckExceptionGenerateClassNotFound(self);
 }
 
+void UnstartedRuntime::UnstartedClassForName(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, false, "Class.forName");
+}
+
 void UnstartedRuntime::UnstartedClassForNameLong(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
-  if (class_name == nullptr) {
-    return;
-  }
-  bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
-  mirror::ClassLoader* class_loader =
-      down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
-  StackHandleScope<2> hs(self);
-  Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
-  Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
-  UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.forName",
-                            initialize_class, false);
-  CheckExceptionGenerateClassNotFound(self);
+  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.forName");
 }
 
 void UnstartedRuntime::UnstartedClassClassForName(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
-  if (class_name == nullptr) {
-    return;
-  }
-  bool initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
-  mirror::ClassLoader* class_loader =
-      down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
-  StackHandleScope<2> hs(self);
-  Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
-  Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
-  UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, "Class.classForName",
-                            initialize_class, false);
-  CheckExceptionGenerateClassNotFound(self);
+  UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.classForName");
 }
 
 void UnstartedRuntime::UnstartedClassNewInstance(
@@ -440,6 +445,20 @@
   result->SetI(mirror::Class::GetInnerClassFlags(klass, default_value));
 }
 
+void UnstartedRuntime::UnstartedClassGetSignatureAnnotation(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+  StackHandleScope<1> hs(self);
+  Handle<mirror::Class> klass(hs.NewHandle(
+      reinterpret_cast<mirror::Class*>(shadow_frame->GetVRegReference(arg_offset))));
+
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    result->SetL(nullptr);
+    return;
+  }
+
+  result->SetL(annotations::GetSignatureAnnotationForClass(klass));
+}
+
 void UnstartedRuntime::UnstartedClassIsAnonymousClass(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   StackHandleScope<1> hs(self);
diff --git a/runtime/interpreter/unstarted_runtime.h b/runtime/interpreter/unstarted_runtime.h
index 3f36a27..bc9ead8 100644
--- a/runtime/interpreter/unstarted_runtime.h
+++ b/runtime/interpreter/unstarted_runtime.h
@@ -89,6 +89,13 @@
 #undef UNSTARTED_RUNTIME_JNI_LIST
 #undef UNSTARTED_JNI
 
+  static void UnstartedClassForNameCommon(Thread* self,
+                                          ShadowFrame* shadow_frame,
+                                          JValue* result,
+                                          size_t arg_offset,
+                                          bool long_form,
+                                          const char* caller) REQUIRES_SHARED(Locks::mutator_lock_);
+
   static void InitializeInvokeHandlers();
   static void InitializeJNIHandlers();
 
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index 929b747..c6114da 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -31,6 +31,7 @@
   V(ClassGetDeclaringClass, "java.lang.Class java.lang.Class.getDeclaringClass()") \
   V(ClassGetEnclosingClass, "java.lang.Class java.lang.Class.getEnclosingClass()") \
   V(ClassGetInnerClassFlags, "int java.lang.Class.getInnerClassFlags(int)") \
+  V(ClassGetSignatureAnnotation, "java.lang.String[] java.lang.Class.getSignatureAnnotation()") \
   V(ClassIsAnonymousClass, "boolean java.lang.Class.isAnonymousClass()") \
   V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \
   V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 98a17e4..4186c37 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -29,6 +29,8 @@
 #include "handle_scope-inl.h"
 #include "interpreter/interpreter_common.h"
 #include "mirror/class_loader.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/object-inl.h"
 #include "mirror/string-inl.h"
 #include "runtime.h"
 #include "scoped_thread_state_change-inl.h"
@@ -1077,12 +1079,243 @@
   StackHandleScope<1> hs(self);
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Handle<mirror::Class> log_manager_class = hs.NewHandle(
-          class_linker->FindClass(self,
-                                  "Ljava/util/logging/LogManager;",
-                                  ScopedNullHandle<mirror::ClassLoader>()));
+      class_linker->FindClass(self,
+                              "Ljava/util/logging/LogManager;",
+                              ScopedNullHandle<mirror::ClassLoader>()));
   ASSERT_TRUE(log_manager_class.Get() != nullptr);
   ASSERT_TRUE(class_linker->EnsureInitialized(self, log_manager_class, true, true));
 }
 
+class UnstartedClassForNameTest : public UnstartedRuntimeTest {
+ public:
+  template <typename T>
+  void RunTest(T& runner, bool in_transaction, bool should_succeed) {
+    Thread* self = Thread::Current();
+    ScopedObjectAccess soa(self);
+
+    // Ensure that Class is initialized.
+    {
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      StackHandleScope<1> hs(self);
+      Handle<mirror::Class> h_class = hs.NewHandle(mirror::Class::GetJavaLangClass());
+      CHECK(class_linker->EnsureInitialized(self, h_class, true, true));
+    }
+
+    // A selection of classes from different core classpath components.
+    constexpr const char* kTestCases[] = {
+        "java.net.CookieManager",  // From libcore.
+        "dalvik.system.ClassExt",  // From libart.
+    };
+
+    if (in_transaction) {
+      // For transaction mode, we cannot load any classes, as the pre-fence initialization of
+      // classes isn't transactional. Load them ahead of time.
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      for (const char* name : kTestCases) {
+        class_linker->FindClass(self,
+                                DotToDescriptor(name).c_str(),
+                                ScopedNullHandle<mirror::ClassLoader>());
+        CHECK(!self->IsExceptionPending()) << self->GetException()->Dump();
+      }
+    }
+
+    if (!should_succeed) {
+      // Negative test. In general, currentThread should fail (as we should not leak a peer that will
+      // be recreated at runtime).
+      PrepareForAborts();
+    }
+
+    JValue result;
+    ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
+
+    for (const char* name : kTestCases) {
+      mirror::String* name_string = mirror::String::AllocFromModifiedUtf8(self, name);
+      CHECK(name_string != nullptr);
+
+      Transaction transaction;
+      if (in_transaction) {
+        Runtime::Current()->EnterTransactionMode(&transaction);
+      }
+      CHECK(!self->IsExceptionPending());
+
+      runner(self, shadow_frame, name_string, &result);
+
+      if (in_transaction) {
+        Runtime::Current()->ExitTransactionMode();
+      }
+
+      if (should_succeed) {
+        CHECK(!self->IsExceptionPending()) << name << " " << self->GetException()->Dump();
+        CHECK(result.GetL() != nullptr) << name;
+      } else {
+        CHECK(self->IsExceptionPending()) << name;
+        if (in_transaction) {
+          ASSERT_TRUE(transaction.IsAborted());
+        }
+        self->ClearException();
+      }
+    }
+
+    ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
+  }
+
+  mirror::ClassLoader* GetBootClassLoader() REQUIRES_SHARED(Locks::mutator_lock_) {
+    Thread* self = Thread::Current();
+    StackHandleScope<2> hs(self);
+    MutableHandle<mirror::ClassLoader> boot_cp = hs.NewHandle<mirror::ClassLoader>(nullptr);
+
+    {
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+      // Create the fake boot classloader. Any instance is fine, they are technically interchangeable.
+      Handle<mirror::Class> boot_cp_class = hs.NewHandle(
+          class_linker->FindClass(self,
+                                  "Ljava/lang/BootClassLoader;",
+                                  ScopedNullHandle<mirror::ClassLoader>()));
+      CHECK(boot_cp_class != nullptr);
+      CHECK(class_linker->EnsureInitialized(self, boot_cp_class, true, true));
+
+      boot_cp.Assign(boot_cp_class->AllocObject(self)->AsClassLoader());
+      CHECK(boot_cp != nullptr);
+
+      ArtMethod* boot_cp_init = boot_cp_class->FindDeclaredDirectMethod(
+          "<init>", "()V", class_linker->GetImagePointerSize());
+      CHECK(boot_cp_init != nullptr);
+
+      JValue result;
+      ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, boot_cp_init, 0);
+      shadow_frame->SetVRegReference(0, boot_cp.Get());
+
+      // create instruction data for invoke-direct {v0} of method with fake index
+      uint16_t inst_data[3] = { 0x1070, 0x0000, 0x0010 };
+      const Instruction* inst = Instruction::At(inst_data);
+
+      interpreter::DoCall<false, false>(boot_cp_init,
+                                        self,
+                                        *shadow_frame,
+                                        inst,
+                                        inst_data[0],
+                                        &result);
+      CHECK(!self->IsExceptionPending());
+
+      ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
+    }
+
+    return boot_cp.Get();
+  }
+};
+
+TEST_F(UnstartedClassForNameTest, ClassForName) {
+  auto runner = [](Thread* self, ShadowFrame* shadow_frame, mirror::String* name, JValue* result)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame->SetVRegReference(0, name);
+    UnstartedClassForName(self, shadow_frame, result, 0);
+  };
+  RunTest(runner, false, true);
+}
+
+TEST_F(UnstartedClassForNameTest, ClassForNameLong) {
+  auto runner = [](Thread* self, ShadowFrame* shadow_frame, mirror::String* name, JValue* result)
+            REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame->SetVRegReference(0, name);
+    shadow_frame->SetVReg(1, 0);
+    shadow_frame->SetVRegReference(2, nullptr);
+    UnstartedClassForNameLong(self, shadow_frame, result, 0);
+  };
+  RunTest(runner, false, true);
+}
+
+TEST_F(UnstartedClassForNameTest, ClassForNameLongWithClassLoader) {
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+
+  StackHandleScope<1> hs(self);
+  Handle<mirror::ClassLoader> boot_cp = hs.NewHandle(GetBootClassLoader());
+
+  auto runner = [&](Thread* th, ShadowFrame* shadow_frame, mirror::String* name, JValue* result)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame->SetVRegReference(0, name);
+    shadow_frame->SetVReg(1, 0);
+    shadow_frame->SetVRegReference(2, boot_cp.Get());
+    UnstartedClassForNameLong(th, shadow_frame, result, 0);
+  };
+  RunTest(runner, false, true);
+}
+
+TEST_F(UnstartedClassForNameTest, ClassForNameLongWithClassLoaderTransaction) {
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+
+  StackHandleScope<1> hs(self);
+  Handle<mirror::ClassLoader> boot_cp = hs.NewHandle(GetBootClassLoader());
+
+  auto runner = [&](Thread* th, ShadowFrame* shadow_frame, mirror::String* name, JValue* result)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame->SetVRegReference(0, name);
+    shadow_frame->SetVReg(1, 0);
+    shadow_frame->SetVRegReference(2, boot_cp.Get());
+    UnstartedClassForNameLong(th, shadow_frame, result, 0);
+  };
+  RunTest(runner, true, true);
+}
+
+TEST_F(UnstartedClassForNameTest, ClassForNameLongWithClassLoaderFail) {
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+
+  StackHandleScope<2> hs(self);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  jobject path_jobj = class_linker->CreatePathClassLoader(self, {});
+  ASSERT_TRUE(path_jobj != nullptr);
+  Handle<mirror::ClassLoader> path_cp = hs.NewHandle<mirror::ClassLoader>(
+      self->DecodeJObject(path_jobj)->AsClassLoader());
+
+  auto runner = [&](Thread* th, ShadowFrame* shadow_frame, mirror::String* name, JValue* result)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    shadow_frame->SetVRegReference(0, name);
+    shadow_frame->SetVReg(1, 0);
+    shadow_frame->SetVRegReference(2, path_cp.Get());
+    UnstartedClassForNameLong(th, shadow_frame, result, 0);
+  };
+  RunTest(runner, true, false);
+}
+
+TEST_F(UnstartedRuntimeTest, ClassGetSignatureAnnotation) {
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+
+  StackHandleScope<1> hs(self);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Handle<mirror::Class> list_class = hs.NewHandle(
+      class_linker->FindClass(self,
+                              "Ljava/util/List;",
+                              ScopedNullHandle<mirror::ClassLoader>()));
+  ASSERT_TRUE(list_class.Get() != nullptr);
+  ASSERT_TRUE(class_linker->EnsureInitialized(self, list_class, true, true));
+
+  JValue result;
+  ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
+
+  shadow_frame->SetVRegReference(0, list_class.Get());
+  UnstartedClassGetSignatureAnnotation(self, shadow_frame, &result, 0);
+  ASSERT_TRUE(result.GetL() != nullptr);
+  ASSERT_FALSE(self->IsExceptionPending());
+
+  ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
+
+  ASSERT_TRUE(result.GetL()->IsObjectArray());
+  ObjPtr<mirror::ObjectArray<mirror::Object>> array =
+      result.GetL()->AsObjectArray<mirror::Object>();
+  std::ostringstream oss;
+  for (int32_t i = 0; i != array->GetLength(); ++i) {
+    ObjPtr<mirror::Object> elem = array->Get(i);
+    ASSERT_TRUE(elem != nullptr);
+    ASSERT_TRUE(elem->IsString());
+    oss << elem->AsString()->ToModifiedUtf8();
+  }
+  std::string output_string = oss.str();
+  ASSERT_EQ(output_string, "<E:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/Collection<TE;>;");
+}
+
 }  // namespace interpreter
 }  // namespace art
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 6ecfd8c..58c5d17 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -419,6 +419,32 @@
                                      JValue* result,
                                      const mirror::MethodHandle::Kind handle_kind)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  // For virtual and interface methods ensure called_method points to
+  // the actual method to invoke.
+  if (handle_kind == mirror::MethodHandle::Kind::kInvokeVirtual ||
+      handle_kind == mirror::MethodHandle::Kind::kInvokeInterface) {
+    uint32_t receiver_reg = is_range ? first_arg : args[0];
+    ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(receiver_reg));
+    if (IsCallerTransformer(callsite_type)) {
+      // The current receiver is an emulated stack frame, the method's
+      // receiver needs to be fetched from there as the emulated frame
+      // will be unpacked into a new frame.
+      receiver = ObjPtr<mirror::EmulatedStackFrame>::DownCast(receiver)->GetReceiver();
+    }
+
+    ObjPtr<mirror::Class> declaring_class(called_method->GetDeclaringClass());
+    if (receiver == nullptr || receiver->GetClass() != declaring_class) {
+      // Verify that _vRegC is an object reference and of the type expected by
+      // the receiver.
+      if (!VerifyObjectIsClass(receiver, declaring_class)) {
+        DCHECK(self->IsExceptionPending());
+        return false;
+      }
+      called_method = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
+          called_method, kRuntimePointerSize);
+    }
+  }
+
   // Compute method information.
   const DexFile::CodeItem* code_item = called_method->GetCodeItem();
 
@@ -502,24 +528,6 @@
     }
   }
 
-  // See TODO in DoInvokePolymorphic : We need to perform this dynamic, receiver
-  // based dispatch right before we perform the actual call, because the
-  // receiver isn't known very early.
-  if (handle_kind == mirror::MethodHandle::Kind::kInvokeVirtual ||
-      handle_kind == mirror::MethodHandle::Kind::kInvokeInterface) {
-    ObjPtr<mirror::Object> receiver(new_shadow_frame->GetVRegReference(first_dest_reg));
-    ObjPtr<mirror::Class> declaring_class(called_method->GetDeclaringClass());
-    // Verify that _vRegC is an object reference and of the type expected by
-    // the receiver.
-    if (!VerifyObjectIsClass(receiver, declaring_class)) {
-      DCHECK(self->IsExceptionPending());
-      return false;
-    }
-
-    called_method = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
-        called_method, kRuntimePointerSize);
-  }
-
   PerformCall(self, code_item, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result);
   if (self->IsExceptionPending()) {
     return false;
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
index ddd84a1..76859ef 100644
--- a/runtime/mirror/emulated_stack_frame.h
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -62,6 +62,10 @@
     return GetFieldObject<MethodType>(OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, type_));
   }
 
+  mirror::Object* GetReceiver() REQUIRES_SHARED(Locks::mutator_lock_) {
+    return GetReferences()->Get(0);
+  }
+
   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/oat.h b/runtime/oat.h
index 0f6657b..656b868 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
-  static constexpr uint8_t kOatVersion[] = { '1', '1', '2', '\0' };  // Manual bump (Revert^3 hash-based DexCache types; stack maps).
+  static constexpr uint8_t kOatVersion[] = { '1', '1', '3', '\0' };  // Invoke info change.
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc
index 7ca233f..a8a0ded 100644
--- a/runtime/openjdkjvmti/ti_class.cc
+++ b/runtime/openjdkjvmti/ti_class.cc
@@ -41,6 +41,7 @@
 #include "class_table-inl.h"
 #include "class_linker.h"
 #include "common_throws.h"
+#include "dex_file_annotations.h"
 #include "events-inl.h"
 #include "gc/heap.h"
 #include "gc_root.h"
@@ -50,6 +51,7 @@
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_ext.h"
+#include "mirror/object_array-inl.h"
 #include "mirror/object_reference.h"
 #include "mirror/object-inl.h"
 #include "mirror/reference.h"
@@ -685,9 +687,30 @@
     *signature_ptr = reinterpret_cast<char*>(tmp);
   }
 
-  // TODO: Support generic signature.
   if (generic_ptr != nullptr) {
     *generic_ptr = nullptr;
+    if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
+      art::StackHandleScope<1> hs(soa.Self());
+      art::Handle<art::mirror::Class> h_klass = hs.NewHandle(klass);
+      art::mirror::ObjectArray<art::mirror::String>* str_array =
+          art::annotations::GetSignatureAnnotationForClass(h_klass);
+      if (str_array != nullptr) {
+        std::ostringstream oss;
+        for (int32_t i = 0; i != str_array->GetLength(); ++i) {
+          oss << str_array->Get(i)->ToModifiedUtf8();
+        }
+        std::string output_string = oss.str();
+        unsigned char* tmp;
+        jvmtiError ret = CopyString(env, output_string.c_str(), &tmp);
+        if (ret != ERR(NONE)) {
+          return ret;
+        }
+        *generic_ptr = reinterpret_cast<char*>(tmp);
+      } else if (soa.Self()->IsExceptionPending()) {
+        // TODO: Should we report an error here?
+        soa.Self()->ClearException();
+      }
+    }
   }
 
   // Everything is fine, release the buffers.
diff --git a/runtime/openjdkjvmti/ti_field.cc b/runtime/openjdkjvmti/ti_field.cc
index a762830..131e6c3 100644
--- a/runtime/openjdkjvmti/ti_field.cc
+++ b/runtime/openjdkjvmti/ti_field.cc
@@ -34,7 +34,9 @@
 #include "art_jvmti.h"
 #include "art_field-inl.h"
 #include "base/enums.h"
+#include "dex_file_annotations.h"
 #include "jni_internal.h"
+#include "mirror/object_array-inl.h"
 #include "modifiers.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread-inl.h"
@@ -91,6 +93,26 @@
   // TODO: Support generic signature.
   if (generic_ptr != nullptr) {
     *generic_ptr = nullptr;
+    if (!art_field->GetDeclaringClass()->IsProxyClass()) {
+      art::mirror::ObjectArray<art::mirror::String>* str_array =
+          art::annotations::GetSignatureAnnotationForField(art_field);
+      if (str_array != nullptr) {
+        std::ostringstream oss;
+        for (int32_t i = 0; i != str_array->GetLength(); ++i) {
+          oss << str_array->Get(i)->ToModifiedUtf8();
+        }
+        std::string output_string = oss.str();
+        unsigned char* tmp;
+        jvmtiError ret = CopyString(env, output_string.c_str(), &tmp);
+        if (ret != ERR(NONE)) {
+          return ret;
+        }
+        *generic_ptr = reinterpret_cast<char*>(tmp);
+      } else if (soa.Self()->IsExceptionPending()) {
+        // TODO: Should we report an error here?
+        soa.Self()->ClearException();
+      }
+    }
   }
 
   // Everything is fine, release the buffers.
diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc
index 2ddd64a..a6cfcc1 100644
--- a/runtime/openjdkjvmti/ti_method.cc
+++ b/runtime/openjdkjvmti/ti_method.cc
@@ -34,7 +34,9 @@
 #include "art_jvmti.h"
 #include "art_method-inl.h"
 #include "base/enums.h"
+#include "dex_file_annotations.h"
 #include "jni_internal.h"
+#include "mirror/object_array-inl.h"
 #include "modifiers.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread-inl.h"
@@ -139,6 +141,26 @@
   // TODO: Support generic signature.
   if (generic_ptr != nullptr) {
     *generic_ptr = nullptr;
+    if (!art_method->GetDeclaringClass()->IsProxyClass()) {
+      art::mirror::ObjectArray<art::mirror::String>* str_array =
+          art::annotations::GetSignatureAnnotationForMethod(art_method);
+      if (str_array != nullptr) {
+        std::ostringstream oss;
+        for (int32_t i = 0; i != str_array->GetLength(); ++i) {
+          oss << str_array->Get(i)->ToModifiedUtf8();
+        }
+        std::string output_string = oss.str();
+        unsigned char* tmp;
+        jvmtiError ret = CopyString(env, output_string.c_str(), &tmp);
+        if (ret != ERR(NONE)) {
+          return ret;
+        }
+        *generic_ptr = reinterpret_cast<char*>(tmp);
+      } else if (soa.Self()->IsExceptionPending()) {
+        // TODO: Should we report an error here?
+        soa.Self()->ClearException();
+      }
+    }
   }
 
   // Everything is fine, release the buffers.
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index f01acc1..8436045 100644
--- a/runtime/openjdkjvmti/ti_redefine.cc
+++ b/runtime/openjdkjvmti/ti_redefine.cc
@@ -747,8 +747,6 @@
       }
     }
   }
-  LOG(WARNING) << "No verification is done on annotations of redefined classes.";
-
   return true;
 }
 
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index f7a6402..67f0b57 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -1145,6 +1145,94 @@
   }
 };
 
+// Format is [native pc, invoke type, method index].
+class InvokeInfoEncoding {
+ public:
+  void SetFromSizes(size_t native_pc_max,
+                    size_t invoke_type_max,
+                    size_t method_index_max) {
+    total_bit_size_ = 0;
+    DCHECK_EQ(kNativePcBitOffset, total_bit_size_);
+    total_bit_size_ += MinimumBitsToStore(native_pc_max);
+    invoke_type_bit_offset_ = total_bit_size_;
+    total_bit_size_ += MinimumBitsToStore(invoke_type_max);
+    method_index_bit_offset_ = total_bit_size_;
+    total_bit_size_ += MinimumBitsToStore(method_index_max);
+  }
+
+  ALWAYS_INLINE FieldEncoding GetNativePcEncoding() const {
+    return FieldEncoding(kNativePcBitOffset, invoke_type_bit_offset_);
+  }
+
+  ALWAYS_INLINE FieldEncoding GetInvokeTypeEncoding() const {
+    return FieldEncoding(invoke_type_bit_offset_, method_index_bit_offset_);
+  }
+
+  ALWAYS_INLINE FieldEncoding GetMethodIndexEncoding() const {
+    return FieldEncoding(method_index_bit_offset_, total_bit_size_);
+  }
+
+  ALWAYS_INLINE size_t BitSize() const {
+    return total_bit_size_;
+  }
+
+  template<typename Vector>
+  void Encode(Vector* dest) const {
+    static_assert(alignof(InvokeInfoEncoding) == 1, "Should not require alignment");
+    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
+    dest->insert(dest->end(), ptr, ptr + sizeof(*this));
+  }
+
+  void Decode(const uint8_t** ptr) {
+    *this = *reinterpret_cast<const InvokeInfoEncoding*>(*ptr);
+    *ptr += sizeof(*this);
+  }
+
+ private:
+  static constexpr uint8_t kNativePcBitOffset = 0;
+  uint8_t invoke_type_bit_offset_;
+  uint8_t method_index_bit_offset_;
+  uint8_t total_bit_size_;
+};
+
+class InvokeInfo {
+ public:
+  explicit InvokeInfo(BitMemoryRegion region) : region_(region) {}
+
+  ALWAYS_INLINE uint32_t GetNativePcOffset(const InvokeInfoEncoding& encoding,
+                                           InstructionSet instruction_set) const {
+    CodeOffset offset(
+        CodeOffset::FromCompressedOffset(encoding.GetNativePcEncoding().Load(region_)));
+    return offset.Uint32Value(instruction_set);
+  }
+
+  ALWAYS_INLINE void SetNativePcCodeOffset(const InvokeInfoEncoding& encoding,
+                                           CodeOffset native_pc_offset) {
+    encoding.GetNativePcEncoding().Store(region_, native_pc_offset.CompressedValue());
+  }
+
+  ALWAYS_INLINE uint32_t GetInvokeType(const InvokeInfoEncoding& encoding) const {
+    return encoding.GetInvokeTypeEncoding().Load(region_);
+  }
+
+  ALWAYS_INLINE void SetInvokeType(const InvokeInfoEncoding& encoding, uint32_t invoke_type) {
+    encoding.GetInvokeTypeEncoding().Store(region_, invoke_type);
+  }
+
+  ALWAYS_INLINE uint32_t GetMethodIndex(const InvokeInfoEncoding& encoding) const {
+    return encoding.GetMethodIndexEncoding().Load(region_);
+  }
+
+  ALWAYS_INLINE void SetMethodIndex(const InvokeInfoEncoding& encoding, uint32_t method_index) {
+    encoding.GetMethodIndexEncoding().Store(region_, method_index);
+  }
+
+  bool IsValid() const { return region_.pointer() != nullptr; }
+
+ private:
+  BitMemoryRegion region_;
+};
+
 // Most of the fields are encoded as ULEB128 to save space.
 struct CodeInfoEncoding {
   static constexpr uint32_t kInvalidSize = static_cast<size_t>(-1);
@@ -1154,6 +1242,7 @@
   BitEncodingTable<StackMapEncoding> stack_map;
   BitEncodingTable<BitRegionEncoding> register_mask;
   BitEncodingTable<BitRegionEncoding> stack_mask;
+  BitEncodingTable<InvokeInfoEncoding> invoke_info;
   BitEncodingTable<InlineInfoEncoding> inline_info;
 
   CodeInfoEncoding() {}
@@ -1165,6 +1254,7 @@
     stack_map.Decode(&ptr);
     register_mask.Decode(&ptr);
     stack_mask.Decode(&ptr);
+    invoke_info.Decode(&ptr);
     if (stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
       inline_info.Decode(&ptr);
     } else {
@@ -1183,6 +1273,7 @@
     stack_map.Encode(dest);
     register_mask.Encode(dest);
     stack_mask.Encode(dest);
+    invoke_info.Encode(dest);
     if (stack_map.encoding.GetInlineInfoEncoding().BitSize() > 0) {
       inline_info.Encode(dest);
     }
@@ -1199,6 +1290,7 @@
     stack_map.UpdateBitOffset(&bit_offset);
     register_mask.UpdateBitOffset(&bit_offset);
     stack_mask.UpdateBitOffset(&bit_offset);
+    invoke_info.UpdateBitOffset(&bit_offset);
     inline_info.UpdateBitOffset(&bit_offset);
     cache_non_header_size = RoundUp(bit_offset, kBitsPerByte) / kBitsPerByte - HeaderSize();
   }
@@ -1303,6 +1395,10 @@
     return encoding.stack_map.encoding.BitSize() * GetNumberOfStackMaps(encoding);
   }
 
+  InvokeInfo GetInvokeInfo(const CodeInfoEncoding& encoding, size_t index) const {
+    return InvokeInfo(encoding.invoke_info.BitRegion(region_, index));
+  }
+
   DexRegisterMap GetDexRegisterMapOf(StackMap stack_map,
                                      const CodeInfoEncoding& encoding,
                                      size_t number_of_dex_registers) const {
@@ -1426,6 +1522,17 @@
     return StackMap();
   }
 
+  InvokeInfo GetInvokeInfoForNativePcOffset(uint32_t native_pc_offset,
+                                            const CodeInfoEncoding& encoding) {
+    for (size_t index = 0; index < encoding.invoke_info.num_entries; index++) {
+      InvokeInfo item = GetInvokeInfo(encoding, index);
+      if (item.GetNativePcOffset(encoding.invoke_info.encoding, kRuntimeISA) == native_pc_offset) {
+        return item;
+      }
+    }
+    return InvokeInfo(BitMemoryRegion());
+  }
+
   // Dump this CodeInfo object on `os`.  `code_offset` is the (absolute)
   // native PC of the compiled method and `number_of_dex_registers` the
   // number of Dex virtual registers used in this method.  If
diff --git a/test/021-string2/src/Main.java b/test/021-string2/src/Main.java
index 5a43a4f..0dd82ab 100644
--- a/test/021-string2/src/Main.java
+++ b/test/021-string2/src/Main.java
@@ -16,6 +16,7 @@
 
 import junit.framework.Assert;
 import java.lang.reflect.Method;
+import java.util.Locale;
 
 /**
  * more string tests
@@ -120,6 +121,12 @@
 
         testEqualsConstString();
         testConstStringEquals();
+
+        // Regression tests for String.setCharAt() breaking string compression invariants.
+        Locale en_US = new Locale("en", "US");
+        Assert.assertEquals("I", /* Small latin dotless i */ "\u0131".toUpperCase());
+        Assert.assertEquals("abc", "a\u0131c".replace('\u0131', 'b'));
+        Assert.assertEquals("a\u0131c", "abc".replace('b', '\u0131'));
     }
 
     public static void testCompareToAndEquals() {
diff --git a/test/044-proxy/build b/test/044-proxy/build
deleted file mode 100755
index ab956e2..0000000
--- a/test/044-proxy/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental java-8
diff --git a/test/624-checker-stringops/src/Main.java b/test/624-checker-stringops/src/Main.java
index 75b782e..63da4f5 100644
--- a/test/624-checker-stringops/src/Main.java
+++ b/test/624-checker-stringops/src/Main.java
@@ -232,8 +232,9 @@
   /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter
   static int bufferDeadLoop() {
     StringBuffer b = new StringBuffer();
+    String x = "x";
     for (int i = 0; i < 10; i++) {
-      int d = b.toString().indexOf("x", 1);
+      int d = b.toString().indexOf(x, 1);
     }
     return b.length();
   }
@@ -252,8 +253,9 @@
   /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter
   static int builderDeadLoop() {
     StringBuilder b = new StringBuilder();
+    String x = "x";
     for (int i = 0; i < 10; i++) {
-      int d = b.toString().indexOf("x", 1);
+      int d = b.toString().indexOf(x, 1);
     }
     return b.length();
   }
diff --git a/test/901-hello-ti-agent/build b/test/901-hello-ti-agent/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/901-hello-ti-agent/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/902-hello-transformation/build b/test/902-hello-transformation/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/902-hello-transformation/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/903-hello-tagging/build b/test/903-hello-tagging/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/903-hello-tagging/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/904-object-allocation/build b/test/904-object-allocation/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/904-object-allocation/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/905-object-free/build b/test/905-object-free/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/905-object-free/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/906-iterate-heap/build b/test/906-iterate-heap/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/906-iterate-heap/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/908-gc-start-finish/build b/test/908-gc-start-finish/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/908-gc-start-finish/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/909-attach-agent/build b/test/909-attach-agent/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/909-attach-agent/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/910-methods/build b/test/910-methods/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/910-methods/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/910-methods/expected.txt b/test/910-methods/expected.txt
index c913b3f..e87929f 100644
--- a/test/910-methods/expected.txt
+++ b/test/910-methods/expected.txt
@@ -28,7 +28,7 @@
 Is native: true
 Is obsolete: false
 Is synthetic: false
-[add, (Ljava/lang/Object;)Z, null]
+[add, (Ljava/lang/Object;)Z, (TE;)Z]
 interface java.util.List
 1025
 Max locals: 0
diff --git a/test/911-get-stack-trace/build b/test/911-get-stack-trace/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/911-get-stack-trace/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/912-classes/build b/test/912-classes/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/912-classes/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt
index 328216b..e932b20 100644
--- a/test/912-classes/expected.txt
+++ b/test/912-classes/expected.txt
@@ -1,10 +1,10 @@
 [Ljava/lang/Object;, null]
 1
-[Ljava/lang/String;, null]
+[Ljava/lang/String;, Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/lang/CharSequence;]
 11
 [Ljava/lang/Math;, null]
 11
-[Ljava/util/List;, null]
+[Ljava/util/List;, <E:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/Collection<TE;>;]
 601
 [L$Proxy0;, null]
 11
diff --git a/test/913-heaps/build b/test/913-heaps/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/913-heaps/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/914-hello-obsolescence/build b/test/914-hello-obsolescence/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/914-hello-obsolescence/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/915-obsolete-2/build b/test/915-obsolete-2/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/915-obsolete-2/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/916-obsolete-jit/build b/test/916-obsolete-jit/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/916-obsolete-jit/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/917-fields-transformation/build b/test/917-fields-transformation/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/917-fields-transformation/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/918-fields/build b/test/918-fields/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/918-fields/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/918-fields/expected.txt b/test/918-fields/expected.txt
index 39d3e70..1a1209c 100644
--- a/test/918-fields/expected.txt
+++ b/test/918-fields/expected.txt
@@ -14,3 +14,7 @@
 interface Main$Bar
 25
 false
+[generics, Ljava/lang/Object;, TT;]
+class Main$Generics
+0
+false
diff --git a/test/918-fields/src/Main.java b/test/918-fields/src/Main.java
index 3ba535b..ad0d0c5 100644
--- a/test/918-fields/src/Main.java
+++ b/test/918-fields/src/Main.java
@@ -27,6 +27,7 @@
     testField(Integer.class, "value");
     testField(Foo.class, "this$0");
     testField(Bar.class, "VAL");
+    testField(Generics.class, "generics");
   }
 
   private static void testField(Class<?> base, String fieldName)
@@ -65,4 +66,8 @@
   private static interface Bar {
     public static int VAL = 1;
   }
+
+  private static class Generics<T> {
+    T generics;
+  }
 }
diff --git a/test/919-obsolete-fields/build b/test/919-obsolete-fields/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/919-obsolete-fields/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/920-objects/build b/test/920-objects/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/920-objects/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/921-hello-failure/build b/test/921-hello-failure/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/921-hello-failure/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/922-properties/build b/test/922-properties/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/922-properties/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/923-monitors/build b/test/923-monitors/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/923-monitors/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/924-threads/build b/test/924-threads/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/924-threads/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/925-threadgroups/build b/test/925-threadgroups/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/925-threadgroups/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/926-multi-obsolescence/build b/test/926-multi-obsolescence/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/926-multi-obsolescence/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/927-timers/build b/test/927-timers/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/927-timers/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/928-jni-table/build b/test/928-jni-table/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/928-jni-table/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/929-search/build b/test/929-search/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/929-search/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/930-hello-retransform/build b/test/930-hello-retransform/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/930-hello-retransform/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/931-agent-thread/build b/test/931-agent-thread/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/931-agent-thread/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/932-transform-saves/build b/test/932-transform-saves/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/932-transform-saves/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/933-misc-events/build b/test/933-misc-events/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/933-misc-events/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/934-load-transform/build b/test/934-load-transform/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/934-load-transform/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/935-non-retransformable/build b/test/935-non-retransformable/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/935-non-retransformable/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/936-search-onload/build b/test/936-search-onload/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/936-search-onload/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/937-hello-retransform-package/build b/test/937-hello-retransform-package/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/937-hello-retransform-package/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/938-load-transform-bcp/build b/test/938-load-transform-bcp/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/938-load-transform-bcp/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/939-hello-transformation-bcp/build b/test/939-hello-transformation-bcp/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/939-hello-transformation-bcp/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/940-recursive-obsolete/build b/test/940-recursive-obsolete/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/940-recursive-obsolete/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/941-recurive-obsolete-jit/build b/test/941-recurive-obsolete-jit/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/941-recurive-obsolete-jit/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/942-private-recursive/build b/test/942-private-recursive/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/942-private-recursive/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/943-private-recursive-jit/build b/test/943-private-recursive-jit/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/943-private-recursive-jit/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/944-transform-classloaders/build b/test/944-transform-classloaders/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/944-transform-classloaders/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/945-obsolete-native/build b/test/945-obsolete-native/build
deleted file mode 100755
index 898e2e5..0000000
--- a/test/945-obsolete-native/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/946-obsolete-throw/build b/test/946-obsolete-throw/build
deleted file mode 100755
index ebbc368..0000000
--- a/test/946-obsolete-throw/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/947-reflect-method/build b/test/947-reflect-method/build
deleted file mode 100755
index ebbc368..0000000
--- a/test/947-reflect-method/build
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-./default-build "$@" --experimental agents
diff --git a/test/907-get-loaded-classes/build b/test/948-change-annotations/build
similarity index 100%
rename from test/907-get-loaded-classes/build
rename to test/948-change-annotations/build
diff --git a/test/948-change-annotations/expected.txt b/test/948-change-annotations/expected.txt
new file mode 100644
index 0000000..7974c7a
--- /dev/null
+++ b/test/948-change-annotations/expected.txt
@@ -0,0 +1,21 @@
+Running test class RemoveAnnotationsTest
+Type annotations: [@TestClassAnnotation1(value=hello)]
+method public void Transform.sayHi() -> [@TestMethodAnnotation1(value=hi hi)]
+hello
+Goodbye
+Type annotations: []
+method public void Transform.sayHi() -> []
+Running test class AddAnnotationsTest
+Type annotations: [@TestClassAnnotation1(value=hello)]
+method public void Transform.sayHi() -> [@TestMethodAnnotation1(value=hi hi)]
+hello
+Goodbye
+Type annotations: [@TestClassAnnotation1(value=hello), @TestClassAnnotation2(value=hello2)]
+method public void Transform.sayHi() -> [@TestMethodAnnotation1(value=hi hi), @TestMethodAnnotation2(value=hi hi2)]
+Running test class ChangeAnnotationValues
+Type annotations: [@TestClassAnnotation1(value=hello)]
+method public void Transform.sayHi() -> [@TestMethodAnnotation1(value=hi hi)]
+hello
+Goodbye
+Type annotations: [@TestClassAnnotation1(value=Goodbye)]
+method public void Transform.sayHi() -> [@TestMethodAnnotation1(value=Bye Bye)]
diff --git a/test/948-change-annotations/info.txt b/test/948-change-annotations/info.txt
new file mode 100644
index 0000000..875a5f6
--- /dev/null
+++ b/test/948-change-annotations/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/900-hello-plugin/build b/test/948-change-annotations/run
similarity index 92%
rename from test/900-hello-plugin/build
rename to test/948-change-annotations/run
index 898e2e5..c6e62ae 100755
--- a/test/900-hello-plugin/build
+++ b/test/948-change-annotations/run
@@ -14,4 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-./default-build "$@" --experimental agents
+./default-run "$@" --jvmti
diff --git a/test/948-change-annotations/src/AddAnnotationsTest.java b/test/948-change-annotations/src/AddAnnotationsTest.java
new file mode 100644
index 0000000..6876e87
--- /dev/null
+++ b/test/948-change-annotations/src/AddAnnotationsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Base64;
+public class AddAnnotationsTest implements TestCase {
+  /**
+   * base64 encoded class/dex file for
+   * @TestClassAnnotation1("hello")
+   * @TestClassAnnotation2("hello2")
+   * class Transform {
+   *   @TestMethodAnnotation1("hi hi")
+   *   @TestMethodAnnotation2("hi hi2")
+   *   public void sayHi() {
+   *    System.out.println("Goodbye");
+   *   }
+   * }
+   */
+  private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+    "yv66vgAAADQAKQoABgAbCQAcAB0IAB4KAB8AIAcAIQcAIgEABjxpbml0PgEAAygpVgEABENvZGUB" +
+    "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQALTFRyYW5zZm9y" +
+    "bTsBAAVzYXlIaQEAGVJ1bnRpbWVWaXNpYmxlQW5ub3RhdGlvbnMBABdMVGVzdE1ldGhvZEFubm90" +
+    "YXRpb24xOwEABXZhbHVlAQAFaGkgaGkBABdMVGVzdE1ldGhvZEFubm90YXRpb24yOwEABmhpIGhp" +
+    "MgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQEAFkxUZXN0Q2xhc3NBbm5vdGF0aW9uMTsB" +
+    "AAVoZWxsbwEAFkxUZXN0Q2xhc3NBbm5vdGF0aW9uMjsBAAZoZWxsbzIMAAcACAcAIwwAJAAlAQAH" +
+    "R29vZGJ5ZQcAJgwAJwAoAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFu" +
+    "Zy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3Ry" +
+    "ZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAgAAUABgAAAAAAAgAAAAcACAAB" +
+    "AAkAAAAvAAEAAQAAAAUqtwABsQAAAAIACgAAAAYAAQAAABMACwAAAAwAAQAAAAUADAANAAAAAQAO" +
+    "AAgAAgAJAAAANwACAAEAAAAJsgACEgO2AASxAAAAAgAKAAAACgACAAAAFwAIABgACwAAAAwAAQAA" +
+    "AAkADAANAAAADwAAABQAAgAQAAEAEXMAEgATAAEAEXMAFAACABUAAAACABYADwAAABQAAgAXAAEA" +
+    "EXMAGAAZAAEAEXMAGg==");
+  private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+    "ZGV4CjAzNQA7mPKPjUKe43s+OLHHgFVRVCAPn/rRz9z0AwAAcAAAAHhWNBIAAAAAAAAAADADAAAX" +
+    "AAAAcAAAAAoAAADMAAAAAgAAAPQAAAABAAAADAEAAAQAAAAUAQAAAQAAADQBAACgAgAAVAEAAMYB" +
+    "AADOAQAA1wEAAO8BAAAHAgAAIAIAADkCAABGAgAAXQIAAHECAACFAgAAmQIAAKkCAACsAgAAsAIA" +
+    "AMQCAADLAgAA0wIAANoCAADiAgAA5wIAAPACAAD3AgAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAA" +
+    "CAAAAAkAAAAKAAAADAAAAAwAAAAJAAAAAAAAAA0AAAAJAAAAwAEAAAgABQATAAAABAAAAAAAAAAE" +
+    "AAAAFQAAAAUAAQAUAAAABgAAAAAAAAAEAAAAAAAAAAYAAAAAAAAACwAAAKgBAAAhAwAAAAAAAAIA" +
+    "AAAJAwAADwMAAAIAAAAVAwAAGwMAAAEAAQABAAAA/gIAAAQAAABwEAMAAAAOAAMAAQACAAAAAwMA" +
+    "AAkAAABiAAAAGwEBAAAAbiACABAADgAAAFQBAAAAAAAAAQAAAAAAAAABAAAAYAEAAAEAAAAHAAY8" +
+    "aW5pdD4AB0dvb2RieWUAFkxUZXN0Q2xhc3NBbm5vdGF0aW9uMTsAFkxUZXN0Q2xhc3NBbm5vdGF0" +
+    "aW9uMjsAF0xUZXN0TWV0aG9kQW5ub3RhdGlvbjE7ABdMVGVzdE1ldGhvZEFubm90YXRpb24yOwAL" +
+    "TFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJM" +
+    "amF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xhbmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYA" +
+    "AlZMABJlbWl0dGVyOiBqYWNrLTQuMjUABWhlbGxvAAZoZWxsbzIABWhpIGhpAAZoaSBoaTIAA291" +
+    "dAAHcHJpbnRsbgAFc2F5SGkABXZhbHVlABMABw4AFwAHDocAAQABFhcPAQEBFhcQAQIBFhcRAQMB" +
+    "FhcSAAABAQCAgATsAgEBhAMAEAAAAAAAAAABAAAAAAAAAAEAAAAXAAAAcAAAAAIAAAAKAAAAzAAA" +
+    "AAMAAAACAAAA9AAAAAQAAAABAAAADAEAAAUAAAAEAAAAFAEAAAYAAAABAAAANAEAAAMQAAACAAAA" +
+    "VAEAAAEgAAACAAAAbAEAAAYgAAABAAAAqAEAAAEQAAABAAAAwAEAAAIgAAAXAAAAxgEAAAMgAAAC" +
+    "AAAA/gIAAAQgAAAEAAAACQMAAAAgAAABAAAAIQMAAAAQAAABAAAAMAMAAA==");
+
+  public void runTest(Transform t) {
+    t.sayHi();
+    Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+    t.sayHi();
+  }
+}
diff --git a/test/948-change-annotations/src/ChangeAnnotationValues.java b/test/948-change-annotations/src/ChangeAnnotationValues.java
new file mode 100644
index 0000000..89a766c
--- /dev/null
+++ b/test/948-change-annotations/src/ChangeAnnotationValues.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Base64;
+public class ChangeAnnotationValues implements TestCase {
+  /**
+   * base64 encoded class/dex file for
+   * @TestClassAnnotation1("Goodbye")
+   * class Transform {
+   *   @TestMethodAnnotation1("Bye Bye")
+   *   public void sayHi() {
+   *    System.out.println("Goodbye");
+   *   }
+   * }
+   */
+  private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+    "yv66vgAAADQAJAoABgAXCQAYABkIABYKABoAGwcAHAcAHQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+    "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQALTFRyYW5zZm9y" +
+    "bTsBAAVzYXlIaQEAGVJ1bnRpbWVWaXNpYmxlQW5ub3RhdGlvbnMBABdMVGVzdE1ldGhvZEFubm90" +
+    "YXRpb24xOwEABXZhbHVlAQAHQnllIEJ5ZQEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQEA" +
+    "FkxUZXN0Q2xhc3NBbm5vdGF0aW9uMTsBAAdHb29kYnllDAAHAAgHAB4MAB8AIAcAIQwAIgAjAQAJ" +
+    "VHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVM" +
+    "amF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShM" +
+    "amF2YS9sYW5nL1N0cmluZzspVgAgAAUABgAAAAAAAgAAAAcACAABAAkAAAAvAAEAAQAAAAUqtwAB" +
+    "sQAAAAIACgAAAAYAAQAAAAIACwAAAAwAAQAAAAUADAANAAAAAQAOAAgAAgAJAAAANwACAAEAAAAJ" +
+    "sgACEgO2AASxAAAAAgAKAAAACgACAAAABQAIAAYACwAAAAwAAQAAAAkADAANAAAADwAAAAsAAQAQ" +
+    "AAEAEXMAEgACABMAAAACABQADwAAAAsAAQAVAAEAEXMAFg==");
+  private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+    "ZGV4CjAzNQAXfYs9FUE830lxfnB+X66S7iZiP5A7uDSAAwAAcAAAAHhWNBIAAAAAAAAAALwCAAAS" +
+    "AAAAcAAAAAgAAAC4AAAAAgAAANgAAAABAAAA8AAAAAQAAAD4AAAAAQAAABgBAABIAgAAOAEAAKIB" +
+    "AACqAQAAswEAALwBAADUAQAA7QEAAPoBAAARAgAAJQIAADkCAABNAgAAXQIAAGACAABkAgAAeAIA" +
+    "AH0CAACGAgAAjQIAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAALAAAACwAAAAcAAAAAAAAA" +
+    "DAAAAAcAAACcAQAABgADAA4AAAACAAAAAAAAAAIAAAAQAAAAAwABAA8AAAAEAAAAAAAAAAIAAAAA" +
+    "AAAABAAAAAAAAAAKAAAAhAEAAKsCAAAAAAAAAQAAAJ8CAAABAAAApQIAAAEAAQABAAAAlAIAAAQA" +
+    "AABwEAMAAAAOAAMAAQACAAAAmQIAAAkAAABiAAAAGwECAAAAbiACABAADgAAADgBAAAAAAAAAQAA" +
+    "AAAAAAABAAAAQAEAAAEAAAAFAAY8aW5pdD4AB0J5ZSBCeWUAB0dvb2RieWUAFkxUZXN0Q2xhc3NB" +
+    "bm5vdGF0aW9uMTsAF0xUZXN0TWV0aG9kQW5ub3RhdGlvbjE7AAtMVHJhbnNmb3JtOwAVTGphdmEv" +
+    "aW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAS" +
+    "TGphdmEvbGFuZy9TeXN0ZW07AA5UcmFuc2Zvcm0uamF2YQABVgACVkwAEmVtaXR0ZXI6IGphY2st" +
+    "NC4yNQADb3V0AAdwcmludGxuAAVzYXlIaQAFdmFsdWUAAgAHDgAFAAcOhwABAAERFwIBAQERFwEA" +
+    "AAEBAICABMgCAQHgAgAAABAAAAAAAAAAAQAAAAAAAAABAAAAEgAAAHAAAAACAAAACAAAALgAAAAD" +
+    "AAAAAgAAANgAAAAEAAAAAQAAAPAAAAAFAAAABAAAAPgAAAAGAAAAAQAAABgBAAADEAAAAgAAADgB" +
+    "AAABIAAAAgAAAEgBAAAGIAAAAQAAAIQBAAABEAAAAQAAAJwBAAACIAAAEgAAAKIBAAADIAAAAgAA" +
+    "AJQCAAAEIAAAAgAAAJ8CAAAAIAAAAQAAAKsCAAAAEAAAAQAAALwCAAA=");
+
+  public void runTest(Transform t) {
+    t.sayHi();
+    Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+    t.sayHi();
+  }
+}
diff --git a/test/948-change-annotations/src/Main.java b/test/948-change-annotations/src/Main.java
new file mode 100644
index 0000000..30bfbf9
--- /dev/null
+++ b/test/948-change-annotations/src/Main.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Comparator;
+import java.lang.reflect.*;
+import java.lang.annotation.*;
+public class Main {
+
+  /**
+   * base64 encoded class/dex file for for initial Transform.java
+   */
+  private static final byte[] INITIAL_CLASS_BYTES = Base64.getDecoder().decode(
+    "yv66vgAAADQAJAoABgAXCQAYABkIABYKABoAGwcAHAcAHQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+    "AA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQALTFRyYW5zZm9y" +
+    "bTsBAAVzYXlIaQEAGVJ1bnRpbWVWaXNpYmxlQW5ub3RhdGlvbnMBABdMVGVzdE1ldGhvZEFubm90" +
+    "YXRpb24xOwEABXZhbHVlAQAFaGkgaGkBAApTb3VyY2VGaWxlAQAOVHJhbnNmb3JtLmphdmEBABZM" +
+    "VGVzdENsYXNzQW5ub3RhdGlvbjE7AQAFaGVsbG8MAAcACAcAHgwAHwAgBwAhDAAiACMBAAlUcmFu" +
+    "c2Zvcm0BABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZh" +
+    "L2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZh" +
+    "L2xhbmcvU3RyaW5nOylWACAABQAGAAAAAAACAAAABwAIAAEACQAAAC8AAQABAAAABSq3AAGxAAAA" +
+    "AgAKAAAABgABAAAAEgALAAAADAABAAAABQAMAA0AAAABAA4ACAACAAkAAAA3AAIAAQAAAAmyAAIS" +
+    "A7YABLEAAAACAAoAAAAKAAIAAAAVAAgAFgALAAAADAABAAAACQAMAA0AAAAPAAAACwABABAAAQAR" +
+    "cwASAAIAEwAAAAIAFAAPAAAACwABABUAAQARcwAW");
+  private static final byte[] INITIAL_DEX_BYTES = Base64.getDecoder().decode(
+    "ZGV4CjAzNQCufKz9atC18kWgSsEfRq699UEcX4cHonN8AwAAcAAAAHhWNBIAAAAAAAAAALgCAAAS" +
+    "AAAAcAAAAAgAAAC4AAAAAgAAANgAAAABAAAA8AAAAAQAAAD4AAAAAQAAABgBAABEAgAAOAEAAKIB" +
+    "AACqAQAAwgEAANsBAADoAQAA/wEAABMCAAAnAgAAOwIAAEsCAABOAgAAUgIAAGYCAABtAgAAdAIA" +
+    "AHkCAACCAgAAiQIAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAJAAAACQAAAAcAAAAAAAAA" +
+    "CgAAAAcAAACcAQAABgADAA4AAAACAAAAAAAAAAIAAAAQAAAAAwABAA8AAAAEAAAAAAAAAAIAAAAA" +
+    "AAAABAAAAAAAAAAIAAAAhAEAAKcCAAAAAAAAAQAAAJsCAAABAAAAoQIAAAEAAQABAAAAkAIAAAQA" +
+    "AABwEAMAAAAOAAMAAQACAAAAlQIAAAkAAABiAAAAGwEMAAAAbiACABAADgAAADgBAAAAAAAAAQAA" +
+    "AAAAAAABAAAAQAEAAAEAAAAFAAY8aW5pdD4AFkxUZXN0Q2xhc3NBbm5vdGF0aW9uMTsAF0xUZXN0" +
+    "TWV0aG9kQW5ub3RhdGlvbjE7AAtMVHJhbnNmb3JtOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJM" +
+    "amF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07" +
+    "AA5UcmFuc2Zvcm0uamF2YQABVgACVkwAEmVtaXR0ZXI6IGphY2stNC4yNQAFaGVsbG8ABWhpIGhp" +
+    "AANvdXQAB3ByaW50bG4ABXNheUhpAAV2YWx1ZQASAAcOABUABw6HAAEAAREXDAEBAREXDQAAAQEA" +
+    "gIAEyAIBAeACAAAAEAAAAAAAAAABAAAAAAAAAAEAAAASAAAAcAAAAAIAAAAIAAAAuAAAAAMAAAAC" +
+    "AAAA2AAAAAQAAAABAAAA8AAAAAUAAAAEAAAA+AAAAAYAAAABAAAAGAEAAAMQAAACAAAAOAEAAAEg" +
+    "AAACAAAASAEAAAYgAAABAAAAhAEAAAEQAAABAAAAnAEAAAIgAAASAAAAogEAAAMgAAACAAAAkAIA" +
+    "AAQgAAACAAAAmwIAAAAgAAABAAAApwIAAAAQAAABAAAAuAIAAA==");
+
+  public static void main(String[] args) {
+    doTest(new RemoveAnnotationsTest());
+    doTest(new AddAnnotationsTest());
+    doTest(new ChangeAnnotationValues());
+  }
+
+  private static Annotation[] sortedAnno(Annotation[] annos) {
+    Arrays.sort(annos, Comparator.comparing((v) -> v.toString()));
+    return annos;
+  }
+
+  public static void doTest(TestCase t) {
+    // Get back to normal first.
+    doCommonClassRedefinition(Transform.class, INITIAL_CLASS_BYTES, INITIAL_DEX_BYTES);
+    System.out.println("Running test " + t.getClass());
+    printAnnotations(Transform.class);
+    t.runTest(new Transform());
+    printAnnotations(Transform.class);
+  }
+
+  private static void printAnnotations(Class<?> transform) {
+    System.out.println("Type annotations: "
+        + Arrays.toString(sortedAnno(transform.getAnnotations())));
+    for (Method m : transform.getDeclaredMethods()) {
+      System.out.println("method " + m + " -> "
+          + Arrays.toString(sortedAnno(m.getDeclaredAnnotations())));
+    }
+  }
+
+  // Transforms the class
+  public static native void doCommonClassRedefinition(Class<?> target,
+                                                      byte[] class_file,
+                                                      byte[] dex_file);
+}
diff --git a/test/948-change-annotations/src/RemoveAnnotationsTest.java b/test/948-change-annotations/src/RemoveAnnotationsTest.java
new file mode 100644
index 0000000..3b1725a
--- /dev/null
+++ b/test/948-change-annotations/src/RemoveAnnotationsTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Base64;
+public class RemoveAnnotationsTest implements TestCase {
+  /**
+   * base64 encoded class/dex file for
+   * class Transform {
+   *   public void sayHi() {
+   *    System.out.println("Goodbye");
+   *   }
+   * }
+   */
+  private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+    "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+    "AA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwA" +
+    "BwAIBwAWDAAXABgBAAdHb29kYnllBwAZDAAaABsBAAlUcmFuc2Zvcm0BABBqYXZhL2xhbmcvT2Jq" +
+    "ZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2ph" +
+    "dmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACAABQAG" +
+    "AAAAAAACAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAAEQABAAsACAAB" +
+    "AAkAAAAlAAIAAQAAAAmyAAISA7YABLEAAAABAAoAAAAKAAIAAAATAAgAFAABAAwAAAACAA0=");
+  private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+    "ZGV4CjAzNQCLXSBQ5FiS3f16krSYZFF8xYZtFVp0GRXMAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAO" +
+    "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACsAQAAIAEAAGIB" +
+    "AABqAQAAcwEAAIABAACXAQAAqwEAAL8BAADTAQAA4wEAAOYBAADqAQAA/gEAAAMCAAAMAgAAAgAA" +
+    "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
+    "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAAB4CAAAA" +
+    "AAAAAQABAAEAAAATAgAABAAAAHAQAwAAAA4AAwABAAIAAAAYAgAACQAAAGIAAAAbAQEAAABuIAIA" +
+    "EAAOAAAAAQAAAAMABjxpbml0PgAHR29vZGJ5ZQALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50" +
+    "U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xh" +
+    "bmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTMuMzYAA291" +
+    "dAAHcHJpbnRsbgAFc2F5SGkAEQAHDgATAAcOhQAAAAEBAICABKACAQG4Ag0AAAAAAAAAAQAAAAAA" +
+    "AAABAAAADgAAAHAAAAACAAAABgAAAKgAAAADAAAAAgAAAMAAAAAEAAAAAQAAANgAAAAFAAAABAAA" +
+    "AOAAAAAGAAAAAQAAAAABAAABIAAAAgAAACABAAABEAAAAQAAAFwBAAACIAAADgAAAGIBAAADIAAA" +
+    "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA=");
+
+  public void runTest(Transform t) {
+    t.sayHi();
+    Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+    t.sayHi();
+  }
+}
diff --git a/test/948-change-annotations/src/TestCase.java b/test/948-change-annotations/src/TestCase.java
new file mode 100644
index 0000000..9edc01e4
--- /dev/null
+++ b/test/948-change-annotations/src/TestCase.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public interface TestCase {
+  public void runTest(Transform t);
+}
diff --git a/test/948-change-annotations/src/TestClassAnnotation1.java b/test/948-change-annotations/src/TestClassAnnotation1.java
new file mode 100644
index 0000000..adef98f
--- /dev/null
+++ b/test/948-change-annotations/src/TestClassAnnotation1.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.annotation.*;
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @ interface TestClassAnnotation1 {
+  public String value();
+}
diff --git a/test/948-change-annotations/src/TestClassAnnotation2.java b/test/948-change-annotations/src/TestClassAnnotation2.java
new file mode 100644
index 0000000..67e6260
--- /dev/null
+++ b/test/948-change-annotations/src/TestClassAnnotation2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.annotation.*;
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @ interface TestClassAnnotation2 {
+  public String value();
+}
diff --git a/test/948-change-annotations/src/TestMethodAnnotation1.java b/test/948-change-annotations/src/TestMethodAnnotation1.java
new file mode 100644
index 0000000..d3920f3
--- /dev/null
+++ b/test/948-change-annotations/src/TestMethodAnnotation1.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.annotation.*;
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @ interface TestMethodAnnotation1 {
+  public String value();
+}
diff --git a/test/948-change-annotations/src/TestMethodAnnotation2.java b/test/948-change-annotations/src/TestMethodAnnotation2.java
new file mode 100644
index 0000000..2d5bb72
--- /dev/null
+++ b/test/948-change-annotations/src/TestMethodAnnotation2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.annotation.*;
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @ interface TestMethodAnnotation2 {
+  public String value();
+}
diff --git a/test/948-change-annotations/src/Transform.java b/test/948-change-annotations/src/Transform.java
new file mode 100644
index 0000000..1c6a145
--- /dev/null
+++ b/test/948-change-annotations/src/Transform.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@TestClassAnnotation1("hello")
+class Transform {
+  @TestMethodAnnotation1("hi hi")
+  public void sayHi() {
+    System.out.println("hello");
+  }
+}
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index fc9f030..cb06e42 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -183,15 +183,23 @@
     public String bar();
   }
 
-  public static class BarSuper {
+  public static abstract class BarAbstractSuper {
+    public abstract String abstractSuperPublicMethod();
+  }
+
+  public static class BarSuper extends BarAbstractSuper {
     public String superPublicMethod() {
       return "superPublicMethod";
     }
 
-    public String superProtectedMethod() {
+    protected String superProtectedMethod() {
       return "superProtectedMethod";
     }
 
+    public String abstractSuperPublicMethod() {
+      return "abstractSuperPublicMethod";
+    }
+
     String superPackageMethod() {
       return "superPackageMethod";
     }
@@ -288,15 +296,19 @@
       System.out.println("Unexpected return value for BarImpl#bar: " + str);
     }
 
-    // TODO(narayan): Fix this case, we're using the wrong ArtMethod for the
-    // invoke resulting in a failing check in the interpreter.
-    //
-    // mh = MethodHandles.lookup().findVirtual(Bar.class, "bar",
-    //    MethodType.methodType(String.class));
-    // str = (String) mh.invoke(new BarImpl());
-    // if (!"bar".equals(str)) {
-    //   System.out.println("Unexpected return value for BarImpl#bar: " + str);
-    // }
+    mh = MethodHandles.lookup().findVirtual(Bar.class, "bar",
+                                            MethodType.methodType(String.class));
+    str = (String) mh.invoke(new BarImpl());
+    if (!"bar".equals(str)) {
+      System.out.println("Unexpected return value for BarImpl#bar: " + str);
+    }
+
+    mh = MethodHandles.lookup().findVirtual(BarAbstractSuper.class, "abstractSuperPublicMethod",
+        MethodType.methodType(String.class));
+    str = (String) mh.invoke(new BarImpl());
+    if (!"abstractSuperPublicMethod".equals(str)) {
+      System.out.println("Unexpected return value for BarImpl#abstractSuperPublicMethod: " + str);
+    }
 
     // We should also be able to lookup public / protected / package methods in
     // the super class, given sufficient access privileges.
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 1938b92..c14a0b2 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -898,12 +898,24 @@
   endif
 endef
 
+COMPILER_TYPES_2 := optimizing
+COMPILER_TYPES_2 += interpreter
+COMPILER_TYPES_2 += jit
+COMPILER_TYPES_2 += regalloc_gc
+COMPILER_TYPES_2 += interp-ac
+ALL_ADDRESS_SIZES_2 := 32 64
+IMAGE_TYPES_2 := picimage
+IMAGE_TYPES_2 += no-image
+IMAGE_TYPES_2 += npicimage
+IMAGE_TYPES_2 += multinpicimage
+IMAGE_TYPES_2 += multipicimage
+
 # Add core image dependencies required for given target - HOST or TARGET,
 # IMAGE_TYPE, COMPILER_TYPE and ADDRESS_SIZE to the prereq_rules.
 $(foreach target, $(TARGET_TYPES), \
-  $(foreach image, $(IMAGE_TYPES), \
-    $(foreach compiler, $(COMPILER_TYPES), \
-      $(foreach address_size, $(ALL_ADDRESS_SIZES), $(eval \
+  $(foreach image, $(IMAGE_TYPES_2), \
+    $(foreach compiler, $(COMPILER_TYPES_2), \
+      $(foreach address_size, $(ALL_ADDRESS_SIZES_2), $(eval \
         $(call core-image-dependencies,$(target),$(image),$(compiler),$(address_size)))))))
 
 test-art-host-run-test-dependencies : $(host_prereq_rules)
diff --git a/test/etc/default-build b/test/etc/default-build
index 3d7b7dd..4318966 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -79,7 +79,7 @@
 JACK_EXPERIMENTAL_ARGS["default-methods"]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
 JACK_EXPERIMENTAL_ARGS["lambdas"]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
 JACK_EXPERIMENTAL_ARGS["method-handles"]="-D jack.java.source.version=1.7 -D jack.android.min-api-level=o-b1"
-JACK_EXPERIMENTAL_ARGS["java-8"]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
+JACK_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
 
 declare -A SMALI_EXPERIMENTAL_ARGS
 SMALI_EXPERIMENTAL_ARGS["default-methods"]="--api-level 24"
@@ -90,6 +90,7 @@
 JAVAC_EXPERIMENTAL_ARGS["default-methods"]="-source 1.8 -target 1.8"
 JAVAC_EXPERIMENTAL_ARGS["lambdas"]="-source 1.8 -target 1.8"
 JAVAC_EXPERIMENTAL_ARGS["method-handles"]="-source 1.8 -target 1.8"
+# We need to leave javac at default 1.7 so that dx will continue to work
 JAVAC_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-source 1.7 -target 1.7"
 JAVAC_EXPERIMENTAL_ARGS["agents"]="-source 1.8 -target 1.8"
 
diff --git a/test/run-test b/test/run-test
index c926c11..d55ba77 100755
--- a/test/run-test
+++ b/test/run-test
@@ -80,7 +80,7 @@
 
 # ANDROID_HOST_OUT is not set in a build environment.
 if [ -z "$ANDROID_HOST_OUT" ]; then
-    export ANDROID_HOST_OUT=${OUT_DIR:-$ANDROID_BUILD_TOP/out/}host/linux-x86
+    export ANDROID_HOST_OUT=$ANDROID_BUILD_TOP/out/host/linux-x86
 fi
 
 # If JACK_CLASSPATH is not set, assume it only contains core-libart.
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index a5bfcff..5a6114e 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -446,29 +446,34 @@
     test_name: The name of the test along with the variants.
   """
   global stop_testrunner
-  if is_test_disabled(test, test_variant):
-    test_skipped = True
-  else:
-    test_skipped = False
-    proc = subprocess.Popen(command.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
-    script_output = proc.stdout.read().strip()
-    test_passed = not proc.wait()
-
-  if not test_skipped:
-    if test_passed:
-     print_test_info(test_name, 'PASS')
+  try:
+    if is_test_disabled(test, test_variant):
+      test_skipped = True
     else:
-      failed_tests.append(test_name)
-      if not env.ART_TEST_KEEP_GOING:
-        stop_testrunner = True
-      print_test_info(test_name, 'FAIL', ('%s\n%s') % (
-        command, script_output))
-  elif not dry_run:
-    print_test_info(test_name, 'SKIP')
-    skipped_tests.append(test_name)
-  else:
-    print_test_info(test_name, '')
-  semaphore.release()
+      test_skipped = False
+      proc = subprocess.Popen(command.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
+      script_output = proc.stdout.read().strip()
+      test_passed = not proc.wait()
+
+    if not test_skipped:
+      if test_passed:
+        print_test_info(test_name, 'PASS')
+      else:
+        failed_tests.append(test_name)
+        if not env.ART_TEST_KEEP_GOING:
+          stop_testrunner = True
+        print_test_info(test_name, 'FAIL', ('%s\n%s') % (
+          command, script_output))
+    elif not dry_run:
+      print_test_info(test_name, 'SKIP')
+      skipped_tests.append(test_name)
+    else:
+      print_test_info(test_name, '')
+  except Exception, e:
+    failed_tests.append(test_name)
+    print_text(('%s\n%s\n') % (command, str(e)))
+  finally:
+    semaphore.release()
 
 
 def print_test_info(test_name, result, failed_test_info=""):
@@ -485,6 +490,7 @@
   command used to invoke the script. It doesn't override the failing
   test information in either of the cases.
   """
+
   global test_count
   info = ''
   if not verbose:
@@ -493,48 +499,53 @@
     # the console width.
     console_width = int(os.popen('stty size', 'r').read().split()[1])
     info = '\r' + ' ' * console_width + '\r'
-  print_mutex.acquire()
-  test_count += 1
-  percent = (test_count * 100) / total_test_count
-  progress_info = ('[ %d%% %d/%d ]') % (
-    percent,
-    test_count,
-    total_test_count)
+  try:
+    print_mutex.acquire()
+    test_count += 1
+    percent = (test_count * 100) / total_test_count
+    progress_info = ('[ %d%% %d/%d ]') % (
+      percent,
+      test_count,
+      total_test_count)
 
-  if result == "FAIL":
-    info += ('%s %s %s\n%s\n') % (
-      progress_info,
-      test_name,
-      COLOR_ERROR + 'FAIL' + COLOR_NORMAL,
-      failed_test_info)
-  else:
-    result_text = ''
-    if result == 'PASS':
-      result_text += COLOR_PASS + 'PASS' + COLOR_NORMAL
-    elif result == 'SKIP':
-      result_text += COLOR_SKIP + 'SKIP' + COLOR_NORMAL
-
-    if verbose:
-      info += ('%s %s %s\n') % (
-      progress_info,
-      test_name,
-      result_text)
-    else:
-      total_output_length = 2 # Two spaces
-      total_output_length += len(progress_info)
-      total_output_length += len(result)
-      allowed_test_length = console_width - total_output_length
-      test_name_len = len(test_name)
-      if allowed_test_length < test_name_len:
-        test_name = ('%s...%s') % (
-          test_name[:(allowed_test_length - 3)/2],
-          test_name[-(allowed_test_length - 3)/2:])
-      info += ('%s %s %s') % (
+    if result == "FAIL":
+      info += ('%s %s %s\n%s\n') % (
         progress_info,
         test_name,
-        result_text)
-  print_text(info)
-  print_mutex.release()
+        COLOR_ERROR + 'FAIL' + COLOR_NORMAL,
+        failed_test_info)
+    else:
+      result_text = ''
+      if result == 'PASS':
+        result_text += COLOR_PASS + 'PASS' + COLOR_NORMAL
+      elif result == 'SKIP':
+        result_text += COLOR_SKIP + 'SKIP' + COLOR_NORMAL
+
+      if verbose:
+        info += ('%s %s %s\n') % (
+          progress_info,
+          test_name,
+          result_text)
+      else:
+        total_output_length = 2 # Two spaces
+        total_output_length += len(progress_info)
+        total_output_length += len(result)
+        allowed_test_length = console_width - total_output_length
+        test_name_len = len(test_name)
+        if allowed_test_length < test_name_len:
+          test_name = ('%s...%s') % (
+            test_name[:(allowed_test_length - 3)/2],
+            test_name[-(allowed_test_length - 3)/2:])
+          info += ('%s %s %s') % (
+            progress_info,
+            test_name,
+            result_text)
+    print_text(info)
+  except Exception, e:
+    print_text(('%s\n%s\n') % (test_name, str(e)))
+    failed_tests.append(test_name)
+  finally:
+    print_mutex.release()
 
 def get_disabled_test_info():
   """Generate set of known failures.
@@ -812,8 +823,10 @@
   return test
 
 def main():
+  global verbose
   gather_test_info()
   user_requested_test = parse_option()
+  verbose = True
   setup_test_env()
   if build:
     build_targets = ''
@@ -837,15 +850,13 @@
     while threading.active_count() > 1:
       time.sleep(0.1)
     print_analysis()
-    if failed_tests:
-      sys.exit(1)
-    sys.exit(0)
-  except SystemExit:
-    pass
   except Exception, e:
     print_analysis()
     print_text(str(e))
     sys.exit(1)
+  if failed_tests:
+    sys.exit(1)
+  sys.exit(0)
 
 if __name__ == '__main__':
   main()
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index dcef8c0..08abdb3 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -105,12 +105,6 @@
   names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_getErrorStream"]
 },
 {
-  description: "Short date format flag ignored for es_US locale.",
-  result: EXEC_FAILED,
-  name: "libcore.icu.DateIntervalFormatTest#test_formatDateInterval",
-  bug: 18619426
-},
-{
   description: "Error decoding digital signature bytes.",
   result: EXEC_FAILED,
   name: "org.apache.harmony.security.tests.java.security.Signature2Test#test_verify$BII",
@@ -134,12 +128,6 @@
   names: ["org.apache.harmony.tests.java.lang.ProcessManagerTest#testEnvironment"]
 },
 {
-  description: "Crypto failures",
-  result: EXEC_FAILED,
-  names: ["libcore.javax.crypto.CipherTest#testCipher_ShortBlock_Failure",
-          "libcore.javax.crypto.CipherTest#testCipher_Success"]
-},
-{
   description: "Flake when running with libartd.so or interpreter",
   result: EXEC_FAILED,
   bug:22106064,