ART: Improve JitProfiling perf in mips/mips64 mterp.
Change-Id: I4e1a214d92bd17ebd0a9b595e2eca2d7dcc13758
diff --git a/runtime/interpreter/mterp/mips/footer.S b/runtime/interpreter/mterp/mips/footer.S
index 083dc15..1363751 100644
--- a/runtime/interpreter/mterp/mips/footer.S
+++ b/runtime/interpreter/mterp/mips/footer.S
@@ -112,20 +112,110 @@
/* NOTE: no fallthrough */
/*
- * Check for suspend check request. Assumes rINST already loaded, rPC advanced and
- * still needs to get the opcode and branch to it, and flags are in lr.
+ * Common handling for branches with support for Jit profiling.
+ * On entry:
+ * rINST <= signed offset
+ * rPROFILE <= signed hotness countdown (expanded to 32 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.
*/
-MterpCheckSuspendAndContinue:
- lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh rIBASE
+MterpCommonTakenBranchNoFlags:
+ bgtz 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.
+ */
+#if JIT_CHECK_OSR != -1
+# error "JIT_CHECK_OSR must be -1."
+#endif
+ li t0, JIT_CHECK_OSR
+ beq rPROFILE, t0, .L_osr_check
+ blt rPROFILE, t0, .L_resume_backward_branch
+ subu rPROFILE, 1
+ beqz rPROFILE, .L_add_batch # counted down to zero - report
+.L_resume_backward_branch:
+ lw ra, THREAD_FLAGS_OFFSET(rSELF)
+ REFRESH_IBASE()
+ addu a2, rINST, rINST # a2<- byte offset
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
- bnez ra, 1f
+ bnez ra, .L_suspend_request_pending
GET_INST_OPCODE(t0) # extract opcode from rINST
GOTO_OPCODE(t0) # jump to next instruction
-1:
+
+.L_suspend_request_pending:
EXPORT_PC()
move a0, rSELF
JAL(MterpSuspendCheck) # (self)
bnez v0, MterpFallback
+ REFRESH_IBASE() # might have changed during suspend
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+.L_no_count_backwards:
+ li t0, JIT_CHECK_OSR # check for possible OSR re-entry
+ bne rPROFILE, t0, .L_resume_backward_branch
+.L_osr_check:
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ EXPORT_PC()
+ JAL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement
+ b .L_resume_backward_branch
+
+.L_forward_branch:
+ li t0, JIT_CHECK_OSR # check for possible OSR re-entry
+ beq rPROFILE, t0, .L_check_osr_forward
+.L_resume_forward_branch:
+ add a2, rINST, rINST # a2<- byte offset
+ FETCH_ADVANCE_INST_RB(a2) # update rPC, load rINST
+ GET_INST_OPCODE(t0) # extract opcode from rINST
+ GOTO_OPCODE(t0) # jump to next instruction
+
+.L_check_osr_forward:
+ move a0, rSELF
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ move a2, rINST
+ EXPORT_PC()
+ JAL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement
+ b .L_resume_forward_branch
+
+.L_add_batch:
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ sh rPROFILE, SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET(a1)
+ lw 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
+ addu a1, rFP, OFF_FP_SHADOWFRAME
+ li a2, 2
+ EXPORT_PC()
+ JAL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
+ bnez v0, MterpOnStackReplacement
+ FETCH_ADVANCE_INST(2)
GET_INST_OPCODE(t0) # extract opcode from rINST
GOTO_OPCODE(t0) # jump to next instruction
@@ -172,6 +262,26 @@
sw v1, 4(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 */
+ lw a0, OFF_FP_METHOD(rFP)
+ addu 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:
/* Restore from the stack and return. Frame size = STACK_SIZE */
STACK_LOAD_FULL()
jalr zero, ra