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_CODE_ITEM] 101 ldr r1, [rFP, #OFF_FP_DEX_PC] 102 ldr rIBASE, [rSELF, #THREAD_CURRENT_IBASE_OFFSET] 103 add rPC, r0, #CODEITEM_INSNS_OFFSET 104 add rPC, rPC, r1, lsl #1 @ generate new dex_pc_ptr 105 /* Do we need to switch interpreters? */ 106 bl MterpShouldSwitchInterpreters 107 cmp r0, #0 108 bne MterpFallback 109 /* resume execution at catch block */ 110 EXPORT_PC 111 FETCH_INST 112 GET_INST_OPCODE ip 113 GOTO_OPCODE ip 114 /* NOTE: no fallthrough */ 115 116/* 117 * Common handling for branches with support for Jit profiling. 118 * On entry: 119 * rINST <= signed offset 120 * rPROFILE <= signed hotness countdown (expanded to 32 bits) 121 * condition bits <= set to establish sign of offset (use "NoFlags" entry if not) 122 * 123 * We have quite a few different cases for branch profiling, OSR detection and 124 * suspend check support here. 125 * 126 * Taken backward branches: 127 * If profiling active, do hotness countdown and report if we hit zero. 128 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 129 * Is there a pending suspend request? If so, suspend. 130 * 131 * Taken forward branches and not-taken backward branches: 132 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 133 * 134 * Our most common case is expected to be a taken backward branch with active jit profiling, 135 * but no full OSR check and no pending suspend request. 136 * Next most common case is not-taken branch with no full OSR check. 137 * 138 */ 139MterpCommonTakenBranchNoFlags: 140 cmp rINST, #0 141MterpCommonTakenBranch: 142 bgt .L_forward_branch @ don't add forward branches to hotness 143/* 144 * We need to subtract 1 from positive values and we should not see 0 here, 145 * so we may use the result of the comparison with -1. 146 */ 147#if JIT_CHECK_OSR != -1 148# error "JIT_CHECK_OSR must be -1." 149#endif 150 cmp rPROFILE, #JIT_CHECK_OSR 151 beq .L_osr_check 152 subgts rPROFILE, #1 153 beq .L_add_batch @ counted down to zero - report 154.L_resume_backward_branch: 155 ldr lr, [rSELF, #THREAD_FLAGS_OFFSET] 156 REFRESH_IBASE 157 add r2, rINST, rINST @ r2<- byte offset 158 FETCH_ADVANCE_INST_RB r2 @ update rPC, load rINST 159 ands lr, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST 160 bne .L_suspend_request_pending 161 GET_INST_OPCODE ip @ extract opcode from rINST 162 GOTO_OPCODE ip @ jump to next instruction 163 164.L_suspend_request_pending: 165 EXPORT_PC 166 mov r0, rSELF 167 bl MterpSuspendCheck @ (self) 168 cmp r0, #0 169 bne MterpFallback 170 REFRESH_IBASE @ might have changed during suspend 171 GET_INST_OPCODE ip @ extract opcode from rINST 172 GOTO_OPCODE ip @ jump to next instruction 173 174.L_no_count_backwards: 175 cmp rPROFILE, #JIT_CHECK_OSR @ possible OSR re-entry? 176 bne .L_resume_backward_branch 177.L_osr_check: 178 mov r0, rSELF 179 add r1, rFP, #OFF_FP_SHADOWFRAME 180 mov r2, rINST 181 EXPORT_PC 182 bl MterpMaybeDoOnStackReplacement @ (self, shadow_frame, offset) 183 cmp r0, #0 184 bne MterpOnStackReplacement 185 b .L_resume_backward_branch 186 187.L_forward_branch: 188 cmp rPROFILE, #JIT_CHECK_OSR @ possible OSR re-entry? 189 beq .L_check_osr_forward 190.L_resume_forward_branch: 191 add r2, rINST, rINST @ r2<- byte offset 192 FETCH_ADVANCE_INST_RB r2 @ update rPC, load rINST 193 GET_INST_OPCODE ip @ extract opcode from rINST 194 GOTO_OPCODE ip @ jump to next instruction 195 196.L_check_osr_forward: 197 mov r0, rSELF 198 add r1, rFP, #OFF_FP_SHADOWFRAME 199 mov r2, rINST 200 EXPORT_PC 201 bl MterpMaybeDoOnStackReplacement @ (self, shadow_frame, offset) 202 cmp r0, #0 203 bne MterpOnStackReplacement 204 b .L_resume_forward_branch 205 206.L_add_batch: 207 add r1, rFP, #OFF_FP_SHADOWFRAME 208 strh rPROFILE, [r1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET] 209 ldr r0, [rFP, #OFF_FP_METHOD] 210 mov r2, rSELF 211 bl MterpAddHotnessBatch @ (method, shadow_frame, self) 212 mov rPROFILE, r0 @ restore new hotness countdown to rPROFILE 213 b .L_no_count_backwards 214 215/* 216 * Entered from the conditional branch handlers when OSR check request active on 217 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 218 */ 219.L_check_not_taken_osr: 220 mov r0, rSELF 221 add r1, rFP, #OFF_FP_SHADOWFRAME 222 mov r2, #2 223 EXPORT_PC 224 bl MterpMaybeDoOnStackReplacement @ (self, shadow_frame, offset) 225 cmp r0, #0 226 bne MterpOnStackReplacement 227 FETCH_ADVANCE_INST 2 228 GET_INST_OPCODE ip @ extract opcode from rINST 229 GOTO_OPCODE ip @ jump to next instruction 230 231/* 232 * On-stack replacement has happened, and now we've returned from the compiled method. 233 */ 234MterpOnStackReplacement: 235#if MTERP_LOGGING 236 mov r0, rSELF 237 add r1, rFP, #OFF_FP_SHADOWFRAME 238 mov r2, rINST 239 bl MterpLogOSR 240#endif 241 mov r0, #1 @ Signal normal return 242 b MterpDone 243 244/* 245 * Bail out to reference interpreter. 246 */ 247MterpFallback: 248 EXPORT_PC 249#if MTERP_LOGGING 250 mov r0, rSELF 251 add r1, rFP, #OFF_FP_SHADOWFRAME 252 bl MterpLogFallback 253#endif 254MterpCommonFallback: 255 mov r0, #0 @ signal retry with reference interpreter. 256 b MterpDone 257 258/* 259 * We pushed some registers on the stack in ExecuteMterpImpl, then saved 260 * SP and LR. Here we restore SP, restore the registers, and then restore 261 * LR to PC. 262 * 263 * On entry: 264 * uint32_t* rFP (should still be live, pointer to base of vregs) 265 */ 266MterpExceptionReturn: 267 mov r0, #1 @ signal return to caller. 268 b MterpDone 269MterpReturn: 270 ldr r2, [rFP, #OFF_FP_RESULT_REGISTER] 271 str r0, [r2] 272 str r1, [r2, #4] 273 mov r0, #1 @ signal return to caller. 274MterpDone: 275/* 276 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're 277 * checking for OSR. If greater than zero, we might have unreported hotness to register 278 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE 279 * should only reach zero immediately after a hotness decrement, and is then reset to either 280 * a negative special state or the new non-zero countdown value. 281 */ 282 cmp rPROFILE, #0 283 bgt MterpProfileActive @ if > 0, we may have some counts to report. 284 ldmfd sp!, {r3-r10,fp,pc} @ restore 10 regs and return 285 286MterpProfileActive: 287 mov rINST, r0 @ stash return value 288 /* Report cached hotness counts */ 289 ldr r0, [rFP, #OFF_FP_METHOD] 290 add r1, rFP, #OFF_FP_SHADOWFRAME 291 mov r2, rSELF 292 strh rPROFILE, [r1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET] 293 bl MterpAddHotnessBatch @ (method, shadow_frame, self) 294 mov r0, rINST @ restore return value 295 ldmfd sp!, {r3-r10,fp,pc} @ restore 10 regs and return 296 297 END ExecuteMterpImpl 298 299