summaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorbuzbee <buzbee@google.com>2011-01-19 15:31:15 -0800
committerbuzbee <buzbee@google.com>2011-01-19 16:39:41 -0800
commit18fba346582c08d81aa96d9508c0e935bad5f36f (patch)
treef69072fa267c06e5a3036c76fc37ba1df9c88f67 /vm
parent9238eb89ea5f0564047a2a2f040a2229d42f6f63 (diff)
downloadandroid_dalvik-18fba346582c08d81aa96d9508c0e935bad5f36f.tar.gz
android_dalvik-18fba346582c08d81aa96d9508c0e935bad5f36f.tar.bz2
android_dalvik-18fba346582c08d81aa96d9508c0e935bad5f36f.zip
Support traceview-style profiling in all builds
This change builds on an earlier bccheng change that allowed JIT'd code to avoid reverting to the debug portable interpeter when doing traceview-style method profiling. That CL introduced a new traceview build (libdvm_traceview) because the performance delta was too great to enable the capability for all builds. In this CL, we remove the libdvm_traceview build and provide full-speed method tracing in all builds. This is done by introducing "_PROF" versions of invoke and return templates used by the JIT. Normally, these templates are not used, and performace in unaffected. However, when method profiling is enabled, all existing translation are purged and new translations are created using the _PROF templates. These templates introduce a smallish performance penalty above and beyond the actual tracing cost, but again are only used when tracing has been enabled. Strictly speaking, there is a slight burden that is placed on invokes and returns in the non-tracing case - on the order of an additional 3 or 4 cycles per invoke/return. Those operations are already heavyweight enough that I was unable to measure the added cost in benchmarks. Change-Id: Ic09baf4249f1e716e136a65458f4e06cea35fc18
Diffstat (limited to 'vm')
-rw-r--r--vm/Android.mk7
-rw-r--r--vm/Globals.h4
-rw-r--r--vm/Init.c3
-rw-r--r--vm/Profile.c7
-rw-r--r--vm/Profile.h2
-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
-rw-r--r--vm/interp/InterpDefs.h7
-rw-r--r--vm/mterp/Mterp.c11
-rw-r--r--vm/mterp/armv5te/footer.S40
-rw-r--r--vm/mterp/out/InterpAsm-armv5te-vfp.S40
-rw-r--r--vm/mterp/out/InterpAsm-armv5te.S40
-rw-r--r--vm/mterp/out/InterpAsm-armv7-a-neon.S40
-rw-r--r--vm/mterp/out/InterpAsm-armv7-a.S40
40 files changed, 1793 insertions, 178 deletions
diff --git a/vm/Android.mk b/vm/Android.mk
index 7465976c1..48a01ccc8 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -86,13 +86,6 @@ ifeq ($(WITH_JIT),true)
LOCAL_MODULE := libdvm_interp
include $(BUILD_SHARED_LIBRARY)
- # Derivation #4
- WITH_JIT := true
- include $(LOCAL_PATH)/ReconfigureDvm.mk
-
- LOCAL_CFLAGS += $(target_smp_flag) -DWITH_INLINE_PROFILING
- LOCAL_MODULE := libdvm_traceview
- include $(BUILD_SHARED_LIBRARY)
endif
#
diff --git a/vm/Globals.h b/vm/Globals.h
index e810a56a5..477a17e02 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -765,6 +765,7 @@ struct DvmJitGlobals {
/* JIT Compiler Control */
bool haltCompilerThread;
bool blockingMode;
+ bool methodTraceSupport;
pthread_t compilerHandle;
pthread_mutex_t compilerLock;
pthread_mutex_t compilerICPatchLock;
@@ -783,6 +784,9 @@ struct DvmJitGlobals {
/* Compiled code cache */
void* codeCache;
+ /* Translation cache version (protected by compilerLock */
+ int cacheVersion;
+
/* Bytes used by the code templates */
unsigned int templateSize;
diff --git a/vm/Init.c b/vm/Init.c
index 97a540e5d..6ff3772ae 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -186,9 +186,6 @@ static void usage(const char* progName)
#if ANDROID_SMP != 0
" smp"
#endif
-#ifdef WITH_INLINE_PROFILING
- " inline_profiling"
-#endif
);
#ifdef DVM_SHOW_EXCEPTION
dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
diff --git a/vm/Profile.c b/vm/Profile.c
index a2cfac152..d1f5b237f 100644
--- a/vm/Profile.c
+++ b/vm/Profile.c
@@ -18,6 +18,7 @@
* Android's method call profiling goodies.
*/
#include "Dalvik.h"
+#include <interp/InterpDefs.h>
#include <stdlib.h>
#include <stddef.h>
@@ -712,8 +713,6 @@ void dvmMethodTraceAdd(Thread* self, const Method* method, int action)
*ptr++ = (u1) (clockDiff >> 24);
}
-#if defined(WITH_INLINE_PROFILING)
-#include <interp/InterpDefs.h>
/*
* Register the METHOD_TRACE_ENTER action for the fast interpreter and
@@ -752,7 +751,6 @@ void dvmFastNativeMethodTraceExit(const Method* method,
dvmMethodTraceAdd(interpState->self, method, METHOD_TRACE_EXIT);
}
}
-#endif
/*
* We just did something with a method. Emit a record by setting a value
@@ -885,9 +883,6 @@ void dvmEmulatorTraceStop(void)
*/
void dvmStartInstructionCounting(void)
{
-#if defined(WITH_INLINE_PROFILING)
- LOGW("Instruction counting not supported with inline profiling");
-#endif
/* in theory we should make this an atomic inc; in practice not important */
gDvm.instructionCountEnableCount++;
updateActiveProfilers(kSubModeInstCounting, true);
diff --git a/vm/Profile.h b/vm/Profile.h
index 167eafe4e..9d604338b 100644
--- a/vm/Profile.h
+++ b/vm/Profile.h
@@ -141,14 +141,12 @@ void dvmMethodTraceGCEnd(void);
void dvmMethodTraceClassPrepBegin(void);
void dvmMethodTraceClassPrepEnd(void);
-#if defined(WITH_INLINE_PROFILING)
struct InterpState; // extern
void dvmFastMethodTraceEnter(const Method* method,
const struct InterpState* interpState);
void dvmFastJavaMethodTraceExit(const struct InterpState* interpState);
void dvmFastNativeMethodTraceExit(const Method*method,
const struct InterpState* interpState);
-#endif
/*
* Start/stop alloc counting.
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:
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index 3781dba73..40eb51d97 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -227,16 +227,9 @@ Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
*/
static inline bool dvmDebuggerOrProfilerActive(void)
{
-#if defined(WITH_INLINE_PROFILING)
return gDvm.interpBreak & (kSubModeDebuggerActive |
kSubModeEmulatorTrace |
kSubModeInstCounting);
-#else
- return gDvm.interpBreak & (kSubModeDebuggerActive |
- kSubModeEmulatorTrace |
- kSubModeMethodTrace |
- kSubModeInstCounting);
-#endif
}
#if defined(WITH_JIT)
diff --git a/vm/mterp/Mterp.c b/vm/mterp/Mterp.c
index 472277978..907618eb5 100644
--- a/vm/mterp/Mterp.c
+++ b/vm/mterp/Mterp.c
@@ -85,18 +85,13 @@ bool dvmMterpStd(Thread* self, InterpState* glue)
glue->jitCacheEnd = (char*)gDvmJit.codeCache + gDvmJit.codeCacheSize;
glue->pProfileCountdown = &gDvmJit.profileCountdown;
#endif
-#if defined(WITH_INLINE_PROFILING)
- /*
- * If WITH_INLINE_PROFILING is defined, we won't switch to the debug
- * interpreter when a new method is entered. So we need to register the
- * METHOD_ENTER action here.
- */
+ glue->pInterpBreak = &gDvm.interpBreak;
+
+ /* Handle method entry bookkeeping */
if (glue->debugIsMethodEntry) {
glue->debugIsMethodEntry = false;
TRACE_METHOD_ENTER(self, glue->method);
}
-#endif
- glue->pInterpBreak = &gDvm.interpBreak;
IF_LOGVV() {
char* desc = dexProtoCopyMethodDescriptor(&glue->method->prototype);
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 7081c52a2..c13cfc850 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -489,11 +489,7 @@ common_periodicChecks:
* source-level single-stepping requires Dalvik singlestepping.
* GC may require a one-shot action and then full-speed resumption.
*/
-#if defined(WITH_INLINE_PROFILING)
ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
-#else
- ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting | kSubModeMethodTrace)
-#endif
bxeq lr @ nothing to do, return
@ debugger/profiler enabled, bail out; glue->entryPoint was set above
@@ -623,10 +619,12 @@ common_invokeMethodNoRange:
ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@ set up newSaveArea
+ ldr lr, [lr] @ lr<- active submodes
#ifdef EASY_GDB
SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
str ip, [r10, #offStackSaveArea_prevSave]
@@ -637,13 +635,14 @@ common_invokeMethodNoRange:
mov r9, #0
str r9, [r10, #offStackSaveArea_returnAddr]
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 1f @ skip if not
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
bl dvmFastMethodTraceEnter
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
+1:
str r0, [r10, #offStackSaveArea_method]
tst r3, #ACC_NATIVE
bne .LinvokeNative
@@ -693,9 +692,11 @@ common_invokeMethodNoRange:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+ ldr lr, [lr] @ lr<- active submodes
mov r9, r3 @ r9<- glue->self (preserve)
mov r2, r0 @ r2<- methodToCall
@@ -713,20 +714,24 @@ dalvik_mterp:
.Lskip:
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 110f @ hop if not
@ r2=JNIMethod, r6=rGLUE
stmfd sp!, {r2,r6}
-#endif
mov lr, pc @ set return addr
ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
-#if defined(WITH_INLINE_PROFILING)
@ r0=JNIMethod, r1=rGLUE
ldmfd sp!, {r0-r1}
bl dvmFastNativeMethodTraceExit
-#endif
-
+ @ r2=JNIMethod, r6=rGLUE
+ stmfd sp!, {r2,r6}
+ b 220f
+110:
+ mov lr, pc @ set return addr
+ ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+220:
#if defined(WITH_JIT)
ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
#endif
@@ -799,19 +804,22 @@ common_returnFromMethod:
mov r9, #0
bl common_periodicChecks
-#if defined(WITH_INLINE_PROFILING)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
+ SAVEAREA_FROM_FP(r0, rFP)
+ ldr lr, [lr] @ lr<- active submodes
+ ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 333f
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r0, r6
@ r0=rGlue
bl dvmFastJavaMethodTraceExit
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
- SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+333:
ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
- ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
- ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ is this a break frame?
#if defined(WORKAROUND_CORTEX_A9_745320)
/* Don't use conditional loads if the HW defect exists */
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index b5e306a32..665f501fd 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -13645,11 +13645,7 @@ common_periodicChecks:
* source-level single-stepping requires Dalvik singlestepping.
* GC may require a one-shot action and then full-speed resumption.
*/
-#if defined(WITH_INLINE_PROFILING)
ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
-#else
- ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting | kSubModeMethodTrace)
-#endif
bxeq lr @ nothing to do, return
@ debugger/profiler enabled, bail out; glue->entryPoint was set above
@@ -13779,10 +13775,12 @@ common_invokeMethodNoRange:
ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@ set up newSaveArea
+ ldr lr, [lr] @ lr<- active submodes
#ifdef EASY_GDB
SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
str ip, [r10, #offStackSaveArea_prevSave]
@@ -13793,13 +13791,14 @@ common_invokeMethodNoRange:
mov r9, #0
str r9, [r10, #offStackSaveArea_returnAddr]
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 1f @ skip if not
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
bl dvmFastMethodTraceEnter
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
+1:
str r0, [r10, #offStackSaveArea_method]
tst r3, #ACC_NATIVE
bne .LinvokeNative
@@ -13849,9 +13848,11 @@ common_invokeMethodNoRange:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+ ldr lr, [lr] @ lr<- active submodes
mov r9, r3 @ r9<- glue->self (preserve)
mov r2, r0 @ r2<- methodToCall
@@ -13869,20 +13870,24 @@ dalvik_mterp:
.Lskip:
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 110f @ hop if not
@ r2=JNIMethod, r6=rGLUE
stmfd sp!, {r2,r6}
-#endif
mov lr, pc @ set return addr
ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
-#if defined(WITH_INLINE_PROFILING)
@ r0=JNIMethod, r1=rGLUE
ldmfd sp!, {r0-r1}
bl dvmFastNativeMethodTraceExit
-#endif
-
+ @ r2=JNIMethod, r6=rGLUE
+ stmfd sp!, {r2,r6}
+ b 220f
+110:
+ mov lr, pc @ set return addr
+ ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+220:
#if defined(WITH_JIT)
ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
#endif
@@ -13955,19 +13960,22 @@ common_returnFromMethod:
mov r9, #0
bl common_periodicChecks
-#if defined(WITH_INLINE_PROFILING)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
+ SAVEAREA_FROM_FP(r0, rFP)
+ ldr lr, [lr] @ lr<- active submodes
+ ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 333f
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r0, r6
@ r0=rGlue
bl dvmFastJavaMethodTraceExit
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
- SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+333:
ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
- ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
- ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ is this a break frame?
#if defined(WORKAROUND_CORTEX_A9_745320)
/* Don't use conditional loads if the HW defect exists */
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index ce1f7f070..5fef4bd1f 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -14103,11 +14103,7 @@ common_periodicChecks:
* source-level single-stepping requires Dalvik singlestepping.
* GC may require a one-shot action and then full-speed resumption.
*/
-#if defined(WITH_INLINE_PROFILING)
ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
-#else
- ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting | kSubModeMethodTrace)
-#endif
bxeq lr @ nothing to do, return
@ debugger/profiler enabled, bail out; glue->entryPoint was set above
@@ -14237,10 +14233,12 @@ common_invokeMethodNoRange:
ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@ set up newSaveArea
+ ldr lr, [lr] @ lr<- active submodes
#ifdef EASY_GDB
SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
str ip, [r10, #offStackSaveArea_prevSave]
@@ -14251,13 +14249,14 @@ common_invokeMethodNoRange:
mov r9, #0
str r9, [r10, #offStackSaveArea_returnAddr]
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 1f @ skip if not
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
bl dvmFastMethodTraceEnter
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
+1:
str r0, [r10, #offStackSaveArea_method]
tst r3, #ACC_NATIVE
bne .LinvokeNative
@@ -14307,9 +14306,11 @@ common_invokeMethodNoRange:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+ ldr lr, [lr] @ lr<- active submodes
mov r9, r3 @ r9<- glue->self (preserve)
mov r2, r0 @ r2<- methodToCall
@@ -14327,20 +14328,24 @@ dalvik_mterp:
.Lskip:
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 110f @ hop if not
@ r2=JNIMethod, r6=rGLUE
stmfd sp!, {r2,r6}
-#endif
mov lr, pc @ set return addr
ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
-#if defined(WITH_INLINE_PROFILING)
@ r0=JNIMethod, r1=rGLUE
ldmfd sp!, {r0-r1}
bl dvmFastNativeMethodTraceExit
-#endif
-
+ @ r2=JNIMethod, r6=rGLUE
+ stmfd sp!, {r2,r6}
+ b 220f
+110:
+ mov lr, pc @ set return addr
+ ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+220:
#if defined(WITH_JIT)
ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
#endif
@@ -14413,19 +14418,22 @@ common_returnFromMethod:
mov r9, #0
bl common_periodicChecks
-#if defined(WITH_INLINE_PROFILING)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
+ SAVEAREA_FROM_FP(r0, rFP)
+ ldr lr, [lr] @ lr<- active submodes
+ ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 333f
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r0, r6
@ r0=rGlue
bl dvmFastJavaMethodTraceExit
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
- SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+333:
ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
- ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
- ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ is this a break frame?
#if defined(WORKAROUND_CORTEX_A9_745320)
/* Don't use conditional loads if the HW defect exists */
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index 0d0136e0b..5423a7a8a 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -13583,11 +13583,7 @@ common_periodicChecks:
* source-level single-stepping requires Dalvik singlestepping.
* GC may require a one-shot action and then full-speed resumption.
*/
-#if defined(WITH_INLINE_PROFILING)
ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
-#else
- ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting | kSubModeMethodTrace)
-#endif
bxeq lr @ nothing to do, return
@ debugger/profiler enabled, bail out; glue->entryPoint was set above
@@ -13717,10 +13713,12 @@ common_invokeMethodNoRange:
ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@ set up newSaveArea
+ ldr lr, [lr] @ lr<- active submodes
#ifdef EASY_GDB
SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
str ip, [r10, #offStackSaveArea_prevSave]
@@ -13731,13 +13729,14 @@ common_invokeMethodNoRange:
mov r9, #0
str r9, [r10, #offStackSaveArea_returnAddr]
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 1f @ skip if not
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
bl dvmFastMethodTraceEnter
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
+1:
str r0, [r10, #offStackSaveArea_method]
tst r3, #ACC_NATIVE
bne .LinvokeNative
@@ -13787,9 +13786,11 @@ common_invokeMethodNoRange:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+ ldr lr, [lr] @ lr<- active submodes
mov r9, r3 @ r9<- glue->self (preserve)
mov r2, r0 @ r2<- methodToCall
@@ -13807,20 +13808,24 @@ dalvik_mterp:
.Lskip:
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 110f @ hop if not
@ r2=JNIMethod, r6=rGLUE
stmfd sp!, {r2,r6}
-#endif
mov lr, pc @ set return addr
ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
-#if defined(WITH_INLINE_PROFILING)
@ r0=JNIMethod, r1=rGLUE
ldmfd sp!, {r0-r1}
bl dvmFastNativeMethodTraceExit
-#endif
-
+ @ r2=JNIMethod, r6=rGLUE
+ stmfd sp!, {r2,r6}
+ b 220f
+110:
+ mov lr, pc @ set return addr
+ ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+220:
#if defined(WITH_JIT)
ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
#endif
@@ -13893,19 +13898,22 @@ common_returnFromMethod:
mov r9, #0
bl common_periodicChecks
-#if defined(WITH_INLINE_PROFILING)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
+ SAVEAREA_FROM_FP(r0, rFP)
+ ldr lr, [lr] @ lr<- active submodes
+ ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 333f
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r0, r6
@ r0=rGlue
bl dvmFastJavaMethodTraceExit
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
- SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+333:
ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
- ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
- ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ is this a break frame?
#if defined(WORKAROUND_CORTEX_A9_745320)
/* Don't use conditional loads if the HW defect exists */
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index f638d9f52..7a1c6eb33 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -13583,11 +13583,7 @@ common_periodicChecks:
* source-level single-stepping requires Dalvik singlestepping.
* GC may require a one-shot action and then full-speed resumption.
*/
-#if defined(WITH_INLINE_PROFILING)
ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting)
-#else
- ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting | kSubModeMethodTrace)
-#endif
bxeq lr @ nothing to do, return
@ debugger/profiler enabled, bail out; glue->entryPoint was set above
@@ -13717,10 +13713,12 @@ common_invokeMethodNoRange:
ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize)
cmp r3, r9 @ bottom < interpStackEnd?
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
blo .LstackOverflow @ yes, this frame will overflow stack
@ set up newSaveArea
+ ldr lr, [lr] @ lr<- active submodes
#ifdef EASY_GDB
SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area
str ip, [r10, #offStackSaveArea_prevSave]
@@ -13731,13 +13729,14 @@ common_invokeMethodNoRange:
mov r9, #0
str r9, [r10, #offStackSaveArea_returnAddr]
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 1f @ skip if not
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r1, r6
@ r0=methodToCall, r1=rGlue
bl dvmFastMethodTraceEnter
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
+1:
str r0, [r10, #offStackSaveArea_method]
tst r3, #ACC_NATIVE
bne .LinvokeNative
@@ -13787,9 +13786,11 @@ common_invokeMethodNoRange:
@ Prep for the native call
@ r0=methodToCall, r1=newFp, r10=newSaveArea
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+ ldr lr, [lr] @ lr<- active submodes
mov r9, r3 @ r9<- glue->self (preserve)
mov r2, r0 @ r2<- methodToCall
@@ -13807,20 +13808,24 @@ dalvik_mterp:
.Lskip:
#endif
-#if defined(WITH_INLINE_PROFILING)
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 110f @ hop if not
@ r2=JNIMethod, r6=rGLUE
stmfd sp!, {r2,r6}
-#endif
mov lr, pc @ set return addr
ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
-#if defined(WITH_INLINE_PROFILING)
@ r0=JNIMethod, r1=rGLUE
ldmfd sp!, {r0-r1}
bl dvmFastNativeMethodTraceExit
-#endif
-
+ @ r2=JNIMethod, r6=rGLUE
+ stmfd sp!, {r2,r6}
+ b 220f
+110:
+ mov lr, pc @ set return addr
+ ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+220:
#if defined(WITH_JIT)
ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
#endif
@@ -13893,19 +13898,22 @@ common_returnFromMethod:
mov r9, #0
bl common_periodicChecks
-#if defined(WITH_INLINE_PROFILING)
+ ldr lr, [rGLUE, #offGlue_pInterpBreak]
+ SAVEAREA_FROM_FP(r0, rFP)
+ ldr lr, [lr] @ lr<- active submodes
+ ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ands lr, #kSubModeMethodTrace @ method tracing?
+ beq 333f
stmfd sp!, {r0-r3} @ preserve r0-r3
mov r0, r6
@ r0=rGlue
bl dvmFastJavaMethodTraceExit
ldmfd sp!, {r0-r3} @ restore r0-r3
-#endif
- SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
+333:
ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
- ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+ ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
- ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ is this a break frame?
#if defined(WORKAROUND_CORTEX_A9_745320)
/* Don't use conditional loads if the HW defect exists */