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