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 movq rSELF, OUT_ARG0 19 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 20 call SYMBOL(MterpLogDivideByZeroException) 21#endif 22 jmp MterpCommonFallback 23 24common_errArrayIndex: 25 EXPORT_PC 26#if MTERP_LOGGING 27 movq rSELF, OUT_ARG0 28 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 29 call SYMBOL(MterpLogArrayIndexException) 30#endif 31 jmp MterpCommonFallback 32 33common_errNegativeArraySize: 34 EXPORT_PC 35#if MTERP_LOGGING 36 movq rSELF, OUT_ARG0 37 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 38 call SYMBOL(MterpLogNegativeArraySizeException) 39#endif 40 jmp MterpCommonFallback 41 42common_errNoSuchMethod: 43 EXPORT_PC 44#if MTERP_LOGGING 45 movq rSELF, OUT_ARG0 46 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 47 call SYMBOL(MterpLogNoSuchMethodException) 48#endif 49 jmp MterpCommonFallback 50 51common_errNullObject: 52 EXPORT_PC 53#if MTERP_LOGGING 54 movq rSELF, OUT_ARG0 55 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 56 call SYMBOL(MterpLogNullObjectException) 57#endif 58 jmp MterpCommonFallback 59 60common_exceptionThrown: 61 EXPORT_PC 62#if MTERP_LOGGING 63 movq rSELF, OUT_ARG0 64 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 65 call SYMBOL(MterpLogExceptionThrownException) 66#endif 67 jmp MterpCommonFallback 68 69MterpSuspendFallback: 70 EXPORT_PC 71#if MTERP_LOGGING 72 movq rSELF, OUT_ARG0 73 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 74 movl THREAD_FLAGS_OFFSET(OUT_ARG0), OUT_32_ARG2 75 call SYMBOL(MterpLogSuspendFallback) 76#endif 77 jmp 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 movq rSELF, %rcx 86 cmpq $$0, THREAD_EXCEPTION_OFFSET(%rcx) 87 jz MterpFallback 88 /* intentional fallthrough - handle pending exception. */ 89 90/* 91 * On return from a runtime helper routine, we've found a pending exception. 92 * Can we handle it here - or need to bail out to caller? 93 * 94 */ 95MterpException: 96 movq rSELF, OUT_ARG0 97 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 98 call SYMBOL(MterpHandleException) 99 testb %al, %al 100 jz MterpExceptionReturn 101 movq OFF_FP_CODE_ITEM(rFP), %rax 102 mov OFF_FP_DEX_PC(rFP), %ecx 103 leaq CODEITEM_INSNS_OFFSET(%rax), rPC 104 leaq (rPC, %rcx, 2), rPC 105 movq rPC, OFF_FP_DEX_PC_PTR(rFP) 106 /* Do we need to switch interpreters? */ 107 call SYMBOL(MterpShouldSwitchInterpreters) 108 testb %al, %al 109 jnz MterpFallback 110 /* resume execution at catch block */ 111 REFRESH_IBASE 112 FETCH_INST 113 GOTO_NEXT 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 */ 139MterpCommonTakenBranch: 140 jg .L_forward_branch # don't add forward branches to hotness 141/* 142 * We need to subtract 1 from positive values and we should not see 0 here, 143 * so we may use the result of the comparison with -1. 144 */ 145#if JIT_CHECK_OSR != -1 146# error "JIT_CHECK_OSR must be -1." 147#endif 148 cmpl $$JIT_CHECK_OSR, rPROFILE 149 je .L_osr_check 150 decl rPROFILE 151 je .L_add_batch # counted down to zero - report 152.L_resume_backward_branch: 153 movq rSELF, %rax 154 testl $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%rax) 155 REFRESH_IBASE 156 leaq (rPC, rINSTq, 2), rPC 157 FETCH_INST 158 jnz .L_suspend_request_pending 159 GOTO_NEXT 160 161.L_suspend_request_pending: 162 EXPORT_PC 163 movq rSELF, OUT_ARG0 164 call SYMBOL(MterpSuspendCheck) # (self) 165 testb %al, %al 166 jnz MterpFallback 167 REFRESH_IBASE # might have changed during suspend 168 GOTO_NEXT 169 170.L_no_count_backwards: 171 cmpl $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 172 jne .L_resume_backward_branch 173.L_osr_check: 174 EXPORT_PC 175 movq rSELF, OUT_ARG0 176 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 177 movq rINSTq, OUT_ARG2 178 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 179 testb %al, %al 180 jz .L_resume_backward_branch 181 jmp MterpOnStackReplacement 182 183.L_forward_branch: 184 cmpl $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 185 je .L_check_osr_forward 186.L_resume_forward_branch: 187 leaq (rPC, rINSTq, 2), rPC 188 FETCH_INST 189 GOTO_NEXT 190 191.L_check_osr_forward: 192 EXPORT_PC 193 movq rSELF, OUT_ARG0 194 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 195 movq rINSTq, OUT_ARG2 196 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 197 testb %al, %al 198 jz .L_resume_forward_branch 199 jmp MterpOnStackReplacement 200 201.L_add_batch: 202 movl rPROFILE, %eax 203 movq OFF_FP_METHOD(rFP), OUT_ARG0 204 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 205 movw %ax, OFF_FP_COUNTDOWN_OFFSET(rFP) 206 movq rSELF, OUT_ARG2 207 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 208 movswl %ax, rPROFILE 209 jmp .L_no_count_backwards 210 211/* 212 * Entered from the conditional branch handlers when OSR check request active on 213 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 214 */ 215.L_check_not_taken_osr: 216 EXPORT_PC 217 movq rSELF, OUT_ARG0 218 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 219 movl $$2, OUT_32_ARG2 220 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 221 testb %al, %al 222 jnz MterpOnStackReplacement 223 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 224 225/* 226 * On-stack replacement has happened, and now we've returned from the compiled method. 227 */ 228MterpOnStackReplacement: 229#if MTERP_LOGGING 230 movq rSELF, OUT_ARG0 231 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 232 movl rINST, OUT_32_ARG2 233 call SYMBOL(MterpLogOSR) 234#endif 235 movl $$1, %eax 236 jmp MterpDone 237 238/* 239 * Bail out to reference interpreter. 240 */ 241MterpFallback: 242 EXPORT_PC 243#if MTERP_LOGGING 244 movq rSELF, OUT_ARG0 245 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 246 call SYMBOL(MterpLogFallback) 247#endif 248MterpCommonFallback: 249 xorl %eax, %eax 250 jmp MterpDone 251 252/* 253 * On entry: 254 * uint32_t* rFP (should still be live, pointer to base of vregs) 255 */ 256MterpExceptionReturn: 257 movl $$1, %eax 258 jmp MterpDone 259MterpReturn: 260 movq OFF_FP_RESULT_REGISTER(rFP), %rdx 261 movq %rax, (%rdx) 262 movl $$1, %eax 263MterpDone: 264/* 265 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're 266 * checking for OSR. If greater than zero, we might have unreported hotness to register 267 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE 268 * should only reach zero immediately after a hotness decrement, and is then reset to either 269 * a negative special state or the new non-zero countdown value. 270 */ 271 testl rPROFILE, rPROFILE 272 jle MRestoreFrame # if > 0, we may have some counts to report. 273 274 movl %eax, rINST # stash return value 275 /* Report cached hotness counts */ 276 movl rPROFILE, %eax 277 movq OFF_FP_METHOD(rFP), OUT_ARG0 278 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 279 movw %ax, OFF_FP_COUNTDOWN_OFFSET(rFP) 280 movq rSELF, OUT_ARG2 281 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 282 movl rINST, %eax # restore return value 283 284 /* pop up frame */ 285MRestoreFrame: 286 addq $$FRAME_SIZE, %rsp 287 .cfi_adjust_cfa_offset -FRAME_SIZE 288 289 /* Restore callee save register */ 290 POP %r15 291 POP %r14 292 POP %r13 293 POP %r12 294 POP %rbp 295 POP %rbx 296 ret 297 .cfi_endproc 298 SIZE(ExecuteMterpImpl,ExecuteMterpImpl) 299