X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=vm%2Finterp%2FInterp.c;h=5df459adf13bd16447bca3eb06683b0d688ece7a;hb=2088bf0b9ebaf0d09ea3f531e1dd798430bfe8ce;hp=daaf0c0da79df824e9e06ce3dd509901379e0848;hpb=9a0e6ece95060792f60dc57040f033b2e5fd5d40;p=android-x86%2Fdalvik.git diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c index daaf0c0da..5df459adf 100644 --- a/vm/interp/Interp.c +++ b/vm/interp/Interp.c @@ -21,9 +21,7 @@ * facilitates switching between them. The standard interpreter may * use the "fast" or "portable" implementation. * - * Some debugger support functions are included here. Ideally their - * entire existence would be "#ifdef WITH_DEBUGGER", but we're not that - * aggressive in other parts of the code yet. + * Some debugger support functions are included here. */ #include "Dalvik.h" #include "interp/InterpDefs.h" @@ -44,12 +42,8 @@ static void dvmBreakpointSetFree(BreakpointSet* pSet); */ bool dvmBreakpointStartup(void) { -#ifdef WITH_DEBUGGER gDvm.breakpointSet = dvmBreakpointSetAlloc(); return (gDvm.breakpointSet != NULL); -#else - return true; -#endif } /* @@ -57,13 +51,10 @@ bool dvmBreakpointStartup(void) */ void dvmBreakpointShutdown(void) { -#ifdef WITH_DEBUGGER dvmBreakpointSetFree(gDvm.breakpointSet); -#endif } -#ifdef WITH_DEBUGGER /* * This represents a breakpoint inserted in the instruction stream. * @@ -73,7 +64,7 @@ void dvmBreakpointShutdown(void) typedef struct { Method* method; /* method we're associated with */ u2* addr; /* absolute memory address */ - u1 originalOpCode; /* original 8-bit opcode value */ + u1 originalOpcode; /* original 8-bit opcode value */ int setCount; /* #of times this breakpoint was set */ } Breakpoint; @@ -176,14 +167,14 @@ static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr) * * Returns "true" with the opcode in *pOrig on success. */ -static bool dvmBreakpointSetOriginalOpCode(const BreakpointSet* pSet, +static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet, const u2* addr, u1* pOrig) { int idx = dvmBreakpointSetFind(pSet, addr); if (idx < 0) return false; - *pOrig = pSet->breakpoints[idx].originalOpCode; + *pOrig = pSet->breakpoints[idx].originalOpcode; return true; } @@ -237,7 +228,7 @@ static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method, LOGV("+++ increasing breakpoint set size to %d\n", newSize); /* pSet->breakpoints will be NULL on first entry */ - newVec = realloc(pSet->breakpoints, newSize * sizeof(Breakpoint)); + newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint)); if (newVec == NULL) return false; @@ -248,7 +239,7 @@ static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method, pBreak = &pSet->breakpoints[pSet->count++]; pBreak->method = method; pBreak->addr = (u2*)addr; - pBreak->originalOpCode = *(u1*)addr; + pBreak->originalOpcode = *(u1*)addr; pBreak->setCount = 1; /* @@ -327,7 +318,7 @@ static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method, * need to. (Not worth worrying about.) */ dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr, - pBreak->originalOpCode); + pBreak->originalOpcode); ANDROID_MEMBAR_FULL(); if (idx != pSet->count-1) { @@ -376,7 +367,6 @@ static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz) } } } -#endif /*WITH_DEBUGGER*/ /* @@ -384,7 +374,6 @@ static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz) */ void dvmInitBreakpoints(void) { -#ifdef WITH_DEBUGGER /* quick sanity check */ BreakpointSet* pSet = gDvm.breakpointSet; dvmBreakpointSetLock(pSet); @@ -393,9 +382,6 @@ void dvmInitBreakpoints(void) /* generally not good, but we can keep going */ } dvmBreakpointSetUnlock(pSet); -#else - assert(false); -#endif } /* @@ -414,14 +400,10 @@ void dvmInitBreakpoints(void) */ void dvmAddBreakAddr(Method* method, unsigned int instrOffset) { -#ifdef WITH_DEBUGGER BreakpointSet* pSet = gDvm.breakpointSet; dvmBreakpointSetLock(pSet); dvmBreakpointSetAdd(pSet, method, instrOffset); dvmBreakpointSetUnlock(pSet); -#else - assert(false); -#endif } /* @@ -436,28 +418,30 @@ void dvmAddBreakAddr(Method* method, unsigned int instrOffset) */ void dvmClearBreakAddr(Method* method, unsigned int instrOffset) { -#ifdef WITH_DEBUGGER BreakpointSet* pSet = gDvm.breakpointSet; dvmBreakpointSetLock(pSet); dvmBreakpointSetRemove(pSet, method, instrOffset); dvmBreakpointSetUnlock(pSet); - -#else - assert(false); -#endif } -#ifdef WITH_DEBUGGER /* * Get the original opcode from under a breakpoint. + * + * On SMP hardware it's possible one core might try to execute a breakpoint + * after another core has cleared it. We need to handle the case where + * there's no entry in the breakpoint set. (The memory barriers in the + * locks and in the breakpoint update code should ensure that, once we've + * observed the absence of a breakpoint entry, we will also now observe + * the restoration of the original opcode. The fact that we're holding + * the lock prevents other threads from confusing things further.) */ -u1 dvmGetOriginalOpCode(const u2* addr) +u1 dvmGetOriginalOpcode(const u2* addr) { BreakpointSet* pSet = gDvm.breakpointSet; u1 orig = 0; dvmBreakpointSetLock(pSet); - if (!dvmBreakpointSetOriginalOpCode(pSet, addr, &orig)) { + if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) { orig = *(u1*)addr; if (orig == OP_BREAKPOINT) { LOGE("GLITCH: can't find breakpoint, opcode is still set\n"); @@ -488,7 +472,6 @@ void dvmFlushBreakpoints(ClassObject* clazz) dvmBreakpointSetFlush(pSet, clazz); dvmBreakpointSetUnlock(pSet); } -#endif /* * Add a single step event. Currently this is a global item. @@ -501,7 +484,6 @@ void dvmFlushBreakpoints(ClassObject* clazz) */ bool dvmAddSingleStep(Thread* thread, int size, int depth) { -#ifdef WITH_DEBUGGER StepControl* pCtrl = &gDvm.stepControl; if (pCtrl->active && thread != pCtrl->thread) { @@ -546,7 +528,7 @@ bool dvmAddSingleStep(Thread* thread, int size, int depth) saveArea = SAVEAREA_FROM_FP(fp); method = saveArea->method; - if (!dvmIsBreakFrame(fp) && !dvmIsNativeMethod(method)) + if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method)) break; prevFp = fp; } @@ -563,7 +545,7 @@ bool dvmAddSingleStep(Thread* thread, int size, int depth) */ LOGV("##### init step while in native method\n"); fp = prevFp; - assert(!dvmIsBreakFrame(fp)); + assert(!dvmIsBreakFrame((u4*)fp)); assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method)); saveArea = SAVEAREA_FROM_FP(fp); } @@ -597,10 +579,6 @@ bool dvmAddSingleStep(Thread* thread, int size, int depth) dvmJdwpStepSizeStr(pCtrl->size)); return true; -#else - assert(false); - return false; -#endif } /* @@ -608,13 +586,9 @@ bool dvmAddSingleStep(Thread* thread, int size, int depth) */ void dvmClearSingleStep(Thread* thread) { -#ifdef WITH_DEBUGGER UNUSED_PARAMETER(thread); gDvm.stepControl.active = false; -#else - assert(false); -#endif } @@ -968,7 +942,7 @@ bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData) size = arrayData[2] | (((u4)arrayData[3]) << 16); if (size > arrayObj->length) { - dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL); + dvmThrowAIOOBE(size, arrayObj->length); return false; } copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width); @@ -1078,14 +1052,15 @@ static char* classNameFromIndex(const Method* method, int ref, } const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref); - char* dotClassName = dvmDescriptorToDot(className); + char* dotClassName = dvmHumanReadableDescriptor(className); if (flags == 0) return dotClassName; char* result = (char*) malloc(kBufLen); if ((flags & kThrowShow_accessFromClass) != 0) { - char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor); + char* dotFromName = + dvmHumanReadableDescriptor(method->clazz->descriptor); snprintf(result, kBufLen, "tried to access class %s from class %s", dotClassName, dotFromName); free(dotFromName); @@ -1115,11 +1090,12 @@ static char* fieldNameFromIndex(const Method* method, int ref, className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx); fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx); - char* dotName = dvmDescriptorToDot(className); + char* dotName = dvmHumanReadableDescriptor(className); char* result = (char*) malloc(kBufLen); if ((flags & kThrowShow_accessFromClass) != 0) { - char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor); + char* dotFromName = + dvmHumanReadableDescriptor(method->clazz->descriptor); snprintf(result, kBufLen, "tried to access field %s.%s from class %s", dotName, fieldName, dotFromName); free(dotFromName); @@ -1148,11 +1124,12 @@ static char* methodNameFromIndex(const Method* method, int ref, className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx); methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx); - char* dotName = dvmDescriptorToDot(className); + char* dotName = dvmHumanReadableDescriptor(className); char* result = (char*) malloc(kBufLen); if ((flags & kThrowShow_accessFromClass) != 0) { - char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor); + char* dotFromName = + dvmHumanReadableDescriptor(method->clazz->descriptor); char* desc = dexProtoCopyMethodDescriptor(&method->prototype); snprintf(result, kBufLen, "tried to access method %s.%s:%s from class %s", @@ -1263,7 +1240,6 @@ void dvmInterpret(Thread* self, const Method* method, JValue* pResult) extern void dvmJitToInterpSingleStep(); extern void dvmJitToInterpTraceSelectNoChain(); extern void dvmJitToInterpTraceSelect(); - extern void dvmJitToPatchPredictedChain(); #if defined(WITH_SELF_VERIFICATION) extern void dvmJitToInterpBackwardBranch(); #endif @@ -1279,13 +1255,18 @@ void dvmInterpret(Thread* self, const Method* method, JValue* pResult) dvmJitToInterpSingleStep, dvmJitToInterpTraceSelectNoChain, dvmJitToInterpTraceSelect, - dvmJitToPatchPredictedChain, #if defined(WITH_SELF_VERIFICATION) dvmJitToInterpBackwardBranch, #endif }; - assert(self->inJitCodeCache == NULL); + /* + * If the previous VM left the code cache through single-stepping the + * inJitCodeCache flag will be set when the VM is re-entered (for example, + * in self-verification mode we single-step NEW_INSTANCE which may re-enter + * the VM through findClassFromLoaderNoInit). Because of that, we cannot + * assert that self->inJitCodeCache is NULL here. + */ #endif @@ -1293,9 +1274,7 @@ void dvmInterpret(Thread* self, const Method* method, JValue* pResult) interpState.debugTrackedRefStart = dvmReferenceTableEntries(&self->internalLocalRefTable); #endif -#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) interpState.debugIsMethodEntry = true; -#endif #if defined(WITH_JIT) dvmJitCalleeSave(interpState.calleeSave); /* Initialize the state to kJitNot */ @@ -1366,19 +1345,15 @@ void dvmInterpret(Thread* self, const Method* method, JValue* pResult) LOGVV("threadid=%d: interp STD\n", self->threadId); change = (*stdInterp)(self, &interpState); break; -#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) || defined(WITH_JIT) case INTERP_DBG: LOGVV("threadid=%d: interp DBG\n", self->threadId); change = dvmInterpretDbg(self, &interpState); break; -#endif default: dvmAbort(); } } - /* Never on the heap, so no write barrier needed. */ - assert(!dvmIsValidObjectAddress(pResult)); *pResult = interpState.retval; #if defined(WITH_JIT) dvmJitCalleeRestore(interpState.calleeSave);