OSDN Git Service

am af5aa1f4: Don\'t treat dvmJitToPatchPredictedChain as a Jit-to-Interp entry point.
[android-x86/dalvik.git] / vm / interp / Stack.c
index 1ebbcf0..54be90e 100644 (file)
@@ -100,7 +100,7 @@ static bool dvmPushInterpFrame(Thread* self, const Method* method)
     memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
 #endif
 #ifdef EASY_GDB
-    breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
+    breakSaveBlock->prevSave = (StackSaveArea*)FP_FROM_SAVEAREA(self->curFrame);
     saveBlock->prevSave = breakSaveBlock;
 #endif
 
@@ -176,8 +176,10 @@ bool dvmPushJNIFrame(Thread* self, const Method* method)
 #ifdef EASY_GDB
     if (self->curFrame == NULL)
         breakSaveBlock->prevSave = NULL;
-    else
-        breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
+    else {
+        void* fp = FP_FROM_SAVEAREA(self->curFrame);
+        breakSaveBlock->prevSave = (StackSaveArea*)fp;
+    }
     saveBlock->prevSave = breakSaveBlock;
 #endif
 
@@ -245,7 +247,7 @@ bool dvmPushLocalFrame(Thread* self, const Method* method)
     memset(stackPtr, 0xaf, stackReq);
 #endif
 #ifdef EASY_GDB
-    saveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
+    saveBlock->prevSave = (StackSaveArea*)FP_FROM_SAVEAREA(self->curFrame);
 #endif
 
     saveBlock->prevFrame = self->curFrame;
@@ -276,13 +278,13 @@ bool dvmPopLocalFrame(Thread* self)
 {
     StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame);
 
-    assert(!dvmIsBreakFrame(self->curFrame));
+    assert(!dvmIsBreakFrame((u4*)self->curFrame));
     if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
         /*
          * The previous frame doesn't have the same method pointer -- we've
          * been asked to pop too much.
          */
