OSDN Git Service

am af5aa1f4: Don\'t treat dvmJitToPatchPredictedChain as a Jit-to-Interp entry point.
[android-x86/dalvik.git] / vm / interp / Interp.c
index daaf0c0..5df459a 100644 (file)
@@ -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);