MIPS: Fix art_quick_instrumentation_entry/exit

This is a follow-up change for
Iab229353fae23c2ea27c2b698c831627a9f861b1.

This fixes following tests for both MIPS32 and MIPS64:
  * 099-vmdebug
  * 304-method-tracing
  * 545-tracing-and-jit
  * 570-checker-osr
  * 597-deopt-new-string
  * 802-deoptimization
  * 988-method-trace
  * 989-method-trace-throw

Test: ./testrunner.py --optimizing --target in QEMU (MIPS64R6)
Test: ./testrunner.py --optimizing --target on CI20 (MIPS32R2)

Change-Id: I064588283b65971f07150eb30a1fcf90c765eb40
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index d1da67f..a5a65e6 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -2003,10 +2003,11 @@
 ENTRY art_quick_instrumentation_entry
     SETUP_SAVE_REFS_AND_ARGS_FRAME
     sw       $a0, 28($sp)   # save arg0 in free arg slot
-    move     $a3, $ra       # pass $ra
+    addiu    $a3, $sp, ARG_SLOT_SIZE      # Pass $sp.
     la       $t9, artInstrumentationMethodEntryFromCode
-    jalr     $t9            # (Method*, Object*, Thread*, LR)
+    jalr     $t9            # (Method*, Object*, Thread*, SP)
     move     $a2, rSELF     # pass Thread::Current
+    beqz     $v0, .Ldeliver_instrumentation_entry_exception
     move     $t9, $v0       # $t9 holds reference to code
     lw       $a0, 28($sp)   # restore arg0 from free arg slot
     RESTORE_SAVE_REFS_AND_ARGS_FRAME
@@ -2024,26 +2025,35 @@
     SETUP_SAVE_REFS_ONLY_FRAME
     addiu    $sp, $sp, -16  # allocate temp storage on the stack
     .cfi_adjust_cfa_offset 16
-    sw       $v0, ARG_SLOT_SIZE+12($sp)
-    .cfi_rel_offset 2, ARG_SLOT_SIZE+12
-    sw       $v1, ARG_SLOT_SIZE+8($sp)
-    .cfi_rel_offset 3, ARG_SLOT_SIZE+8
+    sw       $v0, ARG_SLOT_SIZE+8($sp)
+    .cfi_rel_offset 2, ARG_SLOT_SIZE+8
+    sw       $v1, ARG_SLOT_SIZE+12($sp)
+    .cfi_rel_offset 3, ARG_SLOT_SIZE+12
     s.d      $f0, ARG_SLOT_SIZE($sp)
-    s.d      $f0, 16($sp)   # pass fpr result
-    move     $a2, $v0       # pass gpr result
-    move     $a3, $v1
-    addiu    $a1, $sp, ARG_SLOT_SIZE+16   # pass $sp (remove arg slots and temp storage)
+    addiu    $a3, $sp, ARG_SLOT_SIZE      # Pass fpr_res pointer.
+    addiu    $a2, $sp, ARG_SLOT_SIZE+8    # Pass gpr_res pointer.
+    addiu    $a1, $sp, ARG_SLOT_SIZE+16   # Pass $sp (remove arg slots and temp storage).
     la       $t9, artInstrumentationMethodExitFromCode
-    jalr     $t9            # (Thread*, SP, gpr_res, fpr_res)
-    move     $a0, rSELF     # pass Thread::Current
-    move     $t9, $v0       # set aside returned link register
-    move     $ra, $v1       # set link register for deoptimization
-    lw       $v0, ARG_SLOT_SIZE+12($sp)   # restore return values
-    lw       $v1, ARG_SLOT_SIZE+8($sp)
+    jalr     $t9                          # (Thread*, SP, gpr_res*, fpr_res*)
+    move     $a0, rSELF                   # Pass Thread::Current.
+    move     $t9, $v0                     # Set aside returned link register.
+    move     $ra, $v1                     # Set link register for deoptimization.
+    lw       $v0, ARG_SLOT_SIZE+8($sp)    # Restore return values.
+    lw       $v1, ARG_SLOT_SIZE+12($sp)
     l.d      $f0, ARG_SLOT_SIZE($sp)
