Merge "Revert "ART: Compiler support for invoke-polymorphic.""
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 86d92ff..4180e0e 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -487,7 +487,7 @@
   EXPECT_EQ(72U, sizeof(OatHeader));
   EXPECT_EQ(4U, sizeof(OatMethodOffsets));
   EXPECT_EQ(20U, sizeof(OatQuickMethodHeader));
-  EXPECT_EQ(164 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
+  EXPECT_EQ(163 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
             sizeof(QuickEntryPoints));
 }
 
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 9ca7b19..f00648f 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -367,12 +367,6 @@
   InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), nullptr);
 }
 
-void CodeGenerator::GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke) {
-  MoveConstant(invoke->GetLocations()->GetTemp(0), static_cast<int32_t>(invoke->GetType()));
-  QuickEntrypointEnum entrypoint = kQuickInvokePolymorphic;
-  InvokeRuntime(entrypoint, invoke, invoke->GetDexPc(), nullptr);
-}
-
 void CodeGenerator::CreateUnresolvedFieldLocationSummary(
     HInstruction* field_access,
     Primitive::Type field_type,
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 7e2dd48..6366b98 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -426,12 +426,12 @@
   }
 
 
-  // Performs checks pertaining to an InvokeRuntime call.
+  // Perfoms checks pertaining to an InvokeRuntime call.
   void ValidateInvokeRuntime(QuickEntrypointEnum entrypoint,
                              HInstruction* instruction,
                              SlowPathCode* slow_path);
 
-  // Performs checks pertaining to an InvokeRuntimeWithoutRecordingPcInfo call.
+  // Perfoms checks pertaining to an InvokeRuntimeWithoutRecordingPcInfo call.
   static void ValidateInvokeRuntimeWithoutRecordingPcInfo(HInstruction* instruction,
                                                           SlowPathCode* slow_path);
 
@@ -495,8 +495,6 @@
 
   void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke);
 
-  void GenerateInvokePolymorphicCall(HInvokePolymorphic* invoke);
-
   void CreateUnresolvedFieldLocationSummary(
       HInstruction* field_access,
       Primitive::Type field_type,
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 3bb97b6..541a1c5 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2370,14 +2370,6 @@
   codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
 }
 
-void LocationsBuilderARM::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorARM::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 void LocationsBuilderARM::VisitNeg(HNeg* neg) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 227ad0f..9aaeadb 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4080,14 +4080,6 @@
   __ Blr(lr);
 }
 
-void LocationsBuilderARM64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorARM64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeStringPatch(
     const DexFile& dex_file,
     uint32_t string_index,
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index fd51aab..c769dec 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -2445,14 +2445,6 @@
   }
 }
 
-void LocationsBuilderARMVIXL::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorARMVIXL::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 void LocationsBuilderARMVIXL::VisitNeg(HNeg* neg) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index ed0d997..bc62854 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -5154,14 +5154,6 @@
   }
 }
 
-void LocationsBuilderMIPS::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorMIPS::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorMIPS* codegen) {
   if (invoke->GetLocations()->Intrinsified()) {
     IntrinsicCodeGeneratorMIPS intrinsic(codegen);
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 0ea5bb0..1b9c6da 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -3256,14 +3256,6 @@
   HandleInvoke(invoke);
 }
 
-void LocationsBuilderMIPS64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorMIPS64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorMIPS64* codegen) {
   if (invoke->GetLocations()->Intrinsified()) {
     IntrinsicCodeGeneratorMIPS64 intrinsic(codegen);
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 624cf81..a9b717d 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -2244,14 +2244,6 @@
   codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
 }
 
-void LocationsBuilderX86::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorX86::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 void LocationsBuilderX86::VisitNeg(HNeg* neg) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 152a9ed..2614735 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -2423,14 +2423,6 @@
   codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
 }
 
-void LocationsBuilderX86_64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  HandleInvoke(invoke);
-}
-
-void InstructionCodeGeneratorX86_64::VisitInvokePolymorphic(HInvokePolymorphic* invoke) {
-  codegen_->GenerateInvokePolymorphicCall(invoke);
-}
-
 void LocationsBuilderX86_64::VisitNeg(HNeg* neg) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index f6fba88..09dcefa 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -464,11 +464,6 @@
     StartAttributeStream("intrinsic") << invoke->GetIntrinsic();
   }
 
-  void VisitInvokePolymorphic(HInvokePolymorphic* invoke) OVERRIDE {
-    VisitInvoke(invoke);
-    StartAttributeStream("invoke_type") << "InvokePolymorphic";
-  }
-
   void VisitInstanceFieldGet(HInstanceFieldGet* iget) OVERRIDE {
     StartAttributeStream("field_name") <<
         iget->GetFieldInfo().GetDexFile().PrettyField(iget->GetFieldInfo().GetFieldIndex(),
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index d7da46b..c970e5c 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -308,10 +308,8 @@
 }
 
 bool HInliner::TryInline(HInvoke* invoke_instruction) {
-  if (invoke_instruction->IsInvokeUnresolved() ||
-      invoke_instruction->IsInvokePolymorphic()) {
-    return false;  // Don't bother to move further if we know the method is unresolved or an
-                   // invoke-polymorphic.
+  if (invoke_instruction->IsInvokeUnresolved()) {
+    return false;  // Don't bother to move further if we know the method is unresolved.
   }
 
   ScopedObjectAccess soa(Thread::Current());
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 3cfabdd..009d549 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2016 The Android Open Source Project
  *
@@ -907,33 +906,6 @@
                       false /* is_unresolved */);
 }
 
-bool HInstructionBuilder::BuildInvokePolymorphic(const Instruction& instruction ATTRIBUTE_UNUSED,
-                                                 uint32_t dex_pc,
-                                                 uint32_t method_idx,
-                                                 uint32_t proto_idx,
-                                                 uint32_t number_of_vreg_arguments,
-                                                 bool is_range,
-                                                 uint32_t* args,
-                                                 uint32_t register_index) {
-  const char* descriptor = dex_file_->GetShorty(proto_idx);
-  DCHECK_EQ(1 + ArtMethod::NumArgRegisters(descriptor), number_of_vreg_arguments);
-  Primitive::Type return_type = Primitive::GetType(descriptor[0]);
-  size_t number_of_arguments = strlen(descriptor);
-  HInvoke* invoke = new (arena_) HInvokePolymorphic(arena_,
-                                                    number_of_arguments,
-                                                    return_type,
-                                                    dex_pc,
-                                                    method_idx);
-  return HandleInvoke(invoke,
-                      number_of_vreg_arguments,
-                      args,
-                      register_index,
-                      is_range,
-                      descriptor,
-                      nullptr /* clinit_check */,
-                      false /* is_unresolved */);
-}
-
 bool HInstructionBuilder::BuildNewInstance(dex::TypeIndex type_index, uint32_t dex_pc) {
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<1> hs(soa.Self());
@@ -1943,37 +1915,6 @@
       break;
     }
 
-    case Instruction::INVOKE_POLYMORPHIC: {
-      uint16_t method_idx = instruction.VRegB_45cc();
-      uint16_t proto_idx = instruction.VRegH_45cc();
-      uint32_t number_of_vreg_arguments = instruction.VRegA_45cc();
-      uint32_t args[5];
-      instruction.GetVarArgs(args);
-      return BuildInvokePolymorphic(instruction,
-                                    dex_pc,
-                                    method_idx,
-                                    proto_idx,
-                                    number_of_vreg_arguments,
-                                    false,
-                                    args,
-                                    -1);
-    }
-
-    case Instruction::INVOKE_POLYMORPHIC_RANGE: {
-      uint16_t method_idx = instruction.VRegB_4rcc();
-      uint16_t proto_idx = instruction.VRegH_4rcc();
-      uint32_t number_of_vreg_arguments = instruction.VRegA_4rcc();
-      uint32_t register_index = instruction.VRegC_4rcc();
-      return BuildInvokePolymorphic(instruction,
-                                    dex_pc,
-                                    method_idx,
-                                    proto_idx,
-                                    number_of_vreg_arguments,
-                                    true,
-                                    nullptr,
-                                    register_index);
-    }
-
     case Instruction::NEG_INT: {
       Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc);
       break;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index aef0b94..f29e522 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -175,17 +175,6 @@
                    uint32_t* args,
                    uint32_t register_index);
 
