Revert "Revert "Revert "Allow deoptimization when returning from a runtime method."""

Bug: 33616143

deopt string test still failing on occasion.

This reverts commit 047abb20d02546d3dd6e8630befc31e5568fa90e.

Change-Id: I89fc28696290da52317d0e3dd07ecf0d1bdac823
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index ea8d501..cf2bfee 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -1832,53 +1832,55 @@
     mov   r12, r0        @ r12 holds reference to code
     ldr   r0, [sp, #4]   @ restore r0
     RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    adr   lr, art_quick_instrumentation_exit + /* thumb mode */ 1
-                         @ load art_quick_instrumentation_exit into lr in thumb mode
     REFRESH_MARKING_REGISTER
-    bx    r12            @ call method with lr set to art_quick_instrumentation_exit
+    blx   r12            @ call method with lr set to art_quick_instrumentation_exit
+@ Deliberate fall-through into art_quick_instrumentation_exit.
+    .type art_quick_instrumentation_exit, #function
+    .global art_quick_instrumentation_exit
+art_quick_instrumentation_exit:
+    mov   lr, #0         @ link register is to here, so clobber with 0 for later checks
+    SETUP_SAVE_REFS_ONLY_FRAME r2  @ set up frame knowing r2 and r3 must be dead on exit
+    mov   r12, sp        @ remember bottom of caller's frame
+    push  {r0-r1}        @ save return value
+    .cfi_adjust_cfa_offset 8
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset r1, 4
+    mov   r2, sp         @ store gpr_res pointer.
+    vpush {d0}           @ save fp return value
+    .cfi_adjust_cfa_offset 8
+    mov   r3, sp         @ store fpr_res pointer
+    mov   r1, r12        @ pass SP
+    mov   r0, r9         @ pass Thread::Current
+    blx   artInstrumentationMethodExitFromCode  @ (Thread*, SP, gpr_res*, fpr_res*)
+
+    mov   r2, r0         @ link register saved by instrumentation
+    mov   lr, r1         @ r1 is holding link register if we're to bounce to deoptimize
+    vpop  {d0}           @ restore fp return value
+    .cfi_adjust_cfa_offset -8
+    pop   {r0, r1}       @ restore return value
+    .cfi_adjust_cfa_offset -8
+    .cfi_restore r0
+    .cfi_restore r1
+    RESTORE_SAVE_REFS_ONLY_FRAME
+    REFRESH_MARKING_REGISTER
+    cbz   r2, .Ldo_deliver_instrumentation_exception
+                         @ Deliver exception if we got nullptr as function.
+    bx    r2             @ Otherwise, return
 .Ldeliver_instrumentation_entry_exception:
     @ Deliver exception for art_quick_instrumentation_entry placed after
     @ art_quick_instrumentation_exit so that the fallthrough works.
     RESTORE_SAVE_REFS_AND_ARGS_FRAME
+.Ldo_deliver_instrumentation_exception:
     DELIVER_PENDING_EXCEPTION
 END art_quick_instrumentation_entry
 
-ENTRY art_quick_instrumentation_exit
-    mov   lr, #0         @ link register is to here, so clobber with 0 for later checks
-    SETUP_SAVE_EVERYTHING_FRAME r2
-
-    add   r3, sp, #8     @ store fpr_res pointer, in kSaveEverything frame
-    add   r2, sp, #136   @ store gpr_res pointer, in kSaveEverything frame
-    mov   r1, sp         @ pass SP
-    mov   r0, r9         @ pass Thread::Current
-    blx   artInstrumentationMethodExitFromCode  @ (Thread*, SP, gpr_res*, fpr_res*)
-
-    cbz   r0, .Ldo_deliver_instrumentation_exception
-                         @ Deliver exception if we got nullptr as function.
-    cbnz  r1, .Ldeoptimize
-    // Normal return.
-    str   r0, [sp, #FRAME_SIZE_SAVE_EVERYTHING - 4]
-                         @ Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    REFRESH_MARKING_REGISTER
-    bx lr
-.Ldo_deliver_instrumentation_exception:
-    DELIVER_PENDING_EXCEPTION_FRAME_READY
-.Ldeoptimize:
-    str   r1, [sp, #FRAME_SIZE_SAVE_EVERYTHING - 4]
-                         @ Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    // Jump to art_quick_deoptimize.
-    b     art_quick_deoptimize
-END art_quick_instrumentation_exit
-
     /*
      * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
      * will long jump to the upcall with a special exception of -1.
      */
     .extern artDeoptimize
 ENTRY art_quick_deoptimize
-    SETUP_SAVE_EVERYTHING_FRAME r0
+    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r0
     mov    r0, r9         @ pass Thread::Current
     blx    artDeoptimize  @ (Thread*)
 END art_quick_deoptimize
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 6c9ce93..3d8ca40 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -2355,31 +2355,32 @@
     .extern artInstrumentationMethodExitFromCode
 ENTRY art_quick_instrumentation_exit
     mov   xLR, #0             // Clobber LR for later checks.
-    SETUP_SAVE_EVERYTHING_FRAME
 
-    add   x3, sp, #8          // Pass floating-point result pointer, in kSaveEverything frame.
-    add   x2, sp, #264        // Pass integer result pointer, in kSaveEverything frame.
-    mov   x1, sp              // Pass SP.
+    SETUP_SAVE_REFS_ONLY_FRAME
+
+    str x0, [sp, #-16]!       // Save integer result.
+    .cfi_adjust_cfa_offset 16
+    str d0, [sp, #8]          // Save floating-point result.
+
+    add   x3, sp, #8          // Pass floating-point result pointer.
+    mov   x2, sp              // Pass integer result pointer.
+    add   x1, sp, #16         // Pass SP.
     mov   x0, xSELF           // Pass Thread.
     bl   artInstrumentationMethodExitFromCode    // (Thread*, SP, gpr_res*, fpr_res*)
 
-    cbz   x0, .Ldo_deliver_instrumentation_exception
-                              // Handle error
-    cbnz  x1, .Ldeoptimize
-    // Normal return.
-    str   x0, [sp, #FRAME_SIZE_SAVE_EVERYTHING - 8]
-                              // Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
+    mov   xIP0, x0            // Return address from instrumentation call.
+    mov   xLR, x1             // r1 is holding link register if we're to bounce to deoptimize
+
+    ldr   d0, [sp, #8]        // Restore floating-point result.
+    ldr   x0, [sp], #16       // Restore integer result, and drop stack area.
+    .cfi_adjust_cfa_offset -16
+
+    RESTORE_SAVE_REFS_ONLY_FRAME
     REFRESH_MARKING_REGISTER
-    br    lr
-.Ldo_deliver_instrumentation_exception:
-    DELIVER_PENDING_EXCEPTION_FRAME_READY
-.Ldeoptimize:
-    str   x1, [sp, #FRAME_SIZE_SAVE_EVERYTHING - 8]
-                              // Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    // Jump to art_quick_deoptimize.
-    b     art_quick_deoptimize
+    cbz   xIP0, 1f            // Handle error
+    br    xIP0                // Tail-call out.
+1:
+    DELIVER_PENDING_EXCEPTION
 END art_quick_instrumentation_exit
 
     /*
@@ -2388,7 +2389,7 @@
      */
     .extern artDeoptimize
 ENTRY art_quick_deoptimize
-    SETUP_SAVE_EVERYTHING_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
     mov    x0, xSELF          // Pass thread.
     bl     artDeoptimize      // (Thread*)
     brk 0
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index af82e08..4e5e93a 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -2056,43 +2056,42 @@
 DEFINE_FUNCTION_CUSTOM_CFA art_quick_instrumentation_exit, 0
     pushl LITERAL(0)              // Push a fake return PC as there will be none on the stack.
     CFI_ADJUST_CFA_OFFSET(4)
-    SETUP_SAVE_EVERYTHING_FRAME ebx, ebx
-
-    movl %esp, %ecx               // Remember SP
-    subl LITERAL(8), %esp         // Align stack.
+    SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx
+    mov  %esp, %ecx               // Remember SP
+    subl LITERAL(8), %esp         // Save float return value.
     CFI_ADJUST_CFA_OFFSET(8)
-    PUSH edx                      // Save gpr return value. edx and eax need to be together,
-                                  // which isn't the case in kSaveEverything frame.
+    movq %xmm0, (%esp)
+    PUSH edx                      // Save gpr return value.
     PUSH eax
-    leal 32(%esp), %eax           // Get pointer to fpr_result, in kSaveEverything frame
+    leal 8(%esp), %eax            // Get pointer to fpr_result
     movl %esp, %edx               // Get pointer to gpr_result
     PUSH eax                      // Pass fpr_result
     PUSH edx                      // Pass gpr_result
-    PUSH ecx                      // Pass SP
+    PUSH ecx                      // Pass SP.
     pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current.
     CFI_ADJUST_CFA_OFFSET(4)
-
     call SYMBOL(artInstrumentationMethodExitFromCode)  // (Thread*, SP, gpr_result*, fpr_result*)
-    // Return result could have been changed if it's a reference.
-    movl 16(%esp), %ecx
-    movl %ecx, (80+32)(%esp)
-    addl LITERAL(32), %esp        // Pop arguments and grp_result.
-    CFI_ADJUST_CFA_OFFSET(-32)
-
     testl %eax, %eax              // Check if we returned error.
-    jz .Ldo_deliver_instrumentation_exception
-    testl %edx, %edx
-    jnz .Ldeoptimize
-    // Normal return.
-    movl %eax, FRAME_SIZE_SAVE_EVERYTHING-4(%esp)   // Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    ret
-.Ldeoptimize:
-    mov %edx, (FRAME_SIZE_SAVE_EVERYTHING-4)(%esp)  // Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    jmp SYMBOL(art_quick_deoptimize)
-.Ldo_deliver_instrumentation_exception:
-    DELIVER_PENDING_EXCEPTION_FRAME_READY
+    jz 1f
+    mov   %eax, %ecx              // Move returned link register.
+    addl LITERAL(16), %esp        // Pop arguments.
+    CFI_ADJUST_CFA_OFFSET(-16)
+    movl %edx, %ebx               // Move returned link register for deopt
+                                  // (ebx is pretending to be our LR).
+    POP eax                       // Restore gpr return value.
+    POP edx
+    movq (%esp), %xmm0            // Restore fpr return value.
+    addl LITERAL(8), %esp
+    CFI_ADJUST_CFA_OFFSET(-8)
+    RESTORE_SAVE_REFS_ONLY_FRAME
+    addl LITERAL(4), %esp         // Remove fake return pc.
+    CFI_ADJUST_CFA_OFFSET(-4)
+    jmp   *%ecx                   // Return.
+1:
+    addl LITERAL(32), %esp
+    CFI_ADJUST_CFA_OFFSET(-32)
+    RESTORE_SAVE_REFS_ONLY_FRAME
+    DELIVER_PENDING_EXCEPTION
 END_FUNCTION art_quick_instrumentation_exit
 
     /*
@@ -2100,7 +2099,8 @@
      * will long jump to the upcall with a special exception of -1.
      */
 DEFINE_FUNCTION art_quick_deoptimize
-    SETUP_SAVE_EVERYTHING_FRAME ebx, ebx
+    PUSH ebx                      // Entry point for a jump. Fake that we were called.
+    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx
     subl LITERAL(12), %esp        // Align stack.
     CFI_ADJUST_CFA_OFFSET(12)
     pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 6bf0828..73e8610 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -2019,31 +2019,45 @@
     pushq LITERAL(0)          // Push a fake return PC as there will be none on the stack.
     CFI_ADJUST_CFA_OFFSET(8)
 
-    SETUP_SAVE_EVERYTHING_FRAME
+    SETUP_SAVE_REFS_ONLY_FRAME
 
-    leaq 16(%rsp), %rcx       // Pass floating-point result pointer, in kSaveEverything frame.
-    leaq 144(%rsp), %rdx      // Pass integer result pointer, in kSaveEverything frame.
-    movq %rsp, %rsi           // Pass SP.
-    movq %gs:THREAD_SELF_OFFSET, %rdi  // Pass Thread.
+    // We need to save rax and xmm0. We could use a callee-save from SETUP_REF_ONLY, but then
+    // we would need to fully restore it. As there are a good number of callee-save registers, it
+    // seems easier to have an extra small stack area. But this should be revisited.
+
+    movq  %rsp, %rsi                          // Pass SP.
+
+    PUSH rax                  // Save integer result.
+    movq %rsp, %rdx           // Pass integer result pointer.
+
+    subq LITERAL(8), %rsp     // Save floating-point result.
+    CFI_ADJUST_CFA_OFFSET(8)
+    movq %xmm0, (%rsp)
+    movq %rsp, %rcx           // Pass floating-point result pointer.
+
+    movq  %gs:THREAD_SELF_OFFSET, %rdi        // Pass Thread.
 
     call SYMBOL(artInstrumentationMethodExitFromCode)   // (Thread*, SP, gpr_res*, fpr_res*)
 
-    testq %rax, %rax          // Check if we have a return-pc to go to. If we don't then there was
+    movq  %rax, %rdi          // Store return PC
+    movq  %rdx, %rsi          // Store second return PC in hidden arg.
+
+    movq (%rsp), %xmm0        // Restore floating-point result.
+    addq LITERAL(8), %rsp
+    CFI_ADJUST_CFA_OFFSET(-8)
+    POP rax                   // Restore integer result.
+
+    RESTORE_SAVE_REFS_ONLY_FRAME
+
+    testq %rdi, %rdi          // Check if we have a return-pc to go to. If we don't then there was
                               // an exception
-    jz .Ldo_deliver_instrumentation_exception
-    testq %rdx, %rdx
-    jnz .Ldeoptimize
-    // Normal return.
-    movq %rax, FRAME_SIZE_SAVE_EVERYTHING-8(%rsp)  // Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    ret
-.Ldeoptimize:
-    movq %rdx, FRAME_SIZE_SAVE_EVERYTHING-8(%rsp)  // Set return pc.
-    RESTORE_SAVE_EVERYTHING_FRAME
-    // Jump to art_quick_deoptimize.
-    jmp SYMBOL(art_quick_deoptimize)
-.Ldo_deliver_instrumentation_exception:
-    DELIVER_PENDING_EXCEPTION_FRAME_READY
+    jz 1f
+
+    addq LITERAL(8), %rsp     // Drop fake return pc.
+
+    jmp   *%rdi               // Return.
+1:
+    DELIVER_PENDING_EXCEPTION
 END_FUNCTION art_quick_instrumentation_exit
 
     /*
@@ -2051,7 +2065,10 @@
      * will long jump to the upcall with a special exception of -1.
      */
 DEFINE_FUNCTION art_quick_deoptimize
-    SETUP_SAVE_EVERYTHING_FRAME        // Stack should be aligned now.
+    pushq %rsi                         // Entry point for a jump. Fake that we were called.
+                                       // Use hidden arg.
+    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+                                       // Stack should be aligned now.
     movq %gs:THREAD_SELF_OFFSET, %rdi  // Pass Thread.
     call SYMBOL(artDeoptimize)         // (Thread*)
     UNREACHABLE
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 5f40711..53f0727 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -73,11 +73,7 @@
   // Before deoptimizing to interpreter, we must push the deoptimization context.
   JValue return_value;
   return_value.SetJ(0);  // we never deoptimize from compiled code with an invoke result.
-  self->PushDeoptimizationContext(return_value,
-                                  false /* is_reference */,
-                                  self->GetException(),
-                                  true /* from_code */,
-                                  DeoptimizationMethodType::kDefault);
+  self->PushDeoptimizationContext(return_value, false, /* from_code */ true, self->GetException());
   artDeoptimizeImpl(self, kind, true);
 }
 
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 5f71326..e08319d 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -744,11 +744,7 @@
 
     ObjPtr<mirror::Throwable> pending_exception;
     bool from_code = false;
-    DeoptimizationMethodType method_type;
-    self->PopDeoptimizationContext(/* out */ &result,
-                                   /* out */ &pending_exception,
-                                   /* out */ &from_code,
-                                   /* out */ &method_type);
+    self->PopDeoptimizationContext(&result, &pending_exception, /* out */ &from_code);
 
     // Push a transition back into managed code onto the linked list in thread.
     self->PushManagedStackFragment(&fragment);
@@ -775,11 +771,7 @@
     if (pending_exception != nullptr) {
       self->SetException(pending_exception);
     }
-    interpreter::EnterInterpreterFromDeoptimize(self,
-                                                deopt_frame,
-                                                &result,
-                                                from_code,
-                                                DeoptimizationMethodType::kDefault);
+    interpreter::EnterInterpreterFromDeoptimize(self, deopt_frame, from_code, &result);
   } else {
     const char* old_cause = self->StartAssertNoThreadSuspension(
         "Building interpreter shadow frame");
@@ -831,11 +823,7 @@
       // Push the context of the deoptimization stack so we can restore the return value and the
       // exception before executing the deoptimized frames.
       self->PushDeoptimizationContext(
-          result,
-          shorty[0] == 'L' || shorty[0] == '[',  /* class or array */
-          self->GetException(),
-          false /* from_code */,
-          DeoptimizationMethodType::kDefault);
+          result, shorty[0] == 'L', /* from_code */ false, self->GetException());
 
       // Set special exception to cause deoptimization.
       self->SetException(Thread::GetDeoptimizationException());
@@ -1053,8 +1041,7 @@
   CHECK(!self->IsExceptionPending()) << "Enter instrumentation exit stub with pending exception "
                                      << self->GetException()->Dump();
   // Compute address of return PC and sanity check that it currently holds 0.
-  size_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA,
-                                                        CalleeSaveType::kSaveEverything);
+  size_t return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, CalleeSaveType::kSaveRefsOnly);
   uintptr_t* return_pc = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) +
                                                       return_pc_offset);
   CHECK_EQ(*return_pc, 0U);
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index de25a6d..a8cf59b 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -26,7 +26,6 @@
 #include "class_linker.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
-#include "dex_instruction-inl.h"
 #include "entrypoints/quick/quick_alloc_entrypoints.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
@@ -228,32 +227,39 @@
         return true;  // Continue.
       }
       uintptr_t return_pc = GetReturnPc();
+      if (m->IsRuntimeMethod()) {
+        if (return_pc == instrumentation_exit_pc_) {
+          if (kVerboseInstrumentation) {
+            LOG(INFO) << "  Handling quick to interpreter transition. Frame " << GetFrameId();
+          }
+          CHECK_LT(instrumentation_stack_depth_, instrumentation_stack_->size());
+          const InstrumentationStackFrame& frame =
+              instrumentation_stack_->at(instrumentation_stack_depth_);
+          CHECK(frame.interpreter_entry_);
+          // This is an interpreter frame so method enter event must have been reported. However we
+          // need to push a DEX pc into the dex_pcs_ list to match size of instrumentation stack.
+          // Since we won't report method entry here, we can safely push any DEX pc.
+          dex_pcs_.push_back(0);
+          last_return_pc_ = frame.return_pc_;
+          ++instrumentation_stack_depth_;
+          return true;
+        } else {
+          if (kVerboseInstrumentation) {
+            LOG(INFO) << "  Skipping runtime method. Frame " << GetFrameId();
+          }
+          last_return_pc_ = GetReturnPc();
+          return true;  // Ignore unresolved methods since they will be instrumented after resolution.
+        }
+      }
       if (kVerboseInstrumentation) {
         LOG(INFO) << "  Installing exit stub in " << DescribeLocation();
       }
       if (return_pc == instrumentation_exit_pc_) {
-        CHECK_LT(instrumentation_stack_depth_, instrumentation_stack_->size());
-
-        if (m->IsRuntimeMethod()) {
-          const InstrumentationStackFrame& frame =
-              instrumentation_stack_->at(instrumentation_stack_depth_);
-          if (frame.interpreter_entry_) {
-            // This instrumentation frame is for an interpreter bridge and is
-            // pushed when executing the instrumented interpreter bridge. So method
-            // enter event must have been reported. However we need to push a DEX pc
-            // into the dex_pcs_ list to match size of instrumentation stack.
-            uint32_t dex_pc = DexFile::kDexNoIndex;
-            dex_pcs_.push_back(dex_pc);
-            last_return_pc_ = frame.return_pc_;
-            ++instrumentation_stack_depth_;
-            return true;
-          }
-        }
-
         // We've reached a frame which has already been installed with instrumentation exit stub.
         // We should have already installed instrumentation on previous frames.
         reached_existing_instrumentation_frames_ = true;
 
+        CHECK_LT(instrumentation_stack_depth_, instrumentation_stack_->size());
         const InstrumentationStackFrame& frame =
             instrumentation_stack_->at(instrumentation_stack_depth_);
         CHECK_EQ(m, frame.method_) << "Expected " << ArtMethod::PrettyMethod(m)
@@ -265,12 +271,8 @@
       } else {
         CHECK_NE(return_pc, 0U);
         CHECK(!reached_existing_instrumentation_frames_);
-        InstrumentationStackFrame instrumentation_frame(
-            m->IsRuntimeMethod() ? nullptr : GetThisObject(),
-            m,
-            return_pc,
-            GetFrameId(),    // A runtime method still gets a frame id.
-            false);
+        InstrumentationStackFrame instrumentation_frame(GetThisObject(), m, return_pc, GetFrameId(),
+                                                        false);
         if (kVerboseInstrumentation) {
           LOG(INFO) << "Pushing frame " << instrumentation_frame.Dump();
         }
@@ -287,12 +289,9 @@
         instrumentation_stack_->insert(it, instrumentation_frame);
         SetReturnPc(instrumentation_exit_pc_);
       }
-      uint32_t dex_pc = DexFile::kDexNoIndex;
-      if (last_return_pc_ != 0 &&
-          GetCurrentOatQuickMethodHeader() != nullptr) {
-        dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_);
-      }
-      dex_pcs_.push_back(dex_pc);
+      dex_pcs_.push_back((GetCurrentOatQuickMethodHeader() == nullptr)
+          ? DexFile::kDexNoIndex
+          : GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_));
       last_return_pc_ = return_pc;
       ++instrumentation_stack_depth_;
       return true;  // Continue.
