1/* 2 * We've detected a condition that will result in an exception, but the exception 3 * has not yet been thrown. Just bail out to the reference interpreter to deal with it. 4 * TUNING: for consistency, we may want to just go ahead and handle these here. 5 */ 6 7 .extern MterpLogDivideByZeroException 8common_errDivideByZero: 9 EXPORT_PC 10#if MTERP_LOGGING 11 move a0, rSELF 12 daddu a1, rFP, OFF_FP_SHADOWFRAME 13 jal MterpLogDivideByZeroException 14#endif 15 b MterpCommonFallback 16 17 .extern MterpLogArrayIndexException 18common_errArrayIndex: 19 EXPORT_PC 20#if MTERP_LOGGING 21 move a0, rSELF 22 daddu a1, rFP, OFF_FP_SHADOWFRAME 23 jal MterpLogArrayIndexException 24#endif 25 b MterpCommonFallback 26 27 .extern MterpLogNullObjectException 28common_errNullObject: 29 EXPORT_PC 30#if MTERP_LOGGING 31 move a0, rSELF 32 daddu a1, rFP, OFF_FP_SHADOWFRAME 33 jal MterpLogNullObjectException 34#endif 35 b MterpCommonFallback 36 37/* 38 * If we're here, something is out of the ordinary. If there is a pending 39 * exception, handle it. Otherwise, roll back and retry with the reference 40 * interpreter. 41 */ 42MterpPossibleException: 43 ld a0, THREAD_EXCEPTION_OFFSET(rSELF) 44 beqzc a0, MterpFallback # If not, fall back to reference interpreter. 45 /* intentional fallthrough - handle pending exception. */ 46/* 47 * On return from a runtime helper routine, we've found a pending exception. 48 * Can we handle it here - or need to bail out to caller? 49 * 50 */ 51 .extern MterpHandleException 52 .extern MterpShouldSwitchInterpreters 53MterpException: 54 move a0, rSELF 55 daddu a1, rFP, OFF_FP_SHADOWFRAME 56 jal MterpHandleException # (self, shadow_frame) 57 beqzc v0, MterpExceptionReturn # no local catch, back to caller. 58 ld a0, OFF_FP_CODE_ITEM(rFP) 59 lwu a1, OFF_FP_DEX_PC(rFP) 60 REFRESH_IBASE 61 daddu rPC, a0, CODEITEM_INSNS_OFFSET 62 dlsa rPC, a1, rPC, 1 # generate new dex_pc_ptr 63 /* Do we need to switch interpreters? */ 64 jal MterpShouldSwitchInterpreters 65 bnezc v0, MterpFallback 66 /* resume execution at catch block */ 67 EXPORT_PC 68 FETCH_INST 69 GET_INST_OPCODE v0 70 GOTO_OPCODE v0 71 /* NOTE: no fallthrough */ 72 73/* 74 * Check for suspend check request. Assumes rINST already loaded, rPC advanced and 75 * still needs to get the opcode and branch to it, and flags are in ra. 76 */ 77 .extern MterpSuspendCheck 78MterpCheckSuspendAndContinue: 79 REFRESH_IBASE 80 and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) 81 bnez ra, check1 82 GET_INST_OPCODE v0 # extract opcode from rINST 83 GOTO_OPCODE v0 # jump to next instruction 84check1: 85 EXPORT_PC 86 move a0, rSELF 87 jal MterpSuspendCheck # (self) 88 bnezc v0, MterpFallback # Something in the environment changed, switch interpreters 89 GET_INST_OPCODE v0 # extract opcode from rINST 90 GOTO_OPCODE v0 # jump to next instruction 91 92/* 93 * On-stack replacement has happened, and now we've returned from the compiled method. 94 */ 95MterpOnStackReplacement: 96#if MTERP_LOGGING 97 move a0, rSELF 98 daddu a1, rFP, OFF_FP_SHADOWFRAME 99 move a2, rINST # rINST contains offset 100 jal MterpLogOSR 101#endif 102 li v0, 1 # Signal normal return 103 b MterpDone 104 105/* 106 * Bail out to reference interpreter. 107 */ 108 .extern MterpLogFallback 109MterpFallback: 110 EXPORT_PC 111#if MTERP_LOGGING 112 move a0, rSELF 113 daddu a1, rFP, OFF_FP_SHADOWFRAME 114 jal MterpLogFallback 115#endif 116MterpCommonFallback: 117 li v0, 0 # signal retry with reference interpreter. 118 b MterpDone 119 120/* 121 * We pushed some registers on the stack in ExecuteMterpImpl, then saved 122 * SP and RA. Here we restore SP, restore the registers, and then restore 123 * RA to PC. 124 * 125 * On entry: 126 * uint32_t* rFP (should still be live, pointer to base of vregs) 127 */ 128MterpExceptionReturn: 129 li v0, 1 # signal return to caller. 130 b MterpDone 131/* 132 * Returned value is expected in a0 and if it's not 64-bit, the 32 most 133 * significant bits of a0 must be 0. 134 */ 135MterpReturn: 136 ld a2, OFF_FP_RESULT_REGISTER(rFP) 137 lw ra, THREAD_FLAGS_OFFSET(rSELF) 138 sd a0, 0(a2) 139 move a0, rSELF 140 and ra, ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) 141 beqzc ra, check2 142 jal MterpSuspendCheck # (self) 143check2: 144 li v0, 1 # signal return to caller. 145MterpDone: 146 ld s5, STACK_OFFSET_S5(sp) 147 .cfi_restore 21 148 ld s4, STACK_OFFSET_S4(sp) 149 .cfi_restore 20 150 ld s3, STACK_OFFSET_S3(sp) 151 .cfi_restore 19 152 ld s2, STACK_OFFSET_S2(sp) 153 .cfi_restore 18 154 ld s1, STACK_OFFSET_S1(sp) 155 .cfi_restore 17 156 ld s0, STACK_OFFSET_S0(sp) 157 .cfi_restore 16 158 159 ld ra, STACK_OFFSET_RA(sp) 160 .cfi_restore 31 161 162 ld t8, STACK_OFFSET_GP(sp) 163 .cpreturn 164 .cfi_restore 28 165 166 .set noreorder 167 jr ra 168 daddu sp, sp, STACK_SIZE 169 .cfi_adjust_cfa_offset -STACK_SIZE 170 171 .cfi_endproc 172 .size ExecuteMterpImpl, .-ExecuteMterpImpl 173