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_DEX_INSTRUCTIONS(rFP), %rax 102 mov OFF_FP_DEX_PC(rFP), %ecx 103 leaq (%rax, %rcx, 2), rPC 104 movq rPC, OFF_FP_DEX_PC_PTR(rFP) 105 /* Do we need to switch interpreters? */ 106 call SYMBOL(MterpShouldSwitchInterpreters) 107 testb %al, %al 108 jnz MterpFallback 109 /* resume execution at catch block */ 110 REFRESH_IBASE 111 FETCH_INST 112 GOTO_NEXT 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 */ 138MterpCommonTakenBranch: 139 jg .L_forward_branch # don't add forward branches to hotness 140/* 141 * We need to subtract 1 from positive values and we should not see 0 here, 142 * so we may use the result of the comparison with -1. 143 */ 144#if JIT_CHECK_OSR != -1 145# error "JIT_CHECK_OSR must be -1." 146#endif 147 cmpl $$JIT_CHECK_OSR, rPROFILE 148 je .L_osr_check 149 decl rPROFILE 150 je .L_add_batch # counted down to zero - report 151.L_resume_backward_branch: 152 movq rSELF, %rax 153 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%rax) 154 REFRESH_IBASE_REG %rax 155 leaq (rPC, rINSTq, 2), rPC 156 FETCH_INST 157 jnz .L_suspend_request_pending 158 GOTO_NEXT 159 160.L_suspend_request_pending: 161 EXPORT_PC 162 movq rSELF, OUT_ARG0 163 call SYMBOL(MterpSuspendCheck) # (self) 164 testb %al, %al 165 jnz MterpFallback 166 REFRESH_IBASE # might have changed during suspend 167 GOTO_NEXT 168 169.L_no_count_backwards: 170 cmpl $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 171 jne .L_resume_backward_branch 172.L_osr_check: 173 EXPORT_PC 174 movq rSELF, OUT_ARG0 175 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 176 movq rINSTq, OUT_ARG2 177 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 178 testb %al, %al 179 jz .L_resume_backward_branch 180 jmp MterpOnStackReplacement 181 182.L_forward_branch: 183 cmpl $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 184 je .L_check_osr_forward 185.L_resume_forward_branch: 186 leaq (rPC, rINSTq, 2), rPC 187 FETCH_INST 188 GOTO_NEXT 189 190.L_check_osr_forward: 191 EXPORT_PC 192 movq rSELF, OUT_ARG0 193 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 194 movq rINSTq, OUT_ARG2 195 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 196 testb %al, %al 197 jz .L_resume_forward_branch 198 jmp MterpOnStackReplacement 199 200.L_add_batch: 201 movl rPROFILE, %eax 202 movq OFF_FP_METHOD(rFP), OUT_ARG0 203 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 204 movw %ax, OFF_FP_COUNTDOWN_OFFSET(rFP) 205 movq rSELF, OUT_ARG2 206 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 207 movswl %ax, rPROFILE 208 jmp .L_no_count_backwards 209 210/* 211 * Entered from the conditional branch handlers when OSR check request active on 212 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 213 */ 214.L_check_not_taken_osr: 215 EXPORT_PC 216 movq rSELF, OUT_ARG0 217 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 218 movl $$2, OUT_32_ARG2 219 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 220 testb %al, %al 221 jnz MterpOnStackReplacement 222 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 223 224/* 225 * On-stack replacement has happened, and now we've returned from the compiled method. 226 */ 227MterpOnStackReplacement: 228#if MTERP_LOGGING 229 movq rSELF, OUT_ARG0 230 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 231 movl rINST, OUT_32_ARG2 232 call SYMBOL(MterpLogOSR) 233#endif 234 movl $$1, %eax 235 jmp MterpDone 236 237/* 238 * Bail out to reference interpreter. 239 */ 240MterpFallback: 241 EXPORT_PC 242#if MTERP_LOGGING 243 movq rSELF, OUT_ARG0 244 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 245 call SYMBOL(MterpLogFallback) 246#endif 247MterpCommonFallback: 248 xorl %eax, %eax 249 jmp MterpDone 250 251/* 252 * On entry: 253 * uint32_t* rFP (should still be live, pointer to base of vregs) 254 */ 255MterpExceptionReturn: 256 movl $$1, %eax 257 jmp MterpDone 258MterpReturn: 259 movq OFF_FP_RESULT_REGISTER(rFP), %rdx 260 movq %rax, (%rdx) 261 movl $$1, %eax 262MterpDone: 263/* 264 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're 265 * checking for OSR. If greater than zero, we might have unreported hotness to register 266 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE 267 * should only reach zero immediately after a hotness decrement, and is then reset to either 268 * a negative special state or the new non-zero countdown value. 269 */ 270 testl rPROFILE, rPROFILE 271 jle MRestoreFrame # if > 0, we may have some counts to report. 272 273 movl %eax, rINST # stash return value 274 /* Report cached hotness counts */ 275 movl rPROFILE, %eax 276 movq OFF_FP_METHOD(rFP), OUT_ARG0 277 leaq OFF_FP_SHADOWFRAME(rFP), OUT_ARG1 278 movw %ax, OFF_FP_COUNTDOWN_OFFSET(rFP) 279 movq rSELF, OUT_ARG2 280 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 281 movl rINST, %eax # restore return value 282 283 /* pop up frame */ 284MRestoreFrame: 285 addq $$FRAME_SIZE, %rsp 286 .cfi_adjust_cfa_offset -FRAME_SIZE 287 288 /* Restore callee save register */ 289 POP %r15 290 POP %r14 291 POP %r13 292 POP %r12 293 POP %rbp 294 POP %rbx 295 ret 296 .cfi_endproc 297 SIZE(ExecuteMterpImpl,ExecuteMterpImpl) 298