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 movl rSELF, %eax 19 movl %eax, OUT_ARG0(%esp) 20 lea OFF_FP_SHADOWFRAME(rFP), %ecx 21 movl %ecx, OUT_ARG1(%esp) 22 call SYMBOL(MterpLogDivideByZeroException) 23#endif 24 jmp MterpCommonFallback 25 26common_errArrayIndex: 27 EXPORT_PC 28#if MTERP_LOGGING 29 movl rSELF, %eax 30 movl %eax, OUT_ARG0(%esp) 31 lea OFF_FP_SHADOWFRAME(rFP), %ecx 32 movl %ecx, OUT_ARG1(%esp) 33 call SYMBOL(MterpLogArrayIndexException) 34#endif 35 jmp MterpCommonFallback 36 37common_errNegativeArraySize: 38 EXPORT_PC 39#if MTERP_LOGGING 40 movl rSELF, %eax 41 movl %eax, OUT_ARG0(%esp) 42 lea OFF_FP_SHADOWFRAME(rFP), %ecx 43 movl %ecx, OUT_ARG1(%esp) 44 call SYMBOL(MterpLogNegativeArraySizeException) 45#endif 46 jmp MterpCommonFallback 47 48common_errNoSuchMethod: 49 EXPORT_PC 50#if MTERP_LOGGING 51 movl rSELF, %eax 52 movl %eax, OUT_ARG0(%esp) 53 lea OFF_FP_SHADOWFRAME(rFP), %ecx 54 movl %ecx, OUT_ARG1(%esp) 55 call SYMBOL(MterpLogNoSuchMethodException) 56#endif 57 jmp MterpCommonFallback 58 59common_errNullObject: 60 EXPORT_PC 61#if MTERP_LOGGING 62 movl rSELF, %eax 63 movl %eax, OUT_ARG0(%esp) 64 lea OFF_FP_SHADOWFRAME(rFP), %ecx 65 movl %ecx, OUT_ARG1(%esp) 66 call SYMBOL(MterpLogNullObjectException) 67#endif 68 jmp MterpCommonFallback 69 70common_exceptionThrown: 71 EXPORT_PC 72#if MTERP_LOGGING 73 movl rSELF, %eax 74 movl %eax, OUT_ARG0(%esp) 75 lea OFF_FP_SHADOWFRAME(rFP), %ecx 76 movl %ecx, OUT_ARG0(%esp) 77 call SYMBOL(MterpLogExceptionThrownException) 78#endif 79 jmp MterpCommonFallback 80 81MterpSuspendFallback: 82 EXPORT_PC 83#if MTERP_LOGGING 84 movl rSELF, %eax 85 movl %eax, OUT_ARG0(%esp) 86 lea OFF_FP_SHADOWFRAME(rFP), %ecx 87 movl %ecx, OUT_ARG0(%esp) 88 movl THREAD_FLAGS_OFFSET(%eax), %eax 89 movl %eax, OUT_ARG2(%esp) 90 call SYMBOL(MterpLogSuspendFallback) 91#endif 92 jmp MterpCommonFallback 93 94/* 95 * If we're here, something is out of the ordinary. If there is a pending 96 * exception, handle it. Otherwise, roll back and retry with the reference 97 * interpreter. 98 */ 99MterpPossibleException: 100 movl rSELF, %eax 101 testl $$-1, THREAD_EXCEPTION_OFFSET(%eax) 102 jz MterpFallback 103 /* intentional fallthrough - handle pending exception. */ 104 105/* 106 * On return from a runtime helper routine, we've found a pending exception. 107 * Can we handle it here - or need to bail out to caller? 108 * 109 */ 110MterpException: 111 movl rSELF, %eax 112 movl %eax, OUT_ARG0(%esp) 113 lea OFF_FP_SHADOWFRAME(rFP), %ecx 114 movl %ecx, OUT_ARG1(%esp) 115 call SYMBOL(MterpHandleException) 116 testb %al, %al 117 jz MterpExceptionReturn 118 movl OFF_FP_DEX_INSTRUCTIONS(rFP), %eax 119 movl OFF_FP_DEX_PC(rFP), %ecx 120 lea (%eax, %ecx, 2), rPC 121 movl rPC, OFF_FP_DEX_PC_PTR(rFP) 122 /* Do we need to switch interpreters? */ 123 call SYMBOL(MterpShouldSwitchInterpreters) 124 testb %al, %al 125 jnz MterpFallback 126 /* resume execution at catch block */ 127 REFRESH_IBASE 128 FETCH_INST 129 GOTO_NEXT 130 /* NOTE: no fallthrough */ 131 132/* 133 * Common handling for branches with support for Jit profiling. 134 * On entry: 135 * rINST <= signed offset 136 * condition bits <= set to establish sign of offset (use "NoFlags" entry if not) 137 * 138 * We have quite a few different cases for branch profiling, OSR detection and 139 * suspend check support here. 140 * 141 * Taken backward branches: 142 * If profiling active, do hotness countdown and report if we hit zero. 143 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 144 * Is there a pending suspend request? If so, suspend. 145 * 146 * Taken forward branches and not-taken backward branches: 147 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 148 * 149 * Our most common case is expected to be a taken backward branch with active jit profiling, 150 * but no full OSR check and no pending suspend request. 151 * Next most common case is not-taken branch with no full OSR check. 152 * 153 */ 154MterpCommonTakenBranch: 155 jg .L_forward_branch # don't add forward branches to hotness 156/* 157 * We need to subtract 1 from positive values and we should not see 0 here, 158 * so we may use the result of the comparison with -1. 159 */ 160#if JIT_CHECK_OSR != -1 161# error "JIT_CHECK_OSR must be -1." 162#endif 163 cmpw $$JIT_CHECK_OSR, rPROFILE 164 je .L_osr_check 165 decw rPROFILE 166 je .L_add_batch # counted down to zero - report 167.L_resume_backward_branch: 168 movl rSELF, %eax 169 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax) 170 leal (rPC, rINST, 2), rPC 171 FETCH_INST 172 jnz .L_suspend_request_pending 173 REFRESH_IBASE 174 GOTO_NEXT 175 176.L_suspend_request_pending: 177 EXPORT_PC 178 movl %eax, OUT_ARG0(%esp) # rSELF in eax 179 call SYMBOL(MterpSuspendCheck) # (self) 180 testb %al, %al 181 jnz MterpFallback 182 REFRESH_IBASE # might have changed during suspend 183 GOTO_NEXT 184 185.L_no_count_backwards: 186 cmpw $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 187 jne .L_resume_backward_branch 188.L_osr_check: 189 EXPORT_PC 190 movl rSELF, %eax 191 movl %eax, OUT_ARG0(%esp) 192 leal OFF_FP_SHADOWFRAME(rFP), %ecx 193 movl %ecx, OUT_ARG1(%esp) 194 movl rINST, OUT_ARG2(%esp) 195 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 196 testb %al, %al 197 jz .L_resume_backward_branch 198 jmp MterpOnStackReplacement 199 200.L_forward_branch: 201 cmpw $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 202 je .L_check_osr_forward 203.L_resume_forward_branch: 204 leal (rPC, rINST, 2), rPC 205 FETCH_INST 206 GOTO_NEXT 207 208.L_check_osr_forward: 209 EXPORT_PC 210 movl rSELF, %eax 211 movl %eax, OUT_ARG0(%esp) 212 leal OFF_FP_SHADOWFRAME(rFP), %ecx 213 movl %ecx, OUT_ARG1(%esp) 214 movl rINST, OUT_ARG2(%esp) 215 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 216 testb %al, %al 217 REFRESH_IBASE 218 jz .L_resume_forward_branch 219 jmp MterpOnStackReplacement 220 221.L_add_batch: 222 movl OFF_FP_METHOD(rFP), %eax 223 movl %eax, OUT_ARG0(%esp) 224 leal OFF_FP_SHADOWFRAME(rFP), %ecx 225 movl %ecx, OUT_ARG1(%esp) 226 movl rSELF, %eax 227 movl %eax, OUT_ARG2(%esp) 228 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 229 jmp .L_no_count_backwards 230 231/* 232 * Entered from the conditional branch handlers when OSR check request active on 233 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 234 */ 235.L_check_not_taken_osr: 236 EXPORT_PC 237 movl rSELF, %eax 238 movl %eax, OUT_ARG0(%esp) 239 leal OFF_FP_SHADOWFRAME(rFP), %ecx 240 movl %ecx, OUT_ARG1(%esp) 241 movl $$2, OUT_ARG2(%esp) 242 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 243 testb %al, %al 244 REFRESH_IBASE 245 jnz MterpOnStackReplacement 246 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 247 248/* 249 * On-stack replacement has happened, and now we've returned from the compiled method. 250 */ 251MterpOnStackReplacement: 252#if MTERP_LOGGING 253 movl rSELF, %eax 254 movl %eax, OUT_ARG0(%esp) 255 lea OFF_FP_SHADOWFRAME(rFP), %ecx 256 movl %ecx, OUT_ARG1(%esp) 257 movl rINST, OUT_ARG2(%esp) 258 call SYMBOL(MterpLogOSR) 259#endif 260 movl $$1, %eax 261 jmp MterpDone 262 263/* 264 * Bail out to reference interpreter. 265 */ 266MterpFallback: 267 EXPORT_PC 268#if MTERP_LOGGING 269 movl rSELF, %eax 270 movl %eax, OUT_ARG0(%esp) 271 lea OFF_FP_SHADOWFRAME(rFP), %ecx 272 movl %ecx, OUT_ARG1(%esp) 273 call SYMBOL(MterpLogFallback) 274#endif 275MterpCommonFallback: 276 xor %eax, %eax 277 jmp MterpDone 278 279/* 280 * On entry: 281 * uint32_t* rFP (should still be live, pointer to base of vregs) 282 */ 283MterpExceptionReturn: 284 movl $$1, %eax 285 jmp MterpDone 286MterpReturn: 287 movl OFF_FP_RESULT_REGISTER(rFP), %edx 288 movl %eax, (%edx) 289 movl %ecx, 4(%edx) 290 mov $$1, %eax 291MterpDone: 292/* 293 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're 294 * checking for OSR. If greater than zero, we might have unreported hotness to register 295 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE 296 * should only reach zero immediately after a hotness decrement, and is then reset to either 297 * a negative special state or the new non-zero countdown value. 298 */ 299 cmpw $$0, rPROFILE 300 jle MRestoreFrame # if > 0, we may have some counts to report. 301 302 movl %eax, rINST # stash return value 303 /* Report cached hotness counts */ 304 movl OFF_FP_METHOD(rFP), %eax 305 movl %eax, OUT_ARG0(%esp) 306 leal OFF_FP_SHADOWFRAME(rFP), %ecx 307 movl %ecx, OUT_ARG1(%esp) 308 movl rSELF, %eax 309 movl %eax, OUT_ARG2(%esp) 310 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 311 movl rINST, %eax # restore return value 312 313 /* pop up frame */ 314MRestoreFrame: 315 addl $$FRAME_SIZE, %esp 316 .cfi_adjust_cfa_offset -FRAME_SIZE 317 318 /* Restore callee save register */ 319 POP %ebx 320 POP %esi 321 POP %edi 322 POP %ebp 323 ret 324 .cfi_endproc 325 SIZE(ExecuteMterpImpl,ExecuteMterpImpl) 326