MIPS: Follow-up to "Allow deoptimization when returning from a runtime method"

This is a MIPS-specific follow-up to
https://android-review.googlesource.com/442545.

Test: booted MIPS64 (with 2nd arch MIPS32R6) in QEMU
Test: testrunner.py --target --optimizing
Test: same tests as above on CI20
Test: booted MIPS32R2 in QEMU

Bug: 33616143

Change-Id: I3478f1ac332b0b97578225fd55ac0fccdfa4e33f
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index b876353..74e0a7a 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -2317,58 +2317,50 @@
     .extern artInstrumentationMethodExitFromCode
 ENTRY art_quick_instrumentation_entry
     SETUP_SAVE_REFS_AND_ARGS_FRAME
-    sw       $a0, 28($sp)   # save arg0 in free arg slot
-    addiu    $a3, $sp, ARG_SLOT_SIZE      # Pass $sp.
-    la       $t9, artInstrumentationMethodEntryFromCode
-    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
+    sw      $a0, 28($sp)    # save arg0 in free arg slot
+    addiu   $a3, $sp, ARG_SLOT_SIZE     # Pass $sp.
+    la      $t9, artInstrumentationMethodEntryFromCode
+    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
-    jalr     $t9            # call method
-    nop
-END art_quick_instrumentation_entry
-    /* intentional fallthrough */
-    .global art_quick_instrumentation_exit
-art_quick_instrumentation_exit:
-    .cfi_startproc
-    addiu    $t9, $ra, 4    # put current address into $t9 to rebuild $gp
-    .cpload  $t9
-    move     $ra, $zero     # link register is to here, so clobber with 0 for later checks
-
-    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+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)
-    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+8($sp)    # Restore return values.
-    lw       $v1, ARG_SLOT_SIZE+12($sp)
-    l.d      $f0, ARG_SLOT_SIZE($sp)
-    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.
+    la      $ra, art_quick_instrumentation_exit
+    jalr    $zero, $t9      # call method, returning to art_quick_instrumentation_exit
     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_entry
+
+ENTRY_NO_GP art_quick_instrumentation_exit
+    move    $ra, $zero      # RA points here, so clobber with 0 for later checks.
+    SETUP_SAVE_EVERYTHING_FRAME  # Allocates ARG_SLOT_SIZE bytes at the bottom of the stack.
+    move    $s2, $gp             # Preserve $gp across the call for exception delivery.
+
+    addiu   $a3, $sp, ARG_SLOT_SIZE+16  # Pass fpr_res pointer ($f0 in SAVE_EVERYTHING_FRAME).
+    addiu   $a2, $sp, ARG_SLOT_SIZE+148 # Pass gpr_res pointer ($v0 in SAVE_EVERYTHING_FRAME).
+    addiu   $a1, $sp, ARG_SLOT_SIZE     # Pass $sp.
+    la      $t9, artInstrumentationMethodExitFromCode
+    jalr    $t9                         # (Thread*, SP, gpr_res*, fpr_res*)
+    move    $a0, rSELF                  # Pass Thread::Current.
+
+    beqz    $v0, .Ldo_deliver_instrumentation_exception
+    move    $gp, $s2        # Deliver exception if we got nullptr as function.
+    bnez    $v1, .Ldeoptimize
+
+    # Normal return.
+    sw      $v0, (ARG_SLOT_SIZE+FRAME_SIZE_SAVE_EVERYTHING-4)($sp)  # Set return pc.
+    RESTORE_SAVE_EVERYTHING_FRAME
+    jalr    $zero, $ra
+    nop
+.Ldo_deliver_instrumentation_exception:
+    DELIVER_PENDING_EXCEPTION_FRAME_READY
+.Ldeoptimize:
+    b       art_quick_deoptimize
+    sw      $v1, (ARG_SLOT_SIZE+FRAME_SIZE_SAVE_EVERYTHING-4)($sp)
+                            # Fake a call from instrumentation return pc.
 END art_quick_instrumentation_exit
 
     /*
@@ -2376,11 +2368,41 @@
      * will long jump to the upcall with a special exception of -1.
      */
     .extern artDeoptimize