-  // Builds an invocation node for invoke-polymorphic and returns whether the
-  // instruction is supported.
-  bool BuildInvokePolymorphic(const Instruction& instruction,
-                              uint32_t dex_pc,
-                              uint32_t method_idx,
-                              uint32_t proto_idx,
-                              uint32_t number_of_vreg_arguments,
-                              bool is_range,
-                              uint32_t* args,
-                              uint32_t register_index);
-
   // Builds a new array node and the instructions that fill it.
   void BuildFilledNewArray(uint32_t dex_pc,
                            dex::TypeIndex type_index,
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 4f30b11..2856c3e 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -943,10 +943,6 @@
     HandleInvoke(invoke);
   }
 
-  void VisitInvokePolymorphic(HInvokePolymorphic* invoke) OVERRIDE {
-    HandleInvoke(invoke);
-  }
-
   void VisitClinitCheck(HClinitCheck* clinit) OVERRIDE {
     HandleInvoke(clinit);
   }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 064e119..ea9a94c 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1291,7 +1291,6 @@
   M(InvokeInterface, Invoke)                                            \
   M(InvokeStaticOrDirect, Invoke)                                       \
   M(InvokeVirtual, Invoke)                                              \
-  M(InvokePolymorphic, Invoke)                                          \
   M(LessThan, Condition)                                                \
   M(LessThanOrEqual, Condition)                                         \
   M(LoadClass, Instruction)                                             \
@@ -3984,28 +3983,6 @@
   DISALLOW_COPY_AND_ASSIGN(HInvokeUnresolved);
 };
 
-class HInvokePolymorphic FINAL : public HInvoke {
- public:
-  HInvokePolymorphic(ArenaAllocator* arena,
-                     uint32_t number_of_arguments,
-                     Primitive::Type return_type,
-                     uint32_t dex_pc,
-                     uint32_t dex_method_index)
-      : HInvoke(arena,
-                number_of_arguments,
-                0u /* number_of_other_inputs */,
-                return_type,
-                dex_pc,
-                dex_method_index,
-                nullptr,
-                kVirtual) {}
-
-  DECLARE_INSTRUCTION(InvokePolymorphic);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(HInvokePolymorphic);
-};
-
 class HInvokeStaticOrDirect FINAL : public HInvoke {
  public:
   // Requirements of this method call regarding the class
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index ab4f9e9..a3fce02 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -5610,7 +5610,7 @@
   " 214:	ecbd 8a10 	vpop	{s16-s31}\n",
   " 218:	e8bd 8de0 	ldmia.w	sp!, {r5, r6, r7, r8, sl, fp, pc}\n",
   " 21c:	4660      	mov	r0, ip\n",
-  " 21e:	f8d9 c2b0 	ldr.w	ip, [r9, #688]	; 0x2b0\n",
+  " 21e:	f8d9 c2ac 	ldr.w	ip, [r9, #684]	; 0x2ac\n",
   " 222:	47e0      	blx	ip\n",
   nullptr
 };
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 9e82f01..4d4ebdc 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -2010,83 +2010,3 @@
 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg09, r9
 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg10, r10
 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg11, r11
