summaryrefslogtreecommitdiffstats
path: root/vm/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler')
-rw-r--r--vm/compiler/Compiler.c31
-rw-r--r--vm/compiler/Compiler.h1
-rw-r--r--vm/compiler/Frontend.c5
-rw-r--r--vm/compiler/InlineTransformation.c4
-rw-r--r--vm/compiler/codegen/arm/Assemble.c20
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c32
-rw-r--r--vm/compiler/template/armv5te-vfp/TemplateOpList.h5
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S5
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S3
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S4
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S3
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S2
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S3
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S3
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S3
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_RETURN.S2
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_RETURN_PROF.S3
-rw-r--r--vm/compiler/template/armv5te/TemplateOpList.h5
-rw-r--r--vm/compiler/template/armv5te/footer.S15
-rw-r--r--vm/compiler/template/armv7-a-neon/TemplateOpList.h5
-rw-r--r--vm/compiler/template/armv7-a/TemplateOpList.h5
-rw-r--r--vm/compiler/template/config-armv5te-vfp5
-rw-r--r--vm/compiler/template/config-armv7-a5
-rw-r--r--vm/compiler/template/config-armv7-a-neon5
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S389
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv5te.S389
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S389
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S389
28 files changed, 1665 insertions, 65 deletions
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 886b1f11a..a1e3d0e8d 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -99,6 +99,7 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
newOrder->result.codeAddress = NULL;
newOrder->result.discardResult =
(kind == kWorkOrderTraceDebug) ? true : false;
+ newOrder->result.cacheVersion = gDvmJit.cacheVersion;
newOrder->result.requestingThread = dvmThreadSelf();
gDvmJit.compilerWorkEnqueueIndex++;
@@ -264,6 +265,9 @@ static void resetCodeCache(void)
/* Lock the mutex to clean up the work queue */
dvmLockMutex(&gDvmJit.compilerLock);
+ /* Update the translation cache version */
+ gDvmJit.cacheVersion++;
+
/* Drain the work queue to free the work orders */
while (workQueueLength()) {
CompilerWorkOrder work = workDequeue();
@@ -749,6 +753,33 @@ void dvmCompilerStateRefresh()
return;
}
+ /*
+ * On the first enabling of method tracing, switch the compiler
+ * into a mode that includes trace support for invokes and returns.
+ * If there are any existing translations, flush them. NOTE: we
+ * can't blindly flush the translation cache because this code
+ * may be executed before the compiler thread has finished
+ * initialization.
+ */
+ if ((gDvm.interpBreak & kSubModeMethodTrace) &&
+ !gDvmJit.methodTraceSupport) {
+ bool resetRequired;
+ /*
+ * compilerLock will prevent new compilations from being
+ * installed while we are working.
+ */
+ dvmLockMutex(&gDvmJit.compilerLock);
+ gDvmJit.cacheVersion++; // invalidate compilations in flight
+ gDvmJit.methodTraceSupport = true;
+ resetRequired = (gDvmJit.numCompilations != 0);
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ if (resetRequired) {
+ dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET);
+ resetCodeCache();
+ dvmResumeAllThreads(SUSPEND_FOR_CC_RESET);
+ }
+ }
+
dvmLockMutex(&gDvmJit.tableLock);
jitActive = gDvmJit.pProfTable != NULL;
jitActivate = !dvmDebuggerOrProfilerActive();
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index cd9d21bb3..d29520d2e 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -87,6 +87,7 @@ typedef struct JitTranslationInfo {
bool discardResult; // Used for debugging divergence and IC patching
bool methodCompilationAborted; // Cannot compile the whole method
Thread *requestingThread; // For debugging purpose
+ int cacheVersion; // Used to identify stale trace requests
} JitTranslationInfo;
typedef enum WorkOrderKind {
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index b4c48e4a3..1095225b3 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -449,6 +449,11 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
return true;
}
+ /* If the work order is stale, discard it */
+ if (info->cacheVersion != gDvmJit.cacheVersion) {
+ return false;
+ }
+
compilationId++;
memset(&cUnit, 0, sizeof(CompilationUnit));
diff --git a/vm/compiler/InlineTransformation.c b/vm/compiler/InlineTransformation.c
index 2cdba18cd..cab790cac 100644
--- a/vm/compiler/InlineTransformation.c
+++ b/vm/compiler/InlineTransformation.c
@@ -304,6 +304,10 @@ void dvmCompilerInlineMIR(CompilationUnit *cUnit)
if ((flags & kInstrInvoke) == 0)
continue;
+ /* Disable inlining when doing method tracing */
+ if (gDvmJit.methodTraceSupport)
+ continue;
+
/*
* If the invoke itself is selected for single stepping, don't bother
* to inline it.
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index e52c26c8c..aa6128593 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1326,6 +1326,22 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
/* Don't go all the way if the goal is just to get the verbose output */
if (info->discardResult) return;
+ /*
+ * The cache might disappear - acquire lock and check version
+ * Continue holding lock until translation cache update is complete.
+ * These actions are required here in the compiler thread because
+ * it is unaffected by suspend requests and doesn't know if a
+ * translation cache flush is in progress.
+ */
+ dvmLockMutex(&gDvmJit.compilerLock);
+ if (info->cacheVersion != gDvmJit.cacheVersion) {
+ /* Cache changed - discard current translation */
+ info->discardResult = true;
+ info->codeAddress = NULL;
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ return;
+ }
+
cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
gDvmJit.codeCacheByteUsed += offset;
@@ -1353,6 +1369,7 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
/* Write the literals directly into the code cache */
installDataContent(cUnit);
+
/* Flush dcache and invalidate the icache to maintain coherence */
dvmCompilerCacheFlush((long)cUnit->baseAddr,
(long)((char *) cUnit->baseAddr + offset), 0);
@@ -1360,6 +1377,9 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
PROTECT_CODE_CACHE(cUnit->baseAddr, offset);
+ /* Translation cache update complete - release lock */
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+
/* Record code entry point and instruction set */
info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
/* If applicable, mark low bit to denote thumb */
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 236482f39..7f62816f3 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -904,7 +904,9 @@ static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
/* Perform the actual operation for OP_RETURN_* */
static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
{
- genDispatchToHandler(cUnit, TEMPLATE_RETURN);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_RETURN_PROF :
+ TEMPLATE_RETURN);
#if defined(WITH_JIT_TUNING)
gDvmJit.returnOp++;
#endif
@@ -1082,14 +1084,18 @@ static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
* r7 = calleeMethod->registersSize
*/
if (dvmIsNativeMethod(calleeMethod)) {
- genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_INVOKE_METHOD_NATIVE_PROF :
+ TEMPLATE_INVOKE_METHOD_NATIVE);
#if defined(WITH_JIT_TUNING)
gDvmJit.invokeNative++;
#endif
} else {
/* For Java callees, set up r2 to be calleeMethod->outsSize */
loadConstant(cUnit, r2, calleeMethod->outsSize);
- genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_INVOKE_METHOD_CHAIN_PROF :
+ TEMPLATE_INVOKE_METHOD_CHAIN);
#if defined(WITH_JIT_TUNING)
gDvmJit.invokeMonomorphic++;
#endif
@@ -1148,7 +1154,9 @@ static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
ArmLIR *predictedChainingCell = opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
predictedChainingCell->generic.target = (LIR *) predChainingCell;
- genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF :
+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
/* return through lr - jump to the chaining cell */
genUnconditionalBranch(cUnit, predChainingCell);
@@ -1211,7 +1219,9 @@ static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
* r1 = &ChainingCell,
* r4PC = callsiteDPC,
*/
- genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_INVOKE_METHOD_NO_OPT_PROF :
+ TEMPLATE_INVOKE_METHOD_NO_OPT);
#if defined(WITH_JIT_TUNING)
gDvmJit.invokePolymorphic++;
#endif
@@ -3053,7 +3063,9 @@ static bool handleFmt35c_3rc_5rc(CompilationUnit *cUnit, MIR *mir,
opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
predictedChainingCell->generic.target = (LIR *) predChainingCell;
- genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF :
+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
/* return through lr - jump to the chaining cell */
genUnconditionalBranch(cUnit, predChainingCell);
@@ -3156,7 +3168,9 @@ static bool handleFmt35c_3rc_5rc(CompilationUnit *cUnit, MIR *mir,
* r1 = &ChainingCell,
* r4PC = callsiteDPC,
*/
- genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
+ genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
+ TEMPLATE_INVOKE_METHOD_NO_OPT_PROF :
+ TEMPLATE_INVOKE_METHOD_NO_OPT);
#if defined(WITH_JIT_TUNING)
gDvmJit.invokePolymorphic++;
#endif
@@ -3166,7 +3180,9 @@ static bool handleFmt35c_3rc_5rc(CompilationUnit *cUnit, MIR *mir,
}
/* NOP */
case OP_INVOKE_DIRECT_EMPTY: {
- return false;
+ if (gDvmJit.methodTraceSupport)
+ genInterpSingleStep(cUnit, mir);
+ break;
}
case OP_FILLED_NEW_ARRAY:
case OP_FILLED_NEW_ARRAY_RANGE:
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index 97addfaf8..0365ba4d2 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -58,3 +58,8 @@ JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
JIT_TEMPLATE(PERIODIC_PROFILING)
+JIT_TEMPLATE(RETURN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE_PROF)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
index f1650d939..b6a8540ab 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
@@ -1,3 +1,4 @@
+%default { "chaintgt" : ".LinvokeChain" }
/*
* For monomorphic callsite, setup the Dalvik frame and return to the
* Thumb code through the link register to transfer control to the callee
@@ -6,7 +7,7 @@
@ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
@ rPC = dalvikCallsite, r7 = methodToCall->registersSize
@ methodToCall is guaranteed to be non-native
-.LinvokeChain:
+$chaintgt:
ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
add r3, r1, #1 @ Thumb addr is odd
@@ -38,7 +39,7 @@
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@ r0=methodToCall, r1=rGlue
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S
new file mode 100644
index 000000000..d1be4fdf7
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S
@@ -0,0 +1,3 @@
+#define TEMPLATE_INLINE_PROFILING
+%include "armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S" { "chaintgt" : ".LinvokeChainProf" }
+#undef TEMPLATE_INLINE_PROFILING
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
index 2a22a224e..c3390edb8 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
@@ -39,7 +39,7 @@
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
@ r2=methodToCall, r6=rGLUE
stmfd sp!, {r2,r6} @ to be consumed after JNI return
stmfd sp!, {r0-r3} @ preserve r0-r3
@@ -53,7 +53,7 @@
blx r8 @ off to the native code
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
ldmfd sp!, {r0-r1} @ restore r2 and r6
@ r0=JNIMethod, r1=rGlue
mov lr, pc
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S
new file mode 100644
index 000000000..816277ac3
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S
@@ -0,0 +1,3 @@
+#define TEMPLATE_INLINE_PROFILING
+%include "armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S"
+#undef TEMPLATE_INLINE_PROFILING
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
index 405065f22..72fe91005 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
@@ -46,7 +46,7 @@
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S
new file mode 100644
index 000000000..bfea7d915
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S
@@ -0,0 +1,3 @@
+#define TEMPLATE_INLINE_PROFILING
+%include "armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S"
+#undef TEMPLATE_INLINE_PROFILING
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
index 65b2cc30a..6bce7bff9 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
@@ -1,3 +1,4 @@
+%default { "chaintgt" : ".LinvokeChain" }
/*
* For polymorphic callsite, check whether the cached class pointer matches
* the current one. If so setup the Dalvik frame and return to the
@@ -42,7 +43,7 @@
#endif
ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
- beq .LinvokeChain @ predicted chain is valid
+ beq $chaintgt @ predicted chain is valid
ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
cmp r8, #0 @ initialized class or not
moveq r1, #0
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S
new file mode 100644
index 000000000..6ca5bddb9
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S
@@ -0,0 +1,3 @@
+#define TEMPLATE_INLINE_PROFILING
+%include "armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S" { "chaintgt" : ".LinvokeChainProf" }
+#undef TEMPLATE_INLINE_PROFILING
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
index 564b84462..d0bbbfc05 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
@@ -5,7 +5,7 @@
* address in the code cache following the invoke instruction. Otherwise
* return to the special dvmJitToInterpNoChain entry point.
*/
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve live registers
mov r0, r6
@ r0=rGlue
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN_PROF.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN_PROF.S
new file mode 100644
index 000000000..d7af0bd1f
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN_PROF.S
@@ -0,0 +1,3 @@
+#define TEMPLATE_INLINE_PROFILING
+%include "armv5te/TEMPLATE_RETURN.S"
+#undef TEMPLATE_INLINE_PROFILING
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index 663e0df68..abfec4b9f 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -43,3 +43,8 @@ JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
JIT_TEMPLATE(PERIODIC_PROFILING)
+JIT_TEMPLATE(RETURN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE_PROF)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 7b35e8a1c..0a4e92d81 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -17,12 +17,15 @@
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
mov r9, r3 @ r9<- glue->self (preserve)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
+ ldr lr, [lr] @ lr<- set of active profilers
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace
+ beq 121f @ hop if not profiling
@ r2: methodToCall, r6: rGLUE
stmfd sp!, {r2,r6}
stmfd sp!, {r0-r3}
@@ -31,16 +34,18 @@
mov lr, pc
ldr pc, .LdvmFastMethodTraceEnter
ldmfd sp!, {r0-r3}
-#endif
mov lr, pc
ldr pc, [r2, #offMethod_nativeFunc]
-#if defined(WITH_INLINE_PROFILING)
ldmfd sp!, {r0-r1}
mov lr, pc
ldr pc, .LdvmFastNativeMethodTraceExit
-#endif
+ b 212f
+121:
+ mov lr, pc
+ ldr pc, [r2, #offMethod_nativeFunc]
+212:
@ Refresh Jit's on/off status
ldr r3, [rGLUE, #offGlue_ppJitProfTable]
@@ -114,14 +119,12 @@
.LdvmSelfVerificationMemOpDecode:
.word dvmSelfVerificationMemOpDecode
#endif
-#if defined(WITH_INLINE_PROFILING)
.LdvmFastMethodTraceEnter:
.word dvmFastMethodTraceEnter
.LdvmFastNativeMethodTraceExit:
.word dvmFastNativeMethodTraceExit
.LdvmFastJavaMethodTraceExit:
.word dvmFastJavaMethodTraceExit
-#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/armv7-a-neon/TemplateOpList.h b/vm/compiler/template/armv7-a-neon/TemplateOpList.h
index 97addfaf8..0365ba4d2 100644
--- a/vm/compiler/template/armv7-a-neon/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a-neon/TemplateOpList.h
@@ -58,3 +58,8 @@ JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
JIT_TEMPLATE(PERIODIC_PROFILING)
+JIT_TEMPLATE(RETURN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE_PROF)
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index 97addfaf8..0365ba4d2 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -58,3 +58,8 @@ JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
JIT_TEMPLATE(PERIODIC_PROFILING)
+JIT_TEMPLATE(RETURN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN_PROF)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE_PROF)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index 30b9200a8..774bd96cb 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -49,6 +49,11 @@ op-start armv5te-vfp
op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
op TEMPLATE_PERIODIC_PROFILING armv5te
+ op TEMPLATE_INVOKE_METHOD_CHAIN_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_NATIVE_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_NO_OPT_PROF armv5te
+ op TEMPLATE_RETURN_PROF armv5te
op-end
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index 1408ca117..9d66e55df 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -49,6 +49,11 @@ op-start armv5te-vfp
op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
op TEMPLATE_PERIODIC_PROFILING armv5te
+ op TEMPLATE_INVOKE_METHOD_CHAIN_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_NATIVE_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_NO_OPT_PROF armv5te
+ op TEMPLATE_RETURN_PROF armv5te
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/compiler/template/config-armv7-a-neon b/vm/compiler/template/config-armv7-a-neon
index 1408ca117..9d66e55df 100644
--- a/vm/compiler/template/config-armv7-a-neon
+++ b/vm/compiler/template/config-armv7-a-neon
@@ -49,6 +49,11 @@ op-start armv5te-vfp
op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
op TEMPLATE_PERIODIC_PROFILING armv5te
+ op TEMPLATE_INVOKE_METHOD_CHAIN_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_NATIVE_PROF armv5te
+ op TEMPLATE_INVOKE_METHOD_NO_OPT_PROF armv5te
+ op TEMPLATE_RETURN_PROF armv5te
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index a107b24de..cd530960d 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -166,7 +166,7 @@ dvmCompiler_TEMPLATE_RETURN:
* address in the code cache following the invoke instruction. Otherwise
* return to the special dvmJitToInterpNoChain entry point.
*/
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve live registers
mov r0, r6
@ r0=rGlue
@@ -271,7 +271,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -331,7 +331,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -453,7 +453,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
@ r2=methodToCall, r6=rGLUE
stmfd sp!, {r2,r6} @ to be consumed after JNI return
stmfd sp!, {r0-r3} @ preserve r0-r3
@@ -467,7 +467,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
blx r8 @ off to the native code
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
ldmfd sp!, {r0-r1} @ restore r2 and r6
@ r0=JNIMethod, r1=rGlue
mov lr, pc
@@ -1505,6 +1505,370 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
blx r0
bx r4
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_RETURN_PROF
+dvmCompiler_TEMPLATE_RETURN_PROF:
+/* File: armv5te/TEMPLATE_RETURN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_RETURN.S */
+ /*
+ * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+ * If the stored value in returnAddr
+ * is non-zero, the caller is compiled by the JIT thus return to the
+ * address in the code cache following the invoke instruction. Otherwise
+ * return to the special dvmJitToInterpNoChain entry point.
+ */
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve live registers
+ mov r0, r6
+ @ r0=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastJavaMethodTraceExit
+ ldmfd sp!, {r0-r2,lr} @ restore live registers
+#endif
+ SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+ ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
+ ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
+ ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ @ r2<- method we're returning to
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
+ beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
+ ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
+ mov rFP, r10 @ publish new FP
+ ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+ ldr r8, [r8] @ r8<- suspendCount
+
+ str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+ ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
+ str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+ add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
+ str r0, [rGLUE, #offGlue_methodClassDex]
+ cmp r8, #0 @ check the suspendCount
+ movne r9, #0 @ clear the chaining cell address
+ str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
+ cmp r9, #0 @ chaining cell exists?
+ blxne r9 @ jump to the chaining cell
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1 @ callsite is interpreted
+1:
+ stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
+ ldr r2, .LdvmMterpStdBail @ defined in footer.S
+ mov r1, #0 @ changeInterp = false
+ mov r0, rGLUE @ Expecting rGLUE in r0
+ blx r2 @ exit the interpreter
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+ /*
+ * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+ * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+ * runtime-resolved callee.
+ */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+ ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
+
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne lr @ bail to the interpreter
+ tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
+ bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
+
+ ldr r10, .LdvmJitToInterpTraceSelectNoChain
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ @ Start executing the callee
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kInlineCacheMiss
+#endif
+ mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+ /*
+ * For monomorphic callsite, setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ */
+ @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
+ @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
+ @ methodToCall is guaranteed to be non-native
+.LinvokeChainProf:
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ add r12, lr, #2 @ setup the punt-to-interp address
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo r12 @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne r12 @ bail to the interpreter
+
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r2,lr} @ restore registers
+#endif
+
+ bx lr @ return to the callee-chaining cell
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+ /*
+ * For polymorphic callsite, check whether the cached class pointer matches
+ * the current one. If so setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ *
+ * The predicted chaining cell is declared in ArmLIR.h with the
+ * following layout:
+ *
+ * typedef struct PredictedChainingCell {
+ * u4 branch;
+ * const ClassObject *clazz;
+ * const Method *method;
+ * u4 counter;
+ * } PredictedChainingCell;
+ *
+ * Upon returning to the callsite:
+ * - lr : to branch to the chaining cell
+ * - lr+2: to punt to the interpreter
+ * - lr+4: to fully resolve the callee and may rechain.
+ * r3 <- class
+ * r9 <- counter
+ */
+ @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+ ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
+ ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
+ ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
+ ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount
+ cmp r3, r8 @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+ ldr r7, .LdvmICHitCount
+#if defined(WORKAROUND_CORTEX_A9_745320)
+ /* Don't use conditional loads if the HW defect exists */
+ bne 101f
+ ldr r10, [r7, #0]
+101:
+#else
+ ldreq r10, [r7, #0]
+#endif
+ add r10, r10, #1
+ streq r10, [r7, #0]
+#endif
+ ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ beq .LinvokeChainProf @ predicted chain is valid
+ ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+ cmp r8, #0 @ initialized class or not
+ moveq r1, #0
+ subne r1, r9, #1 @ count--
+ strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState
+ add lr, lr, #4 @ return to fully-resolve landing pad
+ /*
+ * r1 <- count
+ * r2 <- &predictedChainCell
+ * r3 <- this->class
+ * r4 <- dPC
+ * r7 <- this->class->vtable
+ */
+ bx lr
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ @ r7 = methodToCall->registersSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ ldr r8, [r8] @ r3<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
+ bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
+
+ @ go ahead and transfer control to the native code
+ ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+ mov r2, #0
+ str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
+ str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
+ str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+ @ newFp->localRefCookie=top
+ mov r9, r3 @ r9<- glue->self (preserve)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
+
+ mov r2, r0 @ r2<- methodToCall
+ mov r0, r1 @ r0<- newFP
+ add r1, rGLUE, #offGlue_retval @ r1<- &retval
+#if defined(TEMPLATE_INLINE_PROFILING)
+ @ r2=methodToCall, r6=rGLUE
+ stmfd sp!, {r2,r6} @ to be consumed after JNI return
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r0, r2
+ mov r1, r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ blx r8 @ off to the native code
+
+#if defined(TEMPLATE_INLINE_PROFILING)
+ ldmfd sp!, {r0-r1} @ restore r2 and r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastNativeMethodTraceExit
+#endif
+ @ native return; r9=self, r10=newSaveArea
+ @ equivalent to dvmPopJniLocals
+ ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+ ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+ ldr r1, [r9, #offThread_exception] @ check for exception
+ str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
+ cmp r1, #0 @ null?
+ str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+
+ @ r0 = dalvikCallsitePC
+ bne .LhandleException @ no, handle exception
+
+ str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
+ cmp r2, #0 @ return chaining cell still exists?
+ bxne r2 @ yes - go ahead
+
+ @ continue executing the next instruction through the interpreter
+ ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
+ add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1
+
+#undef TEMPLATE_INLINE_PROFILING
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1526,12 +1890,15 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
mov r9, r3 @ r9<- glue->self (preserve)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
+ ldr lr, [lr] @ lr<- set of active profilers
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace
+ beq 121f @ hop if not profiling
@ r2: methodToCall, r6: rGLUE
stmfd sp!, {r2,r6}
stmfd sp!, {r0-r3}
@@ -1540,16 +1907,18 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
mov lr, pc
ldr pc, .LdvmFastMethodTraceEnter
ldmfd sp!, {r0-r3}
-#endif
mov lr, pc
ldr pc, [r2, #offMethod_nativeFunc]
-#if defined(WITH_INLINE_PROFILING)
ldmfd sp!, {r0-r1}
mov lr, pc
ldr pc, .LdvmFastNativeMethodTraceExit
-#endif
+ b 212f
+121:
+ mov lr, pc
+ ldr pc, [r2, #offMethod_nativeFunc]
+212:
@ Refresh Jit's on/off status
ldr r3, [rGLUE, #offGlue_ppJitProfTable]
@@ -1623,14 +1992,12 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
.LdvmSelfVerificationMemOpDecode:
.word dvmSelfVerificationMemOpDecode
#endif
-#if defined(WITH_INLINE_PROFILING)
.LdvmFastMethodTraceEnter:
.word dvmFastMethodTraceEnter
.LdvmFastNativeMethodTraceExit:
.word dvmFastNativeMethodTraceExit
.LdvmFastJavaMethodTraceExit:
.word dvmFastJavaMethodTraceExit
-#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index a6a0e9ff8..57d0aff9a 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -166,7 +166,7 @@ dvmCompiler_TEMPLATE_RETURN:
* address in the code cache following the invoke instruction. Otherwise
* return to the special dvmJitToInterpNoChain entry point.
*/
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve live registers
mov r0, r6
@ r0=rGlue
@@ -271,7 +271,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -331,7 +331,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -453,7 +453,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
@ r2=methodToCall, r6=rGLUE
stmfd sp!, {r2,r6} @ to be consumed after JNI return
stmfd sp!, {r0-r3} @ preserve r0-r3
@@ -467,7 +467,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
blx r8 @ off to the native code
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
ldmfd sp!, {r0-r1} @ restore r2 and r6
@ r0=JNIMethod, r1=rGlue
mov lr, pc
@@ -1236,6 +1236,370 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
blx r0
bx r4
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_RETURN_PROF
+dvmCompiler_TEMPLATE_RETURN_PROF:
+/* File: armv5te/TEMPLATE_RETURN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_RETURN.S */
+ /*
+ * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+ * If the stored value in returnAddr
+ * is non-zero, the caller is compiled by the JIT thus return to the
+ * address in the code cache following the invoke instruction. Otherwise
+ * return to the special dvmJitToInterpNoChain entry point.
+ */
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve live registers
+ mov r0, r6
+ @ r0=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastJavaMethodTraceExit
+ ldmfd sp!, {r0-r2,lr} @ restore live registers
+#endif
+ SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+ ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
+ ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
+ ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ @ r2<- method we're returning to
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
+ beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
+ ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
+ mov rFP, r10 @ publish new FP
+ ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+ ldr r8, [r8] @ r8<- suspendCount
+
+ str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+ ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
+ str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+ add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
+ str r0, [rGLUE, #offGlue_methodClassDex]
+ cmp r8, #0 @ check the suspendCount
+ movne r9, #0 @ clear the chaining cell address
+ str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
+ cmp r9, #0 @ chaining cell exists?
+ blxne r9 @ jump to the chaining cell
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1 @ callsite is interpreted
+1:
+ stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
+ ldr r2, .LdvmMterpStdBail @ defined in footer.S
+ mov r1, #0 @ changeInterp = false
+ mov r0, rGLUE @ Expecting rGLUE in r0
+ blx r2 @ exit the interpreter
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+ /*
+ * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+ * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+ * runtime-resolved callee.
+ */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+ ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
+
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne lr @ bail to the interpreter
+ tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
+ bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
+
+ ldr r10, .LdvmJitToInterpTraceSelectNoChain
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ @ Start executing the callee
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kInlineCacheMiss
+#endif
+ mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+ /*
+ * For monomorphic callsite, setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ */
+ @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
+ @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
+ @ methodToCall is guaranteed to be non-native
+.LinvokeChainProf:
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ add r12, lr, #2 @ setup the punt-to-interp address
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo r12 @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne r12 @ bail to the interpreter
+
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r2,lr} @ restore registers
+#endif
+
+ bx lr @ return to the callee-chaining cell
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+ /*
+ * For polymorphic callsite, check whether the cached class pointer matches
+ * the current one. If so setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ *
+ * The predicted chaining cell is declared in ArmLIR.h with the
+ * following layout:
+ *
+ * typedef struct PredictedChainingCell {
+ * u4 branch;
+ * const ClassObject *clazz;
+ * const Method *method;
+ * u4 counter;
+ * } PredictedChainingCell;
+ *
+ * Upon returning to the callsite:
+ * - lr : to branch to the chaining cell
+ * - lr+2: to punt to the interpreter
+ * - lr+4: to fully resolve the callee and may rechain.
+ * r3 <- class
+ * r9 <- counter
+ */
+ @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+ ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
+ ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
+ ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
+ ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount
+ cmp r3, r8 @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+ ldr r7, .LdvmICHitCount
+#if defined(WORKAROUND_CORTEX_A9_745320)
+ /* Don't use conditional loads if the HW defect exists */
+ bne 101f
+ ldr r10, [r7, #0]
+101:
+#else
+ ldreq r10, [r7, #0]
+#endif
+ add r10, r10, #1
+ streq r10, [r7, #0]
+#endif
+ ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ beq .LinvokeChainProf @ predicted chain is valid
+ ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+ cmp r8, #0 @ initialized class or not
+ moveq r1, #0
+ subne r1, r9, #1 @ count--
+ strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState
+ add lr, lr, #4 @ return to fully-resolve landing pad
+ /*
+ * r1 <- count
+ * r2 <- &predictedChainCell
+ * r3 <- this->class
+ * r4 <- dPC
+ * r7 <- this->class->vtable
+ */
+ bx lr
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ @ r7 = methodToCall->registersSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ ldr r8, [r8] @ r3<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
+ bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
+
+ @ go ahead and transfer control to the native code
+ ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+ mov r2, #0
+ str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
+ str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
+ str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+ @ newFp->localRefCookie=top
+ mov r9, r3 @ r9<- glue->self (preserve)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
+
+ mov r2, r0 @ r2<- methodToCall
+ mov r0, r1 @ r0<- newFP
+ add r1, rGLUE, #offGlue_retval @ r1<- &retval
+#if defined(TEMPLATE_INLINE_PROFILING)
+ @ r2=methodToCall, r6=rGLUE
+ stmfd sp!, {r2,r6} @ to be consumed after JNI return
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r0, r2
+ mov r1, r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ blx r8 @ off to the native code
+
+#if defined(TEMPLATE_INLINE_PROFILING)
+ ldmfd sp!, {r0-r1} @ restore r2 and r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastNativeMethodTraceExit
+#endif
+ @ native return; r9=self, r10=newSaveArea
+ @ equivalent to dvmPopJniLocals
+ ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+ ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+ ldr r1, [r9, #offThread_exception] @ check for exception
+ str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
+ cmp r1, #0 @ null?
+ str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+
+ @ r0 = dalvikCallsitePC
+ bne .LhandleException @ no, handle exception
+
+ str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
+ cmp r2, #0 @ return chaining cell still exists?
+ bxne r2 @ yes - go ahead
+
+ @ continue executing the next instruction through the interpreter
+ ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
+ add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1
+
+#undef TEMPLATE_INLINE_PROFILING
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1257,12 +1621,15 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
mov r9, r3 @ r9<- glue->self (preserve)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
+ ldr lr, [lr] @ lr<- set of active profilers
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace
+ beq 121f @ hop if not profiling
@ r2: methodToCall, r6: rGLUE
stmfd sp!, {r2,r6}
stmfd sp!, {r0-r3}
@@ -1271,16 +1638,18 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
mov lr, pc
ldr pc, .LdvmFastMethodTraceEnter
ldmfd sp!, {r0-r3}
-#endif
mov lr, pc
ldr pc, [r2, #offMethod_nativeFunc]
-#if defined(WITH_INLINE_PROFILING)
ldmfd sp!, {r0-r1}
mov lr, pc
ldr pc, .LdvmFastNativeMethodTraceExit
-#endif
+ b 212f
+121:
+ mov lr, pc
+ ldr pc, [r2, #offMethod_nativeFunc]
+212:
@ Refresh Jit's on/off status
ldr r3, [rGLUE, #offGlue_ppJitProfTable]
@@ -1354,14 +1723,12 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
.LdvmSelfVerificationMemOpDecode:
.word dvmSelfVerificationMemOpDecode
#endif
-#if defined(WITH_INLINE_PROFILING)
.LdvmFastMethodTraceEnter:
.word dvmFastMethodTraceEnter
.LdvmFastNativeMethodTraceExit:
.word dvmFastNativeMethodTraceExit
.LdvmFastJavaMethodTraceExit:
.word dvmFastJavaMethodTraceExit
-#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
index e4ed30bef..10541d39a 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
@@ -166,7 +166,7 @@ dvmCompiler_TEMPLATE_RETURN:
* address in the code cache following the invoke instruction. Otherwise
* return to the special dvmJitToInterpNoChain entry point.
*/
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve live registers
mov r0, r6
@ r0=rGlue
@@ -271,7 +271,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -331,7 +331,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -453,7 +453,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
@ r2=methodToCall, r6=rGLUE
stmfd sp!, {r2,r6} @ to be consumed after JNI return
stmfd sp!, {r0-r3} @ preserve r0-r3
@@ -467,7 +467,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
blx r8 @ off to the native code
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
ldmfd sp!, {r0-r1} @ restore r2 and r6
@ r0=JNIMethod, r1=rGlue
mov lr, pc
@@ -1505,6 +1505,370 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
blx r0
bx r4
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_RETURN_PROF
+dvmCompiler_TEMPLATE_RETURN_PROF:
+/* File: armv5te/TEMPLATE_RETURN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_RETURN.S */
+ /*
+ * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+ * If the stored value in returnAddr
+ * is non-zero, the caller is compiled by the JIT thus return to the
+ * address in the code cache following the invoke instruction. Otherwise
+ * return to the special dvmJitToInterpNoChain entry point.
+ */
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve live registers
+ mov r0, r6
+ @ r0=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastJavaMethodTraceExit
+ ldmfd sp!, {r0-r2,lr} @ restore live registers
+#endif
+ SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+ ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
+ ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
+ ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ @ r2<- method we're returning to
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
+ beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
+ ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
+ mov rFP, r10 @ publish new FP
+ ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+ ldr r8, [r8] @ r8<- suspendCount
+
+ str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+ ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
+ str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+ add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
+ str r0, [rGLUE, #offGlue_methodClassDex]
+ cmp r8, #0 @ check the suspendCount
+ movne r9, #0 @ clear the chaining cell address
+ str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
+ cmp r9, #0 @ chaining cell exists?
+ blxne r9 @ jump to the chaining cell
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1 @ callsite is interpreted
+1:
+ stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
+ ldr r2, .LdvmMterpStdBail @ defined in footer.S
+ mov r1, #0 @ changeInterp = false
+ mov r0, rGLUE @ Expecting rGLUE in r0
+ blx r2 @ exit the interpreter
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+ /*
+ * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+ * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+ * runtime-resolved callee.
+ */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+ ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
+
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne lr @ bail to the interpreter
+ tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
+ bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
+
+ ldr r10, .LdvmJitToInterpTraceSelectNoChain
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ @ Start executing the callee
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kInlineCacheMiss
+#endif
+ mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+ /*
+ * For monomorphic callsite, setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ */
+ @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
+ @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
+ @ methodToCall is guaranteed to be non-native
+.LinvokeChainProf:
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ add r12, lr, #2 @ setup the punt-to-interp address
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo r12 @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne r12 @ bail to the interpreter
+
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r2,lr} @ restore registers
+#endif
+
+ bx lr @ return to the callee-chaining cell
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+ /*
+ * For polymorphic callsite, check whether the cached class pointer matches
+ * the current one. If so setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ *
+ * The predicted chaining cell is declared in ArmLIR.h with the
+ * following layout:
+ *
+ * typedef struct PredictedChainingCell {
+ * u4 branch;
+ * const ClassObject *clazz;
+ * const Method *method;
+ * u4 counter;
+ * } PredictedChainingCell;
+ *
+ * Upon returning to the callsite:
+ * - lr : to branch to the chaining cell
+ * - lr+2: to punt to the interpreter
+ * - lr+4: to fully resolve the callee and may rechain.
+ * r3 <- class
+ * r9 <- counter
+ */
+ @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+ ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
+ ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
+ ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
+ ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount
+ cmp r3, r8 @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+ ldr r7, .LdvmICHitCount
+#if defined(WORKAROUND_CORTEX_A9_745320)
+ /* Don't use conditional loads if the HW defect exists */
+ bne 101f
+ ldr r10, [r7, #0]
+101:
+#else
+ ldreq r10, [r7, #0]
+#endif
+ add r10, r10, #1
+ streq r10, [r7, #0]
+#endif
+ ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ beq .LinvokeChainProf @ predicted chain is valid
+ ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+ cmp r8, #0 @ initialized class or not
+ moveq r1, #0
+ subne r1, r9, #1 @ count--
+ strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState
+ add lr, lr, #4 @ return to fully-resolve landing pad
+ /*
+ * r1 <- count
+ * r2 <- &predictedChainCell
+ * r3 <- this->class
+ * r4 <- dPC
+ * r7 <- this->class->vtable
+ */
+ bx lr
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ @ r7 = methodToCall->registersSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ ldr r8, [r8] @ r3<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
+ bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
+
+ @ go ahead and transfer control to the native code
+ ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+ mov r2, #0
+ str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
+ str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
+ str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+ @ newFp->localRefCookie=top
+ mov r9, r3 @ r9<- glue->self (preserve)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
+
+ mov r2, r0 @ r2<- methodToCall
+ mov r0, r1 @ r0<- newFP
+ add r1, rGLUE, #offGlue_retval @ r1<- &retval
+#if defined(TEMPLATE_INLINE_PROFILING)
+ @ r2=methodToCall, r6=rGLUE
+ stmfd sp!, {r2,r6} @ to be consumed after JNI return
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r0, r2
+ mov r1, r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ blx r8 @ off to the native code
+
+#if defined(TEMPLATE_INLINE_PROFILING)
+ ldmfd sp!, {r0-r1} @ restore r2 and r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastNativeMethodTraceExit
+#endif
+ @ native return; r9=self, r10=newSaveArea
+ @ equivalent to dvmPopJniLocals
+ ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+ ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+ ldr r1, [r9, #offThread_exception] @ check for exception
+ str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
+ cmp r1, #0 @ null?
+ str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+
+ @ r0 = dalvikCallsitePC
+ bne .LhandleException @ no, handle exception
+
+ str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
+ cmp r2, #0 @ return chaining cell still exists?
+ bxne r2 @ yes - go ahead
+
+ @ continue executing the next instruction through the interpreter
+ ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
+ add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1
+
+#undef TEMPLATE_INLINE_PROFILING
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1526,12 +1890,15 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
mov r9, r3 @ r9<- glue->self (preserve)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
+ ldr lr, [lr] @ lr<- set of active profilers
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace
+ beq 121f @ hop if not profiling
@ r2: methodToCall, r6: rGLUE
stmfd sp!, {r2,r6}
stmfd sp!, {r0-r3}
@@ -1540,16 +1907,18 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
mov lr, pc
ldr pc, .LdvmFastMethodTraceEnter
ldmfd sp!, {r0-r3}
-#endif
mov lr, pc
ldr pc, [r2, #offMethod_nativeFunc]
-#if defined(WITH_INLINE_PROFILING)
ldmfd sp!, {r0-r1}
mov lr, pc
ldr pc, .LdvmFastNativeMethodTraceExit
-#endif
+ b 212f
+121:
+ mov lr, pc
+ ldr pc, [r2, #offMethod_nativeFunc]
+212:
@ Refresh Jit's on/off status
ldr r3, [rGLUE, #offGlue_ppJitProfTable]
@@ -1623,14 +1992,12 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
.LdvmSelfVerificationMemOpDecode:
.word dvmSelfVerificationMemOpDecode
#endif
-#if defined(WITH_INLINE_PROFILING)
.LdvmFastMethodTraceEnter:
.word dvmFastMethodTraceEnter
.LdvmFastNativeMethodTraceExit:
.word dvmFastNativeMethodTraceExit
.LdvmFastJavaMethodTraceExit:
.word dvmFastJavaMethodTraceExit
-#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index fc26b3a95..d5847444b 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -166,7 +166,7 @@ dvmCompiler_TEMPLATE_RETURN:
* address in the code cache following the invoke instruction. Otherwise
* return to the special dvmJitToInterpNoChain entry point.
*/
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve live registers
mov r0, r6
@ r0=rGlue
@@ -271,7 +271,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -331,7 +331,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
mov rFP, r1 @ fp = newFp
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
mov r1, r6
@ r0=methodToCall, r1=rGlue
@@ -453,7 +453,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
mov r2, r0 @ r2<- methodToCall
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
@ r2=methodToCall, r6=rGLUE
stmfd sp!, {r2,r6} @ to be consumed after JNI return
stmfd sp!, {r0-r3} @ preserve r0-r3
@@ -467,7 +467,7 @@ dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
blx r8 @ off to the native code
-#if defined(WITH_INLINE_PROFILING)
+#if defined(TEMPLATE_INLINE_PROFILING)
ldmfd sp!, {r0-r1} @ restore r2 and r6
@ r0=JNIMethod, r1=rGlue
mov lr, pc
@@ -1505,6 +1505,370 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
blx r0
bx r4
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_RETURN_PROF
+dvmCompiler_TEMPLATE_RETURN_PROF:
+/* File: armv5te/TEMPLATE_RETURN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_RETURN.S */
+ /*
+ * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+ * If the stored value in returnAddr
+ * is non-zero, the caller is compiled by the JIT thus return to the
+ * address in the code cache following the invoke instruction. Otherwise
+ * return to the special dvmJitToInterpNoChain entry point.
+ */
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve live registers
+ mov r0, r6
+ @ r0=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastJavaMethodTraceExit
+ ldmfd sp!, {r0-r2,lr} @ restore live registers
+#endif
+ SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+ ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
+ ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
+ ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ @ r2<- method we're returning to
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
+ beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
+ ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
+ mov rFP, r10 @ publish new FP
+ ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+ ldr r8, [r8] @ r8<- suspendCount
+
+ str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+ ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
+ str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+ add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
+ str r0, [rGLUE, #offGlue_methodClassDex]
+ cmp r8, #0 @ check the suspendCount
+ movne r9, #0 @ clear the chaining cell address
+ str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
+ cmp r9, #0 @ chaining cell exists?
+ blxne r9 @ jump to the chaining cell
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1 @ callsite is interpreted
+1:
+ stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
+ ldr r2, .LdvmMterpStdBail @ defined in footer.S
+ mov r1, #0 @ changeInterp = false
+ mov r0, rGLUE @ Expecting rGLUE in r0
+ blx r2 @ exit the interpreter
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+ /*
+ * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+ * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+ * runtime-resolved callee.
+ */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+ ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
+
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne lr @ bail to the interpreter
+ tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
+ bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
+
+ ldr r10, .LdvmJitToInterpTraceSelectNoChain
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ @ Start executing the callee
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kInlineCacheMiss
+#endif
+ mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+ /*
+ * For monomorphic callsite, setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ */
+ @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
+ @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
+ @ methodToCall is guaranteed to be non-native
+.LinvokeChainProf:
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ add r12, lr, #2 @ setup the punt-to-interp address
+ sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
+ ldr r8, [r8] @ r8<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo r12 @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ bxne r12 @ bail to the interpreter
+
+ ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+ ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
+
+ @ Update "glue" values for the new method
+ str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
+ str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+ mov rFP, r1 @ fp = newFp
+ str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
+#if defined(TEMPLATE_INLINE_PROFILING)
+ stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
+ mov r1, r6
+ @ r0=methodToCall, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r2,lr} @ restore registers
+#endif
+
+ bx lr @ return to the callee-chaining cell
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+ /*
+ * For polymorphic callsite, check whether the cached class pointer matches
+ * the current one. If so setup the Dalvik frame and return to the
+ * Thumb code through the link register to transfer control to the callee
+ * method through a dedicated chaining cell.
+ *
+ * The predicted chaining cell is declared in ArmLIR.h with the
+ * following layout:
+ *
+ * typedef struct PredictedChainingCell {
+ * u4 branch;
+ * const ClassObject *clazz;
+ * const Method *method;
+ * u4 counter;
+ * } PredictedChainingCell;
+ *
+ * Upon returning to the callsite:
+ * - lr : to branch to the chaining cell
+ * - lr+2: to punt to the interpreter
+ * - lr+4: to fully resolve the callee and may rechain.
+ * r3 <- class
+ * r9 <- counter
+ */
+ @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+ ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
+ ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
+ ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
+ ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount
+ cmp r3, r8 @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+ ldr r7, .LdvmICHitCount
+#if defined(WORKAROUND_CORTEX_A9_745320)
+ /* Don't use conditional loads if the HW defect exists */
+ bne 101f
+ ldr r10, [r7, #0]
+101:
+#else
+ ldreq r10, [r7, #0]
+#endif
+ add r10, r10, #1
+ streq r10, [r7, #0]
+#endif
+ ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
+ ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
+ beq .LinvokeChainProf @ predicted chain is valid
+ ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+ cmp r8, #0 @ initialized class or not
+ moveq r1, #0
+ subne r1, r9, #1 @ count--
+ strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState
+ add lr, lr, #4 @ return to fully-resolve landing pad
+ /*
+ * r1 <- count
+ * r2 <- &predictedChainCell
+ * r3 <- this->class
+ * r4 <- dPC
+ * r7 <- this->class->vtable
+ */
+ bx lr
+
+#undef TEMPLATE_INLINE_PROFILING
+
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */
+#define TEMPLATE_INLINE_PROFILING
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+ @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+ @ r7 = methodToCall->registersSize
+ ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
+ ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+ add r3, r1, #1 @ Thumb addr is odd
+ SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
+ sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
+ ldr r8, [r8] @ r3<- suspendCount (int)
+ cmp r10, r9 @ bottom < interpStackEnd?
+ bxlo lr @ return to raise stack overflow excep.
+ @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+ str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+ str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+
+ @ set up newSaveArea
+ str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+ str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+ cmp r8, #0 @ suspendCount != 0
+ ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
+ bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
+
+ @ go ahead and transfer control to the native code
+ ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+ mov r2, #0
+ str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
+ str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
+ str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+ @ newFp->localRefCookie=top
+ mov r9, r3 @ r9<- glue->self (preserve)
+ SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
+
+ mov r2, r0 @ r2<- methodToCall
+ mov r0, r1 @ r0<- newFP
+ add r1, rGLUE, #offGlue_retval @ r1<- &retval
+#if defined(TEMPLATE_INLINE_PROFILING)
+ @ r2=methodToCall, r6=rGLUE
+ stmfd sp!, {r2,r6} @ to be consumed after JNI return
+ stmfd sp!, {r0-r3} @ preserve r0-r3
+ mov r0, r2
+ mov r1, r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastMethodTraceEnter
+ ldmfd sp!, {r0-r3} @ restore r0-r3
+#endif
+
+ blx r8 @ off to the native code
+
+#if defined(TEMPLATE_INLINE_PROFILING)
+ ldmfd sp!, {r0-r1} @ restore r2 and r6
+ @ r0=JNIMethod, r1=rGlue
+ mov lr, pc
+ ldr pc, .LdvmFastNativeMethodTraceExit
+#endif
+ @ native return; r9=self, r10=newSaveArea
+ @ equivalent to dvmPopJniLocals
+ ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+ ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+ ldr r1, [r9, #offThread_exception] @ check for exception
+ str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
+ cmp r1, #0 @ null?
+ str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+
+ @ r0 = dalvikCallsitePC
+ bne .LhandleException @ no, handle exception
+
+ str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
+ cmp r2, #0 @ return chaining cell still exists?
+ bxne r2 @ yes - go ahead
+
+ @ continue executing the next instruction through the interpreter
+ ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
+ add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
+#if defined(WITH_JIT_TUNING)
+ mov r0, #kCallsiteInterpreted
+#endif
+ mov pc, r1
+
+#undef TEMPLATE_INLINE_PROFILING
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1526,12 +1890,15 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
@ newFp->localRefCookie=top
mov r9, r3 @ r9<- glue->self (preserve)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
mov r2, r0 @ r2<- methodToCall
+ ldr lr, [lr] @ lr<- set of active profilers
mov r0, r1 @ r0<- newFP
add r1, rGLUE, #offGlue_retval @ r1<- &retval
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace
+ beq 121f @ hop if not profiling
@ r2: methodToCall, r6: rGLUE
stmfd sp!, {r2,r6}
stmfd sp!, {r0-r3}
@@ -1540,16 +1907,18 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
mov lr, pc
ldr pc, .LdvmFastMethodTraceEnter
ldmfd sp!, {r0-r3}
-#endif
mov lr, pc
ldr pc, [r2, #offMethod_nativeFunc]
-#if defined(WITH_INLINE_PROFILING)
ldmfd sp!, {r0-r1}
mov lr, pc
ldr pc, .LdvmFastNativeMethodTraceExit
-#endif
+ b 212f
+121:
+ mov lr, pc
+ ldr pc, [r2, #offMethod_nativeFunc]
+212:
@ Refresh Jit's on/off status
ldr r3, [rGLUE, #offGlue_ppJitProfTable]
@@ -1623,14 +1992,12 @@ dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
.LdvmSelfVerificationMemOpDecode:
.word dvmSelfVerificationMemOpDecode
#endif
-#if defined(WITH_INLINE_PROFILING)
.LdvmFastMethodTraceEnter:
.word dvmFastMethodTraceEnter
.LdvmFastNativeMethodTraceExit:
.word dvmFastNativeMethodTraceExit
.LdvmFastJavaMethodTraceExit:
.word dvmFastJavaMethodTraceExit
-#endif
.L__aeabi_cdcmple:
.word __aeabi_cdcmple
.L__aeabi_cfcmple: