1/* 2 * =========================================================================== 3 * Common subroutines and data 4 * =========================================================================== 5 */ 6 7 .text 8 .align 2 9 10/* 11 * We've detected a condition that will result in an exception, but the exception 12 * has not yet been thrown. Just bail out to the reference interpreter to deal with it. 13 * TUNING: for consistency, we may want to just go ahead and handle these here. 14 */ 15common_errDivideByZero: 16 EXPORT_PC 17#if MTERP_LOGGING 18 mov r0, rSELF 19 add r1, rFP, #OFF_FP_SHADOWFRAME 20 bl MterpLogDivideByZeroException 21#endif 22 b MterpCommonFallback 23 24common_errArrayIndex: 25 EXPORT_PC 26#if MTERP_LOGGING 27 mov r0, rSELF 28 add r1, rFP, #OFF_FP_SHADOWFRAME 29 bl MterpLogArrayIndexException 30#endif 31 b MterpCommonFallback 32 33common_errNegativeArraySize: 34 EXPORT_PC 35#if MTERP_LOGGING 36 mov r0, rSELF 37 add r1, rFP, #OFF_FP_SHADOWFRAME 38 bl MterpLogNegativeArraySizeException 39#endif 40 b MterpCommonFallback 41 42common_errNoSuchMethod: 43 EXPORT_PC 44#if MTERP_LOGGING 45 mov r0, rSELF 46 add r1, rFP, #OFF_FP_SHADOWFRAME 47 bl MterpLogNoSuchMethodException 48#endif 49 b MterpCommonFallback 50 51common_errNullObject: 52 EXPORT_PC 53#if MTERP_LOGGING 54 mov r0, rSELF 55 add r1, rFP, #OFF_FP_SHADOWFRAME 56 bl MterpLogNullObjectException 57#endif 58 b MterpCommonFallback 59 60common_exceptionThrown: 61 EXPORT_PC 62#if MTERP_LOGGING 63 mov r0, rSELF 64 add r1, rFP, #OFF_FP_SHADOWFRAME 65 bl MterpLogExceptionThrownException 66#endif 67 b MterpCommonFallback 68 69MterpSuspendFallback: 70 EXPORT_PC 71#if MTERP_LOGGING 72 mov r0, rSELF 73 add r1, rFP, #OFF_FP_SHADOWFRAME 74 ldr r2, [rSELF, #THREAD_FLAGS_OFFSET] 75 bl MterpLogSuspendFallback 76#endif 77 b MterpCommonFallback 78 79/* 80 * If we're here, something is out of the ordinary. If there is a pending 81 * exception, handle it. Otherwise, roll back and retry with the reference 82 * interpreter. 83 */ 84MterpPossibleException: 85 ldr r0, [rSELF, #THREAD_EXCEPTION_OFFSET] 86 cmp r0, #0 @ Exception pending? 87 beq MterpFallback @ If not, fall back to reference interpreter. 88 /* intentional fallthrough - handle pending exception. */ 89/* 90 * On return from a runtime helper routine, we've found a pending exception. 91 * Can we handle it here - or need to bail out to caller? 92 * 93 */ 94MterpException: 95 mov r0, rSELF 96 add r1, rFP, #OFF_FP_SHADOWFRAME 97 bl MterpHandleException @ (self, shadow_frame) 98 cmp r0, #0 99 beq MterpExceptionReturn @ no local catch, back to caller. 100 ldr r0, [rFP, #OFF_FP_DEX_INSTRUCTIONS] 101 ldr r1, [rFP, #OFF_FP_DEX_PC] 102 ldr rIBASE, [rSELF, #THREAD_CURRENT_IBASE_OFFSET] 103 add rPC, r0, r1, lsl #1 @ generate new dex_pc_ptr 104 /* Do we need to switch interpreters? */ 105 bl MterpShouldSwitchInterpreters 106 cmp r0, #0 107 bne MterpFallback 108 /* resume execution at catch block */ 109 EXPORT_PC 110 FETCH_INST 111 GET_INST_OPCODE ip 112 GOTO_OPCODE ip 113 /* NOTE: no fallthrough */ 114 115/* 116 * Common handling for branches with support for Jit profiling. 117 * On entry: 118 * rINST <= signed offset 119 * rPROFILE <= signed hotness countdown (expanded to 32 bits) 120 * condition bits <= set to establish sign of offset (use "NoFlags" entry if not) 121 * 122 * We have quite a few different cases for branch profiling, OSR detection and 123 * suspend check support here. 124 * 125 * Taken backward branches: 126 * If profiling active, do hotness countdown and report if we hit zero. 127 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 128 * Is there a pending suspend request? If so, suspend. 129 * 130 * Taken forward branches and not-taken backward branches: 131 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 132 * 133 * Our most common case is expected to be a taken backward branch with active jit profiling, 134 * but no full OSR check and no pending suspend request. 135 * Next most common case is not-taken branch with no full OSR check. 136 * 137 */ 138MterpCommonTakenBranchNoFlags: 139 cmp rINST, #0 140MterpCommonTakenBranch: 141 bgt .L_forward_branch @ don't add forward branches to hotness 142/* 143 * We need to subtract 1 from positive values and we should not see 0 here, 144 * so we may use the result of the comparison with -1. 145 */ 146#if JIT_CHECK_OSR != -1 147# error "JIT_CHECK_OSR must be -1." 148#endif 149 cmp rPROFILE, #JIT_CHECK_OSR 150 beq .L_osr_check 151 subgts rPROFILE, #1 152 beq .L_add_batch @ counted down to zero - report 153.L_resume_backward_branch: 154 ldr lr, [rSELF, #THREAD_FLAGS_OFFSET] 155 REFRESH_IBASE 156 add r2, rINST, rINST @ r2<- byte offset 157 FETCH_ADVANCE_INST_RB r2 @ update rPC, load rINST 158 ands lr, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST 159 bne .L_suspend_request_pending 160 GET_INST_OPCODE ip @ extract opcode from rINST 161 GOTO_OPCODE ip @ jump to next instruction 162 163.L_suspend_request_pending: 164 EXPORT_PC 165 mov r0, rSELF 166 bl MterpSuspendCheck @ (self) 167 cmp r0, #0 168 bne MterpFallback 169 REFRESH_IBASE @ might have changed during suspend 170 GET_INST_OPCODE ip @ extract opcode from rINST 171 GOTO_OPCODE ip @ jump to next instruction 172 173.L_no_count_backwards: 174 cmp rPROFILE, #JIT_CHECK_OSR @ possible OSR re-entry? 175 bne .L_resume_backward_branch 176.L_osr_check: 177 mov r0, rSELF 178 add r1, rFP, #OFF_FP_SHADOWFRAME 179 mov r2, rINST 180 EXPORT_PC 181 bl MterpMaybeDoOnStackReplacement @ (self, shadow_frame, offset) 182 cmp r0, #0 183 bne MterpOnStackReplacement 184 b .L_resume_backward_branch 185 186.L_forward_branch: 187 cmp rPROFILE, #JIT_CHECK_OSR @ possible OSR re-entry? 188 beq .L_check_osr_forward 189.L_resume_forward_branch: 190 add r2, rINST, rINST @ r2<- byte offset 191 FETCH_ADVANCE_INST_RB r2 @ update rPC, load rINST 192 GET_INST_OPCODE ip @ extract opcode from rINST 193 GOTO_OPCODE ip @ jump to next instruction 194 195.L_check_osr_forward: 196 mov r0, rSELF 197 add r1, rFP, #OFF_FP_SHADOWFRAME 198 mov r2, rINST 199 EXPORT_PC 200 bl MterpMaybeDoOnStackReplacement @ (self, shadow_frame, offset) 201 cmp r0, #0 202 bne MterpOnStackReplacement 203 b .L_resume_forward_branch 204 205.L_add_batch: 206 add r1, rFP, #OFF_FP_SHADOWFRAME 207 strh rPROFILE, [r1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET] 208 ldr r0, [rFP, #OFF_FP_METHOD] 209 mov r2, rSELF 210 bl MterpAddHotnessBatch @ (method, shadow_frame, self) 211 mov rPROFILE, r0 @ restore new hotness countdown to rPROFILE 212 b .L_no_count_backwards 213 214/* 215 * Entered from the conditional branch handlers when OSR check request active on 216 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 217 */ 218.L_check_not_taken_osr: 219 mov r0, rSELF 220 add r1, rFP, #OFF_FP_SHADOWFRAME 221 mov r2, #2 222 EXPORT_PC 223 bl MterpMaybeDoOnStackReplacement @ (self, shadow_frame, offset) 224 cmp r0, #0 225 bne MterpOnStackReplacement 226 FETCH_ADVANCE_INST 2 227 GET_INST_OPCODE ip @ extract opcode from rINST 228 GOTO_OPCODE ip @ jump to next instruction 229 230/* 231 * On-stack replacement has happened, and now we've returned from the compiled method. 232 */ 233MterpOnStackReplacement: 234#if MTERP_LOGGING 235 mov r0, rSELF 236 add r1, rFP, #OFF_FP_SHADOWFRAME 237 mov r2, rINST 238 bl MterpLogOSR 239#endif 240 mov r0, #1 @ Signal normal return 241 b MterpDone 242 243/* 244 * Bail out to reference interpreter. 245 */ 246MterpFallback: 247 EXPORT_PC 248#if MTERP_LOGGING 249 mov r0, rSELF 250 add r1, rFP, #OFF_FP_SHADOWFRAME 251 bl MterpLogFallback 252#endif 253MterpCommonFallback: 254 mov r0, #0 @ signal retry with reference interpreter. 255 b MterpDone 256 257/* 258 * We pushed some registers on the stack in ExecuteMterpImpl, then saved 259 * SP and LR. Here we restore SP, restore the registers, and then restore 260 * LR to PC. 261 * 262 * On entry: 263 * uint32_t* rFP (should still be live, pointer to base of vregs) 264 */ 265MterpExceptionReturn: 266 mov r0, #1 @ signal return to caller. 267 b MterpDone 268MterpReturn: 269 ldr r2, [rFP, #OFF_FP_RESULT_REGISTER] 270 str r0, [r2] 271 str r1, [r2, #4] 272 mov r0, #1 @ signal return to caller. 273MterpDone: 274/* 275 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're 276 * checking for OSR. If greater than zero, we might have unreported hotness to register 277 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE 278 * should only reach zero immediately after a hotness decrement, and is then reset to either 279 * a negative special state or the new non-zero countdown value. 280 */ 281 cmp rPROFILE, #0 282 bgt MterpProfileActive @ if > 0, we may have some counts to report. 283 ldmfd sp!, {r3-r10,fp,pc} @ restore 10 regs and return 284 285MterpProfileActive: 286 mov rINST, r0 @ stash return value 287 /* Report cached hotness counts */ 288 ldr r0, [rFP, #OFF_FP_METHOD] 289 add r1, rFP, #OFF_FP_SHADOWFRAME 290 mov r2, rSELF 291 strh rPROFILE, [r1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET] 292 bl MterpAddHotnessBatch @ (method, shadow_frame, self) 293 mov r0, rINST @ restore return value 294 ldmfd sp!, {r3-r10,fp,pc} @ restore 10 regs and return 295 296 END ExecuteMterpImpl 297 298