-
-.extern artInvokePolymorphic
-ENTRY art_quick_invoke_polymorphic
-    SETUP_SAVE_REFS_AND_ARGS_FRAME r2
-    mov     r2, r9                 @ pass Thread::Current
-    mov     r3, sp                 @ pass SP
-    mov     r0, #0                 @ initialize 64-bit JValue as zero.
-    str     r0, [sp, #-4]!
-    .cfi_adjust_cfa_offset 4
-    str     r0, [sp, #-4]!
-    .cfi_adjust_cfa_offset 4
-    mov     r0, sp                 @ pass JValue for return result as first argument.
-    bl      artInvokePolymorphic   @ artInvokePolymorphic(JValue, receiver, Thread*, SP)
-    sub     r0, 'A'                @ return value is descriptor of handle's return type.
-    cmp     r0, 'Z' - 'A'          @ check if value is in bounds of handler table
-    bgt     .Lcleanup_and_return   @ and clean-up if not.
-    adr     r1, .Lhandler_table
-    tbb     [r0, r1]               @ branch to handler for return value based on return type.
-
-.Lstart_of_handlers:
-.Lstore_boolean_result:
-    ldrb    r0, [sp]               @ Copy boolean value to return value of this function.
-    b       .Lcleanup_and_return
-.Lstore_char_result:
-    ldrh    r0, [sp]               @ Copy char value to return value of this function.
-    b       .Lcleanup_and_return
-.Lstore_float_result:
-    vldr    s0, [sp]               @ Copy float value from JValue result to the context restored by
-    vstr    s0, [sp, #16]          @ RESTORE_SAVE_REFS_AND_ARGS_FRAME.
-    b       .Lcleanup_and_return
-.Lstore_double_result:
-    vldr    d0, [sp]               @ Copy double value from JValue result to the context restored by
-    vstr    d0, [sp, #16]          @ RESTORE_SAVE_REFS_AND_ARGS_FRAME.
-    b       .Lcleanup_and_return
-.Lstore_long_result:
-    ldr     r1, [sp, #4]           @ Copy the upper bits from JValue result to the context restored by
-    str     r1, [sp, #80]          @ RESTORE_SAVE_REFS_AND_ARGS_FRAME.
-    // Fall-through for lower bits.
-.Lstore_int_result:
-    ldr     r0, [sp]               @ Copy int value to return value of this function.
-    // Fall-through to clean up and return.
-.Lcleanup_and_return:
-    add     sp, #8
-    .cfi_adjust_cfa_offset -8
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    RETURN_OR_DELIVER_PENDING_EXCEPTION_REG r2
-
-.macro HANDLER_TABLE_OFFSET handler_label
-    .byte (\handler_label - .Lstart_of_handlers) / 2
-.endm
-
-.Lhandler_table:
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // A
-    HANDLER_TABLE_OFFSET(.Lstore_int_result)      // B (byte)
-    HANDLER_TABLE_OFFSET(.Lstore_char_result)     // C (char)
-    HANDLER_TABLE_OFFSET(.Lstore_double_result)   // D (double)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // E
-    HANDLER_TABLE_OFFSET(.Lstore_float_result)    // F (float)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // G
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // H
-    HANDLER_TABLE_OFFSET(.Lstore_int_result)      // I (int)
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // J (long)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // K
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // L (object)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // M
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // N
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // O
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // P
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // Q
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // R
-    HANDLER_TABLE_OFFSET(.Lstore_int_result)      // S (short)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // T
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // U
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // V (void)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // W
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // X
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // Y
-    HANDLER_TABLE_OFFSET(.Lstore_boolean_result)  // Z (boolean)
-.purgem HANDLER_TABLE_OFFSET
-END art_quick_invoke_polymorphic
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index eba0c87..8b1e038 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -2567,82 +2567,3 @@
 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg27, w27, x27
 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg28, w28, x28
 READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg29, w29, x29
-
-.extern artInvokePolymorphic
-ENTRY art_quick_invoke_polymorphic
-    SETUP_SAVE_REFS_AND_ARGS_FRAME                // Save callee saves in case allocation triggers GC.
-    mov     x2, xSELF
-    mov     x3, sp
-    INCREASE_FRAME 16                             // Reserve space for JValue result.
-    str     xzr, [sp, #0]                         // Initialize result to zero.
-    mov     x0, sp                                // Set r0 to point to result.
-    bl      artInvokePolymorphic                  // ArtInvokePolymorphic(result, receiver, thread, save_area)
-    uxtb    w0, w0                                // Result is the return type descriptor as a char.
-    sub     w0, w0, 'A'                           // Convert to zero based index.
-    cmp     w0, 'Z' - 'A'
-    bhi     .Lcleanup_and_return                  // Clean-up if out-of-bounds.
-    adrp    x1, .Lhandler_table                   // Compute address of handler table.
-    add     x1, x1, :lo12:.Lhandler_table
-    ldrb    w0, [x1, w0, uxtw]                    // Lookup handler offset in handler table.
-    adr     x1, .Lstart_of_handlers
-    add     x0, x1, w0, sxtb #2                   // Convert relative offset to absolute address.
-    br      x0                                    // Branch to handler.
-
-.Lstart_of_handlers:
-.Lstore_boolean_result:
-    ldrb    w0, [sp]
-    b       .Lcleanup_and_return
-.Lstore_char_result:
-    ldrh    w0, [sp]
-    b       .Lcleanup_and_return
-.Lstore_float_result:
-    ldr     s0, [sp]
-    str     s0, [sp, #32]
-    b       .Lcleanup_and_return
-.Lstore_double_result:
-    ldr     d0, [sp]
-    str     d0, [sp, #32]
-    b       .Lcleanup_and_return
-.Lstore_long_result:
-    ldr     x0, [sp]
-    // Fall-through
-.Lcleanup_and_return:
-    DECREASE_FRAME 16
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    RETURN_OR_DELIVER_PENDING_EXCEPTION_X1
-
-    .section    .rodata                           // Place handler table in read-only section away from text.
-    .align  2
-.macro HANDLER_TABLE_OFFSET handler_label
-    .byte (\handler_label - .Lstart_of_handlers) / 4
-.endm
-.Lhandler_table:
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // A
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // B (byte)
-    HANDLER_TABLE_OFFSET(.Lstore_char_result)     // C (char)
-    HANDLER_TABLE_OFFSET(.Lstore_double_result)   // D (double)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // E
-    HANDLER_TABLE_OFFSET(.Lstore_float_result)    // F (float)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // G
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // H
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // I (int)
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // J (long)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // K
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // L (object)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // M
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // N
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // O
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // P
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // Q
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // R
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // S (short)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // T
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // U
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // V (void)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // W
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // X
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // Y
-    HANDLER_TABLE_OFFSET(.Lstore_boolean_result)  // Z (boolean)
-    .text
-
-END  art_quick_invoke_polymorphic
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index ea95bbc..62c29cf 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -468,7 +468,7 @@
      * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
      * of the target Method* in r0 and method->code_ in r1.
      *
-     * If unsuccessful, the helper will return null/null and there will be a pending exception in the
+     * If unsuccessful, the helper will return null/null will bea pending exception in the
      * thread and we branch to another stub to deliver it.
      *
      * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
@@ -2223,97 +2223,5 @@
     jmp *%ebx
 END_FUNCTION art_quick_osr_stub
 
-DEFINE_FUNCTION art_quick_invoke_polymorphic
-    SETUP_SAVE_REFS_AND_ARGS_FRAME  ebx, ebx       // Save frame.
-    mov %esp, %edx                                 // Remember SP.
-    subl LITERAL(16), %esp                         // Make space for JValue result.
-    CFI_ADJUST_CFA_OFFSET(16)
-    movl LITERAL(0), (%esp)                        // Initialize result to zero.
-    movl LITERAL(0), 4(%esp)
-    mov %esp, %eax                                 // Store pointer to JValue result in eax.
-    PUSH edx                                       // pass SP
-    pushl %fs:THREAD_SELF_OFFSET                   // pass Thread::Current()
-    CFI_ADJUST_CFA_OFFSET(4)
-    PUSH ecx                                       // pass receiver (method handle)
-    PUSH eax                                       // pass JResult
-    call SYMBOL(artInvokePolymorphic)              // (result, receiver, Thread*, SP)
-    subl LITERAL('A'), %eax                        // Eliminate out of bounds options
-    cmpb LITERAL('Z' - 'A'), %al
-    ja .Lcleanup_and_return
-    movzbl %al, %eax
-    call .Lput_eip_in_ecx
-.Lbranch_start:
-    add $(.Lhandler_table - .Lbranch_start), %eax  // Add offset of handler table to index.
-    addl %ecx, %eax                                // Add EIP relative address of table.
-    movzbl (%eax), %eax                            // Lookup relative branch in table.
-    addl %ecx, %eax                                // Add EIP relative offset.
-    jmp *%eax                                      // Branch to handler.
-
-    // Handlers for different return types.
-.Lstore_boolean_result:
-    movzbl 16(%esp), %eax                          // Copy boolean result to the accumulator.
-    jmp .Lcleanup_and_return
-.Lstore_char_result:
-    movzwl 16(%esp), %eax                          // Copy char result to the accumulator.
-    jmp .Lcleanup_and_return
-.Lstore_float_result:
-    movd 16(%esp), %xmm0                           // Copy float result to the context restored by
-    movd %xmm0, 36(%esp)                           // RESTORE_SAVE_REFS_ONLY_FRAME.
-    jmp .Lcleanup_and_return
-.Lstore_double_result:
-    movsd 16(%esp), %xmm0                          // Copy double result to the context restored by
-    movsd %xmm0, 36(%esp)                          // RESTORE_SAVE_REFS_ONLY_FRAME.
-    jmp .Lcleanup_and_return
-.Lstore_long_result:
-    movl 20(%esp), %edx                            // Copy upper-word of result to the context restored by
-    movl %edx, 72(%esp)                            // RESTORE_SAVE_REFS_ONLY_FRAME.
-    // Fall-through for lower bits.
-.Lstore_int_result:
-    movl 16(%esp), %eax                            // Copy int result to the accumulator.
-    // Fall-through to clean up and return.
-.Lcleanup_and_return:
-    addl LITERAL(32), %esp                         // Pop arguments and stack allocated JValue result.
-    CFI_ADJUST_CFA_OFFSET(-32)
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    RETURN_OR_DELIVER_PENDING_EXCEPTION
-
-.Lput_eip_in_ecx:                                  // Internal function that puts address of
-    movl 0(%esp), %ecx                             // next instruction into ECX when CALL
-    ret
-
-    // Handler table to handlers for given type.
-.Lhandler_table:
-MACRO1(HANDLER_TABLE_ENTRY, handler_label)
-    .byte RAW_VAR(handler_label) - .Lbranch_start
-END_MACRO
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // A
-    HANDLER_TABLE_ENTRY(.Lstore_int_result)        // B (byte)
-    HANDLER_TABLE_ENTRY(.Lstore_char_result)       // C (char)
-    HANDLER_TABLE_ENTRY(.Lstore_double_result)     // D (double)
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // E
-    HANDLER_TABLE_ENTRY(.Lstore_float_result)      // F (float)
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // G
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // H
-    HANDLER_TABLE_ENTRY(.Lstore_int_result)        // I (int)
-    HANDLER_TABLE_ENTRY(.Lstore_long_result)       // J (long)
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // K
-    HANDLER_TABLE_ENTRY(.Lstore_int_result)        // L (object)
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // M
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // N
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // O
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // P
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // Q
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // R
-    HANDLER_TABLE_ENTRY(.Lstore_int_result)        // S (short)
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // T
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // U
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // V (void)
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // W
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // X
-    HANDLER_TABLE_ENTRY(.Lcleanup_and_return)      // Y
-    HANDLER_TABLE_ENTRY(.Lstore_boolean_result)    // Z (boolean)
-
-END_FUNCTION art_quick_invoke_polymorphic
-
     // TODO: implement these!
 UNIMPLEMENTED art_quick_memcmp16
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 5b3a314..facd563 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -2394,78 +2394,3 @@
     rep movsb                     // while (rcx--) { *rdi++ = *rsi++ }
     jmp *%rdx
 END_FUNCTION art_quick_osr_stub
-
-DEFINE_FUNCTION art_quick_invoke_polymorphic
-    SETUP_SAVE_REFS_AND_ARGS_FRAME                // save callee saves
-    movq %gs:THREAD_SELF_OFFSET, %rdx             // pass Thread
-    movq %rsp, %rcx                               // pass SP
-    subq LITERAL(16), %rsp                        // make space for JValue result
-    CFI_ADJUST_CFA_OFFSET(16)
-    movq LITERAL(0), (%rsp)                       // initialize result
-    movq %rsp, %rdi                               // store pointer to JValue result
-    call SYMBOL(artInvokePolymorphic)             // artInvokePolymorphic(result, receiver, Thread*, SP)
-                                                  // save the code pointer
-    subq LITERAL('A'), %rax                       // Convert type descriptor character value to a zero based index.
-    cmpb LITERAL('Z' - 'A'), %al                  // Eliminate out of bounds options
-    ja .Lcleanup_and_return
-    movzbq %al, %rax
-    leaq .Lhandler_table(%rip), %rcx              // Get the address of the handler table
-    movsbq (%rcx, %rax, 1), %rax                  // Lookup handler offset relative to table
-    addq %rcx, %rax                               // Add table address to yield handler address.
-    jmpq *%rax                                    // Jump to handler.
-
-.align 4
-.Lhandler_table:                                  // Table of type descriptor to handlers.
-MACRO1(HANDLER_TABLE_OFFSET, handle_label)
-    .byte RAW_VAR(handle_label) - .Lhandler_table
-END_MACRO
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // A
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // B (byte)
-    HANDLER_TABLE_OFFSET(.Lstore_char_result)     // C (char)
-    HANDLER_TABLE_OFFSET(.Lstore_double_result)   // D (double)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // E
-    HANDLER_TABLE_OFFSET(.Lstore_float_result)    // F (float)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // G
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // H
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // I (int)
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // J (long)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // K
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // L (object)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // M
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // N
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // O
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // P
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // Q
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // R
-    HANDLER_TABLE_OFFSET(.Lstore_long_result)     // S (short)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // T
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // U
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // V (void)
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // W
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // X
-    HANDLER_TABLE_OFFSET(.Lcleanup_and_return)    // Y
-    HANDLER_TABLE_OFFSET(.Lstore_boolean_result)  // Z (boolean)
-
-.Lstore_boolean_result:
-    movzbq (%rsp), %rax                           // Copy boolean result to the accumulator
-    jmp .Lcleanup_and_return
-.Lstore_char_result:
-    movzwq (%rsp), %rax                           // Copy char result to the accumulator
-    jmp .Lcleanup_and_return
-.Lstore_float_result:
-    movd (%rsp), %xmm0                            // Copy float result to the context restored by
-    movd %xmm0, 32(%rsp)                          // RESTORE_SAVE_REFS_AND_ARGS_FRAME.
-    jmp .Lcleanup_and_return
-.Lstore_double_result:
-    movsd (%rsp), %xmm0                           // Copy double result to the context restored by
-    movsd %xmm0, 32(%rsp)                         // RESTORE_SAVE_REFS_AND_ARGS_FRAME.
-    jmp .Lcleanup_and_return
-.Lstore_long_result:
-    movq (%rsp), %rax                             // Copy long result to the accumulator.
-    // Fall-through
-.Lcleanup_and_return:
-    addq LITERAL(16), %rsp                        // Pop space for JValue result.
-    CFI_ADJUST_CFA_OFFSET(16)
-    RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    RETURN_OR_DELIVER_PENDING_EXCEPTION
-END_FUNCTION art_quick_invoke_polymorphic
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index e4972da..bfdddf7 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -98,7 +98,7 @@
 ADD_TEST_EQ(THREAD_LOCAL_END_OFFSET,
             art::Thread::ThreadLocalEndOffset<POINTER_SIZE>().Int32Value())
 // Offset of field Thread::tlsPtr_.thread_local_objects.
-#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_LOCAL_END_OFFSET + 2 * __SIZEOF_POINTER__)
+#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_LOCAL_END_OFFSET + __SIZEOF_POINTER__)
 ADD_TEST_EQ(THREAD_LOCAL_OBJECTS_OFFSET,
             art::Thread::ThreadLocalObjectsOffset<POINTER_SIZE>().Int32Value())
 // Offset of field Thread::tlsPtr_.mterp_current_ibase.
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index a44f79e..c30272e 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -428,8 +428,6 @@
     case Instruction::INVOKE_VIRTUAL_RANGE:
     case Instruction::INVOKE_INTERFACE:
     case Instruction::INVOKE_INTERFACE_RANGE:
-    case Instruction::INVOKE_POLYMORPHIC:
-    case Instruction::INVOKE_POLYMORPHIC_RANGE:
     case Instruction::INVOKE_VIRTUAL_QUICK:
     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
       // Without inlining, we could just check that the offset is the class offset.
@@ -553,12 +551,6 @@
     case Instruction::INVOKE_INTERFACE_RANGE:
       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kInterface);
       break;
-    case Instruction::INVOKE_POLYMORPHIC:
-      ThrowNullPointerExceptionForMethodAccess(instr->VRegB_45cc(), kVirtual);
-      break;
-    case Instruction::INVOKE_POLYMORPHIC_RANGE:
-      ThrowNullPointerExceptionForMethodAccess(instr->VRegB_4rcc(), kVirtual);
-      break;
     case Instruction::INVOKE_VIRTUAL_QUICK:
     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
       // Since we replaced the method index, we ask the verifier to tell us which
diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc
index 37f3ac9..7b8974f 100644
--- a/runtime/dex_instruction.cc
+++ b/runtime/dex_instruction.cc
@@ -358,7 +358,7 @@
       }
       break;
     case k35c: {
-      uint32_t arg[kMaxVarArgRegs];
+      uint32_t arg[5];
       GetVarArgs(arg);
       switch (Opcode()) {
         case FILLED_NEW_ARRAY:
@@ -443,50 +443,8 @@
       }
       break;
     }
-    case k45cc: {
-      uint32_t arg[kMaxVarArgRegs];
-      GetVarArgs(arg);
-      uint32_t method_idx = VRegB_45cc();
-      uint32_t proto_idx = VRegH_45cc();
-      os << opcode << " {";
-      for (int i = 0; i < VRegA_45cc(); ++i) {
-        if (i != 0) {
-          os << ", ";
-        }
-        os << "v" << arg[i];
-      }
-      os << "}";
-      if (file != nullptr) {
-        os << ", " << file->PrettyMethod(method_idx) << ", " << file->GetShorty(proto_idx)
-           << " // ";
-      } else {
-        os << ", ";
-      }
-      os << "method@" << method_idx << ", proto@" << proto_idx;
-      break;
-    }
-    case k4rcc:
-      switch (Opcode()) {
-        case INVOKE_POLYMORPHIC_RANGE: {
-          if (file != nullptr) {
-            uint32_t method_idx = VRegB_4rcc();
-            uint32_t proto_idx = VRegH_4rcc();
-            os << opcode << ", {v" << VRegC_4rcc() << " .. v" << (VRegC_4rcc() + VRegA_4rcc())
-               << "}, " << file->PrettyMethod(method_idx) << ", " << file->GetShorty(proto_idx)
-               << " // method@" << method_idx << ", proto@" << proto_idx;
-            break;
-          }
-        }
-        FALLTHROUGH_INTENDED;
-        default: {
-          uint32_t method_idx = VRegB_4rcc();
-          uint32_t proto_idx = VRegH_4rcc();
-          os << opcode << ", {v" << VRegC_4rcc() << " .. v" << (VRegC_4rcc() + VRegA_4rcc())
-             << "}, method@" << method_idx << ", proto@" << proto_idx;
-        }
-      }
-      break;
     case k51l: os << StringPrintf("%s v%d, #%+" PRId64, opcode, VRegA_51l(), VRegB_51l()); break;
+    default: os << " unknown format (" << DumpHex(5) << ")"; break;
   }
   return os.str();
 }
diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h
index 2d0932a..64030f3 100644
--- a/runtime/entrypoints/quick/quick_default_externs.h
+++ b/runtime/entrypoints/quick/quick_default_externs.h
@@ -109,13 +109,8 @@
 extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
-
 extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
 
-// Invoke polymorphic entrypoint. Return type is dynamic and may be void, a primitive value, or
-// reference return type.
-extern "C" void art_quick_invoke_polymorphic(uint32_t, void*);
-
 // Thread entrypoints.
 extern "C" void art_quick_test_suspend();
 
diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
index 8ce61c1..78dad94 100644
--- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
@@ -106,7 +106,6 @@
       art_quick_invoke_super_trampoline_with_access_check;
   qpoints->pInvokeVirtualTrampolineWithAccessCheck =
       art_quick_invoke_virtual_trampoline_with_access_check;
-  qpoints->pInvokePolymorphic = art_quick_invoke_polymorphic;
 
   // Thread
   qpoints->pTestSuspend = art_quick_test_suspend;
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index 4d5d6de..0911aeb 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -133,7 +133,6 @@
   V(InvokeStaticTrampolineWithAccessCheck, void, uint32_t, void*) \
   V(InvokeSuperTrampolineWithAccessCheck, void, uint32_t, void*) \
   V(InvokeVirtualTrampolineWithAccessCheck, void, uint32_t, void*) \
-  V(InvokePolymorphic, void, uint32_t, void*) \
 \
   V(TestSuspend, void, void) \
 \
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index b22afc3..a3e5b55 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -27,12 +27,10 @@
 #include "imtable-inl.h"
 #include "interpreter/interpreter.h"
 #include "linear_alloc.h"
-#include "method_handles.h"
 #include "method_reference.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/method.h"
-#include "mirror/method_handle_impl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "oat_quick_method_header.h"
@@ -41,7 +39,6 @@
 #include "scoped_thread_state_change-inl.h"
 #include "stack.h"
 #include "debugger.h"
-#include "well_known_classes.h"
 
 namespace art {
 
@@ -2394,114 +2391,4 @@
                                 reinterpret_cast<uintptr_t>(method));
 }
 
-// Returns shorty type so the caller can determine how to put |result|
-// into expected registers. The shorty type is static so the compiler
-// could call different flavors of this code path depending on the
-// shorty type though this would require different entry points for
-// each type.
-extern "C" uintptr_t artInvokePolymorphic(
-    JValue* result,
-    mirror::Object* raw_method_handle,
-    Thread* self,
-    ArtMethod** sp)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  ScopedQuickEntrypointChecks sqec(self);
-  DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveRefsAndArgs));
-
-  // Start new JNI local reference state
-  JNIEnvExt* env = self->GetJniEnv();
-  ScopedObjectAccessUnchecked soa(env);
-  ScopedJniEnvLocalRefState env_state(env);
-  const char* old_cause = self->StartAssertNoThreadSuspension("Making stack arguments safe.");
-
-  // From the instruction, get the |callsite_shorty| and expose arguments on the stack to the GC.
-  ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
-  uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
-  const DexFile::CodeItem* code = caller_method->GetCodeItem();
-  const Instruction* inst = Instruction::At(&code->insns_[dex_pc]);
-  DCHECK(inst->Opcode() == Instruction::INVOKE_POLYMORPHIC ||
-         inst->Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
-  const DexFile* dex_file = caller_method->GetDexFile();
-  const uint32_t proto_idx = inst->VRegH();
-  const char* shorty = dex_file->GetShorty(proto_idx);
-  const size_t shorty_length = strlen(shorty);
-  static const bool kMethodIsStatic = false;  // invoke() and invokeExact() are not static.
-  RememberForGcArgumentVisitor gc_visitor(sp, kMethodIsStatic, shorty, shorty_length, &soa);
-  gc_visitor.Visit();
-
-  // Wrap raw_method_handle in a Handle for safety.
-  StackHandleScope<5> hs(self);
-  Handle<mirror::MethodHandleImpl> method_handle(
-      hs.NewHandle(ObjPtr<mirror::MethodHandleImpl>::DownCast(MakeObjPtr(raw_method_handle))));
-  raw_method_handle = nullptr;
-  self->EndAssertNoThreadSuspension(old_cause);
-
-  // Resolve method - it's either MethodHandle.invoke() or MethodHandle.invokeExact().
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::kForceICCECheck>(self,
-                                                                                   inst->VRegB(),
-                                                                                   caller_method,
-                                                                                   kVirtual);
-  DCHECK((resolved_method ==
-          jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact)) ||
-         (resolved_method ==
-          jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_invoke)));
-  if (UNLIKELY(method_handle.IsNull())) {
-    ThrowNullPointerExceptionForMethodAccess(resolved_method, InvokeType::kVirtual);
-    return static_cast<uintptr_t>('V');
-  }
-
-  Handle<mirror::Class> caller_class(hs.NewHandle(caller_method->GetDeclaringClass()));
-  Handle<mirror::MethodType> method_type(hs.NewHandle(linker->ResolveMethodType(
-      *dex_file, proto_idx,
-      hs.NewHandle<mirror::DexCache>(caller_class->GetDexCache()),
-      hs.NewHandle<mirror::ClassLoader>(caller_class->GetClassLoader()))));
-  // This implies we couldn't resolve one or more types in this method handle.
-  if (UNLIKELY(method_type.IsNull())) {
-    CHECK(self->IsExceptionPending());
-    return static_cast<uintptr_t>('V');
-  }
-
-  DCHECK_EQ(ArtMethod::NumArgRegisters(shorty) + 1u, (uint32_t)inst->VRegA());
-  DCHECK_EQ(resolved_method->IsStatic(), kMethodIsStatic);
-
-  // Fix references before constructing the shadow frame.
-  gc_visitor.FixupReferences();
-
-  // Construct shadow frame placing arguments consecutively from |first_arg|.
-  const bool is_range = (inst->Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
-  const size_t num_vregs = is_range ? inst->VRegA_4rcc() : inst->VRegA_45cc();
-  const size_t first_arg = 0;
-  ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
-      CREATE_SHADOW_FRAME(num_vregs, /* link */ nullptr, resolved_method, dex_pc);
-  ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
-  ScopedStackedShadowFramePusher
-      frame_pusher(self, shadow_frame, StackedShadowFrameType::kShadowFrameUnderConstruction);
-  BuildQuickShadowFrameVisitor shadow_frame_builder(sp,
-                                                    kMethodIsStatic,
-                                                    shorty,
-                                                    strlen(shorty),
-                                                    shadow_frame,
-                                                    first_arg);
-  shadow_frame_builder.VisitArguments();
-
-  // Call DoInvokePolymorphic with |is_range| = true, as shadow frame has argument registers in
-  // consecutive order.
-  uint32_t unused_args[Instruction::kMaxVarArgRegs] = {};
-  uint32_t first_callee_arg = first_arg + 1;
-  const bool do_assignability_check = false;
-  if (!DoInvokePolymorphic<true /* is_range */, do_assignability_check>(self,
-                                                                        resolved_method,
-                                                                        *shadow_frame,
-                                                                        method_handle,
-                                                                        method_type,
-                                                                        unused_args,
-                                                                        first_callee_arg,
-                                                                        result)) {
-    DCHECK(self->IsExceptionPending());
-  }
-
-  return static_cast<uintptr_t>(shorty[0]);
-}
-
 }  // namespace art
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 96e17da..6866abb 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -121,10 +121,10 @@
                         sizeof(Thread::tls_ptr_sized_values::active_suspend_barriers));
 
     // Skip across the entrypoints structures.