@@ -390,8 +389,7 @@
             CHECK(m == instrumentation_frame.method_) << ArtMethod::PrettyMethod(m);
           }
           SetReturnPc(instrumentation_frame.return_pc_);
-          if (instrumentation_->ShouldNotifyMethodEnterExitEvents() &&
-              !m->IsRuntimeMethod()) {
+          if (instrumentation_->ShouldNotifyMethodEnterExitEvents()) {
             // Create the method exit events. As the methods didn't really exit the result is 0.
             // We only do this if no debugger is attached to prevent from posting events twice.
             instrumentation_->MethodExitEvent(thread_, instrumentation_frame.this_object_, m,
@@ -949,7 +947,6 @@
                                            ObjPtr<mirror::Object> this_object,
                                            ArtMethod* method,
                                            uint32_t dex_pc) const {
-  DCHECK(!method->IsRuntimeMethod());
   if (HasMethodEntryListeners()) {
     Thread* self = Thread::Current();
     StackHandleScope<1> hs(self);
@@ -1154,54 +1151,6 @@
   stack->push_front(instrumentation_frame);
 }
 
-DeoptimizationMethodType Instrumentation::GetDeoptimizationMethodType(ArtMethod* method) {
-  if (method->IsRuntimeMethod()) {
-    // Certain methods have strict requirement on whether the dex instruction
-    // should be re-executed upon deoptimization.
-    if (method == Runtime::Current()->GetCalleeSaveMethod(
-        CalleeSaveType::kSaveEverythingForClinit)) {
-      return DeoptimizationMethodType::kKeepDexPc;
-    }
-    if (method == Runtime::Current()->GetCalleeSaveMethod(
-        CalleeSaveType::kSaveEverythingForSuspendCheck)) {
-      return DeoptimizationMethodType::kKeepDexPc;
-    }
-  }
-  return DeoptimizationMethodType::kDefault;
-}
-
-// Try to get the shorty of a runtime method if it's an invocation stub.
-struct RuntimeMethodShortyVisitor : public StackVisitor {
-  explicit RuntimeMethodShortyVisitor(Thread* thread)
-      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
-        shorty('V') {}
-
-  bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
-    ArtMethod* m = GetMethod();
-    if (m != nullptr && !m->IsRuntimeMethod()) {
-      // The first Java method.
-      if (m->IsNative()) {
-        // Use JNI method's shorty for the jni stub.
-        shorty = m->GetShorty()[0];
-        return false;
-      }
-      const DexFile::CodeItem* code_item = m->GetCodeItem();
-      const Instruction* instr = Instruction::At(&code_item->insns_[GetDexPc()]);
-      if (instr->IsInvoke()) {
-        // If it's an invoke, use its shorty.
-        uint32_t method_idx = instr->VRegB();
-        shorty = m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetDexFile()
-            ->GetMethodShorty(method_idx)[0];
-      }
-      // Stop stack walking since we've seen a Java frame.
-      return false;
-    }
-    return true;
-  }
-
-  char shorty;
-};
-
 TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self,
                                                             uintptr_t* return_pc,
                                                             uint64_t* gpr_result,
@@ -1222,36 +1171,7 @@
   ArtMethod* method = instrumentation_frame.method_;
   uint32_t length;
   const PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
-  char return_shorty;
-
-  // Runtime method does not call into MethodExitEvent() so there should not be
-  // suspension point below.
-  ScopedAssertNoThreadSuspension ants(__FUNCTION__, method->IsRuntimeMethod());
-  if (method->IsRuntimeMethod()) {
-    if (method != Runtime::Current()->GetCalleeSaveMethod(
-        CalleeSaveType::kSaveEverythingForClinit)) {
-      // If the caller is at an invocation point and the runtime method is not
-      // for clinit, we need to pass return results to the caller.
-      // We need the correct shorty to decide whether we need to pass the return
-      // result for deoptimization below.
-      RuntimeMethodShortyVisitor visitor(self);
-      visitor.WalkStack();
-      return_shorty = visitor.shorty;
-    } else {
-      // Some runtime methods such as allocations, unresolved field getters, etc.
-      // have return value. We don't need to set return_value since MethodExitEvent()
-      // below isn't called for runtime methods. Deoptimization doesn't need the
-      // value either since the dex instruction will be re-executed by the
-      // interpreter, except these two cases:
-      // (1) For an invoke, which is handled above to get the correct shorty.
-      // (2) For MONITOR_ENTER/EXIT, which cannot be re-executed since it's not
-      //     idempotent. However there is no return value for it anyway.
-      return_shorty = 'V';
-    }
-  } else {
-    return_shorty = method->GetInterfaceMethodIfProxy(pointer_size)->GetShorty(&length)[0];
-  }
-
+  char return_shorty = method->GetInterfaceMethodIfProxy(pointer_size)->GetShorty(&length)[0];
   bool is_ref = return_shorty == '[' || return_shorty == 'L';
   StackHandleScope<1> hs(self);
   MutableHandle<mirror::Object> res(hs.NewHandle<mirror::Object>(nullptr));
@@ -1271,7 +1191,7 @@
   //       return_pc.
   uint32_t dex_pc = DexFile::kDexNoIndex;
   mirror::Object* this_object = instrumentation_frame.this_object_;
-  if (!method->IsRuntimeMethod() && !instrumentation_frame.interpreter_entry_) {
+  if (!instrumentation_frame.interpreter_entry_) {
     MethodExitEvent(self, this_object, instrumentation_frame.method_, dex_pc, return_value);
   }
 
@@ -1297,12 +1217,10 @@
                 << " in "
                 << *self;
     }
-    DeoptimizationMethodType deopt_method_type = GetDeoptimizationMethodType(method);
     self->PushDeoptimizationContext(return_value,
-                                    return_shorty == 'L' || return_shorty == '[',
-                                    nullptr /* no pending exception */,
+                                    return_shorty == 'L',
                                     false /* from_code */,
-                                    deopt_method_type);
+                                    nullptr /* no pending exception */);
     return GetTwoWordSuccessValue(*return_pc,
                                   reinterpret_cast<uintptr_t>(GetQuickDeoptimizationEntryPoint()));
   } else {
@@ -1339,9 +1257,7 @@
     // TODO: improve the dex pc information here, requires knowledge of current PC as opposed to
     //       return_pc.
     uint32_t dex_pc = DexFile::kDexNoIndex;
-    if (!method->IsRuntimeMethod()) {
-      MethodUnwindEvent(self, instrumentation_frame.this_object_, method, dex_pc);
-    }
+    MethodUnwindEvent(self, instrumentation_frame.this_object_, method, dex_pc);
   }
   // TODO: bring back CheckStackDepth(self, instrumentation_frame, 2);
   CHECK_EQ(stack->size(), idx);
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 577bbf9..9969489 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -39,7 +39,6 @@
 template <typename T> class Handle;
 union JValue;
 class Thread;