-ENTRY art_quick_deoptimize
-    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
-    la       $t9, artDeoptimize
-    jalr     $t9            # (Thread*)
-    move     $a0, rSELF     # pass Thread::current
+ENTRY_NO_GP_CUSTOM_CFA art_quick_deoptimize, ARG_SLOT_SIZE+FRAME_SIZE_SAVE_EVERYTHING
+    # SETUP_SAVE_EVERYTHING_FRAME has been done by art_quick_instrumentation_exit.
+    .cfi_rel_offset 31, ARG_SLOT_SIZE+252
+    .cfi_rel_offset 30, ARG_SLOT_SIZE+248
+    .cfi_rel_offset 28, ARG_SLOT_SIZE+244
+    .cfi_rel_offset 25, ARG_SLOT_SIZE+240
+    .cfi_rel_offset 24, ARG_SLOT_SIZE+236
+    .cfi_rel_offset 23, ARG_SLOT_SIZE+232
+    .cfi_rel_offset 22, ARG_SLOT_SIZE+228
+    .cfi_rel_offset 21, ARG_SLOT_SIZE+224
+    .cfi_rel_offset 20, ARG_SLOT_SIZE+220
+    .cfi_rel_offset 19, ARG_SLOT_SIZE+216
+    .cfi_rel_offset 18, ARG_SLOT_SIZE+212
+    .cfi_rel_offset 17, ARG_SLOT_SIZE+208
+    .cfi_rel_offset 16, ARG_SLOT_SIZE+204
+    .cfi_rel_offset 15, ARG_SLOT_SIZE+200
+    .cfi_rel_offset 14, ARG_SLOT_SIZE+196
+    .cfi_rel_offset 13, ARG_SLOT_SIZE+192
+    .cfi_rel_offset 12, ARG_SLOT_SIZE+188
+    .cfi_rel_offset 11, ARG_SLOT_SIZE+184
+    .cfi_rel_offset 10, ARG_SLOT_SIZE+180
+    .cfi_rel_offset 9, ARG_SLOT_SIZE+176
+    .cfi_rel_offset 8, ARG_SLOT_SIZE+172
+    .cfi_rel_offset 7, ARG_SLOT_SIZE+168
+    .cfi_rel_offset 6, ARG_SLOT_SIZE+164
+    .cfi_rel_offset 5, ARG_SLOT_SIZE+160
+    .cfi_rel_offset 4, ARG_SLOT_SIZE+156
+    .cfi_rel_offset 3, ARG_SLOT_SIZE+152
+    .cfi_rel_offset 2, ARG_SLOT_SIZE+148
+    .cfi_rel_offset 1, ARG_SLOT_SIZE+144
+
+    la      $t9, artDeoptimize
+    jalr    $t9             # (Thread*)
+    move    $a0, rSELF      # pass Thread::current
+    break
 END art_quick_deoptimize
 
     /*
@@ -2388,7 +2410,7 @@
      * will long jump to the upcall with a special exception of -1.
      */
     .extern artDeoptimizeFromCompiledCode
-ENTRY art_quick_deoptimize_from_compiled_code
+ENTRY_NO_GP art_quick_deoptimize_from_compiled_code
     SETUP_SAVE_EVERYTHING_FRAME
     la       $t9, artDeoptimizeFromCompiledCode
     jalr     $t9                            # (DeoptimizationKind, Thread*)
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index eeaae3c..1817502 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -2203,53 +2203,47 @@
 ENTRY art_quick_instrumentation_entry
     SETUP_SAVE_REFS_AND_ARGS_FRAME
     # 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, 8($sp)       # Restore arg0.
+    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, 8($sp)     # Restore arg0.
     RESTORE_SAVE_REFS_AND_ARGS_FRAME