-        assert(dvmIsBreakFrame(saveBlock->prevFrame) ||
+        assert(dvmIsBreakFrame((u4*)saveBlock->prevFrame) ||
                !dvmIsNativeMethod(
                        SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
         return false;
@@ -314,7 +316,7 @@ static bool dvmPopFrame(Thread* self)
         return false;
 
     saveBlock = SAVEAREA_FROM_FP(self->curFrame);
-    assert(!dvmIsBreakFrame(self->curFrame));
+    assert(!dvmIsBreakFrame((u4*)self->curFrame));
 
     /*
      * Remove everything up to the break frame.  If this was a call into
@@ -429,8 +431,6 @@ static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
 void dvmCallMethod(Thread* self, const Method* method, Object* obj,
     JValue* pResult, ...)
 {
-    JValue result;
-
     va_list args;
     va_start(args, pResult);
     dvmCallMethodV(self, method, obj, false, pResult, args);
@@ -520,22 +520,20 @@ void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
     //dvmDumpThreadStack(dvmThreadSelf());
 
     if (dvmIsNativeMethod(method)) {
-#ifdef WITH_PROFILER
         TRACE_METHOD_ENTER(self, method);
-#endif
         /*
          * Because we leave no space for local variables, "curFrame" points
          * directly at the method arguments.
          */
-        (*method->nativeFunc)(self->curFrame, pResult, method, self);
-#ifdef WITH_PROFILER
+        (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
         TRACE_METHOD_EXIT(self, method);
-#endif
     } else {
         dvmInterpret(self, method, pResult);
     }
 
+#ifndef NDEBUG
 bail:
+#endif
     dvmPopFrame(self);
 }
 
@@ -626,17 +624,13 @@ void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
 #endif
 
     if (dvmIsNativeMethod(method)) {
-#ifdef WITH_PROFILER
         TRACE_METHOD_ENTER(self, method);
-#endif
         /*
          * Because we leave no space for local variables, "curFrame" points
          * directly at the method arguments.
          */
-        (*method->nativeFunc)(self->curFrame, pResult, method, self);
-#ifdef WITH_PROFILER
+        (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
         TRACE_METHOD_EXIT(self, method);
-#endif
     } else {
         dvmInterpret(self, method, pResult);
     }
@@ -645,6 +639,20 @@ bail:
     dvmPopFrame(self);
 }
 
+static void throwArgumentTypeMismatch(int argIndex, ClassObject* expected,
+    DataObject* arg)
+{
+    char* expectedClassName = dvmHumanReadableDescriptor(expected->descriptor);
+    char* actualClassName = (arg != NULL)
+        ? dvmHumanReadableDescriptor(arg->obj.clazz->descriptor)
+        : strdup("null");
+    dvmThrowExceptionFmt("Ljava/lang/IllegalArgumentException;",
+        "argument %d should have type %s, got %s",
+        argIndex + 1, expectedClassName, actualClassName);
+    free(expectedClassName);
+    free(actualClassName);
+}
+
 /*
  * Invoke a method, using the specified arguments and return type, through
  * one of the reflection interfaces.  Could be a virtual or direct method
@@ -666,6 +674,7 @@ Object* dvmInvokeMethod(Object* obj, const Method* method,
     s4* ins;
     int verifyCount, argListLength;
     JValue retval;
+    bool needPop = false;
 
     /* verify arg count */
     if (argList != NULL)
@@ -673,16 +682,16 @@ Object* dvmInvokeMethod(Object* obj, const Method* method,
     else
         argListLength = 0;
     if (argListLength != (int) params->length) {
-        LOGI("invoke: expected %d args, received %d args\n",
+        dvmThrowExceptionFmt("Ljava/lang/IllegalArgumentException;",
+            "wrong number of arguments; expected %d, got %d",
             params->length, argListLength);
-        dvmThrowException("Ljava/lang/IllegalArgumentException;",
-            "wrong number of arguments");
         return NULL;
     }
 
     clazz = callPrep(self, method, obj, !noAccessCheck);
     if (clazz == NULL)
         return NULL;
+    needPop = true;
 
     /* "ins" for new frame start at frame pointer plus locals */
     ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
@@ -712,46 +721,45 @@ Object* dvmInvokeMethod(Object* obj, const Method* method,
 
         width = dvmConvertArgument(*args++, *types++, ins);
         if (width < 0) {
-            if (*(args-1) != NULL) {
-                LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n",
-                    i, (*(args-1))->obj.clazz->descriptor,
-                    (*(types-1))->descriptor);
-            }
             dvmPopFrame(self);      // throw wants to pull PC out of stack
-            dvmThrowException("Ljava/lang/IllegalArgumentException;",
-                "argument type mismatch");
-            goto bail_popped;
+            needPop = false;
+            throwArgumentTypeMismatch(i, *(types-1), *(args-1));
+            goto bail;
         }
 
         ins += width;
         verifyCount += width;
     }
 
+#ifndef NDEBUG
     if (verifyCount != method->insSize) {
         LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
             method->insSize, clazz->descriptor, method->name);
         assert(false);
         goto bail;
     }
-    //dvmDumpThreadStack(dvmThreadSelf());
+#endif
 
     if (dvmIsNativeMethod(method)) {
-#ifdef WITH_PROFILER
         TRACE_METHOD_ENTER(self, method);
-#endif
         /*
          * Because we leave no space for local variables, "curFrame" points
          * directly at the method arguments.
          */
-        (*method->nativeFunc)(self->curFrame, &retval, method, self);
-#ifdef WITH_PROFILER
+        (*method->nativeFunc)((u4*)self->curFrame, &retval, method, self);
         TRACE_METHOD_EXIT(self, method);
-#endif
     } else {
         dvmInterpret(self, method, &retval);
     }
 
     /*
+     * Pop the frame immediately.  The "wrap" calls below can cause
+     * allocations, and we don't want the GC to walk the now-dead frame.
+     */
+    dvmPopFrame(self);
+    needPop = false;
+
+    /*
      * If an exception is raised, wrap and replace.  This is necessary
      * because the invoked method could have thrown a checked exception
      * that the caller wasn't prepared for.
@@ -770,14 +778,15 @@ Object* dvmInvokeMethod(Object* obj, const Method* method,
          * in "retval" is undefined.
          */
         if (returnType != NULL) {
-            retObj = (Object*)dvmWrapPrimitive(retval, returnType);
+            retObj = (Object*)dvmBoxPrimitive(retval, returnType);
             dvmReleaseTrackedAlloc(retObj, NULL);
         }
     }
 
 bail:
-    dvmPopFrame(self);
-bail_popped:
+    if (needPop) {
+        dvmPopFrame(self);
+    }
     return retObj;
 }
 
