Stack.c revision 8e5c78470229fd2f5474574081eaa4a2286aafea
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 */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stacks and their uses (e.g. native --> interpreted method calls).
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the majestic ASCII art in Stack.h.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "jni.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdarg.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the interpreter stack in a new thread.
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently this doesn't do much, since we don't need to zero out the
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack (and we really don't want to if it was created with mmap).
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitInterpStack(Thread* thread, int stackSize)
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thread->interpStackStart != NULL);
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thread->curFrame == NULL);
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling an interpreted method from an internal VM function or
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection.
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a frame for an interpreted method onto the stack.  This is only
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used when calling into interpreted code from native code.  (The
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreter does its own stack frame manipulation for interp-->interp
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls.)
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The size we need to reserve is the sum of parameters, local variables,
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved goodies, and outbound parameters.
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start by inserting a "break" frame, which ensures that the interpreter
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hands control back to us after the function we call returns or an
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncaught exception is thrown.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPushInterpFrame(Thread* self, const Method* method)
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* breakSaveBlock;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackReq;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackPtr;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsNativeMethod(method));
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsAbstractMethod(method));
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackReq = method->registersSize * 4        // params + locals
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                + sizeof(StackSaveArea) * 2     // break frame + regular frame
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                + method->outsSize * 4;         // args to other methods
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->curFrame != NULL)
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = self->interpStackStart;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackPtr - stackReq < self->interpStackEnd) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* not enough space */
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Stack overflow on call to interp (top=%p cur=%p size=%d %s.%s)\n",
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->interpStackStart, self->curFrame, self->interpStackSize,
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor, method->name);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHandleStackOverflow(self);
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shift the stack pointer down, leaving space for the function's
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * args/registers and save area.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= sizeof(StackSaveArea);
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock = (StackSaveArea*)stackPtr;
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = (StackSaveArea*) stackPtr;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* debug -- memset the new stack, unless we want valgrind's help */
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevSave = breakSaveBlock;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->prevFrame = self->curFrame;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->savedPc = NULL;             // not required
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->xtra.localRefTop = NULL;    // not required
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->method = NULL;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->savedPc = NULL;                  // not required
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->xtra.currentPc = NULL;           // not required?
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->method = method;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("PUSH frame: old=%p new=%p (size=%d)\n",
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame, FP_FROM_SAVEAREA(saveBlock),
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->curFrame = FP_FROM_SAVEAREA(saveBlock);
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling a JNI native method from an internal VM fuction or
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection.  This is also used to create the "fake" native-method
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames at the top of the interpreted stack.
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This actually pushes two frames; the first is a "break" frame.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top frame has additional space for JNI local reference tracking.
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushJNIFrame(Thread* self, const Method* method)
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* breakSaveBlock;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackReq;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackPtr;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsNativeMethod(method));
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackReq = method->registersSize * 4        // params only
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                + sizeof(StackSaveArea) * 2;    // break frame + regular frame
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->curFrame != NULL)
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackPtr = self->interpStackStart;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackPtr - stackReq < self->interpStackEnd) {
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* not enough space */
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Stack overflow on call to native (top=%p cur=%p size=%d '%s')\n",
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->interpStackStart, self->curFrame, self->interpStackSize,
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->name);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHandleStackOverflow(self);
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shift the stack pointer down, leaving space for just the stack save
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * area for the break frame, then shift down farther for the full frame.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We leave space for the method args, which are copied in later.
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= sizeof(StackSaveArea);
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock = (StackSaveArea*)stackPtr;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = (StackSaveArea*) stackPtr;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* debug -- memset the new stack */
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(stackPtr, 0xaf, stackReq);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->curFrame == NULL)
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        breakSaveBlock->prevSave = NULL;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevSave = breakSaveBlock;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->prevFrame = self->curFrame;
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->savedPc = NULL;             // not required
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->xtra.localRefTop = NULL;    // not required
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    breakSaveBlock->method = NULL;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->savedPc = NULL;                  // not required
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->method = method;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n",
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame, FP_FROM_SAVEAREA(saveBlock),
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->curFrame = FP_FROM_SAVEAREA(saveBlock);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by the JNI PushLocalFrame call.  We push a new frame onto
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack that has no ins, outs, or locals, and no break frame above it.
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's strictly used for tracking JNI local refs, and will be popped off
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by dvmPopFrame if it's not removed explicitly.
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushLocalFrame(Thread* self, const Method* method)
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackReq;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackPtr;
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsNativeMethod(method));
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackReq = sizeof(StackSaveArea);       // regular frame
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self->curFrame != NULL);
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackPtr - stackReq < self->interpStackEnd) {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* not enough space; let JNI throw the exception */
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Stack overflow on PushLocal (top=%p cur=%p size=%d '%s')\n",
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->interpStackStart, self->curFrame, self->interpStackSize,
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->name);
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHandleStackOverflow(self);
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Shift the stack pointer down, leaving space for just the stack save
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * area for the break frame, then shift down farther for the full frame.
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackPtr -= sizeof(StackSaveArea);
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = (StackSaveArea*) stackPtr;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* debug -- memset the new stack */
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(stackPtr, 0xaf, stackReq);
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->prevFrame = self->curFrame;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->savedPc = NULL;                  // not required
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock->method = method;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n",
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame, FP_FROM_SAVEAREA(saveBlock),
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->curFrame = FP_FROM_SAVEAREA(saveBlock);
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop one frame pushed on by JNI PushLocalFrame.
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we've gone too far, the previous frame is either a break frame or
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an interpreted frame.  Either way, the method pointer won't match.
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPopLocalFrame(Thread* self)
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame);
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsBreakFrame(self->curFrame));
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The previous frame doesn't have the same method pointer -- we've
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * been asked to pop too much.
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmIsBreakFrame(saveBlock->prevFrame) ||
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               !dvmIsNativeMethod(
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("POP JNI local frame: removing %s, now %s\n",
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveBlock->method->name,
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopJniLocals(self, saveBlock);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->curFrame = saveBlock->prevFrame;
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop a frame we added.  There should be one method frame and one break
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame.
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If JNI Push/PopLocalFrame calls were mismatched, we might end up
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popping multiple method frames before we find the break.
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" if there was no frame to pop.
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPopFrame(Thread* self)
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveBlock;
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->curFrame == NULL)
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    saveBlock = SAVEAREA_FROM_FP(self->curFrame);
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsBreakFrame(self->curFrame));
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Remove everything up to the break frame.  If this was a call into
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * native code, pop the JNI local references table.
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) {
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* probably a native->native JNI call */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(saveBlock->method)) {
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("Popping JNI stack frame for %s.%s%s\n",
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveBlock->method->clazz->descriptor,
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveBlock->method->name,
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "" : " (JNI local)");
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(saveBlock->xtra.localRefTop != NULL);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(saveBlock->xtra.localRefTop >=self->jniLocalRefTable.table &&
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveBlock->xtra.localRefTop <=self->jniLocalRefTable.nextEntry);
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPopJniLocals(self, saveBlock);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (saveBlock->method != NULL) {
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("PopFrame missed the break\n");
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();     // stack trashed -- nowhere to go in this thread
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("POP frame: cur=%p new=%p\n",
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame, saveBlock->prevFrame);
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->curFrame = saveBlock->prevFrame;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Common code for dvmCallMethodV/A and dvmInvokeMethod.
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pushes a call frame on, advancing self->curFrame.
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool checkAccess)
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->status != THREAD_RUNNING) {
354fea44bae077d2d5b4d5197132b2556fd3882d241Andy McFadden        LOGW("threadid=%d: status=%d on call to %s.%s -\n",
355fea44bae077d2d5b4d5197132b2556fd3882d241Andy McFadden            self->threadId, self->status,
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor, method->name);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(method != NULL);
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj != NULL)
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = obj->clazz;
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = method->clazz;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    IF_LOGVV() {
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("thread=%d native code calling %s.%s %s\n", self->threadId,
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor, method->name, desc);
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(desc);
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (checkAccess) {
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* needed for java.lang.reflect.Method.invoke */
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame),
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                method))
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* note this throws IAException, not IAError */
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalAccessException;",
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "access to method denied");
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Push a call frame on.  If there isn't enough room for ins, locals,
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * outs, and the saved state, it will throw an exception.
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This updates self->curFrame.
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* native code calling native code the hard way */
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmPushJNIFrame(self, method)) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* native code calling interpreted code */
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmPushInterpFrame(self, method)) {
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call.
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods.
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Note this can't be inlined because it takes a variable number of args.)
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethod(Thread* self, const Method* method, Object* obj,
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult, ...)
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue result;
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_list args;
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_start(args, pResult);
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmCallMethodV(self, method, obj, pResult, args);
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_end(args);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with a variable number of arguments.  We process
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature.
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods.
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to take the class as an argument because, in Dalvik,
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't need to worry about static synchronized methods.
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodV(Thread* self, const Method* method, Object* obj,
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult, va_list args)
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* desc = &(method->shorty[1]); // [0] is the return type.
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int verifyCount = 0;
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4* ins;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = callPrep(self, method, obj, false);
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "ins" for new frame start at frame pointer plus locals */
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("  FP is %p, INs live at >= %p\n", self->curFrame, ins);
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put "this" pointer into in0 if appropriate */
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(method)) {
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(obj != NULL && dvmIsValidObject(obj));
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ins++ = (u4) obj;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount++;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*desc != '\0') {
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (*(desc++)) {
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D': case 'J': {
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                u8 val = va_arg(args, u8);
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                memcpy(ins, &val, 8);       // EABI prevents direct store
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ins += 2;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount += 2;
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'F': {
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* floats were normalized to doubles; convert back */
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                float f = (float) va_arg(args, double);
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = dvmFloatToU4(f);
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'L': {     /* 'shorty' descr uses L for all refs, incl array */
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Object* argObj = (Object*) va_arg(args, u4);
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(obj == NULL || dvmIsValidObject(obj));
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = (u4) argObj;
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = va_arg(args, u4);
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verifyCount != method->insSize) {
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->insSize, clazz->descriptor, method->name);
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpThreadStack(dvmThreadSelf());
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we leave no space for local variables, "curFrame" points
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * directly at the method arguments.
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (*method->nativeFunc)(self->curFrame, pResult, method, self);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInterpret(self, method, pResult);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopFrame(self);
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with arguments provided in an array.  We process
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature.
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The values were likely placed into an uninitialized jvalue array using
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the field specifiers, which means that sub-32-bit fields (e.g. short,
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean) may not have 32 or 64 bits of valid data.  This is different
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the varargs invocation where the C compiler does a widening
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion when calling a function.  As a result, we have to be a
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * little more precise when pulling stuff out.
5318e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden *
5328e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * "args" may be NULL if the method has no arguments.
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodA(Thread* self, const Method* method, Object* obj,
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult, const jvalue* args)
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* desc = &(method->shorty[1]); // [0] is the return type.
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int verifyCount = 0;
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4* ins;
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = callPrep(self, method, obj, false);
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "ins" for new frame start at frame pointer plus locals */
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put "this" pointer into in0 if appropriate */
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(method)) {
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(obj != NULL);
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ins++ = (u4) obj;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount++;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*desc != '\0') {
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (*(desc++)) {
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D': case 'J': {
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                memcpy(ins, &args->j, 8);   /* EABI prevents direct store */
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ins += 2;
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount += 2;
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                args++;
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'F': case 'I': case 'L': { /* (no '[' in short signatures) */
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = args->i;           /* get all 32 bits */
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                args++;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'S': {
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = args->s;           /* 16 bits, sign-extended */
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                args++;
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'C': {
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = args->c;           /* 16 bits, unsigned */
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                args++;
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'B': {
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = args->b;           /* 8 bits, sign-extended */
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                args++;
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'Z': {
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *ins++ = args->z;           /* 8 bits, zero or non-zero */
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyCount++;
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                args++;
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("Invalid char %c in short signature of %s.%s\n",
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    *(desc-1), clazz->descriptor, method->name);
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verifyCount != method->insSize) {
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->insSize, clazz->descriptor, method->name);
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we leave no space for local variables, "curFrame" points
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * directly at the method arguments.
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (*method->nativeFunc)(self->curFrame, pResult, method, self);
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInterpret(self, method, pResult);
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopFrame(self);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces.  Could be a virtual or direct method
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors).  Used for reflection.
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions.
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method.
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it.
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method,
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool noAccessCheck)
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* retObj = NULL;
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    s4* ins;
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int verifyCount, argListLength;
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue retval;
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* verify arg count */
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argList != NULL)
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argListLength = argList->length;
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argListLength = 0;
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argListLength != (int) params->length) {
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("invoke: expected %d args, received %d args\n",
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            params->length, argListLength);
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/IllegalArgumentException;",
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "wrong number of arguments");
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = callPrep(self, method, obj, !noAccessCheck);
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "ins" for new frame start at frame pointer plus locals */
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyCount = 0;
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("  FP is %p, INs live at >= %p\n", self->curFrame, ins);
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put "this" pointer into in0 if appropriate */
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(method)) {
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(obj != NULL);
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ins++ = (s4) obj;
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount++;
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Copy the args onto the stack.  Primitive types are converted when
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * necessary, and object types are verified.
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DataObject** args;
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject** types;
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    args = (DataObject**) argList->contents;
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    types = (ClassObject**) params->contents;
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < argListLength; i++) {
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int width;
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        width = dvmConvertArgument(*args++, *types++, ins);
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (width < 0) {
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (*(args-1) != NULL) {
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n",
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    i, (*(args-1))->obj.clazz->descriptor,
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    (*(types-1))->descriptor);
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPopFrame(self);      // throw wants to pull PC out of stack
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalArgumentException;",
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "argument type mismatch");
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_popped;
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ins += width;
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyCount += width;
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (verifyCount != method->insSize) {
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->insSize, clazz->descriptor, method->name);
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpThreadStack(dvmThreadSelf());
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsNativeMethod(method)) {
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we leave no space for local variables, "curFrame" points
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * directly at the method arguments.
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (*method->nativeFunc)(self->curFrame, &retval, method, self);
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInterpret(self, method, &retval);
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If an exception is raised, wrap and replace.  This is necessary
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because the invoked method could have thrown a checked exception
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that the caller wasn't prepared for.
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We might be able to do this up in the interpreted code, but that will
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * leave us with a shortened stack trace in the top-level exception.
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmWrapException("Ljava/lang/reflect/InvocationTargetException;");
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If this isn't a void method or constructor, convert the return type
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to an appropriate object.
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't do this when an exception is raised because the value
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in "retval" is undefined.
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (returnType != NULL) {
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            retObj = (Object*)dvmWrapPrimitive(retval, returnType);
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(retObj, NULL);
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPopFrame(self);
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_popped:
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return retObj;
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct LineNumFromPcContext {
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 address;
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 lineNum;
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} LineNumFromPcContext;
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt;
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // We know that this callback will be called in
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ascending address order, so keep going until we find
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // a match or we've just gone past it.
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (address > pContext->address) {
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // The line number from the previous positions callback
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // wil be the final result.
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 1;
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pContext->lineNum = lineNum;
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (address == pContext->address) ? 1 : 0;
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter.
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code.
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present).
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces).
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc)
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pDexCode = dvmGetMethodCode(method);
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexCode == NULL) {
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method))
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -2;
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;      /* can happen for abstract method stub */
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LineNumFromPcContext context;
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&context, 0, sizeof(context));
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    context.address = relPc;
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // A method with no line number info should return -1
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    context.lineNum = -1;
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode,
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor,
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->prototype.protoIdx,
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->accessFlags,
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumForPcCb, NULL, &context);
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return context.lineNum;
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth.
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames.
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp)
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = 0;
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsBreakFrame(fp))
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction.
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation.
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction.
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* interpStackStart = thread->interpStackStart;
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* interpStackBottom = interpStackStart - thread->interpStackSize;
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((u1*) fp >= interpStackBottom && (u1*) fp < interpStackStart);
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return interpStackStart - (u1*) fp;
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame.  Pass in the current fp.
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames.
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame)
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveArea;
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry:
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsBreakFrame(caller)) {
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* pop up one more */
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        caller = SAVEAREA_FROM_FP(caller)->prevFrame;
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (caller == NULL)
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;        /* hit the top */
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we got here by java.lang.reflect.Method.invoke(), we don't
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * want to return Method's class loader.  Shift up one and try
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * again.
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(caller);
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsReflectionMethod(saveArea->method)) {
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            caller = saveArea->prevFrame;
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(caller != NULL);
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto retry;
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return caller;
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class.  Pass in the current fp.
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class.
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame)
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller;
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    caller = dvmGetCallerFP(curFrame);
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (caller == NULL)
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return SAVEAREA_FROM_FP(caller)->method->clazz;
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class.  Pass in the current fp.
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it.
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame)
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* callerCaller;
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* at the top? */
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* go one more */
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    callerCaller = dvmGetCallerFP(caller);
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (callerCaller == NULL)
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return SAVEAREA_FROM_FP(callerCaller)->method->clazz;
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class.  Pass in the current fp.
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it.
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame)
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* at the top? */
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Walk up two frames if possible. */
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < 2; i++) {
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        caller = dvmGetCallerFP(caller);
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (caller == NULL)
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return SAVEAREA_FROM_FP(caller)->method->clazz;
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a flat array of methods that comprise the current interpreter
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack trace.  Pass in the current frame ptr.
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocates a new array and fills it with method pointers.  Break frames
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are skipped, but reflection invocations are not.  The caller must free
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "*pArray".
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0.
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success, "false" on failure (e.g. malloc failed).
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* pLength)
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method** array;
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx, depth;
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    depth = dvmComputeExactFrameDepth(fp);
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    array = (const Method**) malloc(depth * sizeof(Method*));
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (array == NULL)
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsBreakFrame(fp))
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            array[idx++] = SAVEAREA_FROM_FP(fp)->method;
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx == depth);
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pArray = array;
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pLength = depth;
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception.  The reserved area
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself.
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM.
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing.  This is because the catch handler may
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list.
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmHandleStackOverflow(Thread* self)
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Can we make the reserved area available?
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->stackOverflowed) {
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Already did, nothing to do but bail.
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n",
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->threadId);
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(self, false);
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* open it up to the full range */
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("Stack overflow, expanding (%p to %p)\n", self->interpStackEnd,
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->interpStackStart - self->interpStackSize);
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpThread(self, false);
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->interpStackEnd = self->interpStackStart - self->interpStackSize;
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->stackOverflowed = true;
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we were trying to throw an exception when the stack overflowed,
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we will blow up when doing the class lookup on StackOverflowError
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because of the pending exception.  So, we clear it and make it
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the cause of the SOE.
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* excep = dvmGetException(self);
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (excep != NULL) {
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Stack overflow while throwing exception\n");
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(self);
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowChainedException("Ljava/lang/StackOverflowError;", NULL, excep);
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size.  By this point we should have finished
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing.
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCleanupStackOverflow(Thread* self)
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* newStackEnd;
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self->stackOverflowed);
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newStackEnd = (self->interpStackStart - self->interpStackSize)
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        + STACK_OVERFLOW_RESERVE;
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((u1*)self->curFrame <= newStackEnd) {
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n",
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->interpStackEnd, self->curFrame);
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpThread(self, false);
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->interpStackEnd = newStackEnd;
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->stackOverflowed = false;
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd,
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame);
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down.
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame).  This means
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM.  Because
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable.
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances.
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr,
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* thread)
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const StackSaveArea* saveArea;
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* method;
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int checkCount = 0;
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* currentPc = NULL;
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool first = true;
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The "currentPc" is updated whenever we execute an instruction that
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might throw an exception.  Show it here.
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) {
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(framePtr);
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (saveArea->xtra.currentPc != NULL)
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            currentPc = saveArea->xtra.currentPc;
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (framePtr != NULL) {
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(framePtr);
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = saveArea->method;
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsBreakFrame(framePtr)) {
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmPrintDebugMessage(target, "  (break frame)\n");
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int relPc;
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (currentPc != NULL)
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                relPc = currentPc - saveArea->method->insns;
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                relPc = -1;
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char* className = dvmDescriptorToDot(method->clazz->descriptor);
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmIsNativeMethod(method))
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmPrintDebugMessage(target,
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "  at %s.%s(Native Method)\n", className, method->name);
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else {
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmPrintDebugMessage(target,
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "  at %s.%s(%s:%s%d)\n",
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    className, method->name, dvmGetMethodSourceFile(method),
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    (relPc >= 0 && first) ? "~" : "",
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc));
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(className);
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (first &&
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (thread->status == THREAD_WAIT ||
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 thread->status == THREAD_TIMED_WAIT))
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* warning: wait status not stable, even in suspend */
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Monitor* mon = thread->waitMonitor;
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Object* obj = dvmGetMonitorObject(mon);
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (obj != NULL) {
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    className = dvmDescriptorToDot(obj->clazz->descriptor);
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmPrintDebugMessage(target,
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "  - waiting on <%p> (a %s)\n", mon, className);
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    free(className);
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Get saved PC for previous frame.  There's no savedPc in a "break"
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * frame, because that represents native or interpreted code
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * invoked by the VM.  The saved PC is sitting in the "PC register",
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a local variable on the native stack.
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        currentPc = saveArea->savedPc;
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        first = false;
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(framePtr != saveArea->prevFrame);
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        framePtr = saveArea->prevFrame;
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkCount++;
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (checkCount > 200) {
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPrintDebugMessage(target,
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "  ***** printed %d frames, not showing any more\n",
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                checkCount);
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmPrintDebugMessage(target, "\n");
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread.
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpFrames(target, thread->curFrame, thread);
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running.
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory.
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update.  This should
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system.
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM.
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StackSaveArea* saveArea;
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* origStack;
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1* stackCopy = NULL;
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int origSize, fpOffset;
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp;
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int depthLimit = 200;
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (thread == NULL || thread->curFrame == NULL) {
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmPrintDebugMessage(target,
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thread, (thread != NULL) ? thread->threadId : 0);
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* wait for a full quantum */
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sched_yield();
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* copy the info we need, then the stack itself */
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origSize = thread->interpStackSize;
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origStack = (const u1*) thread->interpStackStart - origSize;
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackCopy = (u1*) malloc(origSize);
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fpOffset = (u1*) thread->curFrame - origStack;
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(stackCopy, origStack, origSize);
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through the stack and rewrite the "prev" pointers.
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame);
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = stackCopy + fpOffset;
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int prevOffset;
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (depthLimit-- < 0) {
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* we're probably screwed */
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n");
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (saveArea->prevFrame == NULL)
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        prevOffset = (u1*) saveArea->prevFrame - origStack;
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (prevOffset < 0 || prevOffset > origSize) {
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPrintDebugMessage(target,
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "DumpRunning: bad offset found: %d (from %p %p)\n",
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                prevOffset, origStack, saveArea->prevFrame);
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            saveArea->prevFrame = NULL;
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea->prevFrame = stackCopy + prevOffset;
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We still need to pass the Thread for some monitor wait stuff.
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpFrames(target, stackCopy + fpOffset, thread);
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(stackCopy);
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1237