-enum class DeoptimizationMethodType;
 
 namespace instrumentation {
 
@@ -436,9 +435,6 @@
                                      bool interpreter_entry)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  DeoptimizationMethodType GetDeoptimizationMethodType(ArtMethod* method)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Called when an instrumented method is exited. Removes the pushed instrumentation frame
   // returning the intended link register. Generates method exit events. The gpr_result and
   // fpr_result pointers are pointers to the locations where the integer/pointer and floating point
@@ -665,15 +661,9 @@
 
 // An element in the instrumentation side stack maintained in art::Thread.
 struct InstrumentationStackFrame {
-  InstrumentationStackFrame(mirror::Object* this_object,
-                            ArtMethod* method,
-                            uintptr_t return_pc,
-                            size_t frame_id,
-                            bool interpreter_entry)
-      : this_object_(this_object),
-        method_(method),
-        return_pc_(return_pc),
-        frame_id_(frame_id),
+  InstrumentationStackFrame(mirror::Object* this_object, ArtMethod* method,
+                            uintptr_t return_pc, size_t frame_id, bool interpreter_entry)
+      : this_object_(this_object), method_(method), return_pc_(return_pc), frame_id_(frame_id),
         interpreter_entry_(interpreter_entry) {
   }
 
diff --git a/runtime/instrumentation_test.cc b/runtime/instrumentation_test.cc
index bfd36cc..d25655f 100644
--- a/runtime/instrumentation_test.cc
+++ b/runtime/instrumentation_test.cc
@@ -473,23 +473,7 @@
 
 // Test instrumentation listeners for each event.
 TEST_F(InstrumentationTest, MethodEntryEvent) {
-  ScopedObjectAccess soa(Thread::Current());
-  jobject class_loader = LoadDex("Instrumentation");
-  Runtime* const runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
-  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
-  ASSERT_TRUE(klass != nullptr);
-  ArtMethod* method =
-      klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize);
-  ASSERT_TRUE(method != nullptr);
-  ASSERT_TRUE(method->IsDirect());
-  ASSERT_TRUE(method->GetDeclaringClass() == klass);
-  TestEvent(instrumentation::Instrumentation::kMethodEntered,
-            /*event_method*/ method,
-            /*event_field*/ nullptr,
-            /*with_object*/ true);
+  TestEvent(instrumentation::Instrumentation::kMethodEntered);
 }
 
 TEST_F(InstrumentationTest, MethodExitObjectEvent) {
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 34332d7..9cb74f7 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -499,9 +499,8 @@
 
 void EnterInterpreterFromDeoptimize(Thread* self,
                                     ShadowFrame* shadow_frame,
-                                    JValue* ret_val,
                                     bool from_code,
-                                    DeoptimizationMethodType deopt_method_type)
+                                    JValue* ret_val)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   JValue value;
   // Set value to last known result in case the shadow frame chain is empty.