-    jalr     $zero, $t9     # return
-    addiu    $sp, $sp, ARG_SLOT_SIZE+FRAME_SIZE_SAVE_REFS_ONLY+16  # restore stack
-    .cfi_adjust_cfa_offset -(ARG_SLOT_SIZE+FRAME_SIZE_SAVE_REFS_ONLY+16)
+    addiu    $sp, $sp, 16
+    .cfi_adjust_cfa_offset -16
+    RESTORE_SAVE_REFS_ONLY_FRAME
+    beqz     $t9, .Ldo_deliver_instrumentation_exception
+    nop                     # Deliver exception if we got nullptr as function.
+    jalr     $zero, $t9     # Otherwise, return.
+    nop
+.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_exit
 
     /*
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index c9eeb7c..10074fd 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -1930,16 +1930,15 @@
     .extern artInstrumentationMethodExitFromCode
 ENTRY art_quick_instrumentation_entry
     SETUP_SAVE_REFS_AND_ARGS_FRAME
-    daddiu   $sp, $sp, -16     # space for saving arg0
-    .cfi_adjust_cfa_offset 16
-    sd       $a0, 0($sp)       # save arg0
-    move     $a3, $ra          # pass $ra
-    jal      artInstrumentationMethodEntryFromCode  # (Method*, Object*, Thread*, RA)
+    # Preserve $a0 knowing there is a spare slot in kSaveRefsAndArgs.
+    sd       $a0, 8($sp)       # Save arg0.
+    move     $a3, $sp          # Pass $sp.
+    jal      artInstrumentationMethodEntryFromCode  # (Method*, Object*, Thread*, SP)
     move     $a2, rSELF        # pass Thread::Current
+    beqzc    $v0, .Ldeliver_instrumentation_entry_exception
+                               # Deliver exception if we got nullptr as function.
     move     $t9, $v0          # $t9 holds reference to code
-    ld       $a0, 0($sp)       # restore arg0
-    daddiu   $sp, $sp, 16      # remove args
-    .cfi_adjust_cfa_offset -16
+    ld       $a0, 8($sp)       # Restore arg0.
     RESTORE_SAVE_REFS_AND_ARGS_FRAME
     jalr     $t9               # call method
     nop
@@ -1951,28 +1950,34 @@
     SETUP_GP
     move     $ra, $zero        # link register is to here, so clobber with 0 for later checks
     SETUP_SAVE_REFS_ONLY_FRAME
-    move     $t0, $sp          # remember bottom of caller's frame
     daddiu   $sp, $sp, -16     # save return values and set up args
     .cfi_adjust_cfa_offset 16
     sd       $v0, 0($sp)
     .cfi_rel_offset 2, 0
     s.d      $f0, 8($sp)
-    mov.d    $f15, $f0         # pass fpr result
-    move     $a2, $v0          # pass gpr result
-    move     $a1, $t0          # pass $sp
+    daddiu   $a3, $sp, 8       # Pass fpr_res pointer.
+    move     $a2, $sp          # Pass gpr_res pointer.
+    daddiu   $a1, $sp, 16      # Pass $sp.
+    jal      artInstrumentationMethodExitFromCode  # (Thread*, SP, gpr_res*, fpr_res*)
     move     $a0, rSELF        # pass Thread::Current
-    jal      artInstrumentationMethodExitFromCode  # (Thread*, SP, gpr_res, fpr_res)
-    .cpreturn                  # Restore gp from t8 in branch delay slot. gp is not used anymore,
-                               # and t8 may be clobbered in artInstrumentationMethodExitFromCode.
 
     move     $t9, $v0          # set aside returned link register
     move     $ra, $v1          # set link register for deoptimization
     ld       $v0, 0($sp)       # restore return values
     l.d      $f0, 8($sp)
-    jalr     $zero, $t9        # return
-    # restore stack, 16 bytes of saved values + ref_only callee save frame
-    daddiu   $sp, $sp, 16+FRAME_SIZE_SAVE_REFS_ONLY
-    .cfi_adjust_cfa_offset -(16+FRAME_SIZE_SAVE_REFS_ONLY)
+    daddiu   $sp, $sp, 16
+    .cfi_adjust_cfa_offset -16
+    RESTORE_SAVE_REFS_ONLY_FRAME
+    beqz     $t9, .Ldo_deliver_instrumentation_exception
+    nop                        # Deliver exception if we got nullptr as function.
+    jalr     $zero, $t9        # Otherwise, return.
+    nop
+.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_exit
 
     /*