i = 0;
}
- gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].pc = pc;
- gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].kind = kind;
- gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].info = info;
+ CompilerWorkOrder *newOrder =
+ &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex];
+ newOrder->pc = pc;
+ newOrder->kind = kind;
+ newOrder->info = info;
+ newOrder->result.codeAddress = NULL;
+ newOrder->result.discardResult =
+ (kind == kWorkOrderTraceDebug) ? true : false;
gDvmJit.compilerWorkEnqueueIndex++;
if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
gDvmJit.compilerWorkEnqueueIndex = 0;
/* Description of a compiled trace. */
typedef struct JitTranslationInfo {
- void *codeAddress;
+ void *codeAddress;
JitInstructionSetType instructionSet;
+ bool discardResult; // Used for debugging divergence
} JitTranslationInfo;
typedef enum WorkOrderKind {
kWorkOrderInvalid = 0, // Should never see by the backend
kWorkOrderMethod = 1, // Work is to compile a whole method
kWorkOrderTrace = 2, // Work is to compile code fragment(s)
+ kWorkOrderTraceDebug = 3, // Work is to compile/debug code fragment(s)
} WorkOrderKind;
typedef struct CompilerWorkOrder {
struct BasicBlock *bb);
void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
struct BasicBlock *bb);
+char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn);
char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
struct SSARepresentation *ssaRep);
void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
void (*func)(struct CompilationUnit *, struct BasicBlock *));
+JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc);
#endif /* _DALVIK_VM_COMPILER */
#include "Dalvik.h"
#include "Dataflow.h"
#include "Loop.h"
+#include "dexdump/OpCodeNames.h"
/*
* Main table containing data flow attributes for each bytecode. The first
* and subscript pair. Each SSA register can be used to index the
* ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
*/
+char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn)
+{
+ char buffer[256];
+ int opcode = insn->opCode;
+ int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
+ char *ret;
+
+ buffer[0] = 0;
+ strcpy(buffer, getOpcodeName(opcode));
+
+ if (dfAttributes & DF_FORMAT_35C) {
+ unsigned int i;
+ for (i = 0; i < insn->vA; i++) {
+ if (i != 0) strcat(buffer, ",");
+ sprintf(buffer + strlen(buffer), " v%d", insn->arg[i]);
+ }
+ }
+ else if (dfAttributes & DF_FORMAT_3RC) {
+ sprintf(buffer + strlen(buffer),
+ " v%d..v%d", insn->vC, insn->vC + insn->vA - 1);
+ }
+ else {
+ if (dfAttributes & DF_A_IS_REG) {
+ sprintf(buffer + strlen(buffer), " v%d", insn->vA);
+ }
+ if (dfAttributes & DF_B_IS_REG) {
+ sprintf(buffer + strlen(buffer),
+ ", v%d", insn->vB);
+ }
+ else {
+ sprintf(buffer + strlen(buffer),
+ ", (#%d)", insn->vB);
+ }
+ if (dfAttributes & DF_C_IS_REG) {
+ sprintf(buffer + strlen(buffer),
+ ", v%d", insn->vC);
+ }
+ else {
+ sprintf(buffer + strlen(buffer),
+ ", (#%d)", insn->vC);
+ }
+ }
+ int length = strlen(buffer) + 1;
+ ret = dvmCompilerNew(length, false);
+ memcpy(ret, buffer, length);
+ return ret;
+}
+
+/*
+ * Utility function to convert encoded SSA register value into Dalvik register
+ * and subscript pair. Each SSA register can be used to index the
+ * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
+ */
char *dvmCompilerGetSSAString(CompilationUnit *cUnit, SSARepresentation *ssaRep)
{
char buffer[256];
DF_NULL_N_RANGE_CHECK_1 | \
DF_NULL_N_RANGE_CHECK_2)
+#define DF_A_IS_REG (DF_UA | DF_UA_WIDE | DF_DA | DF_DA_WIDE)
+#define DF_B_IS_REG (DF_UB | DF_UB_WIDE)
+#define DF_C_IS_REG (DF_UC | DF_UC_WIDE)
+
extern int dvmCompilerDataFlowAttributes[MIR_OP_LAST];
typedef struct BasicBlockDataFlow {
#include "Dalvik.h"
#include "libdex/OpCode.h"
-#include "dexdump/OpCodeNames.h"
#include "interp/Jit.h"
#include "CompilerInternals.h"
dexDecodeInstruction(gDvm.instrFormat, codePtr, decInsn);
if (printMe) {
- LOGD("%p: %#06x %s\n", codePtr, opcode, getOpcodeName(opcode));
+ char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn);
+ LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
}
return insnWidth;
}
break;
case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
- getOpcodeName(lir->operands[1]));
+ (char *) lir->operands[1]);
break;
case ARM_PSEUDO_EXIT_BLOCK:
LOGD("-------- exit offset: 0x%04x\n", dest);
ChainCellCounts chainCellCounts;
int descSize = jitTraceDescriptionSize(cUnit->traceDesc);
- info->codeAddress = NULL;
info->instructionSet = cUnit->instructionSet;
/* Beginning offset needs to allow space for chain cell offset */
return;
}
+ /* Don't go all the way if the goal is just to get the verbose output */
+ if (info->discardResult) return;
cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
gDvmJit.codeCacheByteUsed += offset;
/* Record code entry point and instruction set */
info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
- info->instructionSet = cUnit->instructionSet;
/* If applicable, mark low bit to denote thumb */
if (info->instructionSet != DALVIK_JIT_ARM)
info->codeAddress = (char*)info->codeAddress + 1;
return *pExecutionCount;
}
+/* Create a copy of the trace descriptor of an existing compilation */
+JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc)
+{
+ JitEntry *jitEntry = dvmFindJitEntry(pc);
+ if (jitEntry == NULL) return NULL;
+
+ /* Find out the startint point */
+ char *traceBase = getTraceBase(jitEntry);
+
+ /* Then find out the starting point of the chaining cell */
+ u2 *pCellOffset = (u2*) (traceBase + 4);
+ ChainCellCounts *pCellCounts =
+ (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
+
+ /* From there we can find out the starting point of the trace descriptor */
+ JitTraceDescription *desc =
+ (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
+
+ /* Now make a copy and return */
+ int descSize = jitTraceDescriptionSize(desc);
+ JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize);
+ memcpy(newCopy, desc, descSize);
+ return newCopy;
+}
+
/* Handy function to retrieve the profile count */
static inline int getProfileCount(const JitEntry *entry)
{
dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
ArmLIR *boundaryLIR =
newLIR2(cUnit, ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY,
- mir->offset, dalvikOpCode);
+ mir->offset,
+ (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
+ );
if (mir->ssaRep) {
char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
newLIR1(cUnit, ARM_PSEUDO_SSA_REP, (int) ssaString);
/* Accept the work and start compiling */
bool dvmCompilerDoWork(CompilerWorkOrder *work)
{
- bool res;
+ bool res;
- if (gDvmJit.codeCacheFull) {
- return false;
- }
+ if (gDvmJit.codeCacheFull) {
+ return false;
+ }
- switch (work->kind) {
- case kWorkOrderMethod:
- res = dvmCompileMethod(work->info, &work->result);
- break;
- case kWorkOrderTrace:
- /* Start compilation with maximally allowed trace length */
- res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
- break;
- default:
- res = false;
- dvmAbort();
- }
- return res;
+ switch (work->kind) {
+ case kWorkOrderMethod:
+ res = dvmCompileMethod(work->info, &work->result);
+ break;
+ case kWorkOrderTrace:
+ /* Start compilation with maximally allowed trace length */
+ res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
+ break;
+ case kWorkOrderTraceDebug: {
+ bool oldPrintMe = gDvmJit.printMe;
+ gDvmJit.printMe = true;
+ /* Start compilation with maximally allowed trace length */
+ res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
+ gDvmJit.printMe = oldPrintMe;;
+ break;
+ }
+ default:
+ res = false;
+ dvmAbort();
+ }
+ return res;
}
/* Architectural-specific debugging helpers go here */
* Return a pointer to the shadow space for JIT to use.
*/
void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
- void* interpStatePtr)
+ InterpState* interpState)
{
Thread *self = dvmThreadSelf();
ShadowSpace *shadowSpace = self->shadowSpace;
- InterpState *interpState = (InterpState *) interpStatePtr;
int preBytes = interpState->method->outsSize*4 + sizeof(StackSaveArea);
int postBytes = interpState->method->registersSize*4;
LOGD("~~~ Save: INCORRECT PREVIOUS STATE(%d): %d",
self->threadId, shadowSpace->selfVerificationState);
LOGD("********** SHADOW STATE DUMP **********");
- LOGD("* PC: 0x%x FP: 0x%x", (int)pc, (int)fp);
+ LOGD("PC: 0x%x FP: 0x%x", (int)pc, (int)fp);
}
shadowSpace->selfVerificationState = kSVSStart;
// Remember original state
shadowSpace->startPC = pc;
shadowSpace->fp = fp;
- shadowSpace->glue = interpStatePtr;
+ shadowSpace->glue = interpState;
+ /*
+ * Store the original method here in case the trace ends with a
+ * return/invoke, the last method.
+ */
+ shadowSpace->method = interpState->method;
shadowSpace->shadowFP = shadowSpace->registerSpace +
shadowSpace->registerSpaceSize - postBytes/4;
// Create a copy of the InterpState
- memcpy(&(shadowSpace->interpState), interpStatePtr, sizeof(InterpState));
+ //shadowSpace->interpState = *interpState;
+ memcpy(&(shadowSpace->interpState), interpState, sizeof(InterpState));
shadowSpace->interpState.fp = shadowSpace->shadowFP;
shadowSpace->interpState.interpStackEnd = (u1*)shadowSpace->registerSpace;
LOGD("~~~ Restore: INCORRECT PREVIOUS STATE(%d): %d",
self->threadId, shadowSpace->selfVerificationState);
LOGD("********** SHADOW STATE DUMP **********");
- LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+ LOGD("Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
(int)shadowSpace->endPC);
- LOGD("* Interp FP: 0x%x", (int)shadowSpace->fp);
- LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+ LOGD("Interp FP: 0x%x", (int)shadowSpace->fp);
+ LOGD("Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
(int)shadowSpace->endShadowFP);
}
}
/* Print contents of virtual registers */
-static void selfVerificationPrintRegisters(int* addr, int numWords)
+static void selfVerificationPrintRegisters(int* addr, int* addrRef,
+ int numWords)
{
int i;
for (i = 0; i < numWords; i++) {
- LOGD("* 0x%x: (v%d) 0x%8x", (int)(addr+i), i, *(addr+i));
+ LOGD("(v%d) 0x%8x%s", i, addr[i], addr[i] != addrRef[i] ? " X" : "");
}
}
frameBytes2 = (int) shadowSpace->fp - (int) self->curFrame - localRegs;
}
LOGD("********** SHADOW STATE DUMP **********");
- LOGD("* CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
+ LOGD("CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
(int)(pc - stackSave->method->insns));
- LOGD("* Class: %s Method: %s", stackSave->method->clazz->descriptor,
- stackSave->method->name);
- LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+ LOGD("Class: %s", shadowSpace->method->clazz->descriptor);
+ LOGD("Method: %s", shadowSpace->method->name);
+ LOGD("Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
(int)shadowSpace->endPC);
- LOGD("* Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
+ LOGD("Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
(int)self->curFrame);
- LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+ LOGD("Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
(int)shadowSpace->endShadowFP);
- LOGD("* Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
+ LOGD("Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
localRegs, frameBytes2);
- LOGD("* Trace length: %d State: %d", shadowSpace->traceLength,
+ LOGD("Trace length: %d State: %d", shadowSpace->traceLength,
shadowSpace->selfVerificationState);
}
offset = (int)((u2*)addr - stackSave->method->insns);
decInsn = &(shadowSpace->trace[i].decInsn);
/* Not properly decoding instruction, some registers may be garbage */
- LOGD("* 0x%x: (0x%04x) %s v%d, v%d, v%d", addr, offset,
- getOpcodeName(decInsn->opCode), decInsn->vA, decInsn->vB,
- decInsn->vC);
+ LOGD("0x%x: (0x%04x) %s", addr, offset, getOpcodeName(decInsn->opCode));
}
}
/* Code is forced into this spin loop when a divergence is detected */
-static void selfVerificationSpinLoop()
+static void selfVerificationSpinLoop(ShadowSpace *shadowSpace)
{
+ const u2 *startPC = shadowSpace->startPC;
+ JitTraceDescription* desc = dvmCopyTraceDescriptor(startPC);
+ if (desc) {
+ dvmCompilerWorkEnqueue(startPC, kWorkOrderTraceDebug, desc);
+ }
gDvmJit.selfVerificationSpin = true;
while(gDvmJit.selfVerificationSpin) sleep(10);
}
shadowSpace->registerSpaceSize*4 -
(int) shadowSpace->shadowFP;
if (memcmp(shadowSpace->fp, shadowSpace->shadowFP, frameBytes)) {
- LOGD("~~~ DbgIntp(%d): REGISTERS UNEQUAL!", self->threadId);
+ LOGD("~~~ DbgIntp(%d): REGISTERS DIVERGENCE!", self->threadId);
selfVerificationDumpState(pc, self);
selfVerificationDumpTrace(pc, self);
LOGD("*** Interp Registers: addr: 0x%x bytes: %d",
(int)shadowSpace->fp, frameBytes);
- selfVerificationPrintRegisters((int*)shadowSpace->fp, frameBytes/4);
+ selfVerificationPrintRegisters((int*)shadowSpace->fp,
+ (int*)shadowSpace->shadowFP,
+ frameBytes/4);
LOGD("*** Shadow Registers: addr: 0x%x bytes: %d",
(int)shadowSpace->shadowFP, frameBytes);
selfVerificationPrintRegisters((int*)shadowSpace->shadowFP,
- frameBytes/4);
- selfVerificationSpinLoop();
+ (int*)shadowSpace->fp,
+ frameBytes/4);
+ selfVerificationSpinLoop(shadowSpace);
}
/* Check new frame if it exists (invokes only) */
if (self->curFrame < shadowSpace->fp) {
(int) self->curFrame - localRegs;
if (memcmp(((char*)self->curFrame)+localRegs,
((char*)shadowSpace->endShadowFP)+localRegs, frameBytes2)) {
- LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) UNEQUAL!",
+ LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) DIVERGENCE!",
self->threadId);
selfVerificationDumpState(pc, self);
selfVerificationDumpTrace(pc, self);
LOGD("*** Interp Registers: addr: 0x%x l: %d bytes: %d",
(int)self->curFrame, localRegs, frameBytes2);
selfVerificationPrintRegisters((int*)self->curFrame,
- (frameBytes2+localRegs)/4);
+ (int*)shadowSpace->endShadowFP,
+ (frameBytes2+localRegs)/4);
LOGD("*** Shadow Registers: addr: 0x%x l: %d bytes: %d",
(int)shadowSpace->endShadowFP, localRegs, frameBytes2);
selfVerificationPrintRegisters((int*)shadowSpace->endShadowFP,
- (frameBytes2+localRegs)/4);
- selfVerificationSpinLoop();
+ (int*)self->curFrame,
+ (frameBytes2+localRegs)/4);
+ selfVerificationSpinLoop(shadowSpace);
}
}
heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
int memData = *((unsigned int*) heapSpacePtr->addr);
if (heapSpacePtr->data != memData) {
- LOGD("~~~ DbgIntp(%d): MEMORY UNEQUAL!", self->threadId);
- LOGD("* Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
+ LOGD("~~~ DbgIntp(%d): MEMORY DIVERGENCE!", self->threadId);
+ LOGD("Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
heapSpacePtr->addr, memData, heapSpacePtr->data);
selfVerificationDumpState(pc, self);
selfVerificationDumpTrace(pc, self);
memDiff = true;
}
}
- if (memDiff) selfVerificationSpinLoop();
+ if (memDiff) selfVerificationSpinLoop(shadowSpace);
return true;
/* If end not been reached, make sure max length not exceeded */
} else if (shadowSpace->traceLength >= JIT_MAX_TRACE_LEN) {
LOGD("~~~ DbgIntp(%d): CONTROL DIVERGENCE!", self->threadId);
- LOGD("* startPC: 0x%x endPC: 0x%x currPC: 0x%x",
+ LOGD("startPC: 0x%x endPC: 0x%x currPC: 0x%x",
(int)shadowSpace->startPC, (int)shadowSpace->endPC, (int)pc);
selfVerificationDumpState(pc, self);
selfVerificationDumpTrace(pc, self);
- selfVerificationSpinLoop();
+ selfVerificationSpinLoop(shadowSpace);
return true;
}
return switchInterp;
}
-static inline JitEntry *findJitEntry(const u2* pc)
+JitEntry *dvmFindJitEntry(const u2* pc)
{
int idx = dvmJitHash(pc);
return NULL;
}
-JitEntry *dvmFindJitEntry(const u2* pc)
-{
- return findJitEntry(pc);
-}
-
/*
* If a translated code address exists for the davik byte code
* pointer return it. This routine needs to be fast.
typedef struct ShadowSpace {
const u2* startPC; /* starting pc of jitted region */
const void* fp; /* starting fp of jitted region */
- void* glue; /* starting glue ptr of jitted region */
+ const void* glue; /* starting glue of jitted region */
SelfVerificationState selfVerificationState; /* self verification state */
const u2* endPC; /* ending pc of jitted region */
void* shadowFP; /* pointer to fp in shadow space */
const void* endShadowFP; /* ending fp in shadow space */
InstructionTrace trace[JIT_MAX_TRACE_LEN]; /* opcode trace for debugging */
int traceLength; /* counter for current trace length */
+ const Method* method; /* starting method of jitted region */
} ShadowSpace;
/*
void* dvmSelfVerificationShadowSpaceAlloc(Thread* self);
void dvmSelfVerificationShadowSpaceFree(Thread* self);
void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
- void* interpStatePtr);
+ InterpState* interpState);
void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
SelfVerificationState exitPoint);
#endif
* before jumping to native translation.
*/
dvmJitSelfVerificationStart:
- sub sp,sp,#4 @ allocate stack space
- str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r10, r0 @ r10 <- dvmJitGetCodeAddr(rPC)
mov r0,rPC @ r0<- program counter
mov r1,rFP @ r1<- frame pointer
mov r2,rGLUE @ r2<- InterpState pointer
bl dvmSelfVerificationSaveState @ save registers to shadow space
- ldr rFP,[r0,#20] @ rFP<- fp in shadow space
- add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
- ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
- add sp,sp,#4 @ restore stack
- bx r0 @ jump to the translation
+ ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+ add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+ bx r10 @ jump to the translation
/*
* Restore PC, registers, and interpState to original values
dvmJitSelfVerificationEnd:
mov r1,rFP @ pass ending fp
bl dvmSelfVerificationRestoreState @ restore pc and fp values
- ldr rPC,[r0,#0] @ restore PC
- ldr rFP,[r0,#4] @ restore FP
- ldr rGLUE,[r0,#8] @ restore InterpState
- ldr r1,[r0,#12] @ get exitPoint
+ ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
+ ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
+ ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+ ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
cmp r1,#0 @ check for punt condition
beq 1f
mov r2,#kJitSelfVerification @ ask for self verification
MTERP_SIZEOF(sizeofStackSaveArea, StackSaveArea, 20)
#endif
+ /* ShadowSpace fields */
+#if defined(WITH_JIT) && defined(WITH_SELF_VERIFICATION)
+MTERP_OFFSET(offShadowSpace_startPC, ShadowSpace, startPC, 0)
+MTERP_OFFSET(offShadowSpace_fp, ShadowSpace, fp, 4)
+MTERP_OFFSET(offShadowSpace_glue, ShadowSpace, glue, 8)
+MTERP_OFFSET(offShadowSpace_svState, ShadowSpace, selfVerificationState, 12)
+MTERP_OFFSET(offShadowSpace_shadowFP, ShadowSpace, shadowFP, 20)
+MTERP_OFFSET(offShadowSpace_interpState, ShadowSpace, interpState, 24)
+#endif
+
/* InstField fields */
#ifdef PROFILE_FIELD_ACCESS
MTERP_OFFSET(offInstField_byteOffset, InstField, byteOffset, 24)
* before jumping to native translation.
*/
dvmJitSelfVerificationStart:
- sub sp,sp,#4 @ allocate stack space
- str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r10, r0 @ r10 <- dvmJitGetCodeAddr(rPC)
mov r0,rPC @ r0<- program counter
mov r1,rFP @ r1<- frame pointer
mov r2,rGLUE @ r2<- InterpState pointer
bl dvmSelfVerificationSaveState @ save registers to shadow space
- ldr rFP,[r0,#20] @ rFP<- fp in shadow space
- add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
- ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
- add sp,sp,#4 @ restore stack
- bx r0 @ jump to the translation
+ ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+ add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+ bx r10 @ jump to the translation
/*
* Restore PC, registers, and interpState to original values
dvmJitSelfVerificationEnd:
mov r1,rFP @ pass ending fp
bl dvmSelfVerificationRestoreState @ restore pc and fp values
- ldr rPC,[r0,#0] @ restore PC
- ldr rFP,[r0,#4] @ restore FP
- ldr rGLUE,[r0,#8] @ restore InterpState
- ldr r1,[r0,#12] @ get exitPoint
+ ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
+ ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
+ ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+ ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
cmp r1,#0 @ check for punt condition
beq 1f
mov r2,#kJitSelfVerification @ ask for self verification
* before jumping to native translation.
*/
dvmJitSelfVerificationStart:
- sub sp,sp,#4 @ allocate stack space
- str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r10, r0 @ r10 <- dvmJitGetCodeAddr(rPC)
mov r0,rPC @ r0<- program counter
mov r1,rFP @ r1<- frame pointer
mov r2,rGLUE @ r2<- InterpState pointer
bl dvmSelfVerificationSaveState @ save registers to shadow space
- ldr rFP,[r0,#20] @ rFP<- fp in shadow space
- add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
- ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
- add sp,sp,#4 @ restore stack
- bx r0 @ jump to the translation
+ ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+ add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+ bx r10 @ jump to the translation
/*
* Restore PC, registers, and interpState to original values
dvmJitSelfVerificationEnd:
mov r1,rFP @ pass ending fp
bl dvmSelfVerificationRestoreState @ restore pc and fp values
- ldr rPC,[r0,#0] @ restore PC
- ldr rFP,[r0,#4] @ restore FP
- ldr rGLUE,[r0,#8] @ restore InterpState
- ldr r1,[r0,#12] @ get exitPoint
+ ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
+ ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
+ ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+ ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
cmp r1,#0 @ check for punt condition
beq 1f
mov r2,#kJitSelfVerification @ ask for self verification
* before jumping to native translation.
*/
dvmJitSelfVerificationStart:
- sub sp,sp,#4 @ allocate stack space
- str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r10, r0 @ r10 <- dvmJitGetCodeAddr(rPC)
mov r0,rPC @ r0<- program counter
mov r1,rFP @ r1<- frame pointer
mov r2,rGLUE @ r2<- InterpState pointer
bl dvmSelfVerificationSaveState @ save registers to shadow space
- ldr rFP,[r0,#20] @ rFP<- fp in shadow space
- add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
- ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
- add sp,sp,#4 @ restore stack
- bx r0 @ jump to the translation
+ ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+ add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+ bx r10 @ jump to the translation
/*
* Restore PC, registers, and interpState to original values
dvmJitSelfVerificationEnd:
mov r1,rFP @ pass ending fp
bl dvmSelfVerificationRestoreState @ restore pc and fp values
- ldr rPC,[r0,#0] @ restore PC
- ldr rFP,[r0,#4] @ restore FP
- ldr rGLUE,[r0,#8] @ restore InterpState
- ldr r1,[r0,#12] @ get exitPoint
+ ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
+ ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
+ ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+ ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
cmp r1,#0 @ check for punt condition
beq 1f
mov r2,#kJitSelfVerification @ ask for self verification
* before jumping to native translation.
*/
dvmJitSelfVerificationStart:
- sub sp,sp,#4 @ allocate stack space
- str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r10, r0 @ r10 <- dvmJitGetCodeAddr(rPC)
mov r0,rPC @ r0<- program counter
mov r1,rFP @ r1<- frame pointer
mov r2,rGLUE @ r2<- InterpState pointer
bl dvmSelfVerificationSaveState @ save registers to shadow space
- ldr rFP,[r0,#20] @ rFP<- fp in shadow space
- add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
- ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
- add sp,sp,#4 @ restore stack
- bx r0 @ jump to the translation
+ ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+ add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+ bx r10 @ jump to the translation
/*
* Restore PC, registers, and interpState to original values
dvmJitSelfVerificationEnd:
mov r1,rFP @ pass ending fp
bl dvmSelfVerificationRestoreState @ restore pc and fp values
- ldr rPC,[r0,#0] @ restore PC
- ldr rFP,[r0,#4] @ restore FP
- ldr rGLUE,[r0,#8] @ restore InterpState
- ldr r1,[r0,#12] @ get exitPoint
+ ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC
+ ldr rFP,[r0,#offShadowSpace_fp] @ restore FP
+ ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+ ldr r1,[r0,#offShadowSpace_svState] @ get self verification state
cmp r1,#0 @ check for punt condition
beq 1f
mov r2,#kJitSelfVerification @ ask for self verification