@@ -528,27 +527,11 @@
       new_dex_pc = found_dex_pc;  // the dex pc of a matching catch handler
                                   // or DexFile::kDexNoIndex if there is none.
     } else if (!from_code) {
-      // Deoptimization is not called from code directly.
+      // For the debugger and full deoptimization stack, we must go past the invoke
+      // instruction, as it already executed.
+      // TODO: should be tested more once b/17586779 is fixed.
       const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
-      if (deopt_method_type == DeoptimizationMethodType::kKeepDexPc) {
-        DCHECK(first);
-        // Need to re-execute the dex instruction.
-        // (1) An invocation might be split into class initialization and invoke.
-        //     In this case, the invoke should not be skipped.
-        // (2) A suspend check should also execute the dex instruction at the
-        //     corresponding dex pc.
-        DCHECK_EQ(new_dex_pc, dex_pc);
-      } else if (instr->Opcode() == Instruction::MONITOR_ENTER ||
-                 instr->Opcode() == Instruction::MONITOR_EXIT) {
-        DCHECK(deopt_method_type == DeoptimizationMethodType::kDefault);
-        DCHECK(first);
-        // Non-idempotent dex instruction should not be re-executed.
-        // On the other hand, if a MONITOR_ENTER is at the dex_pc of a suspend
-        // check, that MONITOR_ENTER should be executed. That case is handled
-        // above.
-        new_dex_pc = dex_pc + instr->SizeInCodeUnits();
-      } else if (instr->IsInvoke()) {
-        DCHECK(deopt_method_type == DeoptimizationMethodType::kDefault);
+      if (instr->IsInvoke()) {
         if (IsStringInit(instr, shadow_frame->GetMethod())) {
           uint16_t this_obj_vreg = GetReceiverRegisterForStringInit(instr);
           // Move the StringFactory.newStringFromChars() result into the register representing
@@ -561,27 +544,30 @@
         }
         new_dex_pc = dex_pc + instr->SizeInCodeUnits();
       } else if (instr->Opcode() == Instruction::NEW_INSTANCE) {
-        // A NEW_INSTANCE is simply re-executed, including
-        // "new-instance String" which is compiled into a call into
-        // StringFactory.newEmptyString().
-        DCHECK_EQ(new_dex_pc, dex_pc);
+        // It's possible to deoptimize at a NEW_INSTANCE dex instruciton that's for a
+        // java string, which is turned into a call into StringFactory.newEmptyString();
+        // Move the StringFactory.newEmptyString() result into the destination register.
+        DCHECK(value.GetL()->IsString());
+        shadow_frame->SetVRegReference(instr->VRegA_21c(), value.GetL());
+        // new-instance doesn't generate a result value.
+        value.SetJ(0);
+        // Skip the dex instruction since we essentially come back from an invocation.
+        new_dex_pc = dex_pc + instr->SizeInCodeUnits();
+        if (kIsDebugBuild) {
+          ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+          // This is a suspend point. But it's ok since value has been set into shadow_frame.
+          ObjPtr<mirror::Class> klass = class_linker->ResolveType(
+              dex::TypeIndex(instr->VRegB_21c()), shadow_frame->GetMethod());
+          DCHECK(klass->IsStringClass());
+        }
       } else {
-        DCHECK(deopt_method_type == DeoptimizationMethodType::kDefault);
-        DCHECK(first);
-        // By default, we re-execute the dex instruction since if they are not
-        // an invoke, so that we don't have to decode the dex instruction to move
-        // result into the right vreg. All slow paths have been audited to be
-        // idempotent except monitor-enter/exit and invocation stubs.
-        // TODO: move result and advance dex pc. That also requires that we
-        // can tell the return type of a runtime method, possibly by decoding
-        // the dex instruction at the caller.
-        DCHECK_EQ(new_dex_pc, dex_pc);
+        CHECK(false) << "Unexpected instruction opcode " << instr->Opcode()
+                     << " at dex_pc " << dex_pc
+                     << " of method: " << ArtMethod::PrettyMethod(shadow_frame->GetMethod(), false);
       }
     } else {
       // Nothing to do, the dex_pc is the one at which the code requested
       // the deoptimization.
-      DCHECK(first);
-      DCHECK_EQ(new_dex_pc, dex_pc);
     }
     if (new_dex_pc != DexFile::kDexNoIndex) {
       shadow_frame->SetDexPC(new_dex_pc);
@@ -590,10 +576,8 @@
     ShadowFrame* old_frame = shadow_frame;
     shadow_frame = shadow_frame->GetLink();
     ShadowFrame::DeleteDeoptimizedFrame(old_frame);
-    // Following deoptimizations of shadow frames must be at invocation point
-    // and should advance dex pc past the invoke instruction.
+    // Following deoptimizations of shadow frames must pass the invoke instruction.
     from_code = false;
-    deopt_method_type = DeoptimizationMethodType::kDefault;
     first = false;
   }
   ret_val->SetJ(value.GetJ());
diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h
index df8568e..65cfade 100644
--- a/runtime/interpreter/interpreter.h
+++ b/runtime/interpreter/interpreter.h
@@ -30,7 +30,6 @@
 union JValue;
 class ShadowFrame;
 class Thread;
-enum class DeoptimizationMethodType;
 
 namespace interpreter {
 
@@ -45,11 +44,8 @@
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 // 'from_code' denotes whether the deoptimization was explicitly triggered by compiled code.
-extern void EnterInterpreterFromDeoptimize(Thread* self,
-                                           ShadowFrame* shadow_frame,
-                                           JValue* ret_val,
-                                           bool from_code,
-                                           DeoptimizationMethodType method_type)
+extern void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, bool from_code,
+                                           JValue* ret_val)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 extern JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 01560f8..cdbb908 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -166,13 +166,11 @@
                               bool is_reference,
                               bool from_code,
                               ObjPtr<mirror::Throwable> pending_exception,
-                              DeoptimizationMethodType method_type,
                               DeoptimizationContextRecord* link)
       : ret_val_(ret_val),
         is_reference_(is_reference),
         from_code_(from_code),
         pending_exception_(pending_exception.Ptr()),
-        deopt_method_type_(method_type),
         link_(link) {}
 
   JValue GetReturnValue() const { return ret_val_; }
@@ -187,9 +185,6 @@
   mirror::Object** GetPendingExceptionAsGCRoot() {
     return reinterpret_cast<mirror::Object**>(&pending_exception_);
   }
-  DeoptimizationMethodType GetDeoptimizationMethodType() const {
-    return deopt_method_type_;
-  }
 
  private:
   // The value returned by the method at the top of the stack before deoptimization.
@@ -205,9 +200,6 @@
   // exception).
   mirror::Throwable* pending_exception_;
 
-  // Whether the context was created for an (idempotent) runtime method.
-  const DeoptimizationMethodType deopt_method_type_;
-
   // A link to the previous DeoptimizationContextRecord.
   DeoptimizationContextRecord* const link_;
 
@@ -237,30 +229,26 @@
 
 void Thread::PushDeoptimizationContext(const JValue& return_value,
                                        bool is_reference,
-                                       ObjPtr<mirror::Throwable> exception,
                                        bool from_code,
-                                       DeoptimizationMethodType method_type) {
+                                       ObjPtr<mirror::Throwable> exception) {
   DeoptimizationContextRecord* record = new DeoptimizationContextRecord(
       return_value,
       is_reference,
       from_code,
       exception,
-      method_type,
       tlsPtr_.deoptimization_context_stack);
   tlsPtr_.deoptimization_context_stack = record;
 }
 
 void Thread::PopDeoptimizationContext(JValue* result,
                                       ObjPtr<mirror::Throwable>* exception,
-                                      bool* from_code,
-                                      DeoptimizationMethodType* method_type) {
+                                      bool* from_code) {
   AssertHasDeoptimizationContext();
   DeoptimizationContextRecord* record = tlsPtr_.deoptimization_context_stack;
   tlsPtr_.deoptimization_context_stack = record->GetLink();
   result->SetJ(record->GetReturnValue().GetJ());
   *exception = record->GetPendingException();
   *from_code = record->GetFromCode();
-  *method_type = record->GetDeoptimizationMethodType();
   delete record;
 }
 
