12ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
22ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
32ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
42ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
52ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * you may not use this file except in compliance with the License.
62ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * You may obtain a copy of the License at
72ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
82ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
92ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * See the License for the specific language governing permissions and
142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * limitations under the License.
152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
1689c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project
172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Main interpreter entry point and support functions.
192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The entry point selects the "standard" or "debug" interpreter and
212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * facilitates switching between them.  The standard interpreter may
222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * use the "fast" or "portable" implementation.
232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
240d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden * Some debugger support functions are included here.
252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#include "Dalvik.h"
272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#include "interp/InterpDefs.h"
289a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
299a3147c7412f4794434b4c2604aa2ba784867774buzbee#include "interp/Jit.h"
309a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *      Debugger support
362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden// fwd
401e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic BreakpointSet* dvmBreakpointSetAlloc();
4196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetFree(BreakpointSet* pSet);
4296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
431813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#if defined(WITH_JIT)
441813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro/* Target-specific save/restore */
451813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitCalleeSave(double *saveArea);
461813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitCalleeRestore(double *saveArea);
471813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro/* Interpreter entry points from compiled code */
481813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpNormal();
491813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpNoChain();
501813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpPunt();
511813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpSingleStep();
521813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpTraceSelect();
531813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#if defined(WITH_SELF_VERIFICATION)
541813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpBackwardBranch();
551813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#endif
561813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#endif
571813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro
582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
5996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Initialize global breakpoint structures.
6096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
611e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmBreakpointStartup()
6296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
6396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    gDvm.breakpointSet = dvmBreakpointSetAlloc();
6496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return (gDvm.breakpointSet != NULL);
6596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
6696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
6796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
6896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Free resources.
6996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
701e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmBreakpointShutdown()
7196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
7296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetFree(gDvm.breakpointSet);
7396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
7496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
7596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
7696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
7796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This represents a breakpoint inserted in the instruction stream.
782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
7996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The debugger may ask us to create the same breakpoint multiple times.
8096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * We only remove the breakpoint when the last instance is cleared.
8196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
82d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct Breakpoint {
83d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    Method*     method;                 /* method we're associated with */
8496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    u2*         addr;                   /* absolute memory address */
859a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    u1          originalOpcode;         /* original 8-bit opcode value */
8696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int         setCount;               /* #of times this breakpoint was set */
87d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro};
8896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
8996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
9096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Set of breakpoints.
9196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
9296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstruct BreakpointSet {
9396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* grab lock before reading or writing anything else in here */
9496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    pthread_mutex_t lock;
9596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
9696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* vector of breakpoint structures */
9796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int         alloc;
9896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int         count;
9996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    Breakpoint* breakpoints;
10096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden};
10196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
10296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
10396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Initialize a BreakpointSet.  Initially empty.
10496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
1051e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic BreakpointSet* dvmBreakpointSetAlloc()
10696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
10796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
10896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
10996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmInitMutex(&pSet->lock);
11096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* leave the rest zeroed -- will alloc on first use */
11196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
11296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return pSet;
11396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
11496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
11596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
11696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Free storage associated with a BreakpointSet.
11796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
11896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetFree(BreakpointSet* pSet)
11996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
12096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (pSet == NULL)
12196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        return;
12296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
12396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    free(pSet->breakpoints);
12496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    free(pSet);
12596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
12696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
12796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
12896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Lock the breakpoint set.
129d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden *
130d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * It's not currently necessary to switch to VMWAIT in the event of
131d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * contention, because nothing in here can block.  However, it's possible
132d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * that the bytecode-updater code could become fancier in the future, so
133d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * we do the trylock dance as a bit of future-proofing.
13496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
13596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetLock(BreakpointSet* pSet)
13696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
137d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    if (dvmTryLockMutex(&pSet->lock) != 0) {
138d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        Thread* self = dvmThreadSelf();
1395617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro        ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
140d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        dvmLockMutex(&pSet->lock);
141d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        dvmChangeStatus(self, oldStatus);
142d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    }
14396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
14496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
14596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
14696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Unlock the breakpoint set.
14796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
14896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetUnlock(BreakpointSet* pSet)
14996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
15096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmUnlockMutex(&pSet->lock);
15196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
15296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
15396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
15496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Return the #of breakpoints.
15596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
15696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic int dvmBreakpointSetCount(const BreakpointSet* pSet)
15796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
15896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return pSet->count;
15996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
16096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
16196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
16296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * See if we already have an entry for this address.
16396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
16496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
16596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
16696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns the index of the breakpoint entry, or -1 if not found.
16796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
16896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
16996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
17096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int i;
17196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
17296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    for (i = 0; i < pSet->count; i++) {
17396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        Breakpoint* pBreak = &pSet->breakpoints[i];
17496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (pBreak->addr == addr)
17596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            return i;
17696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
17796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
17896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return -1;
17996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
18096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
18196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
18296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Retrieve the opcode that was originally at the specified location.
18396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
18496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
18596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
18696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" with the opcode in *pOrig on success.
18796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
1889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornsteinstatic bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
18996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const u2* addr, u1* pOrig)
19096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
19196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int idx = dvmBreakpointSetFind(pSet, addr);
19296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (idx < 0)
19396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        return false;
19496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
1959a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    *pOrig = pSet->breakpoints[idx].originalOpcode;
19696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return true;
19796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
19896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
19996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
200da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * Check the opcode.  If it's a "magic" NOP, indicating the start of
201da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * switch or array data in the instruction stream, we don't want to set
202da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * a breakpoint.
203da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden *
204da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * This can happen because the line number information dx generates
205da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * associates the switch data with the switch statement's line number,
206da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * and some debuggers put breakpoints at every address associated with
207da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * a given line.  The result is that the breakpoint stomps on the NOP
208da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * instruction that doubles as a data table magic number, and an explicit
209da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * check in the interpreter results in an exception being thrown.
210da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden *
211da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * We don't want to simply refuse to add the breakpoint to the table,
212da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * because that confuses the housekeeping.  We don't want to reject the
213da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * debugger's event request, and we want to be sure that there's exactly
214da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * one un-set operation for every set op.
215da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden */
216da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFaddenstatic bool instructionIsMagicNop(const u2* addr)
217da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden{
218da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden    u2 curVal = *addr;
2199a3147c7412f4794434b4c2604aa2ba784867774buzbee    return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0);
220da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden}
221da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden
222da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden/*
22396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Add a breakpoint at a specific address.  If the address is already
22496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * present in the table, this just increments the count.
22596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
22696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * For a new entry, this will extract and preserve the current opcode from
22796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * the instruction stream, and replace it with a breakpoint opcode.
22896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
22996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
23096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
23196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success.
23296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
23396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
23496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    unsigned int instrOffset)
23596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
23696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const int kBreakpointGrowth = 10;
23796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const u2* addr = method->insns + instrOffset;
23896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int idx = dvmBreakpointSetFind(pSet, addr);
23996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    Breakpoint* pBreak;
24096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
24196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (idx < 0) {
24296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (pSet->count == pSet->alloc) {
24396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            int newSize = pSet->alloc + kBreakpointGrowth;
24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            Breakpoint* newVec;
24596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
24692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("+++ increasing breakpoint set size to %d", newSize);
24796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
24896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            /* pSet->breakpoints will be NULL on first entry */
249fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
25096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            if (newVec == NULL)
25196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                return false;
25296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
25396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->breakpoints = newVec;
25496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->alloc = newSize;
25596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
25696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
25796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak = &pSet->breakpoints[pSet->count++];
258d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        pBreak->method = method;
25996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak->addr = (u2*)addr;
2609a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        pBreak->originalOpcode = *(u1*)addr;
26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak->setCount = 1;
26296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        /*
26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden         * Change the opcode.  We must ensure that the BreakpointSet
26596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden         * updates happen before we change the opcode.
266d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         *
267d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * If the method has not been verified, we do NOT insert the
268d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * breakpoint yet, since that will screw up the verifier.  The
269d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * debugger is allowed to insert breakpoints in unverified code,
270d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * but since we don't execute unverified code we don't need to
271d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * alter the bytecode yet.
272d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         *
273c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden         * The class init code will "flush" all pending opcode writes
274c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden         * before verification completes.
27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden         */
27696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        assert(*(u1*)addr != OP_BREAKPOINT);
277d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        if (dvmIsClassVerified(method->clazz)) {
27892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("Class %s verified, adding breakpoint at %p",
279d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden                method->clazz->descriptor, addr);
280da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden            if (instructionIsMagicNop(addr)) {
28192c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                ALOGV("Refusing to set breakpoint on %04x at %s.%s + %#x",
282da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden                    *addr, method->clazz->descriptor, method->name,
283da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden                    instrOffset);
284da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden            } else {
2856e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden                ANDROID_MEMBAR_FULL();
286da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden                dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
287da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden                    OP_BREAKPOINT);
288da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden            }
289d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        } else {
29092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("Class %s NOT verified, deferring breakpoint at %p",
291d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden                method->clazz->descriptor, addr);
292d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        }
29396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    } else {
294d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        /*
295c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden         * Breakpoint already exists, just increase the count.
296d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         */
297c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden        pBreak = &pSet->breakpoints[idx];
298c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden        pBreak->setCount++;
29996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
30096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
30196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return true;
30296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
30396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
30496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
30596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Remove one instance of the specified breakpoint.  When the count
30696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * reaches zero, the entry is removed from the table, and the original
30796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * opcode is restored.
30896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
30996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
31096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
31196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
31296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    unsigned int instrOffset)
31396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
31496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const u2* addr = method->insns + instrOffset;
31596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int idx = dvmBreakpointSetFind(pSet, addr);
31696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
31796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (idx < 0) {
31896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        /* breakpoint not found in set -- unexpected */
31996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (*(u1*)addr == OP_BREAKPOINT) {
320c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Unable to restore breakpoint opcode (%s.%s +%#x)",
32196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                method->clazz->descriptor, method->name, instrOffset);
32296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            dvmAbort();
32396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        } else {
324e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Breakpoint was already restored? (%s.%s +%#x)",
32596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                method->clazz->descriptor, method->name, instrOffset);
32696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
32796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    } else {
32896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        Breakpoint* pBreak = &pSet->breakpoints[idx];
32996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (pBreak->setCount == 1) {
33096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            /*
33196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden             * Must restore opcode before removing set entry.
332d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             *
333d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * If the breakpoint was never flushed, we could be ovewriting
334d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * a value with the same value.  Not a problem, though we
335d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * could end up causing a copy-on-write here when we didn't
336d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * need to.  (Not worth worrying about.)
33796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden             */
33896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
3399a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein                pBreak->originalOpcode);
3406e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden            ANDROID_MEMBAR_FULL();
34196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
34296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            if (idx != pSet->count-1) {
34396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                /* shift down */
34496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
34596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                    (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
34696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            }
34796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->count--;
34896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
34996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        } else {
35096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pBreak->setCount--;
35196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            assert(pBreak->setCount > 0);
35296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
35396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
35496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
35596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
35696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
357d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * Flush any breakpoints associated with methods in "clazz".  We want to
358d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * change the opcode, which might not have happened when the breakpoint
359d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * was initially set because the class was in the process of being
360d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * verified.
36196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
36296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
36396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
364d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFaddenstatic void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
36596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
36696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int i;
36796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    for (i = 0; i < pSet->count; i++) {
36896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        Breakpoint* pBreak = &pSet->breakpoints[i];
369d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        if (pBreak->method->clazz == clazz) {
370d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            /*
371d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * The breakpoint is associated with a method in this class.
372d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * It might already be there or it might not; either way,
373d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * flush it out.
374d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             */
37592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("Flushing breakpoint at %p for %s",
376d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden                pBreak->addr, clazz->descriptor);
377da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden            if (instructionIsMagicNop(pBreak->addr)) {
37892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                ALOGV("Refusing to flush breakpoint on %04x at %s.%s + %#x",
379e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro                    *pBreak->addr, pBreak->method->clazz->descriptor,
380e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro                    pBreak->method->name, pBreak->addr - pBreak->method->insns);
381da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden            } else {
382da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden                dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
383da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden                    OP_BREAKPOINT);
384da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden            }
38596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
38696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
38796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
38896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
38996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
39096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
39196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Do any debugger-attach-time initialization.
3922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
3931e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmInitBreakpoints()
3942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
39596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* quick sanity check */
39696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
39796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
39896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (dvmBreakpointSetCount(pSet) != 0) {
399e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("WARNING: %d leftover breakpoints", dvmBreakpointSetCount(pSet));
40096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        /* generally not good, but we can keep going */
40196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
40296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
4032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
4042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
4062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add an address to the list, putting it in the first non-empty slot.
4072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Sometimes the debugger likes to add two entries for one breakpoint.
4092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We add two entries here, so that we get the right behavior when it's
4102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * removed twice.
4112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This will only be run from the JDWP thread, and it will happen while
4132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we are updating the event list, which is synchronized.  We're guaranteed
4142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * to be the only one adding entries, and the lock ensures that nobody
4152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * will be trying to remove them while we're in here.
4162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "addr" is the absolute address of the breakpoint bytecode.
4182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
41996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmAddBreakAddr(Method* method, unsigned int instrOffset)
4202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
42196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
42296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
42396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetAdd(pSet, method, instrOffset);
42496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
4252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
4262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
4282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Remove an address from the list by setting the entry to NULL.
4292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This can be called from the JDWP thread (because the debugger has
4312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * cancelled the breakpoint) or from an event thread (because it's a
4322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * single-shot breakpoint, e.g. "run to line").  We only get here as
4332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the result of removing an entry from the event list, which is
4342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * synchronized, so it should not be possible for two threads to be
4352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * updating breakpoints at the same time.
4362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
43796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmClearBreakAddr(Method* method, unsigned int instrOffset)
4382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
43996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
44096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
44196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetRemove(pSet, method, instrOffset);
44296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
4432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
4442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
44596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
44696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Get the original opcode from under a breakpoint.
447fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden *
448fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * On SMP hardware it's possible one core might try to execute a breakpoint
449fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * after another core has cleared it.  We need to handle the case where
450fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * there's no entry in the breakpoint set.  (The memory barriers in the
451fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * locks and in the breakpoint update code should ensure that, once we've
452fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * observed the absence of a breakpoint entry, we will also now observe
453fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * the restoration of the original opcode.  The fact that we're holding
454fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * the lock prevents other threads from confusing things further.)
45596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
4569a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornsteinu1 dvmGetOriginalOpcode(const u2* addr)
45796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
45896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
45996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    u1 orig = 0;
46096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
46196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
4629a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
46396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        orig = *(u1*)addr;
46496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (orig == OP_BREAKPOINT) {
465c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("GLITCH: can't find breakpoint, opcode is still set");
46696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            dvmAbort();
46796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
46896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
46996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
47096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
47196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return orig;
47296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
47396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
47496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
475d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * Flush any breakpoints associated with methods in "clazz".
47696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
477d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * We don't want to modify the bytecode of a method before the verifier
478d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * gets a chance to look at it, so we postpone opcode replacement until
479d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * after verification completes.
48096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
481d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFaddenvoid dvmFlushBreakpoints(ClassObject* clazz)
48296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
48396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
48496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
485d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    if (pSet == NULL)
486d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        return;
48796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
488d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    assert(dvmIsClassVerified(clazz));
489d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    dvmBreakpointSetLock(pSet);
490d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    dvmBreakpointSetFlush(pSet, clazz);
49196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
49296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
49396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
4942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
4952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add a single step event.  Currently this is a global item.
4962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We set up some initial values based on the thread's current state.  This
4982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * won't work well if the thread is running, so it's up to the caller to
4992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * verify that it's suspended.
5002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
5012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This is only called from the JDWP thread.
5022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
5032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectbool dvmAddSingleStep(Thread* thread, int size, int depth)
5042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
5052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    StepControl* pCtrl = &gDvm.stepControl;
5062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (pCtrl->active && thread != pCtrl->thread) {
508e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("WARNING: single-step active for %p; adding %p",
5092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            pCtrl->thread, thread);
5102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /*
5122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * Keep going, overwriting previous.  This can happen if you
5132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * suspend a thread in Object.wait, hit the single-step key, then
5142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * switch to another thread and do the same thing again.
5152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * The first thread's step is still pending.
5162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         *
5172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * TODO: consider making single-step per-thread.  Adds to the
5182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * overhead, but could be useful in rare situations.
5192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         */
5202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5221813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    pCtrl->size = static_cast<JdwpStepSize>(size);
5231813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    pCtrl->depth = static_cast<JdwpStepDepth>(depth);
5242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->thread = thread;
5252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
5272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * We may be stepping into or over method calls, or running until we
5282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * return from the current method.  To make this work we need to track
5292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * the current line, current method, and current stack depth.  We need
5302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * to be checking these after most instructions, notably those that
5312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * call methods, return from methods, or are on a different line from the
5322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * previous instruction.
5332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
5342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * We have to start with a snapshot of the current state.  If we're in
5352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * an interpreted method, everything we need is in the current frame.  If
5362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we're in a native method, possibly with some extra JNI frames pushed
5372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * on by PushLocalFrame, we want to use the topmost native method.
5382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const StackSaveArea* saveArea;
54030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    u4* fp;
54130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    u4* prevFp = NULL;
54238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
54330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    for (fp = thread->interpSave.curFrame; fp != NULL;
54430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee         fp = saveArea->prevFrame) {
5452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        const Method* method;
5462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
5482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        method = saveArea->method;
5492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
550fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
5512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
5522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        prevFp = fp;
5532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (fp == NULL) {
555e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Unexpected: step req in native-only threadid=%d",
5562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            thread->threadId);
5572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
5582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (prevFp != NULL) {
5602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /*
5612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * First interpreted frame wasn't the one at the bottom.  Break
5622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * frames are only inserted when calling from native->interp, so we
5632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * don't need to worry about one being here.
5642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         */
56592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("##### init step while in native method");
5662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        fp = prevFp;
567fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        assert(!dvmIsBreakFrame((u4*)fp));
5682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
5692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
5702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
5732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Pull the goodies out.  "xtra.currentPc" should be accurate since
5742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we update it on every instruction while the debugger is connected.
5752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->method = saveArea->method;
5772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    // Clear out any old address set
5782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (pCtrl->pAddressSet != NULL) {
5792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        // (discard const)
5802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        free((void *)pCtrl->pAddressSet);
5812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->pAddressSet = NULL;
5822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsNativeMethod(pCtrl->method)) {
5842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line = -1;
5852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    } else {
5862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line = dvmLineNumFromPC(saveArea->method,
5872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                        saveArea->xtra.currentPc - saveArea->method->insns);
58838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        pCtrl->pAddressSet
5892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                = dvmAddressSetForLine(saveArea->method, pCtrl->line);
5902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
59130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    pCtrl->frameDepth =
59230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        dvmComputeVagueFrameDepth(thread, thread->interpSave.curFrame);
5932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->active = true;
5942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
59592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s",
5962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->thread, pCtrl->method, pCtrl->method->name,
5972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line, pCtrl->frameDepth,
5982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmJdwpStepDepthStr(pCtrl->depth),
5992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmJdwpStepSizeStr(pCtrl->size));
6002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return true;
6022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
6032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
6052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Disable a single step event.
6062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
6072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmClearSingleStep(Thread* thread)
6082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
6092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    UNUSED_PARAMETER(thread);
6102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    gDvm.stepControl.active = false;
6122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
6132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6149a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
6159a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter just threw.  Handle any special subMode requirements.
61699e3e6e72e3471eb85fc2e405866392b01c080febuzbee * All interpSave state must be valid on entry.
6179a3147c7412f4794434b4c2604aa2ba784867774buzbee */
61899e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmReportExceptionThrow(Thread* self, Object* exception)
6199a3147c7412f4794434b4c2604aa2ba784867774buzbee{
62099e3e6e72e3471eb85fc2e405866392b01c080febuzbee    const Method* curMethod = self->interpSave.method;
6219a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
6229a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
62399e3e6e72e3471eb85fc2e405866392b01c080febuzbee        dvmJitEndTraceSelect(self, self->interpSave.pc);
6249a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6259a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
6269a3147c7412f4794434b4c2604aa2ba784867774buzbee        /* Discard any single-step native returns to translation */
6279a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->jitResumeNPC = NULL;
6289a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6299a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
6309a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
6319a3147c7412f4794434b4c2604aa2ba784867774buzbee        void *catchFrame;
63299e3e6e72e3471eb85fc2e405866392b01c080febuzbee        int offset = self->interpSave.pc - curMethod->insns;
63399e3e6e72e3471eb85fc2e405866392b01c080febuzbee        int catchRelPc = dvmFindCatchBlock(self, offset, exception,
6349a3147c7412f4794434b4c2604aa2ba784867774buzbee                                           true, &catchFrame);
63530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        dvmDbgPostException(self->interpSave.curFrame, offset, catchFrame,
63699e3e6e72e3471eb85fc2e405866392b01c080febuzbee                            catchRelPc, exception);
6379a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6389a3147c7412f4794434b4c2604aa2ba784867774buzbee}
6399a3147c7412f4794434b4c2604aa2ba784867774buzbee
6409a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
6419a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter is preparing to do an invoke (both native & normal).
64299e3e6e72e3471eb85fc2e405866392b01c080febuzbee * Handle any special subMode requirements.  All interpSave state
64399e3e6e72e3471eb85fc2e405866392b01c080febuzbee * must be valid on entry.
6449a3147c7412f4794434b4c2604aa2ba784867774buzbee */
6459a3147c7412f4794434b4c2604aa2ba784867774buzbeevoid dvmReportInvoke(Thread* self, const Method* methodToCall)
6469a3147c7412f4794434b4c2604aa2ba784867774buzbee{
6479a3147c7412f4794434b4c2604aa2ba784867774buzbee    TRACE_METHOD_ENTER(self, methodToCall);
6489a3147c7412f4794434b4c2604aa2ba784867774buzbee}
6499a3147c7412f4794434b4c2604aa2ba784867774buzbee
6509a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
6519a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter is preparing to do a native invoke. Handle any
6529a3147c7412f4794434b4c2604aa2ba784867774buzbee * special subMode requirements.  NOTE: for a native invoke,
6539a3147c7412f4794434b4c2604aa2ba784867774buzbee * dvmReportInvoke() and dvmReportPreNativeInvoke() will both
65430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * be called prior to the invoke.  fp is the Dalvik FP of the calling
65530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * method.
6569a3147c7412f4794434b4c2604aa2ba784867774buzbee */
65730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbeevoid dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
6589a3147c7412f4794434b4c2604aa2ba784867774buzbee{
6599a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
6609a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
6619a3147c7412f4794434b4c2604aa2ba784867774buzbee     * Actively building a trace?  If so, end it now.   The trace
6629a3147c7412f4794434b4c2604aa2ba784867774buzbee     * builder can't follow into or through a native method.
6639a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
6649a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
66599e3e6e72e3471eb85fc2e405866392b01c080febuzbee        dvmCheckJit(self->interpSave.pc, self);
6669a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6679a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
6689a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
66930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
6708bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes        assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr));
6719a3147c7412f4794434b4c2604aa2ba784867774buzbee        dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY);
6729a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6739a3147c7412f4794434b4c2604aa2ba784867774buzbee}
6749a3147c7412f4794434b4c2604aa2ba784867774buzbee
6759a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
6769a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter has returned from a native invoke. Handle any
67730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * special subMode requirements.  fp is the Dalvik FP of the calling
67830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * method.
6799a3147c7412f4794434b4c2604aa2ba784867774buzbee */
68030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbeevoid dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
6819a3147c7412f4794434b4c2604aa2ba784867774buzbee{
6829a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
68330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
6848bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes        assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr));
6859a3147c7412f4794434b4c2604aa2ba784867774buzbee        dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT);
6869a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6879a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) {
6889a3147c7412f4794434b4c2604aa2ba784867774buzbee        dvmFastNativeMethodTraceExit(methodToCall, self);
6899a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
6909a3147c7412f4794434b4c2604aa2ba784867774buzbee}
6919a3147c7412f4794434b4c2604aa2ba784867774buzbee
6929a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
6939a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter has returned from a normal method.  Handle any special
69499e3e6e72e3471eb85fc2e405866392b01c080febuzbee * subMode requirements.  All interpSave state must be valid on entry.
6959a3147c7412f4794434b4c2604aa2ba784867774buzbee */
69699e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmReportReturn(Thread* self)
6979a3147c7412f4794434b4c2604aa2ba784867774buzbee{
6989a3147c7412f4794434b4c2604aa2ba784867774buzbee    TRACE_METHOD_EXIT(self, self->interpSave.method);
6999a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
70030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    if (dvmIsBreakFrame(self->interpSave.curFrame) &&
7019a3147c7412f4794434b4c2604aa2ba784867774buzbee        (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) {
70299e3e6e72e3471eb85fc2e405866392b01c080febuzbee        dvmCheckJit(self->interpSave.pc, self);
7039a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
7049a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
7059a3147c7412f4794434b4c2604aa2ba784867774buzbee}
7069a3147c7412f4794434b4c2604aa2ba784867774buzbee
7079a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
7089a3147c7412f4794434b4c2604aa2ba784867774buzbee * Update the debugger on interesting events, such as hitting a breakpoint
7099a3147c7412f4794434b4c2604aa2ba784867774buzbee * or a single-step point.  This is called from the top of the interpreter
7109a3147c7412f4794434b4c2604aa2ba784867774buzbee * loop, before the current instruction is processed.
7119a3147c7412f4794434b4c2604aa2ba784867774buzbee *
7129a3147c7412f4794434b4c2604aa2ba784867774buzbee * Set "methodEntry" if we've just entered the method.  This detects
7139a3147c7412f4794434b4c2604aa2ba784867774buzbee * method exit by checking to see if the next instruction is "return".
7149a3147c7412f4794434b4c2604aa2ba784867774buzbee *
7159a3147c7412f4794434b4c2604aa2ba784867774buzbee * This can't catch native method entry/exit, so we have to handle that
7169a3147c7412f4794434b4c2604aa2ba784867774buzbee * at the point of invocation.  We also need to catch it in dvmCallMethod
7179a3147c7412f4794434b4c2604aa2ba784867774buzbee * if we want to capture native->native calls made through JNI.
7189a3147c7412f4794434b4c2604aa2ba784867774buzbee *
7199a3147c7412f4794434b4c2604aa2ba784867774buzbee * Notes to self:
7209a3147c7412f4794434b4c2604aa2ba784867774buzbee * - Don't want to switch to VMWAIT while posting events to the debugger.
7219a3147c7412f4794434b4c2604aa2ba784867774buzbee *   Let the debugger code decide if we need to change state.
7229a3147c7412f4794434b4c2604aa2ba784867774buzbee * - We may want to check for debugger-induced thread suspensions on
7239a3147c7412f4794434b4c2604aa2ba784867774buzbee *   every instruction.  That would make a "suspend all" more responsive
7249a3147c7412f4794434b4c2604aa2ba784867774buzbee *   and reduce the chances of multiple simultaneous events occurring.
7259a3147c7412f4794434b4c2604aa2ba784867774buzbee *   However, it could change the behavior some.
7269a3147c7412f4794434b4c2604aa2ba784867774buzbee *
7279a3147c7412f4794434b4c2604aa2ba784867774buzbee * TODO: method entry/exit events are probably less common than location
7289a3147c7412f4794434b4c2604aa2ba784867774buzbee * breakpoints.  We may be able to speed things up a bit if we don't query
7299a3147c7412f4794434b4c2604aa2ba784867774buzbee * the event list unless we know there's at least one lurking within.
7309a3147c7412f4794434b4c2604aa2ba784867774buzbee */
73199e3e6e72e3471eb85fc2e405866392b01c080febuzbeestatic void updateDebugger(const Method* method, const u2* pc, const u4* fp,
732e71474621b968a9bc649d067155d31213f5764a9buzbee                           Thread* self)
7339a3147c7412f4794434b4c2604aa2ba784867774buzbee{
7349a3147c7412f4794434b4c2604aa2ba784867774buzbee    int eventFlags = 0;
7359a3147c7412f4794434b4c2604aa2ba784867774buzbee
7369a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
7379a3147c7412f4794434b4c2604aa2ba784867774buzbee     * Update xtra.currentPc on every instruction.  We need to do this if
7389a3147c7412f4794434b4c2604aa2ba784867774buzbee     * there's a chance that we could get suspended.  This can happen if
7399a3147c7412f4794434b4c2604aa2ba784867774buzbee     * eventFlags != 0 here, or somebody manually requests a suspend
7409a3147c7412f4794434b4c2604aa2ba784867774buzbee     * (which gets handled at PERIOD_CHECKS time).  One place where this
7419a3147c7412f4794434b4c2604aa2ba784867774buzbee     * needs to be correct is in dvmAddSingleStep().
7429a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
7439a3147c7412f4794434b4c2604aa2ba784867774buzbee    dvmExportPC(pc, fp);
7449a3147c7412f4794434b4c2604aa2ba784867774buzbee
745e71474621b968a9bc649d067155d31213f5764a9buzbee    if (self->debugIsMethodEntry) {
7469a3147c7412f4794434b4c2604aa2ba784867774buzbee        eventFlags |= DBG_METHOD_ENTRY;
747e71474621b968a9bc649d067155d31213f5764a9buzbee        self->debugIsMethodEntry = false;
748e71474621b968a9bc649d067155d31213f5764a9buzbee    }
7499a3147c7412f4794434b4c2604aa2ba784867774buzbee
7509a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
7519a3147c7412f4794434b4c2604aa2ba784867774buzbee     * See if we have a breakpoint here.
7529a3147c7412f4794434b4c2604aa2ba784867774buzbee     *
7539a3147c7412f4794434b4c2604aa2ba784867774buzbee     * Depending on the "mods" associated with event(s) on this address,
7549a3147c7412f4794434b4c2604aa2ba784867774buzbee     * we may or may not actually send a message to the debugger.
7559a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
7569a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (GET_OPCODE(*pc) == OP_BREAKPOINT) {
75792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("+++ breakpoint hit at %p", pc);
7589a3147c7412f4794434b4c2604aa2ba784867774buzbee        eventFlags |= DBG_BREAKPOINT;
7599a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
7609a3147c7412f4794434b4c2604aa2ba784867774buzbee
7619a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
7629a3147c7412f4794434b4c2604aa2ba784867774buzbee     * If the debugger is single-stepping one of our threads, check to
7639a3147c7412f4794434b4c2604aa2ba784867774buzbee     * see if we're that thread and we've reached a step point.
7649a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
7659a3147c7412f4794434b4c2604aa2ba784867774buzbee    const StepControl* pCtrl = &gDvm.stepControl;
7669a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (pCtrl->active && pCtrl->thread == self) {
7679a3147c7412f4794434b4c2604aa2ba784867774buzbee        int frameDepth;
7689a3147c7412f4794434b4c2604aa2ba784867774buzbee        bool doStop = false;
7699a3147c7412f4794434b4c2604aa2ba784867774buzbee        const char* msg = NULL;
7709a3147c7412f4794434b4c2604aa2ba784867774buzbee
7719a3147c7412f4794434b4c2604aa2ba784867774buzbee        assert(!dvmIsNativeMethod(method));
7729a3147c7412f4794434b4c2604aa2ba784867774buzbee
7739a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (pCtrl->depth == SD_INTO) {
7749a3147c7412f4794434b4c2604aa2ba784867774buzbee            /*
7759a3147c7412f4794434b4c2604aa2ba784867774buzbee             * Step into method calls.  We break when the line number
7769a3147c7412f4794434b4c2604aa2ba784867774buzbee             * or method pointer changes.  If we're in SS_MIN mode, we
7779a3147c7412f4794434b4c2604aa2ba784867774buzbee             * always stop.
7789a3147c7412f4794434b4c2604aa2ba784867774buzbee             */
7799a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (pCtrl->method != method) {
7809a3147c7412f4794434b4c2604aa2ba784867774buzbee                doStop = true;
7819a3147c7412f4794434b4c2604aa2ba784867774buzbee                msg = "new method";
7829a3147c7412f4794434b4c2604aa2ba784867774buzbee            } else if (pCtrl->size == SS_MIN) {
7839a3147c7412f4794434b4c2604aa2ba784867774buzbee                doStop = true;
7849a3147c7412f4794434b4c2604aa2ba784867774buzbee                msg = "new instruction";
7859a3147c7412f4794434b4c2604aa2ba784867774buzbee            } else if (!dvmAddressSetGet(
7869a3147c7412f4794434b4c2604aa2ba784867774buzbee                    pCtrl->pAddressSet, pc - method->insns)) {
7879a3147c7412f4794434b4c2604aa2ba784867774buzbee                doStop = true;
7889a3147c7412f4794434b4c2604aa2ba784867774buzbee                msg = "new line";
7899a3147c7412f4794434b4c2604aa2ba784867774buzbee            }
7909a3147c7412f4794434b4c2604aa2ba784867774buzbee        } else if (pCtrl->depth == SD_OVER) {
7919a3147c7412f4794434b4c2604aa2ba784867774buzbee            /*
7929a3147c7412f4794434b4c2604aa2ba784867774buzbee             * Step over method calls.  We break when the line number is
7939a3147c7412f4794434b4c2604aa2ba784867774buzbee             * different and the frame depth is <= the original frame
7949a3147c7412f4794434b4c2604aa2ba784867774buzbee             * depth.  (We can't just compare on the method, because we
7959a3147c7412f4794434b4c2604aa2ba784867774buzbee             * might get unrolled past it by an exception, and it's tricky
7969a3147c7412f4794434b4c2604aa2ba784867774buzbee             * to identify recursion.)
7979a3147c7412f4794434b4c2604aa2ba784867774buzbee             */
7989a3147c7412f4794434b4c2604aa2ba784867774buzbee            frameDepth = dvmComputeVagueFrameDepth(self, fp);
7999a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (frameDepth < pCtrl->frameDepth) {
8009a3147c7412f4794434b4c2604aa2ba784867774buzbee                /* popped up one or more frames, always trigger */
8019a3147c7412f4794434b4c2604aa2ba784867774buzbee                doStop = true;
8029a3147c7412f4794434b4c2604aa2ba784867774buzbee                msg = "method pop";
8039a3147c7412f4794434b4c2604aa2ba784867774buzbee            } else if (frameDepth == pCtrl->frameDepth) {
8049a3147c7412f4794434b4c2604aa2ba784867774buzbee                /* same depth, see if we moved */
8059a3147c7412f4794434b4c2604aa2ba784867774buzbee                if (pCtrl->size == SS_MIN) {
8069a3147c7412f4794434b4c2604aa2ba784867774buzbee                    doStop = true;
8079a3147c7412f4794434b4c2604aa2ba784867774buzbee                    msg = "new instruction";
8089a3147c7412f4794434b4c2604aa2ba784867774buzbee                } else if (!dvmAddressSetGet(pCtrl->pAddressSet,
8099a3147c7412f4794434b4c2604aa2ba784867774buzbee                            pc - method->insns)) {
8109a3147c7412f4794434b4c2604aa2ba784867774buzbee                    doStop = true;
8119a3147c7412f4794434b4c2604aa2ba784867774buzbee                    msg = "new line";
8129a3147c7412f4794434b4c2604aa2ba784867774buzbee                }
8139a3147c7412f4794434b4c2604aa2ba784867774buzbee            }
8149a3147c7412f4794434b4c2604aa2ba784867774buzbee        } else {
8159a3147c7412f4794434b4c2604aa2ba784867774buzbee            assert(pCtrl->depth == SD_OUT);
8169a3147c7412f4794434b4c2604aa2ba784867774buzbee            /*
8179a3147c7412f4794434b4c2604aa2ba784867774buzbee             * Return from the current method.  We break when the frame
8189a3147c7412f4794434b4c2604aa2ba784867774buzbee             * depth pops up.
8199a3147c7412f4794434b4c2604aa2ba784867774buzbee             *
8209a3147c7412f4794434b4c2604aa2ba784867774buzbee             * This differs from the "method exit" break in that it stops
8219a3147c7412f4794434b4c2604aa2ba784867774buzbee             * with the PC at the next instruction in the returned-to
8229a3147c7412f4794434b4c2604aa2ba784867774buzbee             * function, rather than the end of the returning function.
8239a3147c7412f4794434b4c2604aa2ba784867774buzbee             */
8249a3147c7412f4794434b4c2604aa2ba784867774buzbee            frameDepth = dvmComputeVagueFrameDepth(self, fp);
8259a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (frameDepth < pCtrl->frameDepth) {
8269a3147c7412f4794434b4c2604aa2ba784867774buzbee                doStop = true;
8279a3147c7412f4794434b4c2604aa2ba784867774buzbee                msg = "method pop";
8289a3147c7412f4794434b4c2604aa2ba784867774buzbee            }
8299a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
8309a3147c7412f4794434b4c2604aa2ba784867774buzbee
8319a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (doStop) {
83292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("#####S %s", msg);
8339a3147c7412f4794434b4c2604aa2ba784867774buzbee            eventFlags |= DBG_SINGLE_STEP;
8349a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
8359a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
8369a3147c7412f4794434b4c2604aa2ba784867774buzbee
8379a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
8389a3147c7412f4794434b4c2604aa2ba784867774buzbee     * Check to see if this is a "return" instruction.  JDWP says we should
8399a3147c7412f4794434b4c2604aa2ba784867774buzbee     * send the event *after* the code has been executed, but it also says
8409a3147c7412f4794434b4c2604aa2ba784867774buzbee     * the location we provide is the last instruction.  Since the "return"
8419a3147c7412f4794434b4c2604aa2ba784867774buzbee     * instruction has no interesting side effects, we should be safe.
8429a3147c7412f4794434b4c2604aa2ba784867774buzbee     * (We can't just move this down to the returnFromMethod label because
8439a3147c7412f4794434b4c2604aa2ba784867774buzbee     * we potentially need to combine it with other events.)
8449a3147c7412f4794434b4c2604aa2ba784867774buzbee     *
8459a3147c7412f4794434b4c2604aa2ba784867774buzbee     * We're also not supposed to generate a method exit event if the method
8469a3147c7412f4794434b4c2604aa2ba784867774buzbee     * terminates "with a thrown exception".
8479a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
8489a3147c7412f4794434b4c2604aa2ba784867774buzbee    u2 opcode = GET_OPCODE(*pc);
8494fa9a95705253695d257381fdb12311f13d7638aElliott Hughes    if (opcode == OP_RETURN_VOID || opcode == OP_RETURN || opcode == OP_RETURN_VOID_BARRIER ||
8504fa9a95705253695d257381fdb12311f13d7638aElliott Hughes        opcode == OP_RETURN_OBJECT || opcode == OP_RETURN_WIDE)
8519a3147c7412f4794434b4c2604aa2ba784867774buzbee    {
8529a3147c7412f4794434b4c2604aa2ba784867774buzbee        eventFlags |= DBG_METHOD_EXIT;
8539a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
8549a3147c7412f4794434b4c2604aa2ba784867774buzbee
8559a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
8569a3147c7412f4794434b4c2604aa2ba784867774buzbee     * If there's something interesting going on, see if it matches one
8579a3147c7412f4794434b4c2604aa2ba784867774buzbee     * of the debugger filters.
8589a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
8599a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (eventFlags != 0) {
8609a3147c7412f4794434b4c2604aa2ba784867774buzbee        Object* thisPtr = dvmGetThisPtr(method, fp);
8618bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes        if (thisPtr != NULL && !dvmIsHeapAddress(thisPtr)) {
8629a3147c7412f4794434b4c2604aa2ba784867774buzbee            /*
8639a3147c7412f4794434b4c2604aa2ba784867774buzbee             * TODO: remove this check if we're confident that the "this"
8649a3147c7412f4794434b4c2604aa2ba784867774buzbee             * pointer is where it should be -- slows us down, especially
8659a3147c7412f4794434b4c2604aa2ba784867774buzbee             * during single-step.
8669a3147c7412f4794434b4c2604aa2ba784867774buzbee             */
8679a3147c7412f4794434b4c2604aa2ba784867774buzbee            char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
868c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("HEY: invalid 'this' ptr %p (%s.%s %s)", thisPtr,
8699a3147c7412f4794434b4c2604aa2ba784867774buzbee                method->clazz->descriptor, method->name, desc);
8709a3147c7412f4794434b4c2604aa2ba784867774buzbee            free(desc);
8719a3147c7412f4794434b4c2604aa2ba784867774buzbee            dvmAbort();
8729a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
8739a3147c7412f4794434b4c2604aa2ba784867774buzbee        dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr,
8749a3147c7412f4794434b4c2604aa2ba784867774buzbee            eventFlags);
8759a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
8769a3147c7412f4794434b4c2604aa2ba784867774buzbee}
8772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
8782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
8792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Recover the "this" pointer from the current interpreted method.  "this"
8802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * is always in "in0" for non-static methods.
8812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
8822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The "ins" start at (#of registers - #of ins).  Note in0 != v0.
8832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
8842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This works because "dx" guarantees that it will work.  It's probably
8852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * fairly common to have a virtual method that doesn't use its "this"
8862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * pointer, in which case we're potentially wasting a register.  However,
8872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the debugger doesn't treat "this" as just another argument.  For
8882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * example, events (such as breakpoints) can be enabled for specific
8892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * values of "this".  There is also a separate StackFrame.ThisObject call
8902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * in JDWP that is expected to work for any non-native non-static method.
8912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
8922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Because we need it when setting up debugger event filters, we want to
8932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * be able to do this quickly.
8942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
8952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectObject* dvmGetThisPtr(const Method* method, const u4* fp)
8962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
8972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsStaticMethod(method))
8982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
8992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return (Object*)fp[method->registersSize - method->insSize];
9002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
9012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS)
9042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
9052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Verify that all internally-tracked references have been released.  If
9062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * they haven't, print them and abort the VM.
9072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
9082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "debugTrackedRefStart" indicates how many refs were on the list when
9092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we were first invoked.
9102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
9112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
9122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int debugTrackedRefStart)
9132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
9142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmReferenceTableEntries(&self->internalLocalRefTable)
9152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        != (size_t) debugTrackedRefStart)
9162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    {
9172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        char* desc;
9182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        Object** top;
9192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        int count;
9202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        count = dvmReferenceTableEntries(&self->internalLocalRefTable);
9222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
923c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("TRACK: unreleased internal reference (prev=%d total=%d)",
9242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            debugTrackedRefStart, count);
9252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        desc = dexProtoCopyMethodDescriptor(&method->prototype);
926c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("       current method is %s.%s %s", method->clazz->descriptor,
9272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            method->name, desc);
9282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        free(desc);
9292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        top = self->internalLocalRefTable.table + debugTrackedRefStart;
9302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        while (top < self->internalLocalRefTable.nextEntry) {
931c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("  %p (%s)",
9322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                 *top,
9332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
9342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            top++;
9352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
9362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmDumpThread(self, false);
9372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmAbort();
9392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9404308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("TRACK OK");
9412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
9422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
9432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef LOG_INSTR
9462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
9472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Dump the v-registers.  Sent to the ILOG log tag.
9482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
9492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
9502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
9512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i, localCount;
9522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    localCount = method->registersSize - method->insSize;
9542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9551663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block    ALOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):", framePtr);
9562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = method->registersSize-1; i >= 0; i--) {
9572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (i >= localCount) {
9581663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d in%-2d : 0x%08x",
9592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                i, i-localCount, framePtr[i]);
9602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        } else {
9612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            if (inOnly) {
9621663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block                ALOG(LOG_VERBOSE, LOG_TAG"i", "  [...]");
9632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                break;
9642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            }
9652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const char* name = "";
9662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0   // "locals" structure has changed -- need to rewrite this
9678afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes            int j;
9682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            DexFile* pDexFile = method->clazz->pDexFile;
9692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const DexCode* pDexCode = dvmGetMethodCode(method);
9702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
9712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
9722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            for (j = 0; j < localsSize, j++) {
9732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                if (locals[j].registerNum == (u4) i) {
9742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                    name = dvmDexStringStr(locals[j].pName);
9752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                    break;
9762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                }
9772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            }
9782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
9791663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d      : 0x%08x %s",
9802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                i, framePtr[i], name);
9812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
9822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
9842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
9852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
9882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
9892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *      Entry point and general support functions
9902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
9912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
9922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
99338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng/*
9942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case.  Returns the offset to the handler instructions.
9952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
9962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the packed-switch
9972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction).
9982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
9992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
10002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
10012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const int kInstrLen = 3;
10022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 size;
10032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    s4 firstKey;
10042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* entries;
10052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
10072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Packed switch data format:
10082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0100   magic value
10092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort size             number of entries in the table
10102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int first_key           first (and lowest) switch case value
10112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int targets[size]       branch targets, relative to switch opcode
10122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
10132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is (4+size*2) 16-bit code units.
10142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
10152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (*switchData++ != kPackedSwitchSignature) {
10162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* should have been caught by verifier */
1017d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowInternalError("bad packed switch magic");
10182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
10192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
10202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = *switchData++;
10222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(size > 0);
10232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    firstKey = *switchData++;
10252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    firstKey |= (*switchData++) << 16;
10262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (testVal < firstKey || testVal >= firstKey + size) {
102860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("Value %d not found in switch (%d-%d)",
10292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            testVal, firstKey, firstKey+size-1);
10302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
10312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
10322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The entries are guaranteed to be aligned on a 32-bit boundary;
10342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
10352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
10362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    entries = (const s4*) switchData;
10372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)entries & 0x3) == 0);
10382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(testVal - firstKey >= 0 && testVal - firstKey < size);
104060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("Value %d found in slot %d (goto 0x%02x)",
10412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        testVal, testVal - firstKey,
10422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        s4FromSwitchData(&entries[testVal - firstKey]));
10432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return s4FromSwitchData(&entries[testVal - firstKey]);
10442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
10452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
10472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case.  Returns the offset to the handler instructions.
10482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
10492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the sparse-switch
10502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction).
10512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
10522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
10532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
10542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const int kInstrLen = 3;
1055e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    u2 size;
10562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* keys;
10572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* entries;
10582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
10602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Sparse switch data format:
10612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0200   magic value
10622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort size             number of entries in the table; > 0
10632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
10642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int targets[size]       branch targets, relative to switch opcode
10652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
10662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is (2+size*4) 16-bit code units.
10672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
10682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (*switchData++ != kSparseSwitchSignature) {
10702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* should have been caught by verifier */
1071d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowInternalError("bad sparse switch magic");
10722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
10732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
10742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = *switchData++;
10762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(size > 0);
107738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
10782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The keys are guaranteed to be aligned on a 32-bit boundary;
10792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
10802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
10812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    keys = (const s4*) switchData;
10822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)keys & 0x3) == 0);
10832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The entries are guaranteed to be aligned on a 32-bit boundary;
10852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
10862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
10872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    entries = keys + size;
10882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)entries & 0x3) == 0);
10892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
109162f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden     * Binary-search through the array of keys, which are guaranteed to
10922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * be sorted low-to-high.
10932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
109462f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden    int lo = 0;
109562f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden    int hi = size - 1;
109662f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden    while (lo <= hi) {
109762f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        int mid = (lo + hi) >> 1;
109862f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden
109962f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        s4 foundVal = s4FromSwitchData(&keys[mid]);
110062f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        if (testVal < foundVal) {
110162f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden            hi = mid - 1;
110262f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        } else if (testVal > foundVal) {
110362f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden            lo = mid + 1;
110462f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        } else {
110560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGVV("Value %d found in entry %d (goto 0x%02x)",
110662f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden                testVal, mid, s4FromSwitchData(&entries[mid]));
110762f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden            return s4FromSwitchData(&entries[mid]);
11082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
11092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
11102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
111160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("Value %d not found in switch", testVal);
11122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return kInstrLen;
11132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
11142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
11152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
11166f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * Copy data for a fill-array-data instruction.  On a little-endian machine
11176f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * we can just do a memcpy(), on a big-endian system we have work to do.
11186f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden *
11196f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * The trick here is that dexopt has byte-swapped each code unit, which is
11206f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * exactly what we want for short/char data.  For byte data we need to undo
11216f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * the swap, and for 4- or 8-byte values we need to swap pieces within
11226f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * each word.
11236f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden */
11246f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFaddenstatic void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
11256f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden{
11266f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#if __BYTE_ORDER == __LITTLE_ENDIAN
11276f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    memcpy(dest, src, size*width);
11286f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#else
11296f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    int i;
11306f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden
11316f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    switch (width) {
11326f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 1:
11336f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* un-swap pairs of bytes as we go */
11346f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        for (i = (size-1) & ~1; i >= 0; i -= 2) {
11356f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u1*)dest)[i] = ((u1*)src)[i+1];
11366f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u1*)dest)[i+1] = ((u1*)src)[i];
11376f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
11386f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /*
11396f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden         * "src" is padded to end on a two-byte boundary, but we don't want to
11406f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden         * assume "dest" is, so we handle odd length specially.
11416f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden         */
11426f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        if ((size & 1) != 0) {
11436f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u1*)dest)[size-1] = ((u1*)src)[size];
11446f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
11456f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
11466f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 2:
11476f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* already swapped correctly */
11486f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        memcpy(dest, src, size*width);
11496f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
11506f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 4:
11516f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* swap word halves */
11526f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        for (i = 0; i < (int) size; i++) {
11536f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
11546f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
11556f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
11566f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 8:
11576f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* swap word halves and words */
11586f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        for (i = 0; i < (int) (size << 1); i += 2) {
11596f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
11606f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
11616f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
11626f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
11636f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    default:
1164c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unexpected width %d in copySwappedArrayData", width);
11656f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        dvmAbort();
11666f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
11676f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    }
11686f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#endif
11696f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden}
11706f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden
11716f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden/*
11722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Fill the array with predefined constant values.
11732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
11742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns true if job is completed, otherwise false to indicate that
11752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * an exception has been thrown.
11762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
117789c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Projectbool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
11782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
11792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 width;
11802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u4 size;
11812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
118289c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project    if (arrayObj == NULL) {
1183d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowNullPointerException(NULL);
11842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
11852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
11867dc966014df20fea6a4643ce2736922d0a7ee2c8Barry Hayes    assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
11877dc966014df20fea6a4643ce2736922d0a7ee2c8Barry Hayes                               CLASS_ISOBJECTARRAY));
118889c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project
11892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
11902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Array data table format:
11912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0300   magic value
11922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort width            width of each element in the table
11932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  uint   size             number of elements in the table
11942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ubyte  data[size*width] table of data values (may contain a single-byte
11952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *                          padding at the end)
11962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
11972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is 4+(width * size + 1)/2 16-bit code units.
11982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
11992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (arrayData[0] != kArrayDataSignature) {
1200d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowInternalError("bad array data magic");
12012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
12022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
12032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    width = arrayData[1];
12052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = arrayData[2] | (((u4)arrayData[3]) << 16);
12062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (size > arrayObj->length) {
120847f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornstein        dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
12092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
12102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
12116f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
12122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return true;
12132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
12142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
12162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the concrete method that corresponds to "methodIdx".  The code in
12172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "method" is executing invoke-method with "thisClass" as its first argument.
12182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
12192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns NULL with an exception raised on failure.
12202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
12212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectMethod* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
12222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const Method* method, DvmDex* methodClassDex)
12232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
12242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Method* absMethod;
12252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Method* methodToCall;
12262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i, vtableIndex;
12272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
12292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Resolve the method.  This gives us the abstract method from the
12302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * interface class declaration.
12312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
12322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
12332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (absMethod == NULL) {
12342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
12352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (absMethod == NULL) {
123692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("+ unknown method");
12372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            return NULL;
12382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
12392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
12402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* make sure absMethod->methodIndex means what we think it means */
12422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(dvmIsAbstractMethod(absMethod));
12432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
12452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Run through the "this" object's iftable.  Find the entry for
12462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * absMethod's class, then use absMethod->methodIndex to find
12472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * the method's entry.  The value there is the offset into our
12482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * vtable of the actual method to execute.
12492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
12502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * The verifier does not guarantee that objects stored into
12512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * interface references actually implement the interface, so this
12522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * check cannot be eliminated.
12532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
12542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = 0; i < thisClass->iftableCount; i++) {
12552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (thisClass->iftable[i].clazz == absMethod->clazz)
12562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
12572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
12582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (i == thisClass->iftableCount) {
12592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* impossible in verified DEX, need to check for it in unverified */
126070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein        dvmThrowIncompatibleClassChangeError("interface not implemented");
12612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
12622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
12632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(absMethod->methodIndex <
12652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        thisClass->iftable[i].clazz->virtualMethodCount);
12662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    vtableIndex =
12682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
12692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
12702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    methodToCall = thisClass->vtable[vtableIndex];
12712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0
12732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* this can happen when there's a stale class file */
12742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsAbstractMethod(methodToCall)) {
1275d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowAbstractMethodError("interface method not implemented");
12762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
12772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
12782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
12792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(!dvmIsAbstractMethod(methodToCall) ||
12802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        methodToCall->nativeFunc != NULL);
12812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
12822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
128360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("+++ interface=%s.%s concrete=%s.%s",
12842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        absMethod->clazz->descriptor, absMethod->name,
12852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        methodToCall->clazz->descriptor, methodToCall->name);
12862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(methodToCall != NULL);
12872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return methodToCall;
12892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
12902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1292b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1293b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/*
1294b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Helpers for dvmThrowVerificationError().
1295b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
1296b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Each returns a newly-allocated string.
1297b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */
1298b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden#define kThrowShow_accessFromClass     1
1299b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic std::string classNameFromIndex(const Method* method, int ref,
1300af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType, int flags)
1301b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
1302b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const DvmDex* pDvmDex = method->clazz->pDvmDex;
1303af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    if (refType == VERIFY_ERROR_REF_FIELD) {
1304af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        /* get class ID from field ID */
1305af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1306af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        ref = pFieldId->classIdx;
1307af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    } else if (refType == VERIFY_ERROR_REF_METHOD) {
1308af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        /* get class ID from method ID */
1309af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1310af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        ref = pMethodId->classIdx;
1311af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    }
1312af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1313b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
1314b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string dotClassName(dvmHumanReadableDescriptor(className));
1315b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    if (flags == 0) {
1316b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        return dotClassName;
1317b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    }
1318b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1319b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string result;
1320b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if ((flags & kThrowShow_accessFromClass) != 0) {
1321b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += "tried to access class " + dotClassName;
1322b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor);
1323b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    } else {
1324b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        assert(false);      // should've been caught above
1325b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1326b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1327b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    return result;
1328b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
1329b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic std::string fieldNameFromIndex(const Method* method, int ref,
1330af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType, int flags)
1331b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
1332af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    if (refType != VERIFY_ERROR_REF_FIELD) {
1333e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_FIELD, refType);
1334af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        return NULL;    /* no message */
1335af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    }
1336af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1337b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const DvmDex* pDvmDex = method->clazz->pDvmDex;
1338b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1339b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1340b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const char* fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1341b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1342b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string dotName(dvmHumanReadableDescriptor(className));
1343b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1344b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if ((flags & kThrowShow_accessFromClass) != 0) {
1345b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        std::string result;
1346b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += "tried to access field ";
1347b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += dotName + "." + fieldName;
1348b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += " from class ";
1349b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += dvmHumanReadableDescriptor(method->clazz->descriptor);
1350b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        return result;
1351b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1352b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    return dotName + "." + fieldName;
1353b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
1354b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic std::string methodNameFromIndex(const Method* method, int ref,
1355af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType, int flags)
1356b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
1357af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    if (refType != VERIFY_ERROR_REF_METHOD) {
1358e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_METHOD,refType);
1359af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        return NULL;    /* no message */
1360af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    }
1361af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1362b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const DvmDex* pDvmDex = method->clazz->pDvmDex;
1363b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1364b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1365b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    const char* methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1366b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1367b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string dotName(dvmHumanReadableDescriptor(className));
1368b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1369b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if ((flags & kThrowShow_accessFromClass) != 0) {
1370b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1371b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        std::string result;
1372b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += "tried to access method ";
1373b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += dotName + "." + methodName + ":" + desc;
1374b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor);
1375b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        free(desc);
1376b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        return result;
1377b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1378b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    return dotName + "." + methodName;
1379b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
1380b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
13812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
13823a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * Throw an exception for a problem identified by the verifier.
13833a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden *
13843a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * This is used by the invoke-verification-error instruction.  It always
13853a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * throws an exception.
13863a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden *
1387af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden * "kind" indicates the kind of failure encountered by the verifier.  It
1388af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden * has two parts, an error code and an indication of the reference type.
13893a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden */
1390b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmThrowVerificationError(const Method* method, int kind, int ref)
13913a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden{
13921813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift);
13931813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    int errorRefPart = kind >> kVerifyErrorRefTypeShift;
13941813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    VerifyError errorKind = static_cast<VerifyError>(errorPart);
13951813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro    VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart);
1396a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein    ClassObject* exceptionClass = gDvm.exVerifyError;
1397b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string msg;
1398b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1399af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    switch ((VerifyError) errorKind) {
1400b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NO_CLASS:
1401a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exNoClassDefFoundError;
1402af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType, 0);
1403b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1404b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NO_FIELD:
1405a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exNoSuchFieldError;
1406af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = fieldNameFromIndex(method, ref, refType, 0);
1407b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1408b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NO_METHOD:
1409a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exNoSuchMethodError;
1410af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = methodNameFromIndex(method, ref, refType, 0);
1411b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1412b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_ACCESS_CLASS:
1413a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exIllegalAccessError;
1414af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType,
1415af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden            kThrowShow_accessFromClass);
1416b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1417b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_ACCESS_FIELD:
1418a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exIllegalAccessError;
1419af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = fieldNameFromIndex(method, ref, refType,
1420af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden            kThrowShow_accessFromClass);
1421b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1422b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_ACCESS_METHOD:
1423a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exIllegalAccessError;
1424af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = methodNameFromIndex(method, ref, refType,
1425af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden            kThrowShow_accessFromClass);
1426b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1427b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_CLASS_CHANGE:
1428a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exIncompatibleClassChangeError;
1429af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType, 0);
1430b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1431b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_INSTANTIATION:
1432a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        exceptionClass = gDvm.exInstantiationError;
1433af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType, 0);
1434b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1435b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1436b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_GENERIC:
1437b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        /* generic VerifyError; use default exception, no message */
1438b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1439b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NONE:
1440b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        /* should never happen; use default exception */
1441b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        assert(false);
14420de2df09a41ffbe2318dbc9a4daa04dc7966f9b8Elliott Hughes        msg = "weird - no error specified";
1443b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1444b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1445b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    /* no default clause -- want warning if enum updated */
1446b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1447b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1448b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    dvmThrowException(exceptionClass, msg.c_str());
14493a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden}
14503a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden
14513a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden/*
1452cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee * Update interpBreak for a single thread.
1453cb3081f675109049e63380170b60871e8275f9a8buzbee */
1454cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable)
1455cb3081f675109049e63380170b60871e8275f9a8buzbee{
14569a3147c7412f4794434b4c2604aa2ba784867774buzbee    InterpBreak oldValue, newValue;
1457cb3081f675109049e63380170b60871e8275f9a8buzbee    do {
14589a3147c7412f4794434b4c2604aa2ba784867774buzbee        oldValue = newValue = thread->interpBreak;
1459cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        newValue.ctl.breakFlags = kInterpNoBreak;  // Assume full reset
1460cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        if (enable)
1461cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            newValue.ctl.subMode |= subMode;
1462cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        else
1463cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            newValue.ctl.subMode &= ~subMode;
1464cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK)
1465cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            newValue.ctl.breakFlags |= kInterpSingleStep;
1466cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK)
1467cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            newValue.ctl.breakFlags |= kInterpSafePoint;
146875425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP
14699a3147c7412f4794434b4c2604aa2ba784867774buzbee        newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
14709a3147c7412f4794434b4c2604aa2ba784867774buzbee            thread->altHandlerTable : thread->mainHandlerTable;
147175425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif
14729a3147c7412f4794434b4c2604aa2ba784867774buzbee    } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
14739a3147c7412f4794434b4c2604aa2ba784867774buzbee             &thread->interpBreak.all) != 0);
14749a3147c7412f4794434b4c2604aa2ba784867774buzbee}
14759a3147c7412f4794434b4c2604aa2ba784867774buzbee
14769a3147c7412f4794434b4c2604aa2ba784867774buzbee/*
1477cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee * Update interpBreak for all threads.
1478cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee */
1479cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid updateAllInterpBreak(ExecutionSubModes subMode, bool enable)
1480cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{
1481cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    Thread* self = dvmThreadSelf();
1482cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    Thread* thread;
1483cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee
1484cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    dvmLockThreadList(self);
1485cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1486cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        updateInterpBreak(thread, subMode, enable);
1487cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    }
1488cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    dvmUnlockThreadList();
1489cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee}
1490cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee
1491cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee/*
14929a3147c7412f4794434b4c2604aa2ba784867774buzbee * Update the normal and debugger suspend counts for a thread.
14939a3147c7412f4794434b4c2604aa2ba784867774buzbee * threadSuspendCount must be acquired before calling this to
14949a3147c7412f4794434b4c2604aa2ba784867774buzbee * ensure a clean update of suspendCount, dbgSuspendCount and
1495389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee * sumThreadSuspendCount.
14969a3147c7412f4794434b4c2604aa2ba784867774buzbee *
14979a3147c7412f4794434b4c2604aa2ba784867774buzbee * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
14989a3147c7412f4794434b4c2604aa2ba784867774buzbee * Move under WITH_JIT ifdefs.
14999a3147c7412f4794434b4c2604aa2ba784867774buzbee*/
15009a3147c7412f4794434b4c2604aa2ba784867774buzbeevoid dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
15019a3147c7412f4794434b4c2604aa2ba784867774buzbee{
1502389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee    thread->suspendCount += delta;
1503389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee    thread->dbgSuspendCount += dbgDelta;
1504cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    updateInterpBreak(thread, kSubModeSuspendPending,
1505cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee                      (thread->suspendCount != 0));
15069a3147c7412f4794434b4c2604aa2ba784867774buzbee    // Update the global suspend count total
15079a3147c7412f4794434b4c2604aa2ba784867774buzbee    gDvm.sumThreadSuspendCount += delta;
15089a3147c7412f4794434b4c2604aa2ba784867774buzbee}
15099a3147c7412f4794434b4c2604aa2ba784867774buzbee
1510cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee
1511cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode)
15129a3147c7412f4794434b4c2604aa2ba784867774buzbee{
1513cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    updateInterpBreak(thread, subMode, false);
1514cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee}
15159a3147c7412f4794434b4c2604aa2ba784867774buzbee
1516cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode)
1517cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{
1518cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    updateInterpBreak(thread, subMode, true);
1519cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee}
1520cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee
1521cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmEnableAllSubMode(ExecutionSubModes subMode)
1522cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{
1523cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    updateAllInterpBreak(subMode, true);
1524cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee}
1525cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee
1526cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmDisableAllSubMode(ExecutionSubModes subMode)
1527cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{
1528cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    updateAllInterpBreak(subMode, false);
1529cb3081f675109049e63380170b60871e8275f9a8buzbee}
1530cb3081f675109049e63380170b60871e8275f9a8buzbee
1531cb3081f675109049e63380170b60871e8275f9a8buzbee/*
153299e3e6e72e3471eb85fc2e405866392b01c080febuzbee * Do a sanity check on interpreter state saved to Thread.
153399e3e6e72e3471eb85fc2e405866392b01c080febuzbee * A failure here doesn't necessarily mean that something is wrong,
153499e3e6e72e3471eb85fc2e405866392b01c080febuzbee * so this code should only be used during development to suggest
153599e3e6e72e3471eb85fc2e405866392b01c080febuzbee * a possible problem.
153699e3e6e72e3471eb85fc2e405866392b01c080febuzbee */
153799e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmCheckInterpStateConsistency()
153899e3e6e72e3471eb85fc2e405866392b01c080febuzbee{
153999e3e6e72e3471eb85fc2e405866392b01c080febuzbee    Thread* self = dvmThreadSelf();
154099e3e6e72e3471eb85fc2e405866392b01c080febuzbee    Thread* thread;
154199e3e6e72e3471eb85fc2e405866392b01c080febuzbee    uint8_t breakFlags;
154299e3e6e72e3471eb85fc2e405866392b01c080febuzbee    uint8_t subMode;
154375425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP
154499e3e6e72e3471eb85fc2e405866392b01c080febuzbee    void* handlerTable;
154575425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif
154699e3e6e72e3471eb85fc2e405866392b01c080febuzbee
154799e3e6e72e3471eb85fc2e405866392b01c080febuzbee    dvmLockThreadList(self);
154899e3e6e72e3471eb85fc2e405866392b01c080febuzbee    breakFlags = self->interpBreak.ctl.breakFlags;
154999e3e6e72e3471eb85fc2e405866392b01c080febuzbee    subMode = self->interpBreak.ctl.subMode;
155075425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP
155199e3e6e72e3471eb85fc2e405866392b01c080febuzbee    handlerTable = self->interpBreak.ctl.curHandlerTable;
155275425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif
155399e3e6e72e3471eb85fc2e405866392b01c080febuzbee    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
155499e3e6e72e3471eb85fc2e405866392b01c080febuzbee        if (subMode != thread->interpBreak.ctl.subMode) {
1555062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Warning: subMode mismatch - %#x:%#x, tid[%d]",
155699e3e6e72e3471eb85fc2e405866392b01c080febuzbee                subMode,thread->interpBreak.ctl.subMode,thread->threadId);
155799e3e6e72e3471eb85fc2e405866392b01c080febuzbee         }
155899e3e6e72e3471eb85fc2e405866392b01c080febuzbee        if (breakFlags != thread->interpBreak.ctl.breakFlags) {
1559062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Warning: breakFlags mismatch - %#x:%#x, tid[%d]",
156099e3e6e72e3471eb85fc2e405866392b01c080febuzbee                breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId);
156199e3e6e72e3471eb85fc2e405866392b01c080febuzbee         }
156275425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP
156399e3e6e72e3471eb85fc2e405866392b01c080febuzbee        if (handlerTable != thread->interpBreak.ctl.curHandlerTable) {
1564062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Warning: curHandlerTable mismatch - %#x:%#x, tid[%d]",
156599e3e6e72e3471eb85fc2e405866392b01c080febuzbee                (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable,
156699e3e6e72e3471eb85fc2e405866392b01c080febuzbee                thread->threadId);
156799e3e6e72e3471eb85fc2e405866392b01c080febuzbee         }
156875425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif
156999e3e6e72e3471eb85fc2e405866392b01c080febuzbee#if defined(WITH_JIT)
157099e3e6e72e3471eb85fc2e405866392b01c080febuzbee         if (thread->pJitProfTable != gDvmJit.pProfTable) {
1571062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block             ALOGD("Warning: pJitProfTable mismatch - %#x:%#x, tid[%d]",
157299e3e6e72e3471eb85fc2e405866392b01c080febuzbee                  (int)thread->pJitProfTable,(int)gDvmJit.pProfTable,
157399e3e6e72e3471eb85fc2e405866392b01c080febuzbee                  thread->threadId);
157499e3e6e72e3471eb85fc2e405866392b01c080febuzbee         }
157599e3e6e72e3471eb85fc2e405866392b01c080febuzbee         if (thread->jitThreshold != gDvmJit.threshold) {
1576062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block             ALOGD("Warning: jitThreshold mismatch - %#x:%#x, tid[%d]",
157799e3e6e72e3471eb85fc2e405866392b01c080febuzbee                  (int)thread->jitThreshold,(int)gDvmJit.threshold,
157899e3e6e72e3471eb85fc2e405866392b01c080febuzbee                  thread->threadId);
157999e3e6e72e3471eb85fc2e405866392b01c080febuzbee         }
158099e3e6e72e3471eb85fc2e405866392b01c080febuzbee#endif
158199e3e6e72e3471eb85fc2e405866392b01c080febuzbee    }
158299e3e6e72e3471eb85fc2e405866392b01c080febuzbee    dvmUnlockThreadList();
158399e3e6e72e3471eb85fc2e405866392b01c080febuzbee}
158499e3e6e72e3471eb85fc2e405866392b01c080febuzbee
158599e3e6e72e3471eb85fc2e405866392b01c080febuzbee/*
158694d65255849ce9f195c971f726e8b09449ba4d14buzbee * Arm a safepoint callback for a thread.  If funct is null,
158794d65255849ce9f195c971f726e8b09449ba4d14buzbee * clear any pending callback.
158894d65255849ce9f195c971f726e8b09449ba4d14buzbee * TODO: only gc is currently using this feature, and will have
158994d65255849ce9f195c971f726e8b09449ba4d14buzbee * at most a single outstanding callback request.  Until we need
159094d65255849ce9f195c971f726e8b09449ba4d14buzbee * something more capable and flexible, enforce this limit.
159194d65255849ce9f195c971f726e8b09449ba4d14buzbee */
159294d65255849ce9f195c971f726e8b09449ba4d14buzbeevoid dvmArmSafePointCallback(Thread* thread, SafePointCallback funct,
159394d65255849ce9f195c971f726e8b09449ba4d14buzbee                             void* arg)
159494d65255849ce9f195c971f726e8b09449ba4d14buzbee{
159594d65255849ce9f195c971f726e8b09449ba4d14buzbee    dvmLockMutex(&thread->callbackMutex);
159694d65255849ce9f195c971f726e8b09449ba4d14buzbee    if ((funct == NULL) || (thread->callback == NULL)) {
159794d65255849ce9f195c971f726e8b09449ba4d14buzbee        thread->callback = funct;
159894d65255849ce9f195c971f726e8b09449ba4d14buzbee        thread->callbackArg = arg;
1599cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        if (funct != NULL) {
1600cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            dvmEnableSubMode(thread, kSubModeCallbackPending);
1601cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        } else {
1602cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            dvmDisableSubMode(thread, kSubModeCallbackPending);
1603cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        }
160494d65255849ce9f195c971f726e8b09449ba4d14buzbee    } else {
160594d65255849ce9f195c971f726e8b09449ba4d14buzbee        // Already armed.  Different?
160694d65255849ce9f195c971f726e8b09449ba4d14buzbee        if ((funct != thread->callback) ||
160794d65255849ce9f195c971f726e8b09449ba4d14buzbee            (arg != thread->callbackArg)) {
160894d65255849ce9f195c971f726e8b09449ba4d14buzbee            // Yes - report failure and die
1609c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("ArmSafePointCallback failed, thread %d", thread->threadId);
161094d65255849ce9f195c971f726e8b09449ba4d14buzbee            dvmUnlockMutex(&thread->callbackMutex);
161194d65255849ce9f195c971f726e8b09449ba4d14buzbee            dvmAbort();
161294d65255849ce9f195c971f726e8b09449ba4d14buzbee        }
161394d65255849ce9f195c971f726e8b09449ba4d14buzbee    }
161494d65255849ce9f195c971f726e8b09449ba4d14buzbee    dvmUnlockMutex(&thread->callbackMutex);
161594d65255849ce9f195c971f726e8b09449ba4d14buzbee}
161694d65255849ce9f195c971f726e8b09449ba4d14buzbee
161794d65255849ce9f195c971f726e8b09449ba4d14buzbee/*
16189f601a917c8878204482c37aec7005054b6776fabuzbee * One-time initialization at thread creation.  Here we initialize
16199f601a917c8878204482c37aec7005054b6776fabuzbee * useful constants.
16202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
16219f601a917c8878204482c37aec7005054b6776fabuzbeevoid dvmInitInterpreterState(Thread* self)
16222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
1623ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
162438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /*
1625ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Reserve a static entity here to quickly setup runtime contents as
1626ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * gcc will issue block copy instructions.
1627ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
1628ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    static struct JitToInterpEntries jitToInterpEntries = {
1629ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpNormal,
1630ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpNoChain,
1631ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpPunt,
1632ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpSingleStep,
163340094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng        dvmJitToInterpTraceSelect,
163497319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#if defined(WITH_SELF_VERIFICATION)
163540094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng        dvmJitToInterpBackwardBranch,
16369f601a917c8878204482c37aec7005054b6776fabuzbee#else
16379f601a917c8878204482c37aec7005054b6776fabuzbee        NULL,
163897319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#endif
1639ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    };
16409f601a917c8878204482c37aec7005054b6776fabuzbee#endif
16419f601a917c8878204482c37aec7005054b6776fabuzbee
16429f601a917c8878204482c37aec7005054b6776fabuzbee    // Begin initialization
16439f601a917c8878204482c37aec7005054b6776fabuzbee    self->cardTable = gDvm.biasedCardTableBase;
16449f601a917c8878204482c37aec7005054b6776fabuzbee#if defined(WITH_JIT)
16459a3147c7412f4794434b4c2604aa2ba784867774buzbee    // One-time initializations
16469f601a917c8878204482c37aec7005054b6776fabuzbee    self->jitToInterpEntries = jitToInterpEntries;
16479f601a917c8878204482c37aec7005054b6776fabuzbee    self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
16489f601a917c8878204482c37aec7005054b6776fabuzbee    self->pProfileCountdown = &gDvmJit.profileCountdown;
16499a3147c7412f4794434b4c2604aa2ba784867774buzbee    // Jit state that can change
165099e3e6e72e3471eb85fc2e405866392b01c080febuzbee    dvmJitUpdateThreadStateSingle(self);
16519f601a917c8878204482c37aec7005054b6776fabuzbee#endif
16522ec9f7802034144383261b2fd915bdf1eb396ea4buzbee    dvmInitializeInterpBreak(self);
165399e3e6e72e3471eb85fc2e405866392b01c080febuzbee}
16547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
165599e3e6e72e3471eb85fc2e405866392b01c080febuzbee/*
165699e3e6e72e3471eb85fc2e405866392b01c080febuzbee * For a newly-created thread, we need to start off with interpBreak
165799e3e6e72e3471eb85fc2e405866392b01c080febuzbee * set to any existing global modes.  The caller must hold the
165899e3e6e72e3471eb85fc2e405866392b01c080febuzbee * thread list lock.
165999e3e6e72e3471eb85fc2e405866392b01c080febuzbee */
166099e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmInitializeInterpBreak(Thread* thread)
166199e3e6e72e3471eb85fc2e405866392b01c080febuzbee{
166299e3e6e72e3471eb85fc2e405866392b01c080febuzbee    if (gDvm.instructionCountEnableCount > 0) {
1663cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmEnableSubMode(thread, kSubModeInstCounting);
166499e3e6e72e3471eb85fc2e405866392b01c080febuzbee    }
166599e3e6e72e3471eb85fc2e405866392b01c080febuzbee    if (dvmIsMethodTraceActive()) {
1666cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmEnableSubMode(thread, kSubModeMethodTrace);
1667cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    }
1668cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    if (gDvm.emulatorTraceEnableCount > 0) {
1669cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmEnableSubMode(thread, kSubModeEmulatorTrace);
167099e3e6e72e3471eb85fc2e405866392b01c080febuzbee    }
167199e3e6e72e3471eb85fc2e405866392b01c080febuzbee    if (gDvm.debuggerActive) {
1672cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmEnableSubMode(thread, kSubModeDebuggerActive);
167399e3e6e72e3471eb85fc2e405866392b01c080febuzbee    }
16742ec9f7802034144383261b2fd915bdf1eb396ea4buzbee#if 0
16752ec9f7802034144383261b2fd915bdf1eb396ea4buzbee    // Debugging stress mode - force checkBefore
16762ec9f7802034144383261b2fd915bdf1eb396ea4buzbee    dvmEnableSubMode(thread, kSubModeCheckAlways);
16772ec9f7802034144383261b2fd915bdf1eb396ea4buzbee#endif
16789f601a917c8878204482c37aec7005054b6776fabuzbee}
16799f601a917c8878204482c37aec7005054b6776fabuzbee
1680a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee/*
1681a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee * Inter-instruction handler invoked in between instruction interpretations
1682a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee * to handle exceptional events such as debugging housekeeping, instruction
16839a3147c7412f4794434b4c2604aa2ba784867774buzbee * count profiling, JIT trace building, etc.  Dalvik PC has been exported
16849a3147c7412f4794434b4c2604aa2ba784867774buzbee * prior to call, but Thread copy of dPC & fp are not current.
1685a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee */
168694d65255849ce9f195c971f726e8b09449ba4d14buzbeevoid dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self)
1687a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee{
16889a3147c7412f4794434b4c2604aa2ba784867774buzbee    const Method* method = self->interpSave.method;
16899a3147c7412f4794434b4c2604aa2ba784867774buzbee    assert(pc >= method->insns && pc <
16909a3147c7412f4794434b4c2604aa2ba784867774buzbee           method->insns + dvmGetMethodInsnsSize(method));
16919a3147c7412f4794434b4c2604aa2ba784867774buzbee
16929a3147c7412f4794434b4c2604aa2ba784867774buzbee#if 0
16939a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
16949a3147c7412f4794434b4c2604aa2ba784867774buzbee     * When we hit a specific method, enable verbose instruction logging.
16959a3147c7412f4794434b4c2604aa2ba784867774buzbee     * Sometimes it's helpful to use the debugger attach as a trigger too.
16969a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
16979a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (*pIsMethodEntry) {
16989a3147c7412f4794434b4c2604aa2ba784867774buzbee        static const char* cd = "Landroid/test/Arithmetic;";
16999a3147c7412f4794434b4c2604aa2ba784867774buzbee        static const char* mn = "shiftTest2";
17009a3147c7412f4794434b4c2604aa2ba784867774buzbee        static const char* sg = "()V";
17019a3147c7412f4794434b4c2604aa2ba784867774buzbee
17029a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/
17039a3147c7412f4794434b4c2604aa2ba784867774buzbee            strcmp(method->clazz->descriptor, cd) == 0 &&
17049a3147c7412f4794434b4c2604aa2ba784867774buzbee            strcmp(method->name, mn) == 0 &&
17059a3147c7412f4794434b4c2604aa2ba784867774buzbee            strcmp(method->shorty, sg) == 0)
17069a3147c7412f4794434b4c2604aa2ba784867774buzbee        {
1707e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Reached %s.%s, enabling verbose mode",
17089a3147c7412f4794434b4c2604aa2ba784867774buzbee                method->clazz->descriptor, method->name);
17099a3147c7412f4794434b4c2604aa2ba784867774buzbee            android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE);
17109a3147c7412f4794434b4c2604aa2ba784867774buzbee            dumpRegs(method, fp, true);
17119a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
17129a3147c7412f4794434b4c2604aa2ba784867774buzbee
17139a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (!gDvm.debuggerActive)
17149a3147c7412f4794434b4c2604aa2ba784867774buzbee            *pIsMethodEntry = false;
17159a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
17169a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
17179a3147c7412f4794434b4c2604aa2ba784867774buzbee
171894d65255849ce9f195c971f726e8b09449ba4d14buzbee    /* Safe point handling */
1719389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee    if (self->suspendCount ||
1720cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) {
1721c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee        // Are we are a safe point?
1722c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee        int flags;
1723c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee        flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
17246e0be609807de9fabe1b63a75f7c7d619bfa2f9fJesse Wilson        if (flags & (VERIFY_GC_INST_MASK & ~kInstrCanThrow)) {
172594d65255849ce9f195c971f726e8b09449ba4d14buzbee            // Yes, at a safe point.  Pending callback?
1726cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) {
172794d65255849ce9f195c971f726e8b09449ba4d14buzbee                SafePointCallback callback;
172894d65255849ce9f195c971f726e8b09449ba4d14buzbee                void* arg;
172994d65255849ce9f195c971f726e8b09449ba4d14buzbee                // Get consistent funct/arg pair
173094d65255849ce9f195c971f726e8b09449ba4d14buzbee                dvmLockMutex(&self->callbackMutex);
173194d65255849ce9f195c971f726e8b09449ba4d14buzbee                callback = self->callback;
173294d65255849ce9f195c971f726e8b09449ba4d14buzbee                arg = self->callbackArg;
173394d65255849ce9f195c971f726e8b09449ba4d14buzbee                dvmUnlockMutex(&self->callbackMutex);
173494d65255849ce9f195c971f726e8b09449ba4d14buzbee                // Update Thread structure
173594d65255849ce9f195c971f726e8b09449ba4d14buzbee                self->interpSave.pc = pc;
173630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee                self->interpSave.curFrame = fp;
173794d65255849ce9f195c971f726e8b09449ba4d14buzbee                if (callback != NULL) {
173894d65255849ce9f195c971f726e8b09449ba4d14buzbee                    // Do the callback
173994d65255849ce9f195c971f726e8b09449ba4d14buzbee                    if (!callback(self,arg)) {
174094d65255849ce9f195c971f726e8b09449ba4d14buzbee                        // disarm
174194d65255849ce9f195c971f726e8b09449ba4d14buzbee                        dvmArmSafePointCallback(self, NULL, NULL);
174294d65255849ce9f195c971f726e8b09449ba4d14buzbee                    }
174394d65255849ce9f195c971f726e8b09449ba4d14buzbee                }
174494d65255849ce9f195c971f726e8b09449ba4d14buzbee            }
174594d65255849ce9f195c971f726e8b09449ba4d14buzbee            // Need to suspend?
1746389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee            if (self->suspendCount) {
174794d65255849ce9f195c971f726e8b09449ba4d14buzbee                dvmExportPC(pc, fp);
174894d65255849ce9f195c971f726e8b09449ba4d14buzbee                dvmCheckSuspendPending(self);
174994d65255849ce9f195c971f726e8b09449ba4d14buzbee            }
1750c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee        }
17519a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
17529a3147c7412f4794434b4c2604aa2ba784867774buzbee
17539a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
1754e71474621b968a9bc649d067155d31213f5764a9buzbee        updateDebugger(method, pc, fp, self);
17559a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
17569a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (gDvm.instructionCountEnableCount != 0) {
17579a3147c7412f4794434b4c2604aa2ba784867774buzbee        /*
17589a3147c7412f4794434b4c2604aa2ba784867774buzbee         * Count up the #of executed instructions.  This isn't synchronized
17599a3147c7412f4794434b4c2604aa2ba784867774buzbee         * for thread-safety; if we need that we should make this
17609a3147c7412f4794434b4c2604aa2ba784867774buzbee         * thread-local and merge counts into the global area when threads
17619a3147c7412f4794434b4c2604aa2ba784867774buzbee         * exit (perhaps suspending all other threads GC-style and pulling
17629a3147c7412f4794434b4c2604aa2ba784867774buzbee         * the data out of them).
17639a3147c7412f4794434b4c2604aa2ba784867774buzbee         */
17649a3147c7412f4794434b4c2604aa2ba784867774buzbee        gDvm.executedInstrCounts[GET_OPCODE(*pc)]++;
17659a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
17669a3147c7412f4794434b4c2604aa2ba784867774buzbee
17679a3147c7412f4794434b4c2604aa2ba784867774buzbee
17689a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_TRACKREF_CHECKS)
17699a3147c7412f4794434b4c2604aa2ba784867774buzbee    dvmInterpCheckTrackedRefs(self, method,
17709a3147c7412f4794434b4c2604aa2ba784867774buzbee                              self->interpSave.debugTrackedRefStart);
17719a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
17729a3147c7412f4794434b4c2604aa2ba784867774buzbee
17739a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
17749a3147c7412f4794434b4c2604aa2ba784867774buzbee    // Does the JIT need anything done now?
1775cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    if (self->interpBreak.ctl.subMode &
1776cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            (kSubModeJitTraceBuild | kSubModeJitSV)) {
17779a3147c7412f4794434b4c2604aa2ba784867774buzbee        // Are we building a trace?
17789a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
17799a3147c7412f4794434b4c2604aa2ba784867774buzbee            dvmCheckJit(pc, self);
17809a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
17819a3147c7412f4794434b4c2604aa2ba784867774buzbee
17829a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_SELF_VERIFICATION)
17839a3147c7412f4794434b4c2604aa2ba784867774buzbee        // Are we replaying a trace?
17849a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->interpBreak.ctl.subMode & kSubModeJitSV) {
17859a3147c7412f4794434b4c2604aa2ba784867774buzbee            dvmCheckSelfVerification(pc, self);
17869a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
17879a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
17889a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
17899a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
17909a3147c7412f4794434b4c2604aa2ba784867774buzbee
17919a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
1792313d430d5b3b96b45370ccddee52a6d88a799f35Ben Cheng     * CountedStep processing.  NOTE: must be the last here to allow
17939a3147c7412f4794434b4c2604aa2ba784867774buzbee     * preceeding special case handler to manipulate single-step count.
17949a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
1795313d430d5b3b96b45370ccddee52a6d88a799f35Ben Cheng    if (self->interpBreak.ctl.subMode & kSubModeCountedStep) {
17969a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->singleStepCount == 0) {
17979a3147c7412f4794434b4c2604aa2ba784867774buzbee            // We've exhausted our single step count
1798cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee            dvmDisableSubMode(self, kSubModeCountedStep);
17999a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
18009a3147c7412f4794434b4c2604aa2ba784867774buzbee#if 0
18019a3147c7412f4794434b4c2604aa2ba784867774buzbee            /*
18029a3147c7412f4794434b4c2604aa2ba784867774buzbee             * For debugging.  If jitResumeDPC is non-zero, then
18039a3147c7412f4794434b4c2604aa2ba784867774buzbee             * we expect to return to a trace in progress.   There
18049a3147c7412f4794434b4c2604aa2ba784867774buzbee             * are valid reasons why we wouldn't (such as an exception
18059a3147c7412f4794434b4c2604aa2ba784867774buzbee             * throw), but here we can keep track.
18069a3147c7412f4794434b4c2604aa2ba784867774buzbee             */
18079a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (self->jitResumeDPC != NULL) {
18089a3147c7412f4794434b4c2604aa2ba784867774buzbee                if (self->jitResumeDPC == pc) {
18099a3147c7412f4794434b4c2604aa2ba784867774buzbee                    if (self->jitResumeNPC != NULL) {
1810062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block                        ALOGD("SS return to trace - pc:%#x to 0x:%x",
18119a3147c7412f4794434b4c2604aa2ba784867774buzbee                             (int)pc, (int)self->jitResumeNPC);
18129a3147c7412f4794434b4c2604aa2ba784867774buzbee                    } else {
1813062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block                        ALOGD("SS return to interp - pc:%#x",(int)pc);
18149a3147c7412f4794434b4c2604aa2ba784867774buzbee                    }
18159a3147c7412f4794434b4c2604aa2ba784867774buzbee                } else {
1816062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block                    ALOGD("SS failed to return.  Expected %#x, now at %#x",
18179a3147c7412f4794434b4c2604aa2ba784867774buzbee                         (int)self->jitResumeDPC, (int)pc);
18189a3147c7412f4794434b4c2604aa2ba784867774buzbee                }
18199a3147c7412f4794434b4c2604aa2ba784867774buzbee            }
18209a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
1821e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng#if 0
1822e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng            // TODO - fix JIT single-stepping resume mode (b/5551114)
1823e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng            // self->jitResumeNPC needs to be cleared in callPrep
1824e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng
18259a3147c7412f4794434b4c2604aa2ba784867774buzbee            // If we've got a native return and no other reasons to
18269a3147c7412f4794434b4c2604aa2ba784867774buzbee            // remain in singlestep/break mode, do a long jump
18279a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (self->jitResumeNPC != NULL &&
18289a3147c7412f4794434b4c2604aa2ba784867774buzbee                self->interpBreak.ctl.breakFlags == 0) {
18299a3147c7412f4794434b4c2604aa2ba784867774buzbee                assert(self->jitResumeDPC == pc);
18309a3147c7412f4794434b4c2604aa2ba784867774buzbee                self->jitResumeDPC = NULL;
18319a3147c7412f4794434b4c2604aa2ba784867774buzbee                dvmJitResumeTranslation(self, pc, fp);
18329a3147c7412f4794434b4c2604aa2ba784867774buzbee                // Doesn't return
18339a3147c7412f4794434b4c2604aa2ba784867774buzbee                dvmAbort();
18349a3147c7412f4794434b4c2604aa2ba784867774buzbee            }
18350c0624bfad83503547b0226bd2dfac055782582aBen Cheng            // In case resume is blocked by non-zero breakFlags, clear
18360c0624bfad83503547b0226bd2dfac055782582aBen Cheng            // jitResumeNPC here.
18370c0624bfad83503547b0226bd2dfac055782582aBen Cheng            self->jitResumeNPC = NULL;
18389a3147c7412f4794434b4c2604aa2ba784867774buzbee            self->jitResumeDPC = NULL;
18397209bdd8ded13e5ea1b936c8836a9a798ccfa688buzbee            self->inJitCodeCache = NULL;
18409a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
1841e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng#endif
18429a3147c7412f4794434b4c2604aa2ba784867774buzbee        } else {
18439a3147c7412f4794434b4c2604aa2ba784867774buzbee            self->singleStepCount--;
18449a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
18459a3147c7412f4794434b4c2604aa2ba784867774buzbee            if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) {
18469a3147c7412f4794434b4c2604aa2ba784867774buzbee                /*
18479a3147c7412f4794434b4c2604aa2ba784867774buzbee                 * Direct return to an existing translation following a
18489a3147c7412f4794434b4c2604aa2ba784867774buzbee                 * single step is valid only if we step once.  If we're
18499a3147c7412f4794434b4c2604aa2ba784867774buzbee                 * here, an additional step was added so we need to invalidate
18509a3147c7412f4794434b4c2604aa2ba784867774buzbee                 * the return to translation.
18519a3147c7412f4794434b4c2604aa2ba784867774buzbee                 */
18529a3147c7412f4794434b4c2604aa2ba784867774buzbee                self->jitResumeNPC = NULL;
18537209bdd8ded13e5ea1b936c8836a9a798ccfa688buzbee                self->inJitCodeCache = NULL;
18549a3147c7412f4794434b4c2604aa2ba784867774buzbee            }
18559a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
18569a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
18579a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
1858a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee}
18599f601a917c8878204482c37aec7005054b6776fabuzbee
18609f601a917c8878204482c37aec7005054b6776fabuzbee/*
18619a3147c7412f4794434b4c2604aa2ba784867774buzbee * Main interpreter loop entry point.
18629f601a917c8878204482c37aec7005054b6776fabuzbee *
18639f601a917c8878204482c37aec7005054b6776fabuzbee * This begins executing code at the start of "method".  On exit, "pResult"
18649f601a917c8878204482c37aec7005054b6776fabuzbee * holds the return value of the method (or, if "method" returns NULL, it
18659f601a917c8878204482c37aec7005054b6776fabuzbee * holds an undefined value).
18669f601a917c8878204482c37aec7005054b6776fabuzbee *
18679f601a917c8878204482c37aec7005054b6776fabuzbee * The interpreted stack frame, which holds the method arguments, has
18689f601a917c8878204482c37aec7005054b6776fabuzbee * already been set up.
18699f601a917c8878204482c37aec7005054b6776fabuzbee */
18709f601a917c8878204482c37aec7005054b6776fabuzbeevoid dvmInterpret(Thread* self, const Method* method, JValue* pResult)
18719f601a917c8878204482c37aec7005054b6776fabuzbee{
18729f601a917c8878204482c37aec7005054b6776fabuzbee    InterpSaveState interpSaveState;
1873cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    ExecutionSubModes savedSubModes;
18749a3147c7412f4794434b4c2604aa2ba784867774buzbee
18759f601a917c8878204482c37aec7005054b6776fabuzbee#if defined(WITH_JIT)
18769f601a917c8878204482c37aec7005054b6776fabuzbee    /* Target-specific save/restore */
18779f601a917c8878204482c37aec7005054b6776fabuzbee    double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
18787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /*
18797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * If the previous VM left the code cache through single-stepping the
18807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * inJitCodeCache flag will be set when the VM is re-entered (for example,
18817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * in self-verification mode we single-step NEW_INSTANCE which may re-enter
18827a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * the VM through findClassFromLoaderNoInit). Because of that, we cannot
18837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * assert that self->inJitCodeCache is NULL here.
18847a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     */
1885ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
1886ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
18879f601a917c8878204482c37aec7005054b6776fabuzbee    /*
18889f601a917c8878204482c37aec7005054b6776fabuzbee     * Save interpreter state from previous activation, linking
18899f601a917c8878204482c37aec7005054b6776fabuzbee     * new to last.
18909f601a917c8878204482c37aec7005054b6776fabuzbee     */
18919f601a917c8878204482c37aec7005054b6776fabuzbee    interpSaveState = self->interpSave;
18929f601a917c8878204482c37aec7005054b6776fabuzbee    self->interpSave.prev = &interpSaveState;
18939a3147c7412f4794434b4c2604aa2ba784867774buzbee    /*
18949a3147c7412f4794434b4c2604aa2ba784867774buzbee     * Strip out and save any flags that should not be inherited by
18959a3147c7412f4794434b4c2604aa2ba784867774buzbee     * nested interpreter activation.
18969a3147c7412f4794434b4c2604aa2ba784867774buzbee     */
1897cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    savedSubModes = (ExecutionSubModes)(
1898cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee              self->interpBreak.ctl.subMode & LOCAL_SUBMODE);
1899cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    if (savedSubModes != kSubModeNormal) {
1900cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmDisableSubMode(self, savedSubModes);
19019a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
19029f601a917c8878204482c37aec7005054b6776fabuzbee#if defined(WITH_JIT)
19039f601a917c8878204482c37aec7005054b6776fabuzbee    dvmJitCalleeSave(calleeSave);
19049f601a917c8878204482c37aec7005054b6776fabuzbee#endif
19059f601a917c8878204482c37aec7005054b6776fabuzbee
19062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
19072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS)
1908ef5db621255680dbbe46cfcce572989deea64387buzbee    self->interpSave.debugTrackedRefStart =
19092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmReferenceTableEntries(&self->internalLocalRefTable);
19102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
19119f601a917c8878204482c37aec7005054b6776fabuzbee    self->debugIsMethodEntry = true;
1912ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
19139f601a917c8878204482c37aec7005054b6776fabuzbee    dvmJitCalleeSave(calleeSave);
1914a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /* Initialize the state to kJitNot */
19159f601a917c8878204482c37aec7005054b6776fabuzbee    self->jitState = kJitNot;
1916ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
19172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
19182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
19192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Initialize working state.
19202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
19212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * No need to initialize "retval".
19222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
19239f601a917c8878204482c37aec7005054b6776fabuzbee    self->interpSave.method = method;
192430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    self->interpSave.curFrame = (u4*) self->interpSave.curFrame;
19259f601a917c8878204482c37aec7005054b6776fabuzbee    self->interpSave.pc = method->insns;
19262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
19272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(!dvmIsNativeMethod(method));
19282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
19292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
19302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Make sure the class is ready to go.  Shouldn't be possible to get
19312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * here otherwise.
19322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
19332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (method->clazz->status < CLASS_INITIALIZING ||
19342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        method->clazz->status == CLASS_ERROR)
19352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    {
1936c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("ERROR: tried to execute code in unprepared class '%s' (%d)",
19372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            method->clazz->descriptor, method->clazz->status);
19382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmDumpThread(self, false);
19392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmAbort();
19402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
19412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
19429a3147c7412f4794434b4c2604aa2ba784867774buzbee    typedef void (*Interpreter)(Thread*);
19432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Interpreter stdInterp;
19442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (gDvm.executionMode == kExecutionModeInterpFast)
19452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        stdInterp = dvmMterpStd;
1946ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
19470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    else if (gDvm.executionMode == kExecutionModeJit ||
19480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen             gDvm.executionMode == kExecutionModeNcgO0 ||
19490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen             gDvm.executionMode == kExecutionModeNcgO1)
1950ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        stdInterp = dvmMterpStd;
1951ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
19522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    else
19539a3147c7412f4794434b4c2604aa2ba784867774buzbee        stdInterp = dvmInterpretPortable;
19549a3147c7412f4794434b4c2604aa2ba784867774buzbee
19559a3147c7412f4794434b4c2604aa2ba784867774buzbee    // Call the interpreter
19569a3147c7412f4794434b4c2604aa2ba784867774buzbee    (*stdInterp)(self);
19572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1958cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee    *pResult = self->interpSave.retval;
19599f601a917c8878204482c37aec7005054b6776fabuzbee
19609f601a917c8878204482c37aec7005054b6776fabuzbee    /* Restore interpreter state from previous activation */
19619f601a917c8878204482c37aec7005054b6776fabuzbee    self->interpSave = interpSaveState;
1962342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee#if defined(WITH_JIT)
19639f601a917c8878204482c37aec7005054b6776fabuzbee    dvmJitCalleeRestore(calleeSave);
1964342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee#endif
1965cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee    if (savedSubModes != kSubModeNormal) {
1966cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmEnableSubMode(self, savedSubModes);
19679a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
19682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
1969