@@ -790,7 +799,7 @@ static int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
 {
     LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt;
 
-    // We know that this callback will be called in 
+    // We know that this callback will be called in
     // ascending address order, so keep going until we find
     // a match or we've just gone past it.
 
@@ -834,7 +843,7 @@ int dvmLineNumFromPC(const Method* method, u4 relPc)
             method->prototype.protoIdx,
             method->accessFlags,
             lineNumForPcCb, NULL, &context);
-    
+
     return context.lineNum;
 }
 
@@ -848,7 +857,7 @@ int dvmComputeExactFrameDepth(const void* fp)
     int count = 0;
 
     for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
-        if (!dvmIsBreakFrame(fp))
+        if (!dvmIsBreakFrame((u4*)fp))
             count++;
     }
 
@@ -867,9 +876,9 @@ int dvmComputeExactFrameDepth(const void* fp)
 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
 {
     const u1* interpStackStart = thread->interpStackStart;
-    const u1* interpStackBottom = interpStackStart - thread->interpStackSize;
 
-    assert((u1*) fp >= interpStackBottom && (u1*) fp < interpStackStart);
+    assert((u1*) fp >= interpStackStart - thread->interpStackSize);
+    assert((u1*) fp < interpStackStart);
     return interpStackStart - (u1*) fp;
 }
 
@@ -884,7 +893,7 @@ void* dvmGetCallerFP(const void* curFrame)
     StackSaveArea* saveArea;
 
 retry:
-    if (dvmIsBreakFrame(caller)) {
+    if (dvmIsBreakFrame((u4*)caller)) {
         /* pop up one more */
         caller = SAVEAREA_FROM_FP(caller)->prevFrame;
         if (caller == NULL)
@@ -934,7 +943,7 @@ ClassObject* dvmGetCaller2Class(const void* curFrame)
     void* callerCaller;
 
     /* at the top? */
-    if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
+    if (dvmIsBreakFrame((u4*)caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
         return NULL;
 
     /* go one more */
@@ -957,7 +966,7 @@ ClassObject* dvmGetCaller3Class(const void* curFrame)
     int i;
 
     /* at the top? */
-    if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
+    if (dvmIsBreakFrame((u4*)caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
         return NULL;
 
     /* Walk up two frames if possible. */
@@ -966,7 +975,7 @@ ClassObject* dvmGetCaller3Class(const void* curFrame)
         if (caller == NULL)
             return NULL;
     }
-    
+
     return SAVEAREA_FROM_FP(caller)->method->clazz;
 }
 
@@ -994,7 +1003,7 @@ bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
         return false;
 
     for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
-        if (!dvmIsBreakFrame(fp))
+        if (!dvmIsBreakFrame((u4*)fp))
             array[idx++] = SAVEAREA_FROM_FP(fp)->method;
     }
     assert(idx == depth);
@@ -1098,7 +1107,7 @@ void dvmCleanupStackOverflow(Thread* self, const Object* exception)
  *
  * The other thread might be alive, so this has to work carefully.
  *
- * We assume the thread list lock is currently held.
+ * The thread list lock must be held.
  *
  * Returns "true" if we successfully recover the object.  "*pOwner" will
  * be NULL if we can't determine the owner for some reason (e.g. race
@@ -1109,7 +1118,7 @@ static bool extractMonitorEnterObject(Thread* thread, Object** pLockObj,
 {
     void* framePtr = thread->curFrame;
 
-    if (framePtr == NULL || dvmIsBreakFrame(framePtr))
+    if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr))
         return false;
 
     const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr);
@@ -1193,10 +1202,17 @@ static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
     bool first = true;
 
     /*
+     * We call functions that require us to be holding the thread list lock.
+     * It's probable that the caller has already done so, but it's not
+     * guaranteed.  If it's not locked, lock it now.
+     */
+    bool needThreadUnlock = dvmTryLockThreadList();
+
+    /*
      * The "currentPc" is updated whenever we execute an instruction that
      * might throw an exception.  Show it here.
      */
-    if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) {
+    if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) {
         saveArea = SAVEAREA_FROM_FP(framePtr);
 
         if (saveArea->xtra.currentPc != NULL)
@@ -1207,7 +1223,7 @@ static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
         saveArea = SAVEAREA_FROM_FP(framePtr);
         method = saveArea->method;
 
-        if (dvmIsBreakFrame(framePtr)) {
+        if (dvmIsBreakFrame((u4*)framePtr)) {
             //dvmPrintDebugMessage(target, "  (break frame)\n");
         } else {
             int relPc;
@@ -1217,7 +1233,7 @@ static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
             else
                 relPc = -1;
 
-            char* className = dvmDescriptorToDot(method->clazz->descriptor);
+            char* className = dvmHumanReadableDescriptor(method->clazz->descriptor);
             if (dvmIsNativeMethod(method))
                 dvmPrintDebugMessage(target,
                     "  at %s.%s(Native Method)\n", className, method->name);
@@ -1243,16 +1259,26 @@ static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
                     Monitor* mon = thread->waitMonitor;
                     Object* obj = dvmGetMonitorObject(mon);
                     if (obj != NULL) {
-                        className = dvmDescriptorToDot(obj->clazz->descriptor);
-                        dvmPrintDebugMessage(target,
-                            "  - waiting on <%p> (a %s)\n", obj, className);
+                        Thread* joinThread = NULL;
+                        className = dvmHumanReadableDescriptor(obj->clazz->descriptor);
+                        if (strcmp(className, "java.lang.VMThread") == 0) {
+                            joinThread = dvmGetThreadFromThreadObject(obj);
+                        }
+                        if (joinThread == NULL) {
+                            dvmPrintDebugMessage(target,
+                                "  - waiting on <%p> (a %s)\n", obj, className);
+                        } else {
+                            dvmPrintDebugMessage(target,
+                                "  - waiting on <%p> (a %s) tid=%d\n",
+                                obj, className, joinThread->threadId);
+                        }
                         free(className);
                     }
                 } else if (thread->status == THREAD_MONITOR) {
                     Object* obj;
                     Thread* owner;
                     if (extractMonitorEnterObject(thread, &obj, &owner)) {
-                        className = dvmDescriptorToDot(obj->clazz->descriptor);
+                        className = dvmHumanReadableDescriptor(obj->clazz->descriptor);
                         if (owner != NULL) {
                             char* threadName = dvmGetThreadName(owner);
                             dvmPrintDebugMessage(target,
@@ -1296,6 +1322,10 @@ static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
         }
     }
     dvmPrintDebugMessage(target, "\n");
+
+    if (needThreadUnlock) {
+        dvmUnlockThreadList();
+    }
 }
 
 
@@ -1380,4 +1410,3 @@ void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
     dumpFrames(target, stackCopy + fpOffset, thread);
     free(stackCopy);
 }
-