@@ -3096,16 +3084,10 @@
     NthCallerVisitor visitor(this, 0, false);
     visitor.WalkStack();
     if (Runtime::Current()->IsAsyncDeoptimizeable(visitor.caller_pc)) {
-      // method_type shouldn't matter due to exception handling.
-      const DeoptimizationMethodType method_type = DeoptimizationMethodType::kDefault;
       // Save the exception into the deoptimization context so it can be restored
       // before entering the interpreter.
       PushDeoptimizationContext(
-          JValue(),
-          false /* is_reference */,
-          exception,
-          false /* from_code */,
-          method_type);
+          JValue(), /*is_reference */ false, /* from_code */ false, exception);
       artDeoptimize(this);
       UNREACHABLE();
     } else {
@@ -3665,8 +3647,7 @@
       PopStackedShadowFrame(StackedShadowFrameType::kDeoptimizationShadowFrame);
   ObjPtr<mirror::Throwable> pending_exception;
   bool from_code = false;
-  DeoptimizationMethodType method_type;
-  PopDeoptimizationContext(result, &pending_exception, &from_code, &method_type);
+  PopDeoptimizationContext(result, &pending_exception, &from_code);
   SetTopOfStack(nullptr);
   SetTopOfShadowStack(shadow_frame);
 
@@ -3675,11 +3656,7 @@
   if (pending_exception != nullptr) {
     SetException(pending_exception);
   }
-  interpreter::EnterInterpreterFromDeoptimize(this,
-                                              shadow_frame,
-                                              result,
-                                              from_code,
-                                              method_type);
+  interpreter::EnterInterpreterFromDeoptimize(this, shadow_frame, from_code, result);
 }
 
 void Thread::SetException(ObjPtr<mirror::Throwable> new_exception) {
diff --git a/runtime/thread.h b/runtime/thread.h
index ad4506e..7540fd2 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -117,13 +117,6 @@
   kDeoptimizationShadowFrame,
 };
 
