1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
|
/*
* We've detected a condition that will result in an exception, but the exception
* has not yet been thrown. Just bail out to the reference interpreter to deal with it.
* TUNING: for consistency, we may want to just go ahead and handle these here.
*/
.extern MterpLogDivideByZeroException
common_errDivideByZero:
EXPORT_PC
#if MTERP_LOGGING
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
jal MterpLogDivideByZeroException
#endif
b MterpCommonFallback
.extern MterpLogArrayIndexException
common_errArrayIndex:
EXPORT_PC
#if MTERP_LOGGING
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
jal MterpLogArrayIndexException
#endif
b MterpCommonFallback
.extern MterpLogNullObjectException
common_errNullObject:
EXPORT_PC
#if MTERP_LOGGING
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
jal MterpLogNullObjectException
#endif
b MterpCommonFallback
/*
* If we're here, something is out of the ordinary. If there is a pending
* exception, handle it. Otherwise, roll back and retry with the reference
* interpreter.
*/
MterpPossibleException:
ld a0, THREAD_EXCEPTION_OFFSET(rSELF)
beqzc a0, MterpFallback # If not, fall back to reference interpreter.
/* intentional fallthrough - handle pending exception. */
/*
* On return from a runtime helper routine, we've found a pending exception.
* Can we handle it here - or need to bail out to caller?
*
*/
.extern MterpHandleException
.extern MterpShouldSwitchInterpreters
MterpException:
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
jal MterpHandleException # (self, shadow_frame)
beqzc v0, MterpExceptionReturn # no local catch, back to caller.
ld a0, OFF_FP_CODE_ITEM(rFP)
lwu a1, OFF_FP_DEX_PC(rFP)
REFRESH_IBASE
daddu rPC, a0, CODEITEM_INSNS_OFFSET
dlsa rPC, a1, rPC, 1 # generate new dex_pc_ptr
/* Do we need to switch interpreters? */
jal MterpShouldSwitchInterpreters
bnezc v0, MterpFallback
/* resume execution at catch block */
EXPORT_PC
FETCH_INST
GET_INST_OPCODE v0
GOTO_OPCODE v0
/* NOTE: no fallthrough */
/*
* Common handling for branches with support for Jit profiling.
* On entry:
* rINST <= signed offset
* rPROFILE <= signed hotness countdown (expanded to 64 bits)
*
* We have quite a few different cases for branch profiling, OSR detection and
* suspend check support here.
*
* Taken backward branches:
* If profiling active, do hotness countdown and report if we hit zero.
* If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
* Is there a pending suspend request? If so, suspend.
*
* Taken forward branches and not-taken backward branches:
* If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
*
* Our most common case is expected to be a taken backward branch with active jit profiling,
* but no full OSR check and no pending suspend request.
* Next most common case is not-taken branch with no full OSR check.
*
*/
MterpCommonTakenBranchNoFlags:
bgtzc rINST, .L_forward_branch # don't add forward branches to hotness
/*
* We need to subtract 1 from positive values and we should not see 0 here,
* so we may use the result of the comparison with -1.
*/
li v0, JIT_CHECK_OSR
beqc rPROFILE, v0, .L_osr_check
bltc rPROFILE, v0, .L_resume_backward_branch
dsubu rPROFILE, 1
beqzc rPROFILE, .L_add_batch # counted down to zero - report
.L_resume_backward_branch:
lw ra, THREAD_FLAGS_OFFSET(rSELF)
REFRESH_IBASE
daddu a2, rINST, rINST # a2<- byte offset
FETCH_ADVANCE_INST_RB a2 # update rPC, load rINST
and ra, THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
bnezc ra, .L_suspend_request_pending
GET_INST_OPCODE v0 # extract opcode from rINST
GOTO_OPCODE v0 # jump to next instruction
.L_suspend_request_pending:
EXPORT_PC
move a0, rSELF
jal MterpSuspendCheck # (self)
bnezc v0, MterpFallback
REFRESH_IBASE # might have changed during suspend
GET_INST_OPCODE v0 # extract opcode from rINST
GOTO_OPCODE v0 # jump to next instruction
.L_no_count_backwards:
li v0, JIT_CHECK_OSR # check for possible OSR re-entry
bnec rPROFILE, v0, .L_resume_backward_branch
.L_osr_check:
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
move a2, rINST
EXPORT_PC
jal MterpMaybeDoOnStackReplacement # (self, shadow_frame, offset)
bnezc v0, MterpOnStackReplacement
b .L_resume_backward_branch
.L_forward_branch:
li v0, JIT_CHECK_OSR # check for possible OSR re-entry
beqc rPROFILE, v0, .L_check_osr_forward
.L_resume_forward_branch:
daddu a2, rINST, rINST # a2<- byte offset
FETCH_ADVANCE_INST_RB a2 # update rPC, load rINST
GET_INST_OPCODE v0 # extract opcode from rINST
GOTO_OPCODE v0 # jump to next instruction
.L_check_osr_forward:
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
move a2, rINST
EXPORT_PC
jal MterpMaybeDoOnStackReplacement # (self, shadow_frame, offset)
bnezc v0, MterpOnStackReplacement
b .L_resume_forward_branch
.L_add_batch:
daddu a1, rFP, OFF_FP_SHADOWFRAME
sh rPROFILE, SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET(a1)
ld a0, OFF_FP_METHOD(rFP)
move a2, rSELF
jal MterpAddHotnessBatch # (method, shadow_frame, self)
move rPROFILE, v0 # restore new hotness countdown to rPROFILE
b .L_no_count_backwards
/*
* Entered from the conditional branch handlers when OSR check request active on
* not-taken path. All Dalvik not-taken conditional branch offsets are 2.
*/
.L_check_not_taken_osr:
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
li a2, 2
EXPORT_PC
jal MterpMaybeDoOnStackReplacement # (self, shadow_frame, offset)
bnezc v0, MterpOnStackReplacement
FETCH_ADVANCE_INST 2
GET_INST_OPCODE v0 # extract opcode from rINST
GOTO_OPCODE v0 # jump to next instruction
/*
* On-stack replacement has happened, and now we've returned from the compiled method.
*/
MterpOnStackReplacement:
#if MTERP_LOGGING
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
move a2, rINST # rINST contains offset
jal MterpLogOSR
#endif
li v0, 1 # Signal normal return
b MterpDone
/*
* Bail out to reference interpreter.
*/
.extern MterpLogFallback
MterpFallback:
EXPORT_PC
#if MTERP_LOGGING
move a0, rSELF
daddu a1, rFP, OFF_FP_SHADOWFRAME
jal MterpLogFallback
#endif
MterpCommonFallback:
li v0, 0 # signal retry with reference interpreter.
b MterpDone
/*
* We pushed some registers on the stack in ExecuteMterpImpl, then saved
* SP and RA. Here we restore SP, restore the registers, and then restore
* RA to PC.
*
* On entry:
* uint32_t* rFP (should still be live, pointer to base of vregs)
*/
MterpExceptionReturn:
li v0, 1 # signal return to caller.
b MterpDone
/*
* Returned value is expected in a0 and if it's not 64-bit, the 32 most
* significant bits of a0 must be zero-extended or sign-extended
* depending on the return type.
*/
MterpReturn:
ld a2, OFF_FP_RESULT_REGISTER(rFP)
sd a0, 0(a2)
li v0, 1 # signal return to caller.
MterpDone:
/*
* At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're
* checking for OSR. If greater than zero, we might have unreported hotness to register
* (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE
* should only reach zero immediately after a hotness decrement, and is then reset to either
* a negative special state or the new non-zero countdown value.
*/
blez rPROFILE, .L_pop_and_return # if > 0, we may have some counts to report.
MterpProfileActive:
move rINST, v0 # stash return value
/* Report cached hotness counts */
ld a0, OFF_FP_METHOD(rFP)
daddu a1, rFP, OFF_FP_SHADOWFRAME
move a2, rSELF
sh rPROFILE, SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET(a1)
jal MterpAddHotnessBatch # (method, shadow_frame, self)
move v0, rINST # restore return value
.L_pop_and_return:
ld s6, STACK_OFFSET_S6(sp)
.cfi_restore 22
ld s5, STACK_OFFSET_S5(sp)
.cfi_restore 21
ld s4, STACK_OFFSET_S4(sp)
.cfi_restore 20
ld s3, STACK_OFFSET_S3(sp)
.cfi_restore 19
ld s2, STACK_OFFSET_S2(sp)
.cfi_restore 18
ld s1, STACK_OFFSET_S1(sp)
.cfi_restore 17
ld s0, STACK_OFFSET_S0(sp)
.cfi_restore 16
ld ra, STACK_OFFSET_RA(sp)
.cfi_restore 31
ld t8, STACK_OFFSET_GP(sp)
.cpreturn
.cfi_restore 28
.set noreorder
jr ra
daddu sp, sp, STACK_SIZE
.cfi_adjust_cfa_offset -STACK_SIZE
.cfi_endproc
.set reorder
.size ExecuteMterpImpl, .-ExecuteMterpImpl
|