blob: 1363751566e1a8d2495b620a2a6a0db21c6fc633 [file] [log] [blame]
Douglas Leung200f0402016-02-25 20:05:47 -08001/*
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 move a0, rSELF
19 addu a1, rFP, OFF_FP_SHADOWFRAME
20 JAL(MterpLogDivideByZeroException)
21#endif
22 b MterpCommonFallback
23
24common_errArrayIndex:
25 EXPORT_PC()
26#if MTERP_LOGGING
27 move a0, rSELF
28 addu a1, rFP, OFF_FP_SHADOWFRAME
29 JAL(MterpLogArrayIndexException)
30#endif
31 b MterpCommonFallback
32
33common_errNegativeArraySize:
34 EXPORT_PC()
35#if MTERP_LOGGING
36 move a0, rSELF
37 addu a1, rFP, OFF_FP_SHADOWFRAME
38 JAL(MterpLogNegativeArraySizeException)
39#endif
40 b MterpCommonFallback
41
42common_errNoSuchMethod:
43 EXPORT_PC()
44#if MTERP_LOGGING
45 move a0, rSELF
46 addu a1, rFP, OFF_FP_SHADOWFRAME
47 JAL(MterpLogNoSuchMethodException)
48#endif
49 b MterpCommonFallback
50
51common_errNullObject:
52 EXPORT_PC()
53#if MTERP_LOGGING
54 move a0, rSELF
55 addu a1, rFP, OFF_FP_SHADOWFRAME
56 JAL(MterpLogNullObjectException)
57#endif
58 b MterpCommonFallback
59
60common_exceptionThrown:
61 EXPORT_PC()
62#if MTERP_LOGGING
63 move a0, rSELF
64 addu a1, rFP, OFF_FP_SHADOWFRAME
65 JAL(MterpLogExceptionThrownException)
66#endif
67 b MterpCommonFallback
68
69MterpSuspendFallback:
70 EXPORT_PC()
71#if MTERP_LOGGING
72 move a0, rSELF
73 addu a1, rFP, OFF_FP_SHADOWFRAME
74 lw a2, THREAD_FLAGS_OFFSET(rSELF)
75 JAL(MterpLogSuspendFallback)
76#endif
77 b 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 lw a0, THREAD_EXCEPTION_OFFSET(rSELF)
86 beqz a0, MterpFallback # If exception, fall back to reference interpreter.
87 /* intentional fallthrough - handle pending exception. */
88/*
89 * On return from a runtime helper routine, we've found a pending exception.
90 * Can we handle it here - or need to bail out to caller?
91 *
92 */
93MterpException:
94 move a0, rSELF
95 addu a1, rFP, OFF_FP_SHADOWFRAME
96 JAL(MterpHandleException) # (self, shadow_frame)
97 beqz v0, MterpExceptionReturn # no local catch, back to caller.
98 lw a0, OFF_FP_CODE_ITEM(rFP)
99 lw a1, OFF_FP_DEX_PC(rFP)
100 lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
101 addu rPC, a0, CODEITEM_INSNS_OFFSET
102 sll a1, a1, 1
103 addu rPC, rPC, a1 # generate new dex_pc_ptr
104 /* Do we need to switch interpreters? */
105 JAL(MterpShouldSwitchInterpreters)
106 bnez v0, MterpFallback
107 /* resume execution at catch block */
108 EXPORT_PC()
109 FETCH_INST()
110 GET_INST_OPCODE(t0)
111 GOTO_OPCODE(t0)
112 /* NOTE: no fallthrough */
113
114/*
Douglas Leung020b18a2016-06-03 18:05:35 -0700115 * Common handling for branches with support for Jit profiling.
116 * On entry:
117 * rINST <= signed offset
118 * rPROFILE <= signed hotness countdown (expanded to 32 bits)
119 *
120 * We have quite a few different cases for branch profiling, OSR detection and
121 * suspend check support here.
122 *
123 * Taken backward branches:
124 * If profiling active, do hotness countdown and report if we hit zero.
125 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
126 * Is there a pending suspend request? If so, suspend.
127 *
128 * Taken forward branches and not-taken backward branches:
129 * If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
130 *
131 * Our most common case is expected to be a taken backward branch with active jit profiling,
132 * but no full OSR check and no pending suspend request.
133 * Next most common case is not-taken branch with no full OSR check.
Douglas Leung200f0402016-02-25 20:05:47 -0800134 */
Douglas Leung020b18a2016-06-03 18:05:35 -0700135MterpCommonTakenBranchNoFlags:
136 bgtz rINST, .L_forward_branch # don't add forward branches to hotness
137/*
138 * We need to subtract 1 from positive values and we should not see 0 here,
139 * so we may use the result of the comparison with -1.
140 */
141#if JIT_CHECK_OSR != -1
142# error "JIT_CHECK_OSR must be -1."
143#endif
144 li t0, JIT_CHECK_OSR
145 beq rPROFILE, t0, .L_osr_check
146 blt rPROFILE, t0, .L_resume_backward_branch
147 subu rPROFILE, 1
148 beqz rPROFILE, .L_add_batch # counted down to zero - report
149.L_resume_backward_branch:
150 lw ra, THREAD_FLAGS_OFFSET(rSELF)
151 REFRESH_IBASE()
152 addu a2, rINST, rINST # a2<- byte offset
153 FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
Douglas Leung200f0402016-02-25 20:05:47 -0800154 and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
Douglas Leung020b18a2016-06-03 18:05:35 -0700155 bnez ra, .L_suspend_request_pending
Douglas Leung200f0402016-02-25 20:05:47 -0800156 GET_INST_OPCODE(t0) # extract opcode from rINST
157 GOTO_OPCODE(t0) # jump to next instruction
Douglas Leung020b18a2016-06-03 18:05:35 -0700158
159.L_suspend_request_pending:
Douglas Leung200f0402016-02-25 20:05:47 -0800160 EXPORT_PC()
161 move a0, rSELF
162 JAL(MterpSuspendCheck) # (self)
163 bnez v0, MterpFallback
Douglas Leung020b18a2016-06-03 18:05:35 -0700164 REFRESH_IBASE() # might have changed during suspend
165 GET_INST_OPCODE(t0) # extract opcode from rINST
166 GOTO_OPCODE(t0) # jump to next instruction
167
168.L_no_count_backwards:
169 li t0, JIT_CHECK_OSR # check for possible OSR re-entry
170 bne rPROFILE, t0, .L_resume_backward_branch
171.L_osr_check:
172 move a0, rSELF
173 addu a1, rFP, OFF_FP_SHADOWFRAME
174 move a2, rINST
175 EXPORT_PC()
176 JAL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
177 bnez v0, MterpOnStackReplacement
178 b .L_resume_backward_branch
179
180.L_forward_branch:
181 li t0, JIT_CHECK_OSR # check for possible OSR re-entry
182 beq rPROFILE, t0, .L_check_osr_forward
183.L_resume_forward_branch:
184 add a2, rINST, rINST # a2<- byte offset
185 FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
186 GET_INST_OPCODE(t0) # extract opcode from rINST
187 GOTO_OPCODE(t0) # jump to next instruction
188
189.L_check_osr_forward:
190 move a0, rSELF
191 addu a1, rFP, OFF_FP_SHADOWFRAME
192 move a2, rINST
193 EXPORT_PC()
194 JAL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
195 bnez v0, MterpOnStackReplacement
196 b .L_resume_forward_branch
197
198.L_add_batch:
199 addu a1, rFP, OFF_FP_SHADOWFRAME
200 sh rPROFILE, SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET(a1)
201 lw a0, OFF_FP_METHOD(rFP)
202 move a2, rSELF
203 JAL(MterpAddHotnessBatch) # (method, shadow_frame, self)
204 move rPROFILE, v0 # restore new hotness countdown to rPROFILE
205 b .L_no_count_backwards
206
207/*
208 * Entered from the conditional branch handlers when OSR check request active on
209 * not-taken path. All Dalvik not-taken conditional branch offsets are 2.
210 */
211.L_check_not_taken_osr:
212 move a0, rSELF
213 addu a1, rFP, OFF_FP_SHADOWFRAME
214 li a2, 2
215 EXPORT_PC()
216 JAL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
217 bnez v0, MterpOnStackReplacement
218 FETCH_ADVANCE_INST(2)
Douglas Leung200f0402016-02-25 20:05:47 -0800219 GET_INST_OPCODE(t0) # extract opcode from rINST
220 GOTO_OPCODE(t0) # jump to next instruction
221
222/*
223 * On-stack replacement has happened, and now we've returned from the compiled method.
224 */
225MterpOnStackReplacement:
226#if MTERP_LOGGING
227 move a0, rSELF
228 addu a1, rFP, OFF_FP_SHADOWFRAME
229 move a2, rINST
230 JAL(MterpLogOSR)
231#endif
232 li v0, 1 # Signal normal return
233 b MterpDone
234
235/*
236 * Bail out to reference interpreter.
237 */
238MterpFallback:
239 EXPORT_PC()
240#if MTERP_LOGGING
241 move a0, rSELF
242 addu a1, rFP, OFF_FP_SHADOWFRAME
243 JAL(MterpLogFallback)
244#endif
245MterpCommonFallback:
246 move v0, zero # signal retry with reference interpreter.
247 b MterpDone
248/*
249 * We pushed some registers on the stack in ExecuteMterpImpl, then saved
250 * SP and LR. Here we restore SP, restore the registers, and then restore
251 * LR to PC.
252 *
253 * On entry:
254 * uint32_t* rFP (should still be live, pointer to base of vregs)
255 */
256MterpExceptionReturn:
257 li v0, 1 # signal return to caller.
258 b MterpDone
259MterpReturn:
260 lw a2, OFF_FP_RESULT_REGISTER(rFP)
261 sw v0, 0(a2)
262 sw v1, 4(a2)
263 li v0, 1 # signal return to caller.
264MterpDone:
Douglas Leung020b18a2016-06-03 18:05:35 -0700265/*
266 * At this point, we expect rPROFILE to be non-zero. If negative, hotness is disabled or we're
267 * checking for OSR. If greater than zero, we might have unreported hotness to register
268 * (the difference between the ending rPROFILE and the cached hotness counter). rPROFILE
269 * should only reach zero immediately after a hotness decrement, and is then reset to either
270 * a negative special state or the new non-zero countdown value.
271 */
272 blez rPROFILE, .L_pop_and_return # if > 0, we may have some counts to report.
273
274MterpProfileActive:
275 move rINST, v0 # stash return value
276 /* Report cached hotness counts */
277 lw a0, OFF_FP_METHOD(rFP)
278 addu a1, rFP, OFF_FP_SHADOWFRAME
279 move a2, rSELF
280 sh rPROFILE, SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET(a1)
281 JAL(MterpAddHotnessBatch) # (method, shadow_frame, self)
282 move v0, rINST # restore return value
283
284.L_pop_and_return:
Douglas Leung200f0402016-02-25 20:05:47 -0800285/* Restore from the stack and return. Frame size = STACK_SIZE */
286 STACK_LOAD_FULL()
287 jalr zero, ra
288
289 .end ExecuteMterpImpl