-// The type of method that triggers deoptimization. It contains info on whether
-// the deoptimized method should advance dex_pc.
-enum class DeoptimizationMethodType {
-  kKeepDexPc,  // dex pc is required to be kept upon deoptimization.
-  kDefault     // dex pc may or may not advance depending on other conditions.
-};
-
 // This should match RosAlloc::kNumThreadLocalSizeBrackets.
 static constexpr size_t kNumRosAllocThreadLocalSizeBracketsInThread = 16;
 
@@ -967,18 +960,14 @@
   // values on stacks.
   // 'from_code' denotes whether the deoptimization was explicitly made from
   // compiled code.
-  // 'method_type' contains info on whether deoptimization should advance
-  // dex_pc.
   void PushDeoptimizationContext(const JValue& return_value,
                                  bool is_reference,
-                                 ObjPtr<mirror::Throwable> exception,
                                  bool from_code,
-                                 DeoptimizationMethodType method_type)
+                                 ObjPtr<mirror::Throwable> exception)
       REQUIRES_SHARED(Locks::mutator_lock_);
   void PopDeoptimizationContext(JValue* result,
                                 ObjPtr<mirror::Throwable>* exception,
-                                bool* from_code,
-                                DeoptimizationMethodType* method_type)
+                                bool* from_code)
       REQUIRES_SHARED(Locks::mutator_lock_);
   void AssertHasDeoptimizationContext()
       REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/test/597-deopt-busy-loop/expected.txt b/test/597-deopt-busy-loop/expected.txt
