• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    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/*
115 * 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.
134 */
135MterpCommonTakenBranchNoFlags:
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
154    and     ra, THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
155    bnez    ra, .L_suspend_request_pending
156    GET_INST_OPCODE(t0)                 # extract opcode from rINST
157    GOTO_OPCODE(t0)                     # jump to next instruction
158
159.L_suspend_request_pending:
160    EXPORT_PC()
161    move    a0, rSELF
162    JAL(MterpSuspendCheck)              # (self)
163    bnez    v0, MterpFallback
164    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)
219    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:
265/*
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:
285/* Restore from the stack and return. Frame size = STACK_SIZE */
286    STACK_LOAD_FULL()
287    jalr    zero, ra
288
289    .end ExecuteMterpImpl
290