-    EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_pos, thread_local_end, sizeof(void*));
-    EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, thread_local_start, sizeof(void*));
-    EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_start, thread_local_objects, sizeof(void*));
 
+    EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_start, thread_local_pos, sizeof(void*));
+    EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_pos, thread_local_end, sizeof(void*));
+    EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_end, thread_local_objects, sizeof(void*));
     EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_objects, mterp_current_ibase, sizeof(size_t));
     EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, mterp_current_ibase, mterp_default_ibase, sizeof(void*));
     EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, mterp_default_ibase, mterp_alt_ibase, sizeof(void*));
@@ -286,8 +286,6 @@
     EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pInvokeSuperTrampolineWithAccessCheck,
                          pInvokeVirtualTrampolineWithAccessCheck, sizeof(void*));
     EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pInvokeVirtualTrampolineWithAccessCheck,
-                         pInvokePolymorphic, sizeof(void*));
-    EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pInvokePolymorphic,
                          pTestSuspend, sizeof(void*));
     EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pTestSuspend, pDeliverException, sizeof(void*));
 
diff --git a/runtime/oat.h b/runtime/oat.h
index 685aa04..dc103e2 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[] = { '0', '9', '6', '\0' };  // invoke-polymorphic entry
+  static constexpr uint8_t kOatVersion[] = { '0', '9', '5', '\0' };  // alloc entrypoints change
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 40b6d73..bdd4ca6 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2727,7 +2727,6 @@
   QUICK_ENTRY_POINT_INFO(pInvokeStaticTrampolineWithAccessCheck)
   QUICK_ENTRY_POINT_INFO(pInvokeSuperTrampolineWithAccessCheck)
   QUICK_ENTRY_POINT_INFO(pInvokeVirtualTrampolineWithAccessCheck)
