blob: 7ad30963643c9ee147f6f2827335436299f78fd2 [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
40static BreakpointSet* dvmBreakpointSetAlloc(void);
41static void dvmBreakpointSetFree(BreakpointSet* pSet);
42
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070043/*
Andy McFadden96516932009-10-28 17:39:02 -070044 * Initialize global breakpoint structures.
45 */
46bool dvmBreakpointStartup(void)
47{
Andy McFadden96516932009-10-28 17:39:02 -070048 gDvm.breakpointSet = dvmBreakpointSetAlloc();
49 return (gDvm.breakpointSet != NULL);
Andy McFadden96516932009-10-28 17:39:02 -070050}
51
52/*
53 * Free resources.
54 */
55void dvmBreakpointShutdown(void)
56{
Andy McFadden96516932009-10-28 17:39:02 -070057 dvmBreakpointSetFree(gDvm.breakpointSet);
Andy McFadden96516932009-10-28 17:39:02 -070058}
59
60
Andy McFadden96516932009-10-28 17:39:02 -070061/*
62 * This represents a breakpoint inserted in the instruction stream.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070063 *
Andy McFadden96516932009-10-28 17:39:02 -070064 * The debugger may ask us to create the same breakpoint multiple times.
65 * We only remove the breakpoint when the last instance is cleared.
66 */
67typedef struct {
Andy McFaddend22748a2010-04-22 17:08:11 -070068 Method* method; /* method we're associated with */
Andy McFadden96516932009-10-28 17:39:02 -070069 u2* addr; /* absolute memory address */
Dan Bornstein9a1f8162010-12-01 17:02:26 -080070 u1 originalOpcode; /* original 8-bit opcode value */
Andy McFadden96516932009-10-28 17:39:02 -070071 int setCount; /* #of times this breakpoint was set */
72} Breakpoint;
73
74/*
75 * Set of breakpoints.
76 */
77struct BreakpointSet {
78 /* grab lock before reading or writing anything else in here */
79 pthread_mutex_t lock;
80
81 /* vector of breakpoint structures */
82 int alloc;
83 int count;
84 Breakpoint* breakpoints;
85};
86
87/*
88 * Initialize a BreakpointSet. Initially empty.
89 */
90static BreakpointSet* dvmBreakpointSetAlloc(void)
91{
92 BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
93
94 dvmInitMutex(&pSet->lock);
95 /* leave the rest zeroed -- will alloc on first use */
96
97 return pSet;
98}
99
100/*
101 * Free storage associated with a BreakpointSet.
102 */
103static void dvmBreakpointSetFree(BreakpointSet* pSet)
104{
105 if (pSet == NULL)
106 return;
107
108 free(pSet->breakpoints);
109 free(pSet);
110}
111
112/*
113 * Lock the breakpoint set.
Andy McFaddend22748a2010-04-22 17:08:11 -0700114 *
115 * It's not currently necessary to switch to VMWAIT in the event of
116 * contention, because nothing in here can block. However, it's possible
117 * that the bytecode-updater code could become fancier in the future, so
118 * we do the trylock dance as a bit of future-proofing.
Andy McFadden96516932009-10-28 17:39:02 -0700119 */
120static void dvmBreakpointSetLock(BreakpointSet* pSet)
121{
Andy McFaddend22748a2010-04-22 17:08:11 -0700122 if (dvmTryLockMutex(&pSet->lock) != 0) {
123 Thread* self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700124 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700125 dvmLockMutex(&pSet->lock);
126 dvmChangeStatus(self, oldStatus);
127 }
Andy McFadden96516932009-10-28 17:39:02 -0700128}
129
130/*
131 * Unlock the breakpoint set.
132 */
133static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
134{
135 dvmUnlockMutex(&pSet->lock);
136}
137
138/*
139 * Return the #of breakpoints.
140 */
141static int dvmBreakpointSetCount(const BreakpointSet* pSet)
142{
143 return pSet->count;
144}
145
146/*
147 * See if we already have an entry for this address.
148 *
149 * The BreakpointSet's lock must be acquired before calling here.
150 *
151 * Returns the index of the breakpoint entry, or -1 if not found.
152 */
153static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
154{
155 int i;
156
157 for (i = 0; i < pSet->count; i++) {
158 Breakpoint* pBreak = &pSet->breakpoints[i];
159 if (pBreak->addr == addr)
160 return i;
161 }
162
163 return -1;
164}
165
166/*
167 * Retrieve the opcode that was originally at the specified location.
168 *
169 * The BreakpointSet's lock must be acquired before calling here.
170 *
171 * Returns "true" with the opcode in *pOrig on success.
172 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800173static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
Andy McFadden96516932009-10-28 17:39:02 -0700174 const u2* addr, u1* pOrig)
175{
176 int idx = dvmBreakpointSetFind(pSet, addr);
177 if (idx < 0)
178 return false;
179
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800180 *pOrig = pSet->breakpoints[idx].originalOpcode;
Andy McFadden96516932009-10-28 17:39:02 -0700181 return true;
182}
183
184/*
Andy McFaddenda9dc842010-05-03 16:11:20 -0700185 * Check the opcode. If it's a "magic" NOP, indicating the start of
186 * switch or array data in the instruction stream, we don't want to set
187 * a breakpoint.
188 *
189 * This can happen because the line number information dx generates
190 * associates the switch data with the switch statement's line number,
191 * and some debuggers put breakpoints at every address associated with
192 * a given line. The result is that the breakpoint stomps on the NOP
193 * instruction that doubles as a data table magic number, and an explicit
194 * check in the interpreter results in an exception being thrown.
195 *
196 * We don't want to simply refuse to add the breakpoint to the table,
197 * because that confuses the housekeeping. We don't want to reject the
198 * debugger's event request, and we want to be sure that there's exactly
199 * one un-set operation for every set op.
200 */
201static bool instructionIsMagicNop(const u2* addr)
202{
203 u2 curVal = *addr;
buzbee9a3147c2011-03-02 15:43:48 -0800204 return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700205}
206
207/*
Andy McFadden96516932009-10-28 17:39:02 -0700208 * Add a breakpoint at a specific address. If the address is already
209 * present in the table, this just increments the count.
210 *
211 * For a new entry, this will extract and preserve the current opcode from
212 * the instruction stream, and replace it with a breakpoint opcode.
213 *
214 * The BreakpointSet's lock must be acquired before calling here.
215 *
216 * Returns "true" on success.
217 */
218static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
219 unsigned int instrOffset)
220{
221 const int kBreakpointGrowth = 10;
222 const u2* addr = method->insns + instrOffset;
223 int idx = dvmBreakpointSetFind(pSet, addr);
224 Breakpoint* pBreak;
225
226 if (idx < 0) {
227 if (pSet->count == pSet->alloc) {
228 int newSize = pSet->alloc + kBreakpointGrowth;
229 Breakpoint* newVec;
230
231 LOGV("+++ increasing breakpoint set size to %d\n", newSize);
232
233 /* pSet->breakpoints will be NULL on first entry */
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800234 newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
Andy McFadden96516932009-10-28 17:39:02 -0700235 if (newVec == NULL)
236 return false;
237
238 pSet->breakpoints = newVec;
239 pSet->alloc = newSize;
240 }
241
242 pBreak = &pSet->breakpoints[pSet->count++];
Andy McFaddend22748a2010-04-22 17:08:11 -0700243 pBreak->method = method;
Andy McFadden96516932009-10-28 17:39:02 -0700244 pBreak->addr = (u2*)addr;
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800245 pBreak->originalOpcode = *(u1*)addr;
Andy McFadden96516932009-10-28 17:39:02 -0700246 pBreak->setCount = 1;
247
248 /*
249 * Change the opcode. We must ensure that the BreakpointSet
250 * updates happen before we change the opcode.
Andy McFaddend22748a2010-04-22 17:08:11 -0700251 *
252 * If the method has not been verified, we do NOT insert the
253 * breakpoint yet, since that will screw up the verifier. The
254 * debugger is allowed to insert breakpoints in unverified code,
255 * but since we don't execute unverified code we don't need to
256 * alter the bytecode yet.
257 *
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700258 * The class init code will "flush" all pending opcode writes
259 * before verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700260 */
Andy McFadden96516932009-10-28 17:39:02 -0700261 assert(*(u1*)addr != OP_BREAKPOINT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700262 if (dvmIsClassVerified(method->clazz)) {
263 LOGV("Class %s verified, adding breakpoint at %p\n",
264 method->clazz->descriptor, addr);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700265 if (instructionIsMagicNop(addr)) {
266 LOGV("Refusing to set breakpoint on %04x at %s.%s + 0x%x\n",
267 *addr, method->clazz->descriptor, method->name,
268 instrOffset);
269 } else {
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700270 ANDROID_MEMBAR_FULL();
Andy McFaddenda9dc842010-05-03 16:11:20 -0700271 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
272 OP_BREAKPOINT);
273 }
Andy McFaddend22748a2010-04-22 17:08:11 -0700274 } else {
275 LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
276 method->clazz->descriptor, addr);
277 }
Andy McFadden96516932009-10-28 17:39:02 -0700278 } else {
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700279 /*
280 * Breakpoint already exists, just increase the count.
281 */
Andy McFadden96516932009-10-28 17:39:02 -0700282 pBreak = &pSet->breakpoints[idx];
283 pBreak->setCount++;
Andy McFadden96516932009-10-28 17:39:02 -0700284 }
285
286 return true;
287}
288
289/*
290 * Remove one instance of the specified breakpoint. When the count
291 * reaches zero, the entry is removed from the table, and the original
292 * opcode is restored.
293 *
294 * The BreakpointSet's lock must be acquired before calling here.
295 */
296static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
297 unsigned int instrOffset)
298{
299 const u2* addr = method->insns + instrOffset;
300 int idx = dvmBreakpointSetFind(pSet, addr);
301
302 if (idx < 0) {
303 /* breakpoint not found in set -- unexpected */
304 if (*(u1*)addr == OP_BREAKPOINT) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700305 LOGE("Unable to restore breakpoint opcode (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700306 method->clazz->descriptor, method->name, instrOffset);
307 dvmAbort();
308 } else {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700309 LOGW("Breakpoint was already restored? (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700310 method->clazz->descriptor, method->name, instrOffset);
311 }
312 } else {
313 Breakpoint* pBreak = &pSet->breakpoints[idx];
314 if (pBreak->setCount == 1) {
315 /*
316 * Must restore opcode before removing set entry.
Andy McFaddend22748a2010-04-22 17:08:11 -0700317 *
318 * If the breakpoint was never flushed, we could be ovewriting
319 * a value with the same value. Not a problem, though we
320 * could end up causing a copy-on-write here when we didn't
321 * need to. (Not worth worrying about.)
Andy McFadden96516932009-10-28 17:39:02 -0700322 */
323 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800324 pBreak->originalOpcode);
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700325 ANDROID_MEMBAR_FULL();
Andy McFadden96516932009-10-28 17:39:02 -0700326
327 if (idx != pSet->count-1) {
328 /* shift down */
329 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
330 (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
331 }
332 pSet->count--;
333 pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
334 } else {
335 pBreak->setCount--;
336 assert(pBreak->setCount > 0);
337 }
338 }
339}
340
341/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700342 * Flush any breakpoints associated with methods in "clazz". We want to
343 * change the opcode, which might not have happened when the breakpoint
344 * was initially set because the class was in the process of being
345 * verified.
Andy McFadden96516932009-10-28 17:39:02 -0700346 *
347 * The BreakpointSet's lock must be acquired before calling here.
348 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700349static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700350{
Andy McFadden96516932009-10-28 17:39:02 -0700351 int i;
352 for (i = 0; i < pSet->count; i++) {
353 Breakpoint* pBreak = &pSet->breakpoints[i];
Andy McFaddend22748a2010-04-22 17:08:11 -0700354 if (pBreak->method->clazz == clazz) {
355 /*
356 * The breakpoint is associated with a method in this class.
357 * It might already be there or it might not; either way,
358 * flush it out.
359 */
360 LOGV("Flushing breakpoint at %p for %s\n",
361 pBreak->addr, clazz->descriptor);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700362 if (instructionIsMagicNop(pBreak->addr)) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700363 LOGV("Refusing to flush breakpoint on %04x at %s.%s + 0x%x\n",
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700364 *pBreak->addr, pBreak->method->clazz->descriptor,
365 pBreak->method->name, pBreak->addr - pBreak->method->insns);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700366 } else {
367 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
368 OP_BREAKPOINT);
369 }
Andy McFadden96516932009-10-28 17:39:02 -0700370 }
371 }
372}
Andy McFadden96516932009-10-28 17:39:02 -0700373
374
375/*
376 * Do any debugger-attach-time initialization.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700377 */
378void dvmInitBreakpoints(void)
379{
Andy McFadden96516932009-10-28 17:39:02 -0700380 /* quick sanity check */
381 BreakpointSet* pSet = gDvm.breakpointSet;
382 dvmBreakpointSetLock(pSet);
383 if (dvmBreakpointSetCount(pSet) != 0) {
384 LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
385 /* generally not good, but we can keep going */
386 }
387 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700388}
389
390/*
391 * Add an address to the list, putting it in the first non-empty slot.
392 *
393 * Sometimes the debugger likes to add two entries for one breakpoint.
394 * We add two entries here, so that we get the right behavior when it's
395 * removed twice.
396 *
397 * This will only be run from the JDWP thread, and it will happen while
398 * we are updating the event list, which is synchronized. We're guaranteed
399 * to be the only one adding entries, and the lock ensures that nobody
400 * will be trying to remove them while we're in here.
401 *
402 * "addr" is the absolute address of the breakpoint bytecode.
403 */
Andy McFadden96516932009-10-28 17:39:02 -0700404void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700405{
Andy McFadden96516932009-10-28 17:39:02 -0700406 BreakpointSet* pSet = gDvm.breakpointSet;
407 dvmBreakpointSetLock(pSet);
408 dvmBreakpointSetAdd(pSet, method, instrOffset);
409 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700410}
411
412/*
413 * Remove an address from the list by setting the entry to NULL.
414 *
415 * This can be called from the JDWP thread (because the debugger has
416 * cancelled the breakpoint) or from an event thread (because it's a
417 * single-shot breakpoint, e.g. "run to line"). We only get here as
418 * the result of removing an entry from the event list, which is
419 * synchronized, so it should not be possible for two threads to be
420 * updating breakpoints at the same time.
421 */
Andy McFadden96516932009-10-28 17:39:02 -0700422void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700423{
Andy McFadden96516932009-10-28 17:39:02 -0700424 BreakpointSet* pSet = gDvm.breakpointSet;
425 dvmBreakpointSetLock(pSet);
426 dvmBreakpointSetRemove(pSet, method, instrOffset);
427 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700428}
429
Andy McFadden96516932009-10-28 17:39:02 -0700430/*
431 * Get the original opcode from under a breakpoint.
Andy McFaddenfc3d3162010-08-05 14:34:26 -0700432 *
433 * On SMP hardware it's possible one core might try to execute a breakpoint
434 * after another core has cleared it. We need to handle the case where
435 * there's no entry in the breakpoint set. (The memory barriers in the
436 * locks and in the breakpoint update code should ensure that, once we've
437 * observed the absence of a breakpoint entry, we will also now observe
438 * the restoration of the original opcode. The fact that we're holding
439 * the lock prevents other threads from confusing things further.)
Andy McFadden96516932009-10-28 17:39:02 -0700440 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800441u1 dvmGetOriginalOpcode(const u2* addr)
Andy McFadden96516932009-10-28 17:39:02 -0700442{
443 BreakpointSet* pSet = gDvm.breakpointSet;
444 u1 orig = 0;
445
446 dvmBreakpointSetLock(pSet);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800447 if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
Andy McFadden96516932009-10-28 17:39:02 -0700448 orig = *(u1*)addr;
449 if (orig == OP_BREAKPOINT) {
450 LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
451 dvmAbort();
452 }
453 }
454 dvmBreakpointSetUnlock(pSet);
455
456 return orig;
457}
458
459/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700460 * Flush any breakpoints associated with methods in "clazz".
Andy McFadden96516932009-10-28 17:39:02 -0700461 *
Andy McFaddend22748a2010-04-22 17:08:11 -0700462 * We don't want to modify the bytecode of a method before the verifier
463 * gets a chance to look at it, so we postpone opcode replacement until
464 * after verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700465 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700466void dvmFlushBreakpoints(ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700467{
468 BreakpointSet* pSet = gDvm.breakpointSet;
469
Andy McFaddend22748a2010-04-22 17:08:11 -0700470 if (pSet == NULL)
471 return;
472
473 assert(dvmIsClassVerified(clazz));
Andy McFadden96516932009-10-28 17:39:02 -0700474 dvmBreakpointSetLock(pSet);
Andy McFaddend22748a2010-04-22 17:08:11 -0700475 dvmBreakpointSetFlush(pSet, clazz);
Andy McFadden96516932009-10-28 17:39:02 -0700476 dvmBreakpointSetUnlock(pSet);
477}
Andy McFadden96516932009-10-28 17:39:02 -0700478
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700479/*
480 * Add a single step event. Currently this is a global item.
481 *
482 * We set up some initial values based on the thread's current state. This
483 * won't work well if the thread is running, so it's up to the caller to
484 * verify that it's suspended.
485 *
486 * This is only called from the JDWP thread.
487 */
488bool dvmAddSingleStep(Thread* thread, int size, int depth)
489{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700490 StepControl* pCtrl = &gDvm.stepControl;
491
492 if (pCtrl->active && thread != pCtrl->thread) {
493 LOGW("WARNING: single-step active for %p; adding %p\n",
494 pCtrl->thread, thread);
495
496 /*
497 * Keep going, overwriting previous. This can happen if you
498 * suspend a thread in Object.wait, hit the single-step key, then
499 * switch to another thread and do the same thing again.
500 * The first thread's step is still pending.
501 *
502 * TODO: consider making single-step per-thread. Adds to the
503 * overhead, but could be useful in rare situations.
504 */
505 }
506
507 pCtrl->size = size;
508 pCtrl->depth = depth;
509 pCtrl->thread = thread;
510
511 /*
512 * We may be stepping into or over method calls, or running until we
513 * return from the current method. To make this work we need to track
514 * the current line, current method, and current stack depth. We need
515 * to be checking these after most instructions, notably those that
516 * call methods, return from methods, or are on a different line from the
517 * previous instruction.
518 *
519 * We have to start with a snapshot of the current state. If we're in
520 * an interpreted method, everything we need is in the current frame. If
521 * we're in a native method, possibly with some extra JNI frames pushed
522 * on by PushLocalFrame, we want to use the topmost native method.
523 */
524 const StackSaveArea* saveArea;
525 void* fp;
526 void* prevFp = NULL;
Ben Cheng38329f52009-07-07 14:19:20 -0700527
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700528 for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
529 const Method* method;
530
531 saveArea = SAVEAREA_FROM_FP(fp);
532 method = saveArea->method;
533
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800534 if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700535 break;
536 prevFp = fp;
537 }
538 if (fp == NULL) {
539 LOGW("Unexpected: step req in native-only threadid=%d\n",
540 thread->threadId);
541 return false;
542 }
543 if (prevFp != NULL) {
544 /*
545 * First interpreted frame wasn't the one at the bottom. Break
546 * frames are only inserted when calling from native->interp, so we
547 * don't need to worry about one being here.
548 */
549 LOGV("##### init step while in native method\n");
550 fp = prevFp;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800551 assert(!dvmIsBreakFrame((u4*)fp));
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700552 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
553 saveArea = SAVEAREA_FROM_FP(fp);
554 }
555
556 /*
557 * Pull the goodies out. "xtra.currentPc" should be accurate since
558 * we update it on every instruction while the debugger is connected.
559 */
560 pCtrl->method = saveArea->method;
561 // Clear out any old address set
562 if (pCtrl->pAddressSet != NULL) {
563 // (discard const)
564 free((void *)pCtrl->pAddressSet);
565 pCtrl->pAddressSet = NULL;
566 }
567 if (dvmIsNativeMethod(pCtrl->method)) {
568 pCtrl->line = -1;
569 } else {
570 pCtrl->line = dvmLineNumFromPC(saveArea->method,
571 saveArea->xtra.currentPc - saveArea->method->insns);
Ben Cheng38329f52009-07-07 14:19:20 -0700572 pCtrl->pAddressSet
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700573 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
574 }
575 pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
576 pCtrl->active = true;
577
578 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
579 pCtrl->thread, pCtrl->method, pCtrl->method->name,
580 pCtrl->line, pCtrl->frameDepth,
581 dvmJdwpStepDepthStr(pCtrl->depth),
582 dvmJdwpStepSizeStr(pCtrl->size));
583
584 return true;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700585}
586
587/*
588 * Disable a single step event.
589 */
590void dvmClearSingleStep(Thread* thread)
591{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700592 UNUSED_PARAMETER(thread);
593
594 gDvm.stepControl.active = false;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700595}
596
buzbee9a3147c2011-03-02 15:43:48 -0800597/*
598 * The interpreter just threw. Handle any special subMode requirements.
599 */
600void dvmReportExceptionThrow(Thread* self, const Method* curMethod,
601 const u2* pc, void* fp)
602{
603#if defined(WITH_JIT)
604 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
605 dvmJitEndTraceSelect(self, pc);
606 }
607 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
608 /* Discard any single-step native returns to translation */
609 self->jitResumeNPC = NULL;
610 }
611#endif
612 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
613 void *catchFrame;
614 int offset = pc - curMethod->insns;
615 int catchRelPc = dvmFindCatchBlock(self, offset, self->exception,
616 true, &catchFrame);
617 dvmDbgPostException(fp, offset, catchFrame, catchRelPc,
618 self->exception);
619 }
620}
621
622/*
623 * The interpreter is preparing to do an invoke (both native & normal).
624 * Handle any special subMode requirements.
625 */
626void dvmReportInvoke(Thread* self, const Method* methodToCall)
627{
628 TRACE_METHOD_ENTER(self, methodToCall);
629}
630
631/*
632 * The interpreter is preparing to do a native invoke. Handle any
633 * special subMode requirements. NOTE: for a native invoke,
634 * dvmReportInvoke() and dvmReportPreNativeInvoke() will both
635 * be called prior to the invoke.
636 */
637void dvmReportPreNativeInvoke(const u2* pc, Thread* self,
638 const Method* methodToCall)
639{
640#if defined(WITH_JIT)
641 /*
642 * Actively building a trace? If so, end it now. The trace
643 * builder can't follow into or through a native method.
644 */
645 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
646 dvmCheckJit(pc, self);
647 }
648#endif
649 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
650 Object* thisPtr = dvmGetThisPtr(self->interpSave.method,
651 self->interpSave.fp);
652 assert(thisPtr != NULL && !dvmIsValidObject(thisPtr));
653 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY);
654 }
655}
656
657/*
658 * The interpreter has returned from a native invoke. Handle any
659 * special subMode requirements.
660 */
661void dvmReportPostNativeInvoke(const u2* pc, Thread* self,
662 const Method* methodToCall)
663{
664 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
665 Object* thisPtr = dvmGetThisPtr(self->interpSave.method,
666 self->interpSave.fp);
667 assert(thisPtr != NULL && !dvmIsValidObject(thisPtr));
668 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT);
669 }
670 if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) {
671 dvmFastNativeMethodTraceExit(methodToCall, self);
672 }
673}
674
675/*
676 * The interpreter has returned from a normal method. Handle any special
677 * subMode requirements.
678 */
679void dvmReportReturn(Thread* self, const u2* pc, const u4* prevFP)
680{
681 TRACE_METHOD_EXIT(self, self->interpSave.method);
682#if defined(WITH_JIT)
683 if (dvmIsBreakFrame(prevFP) &&
684 (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) {
685 dvmCheckJit(pc, self);
686 }
687#endif
688}
689
690/*
691 * Update the debugger on interesting events, such as hitting a breakpoint
692 * or a single-step point. This is called from the top of the interpreter
693 * loop, before the current instruction is processed.
694 *
695 * Set "methodEntry" if we've just entered the method. This detects
696 * method exit by checking to see if the next instruction is "return".
697 *
698 * This can't catch native method entry/exit, so we have to handle that
699 * at the point of invocation. We also need to catch it in dvmCallMethod
700 * if we want to capture native->native calls made through JNI.
701 *
702 * Notes to self:
703 * - Don't want to switch to VMWAIT while posting events to the debugger.
704 * Let the debugger code decide if we need to change state.
705 * - We may want to check for debugger-induced thread suspensions on
706 * every instruction. That would make a "suspend all" more responsive
707 * and reduce the chances of multiple simultaneous events occurring.
708 * However, it could change the behavior some.
709 *
710 * TODO: method entry/exit events are probably less common than location
711 * breakpoints. We may be able to speed things up a bit if we don't query
712 * the event list unless we know there's at least one lurking within.
713 */
714void dvmUpdateDebugger(const Method* method, const u2* pc, const u4* fp,
715 bool methodEntry, Thread* self)
716{
717 int eventFlags = 0;
718
719 /*
720 * Update xtra.currentPc on every instruction. We need to do this if
721 * there's a chance that we could get suspended. This can happen if
722 * eventFlags != 0 here, or somebody manually requests a suspend
723 * (which gets handled at PERIOD_CHECKS time). One place where this
724 * needs to be correct is in dvmAddSingleStep().
725 */
726 dvmExportPC(pc, fp);
727
728 if (methodEntry)
729 eventFlags |= DBG_METHOD_ENTRY;
730
731 /*
732 * See if we have a breakpoint here.
733 *
734 * Depending on the "mods" associated with event(s) on this address,
735 * we may or may not actually send a message to the debugger.
736 */
737 if (GET_OPCODE(*pc) == OP_BREAKPOINT) {
738 LOGV("+++ breakpoint hit at %p\n", pc);
739 eventFlags |= DBG_BREAKPOINT;
740 }
741
742 /*
743 * If the debugger is single-stepping one of our threads, check to
744 * see if we're that thread and we've reached a step point.
745 */
746 const StepControl* pCtrl = &gDvm.stepControl;
747 if (pCtrl->active && pCtrl->thread == self) {
748 int frameDepth;
749 bool doStop = false;
750 const char* msg = NULL;
751
752 assert(!dvmIsNativeMethod(method));
753
754 if (pCtrl->depth == SD_INTO) {
755 /*
756 * Step into method calls. We break when the line number
757 * or method pointer changes. If we're in SS_MIN mode, we
758 * always stop.
759 */
760 if (pCtrl->method != method) {
761 doStop = true;
762 msg = "new method";
763 } else if (pCtrl->size == SS_MIN) {
764 doStop = true;
765 msg = "new instruction";
766 } else if (!dvmAddressSetGet(
767 pCtrl->pAddressSet, pc - method->insns)) {
768 doStop = true;
769 msg = "new line";
770 }
771 } else if (pCtrl->depth == SD_OVER) {
772 /*
773 * Step over method calls. We break when the line number is
774 * different and the frame depth is <= the original frame
775 * depth. (We can't just compare on the method, because we
776 * might get unrolled past it by an exception, and it's tricky
777 * to identify recursion.)
778 */
779 frameDepth = dvmComputeVagueFrameDepth(self, fp);
780 if (frameDepth < pCtrl->frameDepth) {
781 /* popped up one or more frames, always trigger */
782 doStop = true;
783 msg = "method pop";
784 } else if (frameDepth == pCtrl->frameDepth) {
785 /* same depth, see if we moved */
786 if (pCtrl->size == SS_MIN) {
787 doStop = true;
788 msg = "new instruction";
789 } else if (!dvmAddressSetGet(pCtrl->pAddressSet,
790 pc - method->insns)) {
791 doStop = true;
792 msg = "new line";
793 }
794 }
795 } else {
796 assert(pCtrl->depth == SD_OUT);
797 /*
798 * Return from the current method. We break when the frame
799 * depth pops up.
800 *
801 * This differs from the "method exit" break in that it stops
802 * with the PC at the next instruction in the returned-to
803 * function, rather than the end of the returning function.
804 */
805 frameDepth = dvmComputeVagueFrameDepth(self, fp);
806 if (frameDepth < pCtrl->frameDepth) {
807 doStop = true;
808 msg = "method pop";
809 }
810 }
811
812 if (doStop) {
813 LOGV("#####S %s\n", msg);
814 eventFlags |= DBG_SINGLE_STEP;
815 }
816 }
817
818 /*
819 * Check to see if this is a "return" instruction. JDWP says we should
820 * send the event *after* the code has been executed, but it also says
821 * the location we provide is the last instruction. Since the "return"
822 * instruction has no interesting side effects, we should be safe.
823 * (We can't just move this down to the returnFromMethod label because
824 * we potentially need to combine it with other events.)
825 *
826 * We're also not supposed to generate a method exit event if the method
827 * terminates "with a thrown exception".
828 */
829 u2 opcode = GET_OPCODE(*pc);
830 if (opcode == OP_RETURN_VOID || opcode == OP_RETURN ||
831 opcode == OP_RETURN_WIDE ||opcode == OP_RETURN_OBJECT)
832 {
833 eventFlags |= DBG_METHOD_EXIT;
834 }
835
836 /*
837 * If there's something interesting going on, see if it matches one
838 * of the debugger filters.
839 */
840 if (eventFlags != 0) {
841 Object* thisPtr = dvmGetThisPtr(method, fp);
842 if (thisPtr != NULL && !dvmIsValidObject(thisPtr)) {
843 /*
844 * TODO: remove this check if we're confident that the "this"
845 * pointer is where it should be -- slows us down, especially
846 * during single-step.
847 */
848 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
849 LOGE("HEY: invalid 'this' ptr %p (%s.%s %s)\n", thisPtr,
850 method->clazz->descriptor, method->name, desc);
851 free(desc);
852 dvmAbort();
853 }
854 dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr,
855 eventFlags);
856 }
857}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700858
859/*
860 * Recover the "this" pointer from the current interpreted method. "this"
861 * is always in "in0" for non-static methods.
862 *
863 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
864 *
865 * This works because "dx" guarantees that it will work. It's probably
866 * fairly common to have a virtual method that doesn't use its "this"
867 * pointer, in which case we're potentially wasting a register. However,
868 * the debugger doesn't treat "this" as just another argument. For
869 * example, events (such as breakpoints) can be enabled for specific
870 * values of "this". There is also a separate StackFrame.ThisObject call
871 * in JDWP that is expected to work for any non-native non-static method.
872 *
873 * Because we need it when setting up debugger event filters, we want to
874 * be able to do this quickly.
875 */
876Object* dvmGetThisPtr(const Method* method, const u4* fp)
877{
878 if (dvmIsStaticMethod(method))
879 return NULL;
880 return (Object*)fp[method->registersSize - method->insSize];
881}
882
883
884#if defined(WITH_TRACKREF_CHECKS)
885/*
886 * Verify that all internally-tracked references have been released. If
887 * they haven't, print them and abort the VM.
888 *
889 * "debugTrackedRefStart" indicates how many refs were on the list when
890 * we were first invoked.
891 */
892void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
893 int debugTrackedRefStart)
894{
895 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
896 != (size_t) debugTrackedRefStart)
897 {
898 char* desc;
899 Object** top;
900 int count;
901
902 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
903
904 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
905 debugTrackedRefStart, count);
906 desc = dexProtoCopyMethodDescriptor(&method->prototype);
907 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
908 method->name, desc);
909 free(desc);
910 top = self->internalLocalRefTable.table + debugTrackedRefStart;
911 while (top < self->internalLocalRefTable.nextEntry) {
912 LOGE(" %p (%s)\n",
913 *top,
914 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
915 top++;
916 }
917 dvmDumpThread(self, false);
918
919 dvmAbort();
920 }
921 //LOGI("TRACK OK\n");
922}
923#endif
924
925
926#ifdef LOG_INSTR
927/*
928 * Dump the v-registers. Sent to the ILOG log tag.
929 */
930void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
931{
932 int i, localCount;
933
934 localCount = method->registersSize - method->insSize;
935
936 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
937 for (i = method->registersSize-1; i >= 0; i--) {
938 if (i >= localCount) {
939 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
940 i, i-localCount, framePtr[i]);
941 } else {
942 if (inOnly) {
943 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
944 break;
945 }
946 const char* name = "";
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700947#if 0 // "locals" structure has changed -- need to rewrite this
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700948 int j;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700949 DexFile* pDexFile = method->clazz->pDexFile;
950 const DexCode* pDexCode = dvmGetMethodCode(method);
951 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
952 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
953 for (j = 0; j < localsSize, j++) {
954 if (locals[j].registerNum == (u4) i) {
955 name = dvmDexStringStr(locals[j].pName);
956 break;
957 }
958 }
959#endif
960 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
961 i, framePtr[i], name);
962 }
963 }
964}
965#endif
966
967
968/*
969 * ===========================================================================
970 * Entry point and general support functions
971 * ===========================================================================
972 */
973
Ben Cheng38329f52009-07-07 14:19:20 -0700974/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700975 * Construct an s4 from two consecutive half-words of switch data.
976 * This needs to check endianness because the DEX optimizer only swaps
977 * half-words in instruction stream.
978 *
979 * "switchData" must be 32-bit aligned.
980 */
981#if __BYTE_ORDER == __LITTLE_ENDIAN
982static inline s4 s4FromSwitchData(const void* switchData) {
983 return *(s4*) switchData;
984}
985#else
986static inline s4 s4FromSwitchData(const void* switchData) {
987 u2* data = switchData;
988 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +0000989}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700990#endif
991
992/*
993 * Find the matching case. Returns the offset to the handler instructions.
994 *
995 * Returns 3 if we don't find a match (it's the size of the packed-switch
996 * instruction).
997 */
998s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
999{
1000 const int kInstrLen = 3;
1001 u2 size;
1002 s4 firstKey;
1003 const s4* entries;
1004
1005 /*
1006 * Packed switch data format:
1007 * ushort ident = 0x0100 magic value
1008 * ushort size number of entries in the table
1009 * int first_key first (and lowest) switch case value
1010 * int targets[size] branch targets, relative to switch opcode
1011 *
1012 * Total size is (4+size*2) 16-bit code units.
1013 */
1014 if (*switchData++ != kPackedSwitchSignature) {
1015 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001016 dvmThrowInternalError("bad packed switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001017 return kInstrLen;
1018 }
1019
1020 size = *switchData++;
1021 assert(size > 0);
1022
1023 firstKey = *switchData++;
1024 firstKey |= (*switchData++) << 16;
1025
1026 if (testVal < firstKey || testVal >= firstKey + size) {
1027 LOGVV("Value %d not found in switch (%d-%d)\n",
1028 testVal, firstKey, firstKey+size-1);
1029 return kInstrLen;
1030 }
1031
1032 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1033 * we can treat them as a native int array.
1034 */
1035 entries = (const s4*) switchData;
1036 assert(((u4)entries & 0x3) == 0);
1037
1038 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
1039 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
1040 testVal, testVal - firstKey,
1041 s4FromSwitchData(&entries[testVal - firstKey]));
1042 return s4FromSwitchData(&entries[testVal - firstKey]);
1043}
1044
1045/*
1046 * Find the matching case. Returns the offset to the handler instructions.
1047 *
1048 * Returns 3 if we don't find a match (it's the size of the sparse-switch
1049 * instruction).
1050 */
1051s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
1052{
1053 const int kInstrLen = 3;
Carl Shapiroe3c01da2010-05-20 22:54:18 -07001054 u2 size;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001055 const s4* keys;
1056 const s4* entries;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001057
1058 /*
1059 * Sparse switch data format:
1060 * ushort ident = 0x0200 magic value
1061 * ushort size number of entries in the table; > 0
1062 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1063 * int targets[size] branch targets, relative to switch opcode
1064 *
1065 * Total size is (2+size*4) 16-bit code units.
1066 */
1067
1068 if (*switchData++ != kSparseSwitchSignature) {
1069 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001070 dvmThrowInternalError("bad sparse switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001071 return kInstrLen;
1072 }
1073
1074 size = *switchData++;
1075 assert(size > 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001076
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001077 /* The keys are guaranteed to be aligned on a 32-bit boundary;
1078 * we can treat them as a native int array.
1079 */
1080 keys = (const s4*) switchData;
1081 assert(((u4)keys & 0x3) == 0);
1082
1083 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1084 * we can treat them as a native int array.
1085 */
1086 entries = keys + size;
1087 assert(((u4)entries & 0x3) == 0);
1088
1089 /*
Andy McFadden62f19152009-10-21 16:59:31 -07001090 * Binary-search through the array of keys, which are guaranteed to
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001091 * be sorted low-to-high.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001092 */
Andy McFadden62f19152009-10-21 16:59:31 -07001093 int lo = 0;
1094 int hi = size - 1;
1095 while (lo <= hi) {
1096 int mid = (lo + hi) >> 1;
1097
1098 s4 foundVal = s4FromSwitchData(&keys[mid]);
1099 if (testVal < foundVal) {
1100 hi = mid - 1;
1101 } else if (testVal > foundVal) {
1102 lo = mid + 1;
1103 } else {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001104 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
Andy McFadden62f19152009-10-21 16:59:31 -07001105 testVal, mid, s4FromSwitchData(&entries[mid]));
1106 return s4FromSwitchData(&entries[mid]);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001107 }
1108 }
1109
1110 LOGVV("Value %d not found in switch\n", testVal);
1111 return kInstrLen;
1112}
1113
1114/*
Andy McFadden6f214502009-06-30 16:14:30 -07001115 * Copy data for a fill-array-data instruction. On a little-endian machine
1116 * we can just do a memcpy(), on a big-endian system we have work to do.
1117 *
1118 * The trick here is that dexopt has byte-swapped each code unit, which is
1119 * exactly what we want for short/char data. For byte data we need to undo
1120 * the swap, and for 4- or 8-byte values we need to swap pieces within
1121 * each word.
1122 */
1123static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
1124{
1125#if __BYTE_ORDER == __LITTLE_ENDIAN
1126 memcpy(dest, src, size*width);
1127#else
1128 int i;
1129
1130 switch (width) {
1131 case 1:
1132 /* un-swap pairs of bytes as we go */
1133 for (i = (size-1) & ~1; i >= 0; i -= 2) {
1134 ((u1*)dest)[i] = ((u1*)src)[i+1];
1135 ((u1*)dest)[i+1] = ((u1*)src)[i];
1136 }
1137 /*
1138 * "src" is padded to end on a two-byte boundary, but we don't want to
1139 * assume "dest" is, so we handle odd length specially.
1140 */
1141 if ((size & 1) != 0) {
1142 ((u1*)dest)[size-1] = ((u1*)src)[size];
1143 }
1144 break;
1145 case 2:
1146 /* already swapped correctly */
1147 memcpy(dest, src, size*width);
1148 break;
1149 case 4:
1150 /* swap word halves */
1151 for (i = 0; i < (int) size; i++) {
1152 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
1153 }
1154 break;
1155 case 8:
1156 /* swap word halves and words */
1157 for (i = 0; i < (int) (size << 1); i += 2) {
1158 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
1159 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
1160 }
1161 break;
1162 default:
1163 LOGE("Unexpected width %d in copySwappedArrayData\n", width);
1164 dvmAbort();
1165 break;
1166 }
1167#endif
1168}
1169
1170/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001171 * Fill the array with predefined constant values.
1172 *
1173 * Returns true if job is completed, otherwise false to indicate that
1174 * an exception has been thrown.
1175 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001176bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001177{
1178 u2 width;
1179 u4 size;
1180
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001181 if (arrayObj == NULL) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001182 dvmThrowNullPointerException(NULL);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001183 return false;
1184 }
Barry Hayes7dc96602010-02-24 09:19:07 -08001185 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
1186 CLASS_ISOBJECTARRAY));
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001187
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001188 /*
1189 * Array data table format:
1190 * ushort ident = 0x0300 magic value
1191 * ushort width width of each element in the table
1192 * uint size number of elements in the table
1193 * ubyte data[size*width] table of data values (may contain a single-byte
1194 * padding at the end)
1195 *
1196 * Total size is 4+(width * size + 1)/2 16-bit code units.
1197 */
1198 if (arrayData[0] != kArrayDataSignature) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001199 dvmThrowInternalError("bad array data magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001200 return false;
1201 }
1202
1203 width = arrayData[1];
1204 size = arrayData[2] | (((u4)arrayData[3]) << 16);
1205
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001206 if (size > arrayObj->length) {
Dan Bornstein47f58252011-03-07 14:54:14 -08001207 dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001208 return false;
1209 }
Andy McFadden6f214502009-06-30 16:14:30 -07001210 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001211 return true;
1212}
1213
1214/*
1215 * Find the concrete method that corresponds to "methodIdx". The code in
1216 * "method" is executing invoke-method with "thisClass" as its first argument.
1217 *
1218 * Returns NULL with an exception raised on failure.
1219 */
1220Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
1221 const Method* method, DvmDex* methodClassDex)
1222{
1223 Method* absMethod;
1224 Method* methodToCall;
1225 int i, vtableIndex;
1226
1227 /*
1228 * Resolve the method. This gives us the abstract method from the
1229 * interface class declaration.
1230 */
1231 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
1232 if (absMethod == NULL) {
1233 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
1234 if (absMethod == NULL) {
1235 LOGV("+ unknown method\n");
1236 return NULL;
1237 }
1238 }
1239
1240 /* make sure absMethod->methodIndex means what we think it means */
1241 assert(dvmIsAbstractMethod(absMethod));
1242
1243 /*
1244 * Run through the "this" object's iftable. Find the entry for
1245 * absMethod's class, then use absMethod->methodIndex to find
1246 * the method's entry. The value there is the offset into our
1247 * vtable of the actual method to execute.
1248 *
1249 * The verifier does not guarantee that objects stored into
1250 * interface references actually implement the interface, so this
1251 * check cannot be eliminated.
1252 */
1253 for (i = 0; i < thisClass->iftableCount; i++) {
1254 if (thisClass->iftable[i].clazz == absMethod->clazz)
1255 break;
1256 }
1257 if (i == thisClass->iftableCount) {
1258 /* impossible in verified DEX, need to check for it in unverified */
Dan Bornstein70b00ab2011-02-23 14:11:27 -08001259 dvmThrowIncompatibleClassChangeError("interface not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001260 return NULL;
1261 }
1262
1263 assert(absMethod->methodIndex <
1264 thisClass->iftable[i].clazz->virtualMethodCount);
1265
1266 vtableIndex =
1267 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1268 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1269 methodToCall = thisClass->vtable[vtableIndex];
1270
1271#if 0
1272 /* this can happen when there's a stale class file */
1273 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001274 dvmThrowAbstractMethodError("interface method not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001275 return NULL;
1276 }
1277#else
1278 assert(!dvmIsAbstractMethod(methodToCall) ||
1279 methodToCall->nativeFunc != NULL);
1280#endif
1281
1282 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1283 absMethod->clazz->descriptor, absMethod->name,
1284 methodToCall->clazz->descriptor, methodToCall->name);
1285 assert(methodToCall != NULL);
1286
1287 return methodToCall;
1288}
1289
1290
Andy McFaddenb51ea112009-05-08 16:50:17 -07001291
1292/*
1293 * Helpers for dvmThrowVerificationError().
1294 *
1295 * Each returns a newly-allocated string.
1296 */
1297#define kThrowShow_accessFromClass 1
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001298static char* classNameFromIndex(const Method* method, int ref,
1299 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001300{
1301 static const int kBufLen = 256;
1302 const DvmDex* pDvmDex = method->clazz->pDvmDex;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001303
1304 if (refType == VERIFY_ERROR_REF_FIELD) {
1305 /* get class ID from field ID */
1306 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1307 ref = pFieldId->classIdx;
1308 } else if (refType == VERIFY_ERROR_REF_METHOD) {
1309 /* get class ID from method ID */
1310 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1311 ref = pMethodId->classIdx;
1312 }
1313
Andy McFaddenb51ea112009-05-08 16:50:17 -07001314 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
Elliott Hughes50169662010-11-22 13:14:23 -08001315 char* dotClassName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001316 if (flags == 0)
1317 return dotClassName;
1318
1319 char* result = (char*) malloc(kBufLen);
1320
1321 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001322 char* dotFromName =
1323 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001324 snprintf(result, kBufLen, "tried to access class %s from class %s",
1325 dotClassName, dotFromName);
1326 free(dotFromName);
1327 } else {
1328 assert(false); // should've been caught above
1329 result[0] = '\0';
1330 }
1331
1332 free(dotClassName);
1333 return result;
1334}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001335static char* fieldNameFromIndex(const Method* method, int ref,
1336 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001337{
1338 static const int kBufLen = 256;
1339 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1340 const DexFieldId* pFieldId;
1341 const char* className;
1342 const char* fieldName;
1343
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001344 if (refType != VERIFY_ERROR_REF_FIELD) {
1345 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1346 return NULL; /* no message */
1347 }
1348
Andy McFaddenb51ea112009-05-08 16:50:17 -07001349 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1350 className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1351 fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1352
Elliott Hughes50169662010-11-22 13:14:23 -08001353 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001354 char* result = (char*) malloc(kBufLen);
1355
1356 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001357 char* dotFromName =
1358 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001359 snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1360 dotName, fieldName, dotFromName);
1361 free(dotFromName);
1362 } else {
1363 snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1364 }
1365
1366 free(dotName);
1367 return result;
1368}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001369static char* methodNameFromIndex(const Method* method, int ref,
1370 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001371{
1372 static const int kBufLen = 384;
1373 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1374 const DexMethodId* pMethodId;
1375 const char* className;
1376 const char* methodName;
1377
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001378 if (refType != VERIFY_ERROR_REF_METHOD) {
1379 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1380 return NULL; /* no message */
1381 }
1382
Andy McFaddenb51ea112009-05-08 16:50:17 -07001383 pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1384 className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1385 methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1386
Elliott Hughes50169662010-11-22 13:14:23 -08001387 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001388 char* result = (char*) malloc(kBufLen);
1389
1390 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001391 char* dotFromName =
1392 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001393 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1394 snprintf(result, kBufLen,
1395 "tried to access method %s.%s:%s from class %s",
1396 dotName, methodName, desc, dotFromName);
1397 free(dotFromName);
1398 free(desc);
1399 } else {
1400 snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1401 }
1402
1403 free(dotName);
1404 return result;
1405}
1406
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001407/*
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001408 * Throw an exception for a problem identified by the verifier.
1409 *
1410 * This is used by the invoke-verification-error instruction. It always
1411 * throws an exception.
1412 *
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001413 * "kind" indicates the kind of failure encountered by the verifier. It
1414 * has two parts, an error code and an indication of the reference type.
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001415 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001416void dvmThrowVerificationError(const Method* method, int kind, int ref)
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001417{
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001418 const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1419 VerifyError errorKind = kind & ~typeMask;
1420 VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
Dan Bornsteina3b35122011-03-03 16:17:37 -08001421 ClassObject* exceptionClass = gDvm.exVerifyError;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001422 char* msg = NULL;
1423
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001424 switch ((VerifyError) errorKind) {
Andy McFaddenb51ea112009-05-08 16:50:17 -07001425 case VERIFY_ERROR_NO_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001426 exceptionClass = gDvm.exNoClassDefFoundError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001427 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001428 break;
1429 case VERIFY_ERROR_NO_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001430 exceptionClass = gDvm.exNoSuchFieldError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001431 msg = fieldNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001432 break;
1433 case VERIFY_ERROR_NO_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001434 exceptionClass = gDvm.exNoSuchMethodError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001435 msg = methodNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001436 break;
1437 case VERIFY_ERROR_ACCESS_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001438 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001439 msg = classNameFromIndex(method, ref, refType,
1440 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001441 break;
1442 case VERIFY_ERROR_ACCESS_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001443 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001444 msg = fieldNameFromIndex(method, ref, refType,
1445 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001446 break;
1447 case VERIFY_ERROR_ACCESS_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001448 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001449 msg = methodNameFromIndex(method, ref, refType,
1450 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001451 break;
1452 case VERIFY_ERROR_CLASS_CHANGE:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001453 exceptionClass = gDvm.exIncompatibleClassChangeError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001454 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001455 break;
1456 case VERIFY_ERROR_INSTANTIATION:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001457 exceptionClass = gDvm.exInstantiationError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001458 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001459 break;
1460
1461 case VERIFY_ERROR_GENERIC:
1462 /* generic VerifyError; use default exception, no message */
1463 break;
1464 case VERIFY_ERROR_NONE:
1465 /* should never happen; use default exception */
1466 assert(false);
1467 msg = strdup("weird - no error specified");
1468 break;
1469
1470 /* no default clause -- want warning if enum updated */
1471 }
1472
Dan Bornstein0b8b2932011-03-04 11:53:40 -08001473 dvmThrowException(exceptionClass, msg);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001474 free(msg);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001475}
1476
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001477/*
buzbee9a3147c2011-03-02 15:43:48 -08001478 * Update interpBreak. If there is an active break when
1479 * we're done, set altHandlerTable. Otherwise, revert to
1480 * the non-breaking table base.
buzbeecb3081f2011-01-14 13:37:31 -08001481 */
buzbee9a3147c2011-03-02 15:43:48 -08001482void dvmUpdateInterpBreak(Thread* thread, int newBreak, int newMode,
1483 bool enable)
buzbeecb3081f2011-01-14 13:37:31 -08001484{
buzbee9a3147c2011-03-02 15:43:48 -08001485 InterpBreak oldValue, newValue;
1486
1487 // Do not use this routine for suspend updates. See below.
1488 assert((newBreak & kInterpSuspendBreak) == 0);
buzbeecb3081f2011-01-14 13:37:31 -08001489
1490 do {
buzbee9a3147c2011-03-02 15:43:48 -08001491 oldValue = newValue = thread->interpBreak;
1492 if (enable) {
1493 newValue.ctl.breakFlags |= newBreak;
1494 newValue.ctl.subMode |= newMode;
1495 } else {
1496 newValue.ctl.breakFlags &= ~newBreak;
1497 newValue.ctl.subMode &= ~newMode;
1498 }
1499 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1500 thread->altHandlerTable : thread->mainHandlerTable;
1501 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1502 &thread->interpBreak.all) != 0);
1503}
1504
1505/*
1506 * Update the normal and debugger suspend counts for a thread.
1507 * threadSuspendCount must be acquired before calling this to
1508 * ensure a clean update of suspendCount, dbgSuspendCount and
1509 * sumThreadSuspendCount. suspendCount & dbgSuspendCount must
1510 * use the atomic update to avoid conflict with writes to the
1511 * other fields in interpBreak.
1512 *
1513 * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
1514 * Move under WITH_JIT ifdefs.
1515*/
1516void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
1517{
1518 InterpBreak oldValue, newValue;
1519
1520 do {
1521 oldValue = newValue = thread->interpBreak;
1522 newValue.ctl.suspendCount += delta;
1523 newValue.ctl.dbgSuspendCount += dbgDelta;
1524 assert(newValue.ctl.suspendCount >= newValue.ctl.dbgSuspendCount);
1525 if (newValue.ctl.suspendCount > 0) {
1526 newValue.ctl.breakFlags |= kInterpSuspendBreak;
1527 } else {
1528 newValue.ctl.breakFlags &= ~kInterpSuspendBreak;
1529 }
1530 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1531 thread->altHandlerTable : thread->mainHandlerTable;
1532 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1533 &thread->interpBreak.all) != 0);
1534
1535 // Update the global suspend count total
1536 gDvm.sumThreadSuspendCount += delta;
1537}
1538
1539/*
1540 * Update interpBreak for all threads.
1541 */
1542void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable)
1543{
1544 Thread* self = dvmThreadSelf();
1545 Thread* thread;
1546
1547 dvmLockThreadList(self);
1548 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1549 dvmUpdateInterpBreak(thread, newBreak, newMode, enable);
1550 }
1551 dvmUnlockThreadList();
buzbeecb3081f2011-01-14 13:37:31 -08001552}
1553
1554/*
buzbee9f601a92011-02-11 17:48:20 -08001555 * One-time initialization at thread creation. Here we initialize
1556 * useful constants.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001557 */
buzbee9f601a92011-02-11 17:48:20 -08001558void dvmInitInterpreterState(Thread* self)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001559{
Ben Chengba4fc8b2009-06-01 13:00:29 -07001560#if defined(WITH_JIT)
1561 /* Interpreter entry points from compiled code */
1562 extern void dvmJitToInterpNormal();
1563 extern void dvmJitToInterpNoChain();
1564 extern void dvmJitToInterpPunt();
1565 extern void dvmJitToInterpSingleStep();
Ben Cheng40094c12010-02-24 20:58:44 -08001566 extern void dvmJitToInterpTraceSelect();
Jeff Hao97319a82009-08-12 16:57:15 -07001567#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001568 extern void dvmJitToInterpBackwardBranch();
Jeff Hao97319a82009-08-12 16:57:15 -07001569#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001570 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001571 * Reserve a static entity here to quickly setup runtime contents as
1572 * gcc will issue block copy instructions.
1573 */
1574 static struct JitToInterpEntries jitToInterpEntries = {
1575 dvmJitToInterpNormal,
1576 dvmJitToInterpNoChain,
1577 dvmJitToInterpPunt,
1578 dvmJitToInterpSingleStep,
Ben Cheng40094c12010-02-24 20:58:44 -08001579 dvmJitToInterpTraceSelect,
Jeff Hao97319a82009-08-12 16:57:15 -07001580#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001581 dvmJitToInterpBackwardBranch,
buzbee9f601a92011-02-11 17:48:20 -08001582#else
1583 NULL,
Jeff Hao97319a82009-08-12 16:57:15 -07001584#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001585 };
buzbee9f601a92011-02-11 17:48:20 -08001586#endif
Ben Cheng7a0bcd02010-01-22 16:45:45 -08001587
buzbee9f601a92011-02-11 17:48:20 -08001588 // Begin initialization
1589 self->cardTable = gDvm.biasedCardTableBase;
buzbee9f601a92011-02-11 17:48:20 -08001590#if defined(WITH_JIT)
buzbee9a3147c2011-03-02 15:43:48 -08001591 // One-time initializations
buzbee9f601a92011-02-11 17:48:20 -08001592 self->jitToInterpEntries = jitToInterpEntries;
1593 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
buzbee9f601a92011-02-11 17:48:20 -08001594 self->pProfileCountdown = &gDvmJit.profileCountdown;
buzbee9a3147c2011-03-02 15:43:48 -08001595 // Jit state that can change
1596 dvmJitUpdateState();
buzbee9f601a92011-02-11 17:48:20 -08001597#endif
1598
1599}
1600
buzbeea7d59bb2011-02-24 09:38:17 -08001601/*
1602 * Inter-instruction handler invoked in between instruction interpretations
1603 * to handle exceptional events such as debugging housekeeping, instruction
buzbee9a3147c2011-03-02 15:43:48 -08001604 * count profiling, JIT trace building, etc. Dalvik PC has been exported
1605 * prior to call, but Thread copy of dPC & fp are not current.
buzbeea7d59bb2011-02-24 09:38:17 -08001606 */
buzbee9a3147c2011-03-02 15:43:48 -08001607void dvmCheckBefore(const u2 *pc, const u4 *fp, Thread* self)
buzbeea7d59bb2011-02-24 09:38:17 -08001608{
buzbee9a3147c2011-03-02 15:43:48 -08001609 const Method* method = self->interpSave.method;
1610 assert(self->interpBreak.ctl.breakFlags != 0);
1611 assert(pc >= method->insns && pc <
1612 method->insns + dvmGetMethodInsnsSize(method));
1613
1614#if 0
1615 /*
1616 * When we hit a specific method, enable verbose instruction logging.
1617 * Sometimes it's helpful to use the debugger attach as a trigger too.
1618 */
1619 if (*pIsMethodEntry) {
1620 static const char* cd = "Landroid/test/Arithmetic;";
1621 static const char* mn = "shiftTest2";
1622 static const char* sg = "()V";
1623
1624 if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/
1625 strcmp(method->clazz->descriptor, cd) == 0 &&
1626 strcmp(method->name, mn) == 0 &&
1627 strcmp(method->shorty, sg) == 0)
1628 {
1629 LOGW("Reached %s.%s, enabling verbose mode\n",
1630 method->clazz->descriptor, method->name);
1631 android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE);
1632 dumpRegs(method, fp, true);
1633 }
1634
1635 if (!gDvm.debuggerActive)
1636 *pIsMethodEntry = false;
1637 }
1638#endif
1639
1640 /* Suspend pending? */
1641 if (self->interpBreak.ctl.suspendCount) {
buzbeec4a8caf2011-03-24 12:56:41 -07001642 // Are we are a safe point?
1643 int flags;
1644 flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
1645 if (flags & VERIFY_GC_INST_MASK) {
1646 dvmExportPC(pc, fp);
1647 dvmCheckSuspendPending(self);
1648 }
buzbee9a3147c2011-03-02 15:43:48 -08001649 }
1650
1651 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
1652 dvmUpdateDebugger(method, pc, fp,
1653 self->debugIsMethodEntry, self);
1654 }
1655 if (gDvm.instructionCountEnableCount != 0) {
1656 /*
1657 * Count up the #of executed instructions. This isn't synchronized
1658 * for thread-safety; if we need that we should make this
1659 * thread-local and merge counts into the global area when threads
1660 * exit (perhaps suspending all other threads GC-style and pulling
1661 * the data out of them).
1662 */
1663 gDvm.executedInstrCounts[GET_OPCODE(*pc)]++;
1664 }
1665
1666
1667#if defined(WITH_TRACKREF_CHECKS)
1668 dvmInterpCheckTrackedRefs(self, method,
1669 self->interpSave.debugTrackedRefStart);
1670#endif
1671
1672#if defined(WITH_JIT)
1673 // Does the JIT need anything done now?
1674 if (self->interpBreak.ctl.breakFlags & kInterpJitBreak) {
1675 // Are we building a trace?
1676 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
1677 dvmCheckJit(pc, self);
1678 }
1679
1680#if defined(WITH_SELF_VERIFICATION)
1681 // Are we replaying a trace?
1682 if (self->interpBreak.ctl.subMode & kSubModeJitSV) {
1683 dvmCheckSelfVerification(pc, self);
1684 }
1685#endif
1686 }
1687#endif
1688
1689 /*
1690 * SingleStep processing. NOTE: must be the last here to allow
1691 * preceeding special case handler to manipulate single-step count.
1692 */
1693 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
1694 if (self->singleStepCount == 0) {
1695 // We've exhausted our single step count
1696 dvmUpdateInterpBreak(self, kInterpSingleStep, kSubModeNormal,
1697 false /* remove */);
1698#if defined(WITH_JIT)
1699#if 0
1700 /*
1701 * For debugging. If jitResumeDPC is non-zero, then
1702 * we expect to return to a trace in progress. There
1703 * are valid reasons why we wouldn't (such as an exception
1704 * throw), but here we can keep track.
1705 */
1706 if (self->jitResumeDPC != NULL) {
1707 if (self->jitResumeDPC == pc) {
1708 if (self->jitResumeNPC != NULL) {
1709 LOGD("SS return to trace - pc:0x%x to 0x:%x",
1710 (int)pc, (int)self->jitResumeNPC);
1711 } else {
1712 LOGD("SS return to interp - pc:0x%x",(int)pc);
1713 }
1714 } else {
1715 LOGD("SS failed to return. Expected 0x%x, now at 0x%x",
1716 (int)self->jitResumeDPC, (int)pc);
1717 }
1718 }
1719#endif
1720 // If we've got a native return and no other reasons to
1721 // remain in singlestep/break mode, do a long jump
1722 if (self->jitResumeNPC != NULL &&
1723 self->interpBreak.ctl.breakFlags == 0) {
1724 assert(self->jitResumeDPC == pc);
1725 self->jitResumeDPC = NULL;
1726 dvmJitResumeTranslation(self, pc, fp);
1727 // Doesn't return
1728 dvmAbort();
1729 }
1730 self->jitResumeDPC = NULL;
1731#endif
1732 } else {
1733 self->singleStepCount--;
1734#if defined(WITH_JIT)
1735 if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) {
1736 /*
1737 * Direct return to an existing translation following a
1738 * single step is valid only if we step once. If we're
1739 * here, an additional step was added so we need to invalidate
1740 * the return to translation.
1741 */
1742 self->jitResumeNPC = NULL;
1743 }
1744#endif
1745 }
1746 }
buzbeea7d59bb2011-02-24 09:38:17 -08001747}
buzbee9f601a92011-02-11 17:48:20 -08001748
1749/*
buzbee9a3147c2011-03-02 15:43:48 -08001750 * Main interpreter loop entry point.
buzbee9f601a92011-02-11 17:48:20 -08001751 *
1752 * This begins executing code at the start of "method". On exit, "pResult"
1753 * holds the return value of the method (or, if "method" returns NULL, it
1754 * holds an undefined value).
1755 *
1756 * The interpreted stack frame, which holds the method arguments, has
1757 * already been set up.
1758 */
1759void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1760{
buzbee9f601a92011-02-11 17:48:20 -08001761 InterpSaveState interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001762 int savedBreakFlags;
1763 int savedSubModes;
1764
buzbee9f601a92011-02-11 17:48:20 -08001765#if defined(WITH_JIT)
1766 /* Target-specific save/restore */
1767 extern void dvmJitCalleeSave(double *saveArea);
1768 extern void dvmJitCalleeRestore(double *saveArea);
1769 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
Ben Cheng7a2697d2010-06-07 13:44:23 -07001770 /*
1771 * If the previous VM left the code cache through single-stepping the
1772 * inJitCodeCache flag will be set when the VM is re-entered (for example,
1773 * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1774 * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1775 * assert that self->inJitCodeCache is NULL here.
1776 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001777#endif
1778
buzbee9f601a92011-02-11 17:48:20 -08001779 /*
1780 * Save interpreter state from previous activation, linking
1781 * new to last.
1782 */
1783 interpSaveState = self->interpSave;
1784 self->interpSave.prev = &interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001785 /*
1786 * Strip out and save any flags that should not be inherited by
1787 * nested interpreter activation.
1788 */
1789 savedBreakFlags = self->interpBreak.ctl.breakFlags & LOCAL_BREAKFLAGS;
1790 savedSubModes = self->interpBreak.ctl.subMode & LOCAL_SUBMODE;
1791 if (savedBreakFlags | savedSubModes) {
1792 dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
1793 false /*disable*/);
1794 }
buzbee9f601a92011-02-11 17:48:20 -08001795#if defined(WITH_JIT)
1796 dvmJitCalleeSave(calleeSave);
1797#endif
1798
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001799
1800#if defined(WITH_TRACKREF_CHECKS)
buzbeeef5db622011-02-22 14:01:46 -08001801 self->interpSave.debugTrackedRefStart =
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001802 dvmReferenceTableEntries(&self->internalLocalRefTable);
1803#endif
buzbee9f601a92011-02-11 17:48:20 -08001804 self->debugIsMethodEntry = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001805#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001806 dvmJitCalleeSave(calleeSave);
Ben Chenga4973592010-03-31 11:59:18 -07001807 /* Initialize the state to kJitNot */
buzbee9f601a92011-02-11 17:48:20 -08001808 self->jitState = kJitNot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001809#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001810
1811 /*
1812 * Initialize working state.
1813 *
1814 * No need to initialize "retval".
1815 */
buzbee9f601a92011-02-11 17:48:20 -08001816 self->interpSave.method = method;
1817 self->interpSave.fp = (u4*) self->curFrame;
1818 self->interpSave.pc = method->insns;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001819
1820 assert(!dvmIsNativeMethod(method));
1821
1822 /*
1823 * Make sure the class is ready to go. Shouldn't be possible to get
1824 * here otherwise.
1825 */
1826 if (method->clazz->status < CLASS_INITIALIZING ||
1827 method->clazz->status == CLASS_ERROR)
1828 {
1829 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1830 method->clazz->descriptor, method->clazz->status);
1831 dvmDumpThread(self, false);
1832 dvmAbort();
1833 }
1834
buzbee9a3147c2011-03-02 15:43:48 -08001835 typedef void (*Interpreter)(Thread*);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001836 Interpreter stdInterp;
1837 if (gDvm.executionMode == kExecutionModeInterpFast)
1838 stdInterp = dvmMterpStd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001839#if defined(WITH_JIT)
1840 else if (gDvm.executionMode == kExecutionModeJit)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001841 stdInterp = dvmMterpStd;
1842#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001843 else
buzbee9a3147c2011-03-02 15:43:48 -08001844 stdInterp = dvmInterpretPortable;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001845
buzbee9a3147c2011-03-02 15:43:48 -08001846 // Call the interpreter
1847 (*stdInterp)(self);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001848
buzbee9f601a92011-02-11 17:48:20 -08001849 *pResult = self->retval;
1850
1851 /* Restore interpreter state from previous activation */
1852 self->interpSave = interpSaveState;
Bill Buzbee342806d2009-12-08 12:37:13 -08001853#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001854 dvmJitCalleeRestore(calleeSave);
Bill Buzbee342806d2009-12-08 12:37:13 -08001855#endif
buzbee9a3147c2011-03-02 15:43:48 -08001856 if (savedBreakFlags | savedSubModes) {
1857 dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
1858 true /*enable*/);
1859 }
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001860}