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 */ 15 common_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 26 common_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 37 common_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 48 common_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 59 common_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 70 common_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 81 MterpSuspendFallback: 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 */ 99 MterpPossibleException: 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 */ 110 MterpException: 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_CODE_ITEM(rFP), %eax 119 movl OFF_FP_DEX_PC(rFP), %ecx 120 lea CODEITEM_INSNS_OFFSET(%eax), rPC 121 lea (rPC, %ecx, 2), rPC 122 movl rPC, OFF_FP_DEX_PC_PTR(rFP) 123 /* Do we need to switch interpreters? */ 124 call SYMBOL(MterpShouldSwitchInterpreters) 125 testb %al, %al 126 jnz MterpFallback 127 /* resume execution at catch block */ 128 REFRESH_IBASE 129 FETCH_INST 130 GOTO_NEXT 131 /* NOTE: no fallthrough */ 132 133 /* 134 * Common handling for branches with support for Jit profiling. 135 * On entry: 136 * rINST <= signed offset 137 * condition bits <= set to establish sign of offset (use "NoFlags" entry if not) 138 * 139 * We have quite a few different cases for branch profiling, OSR detection and 140 * suspend check support here. 141 * 142 * Taken backward branches: 143 * If profiling active, do hotness countdown and report if we hit zero. 144 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 145 * Is there a pending suspend request? If so, suspend. 146 * 147 * Taken forward branches and not-taken backward branches: 148 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so. 149 * 150 * Our most common case is expected to be a taken backward branch with active jit profiling, 151 * but no full OSR check and no pending suspend request. 152 * Next most common case is not-taken branch with no full OSR check. 153 * 154 */ 155 MterpCommonTakenBranch: 156 jg .L_forward_branch # don't add forward branches to hotness 157 /* 158 * We need to subtract 1 from positive values and we should not see 0 here, 159 * so we may use the result of the comparison with -1. 160 */ 161 #if JIT_CHECK_OSR != -1 162 # error "JIT_CHECK_OSR must be -1." 163 #endif 164 cmpw $$JIT_CHECK_OSR, rPROFILE 165 je .L_osr_check 166 decw rPROFILE 167 je .L_add_batch # counted down to zero - report 168 .L_resume_backward_branch: 169 movl rSELF, %eax 170 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax) 171 leal (rPC, rINST, 2), rPC 172 FETCH_INST 173 jnz .L_suspend_request_pending 174 REFRESH_IBASE 175 GOTO_NEXT 176 177 .L_suspend_request_pending: 178 EXPORT_PC 179 movl %eax, OUT_ARG0(%esp) # rSELF in eax 180 call SYMBOL(MterpSuspendCheck) # (self) 181 testb %al, %al 182 jnz MterpFallback 183 REFRESH_IBASE # might have changed during suspend 184 GOTO_NEXT 185 186 .L_no_count_backwards: 187 cmpw $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 188 jne .L_resume_backward_branch 189 .L_osr_check: 190 EXPORT_PC 191 movl rSELF, %eax 192 movl %eax, OUT_ARG0(%esp) 193 leal OFF_FP_SHADOWFRAME(rFP), %ecx 194 movl %ecx, OUT_ARG1(%esp) 195 movl rINST, OUT_ARG2(%esp) 196 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 197 testb %al, %al 198 jz .L_resume_backward_branch 199 jmp MterpOnStackReplacement 200 201 .L_forward_branch: 202 cmpw $$JIT_CHECK_OSR, rPROFILE # possible OSR re-entry? 203 je .L_check_osr_forward 204 .L_resume_forward_branch: 205 leal (rPC, rINST, 2), rPC 206 FETCH_INST 207 GOTO_NEXT 208 209 .L_check_osr_forward: 210 EXPORT_PC 211 movl rSELF, %eax 212 movl %eax, OUT_ARG0(%esp) 213 leal OFF_FP_SHADOWFRAME(rFP), %ecx 214 movl %ecx, OUT_ARG1(%esp) 215 movl rINST, OUT_ARG2(%esp) 216 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 217 testb %al, %al 218 REFRESH_IBASE 219 jz .L_resume_forward_branch 220 jmp MterpOnStackReplacement 221 222 .L_add_batch: 223 movl OFF_FP_METHOD(rFP), %eax 224 movl %eax, OUT_ARG0(%esp) 225 leal OFF_FP_SHADOWFRAME(rFP), %ecx 226 movl %ecx, OUT_ARG1(%esp) 227 movl rSELF, %eax 228 movl %eax, OUT_ARG2(%esp) 229 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 230 jmp .L_no_count_backwards 231 232 /* 233 * Entered from the conditional branch handlers when OSR check request active on 234 * not-taken path. All Dalvik not-taken conditional branch offsets are 2. 235 */ 236 .L_check_not_taken_osr: 237 EXPORT_PC 238 movl rSELF, %eax 239 movl %eax, OUT_ARG0(%esp) 240 leal OFF_FP_SHADOWFRAME(rFP), %ecx 241 movl %ecx, OUT_ARG1(%esp) 242 movl $$2, OUT_ARG2(%esp) 243 call SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset) 244 testb %al, %al 245 REFRESH_IBASE 246 jnz MterpOnStackReplacement 247 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 248 249 /* 250 * On-stack replacement has happened, and now we've returned from the compiled method. 251 */ 252 MterpOnStackReplacement: 253 #if MTERP_LOGGING 254 movl rSELF, %eax 255 movl %eax, OUT_ARG0(%esp) 256 lea OFF_FP_SHADOWFRAME(rFP), %ecx 257 movl %ecx, OUT_ARG1(%esp) 258 movl rINST, OUT_ARG2(%esp) 259 call SYMBOL(MterpLogOSR) 260 #endif 261 movl $$1, %eax 262 jmp MterpDone 263 264 /* 265 * Bail out to reference interpreter. 266 */ 267 MterpFallback: 268 EXPORT_PC 269 #if MTERP_LOGGING 270 movl rSELF, %eax 271 movl %eax, OUT_ARG0(%esp) 272 lea OFF_FP_SHADOWFRAME(rFP), %ecx 273 movl %ecx, OUT_ARG1(%esp) 274 call SYMBOL(MterpLogFallback) 275 #endif 276 MterpCommonFallback: 277 xor %eax, %eax 278 jmp MterpDone 279 280 /* 281 * On entry: 282 * uint32_t* rFP (should still be live, pointer to base of vregs) 283 */ 284 MterpExceptionReturn: 285 movl $$1, %eax 286 jmp MterpDone 287 MterpReturn: 288 movl OFF_FP_RESULT_REGISTER(rFP), %edx 289 movl %eax, (%edx) 290 movl %ecx, 4(%edx) 291 mov $$1, %eax 292 MterpDone: 293 /* 294 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're 295 * checking for OSR. If greater than zero, we might have unreported hotness to register 296 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE 297 * should only reach zero immediately after a hotness decrement, and is then reset to either 298 * a negative special state or the new non-zero countdown value. 299 */ 300 cmpw $$0, rPROFILE 301 jle MRestoreFrame # if > 0, we may have some counts to report. 302 303 movl %eax, rINST # stash return value 304 /* Report cached hotness counts */ 305 movl OFF_FP_METHOD(rFP), %eax 306 movl %eax, OUT_ARG0(%esp) 307 leal OFF_FP_SHADOWFRAME(rFP), %ecx 308 movl %ecx, OUT_ARG1(%esp) 309 movl rSELF, %eax 310 movl %eax, OUT_ARG2(%esp) 311 call SYMBOL(MterpAddHotnessBatch) # (method, shadow_frame, self) 312 movl rINST, %eax # restore return value 313 314 /* pop up frame */ 315 MRestoreFrame: 316 addl $$FRAME_SIZE, %esp 317 .cfi_adjust_cfa_offset -FRAME_SIZE 318 319 /* Restore callee save register */ 320 POP %ebx 321 POP %esi 322 POP %edi 323 POP %ebp 324 ret 325 .cfi_endproc 326 SIZE(ExecuteMterpImpl,ExecuteMterpImpl) 327