-  QUICK_ENTRY_POINT_INFO(pInvokePolymorphic)
   QUICK_ENTRY_POINT_INFO(pTestSuspend)
   QUICK_ENTRY_POINT_INFO(pDeliverException)
   QUICK_ENTRY_POINT_INFO(pThrowArrayBounds)
diff --git a/runtime/thread.h b/runtime/thread.h
index d54a80d..a3ef9bc 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -1418,7 +1418,7 @@
       stacked_shadow_frame_record(nullptr), deoptimization_context_stack(nullptr),
       frame_id_to_shadow_frame(nullptr), name(nullptr), pthread_self(0),
       last_no_thread_suspension_cause(nullptr), checkpoint_function(nullptr),
-      thread_local_pos(nullptr), thread_local_end(nullptr), thread_local_start(nullptr),
+      thread_local_start(nullptr), thread_local_pos(nullptr), thread_local_end(nullptr),
       thread_local_objects(0), mterp_current_ibase(nullptr), mterp_default_ibase(nullptr),
       mterp_alt_ibase(nullptr), thread_local_alloc_stack_top(nullptr),
       thread_local_alloc_stack_end(nullptr), nested_signal_state(nullptr),
@@ -1542,14 +1542,13 @@
     JniEntryPoints jni_entrypoints;
     QuickEntryPoints quick_entrypoints;
 
+    // Thread-local allocation pointer. Moved here to force alignment for thread_local_pos on ARM.
+    uint8_t* thread_local_start;
     // thread_local_pos and thread_local_end must be consecutive for ldrd and are 8 byte aligned for
     // potentially better performance.
     uint8_t* thread_local_pos;
     uint8_t* thread_local_end;
 
-    // Thread-local allocation pointer.
-    uint8_t* thread_local_start;
-
     size_t thread_local_objects;
 
     // Mterp jump table bases.
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 25a179b..715b237 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3106,16 +3106,19 @@
         break;
       }
       const uint32_t proto_idx = (is_range) ? inst->VRegH_4rcc() : inst->VRegH_45cc();
-      const char* return_descriptor =
+      const char* descriptor =
           dex_file_->GetReturnTypeDescriptor(dex_file_->GetProtoId(proto_idx));
       const RegType& return_type =