deleted file mode 100644
index f993efc..0000000
--- a/test/597-deopt-busy-loop/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-JNI_OnLoad called
-Finishing
diff --git a/test/597-deopt-busy-loop/info.txt b/test/597-deopt-busy-loop/info.txt
deleted file mode 100644
index 2c50dbb..0000000
--- a/test/597-deopt-busy-loop/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test deoptimizing when returning from suspend-check runtime method.
diff --git a/test/597-deopt-busy-loop/run b/test/597-deopt-busy-loop/run
deleted file mode 100644
index bc04498..0000000
--- a/test/597-deopt-busy-loop/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-# We want to run in debuggable mode and compiled.
-exec ${RUN} --jit -Xcompiler-option --debuggable "${@}"
diff --git a/test/597-deopt-busy-loop/src/Main.java b/test/597-deopt-busy-loop/src/Main.java
deleted file mode 100644
index 46b6bbf..0000000
--- a/test/597-deopt-busy-loop/src/Main.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 class Main implements Runnable {
-    static final int numberOfThreads = 2;
-    volatile static boolean sExitFlag = false;
-    volatile static boolean sEntered = false;
-    int threadIndex;
-
-    private static native void deoptimizeAll();
-    private static native void assertIsInterpreted();
-    private static native void assertIsManaged();
-    private static native void ensureJitCompiled(Class<?> cls, String methodName);
-
-    Main(int index) {
-        threadIndex = index;
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.loadLibrary(args[0]);
-
-        final Thread[] threads = new Thread[numberOfThreads];
-        for (int t = 0; t < threads.length; t++) {
-            threads[t] = new Thread(new Main(t));
-            threads[t].start();
-        }
-        for (Thread t : threads) {
-            t.join();
-        }
-        System.out.println("Finishing");
-    }
-
-    public void $noinline$busyLoop() {
-        assertIsManaged();
-        sEntered = true;
-        for (;;) {
-            if (sExitFlag) {
-                break;
-            }
-        }
-        assertIsInterpreted();
-    }
-
-    public void run() {
-        if (threadIndex == 0) {
-            while (!sEntered) {
-              Thread.yield();
-            }
-            deoptimizeAll();
-            sExitFlag = true;
-        } else {
-            ensureJitCompiled(Main.class, "$noinline$busyLoop");
-            $noinline$busyLoop();
-        }
-    }
-}
diff --git a/test/597-deopt-invoke-stub/expected.txt b/test/597-deopt-invoke-stub/expected.txt
deleted file mode 100644
index f993efc..0000000
--- a/test/597-deopt-invoke-stub/expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-JNI_OnLoad called
-Finishing
diff --git a/test/597-deopt-invoke-stub/info.txt b/test/597-deopt-invoke-stub/info.txt
deleted file mode 100644
index 31960a9..0000000
--- a/test/597-deopt-invoke-stub/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test deoptimizing when returning from a quick-to-interpreter bridge.
diff --git a/test/597-deopt-invoke-stub/run b/test/597-deopt-invoke-stub/run
deleted file mode 100644
index bc04498..0000000
--- a/test/597-deopt-invoke-stub/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-# We want to run in debuggable mode and compiled.
-exec ${RUN} --jit -Xcompiler-option --debuggable "${@}"
diff --git a/test/597-deopt-invoke-stub/src/Main.java b/test/597-deopt-invoke-stub/src/Main.java
deleted file mode 100644
index 0751783..0000000
--- a/test/597-deopt-invoke-stub/src/Main.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 class Main implements Runnable {
-    static final int numberOfThreads = 2;
-    volatile static boolean sExitFlag = false;
-    volatile static boolean sEntered = false;
-    int threadIndex;
-
-    private static native void deoptimizeAll();
-    private static native void assertIsInterpreted();
-    private static native void assertIsManaged();
-    private static native void ensureJitCompiled(Class<?> cls, String methodName);
-
-    Main(int index) {
-        threadIndex = index;
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.loadLibrary(args[0]);
-
-        final Thread[] threads = new Thread[numberOfThreads];
-        for (int t = 0; t < threads.length; t++) {
-            threads[t] = new Thread(new Main(t));
-            threads[t].start();
-        }
-        for (Thread t : threads) {
-            t.join();
-        }
-        System.out.println("Finishing");
-    }
-
-    private static int $noinline$bar() {
-        // Should be entered via interpreter bridge.
-        assertIsInterpreted();
-        sEntered = true;
-        while (!sExitFlag) {}
-        assertIsInterpreted();
-        return 0x1234;
-    }
-
-    public void $noinline$foo() {
-        assertIsManaged();
-        if ($noinline$bar() != 0x1234) {
-            System.out.println("Bad return value");
-        }
-        assertIsInterpreted();
-    }
-
-    public void run() {
-        if (threadIndex == 0) {
-            while (!sEntered) {
-              Thread.yield();
-            }
-            deoptimizeAll();
-            sExitFlag = true;
-        } else {
-            ensureJitCompiled(Main.class, "$noinline$foo");
-            $noinline$foo();
-        }
-    }
-}
diff --git a/test/knownfailures.json b/test/knownfailures.json
index d76103a..20cfc34 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -207,9 +207,7 @@
         "variant": "trace | stream"
     },
     {
-        "tests": ["597-deopt-busy-loop",
-                  "597-deopt-invoke-stub",
-                  "604-hot-static-interface",
+        "tests": ["604-hot-static-interface",
                   "612-jit-dex-cache",
                   "613-inlining-dex-cache",
                   "626-set-resolved-string"],