From: Ben Cheng Date: Thu, 15 Oct 2009 21:52:45 +0000 (-0700) Subject: Make the traige process for self-verification found divergence easier. X-Git-Tag: android-x86-2.2~557^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=ccd6c0102d1f898aaea1c94761167fdd083b5275;p=android-x86%2Fdalvik.git Make the traige process for self-verification found divergence easier. 1. Automatically replay the code compilation with verbose mode turned on for the offending compilation. 3. Mark the registers with divergence explicitly. 2. Print accurate operand names using the dataflow attributes. Constant values are still printed for reference only. 3. Fixed a few correctness/style issues in self-verification code. --- diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c index 9db641edc..018dc4a1d 100644 --- a/vm/compiler/Compiler.c +++ b/vm/compiler/Compiler.c @@ -73,9 +73,14 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 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; diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h index 47de33d8b..06367a6ec 100644 --- a/vm/compiler/Compiler.h +++ b/vm/compiler/Compiler.h @@ -36,14 +36,16 @@ typedef enum JitInstructionSetType { /* 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 { @@ -154,9 +156,11 @@ void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit, 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 */ diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c index 9a2e5c055..f8e736b09 100644 --- a/vm/compiler/Dataflow.c +++ b/vm/compiler/Dataflow.c @@ -17,6 +17,7 @@ #include "Dalvik.h" #include "Dataflow.h" #include "Loop.h" +#include "dexdump/OpCodeNames.h" /* * Main table containing data flow attributes for each bytecode. The first @@ -817,6 +818,59 @@ int dvmConvertSSARegToDalvik(CompilationUnit *cUnit, int ssaReg) * 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]; diff --git a/vm/compiler/Dataflow.h b/vm/compiler/Dataflow.h index e4ae93d96..384d43017 100644 --- a/vm/compiler/Dataflow.h +++ b/vm/compiler/Dataflow.h @@ -68,6 +68,10 @@ typedef enum DataFlowAttributePos { 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 { diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c index 163cdf811..959c99ac1 100644 --- a/vm/compiler/Frontend.c +++ b/vm/compiler/Frontend.c @@ -16,7 +16,6 @@ #include "Dalvik.h" #include "libdex/OpCode.h" -#include "dexdump/OpCodeNames.h" #include "interp/Jit.h" #include "CompilerInternals.h" @@ -42,7 +41,8 @@ static inline int parseInsn(const u2 *codePtr, DecodedInstruction *decInsn, 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; } diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c index d1f9870ff..57d5d74fb 100644 --- a/vm/compiler/codegen/arm/ArchUtility.c +++ b/vm/compiler/codegen/arm/ArchUtility.c @@ -276,7 +276,7 @@ void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr) 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); diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c index e386fac58..81dd0e39a 100644 --- a/vm/compiler/codegen/arm/Assemble.c +++ b/vm/compiler/codegen/arm/Assemble.c @@ -1027,7 +1027,6 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) ChainCellCounts chainCellCounts; int descSize = jitTraceDescriptionSize(cUnit->traceDesc); - info->codeAddress = NULL; info->instructionSet = cUnit->instructionSet; /* Beginning offset needs to allow space for chain cell offset */ @@ -1109,6 +1108,8 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) 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; @@ -1137,7 +1138,6 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) /* 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; @@ -1477,6 +1477,31 @@ static int dumpTraceProfile(JitEntry *p) 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) { diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c index 4a85fb255..c0729abf7 100644 --- a/vm/compiler/codegen/arm/Codegen.c +++ b/vm/compiler/codegen/arm/Codegen.c @@ -3997,7 +3997,9 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) 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); @@ -4209,25 +4211,33 @@ gen_fallthrough: /* 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 */ diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c index d8dcf1eff..1d8665785 100644 --- a/vm/interp/Jit.c +++ b/vm/interp/Jit.c @@ -60,11 +60,10 @@ void dvmSelfVerificationShadowSpaceFree(Thread* self) * 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; @@ -75,7 +74,7 @@ void* dvmSelfVerificationSaveState(const u2* pc, const void* fp, 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; @@ -90,12 +89,18 @@ void* dvmSelfVerificationSaveState(const u2* pc, const void* fp, // 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; @@ -132,10 +137,10 @@ void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp, 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); } @@ -150,11 +155,12 @@ void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp, } /* 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" : ""); } } @@ -174,19 +180,19 @@ static void selfVerificationDumpState(const u2* pc, Thread* self) 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); } @@ -204,15 +210,18 @@ static void selfVerificationDumpTrace(const u2* pc, Thread* self) 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); } @@ -254,17 +263,20 @@ static bool selfVerificationDebugInterp(const u2* pc, Thread* self) 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) { @@ -275,19 +287,21 @@ static bool selfVerificationDebugInterp(const u2* pc, Thread* self) (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); } } @@ -298,25 +312,25 @@ static bool selfVerificationDebugInterp(const u2* pc, Thread* self) 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; } @@ -656,7 +670,7 @@ int dvmCheckJit(const u2* pc, Thread* self, InterpState* interpState) return switchInterp; } -static inline JitEntry *findJitEntry(const u2* pc) +JitEntry *dvmFindJitEntry(const u2* pc) { int idx = dvmJitHash(pc); @@ -674,11 +688,6 @@ static inline JitEntry *findJitEntry(const u2* 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. diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h index 70931b867..fe740e590 100644 --- a/vm/interp/Jit.h +++ b/vm/interp/Jit.h @@ -43,7 +43,7 @@ typedef struct InstructionTrace { 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 */ @@ -55,6 +55,7 @@ typedef struct ShadowSpace { 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; /* @@ -63,7 +64,7 @@ typedef struct 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 diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S index 461cc6672..bca89c1ff 100644 --- a/vm/mterp/armv5te/footer.S +++ b/vm/mterp/armv5te/footer.S @@ -229,17 +229,14 @@ common_selectTrace: * 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 @@ -248,10 +245,10 @@ dvmJitSelfVerificationStart: 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 diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h index e157c375a..9dbf6e80e 100644 --- a/vm/mterp/common/asm-constants.h +++ b/vm/mterp/common/asm-constants.h @@ -169,6 +169,16 @@ MTERP_OFFSET(offStackSaveArea_returnAddr, StackSaveArea, returnAddr, 16) 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) diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S index 07075bb8f..6153010bd 100644 --- a/vm/mterp/out/InterpAsm-armv4t.S +++ b/vm/mterp/out/InterpAsm-armv4t.S @@ -9701,17 +9701,14 @@ common_selectTrace: * 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 @@ -9720,10 +9717,10 @@ dvmJitSelfVerificationStart: 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 diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S index 55ac716a7..dde4bd516 100644 --- a/vm/mterp/out/InterpAsm-armv5te-vfp.S +++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S @@ -9219,17 +9219,14 @@ common_selectTrace: * 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 @@ -9238,10 +9235,10 @@ dvmJitSelfVerificationStart: 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 diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S index 55f6fee94..b7d8a6cd9 100644 --- a/vm/mterp/out/InterpAsm-armv5te.S +++ b/vm/mterp/out/InterpAsm-armv5te.S @@ -9695,17 +9695,14 @@ common_selectTrace: * 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 @@ -9714,10 +9711,10 @@ dvmJitSelfVerificationStart: 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 diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S index 3c896ae98..ea9e713fc 100644 --- a/vm/mterp/out/InterpAsm-armv7-a.S +++ b/vm/mterp/out/InterpAsm-armv7-a.S @@ -9155,17 +9155,14 @@ common_selectTrace: * 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 @@ -9174,10 +9171,10 @@ dvmJitSelfVerificationStart: 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