-          reg_types_.FromDescriptor(GetClassLoader(), return_descriptor, false);
+          reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
       if (!return_type.IsLowHalf()) {
         work_line_->SetResultRegisterType(this, return_type);
       } else {
         work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
       }
-      just_set_result = true;
+      // TODO(oth): remove when compiler support is available.
+      Fail(VERIFY_ERROR_FORCE_INTERPRETER)
+          << "invoke-polymorphic is not supported by compiler";
+      have_pending_experimental_failure_ = true;
       break;
     }
     case Instruction::NEG_INT:
diff --git a/test/953-invoke-polymorphic-compiler/build b/test/953-invoke-polymorphic-compiler/build
deleted file mode 100755
index a423ca6..0000000
--- a/test/953-invoke-polymorphic-compiler/build
+++ /dev/null
@@ -1,25 +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.
-
-# make us exit on a failure
-set -e
-
-if [[ $@ != *"--jvm"* ]]; then
-  # Don't do anything with jvm.
-  export USE_JACK=true
-fi
-
-./default-build "$@" --experimental method-handles
diff --git a/test/953-invoke-polymorphic-compiler/expected.txt b/test/953-invoke-polymorphic-compiler/expected.txt
deleted file mode 100644
index f47ee23..0000000
--- a/test/953-invoke-polymorphic-compiler/expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Running Main.Min2Print2([33, -4])
-Running Main.Min2Print2([-4, 33])
-Running Main.Min2Print3([33, -4, 17])
-Running Main.Min2Print3([-4, 17, 33])
-Running Main.Min2Print3([17, 33, -4])
-Running Main.Min2Print6([33, -4, 77, 88, 99, 111])
-Running Main.Min2Print6([-4, 77, 88, 99, 111, 33])
-Running Main.Min2Print6([77, 88, 99, 111, 33, -4])
-Running Main.Min2Print6([88, 99, 111, 33, -4, 77])
-Running Main.Min2Print6([99, 111, 33, -4, 77, 88])
-Running Main.Min2Print6([111, 33, -4, 77, 88, 99])
-Running Main.Min2Print26([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25])
-Running Main.Min2Print26([25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])
-Running Main.Min2Print26([24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])
-BasicTest done.
-$opt$ReturnBooleanTest done.
-$opt$ReturnCharTest done.
-$opt$ReturnByteTest done.
-$opt$ReturnShortTest done.
-$opt$ReturnIntTest done.
-$opt$ReturnLongTest done.
-$opt$ReturnFloatTest done.
-$opt$ReturnDoubleTest done.
-$opt$ReturnStringTest done.
-ReturnValuesTest done.
diff --git a/test/953-invoke-polymorphic-compiler/info.txt b/test/953-invoke-polymorphic-compiler/info.txt
deleted file mode 100644
index f1dbb61..0000000
--- a/test/953-invoke-polymorphic-compiler/info.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests for method handle invocations.
-
-NOTE: needs to run under ART or a Java 8 Language runtime and compiler.
diff --git a/test/953-invoke-polymorphic-compiler/run b/test/953-invoke-polymorphic-compiler/run
deleted file mode 100755
index a9f1822..0000000
--- a/test/953-invoke-polymorphic-compiler/run
+++ /dev/null
@@ -1,20 +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.
-
-# make us exit on a failure
-set -e
-
-./default-run "$@" --experimental method-handles
diff --git a/test/953-invoke-polymorphic-compiler/src/Main.java b/test/953-invoke-polymorphic-compiler/src/Main.java
deleted file mode 100644
index 20a8fec..0000000
--- a/test/953-invoke-polymorphic-compiler/src/Main.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * 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.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.WrongMethodTypeException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class Main {
-  public static void assertTrue(boolean value) {
-    if (!value) {
-      throw new AssertionError("assertTrue value: " + value);
-    }
-  }
-
-  public static void assertFalse(boolean value) {
-    if (value) {
-      throw new AssertionError("assertTrue value: " + value);
-    }
-  }
-
-  public static void assertEquals(int i1, int i2) {
-    if (i1 == i2) { return; }
-    throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2);
-  }
-
-  public static void assertEquals(long i1, long i2) {
-    if (i1 == i2) { return; }
-    throw new AssertionError("assertEquals l1: " + i1 + ", l2: " + i2);
-  }
-
-  public static void assertEquals(Object o, Object p) {
-    if (o == p) { return; }
-    if (o != null && p != null && o.equals(p)) { return; }
-    throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p);
-  }
-
-  public static void assertEquals(String s1, String s2) {
-    if (s1 == s2) {
-      return;
-    }
-
-    if (s1 != null && s2 != null && s1.equals(s2)) {
-      return;
-    }
-
-    throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2);
-  }
-
-  public static void fail() {
-    System.err.println("fail");
-    Thread.dumpStack();
-  }
-
-  public static void fail(String message) {
-    System.err.println("fail: " + message);
-    Thread.dumpStack();
-  }
-
-  public static int Min2Print2(int a, int b) {
-    int[] values = new int[] { a, b };
-    System.err.println("Running Main.Min2Print2(" + Arrays.toString(values) + ")");
-    return a > b ? a : b;
-  }
-
-  public static int Min2Print3(int a, int b, int c) {
-    int[] values = new int[] { a, b, c };
-    System.err.println("Running Main.Min2Print3(" + Arrays.toString(values) + ")");
-    return a > b ? a : b;
-  }
-
-  public static int Min2Print6(int a, int b, int c, int d, int e, int f) {
-    int[] values = new int[] { a, b, c, d, e, f };
-    System.err.println("Running Main.Min2Print6(" + Arrays.toString(values) + ")");
-    return a > b ? a : b;
-  }
-
-  public static int Min2Print26(int a, int b, int c, int d,
-                                int e, int f, int g, int h,
-                                int i, int j, int k, int l,
-                                int m, int n, int o, int p,
-                                int q, int r, int s, int t,
-                                int u, int v, int w, int x,
-                                int y, int z) {
-    int[] values = new int[] { a, b, c, d, e, f, g, h, i, j, k, l, m,
-                               n, o, p, q, r, s, t, u, v, w, x, y, z };
-    System.err.println("Running Main.Min2Print26(" + Arrays.toString(values) + ")");
-    return a > b ? a : b;
-  }
-
-  public static void $opt$BasicTest() throws Throwable {
-    MethodHandle mh;
-    mh = MethodHandles.lookup().findStatic(
-        Main.class, "Min2Print2", MethodType.methodType(int.class, int.class, int.class));
-    assertEquals((int) mh.invokeExact(33, -4), 33);
-    assertEquals((int) mh.invokeExact(-4, 33), 33);
-
-    mh = MethodHandles.lookup().findStatic(
-        Main.class, "Min2Print3",
-        MethodType.methodType(int.class, int.class, int.class, int.class));
-    assertEquals((int) mh.invokeExact(33, -4, 17), 33);
-    assertEquals((int) mh.invokeExact(-4, 17, 33), 17);
-    assertEquals((int) mh.invokeExact(17, 33, -4), 33);
-
-    mh = MethodHandles.lookup().findStatic(
-        Main.class, "Min2Print6",
-        MethodType.methodType(
-            int.class, int.class, int.class, int.class, int.class, int.class, int.class));
-    assertEquals((int) mh.invokeExact(33, -4, 77, 88, 99, 111), 33);
-    try {
-        // Too few arguments
-        assertEquals((int) mh.invokeExact(33, -4, 77, 88), 33);
-        fail("No WMTE for too few arguments");
-    } catch (WrongMethodTypeException e) {}
-    try {
-        // Too many arguments
-        assertEquals((int) mh.invokeExact(33, -4, 77, 88, 89, 90, 91), 33);
-        fail("No WMTE for too many arguments");
-    } catch (WrongMethodTypeException e) {}
-    assertEquals((int) mh.invokeExact(-4, 77, 88, 99, 111, 33), 77);
-    assertEquals((int) mh.invokeExact(77, 88, 99, 111, 33, -4), 88);
-    assertEquals((int) mh.invokeExact(88, 99, 111, 33, -4, 77), 99);
-    assertEquals((int) mh.invokeExact(99, 111, 33, -4, 77, 88), 111);
-    assertEquals((int) mh.invokeExact(111, 33, -4, 77, 88, 99), 111);
-
-    // A preposterous number of arguments.
-    mh = MethodHandles.lookup().findStatic(
-        Main.class, "Min2Print26",
-        MethodType.methodType(
-            // Return-type
-            int.class,
-            // Arguments
-            int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
-            int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
-            int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
-            int.class, int.class));
-    assertEquals(1, (int) mh.invokeExact(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
-                                         13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25));
-    assertEquals(25, (int) mh.invokeExact(25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
-                                         13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24));
-    assertEquals(25, (int) mh.invokeExact(24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
-                                         13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23));
-
-    try {
-        // Wrong argument type
-        mh.invokeExact("a");
-        fail("No WMTE for wrong arguments");
-    } catch (WrongMethodTypeException wmte) {}
-
-    try {
-        // Invoke on null handle.
-        MethodHandle mh0 = null;
-        mh0.invokeExact("bad");
-        fail("No NPE for you");
-    } catch (NullPointerException npe) {}
-
-    System.err.println("BasicTest done.");
-  }
-
-  private static boolean And(boolean lhs, boolean rhs) {
-    return lhs & rhs;
-  }
-
-  private static boolean Xor(boolean lhs, boolean rhs) {
-    return lhs ^ rhs;
-  }
-
-  private static String Multiply(String value, int n) {
-    String result = "";
-    for (int i = 0; i < n; ++i) {
-      result = value + result;
-    }
-    return result;
-  }
-
-  private static byte Multiply(byte value, byte n) {
-    return (byte)(value * n);
-  }
-
-  private static short Multiply(short value, short n) {
-    return (short)(value * n);
-  }
-
-  private static int Multiply(int value, int n) {
-    return value * n;
-  }
-
-  private static long Multiply(long value, long n) {
-    return value * n;
-  }
-
-  private static float Multiply(float value, float n) {
-    return value * n;
-  }
-
-  private static double Multiply(double value, double n) {
-    return value * n;
-  }
-
-  private static char Next(char c) {
-    return (char)(c + 1);
-  }
-
-  public static void $opt$ReturnBooleanTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh =
-            lookup.findStatic(Main.class, "And",
-                              MethodType.methodType(boolean.class, boolean.class, boolean.class));
-    assertEquals(true, (boolean) mh.invokeExact(true, true));
-    assertEquals(false, (boolean) mh.invokeExact(true, false));
-    assertEquals(false, (boolean) mh.invokeExact(false, true));
-    assertEquals(false, (boolean) mh.invokeExact(false, false));
-    assertEquals(true, (boolean) mh.invoke(true, true));
-    assertEquals(false, (boolean) mh.invoke(true, false));
-    assertEquals(false, (boolean) mh.invoke(false, true));
-    assertEquals(false, (boolean) mh.invoke(false, false));
-
-    mh = lookup.findStatic(Main.class, "Xor",
-                           MethodType.methodType(boolean.class, boolean.class, boolean.class));
-    assertEquals(false, (boolean) mh.invokeExact(true, true));
-    assertEquals(true, (boolean) mh.invokeExact(true, false));
-    assertEquals(true, (boolean) mh.invokeExact(false, true));
-    assertEquals(false, (boolean) mh.invokeExact(false, false));
-    assertEquals(false, (boolean) mh.invoke(true, true));
-    assertEquals(true, (boolean) mh.invoke(true, false));
-    assertEquals(true, (boolean) mh.invoke(false, true));
-    assertEquals(false, (boolean) mh.invoke(false, false));
-
-    System.err.println("$opt$ReturnBooleanTest done.");
-  }
-
-  public static void $opt$ReturnCharTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Next",
-                           MethodType.methodType(char.class, char.class));
-    assertEquals('B', (char) mh.invokeExact('A'));
-    assertEquals((char) -55, (char) mh.invokeExact((char) -56));
-    System.err.println("$opt$ReturnCharTest done.");
-  }
-
-  public static void $opt$ReturnByteTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                                         MethodType.methodType(byte.class, byte.class, byte.class));
-    assertEquals((byte) 30, (byte) mh.invokeExact((byte) 10, (byte) 3));
-    assertEquals((byte) -90, (byte) mh.invoke((byte) -10, (byte) 9));
-    System.err.println("$opt$ReturnByteTest done.");
-  }
-
-  public static void $opt$ReturnShortTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                           MethodType.methodType(short.class, short.class, short.class));
-    assertEquals((short) 3000, (short) mh.invokeExact((short) 1000, (short) 3));
-    assertEquals((short) -3000, (short) mh.invoke((short) -1000, (short) 3));
-    System.err.println("$opt$ReturnShortTest done.");
-  }
-
-  public static void $opt$ReturnIntTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                           MethodType.methodType(int.class, int.class, int.class));
-    assertEquals(3_000_000, (int) mh.invokeExact(1_000_000, 3));
-    assertEquals(-3_000_000, (int) mh.invoke(-1_000, 3_000));
-    System.err.println("$opt$ReturnIntTest done.");
-  }
-
-  public static void $opt$ReturnLongTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                           MethodType.methodType(long.class, long.class, long.class));
-    assertEquals(4_294_967_295_000L, (long) mh.invokeExact(1000L, 4_294_967_295L));
-    assertEquals(-4_294_967_295_000L, (long) mh.invoke(-1000L, 4_294_967_295L));
-    System.err.println("$opt$ReturnLongTest done.");
-  }
-
-  public static void $opt$ReturnFloatTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                           MethodType.methodType(float.class, float.class, float.class));
-    assertEquals(3.0F, (float) mh.invokeExact(1000.0F, 3e-3F));
-    assertEquals(-3.0F, (float) mh.invoke(-1000.0F, 3e-3F));
-    System.err.println("$opt$ReturnFloatTest done.");
-  }
-
-  public static void $opt$ReturnDoubleTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                           MethodType.methodType(double.class, double.class, double.class));
-    assertEquals(3033000.0, (double) mh.invokeExact(1000.0, 3.033e3));
-    assertEquals(-3033000.0, (double) mh.invoke(-1000.0, 3.033e3));
-    System.err.println("$opt$ReturnDoubleTest done.");
-  }
-
-  public static void $opt$ReturnStringTest() throws Throwable {
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-    MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
-                           MethodType.methodType(String.class, String.class, int.class));
-    assertEquals("100010001000", (String) mh.invokeExact("1000", 3));
-    assertEquals("100010001000", (String) mh.invoke("1000", 3));
-    System.err.println("$opt$ReturnStringTest done.");
-  }
-
-  public static void ReturnValuesTest() throws Throwable {
-    $opt$ReturnBooleanTest();
-    $opt$ReturnCharTest();
-    $opt$ReturnByteTest();
-    $opt$ReturnShortTest();
-    $opt$ReturnIntTest();
-    $opt$ReturnLongTest();
-    $opt$ReturnFloatTest();
-    $opt$ReturnDoubleTest();
-    $opt$ReturnStringTest();
-    System.err.println("ReturnValuesTest done.");
-  }
-
-  static class ValueHolder {
-    public boolean m_z;
-    public static boolean s_z;
-  }
-
-  public static void $opt$AccessorsTest() throws Throwable {
-    ValueHolder valueHolder = new ValueHolder();
-    MethodHandles.Lookup lookup = MethodHandles.lookup();
-
-    MethodHandle setMember = lookup.findSetter(ValueHolder.class, "m_z", boolean.class);
-    MethodHandle getMember = lookup.findGetter(ValueHolder.class, "m_z", boolean.class);
-    MethodHandle setStatic = lookup.findStaticSetter(ValueHolder.class, "s_z", boolean.class);
-    MethodHandle getStatic = lookup.findStaticGetter(ValueHolder.class, "s_z", boolean.class);
-
-    boolean [] values = { false, true, false, true, false };
-    for (boolean value : values) {
-      assertEquals((boolean) getStatic.invoke(), ValueHolder.s_z);
-      setStatic.invoke(value);
-      ValueHolder.s_z = value;
-      assertEquals(ValueHolder.s_z, value);
-      assertEquals((boolean) getStatic.invoke(), value);
-
-      assertEquals((boolean) getMember.invoke(valueHolder), valueHolder.m_z);
-      setMember.invoke(valueHolder, value);
-      valueHolder.m_z = value;
-      assertEquals(valueHolder.m_z, value);
-      assertEquals((boolean) getMember.invoke(valueHolder), value);
-    }
-  }
-
-  public static void main(String[] args) throws Throwable {
-    $opt$BasicTest();
-    ReturnValuesTest();
-    $opt$AccessorsTest();
-  }
-}
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
index 9e79ff4..5806509 100644
--- a/test/957-methodhandle-transforms/src/Main.java
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -40,17 +40,17 @@
         IllegalArgumentException.class);
 
     if (handle.type().returnType() != String.class) {
-      fail("Unexpected return type for handle: " + handle +
+      System.out.println("Unexpected return type for handle: " + handle +
           " [ " + handle.type() + "]");
     }
 
     final IllegalArgumentException iae = new IllegalArgumentException("boo!");
     try {
       handle.invoke(iae);
-      fail("Expected an exception of type: java.lang.IllegalArgumentException");
+      System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
     } catch (IllegalArgumentException expected) {
       if (expected != iae) {
-        fail("Wrong exception: expected " + iae + " but was " + expected);
+        System.out.println("Wrong exception: expected " + iae + " but was " + expected);
       }
     }
   }
