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
#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
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;
{
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;
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
* Because we leave no space for local variables, "curFrame" points
* directly at the method arguments.
*/
- (*method->nativeFunc)(self->curFrame, pResult, method, self);
+ (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
TRACE_METHOD_EXIT(self, method);
} else {
dvmInterpret(self, method, pResult);
* Because we leave no space for local variables, "curFrame" points
* directly at the method arguments.
*/
- (*method->nativeFunc)(self->curFrame, pResult, method, self);
+ (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
TRACE_METHOD_EXIT(self, method);
} else {
dvmInterpret(self, method, pResult);
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
s4* ins;
int verifyCount, argListLength;
JValue retval;
+ bool needPop = false;
/* verify arg count */
if (argList != NULL)
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);
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)) {
TRACE_METHOD_ENTER(self, method);
* Because we leave no space for local variables, "curFrame" points
* directly at the method arguments.
*/
- (*method->nativeFunc)(self->curFrame, &retval, method, self);
+ (*method->nativeFunc)((u4*)self->curFrame, &retval, method, self);
TRACE_METHOD_EXIT(self, method);
} 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.
* 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;
}
int count = 0;
for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
- if (!dvmIsBreakFrame(fp))
+ if (!dvmIsBreakFrame((u4*)fp))
count++;
}
StackSaveArea* saveArea;
retry:
- if (dvmIsBreakFrame(caller)) {
+ if (dvmIsBreakFrame((u4*)caller)) {
/* pop up one more */
caller = SAVEAREA_FROM_FP(caller)->prevFrame;
if (caller == NULL)
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 */
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. */
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);
*
* 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
{
void* framePtr = thread->curFrame;
- if (framePtr == NULL || dvmIsBreakFrame(framePtr))
+ if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr))
return false;
const StackSaveArea* saveArea = SAVEAREA_FROM_FP(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)
saveArea = SAVEAREA_FROM_FP(framePtr);
method = saveArea->method;
- if (dvmIsBreakFrame(framePtr)) {
+ if (dvmIsBreakFrame((u4*)framePtr)) {
//dvmPrintDebugMessage(target, " (break frame)\n");
} else {
int relPc;
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);
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,
}
}
dvmPrintDebugMessage(target, "\n");
+
+ if (needThreadUnlock) {
+ dvmUnlockThreadList();
+ }
}