2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Stacks and their uses (e.g. native --> interpreted method calls).
20 * See the majestic ASCII art in Stack.h.
29 * Initialize the interpreter stack in a new thread.
31 * Currently this doesn't do much, since we don't need to zero out the
32 * stack (and we really don't want to if it was created with mmap).
34 bool dvmInitInterpStack(Thread* thread, int stackSize)
36 assert(thread->interpStackStart != NULL);
38 assert(thread->curFrame == NULL);
44 * We're calling an interpreted method from an internal VM function or
47 * Push a frame for an interpreted method onto the stack. This is only
48 * used when calling into interpreted code from native code. (The
49 * interpreter does its own stack frame manipulation for interp-->interp
52 * The size we need to reserve is the sum of parameters, local variables,
53 * saved goodies, and outbound parameters.
55 * We start by inserting a "break" frame, which ensures that the interpreter
56 * hands control back to us after the function we call returns or an
57 * uncaught exception is thrown.
59 static bool dvmPushInterpFrame(Thread* self, const Method* method)
61 StackSaveArea* saveBlock;
62 StackSaveArea* breakSaveBlock;
66 assert(!dvmIsNativeMethod(method));
67 assert(!dvmIsAbstractMethod(method));
69 stackReq = method->registersSize * 4 // params + locals
70 + sizeof(StackSaveArea) * 2 // break frame + regular frame
71 + method->outsSize * 4; // args to other methods
73 if (self->curFrame != NULL)
74 stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
76 stackPtr = self->interpStackStart;
78 if (stackPtr - stackReq < self->interpStackEnd) {
79 /* not enough space */
80 LOGW("Stack overflow on call to interp "
81 "(req=%d top=%p cur=%p size=%d %s.%s)\n",
82 stackReq, self->interpStackStart, self->curFrame,
83 self->interpStackSize, method->clazz->descriptor, method->name);
84 dvmHandleStackOverflow(self, method);
85 assert(dvmCheckException(self));
90 * Shift the stack pointer down, leaving space for the function's
91 * args/registers and save area.
93 stackPtr -= sizeof(StackSaveArea);
94 breakSaveBlock = (StackSaveArea*)stackPtr;
95 stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
96 saveBlock = (StackSaveArea*) stackPtr;
98 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
99 /* debug -- memset the new stack, unless we want valgrind's help */
100 memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
103 breakSaveBlock->prevSave = (StackSaveArea*)FP_FROM_SAVEAREA(self->curFrame);
104 saveBlock->prevSave = breakSaveBlock;
107 breakSaveBlock->prevFrame = self->curFrame;
108 breakSaveBlock->savedPc = NULL; // not required
109 breakSaveBlock->xtra.localRefCookie = 0; // not required
110 breakSaveBlock->method = NULL;
111 saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
112 saveBlock->savedPc = NULL; // not required
113 saveBlock->xtra.currentPc = NULL; // not required?
114 saveBlock->method = method;
116 LOGVV("PUSH frame: old=%p new=%p (size=%d)\n",
117 self->curFrame, FP_FROM_SAVEAREA(saveBlock),
118 (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
120 self->curFrame = FP_FROM_SAVEAREA(saveBlock);
126 * We're calling a JNI native method from an internal VM fuction or
127 * via reflection. This is also used to create the "fake" native-method
128 * frames at the top of the interpreted stack.
130 * This actually pushes two frames; the first is a "break" frame.
132 * The top frame has additional space for JNI local reference tracking.
134 bool dvmPushJNIFrame(Thread* self, const Method* method)
136 StackSaveArea* saveBlock;
137 StackSaveArea* breakSaveBlock;
141 assert(dvmIsNativeMethod(method));
143 stackReq = method->registersSize * 4 // params only
144 + sizeof(StackSaveArea) * 2; // break frame + regular frame
146 if (self->curFrame != NULL)
147 stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
149 stackPtr = self->interpStackStart;
151 if (stackPtr - stackReq < self->interpStackEnd) {
152 /* not enough space */
153 LOGW("Stack overflow on call to native "
154 "(req=%d top=%p cur=%p size=%d '%s')\n",
155 stackReq, self->interpStackStart, self->curFrame,
156 self->interpStackSize, method->name);
157 dvmHandleStackOverflow(self, method);
158 assert(dvmCheckException(self));
163 * Shift the stack pointer down, leaving space for just the stack save
164 * area for the break frame, then shift down farther for the full frame.
165 * We leave space for the method args, which are copied in later.
167 stackPtr -= sizeof(StackSaveArea);
168 breakSaveBlock = (StackSaveArea*)stackPtr;
169 stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
170 saveBlock = (StackSaveArea*) stackPtr;
172 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
173 /* debug -- memset the new stack */
174 memset(stackPtr, 0xaf, stackReq);
177 if (self->curFrame == NULL)
178 breakSaveBlock->prevSave = NULL;
180 void* fp = FP_FROM_SAVEAREA(self->curFrame);
181 breakSaveBlock->prevSave = (StackSaveArea*)fp;
183 saveBlock->prevSave = breakSaveBlock;
186 breakSaveBlock->prevFrame = self->curFrame;
187 breakSaveBlock->savedPc = NULL; // not required
188 breakSaveBlock->xtra.localRefCookie = 0; // not required
189 breakSaveBlock->method = NULL;
190 saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
191 saveBlock->savedPc = NULL; // not required
192 #ifdef USE_INDIRECT_REF
193 saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
195 saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
197 saveBlock->method = method;
199 LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n",
200 self->curFrame, FP_FROM_SAVEAREA(saveBlock),
201 (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
203 self->curFrame = FP_FROM_SAVEAREA(saveBlock);
209 * This is used by the JNI PushLocalFrame call. We push a new frame onto
210 * the stack that has no ins, outs, or locals, and no break frame above it.
211 * It's strictly used for tracking JNI local refs, and will be popped off
212 * by dvmPopFrame if it's not removed explicitly.
214 bool dvmPushLocalFrame(Thread* self, const Method* method)
216 StackSaveArea* saveBlock;
220 assert(dvmIsNativeMethod(method));
222 stackReq = sizeof(StackSaveArea); // regular frame
224 assert(self->curFrame != NULL);
225 stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
227 if (stackPtr - stackReq < self->interpStackEnd) {
228 /* not enough space; let JNI throw the exception */
229 LOGW("Stack overflow on PushLocal "
230 "(req=%d top=%p cur=%p size=%d '%s')\n",
231 stackReq, self->interpStackStart, self->curFrame,
232 self->interpStackSize, method->name);
233 dvmHandleStackOverflow(self, method);
234 assert(dvmCheckException(self));
239 * Shift the stack pointer down, leaving space for just the stack save
240 * area for the break frame, then shift down farther for the full frame.
242 stackPtr -= sizeof(StackSaveArea);
243 saveBlock = (StackSaveArea*) stackPtr;
245 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
246 /* debug -- memset the new stack */
247 memset(stackPtr, 0xaf, stackReq);
250 saveBlock->prevSave = (StackSaveArea*)FP_FROM_SAVEAREA(self->curFrame);
253 saveBlock->prevFrame = self->curFrame;
254 saveBlock->savedPc = NULL; // not required
255 #ifdef USE_INDIRECT_REF
256 saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
258 saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
260 saveBlock->method = method;
262 LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n",
263 self->curFrame, FP_FROM_SAVEAREA(saveBlock),
264 (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
266 self->curFrame = FP_FROM_SAVEAREA(saveBlock);
272 * Pop one frame pushed on by JNI PushLocalFrame.
274 * If we've gone too far, the previous frame is either a break frame or
275 * an interpreted frame. Either way, the method pointer won't match.
277 bool dvmPopLocalFrame(Thread* self)
279 StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame);
281 assert(!dvmIsBreakFrame((u4*)self->curFrame));
282 if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
284 * The previous frame doesn't have the same method pointer -- we've
285 * been asked to pop too much.
287 assert(dvmIsBreakFrame((u4*)saveBlock->prevFrame) ||
289 SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
293 LOGVV("POP JNI local frame: removing %s, now %s\n",
294 saveBlock->method->name,
295 SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
296 dvmPopJniLocals(self, saveBlock);
297 self->curFrame = saveBlock->prevFrame;
303 * Pop a frame we added. There should be one method frame and one break
306 * If JNI Push/PopLocalFrame calls were mismatched, we might end up
307 * popping multiple method frames before we find the break.
309 * Returns "false" if there was no frame to pop.
311 static bool dvmPopFrame(Thread* self)
313 StackSaveArea* saveBlock;
315 if (self->curFrame == NULL)
318 saveBlock = SAVEAREA_FROM_FP(self->curFrame);
319 assert(!dvmIsBreakFrame((u4*)self->curFrame));
322 * Remove everything up to the break frame. If this was a call into
323 * native code, pop the JNI local references table.
325 while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) {
326 /* probably a native->native JNI call */
328 if (dvmIsNativeMethod(saveBlock->method)) {
329 LOGVV("Popping JNI stack frame for %s.%s%s\n",
330 saveBlock->method->clazz->descriptor,
331 saveBlock->method->name,
332 (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
333 "" : " (JNI local)");
334 assert(saveBlock->xtra.localRefCookie != 0);
335 //assert(saveBlock->xtra.localRefCookie >= self->jniLocalRefTable.table &&
336 // saveBlock->xtra.localRefCookie <=self->jniLocalRefTable.nextEntry);
338 dvmPopJniLocals(self, saveBlock);
341 saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame);
343 if (saveBlock->method != NULL) {
344 LOGE("PopFrame missed the break\n");
346 dvmAbort(); // stack trashed -- nowhere to go in this thread
349 LOGVV("POP frame: cur=%p new=%p\n",
350 self->curFrame, saveBlock->prevFrame);
352 self->curFrame = saveBlock->prevFrame;
357 * Common code for dvmCallMethodV/A and dvmInvokeMethod.
359 * Pushes a call frame on, advancing self->curFrame.
361 static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
367 if (self->status != THREAD_RUNNING) {
368 LOGW("threadid=%d: status=%d on call to %s.%s -\n",
369 self->threadId, self->status,
370 method->clazz->descriptor, method->name);
374 assert(self != NULL);
375 assert(method != NULL);
380 clazz = method->clazz;
383 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
384 LOGVV("thread=%d native code calling %s.%s %s\n", self->threadId,
385 clazz->descriptor, method->name, desc);
390 /* needed for java.lang.reflect.Method.invoke */
391 if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame),
394 /* note this throws IAException, not IAError */
395 dvmThrowException("Ljava/lang/IllegalAccessException;",
396 "access to method denied");
402 * Push a call frame on. If there isn't enough room for ins, locals,
403 * outs, and the saved state, it will throw an exception.
405 * This updates self->curFrame.
407 if (dvmIsNativeMethod(method)) {
408 /* native code calling native code the hard way */
409 if (!dvmPushJNIFrame(self, method)) {
410 assert(dvmCheckException(self));
414 /* native code calling interpreted code */
415 if (!dvmPushInterpFrame(self, method)) {
416 assert(dvmCheckException(self));
425 * Issue a method call.
427 * Pass in NULL for "obj" on calls to static methods.
429 * (Note this can't be inlined because it takes a variable number of args.)
431 void dvmCallMethod(Thread* self, const Method* method, Object* obj,
432 JValue* pResult, ...)
435 va_start(args, pResult);
436 dvmCallMethodV(self, method, obj, false, pResult, args);
441 * Issue a method call with a variable number of arguments. We process
442 * the contents of "args" by scanning the method signature.
444 * Pass in NULL for "obj" on calls to static methods.
446 * We don't need to take the class as an argument because, in Dalvik,
447 * we don't need to worry about static synchronized methods.
449 void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
450 bool fromJni, JValue* pResult, va_list args)
452 const char* desc = &(method->shorty[1]); // [0] is the return type.
457 clazz = callPrep(self, method, obj, false);
461 /* "ins" for new frame start at frame pointer plus locals */
462 ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
464 //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins);
466 /* put "this" pointer into in0 if appropriate */
467 if (!dvmIsStaticMethod(method)) {
468 #ifdef WITH_EXTRA_OBJECT_VALIDATION
469 assert(obj != NULL && dvmIsValidObject(obj));
475 JNIEnv* env = self->jniEnv;
476 while (*desc != '\0') {
478 case 'D': case 'J': {
479 u8 val = va_arg(args, u8);
480 memcpy(ins, &val, 8); // EABI prevents direct store
486 /* floats were normalized to doubles; convert back */
487 float f = (float) va_arg(args, double);
488 *ins++ = dvmFloatToU4(f);
492 case 'L': { /* 'shorty' descr uses L for all refs, incl array */
493 void* argObj = va_arg(args, void*);
494 assert(obj == NULL || dvmIsValidObject(obj));
496 *ins++ = (u4) dvmDecodeIndirectRef(env, argObj);
498 *ins++ = (u4) argObj;
503 /* Z B C S I -- all passed as 32-bit integers */
504 *ins++ = va_arg(args, u4);
512 if (verifyCount != method->insSize) {
513 LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
514 method->insSize, clazz->descriptor, method->name);
520 //dvmDumpThreadStack(dvmThreadSelf());
522 if (dvmIsNativeMethod(method)) {
523 TRACE_METHOD_ENTER(self, method);
525 * Because we leave no space for local variables, "curFrame" points
526 * directly at the method arguments.
528 (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
529 TRACE_METHOD_EXIT(self, method);
531 dvmInterpret(self, method, pResult);
541 * Issue a method call with arguments provided in an array. We process
542 * the contents of "args" by scanning the method signature.
544 * The values were likely placed into an uninitialized jvalue array using
545 * the field specifiers, which means that sub-32-bit fields (e.g. short,
546 * boolean) may not have 32 or 64 bits of valid data. This is different
547 * from the varargs invocation where the C compiler does a widening
548 * conversion when calling a function. As a result, we have to be a
549 * little more precise when pulling stuff out.
551 * "args" may be NULL if the method has no arguments.
553 void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
554 bool fromJni, JValue* pResult, const jvalue* args)
556 const char* desc = &(method->shorty[1]); // [0] is the return type.
561 clazz = callPrep(self, method, obj, false);
565 /* "ins" for new frame start at frame pointer plus locals */
566 ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
568 /* put "this" pointer into in0 if appropriate */
569 if (!dvmIsStaticMethod(method)) {
571 *ins++ = (u4) obj; /* obj is a "real" ref */
575 JNIEnv* env = self->jniEnv;
576 while (*desc != '\0') {
578 case 'D': /* 64-bit quantity; have to use */
579 case 'J': /* memcpy() in case of mis-alignment */
580 memcpy(ins, &args->j, 8);
582 verifyCount++; /* this needs an extra push */
584 case 'L': /* includes array refs */
586 *ins++ = (u4) dvmDecodeIndirectRef(env, args->l);
588 *ins++ = (u4) args->l;
592 *ins++ = args->i; /* full 32 bits */
595 *ins++ = args->s; /* 16 bits, sign-extended */
598 *ins++ = args->c; /* 16 bits, unsigned */
601 *ins++ = args->b; /* 8 bits, sign-extended */
604 *ins++ = args->z; /* 8 bits, zero or non-zero */
607 LOGE("Invalid char %c in short signature of %s.%s\n",
608 *(desc-1), clazz->descriptor, method->name);
618 if (verifyCount != method->insSize) {
619 LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
620 method->insSize, clazz->descriptor, method->name);
626 if (dvmIsNativeMethod(method)) {
627 TRACE_METHOD_ENTER(self, method);
629 * Because we leave no space for local variables, "curFrame" points
630 * directly at the method arguments.
632 (*method->nativeFunc)((u4*)self->curFrame, pResult, method, self);
633 TRACE_METHOD_EXIT(self, method);
635 dvmInterpret(self, method, pResult);
642 static void throwArgumentTypeMismatch(int argIndex, ClassObject* expected,
645 char* expectedClassName = dvmHumanReadableDescriptor(expected->descriptor);
646 char* actualClassName = (arg != NULL)
647 ? dvmHumanReadableDescriptor(arg->obj.clazz->descriptor)
649 dvmThrowExceptionFmt("Ljava/lang/IllegalArgumentException;",
650 "argument %d should have type %s, got %s",
651 argIndex + 1, expectedClassName, actualClassName);
652 free(expectedClassName);
653 free(actualClassName);
657 * Invoke a method, using the specified arguments and return type, through
658 * one of the reflection interfaces. Could be a virtual or direct method
659 * (including constructors). Used for reflection.
661 * Deals with boxing/unboxing primitives and performs widening conversions.
663 * "invokeObj" will be null for a static method.
665 * If the invocation returns with an exception raised, we have to wrap it.
667 Object* dvmInvokeMethod(Object* obj, const Method* method,
668 ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
672 Object* retObj = NULL;
673 Thread* self = dvmThreadSelf();
675 int verifyCount, argListLength;
677 bool needPop = false;
679 /* verify arg count */
681 argListLength = argList->length;
684 if (argListLength != (int) params->length) {
685 dvmThrowExceptionFmt("Ljava/lang/IllegalArgumentException;",
686 "wrong number of arguments; expected %d, got %d",
687 params->length, argListLength);
691 clazz = callPrep(self, method, obj, !noAccessCheck);
696 /* "ins" for new frame start at frame pointer plus locals */
697 ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
700 //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins);
702 /* put "this" pointer into in0 if appropriate */
703 if (!dvmIsStaticMethod(method)) {
710 * Copy the args onto the stack. Primitive types are converted when
711 * necessary, and object types are verified.
717 args = (DataObject**) argList->contents;
718 types = (ClassObject**) params->contents;
719 for (i = 0; i < argListLength; i++) {
722 width = dvmConvertArgument(*args++, *types++, ins);
724 dvmPopFrame(self); // throw wants to pull PC out of stack
726 throwArgumentTypeMismatch(i, *(types-1), *(args-1));
731 verifyCount += width;
735 if (verifyCount != method->insSize) {
736 LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
737 method->insSize, clazz->descriptor, method->name);
743 if (dvmIsNativeMethod(method)) {
744 TRACE_METHOD_ENTER(self, method);
746 * Because we leave no space for local variables, "curFrame" points
747 * directly at the method arguments.
749 (*method->nativeFunc)((u4*)self->curFrame, &retval, method, self);
750 TRACE_METHOD_EXIT(self, method);
752 dvmInterpret(self, method, &retval);
756 * Pop the frame immediately. The "wrap" calls below can cause
757 * allocations, and we don't want the GC to walk the now-dead frame.
763 * If an exception is raised, wrap and replace. This is necessary
764 * because the invoked method could have thrown a checked exception
765 * that the caller wasn't prepared for.
767 * We might be able to do this up in the interpreted code, but that will
768 * leave us with a shortened stack trace in the top-level exception.
770 if (dvmCheckException(self)) {
771 dvmWrapException("Ljava/lang/reflect/InvocationTargetException;");
774 * If this isn't a void method or constructor, convert the return type
775 * to an appropriate object.
777 * We don't do this when an exception is raised because the value
778 * in "retval" is undefined.
780 if (returnType != NULL) {
781 retObj = (Object*)dvmBoxPrimitive(retval, returnType);
782 dvmReleaseTrackedAlloc(retObj, NULL);
793 typedef struct LineNumFromPcContext {
796 } LineNumFromPcContext;
798 static int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
800 LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt;
802 // We know that this callback will be called in
803 // ascending address order, so keep going until we find
804 // a match or we've just gone past it.
806 if (address > pContext->address) {
807 // The line number from the previous positions callback
808 // wil be the final result.
812 pContext->lineNum = lineNum;
814 return (address == pContext->address) ? 1 : 0;
818 * Determine the source file line number based on the program counter.
819 * "pc" is an offset, in 16-bit units, from the start of the method's code.
821 * Returns -1 if no match was found (possibly because the source files were
822 * compiled without "-g", so no line number information is present).
823 * Returns -2 for native methods (as expected in exception traces).
825 int dvmLineNumFromPC(const Method* method, u4 relPc)
827 const DexCode* pDexCode = dvmGetMethodCode(method);
829 if (pDexCode == NULL) {
830 if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method))
832 return -1; /* can happen for abstract method stub */
835 LineNumFromPcContext context;
836 memset(&context, 0, sizeof(context));
837 context.address = relPc;
838 // A method with no line number info should return -1
839 context.lineNum = -1;
841 dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode,
842 method->clazz->descriptor,
843 method->prototype.protoIdx,
845 lineNumForPcCb, NULL, &context);
847 return context.lineNum;
851 * Compute the frame depth.
853 * Excludes "break" frames.
855 int dvmComputeExactFrameDepth(const void* fp)
859 for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
860 if (!dvmIsBreakFrame((u4*)fp))
868 * Compute the "vague" frame depth, which is just a pointer subtraction.
869 * The result is NOT an overly generous assessment of the number of
870 * frames; the only meaningful use is to compare against the result of
871 * an earlier invocation.
873 * Useful for implementing single-step debugger modes, which may need to
874 * call this for every instruction.
876 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
878 const u1* interpStackStart = thread->interpStackStart;
880 assert((u1*) fp >= interpStackStart - thread->interpStackSize);
881 assert((u1*) fp < interpStackStart);
882 return interpStackStart - (u1*) fp;
886 * Get the calling frame. Pass in the current fp.
888 * Skip "break" frames and reflection invoke frames.
890 void* dvmGetCallerFP(const void* curFrame)
892 void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
893 StackSaveArea* saveArea;
896 if (dvmIsBreakFrame((u4*)caller)) {
897 /* pop up one more */
898 caller = SAVEAREA_FROM_FP(caller)->prevFrame;
900 return NULL; /* hit the top */
903 * If we got here by java.lang.reflect.Method.invoke(), we don't
904 * want to return Method's class loader. Shift up one and try
907 saveArea = SAVEAREA_FROM_FP(caller);
908 if (dvmIsReflectionMethod(saveArea->method)) {
909 caller = saveArea->prevFrame;
910 assert(caller != NULL);
919 * Get the caller's class. Pass in the current fp.
921 * This is used by e.g. java.lang.Class.
923 ClassObject* dvmGetCallerClass(const void* curFrame)
927 caller = dvmGetCallerFP(curFrame);
931 return SAVEAREA_FROM_FP(caller)->method->clazz;
935 * Get the caller's caller's class. Pass in the current fp.
937 * This is used by e.g. java.lang.Class, which wants to know about the
938 * class loader of the method that called it.
940 ClassObject* dvmGetCaller2Class(const void* curFrame)
942 void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
946 if (dvmIsBreakFrame((u4*)caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
950 callerCaller = dvmGetCallerFP(caller);
951 if (callerCaller == NULL)
954 return SAVEAREA_FROM_FP(callerCaller)->method->clazz;
958 * Get the caller's caller's caller's class. Pass in the current fp.
960 * This is used by e.g. java.lang.Class, which wants to know about the
961 * class loader of the method that called it.
963 ClassObject* dvmGetCaller3Class(const void* curFrame)
965 void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
969 if (dvmIsBreakFrame((u4*)caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
972 /* Walk up two frames if possible. */
973 for (i = 0; i < 2; i++) {
974 caller = dvmGetCallerFP(caller);
979 return SAVEAREA_FROM_FP(caller)->method->clazz;
983 * Create a flat array of methods that comprise the current interpreter
984 * stack trace. Pass in the current frame ptr.
986 * Allocates a new array and fills it with method pointers. Break frames
987 * are skipped, but reflection invocations are not. The caller must free
990 * The current frame will be in element 0.
992 * Returns "true" on success, "false" on failure (e.g. malloc failed).
994 bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
997 const Method** array;
1000 depth = dvmComputeExactFrameDepth(fp);
1001 array = (const Method**) malloc(depth * sizeof(Method*));
1005 for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
1006 if (!dvmIsBreakFrame((u4*)fp))
1007 array[idx++] = SAVEAREA_FROM_FP(fp)->method;
1009 assert(idx == depth);
1017 * Open up the reserved area and throw an exception. The reserved area
1018 * should only be needed to create and initialize the exception itself.
1020 * If we already opened it and we're continuing to overflow, abort the VM.
1022 * We have to leave the "reserved" area open until the "catch" handler has
1023 * finished doing its processing. This is because the catch handler may
1024 * need to resolve classes, which requires calling into the class loader if
1025 * the classes aren't already in the "initiating loader" list.
1027 void dvmHandleStackOverflow(Thread* self, const Method* method)
1030 * Can we make the reserved area available?
1032 if (self->stackOverflowed) {
1034 * Already did, nothing to do but bail.
1036 LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n",
1038 dvmDumpThread(self, false);
1042 /* open it up to the full range */
1043 LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n",
1045 method->clazz->descriptor, method->name, method->shorty);
1046 StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame);
1047 LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n",
1048 method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
1049 (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
1050 saveArea, (u1*) saveArea - self->interpStackEnd);
1051 LOGI(" expanding stack end (%p to %p)\n", self->interpStackEnd,
1052 self->interpStackStart - self->interpStackSize);
1053 //dvmDumpThread(self, false);
1054 self->interpStackEnd = self->interpStackStart - self->interpStackSize;
1055 self->stackOverflowed = true;
1058 * If we were trying to throw an exception when the stack overflowed,
1059 * we will blow up when doing the class lookup on StackOverflowError
1060 * because of the pending exception. So, we clear it and make it
1061 * the cause of the SOE.
1063 Object* excep = dvmGetException(self);
1064 if (excep != NULL) {
1065 LOGW("Stack overflow while throwing exception\n");
1066 dvmClearException(self);
1068 dvmThrowChainedExceptionByClass(gDvm.classJavaLangStackOverflowError,
1073 * Reduce the available stack size. By this point we should have finished
1074 * our overflow processing.
1076 void dvmCleanupStackOverflow(Thread* self, const Object* exception)
1078 const u1* newStackEnd;
1080 assert(self->stackOverflowed);
1082 if (exception->clazz != gDvm.classJavaLangStackOverflowError) {
1083 /* exception caused during SOE, not the SOE itself */
1087 newStackEnd = (self->interpStackStart - self->interpStackSize)
1088 + STACK_OVERFLOW_RESERVE;
1089 if ((u1*)self->curFrame <= newStackEnd) {
1090 LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n",
1091 self->interpStackEnd, self->curFrame);
1092 dvmDumpThread(self, false);
1096 self->interpStackEnd = newStackEnd;
1097 self->stackOverflowed = false;
1099 LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd,
1105 * Extract the object that is the target of a monitor-enter instruction
1106 * in the top stack frame of "thread".
1108 * The other thread might be alive, so this has to work carefully.
1110 * The thread list lock must be held.
1112 * Returns "true" if we successfully recover the object. "*pOwner" will
1113 * be NULL if we can't determine the owner for some reason (e.g. race
1114 * condition on ownership transfer).
1116 static bool extractMonitorEnterObject(Thread* thread, Object** pLockObj,
1119 void* framePtr = thread->curFrame;
1121 if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr))
1124 const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr);
1125 const Method* method = saveArea->method;
1126 const u2* currentPc = saveArea->xtra.currentPc;
1129 if (!dvmLinearAllocContains(method, sizeof(Method))) {
1130 LOGD("ExtrMon: method %p not valid\n", method);
1134 /* check currentPc */
1135 u4 insnsSize = dvmGetMethodInsnsSize(method);
1136 if (currentPc < method->insns ||
1137 currentPc >= method->insns + insnsSize)
1139 LOGD("ExtrMon: insns %p not valid (%p - %p)\n",
1140 currentPc, method->insns, method->insns + insnsSize);
1144 /* check the instruction */
1145 if ((*currentPc & 0xff) != OP_MONITOR_ENTER) {
1146 LOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)\n",
1147 currentPc, *currentPc & 0xff);
1151 /* get and check the register index */
1152 unsigned int reg = *currentPc >> 8;
1153 if (reg >= method->registersSize) {
1154 LOGD("ExtrMon: invalid register %d (max %d)\n",
1155 reg, method->registersSize);
1159 /* get and check the object in that register */
1160 u4* fp = (u4*) framePtr;
1161 Object* obj = (Object*) fp[reg];
1162 if (!dvmIsValidObject(obj)) {
1163 LOGD("ExtrMon: invalid object %p at %p[%d]\n", obj, fp, reg);
1169 * Try to determine the object's lock holder; it's okay if this fails.
1171 * We're assuming the thread list lock is already held by this thread.
1172 * If it's not, we may be living dangerously if we have to scan through
1173 * the thread list to find a match. (The VM will generally be in a
1174 * suspended state when executing here, so this is a minor concern
1175 * unless we're dumping while threads are running, in which case there's
1176 * a good chance of stuff blowing up anyway.)
1178 *pOwner = dvmGetObjectLockHolder(obj);
1184 * Dump stack frames, starting from the specified frame and moving down.
1186 * Each frame holds a pointer to the currently executing method, and the
1187 * saved program counter from the caller ("previous" frame). This means
1188 * we don't have the PC for the current method on the stack, which is
1189 * pretty reasonable since it's in the "PC register" for the VM. Because
1190 * exceptions need to show the correct line number we actually *do* have
1191 * an updated version in the fame's "xtra.currentPc", but it's unreliable.
1193 * Note "framePtr" could be NULL in rare circumstances.
1195 static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
1198 const StackSaveArea* saveArea;
1199 const Method* method;
1201 const u2* currentPc = NULL;
1205 * We call functions that require us to be holding the thread list lock.
1206 * It's probable that the caller has already done so, but it's not
1207 * guaranteed. If it's not locked, lock it now.
1209 bool needThreadUnlock = dvmTryLockThreadList();
1212 * The "currentPc" is updated whenever we execute an instruction that
1213 * might throw an exception. Show it here.
1215 if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) {
1216 saveArea = SAVEAREA_FROM_FP(framePtr);
1218 if (saveArea->xtra.currentPc != NULL)
1219 currentPc = saveArea->xtra.currentPc;
1222 while (framePtr != NULL) {
1223 saveArea = SAVEAREA_FROM_FP(framePtr);
1224 method = saveArea->method;
1226 if (dvmIsBreakFrame((u4*)framePtr)) {
1227 //dvmPrintDebugMessage(target, " (break frame)\n");
1231 if (currentPc != NULL)
1232 relPc = currentPc - saveArea->method->insns;
1236 char* className = dvmHumanReadableDescriptor(method->clazz->descriptor);
1237 if (dvmIsNativeMethod(method))
1238 dvmPrintDebugMessage(target,
1239 " at %s.%s(Native Method)\n", className, method->name);
1241 dvmPrintDebugMessage(target,
1242 " at %s.%s(%s:%s%d)\n",
1243 className, method->name, dvmGetMethodSourceFile(method),
1244 (relPc >= 0 && first) ? "~" : "",
1245 relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc));
1251 * Decorate WAIT and MONITOR threads with some detail on
1254 * warning: wait status not stable, even in suspend
1256 if (thread->status == THREAD_WAIT ||
1257 thread->status == THREAD_TIMED_WAIT)
1259 Monitor* mon = thread->waitMonitor;
1260 Object* obj = dvmGetMonitorObject(mon);
1262 Thread* joinThread = NULL;
1263 className = dvmHumanReadableDescriptor(obj->clazz->descriptor);
1264 if (strcmp(className, "java.lang.VMThread") == 0) {
1265 joinThread = dvmGetThreadFromThreadObject(obj);
1267 if (joinThread == NULL) {
1268 dvmPrintDebugMessage(target,
1269 " - waiting on <%p> (a %s)\n", obj, className);
1271 dvmPrintDebugMessage(target,
1272 " - waiting on <%p> (a %s) tid=%d\n",
1273 obj, className, joinThread->threadId);
1277 } else if (thread->status == THREAD_MONITOR) {
1280 if (extractMonitorEnterObject(thread, &obj, &owner)) {
1281 className = dvmHumanReadableDescriptor(obj->clazz->descriptor);
1282 if (owner != NULL) {
1283 char* threadName = dvmGetThreadName(owner);
1284 dvmPrintDebugMessage(target,
1285 " - waiting to lock <%p> (a %s) held by threadid=%d (%s)\n",
1286 obj, className, owner->threadId, threadName);
1289 dvmPrintDebugMessage(target,
1290 " - waiting to lock <%p> (a %s) held by ???\n",
1300 * Get saved PC for previous frame. There's no savedPc in a "break"
1301 * frame, because that represents native or interpreted code
1302 * invoked by the VM. The saved PC is sitting in the "PC register",
1303 * a local variable on the native stack.
1305 currentPc = saveArea->savedPc;
1309 if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) {
1310 LOGW("Warning: loop in stack trace at frame %d (%p -> %p)\n",
1311 checkCount, framePtr, saveArea->prevFrame);
1314 framePtr = saveArea->prevFrame;
1317 if (checkCount > 300) {
1318 dvmPrintDebugMessage(target,
1319 " ***** printed %d frames, not showing any more\n",
1324 dvmPrintDebugMessage(target, "\n");
1326 if (needThreadUnlock) {
1327 dvmUnlockThreadList();
1333 * Dump the stack for the specified thread.
1335 void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
1337 dumpFrames(target, thread->curFrame, thread);
1341 * Dump the stack for the specified thread, which is still running.
1343 * This is very dangerous, because stack frames are being pushed on and
1344 * popped off, and if the thread exits we'll be looking at freed memory.
1345 * The plan here is to take a snapshot of the stack and then dump that
1346 * to try to minimize the chances of catching it mid-update. This should
1347 * work reasonably well on a single-CPU system.
1349 * There is a small chance that calling here will crash the VM.
1351 void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
1353 StackSaveArea* saveArea;
1354 const u1* origStack;
1355 u1* stackCopy = NULL;
1356 int origSize, fpOffset;
1358 int depthLimit = 200;
1360 if (thread == NULL || thread->curFrame == NULL) {
1361 dvmPrintDebugMessage(target,
1362 "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
1363 thread, (thread != NULL) ? thread->threadId : 0);
1367 /* wait for a full quantum */
1370 /* copy the info we need, then the stack itself */
1371 origSize = thread->interpStackSize;
1372 origStack = (const u1*) thread->interpStackStart - origSize;
1373 stackCopy = (u1*) malloc(origSize);
1374 fpOffset = (u1*) thread->curFrame - origStack;
1375 memcpy(stackCopy, origStack, origSize);
1378 * Run through the stack and rewrite the "prev" pointers.
1380 //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame);
1381 fp = stackCopy + fpOffset;
1385 if (depthLimit-- < 0) {
1386 /* we're probably screwed */
1387 dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n");
1390 saveArea = SAVEAREA_FROM_FP(fp);
1391 if (saveArea->prevFrame == NULL)
1394 prevOffset = (u1*) saveArea->prevFrame - origStack;
1395 if (prevOffset < 0 || prevOffset > origSize) {
1396 dvmPrintDebugMessage(target,
1397 "DumpRunning: bad offset found: %d (from %p %p)\n",
1398 prevOffset, origStack, saveArea->prevFrame);
1399 saveArea->prevFrame = NULL;
1403 saveArea->prevFrame = stackCopy + prevOffset;
1404 fp = saveArea->prevFrame;
1408 * We still need to pass the Thread for some monitor wait stuff.
1410 dumpFrames(target, stackCopy + fpOffset, thread);