@@ -262,7 +262,7 @@
       array[0] = 42;
       int value = (int) getter.invoke(array, 0);
       if (value != 42) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
 
       try {
@@ -284,7 +284,7 @@
       array[0] = 42;
       long value = (long) getter.invoke(array, 0);
       if (value != 42l) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -294,7 +294,7 @@
       array[0] = 42;
       short value = (short) getter.invoke(array, 0);
       if (value != 42l) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -304,7 +304,7 @@
       array[0] = 42;
       char value = (char) getter.invoke(array, 0);
       if (value != 42l) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -314,7 +314,7 @@
       array[0] = (byte) 0x8;
       byte value = (byte) getter.invoke(array, 0);
       if (value != (byte) 0x8) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -324,7 +324,7 @@
       array[0] = true;
       boolean value = (boolean) getter.invoke(array, 0);
       if (!value) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -334,7 +334,7 @@
       array[0] = 42.0f;
       float value = (float) getter.invoke(array, 0);
       if (value != 42.0f) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -344,7 +344,7 @@
       array[0] = 42.0;
       double value = (double) getter.invoke(array, 0);
       if (value != 42.0) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -372,10 +372,10 @@
       setter.invoke(array, 1, 43);
 
       if (array[0] != 42) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
       if (array[1] != 43) {
-        fail("Unexpected value: " + array[1]);
+        System.out.println("Unexpected value: " + array[1]);
       }
 
       try {
@@ -396,7 +396,7 @@
       long[] array = new long[1];
       setter.invoke(array, 0, 42l);
       if (array[0] != 42l) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -405,7 +405,7 @@
       short[] array = new short[1];
       setter.invoke(array, 0, (short) 42);
       if (array[0] != 42l) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -414,7 +414,7 @@
       char[] array = new char[1];
       setter.invoke(array, 0, (char) 42);
       if (array[0] != 42) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -423,7 +423,7 @@
       byte[] array = new byte[1];
       setter.invoke(array, 0, (byte) 0x8);
       if (array[0] != (byte) 0x8) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -432,7 +432,7 @@
       boolean[] array = new boolean[1];
       setter.invoke(array, 0, true);
       if (!array[0]) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -441,7 +441,7 @@
       float[] array = new float[1];
       setter.invoke(array, 0, 42.0f);
       if (array[0] != 42.0f) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -450,7 +450,7 @@
       double[] array = new double[1];
       setter.invoke(array, 0, 42.0);
       if (array[0] != 42.0) {
-        fail("Unexpected value: " + array[0]);
+        System.out.println("Unexpected value: " + array[0]);
       }
     }
 
@@ -471,7 +471,7 @@
       MethodHandle identity = MethodHandles.identity(boolean.class);
       boolean value = (boolean) identity.invoke(false);
       if (value) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -479,7 +479,7 @@
       MethodHandle identity = MethodHandles.identity(byte.class);
       byte value = (byte) identity.invoke((byte) 0x8);
       if (value != (byte) 0x8) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -487,7 +487,7 @@
       MethodHandle identity = MethodHandles.identity(char.class);
       char value = (char) identity.invoke((char) -56);
       if (value != (char) -56) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -495,7 +495,7 @@
       MethodHandle identity = MethodHandles.identity(short.class);
       short value = (short) identity.invoke((short) -59);
       if (value != (short) -59) {
-        fail("Unexpected value: " + Short.toString(value));
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -503,7 +503,7 @@
       MethodHandle identity = MethodHandles.identity(int.class);
       int value = (int) identity.invoke(52);
       if (value != 52) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -511,7 +511,7 @@
       MethodHandle identity = MethodHandles.identity(long.class);
       long value = (long) identity.invoke(-76l);
       if (value != (long) -76) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -519,7 +519,7 @@
       MethodHandle identity = MethodHandles.identity(float.class);
       float value = (float) identity.invoke(56.0f);
       if (value != (float) 56.0f) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -527,7 +527,7 @@
       MethodHandle identity = MethodHandles.identity(double.class);
       double value = (double) identity.invoke((double) 72.0);
       if (value != (double) 72.0) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -544,28 +544,28 @@
       MethodHandle constant = MethodHandles.constant(int.class, 56);
       int value = (int) constant.invoke();
       if (value != 56) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
 
       // short constant values are converted to int.
       constant = MethodHandles.constant(int.class, (short) 52);
       value = (int) constant.invoke();
       if (value != 52) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
 
       // char constant values are converted to int.
       constant = MethodHandles.constant(int.class, (char) 'b');
       value = (int) constant.invoke();
       if (value != (int) 'b') {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
 
       // int constant values are converted to int.
       constant = MethodHandles.constant(int.class, (byte) 0x1);
       value = (int) constant.invoke();
       if (value != 1) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
 
       // boolean, float, double and long primitive constants are not convertible
@@ -600,13 +600,13 @@
       MethodHandle constant = MethodHandles.constant(long.class, 56l);
       long value = (long) constant.invoke();
       if (value != 56l) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
 
       constant = MethodHandles.constant(long.class, (int) 56);
       value = (long) constant.invoke();
       if (value != 56l) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -615,7 +615,7 @@
       MethodHandle constant = MethodHandles.constant(byte.class, (byte) 0x12);
       byte value = (byte) constant.invoke();
       if (value != (byte) 0x12) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -624,7 +624,7 @@
       MethodHandle constant = MethodHandles.constant(boolean.class, true);
       boolean value = (boolean) constant.invoke();
       if (!value) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -633,7 +633,7 @@
       MethodHandle constant = MethodHandles.constant(char.class, 'f');
       char value = (char) constant.invoke();
       if (value != 'f') {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -642,7 +642,7 @@
       MethodHandle constant = MethodHandles.constant(short.class, (short) 123);
       short value = (short) constant.invoke();
       if (value != (short) 123) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -651,7 +651,7 @@
       MethodHandle constant = MethodHandles.constant(float.class, 56.0f);
       float value = (float) constant.invoke();
       if (value != 56.0f) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -660,7 +660,7 @@
       MethodHandle constant = MethodHandles.constant(double.class, 256.0);
       double value = (double) constant.invoke();
       if (value != 256.0) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -678,13 +678,13 @@
 
     char value = (char) stringCharAt.invoke("foo", 0);
     if (value != 'f') {
-      fail("Unexpected value: " + value);
+      System.out.println("Unexpected value: " + value);
     }
 
     MethodHandle bound = stringCharAt.bindTo("foo");
     value = (char) bound.invoke(0);
     if (value != 'f') {
-      fail("Unexpected value: " + value);
+      System.out.println("Unexpected value: " + value);
     }
 
     try {
@@ -706,7 +706,7 @@
     bound = integerParseInt.bindTo("78452");
     int intValue = (int) bound.invoke();
     if (intValue != 78452) {
-      fail("Unexpected value: " + intValue);
+      System.out.println("Unexpected value: " + intValue);
     }
   }
 
@@ -745,11 +745,11 @@
 
       boolean value = (boolean) adapter.invoke((int) 42);
       if (!value) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
       value = (boolean) adapter.invoke((int) 43);
       if (value) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -764,7 +764,7 @@
 
       int value = (int) adapter.invoke("56");
       if (value != 57) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
 
@@ -779,7 +779,7 @@
 
       int value = (int) adapter.invoke();
       if (value != 42) {
-        fail("Unexpected value: " + value);
+        System.out.println("Unexpected value: " + value);
       }
     }
   }
@@ -791,7 +791,7 @@
       return;
     }
 
-    fail("Unexpected arguments: " + a + ", " + b + ", " + c
+    System.out.println("Unexpected arguments: " + a + ", " + b + ", " + c
         + ", " + d + ", " + e + ", " + f + ", " + g + ", " + h);
   }
 
@@ -800,7 +800,7 @@
       return;
     }
 
-    fail("Unexpected arguments: " + a + ", " + b);
+    System.out.println("Unexpected arguments: " + a + ", " + b);
   }
 
   public static void testPermuteArguments() throws Throwable {
@@ -893,11 +893,6 @@
     Thread.dumpStack();
   }
 
-  public static void fail(String message) {
-    System.out.println("fail: " + message);
-    Thread.dumpStack();
-  }
-
   public static void assertEquals(String s1, String s2) {
     if (s1 == s2) {
       return;