-    jalr     $t9               # call method
-    nop
-END art_quick_instrumentation_entry
-    /* intentional fallthrough */
-    .global art_quick_instrumentation_exit
-art_quick_instrumentation_exit:
-    .cfi_startproc
-    SETUP_GP
-    move     $ra, $zero        # link register is to here, so clobber with 0 for later checks
-    SETUP_SAVE_REFS_ONLY_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)
-    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
-
-    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)
-    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
+    dla     $ra, art_quick_instrumentation_exit
+    jic     $t9, 0          # call method, returning to art_quick_instrumentation_exit
 .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_NO_GP art_quick_instrumentation_exit
+    move    $ra, $zero      # RA points here, so clobber with 0 for later checks.
+    SETUP_SAVE_EVERYTHING_FRAME
+
+    daddiu  $a3, $sp, 16    # Pass fpr_res pointer ($f0 in SAVE_EVERYTHING_FRAME).
+    daddiu  $a2, $sp, 280   # Pass gpr_res pointer ($v0 in SAVE_EVERYTHING_FRAME).
+    move    $a1, $sp        # Pass $sp.
+    jal     artInstrumentationMethodExitFromCode  # (Thread*, SP, gpr_res*, fpr_res*)
+    move    $a0, rSELF      # pass Thread::Current
+
+    beqzc   $v0, .Ldo_deliver_instrumentation_exception
+                            # Deliver exception if we got nullptr as function.
+    nop
+    bnez    $v1, .Ldeoptimize
+
+    # Normal return.
+    sd      $v0, (FRAME_SIZE_SAVE_EVERYTHING-8)($sp)  # Set return pc.
+    RESTORE_SAVE_EVERYTHING_FRAME
+    jic     $ra, 0
+.Ldo_deliver_instrumentation_exception:
+    DELIVER_PENDING_EXCEPTION_FRAME_READY
+.Ldeoptimize:
+    b       art_quick_deoptimize
+    sd      $v1, (FRAME_SIZE_SAVE_EVERYTHING-8)($sp)
+                            # Fake a call from instrumentation return pc.
 END art_quick_instrumentation_exit
 
     /*
@@ -2257,11 +2251,40 @@
      * will long jump to the upcall with a special exception of -1.
      */
     .extern artDeoptimize
-    .extern artEnterInterpreterFromDeoptimize
-ENTRY art_quick_deoptimize
-    SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
-    jal      artDeoptimize     # artDeoptimize(Thread*)
-    move     $a0, rSELF        # pass Thread::current
+ENTRY_NO_GP_CUSTOM_CFA art_quick_deoptimize, FRAME_SIZE_SAVE_EVERYTHING
+    # SETUP_SAVE_EVERYTHING_FRAME has been done by art_quick_instrumentation_exit.
+    .cfi_rel_offset 31, 488
+    .cfi_rel_offset 30, 480
+    .cfi_rel_offset 28, 472
+    .cfi_rel_offset 25, 464
+    .cfi_rel_offset 24, 456
+    .cfi_rel_offset 23, 448
+    .cfi_rel_offset 22, 440
+    .cfi_rel_offset 21, 432
+    .cfi_rel_offset 20, 424
+    .cfi_rel_offset 19, 416
+    .cfi_rel_offset 18, 408
+    .cfi_rel_offset 17, 400
+    .cfi_rel_offset 16, 392
+    .cfi_rel_offset 15, 384
+    .cfi_rel_offset 14, 376
+    .cfi_rel_offset 13, 368
+    .cfi_rel_offset 12, 360
+    .cfi_rel_offset 11, 352
+    .cfi_rel_offset 10, 344
+    .cfi_rel_offset 9, 336
+    .cfi_rel_offset 8, 328
+    .cfi_rel_offset 7, 320
+    .cfi_rel_offset 6, 312
+    .cfi_rel_offset 5, 304
+    .cfi_rel_offset 4, 296
+    .cfi_rel_offset 3, 288
+    .cfi_rel_offset 2, 280
+    .cfi_rel_offset 1, 272
+
+    jal     artDeoptimize   # artDeoptimize(Thread*)
+    move    $a0, rSELF      # pass Thread::current
+    break
 END art_quick_deoptimize
 
     /*