1/* 2 * =========================================================================== 3 * Common subroutines and data 4 * =========================================================================== 5 */ 6 7 8/* 9 * We've detected a condition that will result in an exception, but the exception 10 * has not yet been thrown. Just bail out to the reference interpreter to deal with it. 11 * TUNING: for consistency, we may want to just go ahead and handle these here. 12 */ 13common_errDivideByZero: 14 EXPORT_PC 15#if MTERP_LOGGING 16 mov x0, xSELF 17 add x1, xFP, #OFF_FP_SHADOWFRAME 18 bl MterpLogDivideByZeroException 19#endif 20 b MterpCommonFallback 21 22common_errArrayIndex: 23 EXPORT_PC 24#if MTERP_LOGGING 25 mov x0, xSELF 26 add x1, xFP, #OFF_FP_SHADOWFRAME 27 bl MterpLogArrayIndexException 28#endif 29 b MterpCommonFallback 30 31common_errNegativeArraySize: 32 EXPORT_PC 33#if MTERP_LOGGING 34 mov x0, xSELF 35 add x1, xFP, #OFF_FP_SHADOWFRAME 36 bl MterpLogNegativeArraySizeException 37#endif 38 b MterpCommonFallback 39 40common_errNoSuchMethod: 41 EXPORT_PC 42#if MTERP_LOGGING 43 mov x0, xSELF 44 add x1, xFP, #OFF_FP_SHADOWFRAME 45 bl MterpLogNoSuchMethodException 46#endif 47 b MterpCommonFallback 48 49common_errNullObject: 50 EXPORT_PC 51#if MTERP_LOGGING 52 mov x0, xSELF 53 add x1, xFP, #OFF_FP_SHADOWFRAME 54 bl MterpLogNullObjectException 55#endif 56 b MterpCommonFallback 57 58common_exceptionThrown: 59 EXPORT_PC 60#if MTERP_LOGGING 61 mov x0, xSELF 62 add x1, xFP, #OFF_FP_SHADOWFRAME 63 bl MterpLogExceptionThrownException 64#endif 65 b MterpCommonFallback 66 67MterpSuspendFallback: 68 EXPORT_PC 69#if MTERP_LOGGING 70 mov x0, xSELF 71 add x1, xFP, #OFF_FP_SHADOWFRAME 72 ldr x2, [xSELF, #THREAD_FLAGS_OFFSET] 73 bl MterpLogSuspendFallback 74#endif 75 b MterpCommonFallback 76 77/* 78 * If we're here, something is out of the ordinary. If there is a pending 79 * exception, handle it. Otherwise, roll back and retry with the reference 80 * interpreter. 81 */ 82MterpPossibleException: 83 ldr x0, [xSELF, #THREAD_EXCEPTION_OFFSET] 84 cbz x0, MterpFallback // If not, fall back to reference interpreter. 85 /* intentional fallthrough - handle pending exception. */ 86/* 87 * On return from a runtime helper routine, we've found a pending exception. 88 * Can we handle it here - or need to bail out to caller? 89 * 90 */ 91MterpException: 92 mov x0, xSELF 93 add x1, xFP, #OFF_FP_SHADOWFRAME 94 bl MterpHandleException // (self, shadow_frame) 95 cbz w0, MterpExceptionReturn // no local catch, back to caller. 96 ldr x0, [xFP, #OFF_FP_CODE_ITEM] 97 ldr w1, [xFP, #OFF_FP_DEX_PC] 98 ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] 99 add xPC, x0, #CODEITEM_INSNS_OFFSET 100 add xPC, xPC, x1, lsl #1 // generate new dex_pc_ptr 101 /* Do we need to switch interpreters? */ 102 bl MterpShouldSwitchInterpreters 103 cbnz w0, MterpFallback 104 /* resume execution at catch block */ 105 EXPORT_PC 106 FETCH_INST 107 GET_INST_OPCODE ip 108 GOTO_OPCODE ip 109 /* NOTE: no fallthrough */ 110/* 111 * Common handling for branches with support for Jit profiling. 112 * On entry: 113 * wINST <= signed offset 114 * wPROFILE <= signed hotness countdown (expanded to 32 bits) 115 * condition bits <= set to establish sign of offset (use "NoFlags" entry if not) 116 * 117 * We have quite a few different cases for branch profiling, OSR detection and 118 * suspend check support here. 119 * 120 * Taken backward branches: 121 * If profiling active, do hotness countdown and report if we hit zero. 122 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 123 * Is there a pending suspend request? If so, suspend. 124 * 125 * Taken forward branches and not-taken backward branches: 126 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 127 * 128 * Our most common case is expected to be a taken backward branch with active jit profiling, 129 * but no full OSR check and no pending suspend request. 130 * Next most common case is not-taken branch with no full OSR check. 131 * 132 */ 133MterpCommonTakenBranchNoFlags: 134 cmp wINST, #0 135 b.gt .L_forward_branch // don't add forward branches to hotness 136 tbnz wPROFILE, #31, .L_no_count_backwards // go if negative 137 subs wPROFILE, wPROFILE, #1 // countdown 138 b.eq .L_add_batch // counted down to zero - report 139.L_resume_backward_branch: 140 ldr lr, [xSELF, #THREAD_FLAGS_OFFSET] 141 add w2, wINST, wINST // w2<- byte offset 142 FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST 143 REFRESH_IBASE 144 ands lr, lr, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST 145 b.ne .L_suspend_request_pending 146 GET_INST_OPCODE ip // extract opcode from wINST 147 GOTO_OPCODE ip // jump to next instruction 148 149.L_suspend_request_pending: 150 EXPORT_PC 151 mov x0, xSELF 152 bl MterpSuspendCheck // (self) 153 cbnz x0, MterpFallback 154 REFRESH_IBASE // might have changed during suspend 155 GET_INST_OPCODE ip // extract opcode from wINST 156 GOTO_OPCODE ip // jump to next instruction 157 158.L_no_count_backwards: 159 cmp wPROFILE, #JIT_CHECK_OSR // possible OSR re-entry? 160 b.ne .L_resume_backward_branch 161 mov x0, xSELF 162 add x1, xFP, #OFF_FP_SHADOWFRAME 163 mov x2, xINST 164 EXPORT_PC 165 bl MterpMaybeDoOnStackReplacement // (self, shadow_frame, offset) 166 cbnz x0, MterpOnStackReplacement 167 b .L_resume_backward_branch 168 169.L_forward_branch: 170 cmp wPROFILE, #JIT_CHECK_OSR // possible OSR re-entry? 171 b.eq .L_check_osr_forward 172.L_resume_forward_branch: 173 add w2, wINST, wINST // w2<- byte offset 174 FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST 175 GET_INST_OPCODE ip // extract opcode from wINST 176 GOTO_OPCODE ip // jump to next instruction 177 178.L_check_osr_forward: 179 mov x0, xSELF 180 add x1, xFP, #OFF_FP_SHADOWFRAME 181 mov x2, xINST 182 EXPORT_PC 183 bl MterpMaybeDoOnStackReplacement // (self, shadow_frame, offset) 184 cbnz x0, MterpOnStackReplacement 185 b .L_resume_forward_branch 186 187.L_add_batch: 188 add x1, xFP, #OFF_FP_SHADOWFRAME 189 strh wPROFILE, [x1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET] 190 ldr x0, [xFP, #OFF_FP_METHOD] 191 mov x2, xSELF 192 bl MterpAddHotnessBatch // (method, shadow_frame, self) 193 mov wPROFILE, w0 // restore new hotness countdown to wPROFILE 194 b .L_no_count_backwards 195 196/* 197 * Entered from the conditional branch handlers when OSR check request active on 198 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 199 */ 200.L_check_not_taken_osr: 201 mov x0, xSELF 202 add x1, xFP, #OFF_FP_SHADOWFRAME 203 mov x2, #2 204 EXPORT_PC 205 bl MterpMaybeDoOnStackReplacement // (self, shadow_frame, offset) 206 cbnz x0, MterpOnStackReplacement 207 FETCH_ADVANCE_INST 2 208 GET_INST_OPCODE ip // extract opcode from wINST 209 GOTO_OPCODE ip // jump to next instruction 210 211 212/* 213 * Check for suspend check request. Assumes wINST already loaded, xPC advanced and 214 * still needs to get the opcode and branch to it, and flags are in lr. 215 */ 216MterpCheckSuspendAndContinue: 217 ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh xIBASE 218 ands w7, w7, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST 219 b.ne check1 220 GET_INST_OPCODE ip // extract opcode from wINST 221 GOTO_OPCODE ip // jump to next instruction 222check1: 223 EXPORT_PC 224 mov x0, xSELF 225 bl MterpSuspendCheck // (self) 226 cbnz x0, MterpFallback // Something in the environment changed, switch interpreters 227 GET_INST_OPCODE ip // extract opcode from wINST 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 x0, xSELF 236 add x1, xFP, #OFF_FP_SHADOWFRAME 237 sxtw x2, wINST 238 bl MterpLogOSR 239#endif 240 mov x0, #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 x0, xSELF 250 add x1, xFP, #OFF_FP_SHADOWFRAME 251 bl MterpLogFallback 252#endif 253MterpCommonFallback: 254 mov x0, #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* xFP (should still be live, pointer to base of vregs) 264 */ 265MterpExceptionReturn: 266 mov x0, #1 // signal return to caller. 267 b MterpDone 268MterpReturn: 269 ldr x2, [xFP, #OFF_FP_RESULT_REGISTER] 270 str x0, [x2] 271 mov x0, #1 // signal return to caller. 272MterpDone: 273/* 274 * At this point, we expect wPROFILE to be non-zero. If negative, hotness is disabled or we're 275 * checking for OSR. If greater than zero, we might have unreported hotness to register 276 * (the difference between the ending wPROFILE and the cached hotness counter). wPROFILE 277 * should only reach zero immediately after a hotness decrement, and is then reset to either 278 * a negative special state or the new non-zero countdown value. 279 */ 280 cmp wPROFILE, #0 281 bgt MterpProfileActive // if > 0, we may have some counts to report. 282 .cfi_remember_state 283 RESTORE_TWO_REGS fp, lr, 64 284 RESTORE_TWO_REGS xPC, xFP, 48 285 RESTORE_TWO_REGS xSELF, xINST, 32 286 RESTORE_TWO_REGS xIBASE, xREFS, 16 287 RESTORE_TWO_REGS_DECREASE_FRAME xPROFILE, x27, 80 288 ret 289 .cfi_restore_state // Reset unwind info so following code unwinds. 290 .cfi_def_cfa_offset 80 // workaround for clang bug: 31975598 291 292MterpProfileActive: 293 mov xINST, x0 // stash return value 294 /* Report cached hotness counts */ 295 ldr x0, [xFP, #OFF_FP_METHOD] 296 add x1, xFP, #OFF_FP_SHADOWFRAME 297 mov x2, xSELF 298 strh wPROFILE, [x1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET] 299 bl MterpAddHotnessBatch // (method, shadow_frame, self) 300 mov x0, xINST // restore return value 301 RESTORE_TWO_REGS fp, lr, 64 302 RESTORE_TWO_REGS xPC, xFP, 48 303 RESTORE_TWO_REGS xSELF, xINST, 32 304 RESTORE_TWO_REGS xIBASE, xREFS, 16 305 RESTORE_TWO_REGS_DECREASE_FRAME xPROFILE, x27, 80 306 ret 307 308 .cfi_endproc 309 .size ExecuteMterpImpl, .-ExecuteMterpImpl 310 311