1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
164fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stacks and their uses (e.g. native --> interpreted method calls).
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the majestic ASCII art in Stack.h.
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "jni.h"
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdarg.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#ifdef HAVE_ANDROID_OS
29b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#include <corkscrew/backtrace.h>
30b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#endif
31b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the interpreter stack in a new thread.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently this doesn't do much, since we don't need to zero out the
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack (and we really don't want to if it was created with mmap).
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitInterpStack(Thread* thread, int stackSize)
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thread->interpStackStart != NULL);
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    assert(thread->interpSave.curFrame == NULL);
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling an interpreted method from an internal VM function or
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection.
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a frame for an interpreted method onto the stack.  This is only
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used when calling into interpreted code from native code.  (The
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreter does its own stack frame manipulation for interp-->interp
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls.)
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The size we need to reserve is the sum of parameters, local variables,
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved goodies, and outbound parameters.
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start by inserting a "break" frame, which ensures that the interpreter
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hands control back to us after the function we call returns or an
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncaught exception is thrown.
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPushInterpFrame(Thread* self, const Method* method)
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* breakSaveBlock;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackReq;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackPtr;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsNativeMethod(method));
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsAbstractMethod(method));
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackReq = method->registersSize * 4        // params + locals
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                + sizeof(StackSaveArea) * 2     // break frame + regular frame
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                + method->outsSize * 4;         // args to other methods
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (self->interpSave.curFrame != NULL)
7830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = self->interpStackStart;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackPtr - stackReq < self->interpStackEnd) {
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* not enough space */
84e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Stack overflow on call to interp "
856f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein             "(req=%d top=%p cur=%p size=%d %s.%s)",
8630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee            stackReq, self->interpStackStart, self->interpSave.curFrame,
8799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            self->interpStackSize, method->clazz->descriptor, method->name);
886ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        dvmHandleStackOverflow(self, method);
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shift the stack pointer down, leaving space for the function's
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * args/registers and save area.
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= sizeof(StackSaveArea);
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock = (StackSaveArea*)stackPtr;
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = (StackSaveArea*) stackPtr;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* debug -- memset the new stack, unless we want valgrind's help */
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
10730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    breakSaveBlock->prevSave =
10830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee       (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevSave = breakSaveBlock;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
11230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    breakSaveBlock->prevFrame = self->interpSave.curFrame;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->savedPc = NULL;             // not required
114d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    breakSaveBlock->xtra.localRefCookie = 0;    // not required
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->method = NULL;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->savedPc = NULL;                  // not required
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->xtra.currentPc = NULL;           // not required?
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->method = method;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("PUSH frame: old=%p new=%p (size=%d)",
12230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
12330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling a JNI native method from an internal VM fuction or
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection.  This is also used to create the "fake" native-method
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames at the top of the interpreted stack.
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This actually pushes two frames; the first is a "break" frame.
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top frame has additional space for JNI local reference tracking.
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushJNIFrame(Thread* self, const Method* method)
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* breakSaveBlock;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackReq;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackPtr;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsNativeMethod(method));
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackReq = method->registersSize * 4        // params only
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                + sizeof(StackSaveArea) * 2;    // break frame + regular frame
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
15130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (self->interpSave.curFrame != NULL)
15230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = self->interpStackStart;
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackPtr - stackReq < self->interpStackEnd) {
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* not enough space */
158e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Stack overflow on call to native "
1596f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein             "(req=%d top=%p cur=%p size=%d '%s')",
16030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee            stackReq, self->interpStackStart, self->interpSave.curFrame,
16199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            self->interpStackSize, method->name);
1626ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        dvmHandleStackOverflow(self, method);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shift the stack pointer down, leaving space for just the stack save
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * area for the break frame, then shift down farther for the full frame.
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We leave space for the method args, which are copied in later.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= sizeof(StackSaveArea);
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock = (StackSaveArea*)stackPtr;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = (StackSaveArea*) stackPtr;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* debug -- memset the new stack */
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(stackPtr, 0xaf, stackReq);
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
18230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (self->interpSave.curFrame == NULL)
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        breakSaveBlock->prevSave = NULL;
184fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    else {
18530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        void* fp = FP_FROM_SAVEAREA(self->interpSave.curFrame);
186fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        breakSaveBlock->prevSave = (StackSaveArea*)fp;
187fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    }
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevSave = breakSaveBlock;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    breakSaveBlock->prevFrame = self->interpSave.curFrame;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->savedPc = NULL;             // not required
193d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    breakSaveBlock->xtra.localRefCookie = 0;    // not required
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->method = NULL;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->savedPc = NULL;                  // not required
197d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->method = method;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)",
20130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
20230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by the JNI PushLocalFrame call.  We push a new frame onto
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack that has no ins, outs, or locals, and no break frame above it.
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's strictly used for tracking JNI local refs, and will be popped off
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by dvmPopFrame if it's not removed explicitly.
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushLocalFrame(Thread* self, const Method* method)
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackReq;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackPtr;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsNativeMethod(method));
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackReq = sizeof(StackSaveArea);       // regular frame
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    assert(self->interpSave.curFrame != NULL);
22630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackPtr - stackReq < self->interpStackEnd) {
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* not enough space; let JNI throw the exception */
230e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Stack overflow on PushLocal "
2316f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein             "(req=%d top=%p cur=%p size=%d '%s')",
23230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee            stackReq, self->interpStackStart, self->interpSave.curFrame,
23399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            self->interpStackSize, method->name);
2346ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        dvmHandleStackOverflow(self, method);
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shift the stack pointer down, leaving space for just the stack save
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * area for the break frame, then shift down farther for the full frame.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= sizeof(StackSaveArea);
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = (StackSaveArea*) stackPtr;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* debug -- memset the new stack */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(stackPtr, 0xaf, stackReq);
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
25130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    saveBlock->prevSave =
25230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    saveBlock->prevFrame = self->interpSave.curFrame;
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->savedPc = NULL;                  // not required
257d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->method = method;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)",
26130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
26230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop one frame pushed on by JNI PushLocalFrame.
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we've gone too far, the previous frame is either a break frame or
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an interpreted frame.  Either way, the method pointer won't match.
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPopLocalFrame(Thread* self)
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
27730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame);
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The previous frame doesn't have the same method pointer -- we've
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * been asked to pop too much.
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
285fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        assert(dvmIsBreakFrame((u4*)saveBlock->prevFrame) ||
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               !dvmIsNativeMethod(
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("POP JNI local frame: removing %s, now %s",
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveBlock->method->name,
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopJniLocals(self, saveBlock);
29530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    self->interpSave.curFrame = saveBlock->prevFrame;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop a frame we added.  There should be one method frame and one break
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame.
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If JNI Push/PopLocalFrame calls were mismatched, we might end up
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popping multiple method frames before we find the break.
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" if there was no frame to pop.
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPopFrame(Thread* self)
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (self->interpSave.curFrame == NULL)
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame);
31730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Remove everything up to the break frame.  If this was a call into
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * native code, pop the JNI local references table.
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) {
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* probably a native->native JNI call */
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(saveBlock->method)) {
32760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGVV("Popping JNI stack frame for %s.%s%s",
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveBlock->method->clazz->descriptor,
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveBlock->method->name,
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "" : " (JNI local)");
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPopJniLocals(self, saveBlock);
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame);
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (saveBlock->method != NULL) {
338c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("PopFrame missed the break");
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();     // stack trashed -- nowhere to go in this thread
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("POP frame: cur=%p new=%p",
34430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame, saveBlock->prevFrame);
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    self->interpSave.curFrame = saveBlock->prevFrame;
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Common code for dvmCallMethodV/A and dvmInvokeMethod.
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
35330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * Pushes a call frame on, advancing self->interpSave.curFrame.
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool checkAccess)
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->status != THREAD_RUNNING) {
362e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("threadid=%d: status=%d on call to %s.%s -",
36399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            self->threadId, self->status,
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor, method->name);
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(method != NULL);
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj != NULL)
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = obj->clazz;
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = method->clazz;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    IF_LOGVV() {
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
37860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("thread=%d native code calling %s.%s %s", self->threadId,
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor, method->name, desc);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(desc);
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (checkAccess) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* needed for java.lang.reflect.Method.invoke */
38530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame),
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                method))
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* note this throws IAException, not IAError */
389d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowIllegalAccessException("access to method denied");
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Push a call frame on.  If there isn't enough room for ins, locals,
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * outs, and the saved state, it will throw an exception.
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
39830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee     * This updates self->interpSave.curFrame.
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* native code calling native code the hard way */
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmPushJNIFrame(self, method)) {
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* native code calling interpreted code */
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmPushInterpFrame(self, method)) {
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call.
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods.
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Note this can't be inlined because it takes a variable number of args.)
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethod(Thread* self, const Method* method, Object* obj,
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult, ...)
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_list args;
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_start(args, pResult);
429d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    dvmCallMethodV(self, method, obj, false, pResult, args);
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_end(args);
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with a variable number of arguments.  We process
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature.
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods.
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to take the class as an argument because, in Dalvik,
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't need to worry about static synchronized methods.
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodV(Thread* self, const Method* method, Object* obj,
443d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    bool fromJni, JValue* pResult, va_list args)
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* desc = &(method->shorty[1]); // [0] is the return type.
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int verifyCount = 0;
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4* ins;
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = callPrep(self, method, obj, false);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "ins" for new frame start at frame pointer plus locals */
45530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    ins = ((u4*)self->interpSave.curFrame) +
45630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee           (method->registersSize - method->insSize);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
458062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    //ALOGD("  FP is %p, INs live at >= %p", self->interpSave.curFrame, ins);
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put "this" pointer into in0 if appropriate */
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(method)) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION
4638bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes        assert(obj != NULL && dvmIsHeapAddress(obj));
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ins++ = (u4) obj;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount++;
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*desc != '\0') {
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (*(desc++)) {
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D': case 'J': {
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                u8 val = va_arg(args, u8);
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                memcpy(ins, &val, 8);       // EABI prevents direct store
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ins += 2;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount += 2;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'F': {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* floats were normalized to doubles; convert back */
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                float f = (float) va_arg(args, double);
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = dvmFloatToU4(f);
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'L': {     /* 'shorty' descr uses L for all refs, incl array */
4861813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro                void* arg = va_arg(args, void*);
4878bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes                assert(obj == NULL || dvmIsHeapAddress(obj));
4881813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro                jobject argObj = reinterpret_cast<jobject>(arg);
489d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden                if (fromJni)
490de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                    *ins++ = (u4) dvmDecodeIndirectRef(self, argObj);
491d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden                else
492d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden                    *ins++ = (u4) argObj;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
4970083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden                /* Z B C S I -- all passed as 32-bit integers */
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = va_arg(args, u4);
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verifyCount != method->insSize) {
507c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->insSize, clazz->descriptor, method->name);
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpThreadStack(dvmThreadSelf());
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
51799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        TRACE_METHOD_ENTER(self, method);
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we leave no space for local variables, "curFrame" points
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * directly at the method arguments.
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
52230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
52330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee                              method, self);
52499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        TRACE_METHOD_EXIT(self, method);
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInterpret(self, method, pResult);
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
529e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#ifndef NDEBUG
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
531e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#endif
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopFrame(self);
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with arguments provided in an array.  We process
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature.
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The values were likely placed into an uninitialized jvalue array using
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the field specifiers, which means that sub-32-bit fields (e.g. short,
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean) may not have 32 or 64 bits of valid data.  This is different
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the varargs invocation where the C compiler does a widening
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion when calling a function.  As a result, we have to be a
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * little more precise when pulling stuff out.
5458e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden *
5468e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * "args" may be NULL if the method has no arguments.
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodA(Thread* self, const Method* method, Object* obj,
549d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden    bool fromJni, JValue* pResult, const jvalue* args)
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* desc = &(method->shorty[1]); // [0] is the return type.
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int verifyCount = 0;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4* ins;
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = callPrep(self, method, obj, false);
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "ins" for new frame start at frame pointer plus locals */
56130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    ins = ((u4*)self->interpSave.curFrame) +
56230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (method->registersSize - method->insSize);
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put "this" pointer into in0 if appropriate */
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(method)) {
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(obj != NULL);
5670083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        *ins++ = (u4) obj;              /* obj is a "real" ref */
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount++;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*desc != '\0') {
5720083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        switch (*desc++) {
5730083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'D':                       /* 64-bit quantity; have to use */
5740083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'J':                       /*  memcpy() in case of mis-alignment */
5750083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            memcpy(ins, &args->j, 8);
5760083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            ins += 2;
5770083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            verifyCount++;              /* this needs an extra push */
5780083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
5790083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'L':                       /* includes array refs */
580d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            if (fromJni)
581de68817bdae0ca038d824ba79a70ac17cae405e6Elliott Hughes                *ins++ = (u4) dvmDecodeIndirectRef(self, args->l);
582d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            else
583d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden                *ins++ = (u4) args->l;
5840083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
5850083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'F':
5860083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'I':
5870083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            *ins++ = args->i;           /* full 32 bits */
5880083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
5890083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'S':
5900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            *ins++ = args->s;           /* 16 bits, sign-extended */
5910083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
5920083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'C':
5930083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            *ins++ = args->c;           /* 16 bits, unsigned */
5940083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
5950083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'B':
5960083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            *ins++ = args->b;           /* 8 bits, sign-extended */
5970083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
5980083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        case 'Z':
5990083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            *ins++ = args->z;           /* 8 bits, zero or non-zero */
6000083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
6010083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        default:
602c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Invalid char %c in short signature of %s.%s",
6030083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden                *(desc-1), clazz->descriptor, method->name);
6040083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            assert(false);
6050083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            goto bail;
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
6070083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden
6080083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        verifyCount++;
6090083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        args++;
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verifyCount != method->insSize) {
614c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->insSize, clazz->descriptor, method->name);
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
62299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        TRACE_METHOD_ENTER(self, method);
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we leave no space for local variables, "curFrame" points
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * directly at the method arguments.
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
62730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
62830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee                              method, self);
62999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        TRACE_METHOD_EXIT(self, method);
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInterpret(self, method, pResult);
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopFrame(self);
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
638b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic void throwArgumentTypeMismatch(int argIndex, ClassObject* expected, DataObject* arg) {
639b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string expectedClassName(dvmHumanReadableDescriptor(expected->descriptor));
6403ff838ee3920ef819d207cbf4148cc9c7939ef69Jesse Wilson    std::string actualClassName = dvmHumanReadableType(arg);
641b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, "argument %d should have type %s, got %s",
642b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes            argIndex + 1, expectedClassName.c_str(), actualClassName.c_str());
643be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes}
644be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces.  Could be a virtual or direct method
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors).  Used for reflection.
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions.
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it.
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method,
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool noAccessCheck)
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* retObj = NULL;
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    s4* ins;
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int verifyCount, argListLength;
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue retval;
666be420e7ce02692164617fab07facb514147abaa8Andy McFadden    bool needPop = false;
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* verify arg count */
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argList != NULL)
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argListLength = argList->length;
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argListLength = 0;
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argListLength != (int) params->length) {
6740b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein        dvmThrowExceptionFmt(gDvm.exIllegalArgumentException,
675be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes            "wrong number of arguments; expected %d, got %d",
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            params->length, argListLength);
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = callPrep(self, method, obj, !noAccessCheck);
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
683be420e7ce02692164617fab07facb514147abaa8Andy McFadden    needPop = true;
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "ins" for new frame start at frame pointer plus locals */
68630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    ins = ((s4*)self->interpSave.curFrame) +
68730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (method->registersSize - method->insSize);
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyCount = 0;
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
690062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    //ALOGD("  FP is %p, INs live at >= %p", self->interpSave.curFrame, ins);
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put "this" pointer into in0 if appropriate */
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(method)) {
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(obj != NULL);
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ins++ = (s4) obj;
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount++;
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Copy the args onto the stack.  Primitive types are converted when
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * necessary, and object types are verified.
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
7031813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    DataObject** args = (DataObject**)(void*)argList->contents;
7041813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    ClassObject** types = (ClassObject**)(void*)params->contents;
7051813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    for (int i = 0; i < argListLength; i++) {
7061813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro        int width = dvmConvertArgument(*args++, *types++, ins);
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (width < 0) {
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPopFrame(self);      // throw wants to pull PC out of stack
709be420e7ce02692164617fab07facb514147abaa8Andy McFadden            needPop = false;
710be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes            throwArgumentTypeMismatch(i, *(types-1), *(args-1));
711be420e7ce02692164617fab07facb514147abaa8Andy McFadden            goto bail;
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ins += width;
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount += width;
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
718c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#ifndef NDEBUG
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verifyCount != method->insSize) {
720c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->insSize, clazz->descriptor, method->name);
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
725c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#endif
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
72899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        TRACE_METHOD_ENTER(self, method);
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we leave no space for local variables, "curFrame" points
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * directly at the method arguments.
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
73330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval,
73430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee                              method, self);
73599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        TRACE_METHOD_EXIT(self, method);
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInterpret(self, method, &retval);
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
741be420e7ce02692164617fab07facb514147abaa8Andy McFadden     * Pop the frame immediately.  The "wrap" calls below can cause
742be420e7ce02692164617fab07facb514147abaa8Andy McFadden     * allocations, and we don't want the GC to walk the now-dead frame.
743be420e7ce02692164617fab07facb514147abaa8Andy McFadden     */
744be420e7ce02692164617fab07facb514147abaa8Andy McFadden    dvmPopFrame(self);
745be420e7ce02692164617fab07facb514147abaa8Andy McFadden    needPop = false;
746be420e7ce02692164617fab07facb514147abaa8Andy McFadden
747be420e7ce02692164617fab07facb514147abaa8Andy McFadden    /*
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If an exception is raised, wrap and replace.  This is necessary
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because the invoked method could have thrown a checked exception
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that the caller wasn't prepared for.
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We might be able to do this up in the interpreted code, but that will
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * leave us with a shortened stack trace in the top-level exception.
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmWrapException("Ljava/lang/reflect/InvocationTargetException;");
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If this isn't a void method or constructor, convert the return type
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to an appropriate object.
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't do this when an exception is raised because the value
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in "retval" is undefined.
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (returnType != NULL) {
766c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden            retObj = (Object*)dvmBoxPrimitive(retval, returnType);
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(retObj, NULL);
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
772be420e7ce02692164617fab07facb514147abaa8Andy McFadden    if (needPop) {
773be420e7ce02692164617fab07facb514147abaa8Andy McFadden        dvmPopFrame(self);
774be420e7ce02692164617fab07facb514147abaa8Andy McFadden    }
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return retObj;
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
778d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct LineNumFromPcContext {
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 address;
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 lineNum;
781d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro};
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt;
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
787de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    // We know that this callback will be called in
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ascending address order, so keep going until we find
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // a match or we've just gone past it.
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (address > pContext->address) {
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // The line number from the previous positions callback
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // wil be the final result.
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pContext->lineNum = lineNum;
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (address == pContext->address) ? 1 : 0;
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter.
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code.
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present).
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces).
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc)
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pDexCode = dvmGetMethodCode(method);
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexCode == NULL) {
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method))
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -2;
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;      /* can happen for abstract method stub */
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LineNumFromPcContext context;
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&context, 0, sizeof(context));
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    context.address = relPc;
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // A method with no line number info should return -1
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    context.lineNum = -1;
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode,
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor,
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->prototype.protoIdx,
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->accessFlags,
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumForPcCb, NULL, &context);
831de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return context.lineNum;
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth.
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames.
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp)
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = 0;
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
845fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp))
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction.
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation.
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction.
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* interpStackStart = thread->interpStackStart;
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
865e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    assert((u1*) fp >= interpStackStart - thread->interpStackSize);
866e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    assert((u1*) fp < interpStackStart);
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return interpStackStart - (u1*) fp;
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame.  Pass in the current fp.
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames.
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame)
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveArea;
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry:
881fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    if (dvmIsBreakFrame((u4*)caller)) {
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* pop up one more */
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        caller = SAVEAREA_FROM_FP(caller)->prevFrame;
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (caller == NULL)
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;        /* hit the top */
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we got here by java.lang.reflect.Method.invoke(), we don't
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * want to return Method's class loader.  Shift up one and try
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * again.
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(caller);
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsReflectionMethod(saveArea->method)) {
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            caller = saveArea->prevFrame;
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(caller != NULL);
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto retry;
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return caller;
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class.  Pass in the current fp.
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class.
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame)
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller;
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    caller = dvmGetCallerFP(curFrame);
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (caller == NULL)
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return SAVEAREA_FROM_FP(caller)->method->clazz;
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class.  Pass in the current fp.
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it.
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame)
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* callerCaller;
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* at the top? */
93130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (dvmIsBreakFrame((u4*)caller) &&
93230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* go one more */
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    callerCaller = dvmGetCallerFP(caller);
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (callerCaller == NULL)
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return SAVEAREA_FROM_FP(callerCaller)->method->clazz;
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class.  Pass in the current fp.
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it.
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame)
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* at the top? */
95530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (dvmIsBreakFrame((u4*)caller) &&
95630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Walk up two frames if possible. */
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < 2; i++) {
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        caller = dvmGetCallerFP(caller);
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (caller == NULL)
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
965de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return SAVEAREA_FROM_FP(caller)->method->clazz;
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
970db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * Fill a flat array of methods that comprise the current interpreter
971db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * stack trace.  Pass in the current frame ptr.  Break frames are
972db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * skipped, but reflection invocations are not.
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0.
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
976db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapirovoid dvmFillStackTraceArray(const void* fp, const Method** array, size_t length)
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
978db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro    assert(fp != NULL);
979db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro    assert(array != NULL);
980db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro    size_t i = 0;
981db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro    while (fp != NULL) {
982db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro        if (!dvmIsBreakFrame((u4*)fp)) {
983db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro            assert(i < length);
984db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro            array[i++] = SAVEAREA_FROM_FP(fp)->method;
985db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro        }
986db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro        fp = SAVEAREA_FROM_FP(fp)->prevFrame;
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception.  The reserved area
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself.
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM.
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing.  This is because the catch handler may
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list.
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
10016ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFaddenvoid dvmHandleStackOverflow(Thread* self, const Method* method)
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Can we make the reserved area available?
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->stackOverflowed) {
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Already did, nothing to do but bail.
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1010c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting",
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId);
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(self, false);
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* open it up to the full range */
10174308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("threadid=%d: stack overflow on call to %s.%s:%s",
10186ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        self->threadId,
10196ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        method->clazz->descriptor, method->name, method->shorty);
102030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
10214308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("  method requires %d+%d+%d=%d bytes, fp is %p (%d left)",
10226ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
10236ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
10246ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden        saveArea, (u1*) saveArea - self->interpStackEnd);
10254308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("  expanding stack end (%p to %p)", self->interpStackEnd,
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->interpStackStart - self->interpStackSize);
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpThread(self, false);
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->interpStackEnd = self->interpStackStart - self->interpStackSize;
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->stackOverflowed = true;
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we were trying to throw an exception when the stack overflowed,
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we will blow up when doing the class lookup on StackOverflowError
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because of the pending exception.  So, we clear it and make it
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the cause of the SOE.
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* excep = dvmGetException(self);
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (excep != NULL) {
1039e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Stack overflow while throwing exception");
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(self);
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
10420b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowChainedException(gDvm.exStackOverflowError, NULL, excep);
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size.  By this point we should have finished
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing.
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
10494fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFaddenvoid dvmCleanupStackOverflow(Thread* self, const Object* exception)
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* newStackEnd;
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self->stackOverflowed);
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (exception->clazz != gDvm.exStackOverflowError) {
10564fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden        /* exception caused during SOE, not the SOE itself */
10574fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden        return;
10584fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden    }
10594fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newStackEnd = (self->interpStackStart - self->interpStackSize)
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        + STACK_OVERFLOW_RESERVE;
106230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if ((u1*)self->interpSave.curFrame <= newStackEnd) {
1063c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Can't shrink stack: curFrame is in reserved area (%p %p)",
106430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee            self->interpStackEnd, self->interpSave.curFrame);
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(self, false);
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->interpStackEnd = newStackEnd;
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->stackOverflowed = false;
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10724308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("Shrank stack (to %p, curFrame is %p)", self->interpStackEnd,
107330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame);
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1078fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Extract the object that is the target of a monitor-enter instruction
1079fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * in the top stack frame of "thread".
1080fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *
1081fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The other thread might be alive, so this has to work carefully.
1082fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *
1083d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * The thread list lock must be held.
1084fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *
1085fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Returns "true" if we successfully recover the object.  "*pOwner" will
1086fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * be NULL if we can't determine the owner for some reason (e.g. race
1087fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * condition on ownership transfer).
1088fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */
1089fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenstatic bool extractMonitorEnterObject(Thread* thread, Object** pLockObj,
1090fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    Thread** pOwner)
1091fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{
109230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    void* framePtr = thread->interpSave.curFrame;
1093fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1094fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr))
1095fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return false;
1096fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1097fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr);
1098fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    const Method* method = saveArea->method;
1099fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    const u2* currentPc = saveArea->xtra.currentPc;
1100fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1101fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    /* check Method* */
1102fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if (!dvmLinearAllocContains(method, sizeof(Method))) {
1103062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("ExtrMon: method %p not valid", method);
1104fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return false;
1105fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    }
1106fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1107fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    /* check currentPc */
1108fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    u4 insnsSize = dvmGetMethodInsnsSize(method);
1109fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if (currentPc < method->insns ||
1110fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        currentPc >= method->insns + insnsSize)
1111fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    {
1112062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("ExtrMon: insns %p not valid (%p - %p)",
1113fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden            currentPc, method->insns, method->insns + insnsSize);
1114fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return false;
1115fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    }
1116fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1117fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    /* check the instruction */
1118fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if ((*currentPc & 0xff) != OP_MONITOR_ENTER) {
1119062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)",
1120fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden            currentPc, *currentPc & 0xff);
1121fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return false;
1122fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    }
1123fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1124fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    /* get and check the register index */
1125fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    unsigned int reg = *currentPc >> 8;
1126fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    if (reg >= method->registersSize) {
1127062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("ExtrMon: invalid register %d (max %d)",
1128fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden            reg, method->registersSize);
1129fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return false;
1130fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    }
1131fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1132fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    /* get and check the object in that register */
1133fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    u4* fp = (u4*) framePtr;
1134fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    Object* obj = (Object*) fp[reg];
11358bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes    if (obj != NULL && !dvmIsHeapAddress(obj)) {
1136062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("ExtrMon: invalid object %p at %p[%d]", obj, fp, reg);
1137fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden        return false;
1138fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    }
1139fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    *pLockObj = obj;
1140fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1141fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    /*
1142fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * Try to determine the object's lock holder; it's okay if this fails.
1143fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     *
1144fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * We're assuming the thread list lock is already held by this thread.
1145fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * If it's not, we may be living dangerously if we have to scan through
1146fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * the thread list to find a match.  (The VM will generally be in a
1147fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * suspended state when executing here, so this is a minor concern
1148fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * unless we're dumping while threads are running, in which case there's
1149fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     * a good chance of stuff blowing up anyway.)
1150fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden     */
1151fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    *pOwner = dvmGetObjectLockHolder(obj);
1152fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1153fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden    return true;
1154fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden}
1155fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden
1156708f143f318bb2167c810f9506102f4ad656545cElliott Hughesstatic void printWaitMessage(const DebugOutputTarget* target, const char* detail, Object* obj,
1157708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        Thread* thread)
1158708f143f318bb2167c810f9506102f4ad656545cElliott Hughes{
1159837eabb829417c1542037423c55536649de404b8Elliott Hughes    std::string msg(StringPrintf("  - waiting %s <%p> ", detail, obj));
1160708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
1161708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    if (obj->clazz != gDvm.classJavaLangClass) {
1162708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        // I(16573)   - waiting on <0xf5feda38> (a java.util.LinkedList)
1163fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes        // I(16573)   - waiting on <0xf5ed54f8> (a java.lang.Class<java.lang.ref.ReferenceQueue>)
1164fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes        msg += "(a " + dvmHumanReadableType(obj) + ")";
1165708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    }
1166708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
1167708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    if (thread != NULL) {
1168708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        std::string threadName(dvmGetThreadName(thread));
1169837eabb829417c1542037423c55536649de404b8Elliott Hughes        StringAppendF(&msg, " held by tid=%d (%s)", thread->threadId, threadName.c_str());
1170708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    }
1171708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
1172708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    dvmPrintDebugMessage(target, "%s\n", msg.c_str());
1173708f143f318bb2167c810f9506102f4ad656545cElliott Hughes}
1174708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
1175fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/*
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down.
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame).  This means
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM.  Because
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable.
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances.
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr,
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* thread)
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const StackSaveArea* saveArea;
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* method;
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int checkCount = 0;
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* currentPc = NULL;
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool first = true;
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1197d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden     * We call functions that require us to be holding the thread list lock.
1198d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden     * It's probable that the caller has already done so, but it's not
1199d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden     * guaranteed.  If it's not locked, lock it now.
1200d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden     */
1201d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden    bool needThreadUnlock = dvmTryLockThreadList();
1202d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden
1203d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden    /*
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The "currentPc" is updated whenever we execute an instruction that
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might throw an exception.  Show it here.
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1207fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) {
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(framePtr);
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (saveArea->xtra.currentPc != NULL)
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentPc = saveArea->xtra.currentPc;
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (framePtr != NULL) {
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(framePtr);
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = saveArea->method;
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1218fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)framePtr)) {
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmPrintDebugMessage(target, "  (break frame)\n");
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int relPc;
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (currentPc != NULL)
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                relPc = currentPc - saveArea->method->insns;
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                relPc = -1;
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12285719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes            std::string methodName(dvmHumanReadableMethod(method, false));
1229b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes            if (dvmIsNativeMethod(method)) {
12305719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes                dvmPrintDebugMessage(target, "  at %s(Native Method)\n",
12315719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes                        methodName.c_str());
1232b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes            } else {
12335719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes                dvmPrintDebugMessage(target, "  at %s(%s:%s%d)\n",
12345719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes                        methodName.c_str(), dvmGetMethodSourceFile(method),
1235b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes                        (relPc >= 0 && first) ? "~" : "",
1236b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes                        relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc));
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1239fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden            if (first) {
1240fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                /*
1241fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                 * Decorate WAIT and MONITOR threads with some detail on
1242fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                 * the first frame.
1243fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                 *
1244fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                 * warning: wait status not stable, even in suspend
1245fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                 */
1246fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                if (thread->status == THREAD_WAIT ||
1247fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    thread->status == THREAD_TIMED_WAIT)
1248fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                {
1249fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    Monitor* mon = thread->waitMonitor;
1250fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    Object* obj = dvmGetMonitorObject(mon);
1251fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    if (obj != NULL) {
1252d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden                        Thread* joinThread = NULL;
1253708f143f318bb2167c810f9506102f4ad656545cElliott Hughes                        if (obj->clazz == gDvm.classJavaLangVMThread) {
1254d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden                            joinThread = dvmGetThreadFromThreadObject(obj);
1255d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden                        }
1256708f143f318bb2167c810f9506102f4ad656545cElliott Hughes                        printWaitMessage(target, "on", obj, joinThread);
1257fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    }
1258fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                } else if (thread->status == THREAD_MONITOR) {
1259fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    Object* obj;
1260fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    Thread* owner;
1261fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    if (extractMonitorEnterObject(thread, &obj, &owner)) {
1262708f143f318bb2167c810f9506102f4ad656545cElliott Hughes                        printWaitMessage(target, "to lock", obj, owner);
1263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden                    }
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Get saved PC for previous frame.  There's no savedPc in a "break"
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * frame, because that represents native or interpreted code
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * invoked by the VM.  The saved PC is sitting in the "PC register",
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a local variable on the native stack.
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        currentPc = saveArea->savedPc;
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        first = false;
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12780083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) {
1279e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Warning: loop in stack trace at frame %d (%p -> %p)",
12800083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden                checkCount, framePtr, saveArea->prevFrame);
12810083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden            break;
12820083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        }
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        framePtr = saveArea->prevFrame;
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkCount++;
12860083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden        if (checkCount > 300) {
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPrintDebugMessage(target,
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "  ***** printed %d frames, not showing any more\n",
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                checkCount);
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1293d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden
1294d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden    if (needThreadUnlock) {
1295d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden        dvmUnlockThreadList();
1296d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden    }
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread.
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
130530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    dumpFrames(target, thread->interpSave.curFrame, thread);
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running.
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory.
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update.  This should
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system.
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM.
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveArea;
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* origStack;
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackCopy = NULL;
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int origSize, fpOffset;
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp;
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int depthLimit = 200;
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (thread == NULL || thread->interpSave.curFrame == NULL) {
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmPrintDebugMessage(target,
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thread, (thread != NULL) ? thread->threadId : 0);
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* wait for a full quantum */
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sched_yield();
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* copy the info we need, then the stack itself */
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origSize = thread->interpStackSize;
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origStack = (const u1*) thread->interpStackStart - origSize;
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackCopy = (u1*) malloc(origSize);
134230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    fpOffset = (u1*) thread->interpSave.curFrame - origStack;
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(stackCopy, origStack, origSize);
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through the stack and rewrite the "prev" pointers.
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
13484308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("DR: fpOff=%d (from %p %p)",fpOffset, origStack,
134930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    //     thread->interpSave.curFrame);
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = stackCopy + fpOffset;
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int prevOffset;
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (depthLimit-- < 0) {
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* we're probably screwed */
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n");
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (saveArea->prevFrame == NULL)
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        prevOffset = (u1*) saveArea->prevFrame - origStack;
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (prevOffset < 0 || prevOffset > origSize) {
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPrintDebugMessage(target,
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "DumpRunning: bad offset found: %d (from %p %p)\n",
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                prevOffset, origStack, saveArea->prevFrame);
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            saveArea->prevFrame = NULL;
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        saveArea->prevFrame = (u4*)(stackCopy + prevOffset);
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We still need to pass the Thread for some monitor wait stuff.
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpFrames(target, stackCopy + fpOffset, thread);
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(stackCopy);
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1382b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown
1383b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown/*
1384b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown * Dump the native stack for the specified thread.
1385b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown */
1386b1212301d5cffc06907211d243a21d50c4419dc9Jeff Brownvoid dvmDumpNativeStack(const DebugOutputTarget* target, pid_t tid)
1387b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown{
1388b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#ifdef HAVE_ANDROID_OS
1389b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown    const size_t MAX_DEPTH = 32;
1390b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown    backtrace_frame_t backtrace[MAX_DEPTH];
1391b1212301d5cffc06907211d243a21d50c4419dc9Jeff Brown    ssize_t frames = unwind_backtrace_thread(tid, backtrace, 0, MAX_DEPTH);
1392b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown    if (frames > 0) {
1393b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown        backtrace_symbol_t backtrace_symbols[MAX_DEPTH];
1394b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown        get_backtrace_symbols(backtrace, frames, backtrace_symbols);
1395b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown
1396b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown        for (size_t i = 0; i < size_t(frames); i++) {
139769c475676546a97f872df9e19125c0154b40ae0bJeff Brown            char line[MAX_BACKTRACE_LINE_LENGTH];
139869c475676546a97f872df9e19125c0154b40ae0bJeff Brown            format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
139969c475676546a97f872df9e19125c0154b40ae0bJeff Brown                    line, MAX_BACKTRACE_LINE_LENGTH);
140069c475676546a97f872df9e19125c0154b40ae0bJeff Brown            dvmPrintDebugMessage(target, "  %s\n", line);
1401b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown        }
1402b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown
1403b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown        free_backtrace_symbols(backtrace_symbols, frames);
1404b3667a19f5c573b7785876979af4781292d27327Andy McFadden    } else {
1405b3667a19f5c573b7785876979af4781292d27327Andy McFadden        dvmPrintDebugMessage(target, "  (native backtrace unavailable)\n");
1406b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown    }
1407b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown#endif
1408b78eab06552c503106eec5dc832a1eb5b1e0205aJeff Brown}
1409