blob: 67566e86d9efc44b3e28daefe268c1d5345b4b4a [file] [log] [blame]
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -080016
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070017/*
18 * Main interpreter entry point and support functions.
19 *
20 * The entry point selects the "standard" or "debug" interpreter and
21 * facilitates switching between them. The standard interpreter may
22 * use the "fast" or "portable" implementation.
23 *
Andy McFadden0d615c32010-08-18 12:19:51 -070024 * Some debugger support functions are included here.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070025 */
26#include "Dalvik.h"
27#include "interp/InterpDefs.h"
buzbee9a3147c2011-03-02 15:43:48 -080028#if defined(WITH_JIT)
29#include "interp/Jit.h"
30#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070031
32
33/*
34 * ===========================================================================
35 * Debugger support
36 * ===========================================================================
37 */
38
Andy McFadden96516932009-10-28 17:39:02 -070039// fwd
Carl Shapiro1e1433e2011-04-20 16:51:38 -070040static BreakpointSet* dvmBreakpointSetAlloc();
Andy McFadden96516932009-10-28 17:39:02 -070041static void dvmBreakpointSetFree(BreakpointSet* pSet);
42
Carl Shapiro1813ab22011-04-15 15:48:54 -070043#if defined(WITH_JIT)
44/* Target-specific save/restore */
45extern "C" void dvmJitCalleeSave(double *saveArea);
46extern "C" void dvmJitCalleeRestore(double *saveArea);
47/* Interpreter entry points from compiled code */
48extern "C" void dvmJitToInterpNormal();
49extern "C" void dvmJitToInterpNoChain();
50extern "C" void dvmJitToInterpPunt();
51extern "C" void dvmJitToInterpSingleStep();
52extern "C" void dvmJitToInterpTraceSelect();
53#if defined(WITH_SELF_VERIFICATION)
54extern "C" void dvmJitToInterpBackwardBranch();
55#endif
56#endif
57
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070058/*
Andy McFadden96516932009-10-28 17:39:02 -070059 * Initialize global breakpoint structures.
60 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -070061bool dvmBreakpointStartup()
Andy McFadden96516932009-10-28 17:39:02 -070062{
Andy McFadden96516932009-10-28 17:39:02 -070063 gDvm.breakpointSet = dvmBreakpointSetAlloc();
64 return (gDvm.breakpointSet != NULL);
Andy McFadden96516932009-10-28 17:39:02 -070065}
66
67/*
68 * Free resources.
69 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -070070void dvmBreakpointShutdown()
Andy McFadden96516932009-10-28 17:39:02 -070071{
Andy McFadden96516932009-10-28 17:39:02 -070072 dvmBreakpointSetFree(gDvm.breakpointSet);
Andy McFadden96516932009-10-28 17:39:02 -070073}
74
75
Andy McFadden96516932009-10-28 17:39:02 -070076/*
77 * This represents a breakpoint inserted in the instruction stream.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070078 *
Andy McFadden96516932009-10-28 17:39:02 -070079 * The debugger may ask us to create the same breakpoint multiple times.
80 * We only remove the breakpoint when the last instance is cleared.
81 */
Carl Shapirod862faa2011-04-27 23:00:01 -070082struct Breakpoint {
Andy McFaddend22748a2010-04-22 17:08:11 -070083 Method* method; /* method we're associated with */
Andy McFadden96516932009-10-28 17:39:02 -070084 u2* addr; /* absolute memory address */
Dan Bornstein9a1f8162010-12-01 17:02:26 -080085 u1 originalOpcode; /* original 8-bit opcode value */
Andy McFadden96516932009-10-28 17:39:02 -070086 int setCount; /* #of times this breakpoint was set */
Carl Shapirod862faa2011-04-27 23:00:01 -070087};
Andy McFadden96516932009-10-28 17:39:02 -070088
89/*
90 * Set of breakpoints.
91 */
92struct BreakpointSet {
93 /* grab lock before reading or writing anything else in here */
94 pthread_mutex_t lock;
95
96 /* vector of breakpoint structures */
97 int alloc;
98 int count;
99 Breakpoint* breakpoints;
100};
101
102/*
103 * Initialize a BreakpointSet. Initially empty.
104 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700105static BreakpointSet* dvmBreakpointSetAlloc()
Andy McFadden96516932009-10-28 17:39:02 -0700106{
107 BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
108
109 dvmInitMutex(&pSet->lock);
110 /* leave the rest zeroed -- will alloc on first use */
111
112 return pSet;
113}
114
115/*
116 * Free storage associated with a BreakpointSet.
117 */
118static void dvmBreakpointSetFree(BreakpointSet* pSet)
119{
120 if (pSet == NULL)
121 return;
122
123 free(pSet->breakpoints);
124 free(pSet);
125}
126
127/*
128 * Lock the breakpoint set.
Andy McFaddend22748a2010-04-22 17:08:11 -0700129 *
130 * It's not currently necessary to switch to VMWAIT in the event of
131 * contention, because nothing in here can block. However, it's possible
132 * that the bytecode-updater code could become fancier in the future, so
133 * we do the trylock dance as a bit of future-proofing.
Andy McFadden96516932009-10-28 17:39:02 -0700134 */
135static void dvmBreakpointSetLock(BreakpointSet* pSet)
136{
Andy McFaddend22748a2010-04-22 17:08:11 -0700137 if (dvmTryLockMutex(&pSet->lock) != 0) {
138 Thread* self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700139 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700140 dvmLockMutex(&pSet->lock);
141 dvmChangeStatus(self, oldStatus);
142 }
Andy McFadden96516932009-10-28 17:39:02 -0700143}
144
145/*
146 * Unlock the breakpoint set.
147 */
148static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
149{
150 dvmUnlockMutex(&pSet->lock);
151}
152
153/*
154 * Return the #of breakpoints.
155 */
156static int dvmBreakpointSetCount(const BreakpointSet* pSet)
157{
158 return pSet->count;
159}
160
161/*
162 * See if we already have an entry for this address.
163 *
164 * The BreakpointSet's lock must be acquired before calling here.
165 *
166 * Returns the index of the breakpoint entry, or -1 if not found.
167 */
168static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
169{
170 int i;
171
172 for (i = 0; i < pSet->count; i++) {
173 Breakpoint* pBreak = &pSet->breakpoints[i];
174 if (pBreak->addr == addr)
175 return i;
176 }
177
178 return -1;
179}
180
181/*
182 * Retrieve the opcode that was originally at the specified location.
183 *
184 * The BreakpointSet's lock must be acquired before calling here.
185 *
186 * Returns "true" with the opcode in *pOrig on success.
187 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800188static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
Andy McFadden96516932009-10-28 17:39:02 -0700189 const u2* addr, u1* pOrig)
190{
191 int idx = dvmBreakpointSetFind(pSet, addr);
192 if (idx < 0)
193 return false;
194
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800195 *pOrig = pSet->breakpoints[idx].originalOpcode;
Andy McFadden96516932009-10-28 17:39:02 -0700196 return true;
197}
198
199/*
Andy McFaddenda9dc842010-05-03 16:11:20 -0700200 * Check the opcode. If it's a "magic" NOP, indicating the start of
201 * switch or array data in the instruction stream, we don't want to set
202 * a breakpoint.
203 *
204 * This can happen because the line number information dx generates
205 * associates the switch data with the switch statement's line number,
206 * and some debuggers put breakpoints at every address associated with
207 * a given line. The result is that the breakpoint stomps on the NOP
208 * instruction that doubles as a data table magic number, and an explicit
209 * check in the interpreter results in an exception being thrown.
210 *
211 * We don't want to simply refuse to add the breakpoint to the table,
212 * because that confuses the housekeeping. We don't want to reject the
213 * debugger's event request, and we want to be sure that there's exactly
214 * one un-set operation for every set op.
215 */
216static bool instructionIsMagicNop(const u2* addr)
217{
218 u2 curVal = *addr;
buzbee9a3147c2011-03-02 15:43:48 -0800219 return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700220}
221
222/*
Andy McFadden96516932009-10-28 17:39:02 -0700223 * Add a breakpoint at a specific address. If the address is already
224 * present in the table, this just increments the count.
225 *
226 * For a new entry, this will extract and preserve the current opcode from
227 * the instruction stream, and replace it with a breakpoint opcode.
228 *
229 * The BreakpointSet's lock must be acquired before calling here.
230 *
231 * Returns "true" on success.
232 */
233static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
234 unsigned int instrOffset)
235{
236 const int kBreakpointGrowth = 10;
237 const u2* addr = method->insns + instrOffset;
238 int idx = dvmBreakpointSetFind(pSet, addr);
239 Breakpoint* pBreak;
240
241 if (idx < 0) {
242 if (pSet->count == pSet->alloc) {
243 int newSize = pSet->alloc + kBreakpointGrowth;
244 Breakpoint* newVec;
245
246 LOGV("+++ increasing breakpoint set size to %d\n", newSize);
247
248 /* pSet->breakpoints will be NULL on first entry */
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800249 newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
Andy McFadden96516932009-10-28 17:39:02 -0700250 if (newVec == NULL)
251 return false;
252
253 pSet->breakpoints = newVec;
254 pSet->alloc = newSize;
255 }
256
257 pBreak = &pSet->breakpoints[pSet->count++];
Andy McFaddend22748a2010-04-22 17:08:11 -0700258 pBreak->method = method;
Andy McFadden96516932009-10-28 17:39:02 -0700259 pBreak->addr = (u2*)addr;
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800260 pBreak->originalOpcode = *(u1*)addr;
Andy McFadden96516932009-10-28 17:39:02 -0700261 pBreak->setCount = 1;
262
263 /*
264 * Change the opcode. We must ensure that the BreakpointSet
265 * updates happen before we change the opcode.
Andy McFaddend22748a2010-04-22 17:08:11 -0700266 *
267 * If the method has not been verified, we do NOT insert the
268 * breakpoint yet, since that will screw up the verifier. The
269 * debugger is allowed to insert breakpoints in unverified code,
270 * but since we don't execute unverified code we don't need to
271 * alter the bytecode yet.
272 *
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700273 * The class init code will "flush" all pending opcode writes
274 * before verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700275 */
Andy McFadden96516932009-10-28 17:39:02 -0700276 assert(*(u1*)addr != OP_BREAKPOINT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700277 if (dvmIsClassVerified(method->clazz)) {
278 LOGV("Class %s verified, adding breakpoint at %p\n",
279 method->clazz->descriptor, addr);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700280 if (instructionIsMagicNop(addr)) {
281 LOGV("Refusing to set breakpoint on %04x at %s.%s + 0x%x\n",
282 *addr, method->clazz->descriptor, method->name,
283 instrOffset);
284 } else {
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700285 ANDROID_MEMBAR_FULL();
Andy McFaddenda9dc842010-05-03 16:11:20 -0700286 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
287 OP_BREAKPOINT);
288 }
Andy McFaddend22748a2010-04-22 17:08:11 -0700289 } else {
290 LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
291 method->clazz->descriptor, addr);
292 }
Andy McFadden96516932009-10-28 17:39:02 -0700293 } else {
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700294 /*
295 * Breakpoint already exists, just increase the count.
296 */
Andy McFadden96516932009-10-28 17:39:02 -0700297 pBreak = &pSet->breakpoints[idx];
298 pBreak->setCount++;
Andy McFadden96516932009-10-28 17:39:02 -0700299 }
300
301 return true;
302}
303
304/*
305 * Remove one instance of the specified breakpoint. When the count
306 * reaches zero, the entry is removed from the table, and the original
307 * opcode is restored.
308 *
309 * The BreakpointSet's lock must be acquired before calling here.
310 */
311static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
312 unsigned int instrOffset)
313{
314 const u2* addr = method->insns + instrOffset;
315 int idx = dvmBreakpointSetFind(pSet, addr);
316
317 if (idx < 0) {
318 /* breakpoint not found in set -- unexpected */
319 if (*(u1*)addr == OP_BREAKPOINT) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700320 LOGE("Unable to restore breakpoint opcode (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700321 method->clazz->descriptor, method->name, instrOffset);
322 dvmAbort();
323 } else {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700324 LOGW("Breakpoint was already restored? (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700325 method->clazz->descriptor, method->name, instrOffset);
326 }
327 } else {
328 Breakpoint* pBreak = &pSet->breakpoints[idx];
329 if (pBreak->setCount == 1) {
330 /*
331 * Must restore opcode before removing set entry.
Andy McFaddend22748a2010-04-22 17:08:11 -0700332 *
333 * If the breakpoint was never flushed, we could be ovewriting
334 * a value with the same value. Not a problem, though we
335 * could end up causing a copy-on-write here when we didn't
336 * need to. (Not worth worrying about.)
Andy McFadden96516932009-10-28 17:39:02 -0700337 */
338 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800339 pBreak->originalOpcode);
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700340 ANDROID_MEMBAR_FULL();
Andy McFadden96516932009-10-28 17:39:02 -0700341
342 if (idx != pSet->count-1) {
343 /* shift down */
344 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
345 (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
346 }
347 pSet->count--;
348 pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
349 } else {
350 pBreak->setCount--;
351 assert(pBreak->setCount > 0);
352 }
353 }
354}
355
356/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700357 * Flush any breakpoints associated with methods in "clazz". We want to
358 * change the opcode, which might not have happened when the breakpoint
359 * was initially set because the class was in the process of being
360 * verified.
Andy McFadden96516932009-10-28 17:39:02 -0700361 *
362 * The BreakpointSet's lock must be acquired before calling here.
363 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700364static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700365{
Andy McFadden96516932009-10-28 17:39:02 -0700366 int i;
367 for (i = 0; i < pSet->count; i++) {
368 Breakpoint* pBreak = &pSet->breakpoints[i];
Andy McFaddend22748a2010-04-22 17:08:11 -0700369 if (pBreak->method->clazz == clazz) {
370 /*
371 * The breakpoint is associated with a method in this class.
372 * It might already be there or it might not; either way,
373 * flush it out.
374 */
375 LOGV("Flushing breakpoint at %p for %s\n",
376 pBreak->addr, clazz->descriptor);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700377 if (instructionIsMagicNop(pBreak->addr)) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700378 LOGV("Refusing to flush breakpoint on %04x at %s.%s + 0x%x\n",
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700379 *pBreak->addr, pBreak->method->clazz->descriptor,
380 pBreak->method->name, pBreak->addr - pBreak->method->insns);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700381 } else {
382 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
383 OP_BREAKPOINT);
384 }
Andy McFadden96516932009-10-28 17:39:02 -0700385 }
386 }
387}
Andy McFadden96516932009-10-28 17:39:02 -0700388
389
390/*
391 * Do any debugger-attach-time initialization.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700392 */
Carl Shapiro1e1433e2011-04-20 16:51:38 -0700393void dvmInitBreakpoints()
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700394{
Andy McFadden96516932009-10-28 17:39:02 -0700395 /* quick sanity check */
396 BreakpointSet* pSet = gDvm.breakpointSet;
397 dvmBreakpointSetLock(pSet);
398 if (dvmBreakpointSetCount(pSet) != 0) {
399 LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
400 /* generally not good, but we can keep going */
401 }
402 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700403}
404
405/*
406 * Add an address to the list, putting it in the first non-empty slot.
407 *
408 * Sometimes the debugger likes to add two entries for one breakpoint.
409 * We add two entries here, so that we get the right behavior when it's
410 * removed twice.
411 *
412 * This will only be run from the JDWP thread, and it will happen while
413 * we are updating the event list, which is synchronized. We're guaranteed
414 * to be the only one adding entries, and the lock ensures that nobody
415 * will be trying to remove them while we're in here.
416 *
417 * "addr" is the absolute address of the breakpoint bytecode.
418 */
Andy McFadden96516932009-10-28 17:39:02 -0700419void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700420{
Andy McFadden96516932009-10-28 17:39:02 -0700421 BreakpointSet* pSet = gDvm.breakpointSet;
422 dvmBreakpointSetLock(pSet);
423 dvmBreakpointSetAdd(pSet, method, instrOffset);
424 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700425}
426
427/*
428 * Remove an address from the list by setting the entry to NULL.
429 *
430 * This can be called from the JDWP thread (because the debugger has
431 * cancelled the breakpoint) or from an event thread (because it's a
432 * single-shot breakpoint, e.g. "run to line"). We only get here as
433 * the result of removing an entry from the event list, which is
434 * synchronized, so it should not be possible for two threads to be
435 * updating breakpoints at the same time.
436 */
Andy McFadden96516932009-10-28 17:39:02 -0700437void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700438{
Andy McFadden96516932009-10-28 17:39:02 -0700439 BreakpointSet* pSet = gDvm.breakpointSet;
440 dvmBreakpointSetLock(pSet);
441 dvmBreakpointSetRemove(pSet, method, instrOffset);
442 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700443}
444
Andy McFadden96516932009-10-28 17:39:02 -0700445/*
446 * Get the original opcode from under a breakpoint.
Andy McFaddenfc3d3162010-08-05 14:34:26 -0700447 *
448 * On SMP hardware it's possible one core might try to execute a breakpoint
449 * after another core has cleared it. We need to handle the case where
450 * there's no entry in the breakpoint set. (The memory barriers in the
451 * locks and in the breakpoint update code should ensure that, once we've
452 * observed the absence of a breakpoint entry, we will also now observe
453 * the restoration of the original opcode. The fact that we're holding
454 * the lock prevents other threads from confusing things further.)
Andy McFadden96516932009-10-28 17:39:02 -0700455 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800456u1 dvmGetOriginalOpcode(const u2* addr)
Andy McFadden96516932009-10-28 17:39:02 -0700457{
458 BreakpointSet* pSet = gDvm.breakpointSet;
459 u1 orig = 0;
460
461 dvmBreakpointSetLock(pSet);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800462 if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
Andy McFadden96516932009-10-28 17:39:02 -0700463 orig = *(u1*)addr;
464 if (orig == OP_BREAKPOINT) {
465 LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
466 dvmAbort();
467 }
468 }
469 dvmBreakpointSetUnlock(pSet);
470
471 return orig;
472}
473
474/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700475 * Flush any breakpoints associated with methods in "clazz".
Andy McFadden96516932009-10-28 17:39:02 -0700476 *
Andy McFaddend22748a2010-04-22 17:08:11 -0700477 * We don't want to modify the bytecode of a method before the verifier
478 * gets a chance to look at it, so we postpone opcode replacement until
479 * after verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700480 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700481void dvmFlushBreakpoints(ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700482{
483 BreakpointSet* pSet = gDvm.breakpointSet;
484
Andy McFaddend22748a2010-04-22 17:08:11 -0700485 if (pSet == NULL)
486 return;
487
488 assert(dvmIsClassVerified(clazz));
Andy McFadden96516932009-10-28 17:39:02 -0700489 dvmBreakpointSetLock(pSet);
Andy McFaddend22748a2010-04-22 17:08:11 -0700490 dvmBreakpointSetFlush(pSet, clazz);
Andy McFadden96516932009-10-28 17:39:02 -0700491 dvmBreakpointSetUnlock(pSet);
492}
Andy McFadden96516932009-10-28 17:39:02 -0700493
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700494/*
495 * Add a single step event. Currently this is a global item.
496 *
497 * We set up some initial values based on the thread's current state. This
498 * won't work well if the thread is running, so it's up to the caller to
499 * verify that it's suspended.
500 *
501 * This is only called from the JDWP thread.
502 */
503bool dvmAddSingleStep(Thread* thread, int size, int depth)
504{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700505 StepControl* pCtrl = &gDvm.stepControl;
506
507 if (pCtrl->active && thread != pCtrl->thread) {
508 LOGW("WARNING: single-step active for %p; adding %p\n",
509 pCtrl->thread, thread);
510
511 /*
512 * Keep going, overwriting previous. This can happen if you
513 * suspend a thread in Object.wait, hit the single-step key, then
514 * switch to another thread and do the same thing again.
515 * The first thread's step is still pending.
516 *
517 * TODO: consider making single-step per-thread. Adds to the
518 * overhead, but could be useful in rare situations.
519 */
520 }
521
Carl Shapiro1813ab22011-04-15 15:48:54 -0700522 pCtrl->size = static_cast<JdwpStepSize>(size);
523 pCtrl->depth = static_cast<JdwpStepDepth>(depth);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700524 pCtrl->thread = thread;
525
526 /*
527 * We may be stepping into or over method calls, or running until we
528 * return from the current method. To make this work we need to track
529 * the current line, current method, and current stack depth. We need
530 * to be checking these after most instructions, notably those that
531 * call methods, return from methods, or are on a different line from the
532 * previous instruction.
533 *
534 * We have to start with a snapshot of the current state. If we're in
535 * an interpreted method, everything we need is in the current frame. If
536 * we're in a native method, possibly with some extra JNI frames pushed
537 * on by PushLocalFrame, we want to use the topmost native method.
538 */
539 const StackSaveArea* saveArea;
buzbee30bc0d42011-04-22 10:27:14 -0700540 u4* fp;
541 u4* prevFp = NULL;
Ben Cheng38329f52009-07-07 14:19:20 -0700542
buzbee30bc0d42011-04-22 10:27:14 -0700543 for (fp = thread->interpSave.curFrame; fp != NULL;
544 fp = saveArea->prevFrame) {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700545 const Method* method;
546
547 saveArea = SAVEAREA_FROM_FP(fp);
548 method = saveArea->method;
549
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800550 if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700551 break;
552 prevFp = fp;
553 }
554 if (fp == NULL) {
555 LOGW("Unexpected: step req in native-only threadid=%d\n",
556 thread->threadId);
557 return false;
558 }
559 if (prevFp != NULL) {
560 /*
561 * First interpreted frame wasn't the one at the bottom. Break
562 * frames are only inserted when calling from native->interp, so we
563 * don't need to worry about one being here.
564 */
565 LOGV("##### init step while in native method\n");
566 fp = prevFp;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800567 assert(!dvmIsBreakFrame((u4*)fp));
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700568 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
569 saveArea = SAVEAREA_FROM_FP(fp);
570 }
571
572 /*
573 * Pull the goodies out. "xtra.currentPc" should be accurate since
574 * we update it on every instruction while the debugger is connected.
575 */
576 pCtrl->method = saveArea->method;
577 // Clear out any old address set
578 if (pCtrl->pAddressSet != NULL) {
579 // (discard const)
580 free((void *)pCtrl->pAddressSet);
581 pCtrl->pAddressSet = NULL;
582 }
583 if (dvmIsNativeMethod(pCtrl->method)) {
584 pCtrl->line = -1;
585 } else {
586 pCtrl->line = dvmLineNumFromPC(saveArea->method,
587 saveArea->xtra.currentPc - saveArea->method->insns);
Ben Cheng38329f52009-07-07 14:19:20 -0700588 pCtrl->pAddressSet
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700589 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
590 }
buzbee30bc0d42011-04-22 10:27:14 -0700591 pCtrl->frameDepth =
592 dvmComputeVagueFrameDepth(thread, thread->interpSave.curFrame);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700593 pCtrl->active = true;
594
595 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
596 pCtrl->thread, pCtrl->method, pCtrl->method->name,
597 pCtrl->line, pCtrl->frameDepth,
598 dvmJdwpStepDepthStr(pCtrl->depth),
599 dvmJdwpStepSizeStr(pCtrl->size));
600
601 return true;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700602}
603
604/*
605 * Disable a single step event.
606 */
607void dvmClearSingleStep(Thread* thread)
608{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700609 UNUSED_PARAMETER(thread);
610
611 gDvm.stepControl.active = false;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700612}
613
buzbee9a3147c2011-03-02 15:43:48 -0800614/*
615 * The interpreter just threw. Handle any special subMode requirements.
buzbee99e3e6e2011-03-29 10:26:07 -0700616 * All interpSave state must be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800617 */
buzbee99e3e6e2011-03-29 10:26:07 -0700618void dvmReportExceptionThrow(Thread* self, Object* exception)
buzbee9a3147c2011-03-02 15:43:48 -0800619{
buzbee99e3e6e2011-03-29 10:26:07 -0700620 const Method* curMethod = self->interpSave.method;
buzbee9a3147c2011-03-02 15:43:48 -0800621#if defined(WITH_JIT)
622 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
buzbee99e3e6e2011-03-29 10:26:07 -0700623 dvmJitEndTraceSelect(self, self->interpSave.pc);
buzbee9a3147c2011-03-02 15:43:48 -0800624 }
625 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
626 /* Discard any single-step native returns to translation */
627 self->jitResumeNPC = NULL;
628 }
629#endif
630 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
631 void *catchFrame;
buzbee99e3e6e2011-03-29 10:26:07 -0700632 int offset = self->interpSave.pc - curMethod->insns;
633 int catchRelPc = dvmFindCatchBlock(self, offset, exception,
buzbee9a3147c2011-03-02 15:43:48 -0800634 true, &catchFrame);
buzbee30bc0d42011-04-22 10:27:14 -0700635 dvmDbgPostException(self->interpSave.curFrame, offset, catchFrame,
buzbee99e3e6e2011-03-29 10:26:07 -0700636 catchRelPc, exception);
buzbee9a3147c2011-03-02 15:43:48 -0800637 }
638}
639
640/*
641 * The interpreter is preparing to do an invoke (both native & normal).
buzbee99e3e6e2011-03-29 10:26:07 -0700642 * Handle any special subMode requirements. All interpSave state
643 * must be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800644 */
645void dvmReportInvoke(Thread* self, const Method* methodToCall)
646{
647 TRACE_METHOD_ENTER(self, methodToCall);
648}
649
650/*
651 * The interpreter is preparing to do a native invoke. Handle any
652 * special subMode requirements. NOTE: for a native invoke,
653 * dvmReportInvoke() and dvmReportPreNativeInvoke() will both
buzbee30bc0d42011-04-22 10:27:14 -0700654 * be called prior to the invoke. fp is the Dalvik FP of the calling
655 * method.
buzbee9a3147c2011-03-02 15:43:48 -0800656 */
buzbee30bc0d42011-04-22 10:27:14 -0700657void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
buzbee9a3147c2011-03-02 15:43:48 -0800658{
659#if defined(WITH_JIT)
660 /*
661 * Actively building a trace? If so, end it now. The trace
662 * builder can't follow into or through a native method.
663 */
664 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
buzbee99e3e6e2011-03-29 10:26:07 -0700665 dvmCheckJit(self->interpSave.pc, self);
buzbee9a3147c2011-03-02 15:43:48 -0800666 }
667#endif
668 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
buzbee30bc0d42011-04-22 10:27:14 -0700669 Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
Andy McFaddenddab84b2011-03-28 15:23:23 -0700670 assert(thisPtr == NULL || dvmIsValidObject(thisPtr));
buzbee9a3147c2011-03-02 15:43:48 -0800671 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY);
672 }
673}
674
675/*
676 * The interpreter has returned from a native invoke. Handle any
buzbee30bc0d42011-04-22 10:27:14 -0700677 * special subMode requirements. fp is the Dalvik FP of the calling
678 * method.
buzbee9a3147c2011-03-02 15:43:48 -0800679 */
buzbee30bc0d42011-04-22 10:27:14 -0700680void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
buzbee9a3147c2011-03-02 15:43:48 -0800681{
682 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
buzbee30bc0d42011-04-22 10:27:14 -0700683 Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
Andy McFaddenddab84b2011-03-28 15:23:23 -0700684 assert(thisPtr == NULL || dvmIsValidObject(thisPtr));
buzbee9a3147c2011-03-02 15:43:48 -0800685 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT);
686 }
687 if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) {
688 dvmFastNativeMethodTraceExit(methodToCall, self);
689 }
690}
691
692/*
693 * The interpreter has returned from a normal method. Handle any special
buzbee99e3e6e2011-03-29 10:26:07 -0700694 * subMode requirements. All interpSave state must be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800695 */
buzbee99e3e6e2011-03-29 10:26:07 -0700696void dvmReportReturn(Thread* self)
buzbee9a3147c2011-03-02 15:43:48 -0800697{
698 TRACE_METHOD_EXIT(self, self->interpSave.method);
699#if defined(WITH_JIT)
buzbee30bc0d42011-04-22 10:27:14 -0700700 if (dvmIsBreakFrame(self->interpSave.curFrame) &&
buzbee9a3147c2011-03-02 15:43:48 -0800701 (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) {
buzbee99e3e6e2011-03-29 10:26:07 -0700702 dvmCheckJit(self->interpSave.pc, self);
buzbee9a3147c2011-03-02 15:43:48 -0800703 }
704#endif
705}
706
707/*
708 * Update the debugger on interesting events, such as hitting a breakpoint
709 * or a single-step point. This is called from the top of the interpreter
710 * loop, before the current instruction is processed.
711 *
712 * Set "methodEntry" if we've just entered the method. This detects
713 * method exit by checking to see if the next instruction is "return".
714 *
715 * This can't catch native method entry/exit, so we have to handle that
716 * at the point of invocation. We also need to catch it in dvmCallMethod
717 * if we want to capture native->native calls made through JNI.
718 *
719 * Notes to self:
720 * - Don't want to switch to VMWAIT while posting events to the debugger.
721 * Let the debugger code decide if we need to change state.
722 * - We may want to check for debugger-induced thread suspensions on
723 * every instruction. That would make a "suspend all" more responsive
724 * and reduce the chances of multiple simultaneous events occurring.
725 * However, it could change the behavior some.
726 *
727 * TODO: method entry/exit events are probably less common than location
728 * breakpoints. We may be able to speed things up a bit if we don't query
729 * the event list unless we know there's at least one lurking within.
730 */
buzbee99e3e6e2011-03-29 10:26:07 -0700731static void updateDebugger(const Method* method, const u2* pc, const u4* fp,
buzbeee7147462011-04-13 14:10:04 -0700732 Thread* self)
buzbee9a3147c2011-03-02 15:43:48 -0800733{
734 int eventFlags = 0;
735
736 /*
737 * Update xtra.currentPc on every instruction. We need to do this if
738 * there's a chance that we could get suspended. This can happen if
739 * eventFlags != 0 here, or somebody manually requests a suspend
740 * (which gets handled at PERIOD_CHECKS time). One place where this
741 * needs to be correct is in dvmAddSingleStep().
742 */
743 dvmExportPC(pc, fp);
744
buzbeee7147462011-04-13 14:10:04 -0700745 if (self->debugIsMethodEntry) {
buzbee9a3147c2011-03-02 15:43:48 -0800746 eventFlags |= DBG_METHOD_ENTRY;
buzbeee7147462011-04-13 14:10:04 -0700747 self->debugIsMethodEntry = false;
748 }
buzbee9a3147c2011-03-02 15:43:48 -0800749
750 /*
751 * See if we have a breakpoint here.
752 *
753 * Depending on the "mods" associated with event(s) on this address,
754 * we may or may not actually send a message to the debugger.
755 */
756 if (GET_OPCODE(*pc) == OP_BREAKPOINT) {
757 LOGV("+++ breakpoint hit at %p\n", pc);
758 eventFlags |= DBG_BREAKPOINT;
759 }
760
761 /*
762 * If the debugger is single-stepping one of our threads, check to
763 * see if we're that thread and we've reached a step point.
764 */
765 const StepControl* pCtrl = &gDvm.stepControl;
766 if (pCtrl->active && pCtrl->thread == self) {
767 int frameDepth;
768 bool doStop = false;
769 const char* msg = NULL;
770
771 assert(!dvmIsNativeMethod(method));
772
773 if (pCtrl->depth == SD_INTO) {
774 /*
775 * Step into method calls. We break when the line number
776 * or method pointer changes. If we're in SS_MIN mode, we
777 * always stop.
778 */
779 if (pCtrl->method != method) {
780 doStop = true;
781 msg = "new method";
782 } else if (pCtrl->size == SS_MIN) {
783 doStop = true;
784 msg = "new instruction";
785 } else if (!dvmAddressSetGet(
786 pCtrl->pAddressSet, pc - method->insns)) {
787 doStop = true;
788 msg = "new line";
789 }
790 } else if (pCtrl->depth == SD_OVER) {
791 /*
792 * Step over method calls. We break when the line number is
793 * different and the frame depth is <= the original frame
794 * depth. (We can't just compare on the method, because we
795 * might get unrolled past it by an exception, and it's tricky
796 * to identify recursion.)
797 */
798 frameDepth = dvmComputeVagueFrameDepth(self, fp);
799 if (frameDepth < pCtrl->frameDepth) {
800 /* popped up one or more frames, always trigger */
801 doStop = true;
802 msg = "method pop";
803 } else if (frameDepth == pCtrl->frameDepth) {
804 /* same depth, see if we moved */
805 if (pCtrl->size == SS_MIN) {
806 doStop = true;
807 msg = "new instruction";
808 } else if (!dvmAddressSetGet(pCtrl->pAddressSet,
809 pc - method->insns)) {
810 doStop = true;
811 msg = "new line";
812 }
813 }
814 } else {
815 assert(pCtrl->depth == SD_OUT);
816 /*
817 * Return from the current method. We break when the frame
818 * depth pops up.
819 *
820 * This differs from the "method exit" break in that it stops
821 * with the PC at the next instruction in the returned-to
822 * function, rather than the end of the returning function.
823 */
824 frameDepth = dvmComputeVagueFrameDepth(self, fp);
825 if (frameDepth < pCtrl->frameDepth) {
826 doStop = true;
827 msg = "method pop";
828 }
829 }
830
831 if (doStop) {
832 LOGV("#####S %s\n", msg);
833 eventFlags |= DBG_SINGLE_STEP;
834 }
835 }
836
837 /*
838 * Check to see if this is a "return" instruction. JDWP says we should
839 * send the event *after* the code has been executed, but it also says
840 * the location we provide is the last instruction. Since the "return"
841 * instruction has no interesting side effects, we should be safe.
842 * (We can't just move this down to the returnFromMethod label because
843 * we potentially need to combine it with other events.)
844 *
845 * We're also not supposed to generate a method exit event if the method
846 * terminates "with a thrown exception".
847 */
848 u2 opcode = GET_OPCODE(*pc);
849 if (opcode == OP_RETURN_VOID || opcode == OP_RETURN ||
850 opcode == OP_RETURN_WIDE ||opcode == OP_RETURN_OBJECT)
851 {
852 eventFlags |= DBG_METHOD_EXIT;
853 }
854
855 /*
856 * If there's something interesting going on, see if it matches one
857 * of the debugger filters.
858 */
859 if (eventFlags != 0) {
860 Object* thisPtr = dvmGetThisPtr(method, fp);
861 if (thisPtr != NULL && !dvmIsValidObject(thisPtr)) {
862 /*
863 * TODO: remove this check if we're confident that the "this"
864 * pointer is where it should be -- slows us down, especially
865 * during single-step.
866 */
867 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
868 LOGE("HEY: invalid 'this' ptr %p (%s.%s %s)\n", thisPtr,
869 method->clazz->descriptor, method->name, desc);
870 free(desc);
871 dvmAbort();
872 }
873 dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr,
874 eventFlags);
875 }
876}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700877
878/*
879 * Recover the "this" pointer from the current interpreted method. "this"
880 * is always in "in0" for non-static methods.
881 *
882 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
883 *
884 * This works because "dx" guarantees that it will work. It's probably
885 * fairly common to have a virtual method that doesn't use its "this"
886 * pointer, in which case we're potentially wasting a register. However,
887 * the debugger doesn't treat "this" as just another argument. For
888 * example, events (such as breakpoints) can be enabled for specific
889 * values of "this". There is also a separate StackFrame.ThisObject call
890 * in JDWP that is expected to work for any non-native non-static method.
891 *
892 * Because we need it when setting up debugger event filters, we want to
893 * be able to do this quickly.
894 */
895Object* dvmGetThisPtr(const Method* method, const u4* fp)
896{
897 if (dvmIsStaticMethod(method))
898 return NULL;
899 return (Object*)fp[method->registersSize - method->insSize];
900}
901
902
903#if defined(WITH_TRACKREF_CHECKS)
904/*
905 * Verify that all internally-tracked references have been released. If
906 * they haven't, print them and abort the VM.
907 *
908 * "debugTrackedRefStart" indicates how many refs were on the list when
909 * we were first invoked.
910 */
911void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
912 int debugTrackedRefStart)
913{
914 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
915 != (size_t) debugTrackedRefStart)
916 {
917 char* desc;
918 Object** top;
919 int count;
920
921 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
922
923 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
924 debugTrackedRefStart, count);
925 desc = dexProtoCopyMethodDescriptor(&method->prototype);
926 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
927 method->name, desc);
928 free(desc);
929 top = self->internalLocalRefTable.table + debugTrackedRefStart;
930 while (top < self->internalLocalRefTable.nextEntry) {
931 LOGE(" %p (%s)\n",
932 *top,
933 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
934 top++;
935 }
936 dvmDumpThread(self, false);
937
938 dvmAbort();
939 }
940 //LOGI("TRACK OK\n");
941}
942#endif
943
944
945#ifdef LOG_INSTR
946/*
947 * Dump the v-registers. Sent to the ILOG log tag.
948 */
949void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
950{
951 int i, localCount;
952
953 localCount = method->registersSize - method->insSize;
954
955 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
956 for (i = method->registersSize-1; i >= 0; i--) {
957 if (i >= localCount) {
958 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
959 i, i-localCount, framePtr[i]);
960 } else {
961 if (inOnly) {
962 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
963 break;
964 }
965 const char* name = "";
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700966#if 0 // "locals" structure has changed -- need to rewrite this
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700967 int j;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700968 DexFile* pDexFile = method->clazz->pDexFile;
969 const DexCode* pDexCode = dvmGetMethodCode(method);
970 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
971 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
972 for (j = 0; j < localsSize, j++) {
973 if (locals[j].registerNum == (u4) i) {
974 name = dvmDexStringStr(locals[j].pName);
975 break;
976 }
977 }
978#endif
979 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
980 i, framePtr[i], name);
981 }
982 }
983}
984#endif
985
986
987/*
988 * ===========================================================================
989 * Entry point and general support functions
990 * ===========================================================================
991 */
992
Ben Cheng38329f52009-07-07 14:19:20 -0700993/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700994 * Construct an s4 from two consecutive half-words of switch data.
995 * This needs to check endianness because the DEX optimizer only swaps
996 * half-words in instruction stream.
997 *
998 * "switchData" must be 32-bit aligned.
999 */
1000#if __BYTE_ORDER == __LITTLE_ENDIAN
1001static inline s4 s4FromSwitchData(const void* switchData) {
1002 return *(s4*) switchData;
1003}
1004#else
1005static inline s4 s4FromSwitchData(const void* switchData) {
1006 u2* data = switchData;
1007 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +00001008}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001009#endif
1010
1011/*
1012 * Find the matching case. Returns the offset to the handler instructions.
1013 *
1014 * Returns 3 if we don't find a match (it's the size of the packed-switch
1015 * instruction).
1016 */
1017s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
1018{
1019 const int kInstrLen = 3;
1020 u2 size;
1021 s4 firstKey;
1022 const s4* entries;
1023
1024 /*
1025 * Packed switch data format:
1026 * ushort ident = 0x0100 magic value
1027 * ushort size number of entries in the table
1028 * int first_key first (and lowest) switch case value
1029 * int targets[size] branch targets, relative to switch opcode
1030 *
1031 * Total size is (4+size*2) 16-bit code units.
1032 */
1033 if (*switchData++ != kPackedSwitchSignature) {
1034 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001035 dvmThrowInternalError("bad packed switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001036 return kInstrLen;
1037 }
1038
1039 size = *switchData++;
1040 assert(size > 0);
1041
1042 firstKey = *switchData++;
1043 firstKey |= (*switchData++) << 16;
1044
1045 if (testVal < firstKey || testVal >= firstKey + size) {
1046 LOGVV("Value %d not found in switch (%d-%d)\n",
1047 testVal, firstKey, firstKey+size-1);
1048 return kInstrLen;
1049 }
1050
1051 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1052 * we can treat them as a native int array.
1053 */
1054 entries = (const s4*) switchData;
1055 assert(((u4)entries & 0x3) == 0);
1056
1057 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
1058 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
1059 testVal, testVal - firstKey,
1060 s4FromSwitchData(&entries[testVal - firstKey]));
1061 return s4FromSwitchData(&entries[testVal - firstKey]);
1062}
1063
1064/*
1065 * Find the matching case. Returns the offset to the handler instructions.
1066 *
1067 * Returns 3 if we don't find a match (it's the size of the sparse-switch
1068 * instruction).
1069 */
1070s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
1071{
1072 const int kInstrLen = 3;
Carl Shapiroe3c01da2010-05-20 22:54:18 -07001073 u2 size;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001074 const s4* keys;
1075 const s4* entries;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001076
1077 /*
1078 * Sparse switch data format:
1079 * ushort ident = 0x0200 magic value
1080 * ushort size number of entries in the table; > 0
1081 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1082 * int targets[size] branch targets, relative to switch opcode
1083 *
1084 * Total size is (2+size*4) 16-bit code units.
1085 */
1086
1087 if (*switchData++ != kSparseSwitchSignature) {
1088 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001089 dvmThrowInternalError("bad sparse switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001090 return kInstrLen;
1091 }
1092
1093 size = *switchData++;
1094 assert(size > 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001095
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001096 /* The keys are guaranteed to be aligned on a 32-bit boundary;
1097 * we can treat them as a native int array.
1098 */
1099 keys = (const s4*) switchData;
1100 assert(((u4)keys & 0x3) == 0);
1101
1102 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1103 * we can treat them as a native int array.
1104 */
1105 entries = keys + size;
1106 assert(((u4)entries & 0x3) == 0);
1107
1108 /*
Andy McFadden62f19152009-10-21 16:59:31 -07001109 * Binary-search through the array of keys, which are guaranteed to
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001110 * be sorted low-to-high.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001111 */
Andy McFadden62f19152009-10-21 16:59:31 -07001112 int lo = 0;
1113 int hi = size - 1;
1114 while (lo <= hi) {
1115 int mid = (lo + hi) >> 1;
1116
1117 s4 foundVal = s4FromSwitchData(&keys[mid]);
1118 if (testVal < foundVal) {
1119 hi = mid - 1;
1120 } else if (testVal > foundVal) {
1121 lo = mid + 1;
1122 } else {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001123 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
Andy McFadden62f19152009-10-21 16:59:31 -07001124 testVal, mid, s4FromSwitchData(&entries[mid]));
1125 return s4FromSwitchData(&entries[mid]);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001126 }
1127 }
1128
1129 LOGVV("Value %d not found in switch\n", testVal);
1130 return kInstrLen;
1131}
1132
1133/*
Andy McFadden6f214502009-06-30 16:14:30 -07001134 * Copy data for a fill-array-data instruction. On a little-endian machine
1135 * we can just do a memcpy(), on a big-endian system we have work to do.
1136 *
1137 * The trick here is that dexopt has byte-swapped each code unit, which is
1138 * exactly what we want for short/char data. For byte data we need to undo
1139 * the swap, and for 4- or 8-byte values we need to swap pieces within
1140 * each word.
1141 */
1142static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
1143{
1144#if __BYTE_ORDER == __LITTLE_ENDIAN
1145 memcpy(dest, src, size*width);
1146#else
1147 int i;
1148
1149 switch (width) {
1150 case 1:
1151 /* un-swap pairs of bytes as we go */
1152 for (i = (size-1) & ~1; i >= 0; i -= 2) {
1153 ((u1*)dest)[i] = ((u1*)src)[i+1];
1154 ((u1*)dest)[i+1] = ((u1*)src)[i];
1155 }
1156 /*
1157 * "src" is padded to end on a two-byte boundary, but we don't want to
1158 * assume "dest" is, so we handle odd length specially.
1159 */
1160 if ((size & 1) != 0) {
1161 ((u1*)dest)[size-1] = ((u1*)src)[size];
1162 }
1163 break;
1164 case 2:
1165 /* already swapped correctly */
1166 memcpy(dest, src, size*width);
1167 break;
1168 case 4:
1169 /* swap word halves */
1170 for (i = 0; i < (int) size; i++) {
1171 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
1172 }
1173 break;
1174 case 8:
1175 /* swap word halves and words */
1176 for (i = 0; i < (int) (size << 1); i += 2) {
1177 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
1178 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
1179 }
1180 break;
1181 default:
1182 LOGE("Unexpected width %d in copySwappedArrayData\n", width);
1183 dvmAbort();
1184 break;
1185 }
1186#endif
1187}
1188
1189/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001190 * Fill the array with predefined constant values.
1191 *
1192 * Returns true if job is completed, otherwise false to indicate that
1193 * an exception has been thrown.
1194 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001195bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001196{
1197 u2 width;
1198 u4 size;
1199
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001200 if (arrayObj == NULL) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001201 dvmThrowNullPointerException(NULL);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001202 return false;
1203 }
Barry Hayes7dc96602010-02-24 09:19:07 -08001204 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
1205 CLASS_ISOBJECTARRAY));
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001206
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001207 /*
1208 * Array data table format:
1209 * ushort ident = 0x0300 magic value
1210 * ushort width width of each element in the table
1211 * uint size number of elements in the table
1212 * ubyte data[size*width] table of data values (may contain a single-byte
1213 * padding at the end)
1214 *
1215 * Total size is 4+(width * size + 1)/2 16-bit code units.
1216 */
1217 if (arrayData[0] != kArrayDataSignature) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001218 dvmThrowInternalError("bad array data magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001219 return false;
1220 }
1221
1222 width = arrayData[1];
1223 size = arrayData[2] | (((u4)arrayData[3]) << 16);
1224
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001225 if (size > arrayObj->length) {
Dan Bornstein47f58252011-03-07 14:54:14 -08001226 dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001227 return false;
1228 }
Andy McFadden6f214502009-06-30 16:14:30 -07001229 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001230 return true;
1231}
1232
1233/*
1234 * Find the concrete method that corresponds to "methodIdx". The code in
1235 * "method" is executing invoke-method with "thisClass" as its first argument.
1236 *
1237 * Returns NULL with an exception raised on failure.
1238 */
1239Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
1240 const Method* method, DvmDex* methodClassDex)
1241{
1242 Method* absMethod;
1243 Method* methodToCall;
1244 int i, vtableIndex;
1245
1246 /*
1247 * Resolve the method. This gives us the abstract method from the
1248 * interface class declaration.
1249 */
1250 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
1251 if (absMethod == NULL) {
1252 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
1253 if (absMethod == NULL) {
1254 LOGV("+ unknown method\n");
1255 return NULL;
1256 }
1257 }
1258
1259 /* make sure absMethod->methodIndex means what we think it means */
1260 assert(dvmIsAbstractMethod(absMethod));
1261
1262 /*
1263 * Run through the "this" object's iftable. Find the entry for
1264 * absMethod's class, then use absMethod->methodIndex to find
1265 * the method's entry. The value there is the offset into our
1266 * vtable of the actual method to execute.
1267 *
1268 * The verifier does not guarantee that objects stored into
1269 * interface references actually implement the interface, so this
1270 * check cannot be eliminated.
1271 */
1272 for (i = 0; i < thisClass->iftableCount; i++) {
1273 if (thisClass->iftable[i].clazz == absMethod->clazz)
1274 break;
1275 }
1276 if (i == thisClass->iftableCount) {
1277 /* impossible in verified DEX, need to check for it in unverified */
Dan Bornstein70b00ab2011-02-23 14:11:27 -08001278 dvmThrowIncompatibleClassChangeError("interface not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001279 return NULL;
1280 }
1281
1282 assert(absMethod->methodIndex <
1283 thisClass->iftable[i].clazz->virtualMethodCount);
1284
1285 vtableIndex =
1286 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1287 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1288 methodToCall = thisClass->vtable[vtableIndex];
1289
1290#if 0
1291 /* this can happen when there's a stale class file */
1292 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001293 dvmThrowAbstractMethodError("interface method not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001294 return NULL;
1295 }
1296#else
1297 assert(!dvmIsAbstractMethod(methodToCall) ||
1298 methodToCall->nativeFunc != NULL);
1299#endif
1300
1301 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1302 absMethod->clazz->descriptor, absMethod->name,
1303 methodToCall->clazz->descriptor, methodToCall->name);
1304 assert(methodToCall != NULL);
1305
1306 return methodToCall;
1307}
1308
1309
Andy McFaddenb51ea112009-05-08 16:50:17 -07001310
1311/*
1312 * Helpers for dvmThrowVerificationError().
1313 *
1314 * Each returns a newly-allocated string.
1315 */
1316#define kThrowShow_accessFromClass 1
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001317static char* classNameFromIndex(const Method* method, int ref,
1318 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001319{
1320 static const int kBufLen = 256;
1321 const DvmDex* pDvmDex = method->clazz->pDvmDex;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001322
1323 if (refType == VERIFY_ERROR_REF_FIELD) {
1324 /* get class ID from field ID */
1325 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1326 ref = pFieldId->classIdx;
1327 } else if (refType == VERIFY_ERROR_REF_METHOD) {
1328 /* get class ID from method ID */
1329 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1330 ref = pMethodId->classIdx;
1331 }
1332
Andy McFaddenb51ea112009-05-08 16:50:17 -07001333 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
Elliott Hughes50169662010-11-22 13:14:23 -08001334 char* dotClassName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001335 if (flags == 0)
1336 return dotClassName;
1337
1338 char* result = (char*) malloc(kBufLen);
1339
1340 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001341 char* dotFromName =
1342 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001343 snprintf(result, kBufLen, "tried to access class %s from class %s",
1344 dotClassName, dotFromName);
1345 free(dotFromName);
1346 } else {
1347 assert(false); // should've been caught above
1348 result[0] = '\0';
1349 }
1350
1351 free(dotClassName);
1352 return result;
1353}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001354static char* fieldNameFromIndex(const Method* method, int ref,
1355 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001356{
1357 static const int kBufLen = 256;
1358 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1359 const DexFieldId* pFieldId;
1360 const char* className;
1361 const char* fieldName;
1362
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001363 if (refType != VERIFY_ERROR_REF_FIELD) {
1364 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1365 return NULL; /* no message */
1366 }
1367
Andy McFaddenb51ea112009-05-08 16:50:17 -07001368 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1369 className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1370 fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1371
Elliott Hughes50169662010-11-22 13:14:23 -08001372 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001373 char* result = (char*) malloc(kBufLen);
1374
1375 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001376 char* dotFromName =
1377 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001378 snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1379 dotName, fieldName, dotFromName);
1380 free(dotFromName);
1381 } else {
1382 snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1383 }
1384
1385 free(dotName);
1386 return result;
1387}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001388static char* methodNameFromIndex(const Method* method, int ref,
1389 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001390{
1391 static const int kBufLen = 384;
1392 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1393 const DexMethodId* pMethodId;
1394 const char* className;
1395 const char* methodName;
1396
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001397 if (refType != VERIFY_ERROR_REF_METHOD) {
1398 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1399 return NULL; /* no message */
1400 }
1401
Andy McFaddenb51ea112009-05-08 16:50:17 -07001402 pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1403 className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1404 methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1405
Elliott Hughes50169662010-11-22 13:14:23 -08001406 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001407 char* result = (char*) malloc(kBufLen);
1408
1409 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001410 char* dotFromName =
1411 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001412 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1413 snprintf(result, kBufLen,
1414 "tried to access method %s.%s:%s from class %s",
1415 dotName, methodName, desc, dotFromName);
1416 free(dotFromName);
1417 free(desc);
1418 } else {
1419 snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1420 }
1421
1422 free(dotName);
1423 return result;
1424}
1425
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001426/*
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001427 * Throw an exception for a problem identified by the verifier.
1428 *
1429 * This is used by the invoke-verification-error instruction. It always
1430 * throws an exception.
1431 *
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001432 * "kind" indicates the kind of failure encountered by the verifier. It
1433 * has two parts, an error code and an indication of the reference type.
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001434 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001435void dvmThrowVerificationError(const Method* method, int kind, int ref)
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001436{
Carl Shapiro1813ab22011-04-15 15:48:54 -07001437 int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift);
1438 int errorRefPart = kind >> kVerifyErrorRefTypeShift;
1439 VerifyError errorKind = static_cast<VerifyError>(errorPart);
1440 VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart);
Dan Bornsteina3b35122011-03-03 16:17:37 -08001441 ClassObject* exceptionClass = gDvm.exVerifyError;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001442 char* msg = NULL;
1443
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001444 switch ((VerifyError) errorKind) {
Andy McFaddenb51ea112009-05-08 16:50:17 -07001445 case VERIFY_ERROR_NO_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001446 exceptionClass = gDvm.exNoClassDefFoundError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001447 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001448 break;
1449 case VERIFY_ERROR_NO_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001450 exceptionClass = gDvm.exNoSuchFieldError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001451 msg = fieldNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001452 break;
1453 case VERIFY_ERROR_NO_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001454 exceptionClass = gDvm.exNoSuchMethodError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001455 msg = methodNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001456 break;
1457 case VERIFY_ERROR_ACCESS_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001458 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001459 msg = classNameFromIndex(method, ref, refType,
1460 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001461 break;
1462 case VERIFY_ERROR_ACCESS_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001463 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001464 msg = fieldNameFromIndex(method, ref, refType,
1465 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001466 break;
1467 case VERIFY_ERROR_ACCESS_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001468 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001469 msg = methodNameFromIndex(method, ref, refType,
1470 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001471 break;
1472 case VERIFY_ERROR_CLASS_CHANGE:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001473 exceptionClass = gDvm.exIncompatibleClassChangeError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001474 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001475 break;
1476 case VERIFY_ERROR_INSTANTIATION:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001477 exceptionClass = gDvm.exInstantiationError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001478 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001479 break;
1480
1481 case VERIFY_ERROR_GENERIC:
1482 /* generic VerifyError; use default exception, no message */
1483 break;
1484 case VERIFY_ERROR_NONE:
1485 /* should never happen; use default exception */
1486 assert(false);
1487 msg = strdup("weird - no error specified");
1488 break;
1489
1490 /* no default clause -- want warning if enum updated */
1491 }
1492
Dan Bornstein0b8b2932011-03-04 11:53:40 -08001493 dvmThrowException(exceptionClass, msg);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001494 free(msg);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001495}
1496
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001497/*
buzbeecf2aac72011-04-25 11:23:46 -07001498 * Update interpBreak for a single thread.
buzbeecb3081f2011-01-14 13:37:31 -08001499 */
buzbeecf2aac72011-04-25 11:23:46 -07001500void updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable)
buzbeecb3081f2011-01-14 13:37:31 -08001501{
buzbee9a3147c2011-03-02 15:43:48 -08001502 InterpBreak oldValue, newValue;
buzbeecb3081f2011-01-14 13:37:31 -08001503 do {
buzbee9a3147c2011-03-02 15:43:48 -08001504 oldValue = newValue = thread->interpBreak;
buzbeecf2aac72011-04-25 11:23:46 -07001505 newValue.ctl.breakFlags = kInterpNoBreak; // Assume full reset
1506 if (enable)
1507 newValue.ctl.subMode |= subMode;
1508 else
1509 newValue.ctl.subMode &= ~subMode;
1510 if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK)
1511 newValue.ctl.breakFlags |= kInterpSingleStep;
1512 if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK)
1513 newValue.ctl.breakFlags |= kInterpSafePoint;
buzbee9a3147c2011-03-02 15:43:48 -08001514 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1515 thread->altHandlerTable : thread->mainHandlerTable;
1516 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1517 &thread->interpBreak.all) != 0);
1518}
1519
1520/*
buzbeecf2aac72011-04-25 11:23:46 -07001521 * Update interpBreak for all threads.
1522 */
1523void updateAllInterpBreak(ExecutionSubModes subMode, bool enable)
1524{
1525 Thread* self = dvmThreadSelf();
1526 Thread* thread;
1527
1528 dvmLockThreadList(self);
1529 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1530 updateInterpBreak(thread, subMode, enable);
1531 }
1532 dvmUnlockThreadList();
1533}
1534
1535/*
buzbee9a3147c2011-03-02 15:43:48 -08001536 * Update the normal and debugger suspend counts for a thread.
1537 * threadSuspendCount must be acquired before calling this to
1538 * ensure a clean update of suspendCount, dbgSuspendCount and
buzbee389e2582011-04-22 15:12:40 -07001539 * sumThreadSuspendCount.
buzbee9a3147c2011-03-02 15:43:48 -08001540 *
1541 * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
1542 * Move under WITH_JIT ifdefs.
1543*/
1544void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
1545{
buzbee389e2582011-04-22 15:12:40 -07001546 thread->suspendCount += delta;
1547 thread->dbgSuspendCount += dbgDelta;
buzbeecf2aac72011-04-25 11:23:46 -07001548 updateInterpBreak(thread, kSubModeSuspendPending,
1549 (thread->suspendCount != 0));
buzbee9a3147c2011-03-02 15:43:48 -08001550 // Update the global suspend count total
1551 gDvm.sumThreadSuspendCount += delta;
1552}
1553
buzbee9a3147c2011-03-02 15:43:48 -08001554
buzbeecf2aac72011-04-25 11:23:46 -07001555void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode)
1556{
1557 updateInterpBreak(thread, subMode, false);
1558}
1559
1560void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode)
1561{
1562 updateInterpBreak(thread, subMode, true);
1563}
1564
1565void dvmEnableAllSubMode(ExecutionSubModes subMode)
1566{
1567 updateAllInterpBreak(subMode, true);
1568}
1569
1570void dvmDisableAllSubMode(ExecutionSubModes subMode)
1571{
1572 updateAllInterpBreak(subMode, false);
buzbeecb3081f2011-01-14 13:37:31 -08001573}
1574
1575/*
buzbee99e3e6e2011-03-29 10:26:07 -07001576 * Do a sanity check on interpreter state saved to Thread.
1577 * A failure here doesn't necessarily mean that something is wrong,
1578 * so this code should only be used during development to suggest
1579 * a possible problem.
1580 */
1581void dvmCheckInterpStateConsistency()
1582{
1583 Thread* self = dvmThreadSelf();
1584 Thread* thread;
1585 uint8_t breakFlags;
1586 uint8_t subMode;
1587 void* handlerTable;
1588
1589 dvmLockThreadList(self);
1590 breakFlags = self->interpBreak.ctl.breakFlags;
1591 subMode = self->interpBreak.ctl.subMode;
1592 handlerTable = self->interpBreak.ctl.curHandlerTable;
1593 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1594 if (subMode != thread->interpBreak.ctl.subMode) {
1595 LOGD("Warning: subMode mismatch - 0x%x:0x%x, tid[%d]",
1596 subMode,thread->interpBreak.ctl.subMode,thread->threadId);
1597 }
1598 if (breakFlags != thread->interpBreak.ctl.breakFlags) {
1599 LOGD("Warning: breakFlags mismatch - 0x%x:0x%x, tid[%d]",
1600 breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId);
1601 }
1602 if (handlerTable != thread->interpBreak.ctl.curHandlerTable) {
1603 LOGD("Warning: curHandlerTable mismatch - 0x%x:0x%x, tid[%d]",
1604 (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable,
1605 thread->threadId);
1606 }
1607#if defined(WITH_JIT)
1608 if (thread->pJitProfTable != gDvmJit.pProfTable) {
1609 LOGD("Warning: pJitProfTable mismatch - 0x%x:0x%x, tid[%d]",
1610 (int)thread->pJitProfTable,(int)gDvmJit.pProfTable,
1611 thread->threadId);
1612 }
1613 if (thread->jitThreshold != gDvmJit.threshold) {
1614 LOGD("Warning: jitThreshold mismatch - 0x%x:0x%x, tid[%d]",
1615 (int)thread->jitThreshold,(int)gDvmJit.threshold,
1616 thread->threadId);
1617 }
1618#endif
1619 }
1620 dvmUnlockThreadList();
1621}
1622
1623/*
buzbee94d65252011-03-24 16:41:03 -07001624 * Arm a safepoint callback for a thread. If funct is null,
1625 * clear any pending callback.
1626 * TODO: only gc is currently using this feature, and will have
1627 * at most a single outstanding callback request. Until we need
1628 * something more capable and flexible, enforce this limit.
1629 */
1630void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct,
1631 void* arg)
1632{
1633 dvmLockMutex(&thread->callbackMutex);
1634 if ((funct == NULL) || (thread->callback == NULL)) {
1635 thread->callback = funct;
1636 thread->callbackArg = arg;
buzbeecf2aac72011-04-25 11:23:46 -07001637 if (funct != NULL) {
1638 dvmEnableSubMode(thread, kSubModeCallbackPending);
1639 } else {
1640 dvmDisableSubMode(thread, kSubModeCallbackPending);
1641 }
buzbee94d65252011-03-24 16:41:03 -07001642 } else {
1643 // Already armed. Different?
1644 if ((funct != thread->callback) ||
1645 (arg != thread->callbackArg)) {
1646 // Yes - report failure and die
1647 LOGE("ArmSafePointCallback failed, thread %d", thread->threadId);
1648 dvmUnlockMutex(&thread->callbackMutex);
1649 dvmAbort();
1650 }
1651 }
1652 dvmUnlockMutex(&thread->callbackMutex);
1653}
1654
1655/*
buzbee9f601a92011-02-11 17:48:20 -08001656 * One-time initialization at thread creation. Here we initialize
1657 * useful constants.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001658 */
buzbee9f601a92011-02-11 17:48:20 -08001659void dvmInitInterpreterState(Thread* self)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001660{
Ben Chengba4fc8b2009-06-01 13:00:29 -07001661#if defined(WITH_JIT)
Ben Cheng38329f52009-07-07 14:19:20 -07001662 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001663 * Reserve a static entity here to quickly setup runtime contents as
1664 * gcc will issue block copy instructions.
1665 */
1666 static struct JitToInterpEntries jitToInterpEntries = {
1667 dvmJitToInterpNormal,
1668 dvmJitToInterpNoChain,
1669 dvmJitToInterpPunt,
1670 dvmJitToInterpSingleStep,
Ben Cheng40094c12010-02-24 20:58:44 -08001671 dvmJitToInterpTraceSelect,
Jeff Hao97319a82009-08-12 16:57:15 -07001672#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001673 dvmJitToInterpBackwardBranch,
buzbee9f601a92011-02-11 17:48:20 -08001674#else
1675 NULL,
Jeff Hao97319a82009-08-12 16:57:15 -07001676#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001677 };
buzbee9f601a92011-02-11 17:48:20 -08001678#endif
Ben Cheng7a0bcd02010-01-22 16:45:45 -08001679
buzbee9f601a92011-02-11 17:48:20 -08001680 // Begin initialization
1681 self->cardTable = gDvm.biasedCardTableBase;
buzbee9f601a92011-02-11 17:48:20 -08001682#if defined(WITH_JIT)
buzbee9a3147c2011-03-02 15:43:48 -08001683 // One-time initializations
buzbee9f601a92011-02-11 17:48:20 -08001684 self->jitToInterpEntries = jitToInterpEntries;
1685 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
buzbee9f601a92011-02-11 17:48:20 -08001686 self->pProfileCountdown = &gDvmJit.profileCountdown;
buzbee9a3147c2011-03-02 15:43:48 -08001687 // Jit state that can change
buzbee99e3e6e2011-03-29 10:26:07 -07001688 dvmJitUpdateThreadStateSingle(self);
buzbee9f601a92011-02-11 17:48:20 -08001689#endif
buzbee2ec9f782011-05-02 16:06:04 -07001690 dvmInitializeInterpBreak(self);
buzbee99e3e6e2011-03-29 10:26:07 -07001691}
buzbee9f601a92011-02-11 17:48:20 -08001692
buzbee99e3e6e2011-03-29 10:26:07 -07001693/*
1694 * For a newly-created thread, we need to start off with interpBreak
1695 * set to any existing global modes. The caller must hold the
1696 * thread list lock.
1697 */
1698void dvmInitializeInterpBreak(Thread* thread)
1699{
buzbee99e3e6e2011-03-29 10:26:07 -07001700 if (gDvm.instructionCountEnableCount > 0) {
buzbeecf2aac72011-04-25 11:23:46 -07001701 dvmEnableSubMode(thread, kSubModeInstCounting);
buzbee99e3e6e2011-03-29 10:26:07 -07001702 }
1703 if (dvmIsMethodTraceActive()) {
buzbeecf2aac72011-04-25 11:23:46 -07001704 dvmEnableSubMode(thread, kSubModeMethodTrace);
1705 }
1706 if (gDvm.emulatorTraceEnableCount > 0) {
1707 dvmEnableSubMode(thread, kSubModeEmulatorTrace);
buzbee99e3e6e2011-03-29 10:26:07 -07001708 }
1709 if (gDvm.debuggerActive) {
buzbeecf2aac72011-04-25 11:23:46 -07001710 dvmEnableSubMode(thread, kSubModeDebuggerActive);
buzbee99e3e6e2011-03-29 10:26:07 -07001711 }
buzbee2ec9f782011-05-02 16:06:04 -07001712#if 0
1713 // Debugging stress mode - force checkBefore
1714 dvmEnableSubMode(thread, kSubModeCheckAlways);
1715#endif
buzbee9f601a92011-02-11 17:48:20 -08001716}
1717
buzbeea7d59bb2011-02-24 09:38:17 -08001718/*
1719 * Inter-instruction handler invoked in between instruction interpretations
1720 * to handle exceptional events such as debugging housekeeping, instruction
buzbee9a3147c2011-03-02 15:43:48 -08001721 * count profiling, JIT trace building, etc. Dalvik PC has been exported
1722 * prior to call, but Thread copy of dPC & fp are not current.
buzbeea7d59bb2011-02-24 09:38:17 -08001723 */
buzbee94d65252011-03-24 16:41:03 -07001724void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self)
buzbeea7d59bb2011-02-24 09:38:17 -08001725{
buzbee9a3147c2011-03-02 15:43:48 -08001726 const Method* method = self->interpSave.method;
1727 assert(self->interpBreak.ctl.breakFlags != 0);
1728 assert(pc >= method->insns && pc <
1729 method->insns + dvmGetMethodInsnsSize(method));
1730
1731#if 0
1732 /*
1733 * When we hit a specific method, enable verbose instruction logging.
1734 * Sometimes it's helpful to use the debugger attach as a trigger too.
1735 */
1736 if (*pIsMethodEntry) {
1737 static const char* cd = "Landroid/test/Arithmetic;";
1738 static const char* mn = "shiftTest2";
1739 static const char* sg = "()V";
1740
1741 if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/
1742 strcmp(method->clazz->descriptor, cd) == 0 &&
1743 strcmp(method->name, mn) == 0 &&
1744 strcmp(method->shorty, sg) == 0)
1745 {
1746 LOGW("Reached %s.%s, enabling verbose mode\n",
1747 method->clazz->descriptor, method->name);
1748 android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE);
1749 dumpRegs(method, fp, true);
1750 }
1751
1752 if (!gDvm.debuggerActive)
1753 *pIsMethodEntry = false;
1754 }
1755#endif
1756
buzbee94d65252011-03-24 16:41:03 -07001757 /* Safe point handling */
buzbee389e2582011-04-22 15:12:40 -07001758 if (self->suspendCount ||
buzbeecf2aac72011-04-25 11:23:46 -07001759 (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) {
buzbeec4a8caf2011-03-24 12:56:41 -07001760 // Are we are a safe point?
1761 int flags;
1762 flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
1763 if (flags & VERIFY_GC_INST_MASK) {
buzbee94d65252011-03-24 16:41:03 -07001764 // Yes, at a safe point. Pending callback?
buzbeecf2aac72011-04-25 11:23:46 -07001765 if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) {
buzbee94d65252011-03-24 16:41:03 -07001766 SafePointCallback callback;
1767 void* arg;
1768 // Get consistent funct/arg pair
1769 dvmLockMutex(&self->callbackMutex);
1770 callback = self->callback;
1771 arg = self->callbackArg;
1772 dvmUnlockMutex(&self->callbackMutex);
1773 // Update Thread structure
1774 self->interpSave.pc = pc;
buzbee30bc0d42011-04-22 10:27:14 -07001775 self->interpSave.curFrame = fp;
buzbee94d65252011-03-24 16:41:03 -07001776 if (callback != NULL) {
1777 // Do the callback
1778 if (!callback(self,arg)) {
1779 // disarm
1780 dvmArmSafePointCallback(self, NULL, NULL);
1781 }
1782 }
1783 }
1784 // Need to suspend?
buzbee389e2582011-04-22 15:12:40 -07001785 if (self->suspendCount) {
buzbee94d65252011-03-24 16:41:03 -07001786 dvmExportPC(pc, fp);
1787 dvmCheckSuspendPending(self);
1788 }
buzbeec4a8caf2011-03-24 12:56:41 -07001789 }
buzbee9a3147c2011-03-02 15:43:48 -08001790 }
1791
1792 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
buzbeee7147462011-04-13 14:10:04 -07001793 updateDebugger(method, pc, fp, self);
buzbee9a3147c2011-03-02 15:43:48 -08001794 }
1795 if (gDvm.instructionCountEnableCount != 0) {
1796 /*
1797 * Count up the #of executed instructions. This isn't synchronized
1798 * for thread-safety; if we need that we should make this
1799 * thread-local and merge counts into the global area when threads
1800 * exit (perhaps suspending all other threads GC-style and pulling
1801 * the data out of them).
1802 */
1803 gDvm.executedInstrCounts[GET_OPCODE(*pc)]++;
1804 }
1805
1806
1807#if defined(WITH_TRACKREF_CHECKS)
1808 dvmInterpCheckTrackedRefs(self, method,
1809 self->interpSave.debugTrackedRefStart);
1810#endif
1811
1812#if defined(WITH_JIT)
1813 // Does the JIT need anything done now?
buzbeecf2aac72011-04-25 11:23:46 -07001814 if (self->interpBreak.ctl.subMode &
1815 (kSubModeJitTraceBuild | kSubModeJitSV)) {
buzbee9a3147c2011-03-02 15:43:48 -08001816 // Are we building a trace?
1817 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
1818 dvmCheckJit(pc, self);
1819 }
1820
1821#if defined(WITH_SELF_VERIFICATION)
1822 // Are we replaying a trace?
1823 if (self->interpBreak.ctl.subMode & kSubModeJitSV) {
1824 dvmCheckSelfVerification(pc, self);
1825 }
1826#endif
1827 }
1828#endif
1829
1830 /*
Ben Cheng313d4302011-05-11 10:58:52 -07001831 * CountedStep processing. NOTE: must be the last here to allow
buzbee9a3147c2011-03-02 15:43:48 -08001832 * preceeding special case handler to manipulate single-step count.
1833 */
Ben Cheng313d4302011-05-11 10:58:52 -07001834 if (self->interpBreak.ctl.subMode & kSubModeCountedStep) {
buzbee9a3147c2011-03-02 15:43:48 -08001835 if (self->singleStepCount == 0) {
1836 // We've exhausted our single step count
buzbeecf2aac72011-04-25 11:23:46 -07001837 dvmDisableSubMode(self, kSubModeCountedStep);
buzbee9a3147c2011-03-02 15:43:48 -08001838#if defined(WITH_JIT)
1839#if 0
1840 /*
1841 * For debugging. If jitResumeDPC is non-zero, then
1842 * we expect to return to a trace in progress. There
1843 * are valid reasons why we wouldn't (such as an exception
1844 * throw), but here we can keep track.
1845 */
1846 if (self->jitResumeDPC != NULL) {
1847 if (self->jitResumeDPC == pc) {
1848 if (self->jitResumeNPC != NULL) {
1849 LOGD("SS return to trace - pc:0x%x to 0x:%x",
1850 (int)pc, (int)self->jitResumeNPC);
1851 } else {
1852 LOGD("SS return to interp - pc:0x%x",(int)pc);
1853 }
1854 } else {
1855 LOGD("SS failed to return. Expected 0x%x, now at 0x%x",
1856 (int)self->jitResumeDPC, (int)pc);
1857 }
1858 }
1859#endif
1860 // If we've got a native return and no other reasons to
1861 // remain in singlestep/break mode, do a long jump
1862 if (self->jitResumeNPC != NULL &&
1863 self->interpBreak.ctl.breakFlags == 0) {
1864 assert(self->jitResumeDPC == pc);
1865 self->jitResumeDPC = NULL;
1866 dvmJitResumeTranslation(self, pc, fp);
1867 // Doesn't return
1868 dvmAbort();
1869 }
1870 self->jitResumeDPC = NULL;
buzbee7209bdd2011-03-31 15:38:34 -07001871 self->inJitCodeCache = NULL;
buzbee9a3147c2011-03-02 15:43:48 -08001872#endif
1873 } else {
1874 self->singleStepCount--;
1875#if defined(WITH_JIT)
1876 if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) {
1877 /*
1878 * Direct return to an existing translation following a
1879 * single step is valid only if we step once. If we're
1880 * here, an additional step was added so we need to invalidate
1881 * the return to translation.
1882 */
1883 self->jitResumeNPC = NULL;
buzbee7209bdd2011-03-31 15:38:34 -07001884 self->inJitCodeCache = NULL;
buzbee9a3147c2011-03-02 15:43:48 -08001885 }
1886#endif
1887 }
1888 }
buzbeea7d59bb2011-02-24 09:38:17 -08001889}
buzbee9f601a92011-02-11 17:48:20 -08001890
1891/*
buzbee9a3147c2011-03-02 15:43:48 -08001892 * Main interpreter loop entry point.
buzbee9f601a92011-02-11 17:48:20 -08001893 *
1894 * This begins executing code at the start of "method". On exit, "pResult"
1895 * holds the return value of the method (or, if "method" returns NULL, it
1896 * holds an undefined value).
1897 *
1898 * The interpreted stack frame, which holds the method arguments, has
1899 * already been set up.
1900 */
1901void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1902{
buzbee9f601a92011-02-11 17:48:20 -08001903 InterpSaveState interpSaveState;
buzbeecf2aac72011-04-25 11:23:46 -07001904 ExecutionSubModes savedSubModes;
buzbee9a3147c2011-03-02 15:43:48 -08001905
buzbee9f601a92011-02-11 17:48:20 -08001906#if defined(WITH_JIT)
1907 /* Target-specific save/restore */
buzbee9f601a92011-02-11 17:48:20 -08001908 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
Ben Cheng7a2697d2010-06-07 13:44:23 -07001909 /*
1910 * If the previous VM left the code cache through single-stepping the
1911 * inJitCodeCache flag will be set when the VM is re-entered (for example,
1912 * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1913 * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1914 * assert that self->inJitCodeCache is NULL here.
1915 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001916#endif
1917
buzbee9f601a92011-02-11 17:48:20 -08001918 /*
1919 * Save interpreter state from previous activation, linking
1920 * new to last.
1921 */
1922 interpSaveState = self->interpSave;
1923 self->interpSave.prev = &interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001924 /*
1925 * Strip out and save any flags that should not be inherited by
1926 * nested interpreter activation.
1927 */
buzbeecf2aac72011-04-25 11:23:46 -07001928 savedSubModes = (ExecutionSubModes)(
1929 self->interpBreak.ctl.subMode & LOCAL_SUBMODE);
1930 if (savedSubModes != kSubModeNormal) {
1931 dvmDisableSubMode(self, savedSubModes);
buzbee9a3147c2011-03-02 15:43:48 -08001932 }
buzbee9f601a92011-02-11 17:48:20 -08001933#if defined(WITH_JIT)
1934 dvmJitCalleeSave(calleeSave);
1935#endif
1936
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001937
1938#if defined(WITH_TRACKREF_CHECKS)
buzbeeef5db622011-02-22 14:01:46 -08001939 self->interpSave.debugTrackedRefStart =
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001940 dvmReferenceTableEntries(&self->internalLocalRefTable);
1941#endif
buzbee9f601a92011-02-11 17:48:20 -08001942 self->debugIsMethodEntry = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001943#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001944 dvmJitCalleeSave(calleeSave);
Ben Chenga4973592010-03-31 11:59:18 -07001945 /* Initialize the state to kJitNot */
buzbee9f601a92011-02-11 17:48:20 -08001946 self->jitState = kJitNot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001947#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001948
1949 /*
1950 * Initialize working state.
1951 *
1952 * No need to initialize "retval".
1953 */
buzbee9f601a92011-02-11 17:48:20 -08001954 self->interpSave.method = method;
buzbee30bc0d42011-04-22 10:27:14 -07001955 self->interpSave.curFrame = (u4*) self->interpSave.curFrame;
buzbee9f601a92011-02-11 17:48:20 -08001956 self->interpSave.pc = method->insns;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001957
1958 assert(!dvmIsNativeMethod(method));
1959
1960 /*
1961 * Make sure the class is ready to go. Shouldn't be possible to get
1962 * here otherwise.
1963 */
1964 if (method->clazz->status < CLASS_INITIALIZING ||
1965 method->clazz->status == CLASS_ERROR)
1966 {
1967 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1968 method->clazz->descriptor, method->clazz->status);
1969 dvmDumpThread(self, false);
1970 dvmAbort();
1971 }
1972
buzbee9a3147c2011-03-02 15:43:48 -08001973 typedef void (*Interpreter)(Thread*);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001974 Interpreter stdInterp;
1975 if (gDvm.executionMode == kExecutionModeInterpFast)
1976 stdInterp = dvmMterpStd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001977#if defined(WITH_JIT)
1978 else if (gDvm.executionMode == kExecutionModeJit)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001979 stdInterp = dvmMterpStd;
1980#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001981 else
buzbee9a3147c2011-03-02 15:43:48 -08001982 stdInterp = dvmInterpretPortable;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001983
buzbee9a3147c2011-03-02 15:43:48 -08001984 // Call the interpreter
1985 (*stdInterp)(self);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001986
buzbee9f601a92011-02-11 17:48:20 -08001987 *pResult = self->retval;
1988
1989 /* Restore interpreter state from previous activation */
1990 self->interpSave = interpSaveState;
Bill Buzbee342806d2009-12-08 12:37:13 -08001991#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001992 dvmJitCalleeRestore(calleeSave);
Bill Buzbee342806d2009-12-08 12:37:13 -08001993#endif
buzbeecf2aac72011-04-25 11:23:46 -07001994 if (savedSubModes != kSubModeNormal) {
1995 dvmEnableSubMode(self, savedSubModes);
buzbee9a3147c2011-03-02 15:43:48 -08001996 }
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001997}