Interp.c revision c7a12b2fc8270722c7de8d24fd8fa943e5ef1818
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 *
242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Some debugger support functions are included here.  Ideally their
252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * entire existence would be "#ifdef WITH_DEBUGGER", but we're not that
262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * aggressive in other parts of the code yet.
272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#include "Dalvik.h"
292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#include "interp/InterpDefs.h"
302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *      Debugger support
352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden// fwd
3996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic BreakpointSet* dvmBreakpointSetAlloc(void);
4096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetFree(BreakpointSet* pSet);
4196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
4396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Initialize global breakpoint structures.
4496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
4596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmBreakpointStartup(void)
4696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
4796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#ifdef WITH_DEBUGGER
4896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    gDvm.breakpointSet = dvmBreakpointSetAlloc();
4996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return (gDvm.breakpointSet != NULL);
5096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#else
5196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return true;
5296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#endif
5396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
5496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
5596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
5696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Free resources.
5796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
5896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmBreakpointShutdown(void)
5996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
6096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#ifdef WITH_DEBUGGER
6196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetFree(gDvm.breakpointSet);
6296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#endif
6396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
6496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
6596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
6696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#ifdef WITH_DEBUGGER
6796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
6896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This represents a breakpoint inserted in the instruction stream.
692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
7096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The debugger may ask us to create the same breakpoint multiple times.
7196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * We only remove the breakpoint when the last instance is cleared.
7296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
7396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddentypedef struct {
74d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    Method*     method;                 /* method we're associated with */
7596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    u2*         addr;                   /* absolute memory address */
7696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    u1          originalOpCode;         /* original 8-bit opcode value */
7796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int         setCount;               /* #of times this breakpoint was set */
7896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} Breakpoint;
7996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
8096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
8196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Set of breakpoints.
8296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
8396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstruct BreakpointSet {
8496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* grab lock before reading or writing anything else in here */
8596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    pthread_mutex_t lock;
8696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
8796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* vector of breakpoint structures */
8896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int         alloc;
8996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int         count;
9096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    Breakpoint* breakpoints;
9196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden};
9296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
9396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
9496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Initialize a BreakpointSet.  Initially empty.
9596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
9696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic BreakpointSet* dvmBreakpointSetAlloc(void)
9796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
9896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
9996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
10096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmInitMutex(&pSet->lock);
10196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* leave the rest zeroed -- will alloc on first use */
10296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
10396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return pSet;
10496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
10596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
10696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
10796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Free storage associated with a BreakpointSet.
10896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
10996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetFree(BreakpointSet* pSet)
11096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
11196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (pSet == NULL)
11296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        return;
11396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
11496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    free(pSet->breakpoints);
11596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    free(pSet);
11696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
11796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
11896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
11996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Lock the breakpoint set.
120d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden *
121d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * It's not currently necessary to switch to VMWAIT in the event of
122d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * contention, because nothing in here can block.  However, it's possible
123d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * that the bytecode-updater code could become fancier in the future, so
124d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * we do the trylock dance as a bit of future-proofing.
12596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
12696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetLock(BreakpointSet* pSet)
12796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
128d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    if (dvmTryLockMutex(&pSet->lock) != 0) {
129d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        Thread* self = dvmThreadSelf();
130d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        int oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
131d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        dvmLockMutex(&pSet->lock);
132d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        dvmChangeStatus(self, oldStatus);
133d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    }
13496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
13596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
13696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
13796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Unlock the breakpoint set.
13896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
13996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetUnlock(BreakpointSet* pSet)
14096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
14196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmUnlockMutex(&pSet->lock);
14296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
14396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
14496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
14596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Return the #of breakpoints.
14696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
14796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic int dvmBreakpointSetCount(const BreakpointSet* pSet)
14896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
14996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return pSet->count;
15096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
15196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
15296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
15396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * See if we already have an entry for this address.
15496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
15596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
15696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
15796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns the index of the breakpoint entry, or -1 if not found.
15896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
15996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
16096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
16196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int i;
16296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
16396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    for (i = 0; i < pSet->count; i++) {
16496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        Breakpoint* pBreak = &pSet->breakpoints[i];
16596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (pBreak->addr == addr)
16696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            return i;
16796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
16896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
16996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return -1;
17096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
17196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
17296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
17396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Retrieve the opcode that was originally at the specified location.
17496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
17596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
17696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
17796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" with the opcode in *pOrig on success.
17896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
17996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic bool dvmBreakpointSetOriginalOpCode(const BreakpointSet* pSet,
18096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const u2* addr, u1* pOrig)
18196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
18296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int idx = dvmBreakpointSetFind(pSet, addr);
18396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (idx < 0)
18496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        return false;
18596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
18696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    *pOrig = pSet->breakpoints[idx].originalOpCode;
18796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return true;
18896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
18996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
19096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
19196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Add a breakpoint at a specific address.  If the address is already
19296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * present in the table, this just increments the count.
19396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
19496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * For a new entry, this will extract and preserve the current opcode from
19596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * the instruction stream, and replace it with a breakpoint opcode.
19696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
19796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
19896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
19996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success.
20096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
20196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
20296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    unsigned int instrOffset)
20396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
20496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const int kBreakpointGrowth = 10;
20596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const u2* addr = method->insns + instrOffset;
20696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int idx = dvmBreakpointSetFind(pSet, addr);
20796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    Breakpoint* pBreak;
20896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
20996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (idx < 0) {
21096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (pSet->count == pSet->alloc) {
21196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            int newSize = pSet->alloc + kBreakpointGrowth;
21296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            Breakpoint* newVec;
21396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
21496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            LOGV("+++ increasing breakpoint set size to %d\n", newSize);
21596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
21696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            /* pSet->breakpoints will be NULL on first entry */
21796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            newVec = realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
21896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            if (newVec == NULL)
21996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                return false;
22096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
22196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->breakpoints = newVec;
22296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->alloc = newSize;
22396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
22496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
22596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak = &pSet->breakpoints[pSet->count++];
226d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        pBreak->method = method;
22796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak->addr = (u2*)addr;
22896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak->originalOpCode = *(u1*)addr;
22996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        pBreak->setCount = 1;
23096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
23196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        /*
23296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden         * Change the opcode.  We must ensure that the BreakpointSet
23396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden         * updates happen before we change the opcode.
234d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         *
235d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * If the method has not been verified, we do NOT insert the
236d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * breakpoint yet, since that will screw up the verifier.  The
237d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * debugger is allowed to insert breakpoints in unverified code,
238d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * but since we don't execute unverified code we don't need to
239d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         * alter the bytecode yet.
240d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         *
241c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden         * The class init code will "flush" all pending opcode writes
242c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden         * before verification completes.
24396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden         */
24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        assert(*(u1*)addr != OP_BREAKPOINT);
245d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        if (dvmIsClassVerified(method->clazz)) {
246d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            LOGV("Class %s verified, adding breakpoint at %p\n",
247d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden                method->clazz->descriptor, addr);
248c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden            MEM_BARRIER();
249d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr, OP_BREAKPOINT);
250d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        } else {
251d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
252d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden                method->clazz->descriptor, addr);
253d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        }
25496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    } else {
255d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        /*
256c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden         * Breakpoint already exists, just increase the count.
257d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden         */
258c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden        pBreak = &pSet->breakpoints[idx];
259c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden        pBreak->setCount++;
26096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
26296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return true;
26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
26596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
26696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Remove one instance of the specified breakpoint.  When the count
26796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * reaches zero, the entry is removed from the table, and the original
26896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * opcode is restored.
26996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
27096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
27196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
27296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
27396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    unsigned int instrOffset)
27496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    const u2* addr = method->insns + instrOffset;
27696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int idx = dvmBreakpointSetFind(pSet, addr);
27796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
27896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (idx < 0) {
27996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        /* breakpoint not found in set -- unexpected */
28096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (*(u1*)addr == OP_BREAKPOINT) {
28196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            LOGE("Unable to restore breakpoint opcode (%s.%s +%u)\n",
28296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                method->clazz->descriptor, method->name, instrOffset);
28396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            dvmAbort();
28496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        } else {
28596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            LOGW("Breakpoint was already restored? (%s.%s +%u)\n",
28696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                method->clazz->descriptor, method->name, instrOffset);
28796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
28896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    } else {
28996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        Breakpoint* pBreak = &pSet->breakpoints[idx];
29096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (pBreak->setCount == 1) {
29196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            /*
29296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden             * Must restore opcode before removing set entry.
293d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             *
294d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * If the breakpoint was never flushed, we could be ovewriting
295d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * a value with the same value.  Not a problem, though we
296d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * could end up causing a copy-on-write here when we didn't
297d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * need to.  (Not worth worrying about.)
29896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden             */
29996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
30096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                pBreak->originalOpCode);
30196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            MEM_BARRIER();
30296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
30396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            if (idx != pSet->count-1) {
30496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                /* shift down */
30596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
30696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden                    (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
30796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            }
30896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->count--;
30996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
31096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        } else {
31196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            pBreak->setCount--;
31296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            assert(pBreak->setCount > 0);
31396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
31496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
31596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
31696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
31796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
318d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * Flush any breakpoints associated with methods in "clazz".  We want to
319d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * change the opcode, which might not have happened when the breakpoint
320d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * was initially set because the class was in the process of being
321d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * verified.
32296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
32396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here.
32496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
325d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFaddenstatic void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
32696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
32796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    int i;
32896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    for (i = 0; i < pSet->count; i++) {
32996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        Breakpoint* pBreak = &pSet->breakpoints[i];
330d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        if (pBreak->method->clazz == clazz) {
331d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            /*
332d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * The breakpoint is associated with a method in this class.
333d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * It might already be there or it might not; either way,
334d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             * flush it out.
335d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden             */
336d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            LOGV("Flushing breakpoint at %p for %s\n",
337d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden                pBreak->addr, clazz->descriptor);
338d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr, OP_BREAKPOINT);
33996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
34096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
34196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
34296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#endif /*WITH_DEBUGGER*/
34396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
34496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
34596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
34696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Do any debugger-attach-time initialization.
3472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
3482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInitBreakpoints(void)
3492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
3502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
35196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    /* quick sanity check */
35296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
35396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
35496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (dvmBreakpointSetCount(pSet) != 0) {
35596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
35696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        /* generally not good, but we can keep going */
35796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
35896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
3592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
3602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
3612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
3622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
3632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
3652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add an address to the list, putting it in the first non-empty slot.
3662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
3672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Sometimes the debugger likes to add two entries for one breakpoint.
3682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We add two entries here, so that we get the right behavior when it's
3692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * removed twice.
3702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
3712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This will only be run from the JDWP thread, and it will happen while
3722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we are updating the event list, which is synchronized.  We're guaranteed
3732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * to be the only one adding entries, and the lock ensures that nobody
3742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * will be trying to remove them while we're in here.
3752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
3762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "addr" is the absolute address of the breakpoint bytecode.
3772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
37896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmAddBreakAddr(Method* method, unsigned int instrOffset)
3792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
3802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
38196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
38296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
38396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetAdd(pSet, method, instrOffset);
38496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
3852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
3862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
3872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
3882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
3892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
3912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Remove an address from the list by setting the entry to NULL.
3922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
3932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This can be called from the JDWP thread (because the debugger has
3942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * cancelled the breakpoint) or from an event thread (because it's a
3952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * single-shot breakpoint, e.g. "run to line").  We only get here as
3962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the result of removing an entry from the event list, which is
3972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * synchronized, so it should not be possible for two threads to be
3982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * updating breakpoints at the same time.
3992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
40096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmClearBreakAddr(Method* method, unsigned int instrOffset)
4012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
4022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
40396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
40496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
40596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetRemove(pSet, method, instrOffset);
40696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
4072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
4092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
4102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
4112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
4122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
41396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#ifdef WITH_DEBUGGER
41496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
41596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Get the original opcode from under a breakpoint.
41696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
41796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenu1 dvmGetOriginalOpCode(const u2* addr)
41896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
41996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
42096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    u1 orig = 0;
42196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
42296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetLock(pSet);
42396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (!dvmBreakpointSetOriginalOpCode(pSet, addr, &orig)) {
42496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        orig = *(u1*)addr;
42596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        if (orig == OP_BREAKPOINT) {
42696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
42796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden            dvmAbort();
42896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        }
42996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
43096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
43196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
43296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return orig;
43396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
43496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
43596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
436d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * Flush any breakpoints associated with methods in "clazz".
43796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
438d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * We don't want to modify the bytecode of a method before the verifier
439d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * gets a chance to look at it, so we postpone opcode replacement until
440d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * after verification completes.
44196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
442d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFaddenvoid dvmFlushBreakpoints(ClassObject* clazz)
44396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
44496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    BreakpointSet* pSet = gDvm.breakpointSet;
44596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
446d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    if (pSet == NULL)
447d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden        return;
44896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
449d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    assert(dvmIsClassVerified(clazz));
450d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    dvmBreakpointSetLock(pSet);
451d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    dvmBreakpointSetFlush(pSet, clazz);
45296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    dvmBreakpointSetUnlock(pSet);
45396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
45496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#endif
45596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
4562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
4572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add a single step event.  Currently this is a global item.
4582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We set up some initial values based on the thread's current state.  This
4602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * won't work well if the thread is running, so it's up to the caller to
4612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * verify that it's suspended.
4622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This is only called from the JDWP thread.
4642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
4652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectbool dvmAddSingleStep(Thread* thread, int size, int depth)
4662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
4672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
4682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    StepControl* pCtrl = &gDvm.stepControl;
4692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (pCtrl->active && thread != pCtrl->thread) {
4712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGW("WARNING: single-step active for %p; adding %p\n",
4722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            pCtrl->thread, thread);
4732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /*
4752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * Keep going, overwriting previous.  This can happen if you
4762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * suspend a thread in Object.wait, hit the single-step key, then
4772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * switch to another thread and do the same thing again.
4782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * The first thread's step is still pending.
4792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         *
4802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * TODO: consider making single-step per-thread.  Adds to the
4812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * overhead, but could be useful in rare situations.
4822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         */
4832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
4842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->size = size;
4862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->depth = depth;
4872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->thread = thread;
4882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
4902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * We may be stepping into or over method calls, or running until we
4912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * return from the current method.  To make this work we need to track
4922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * the current line, current method, and current stack depth.  We need
4932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * to be checking these after most instructions, notably those that
4942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * call methods, return from methods, or are on a different line from the
4952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * previous instruction.
4962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
4972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * We have to start with a snapshot of the current state.  If we're in
4982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * an interpreted method, everything we need is in the current frame.  If
4992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we're in a native method, possibly with some extra JNI frames pushed
5002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * on by PushLocalFrame, we want to use the topmost native method.
5012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const StackSaveArea* saveArea;
5032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    void* fp;
5042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    void* prevFp = NULL;
50538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
5062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
5072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        const Method* method;
5082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
5102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        method = saveArea->method;
5112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (!dvmIsBreakFrame(fp) && !dvmIsNativeMethod(method))
5132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
5142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        prevFp = fp;
5152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (fp == NULL) {
5172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGW("Unexpected: step req in native-only threadid=%d\n",
5182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            thread->threadId);
5192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
5202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (prevFp != NULL) {
5222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /*
5232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * First interpreted frame wasn't the one at the bottom.  Break
5242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * frames are only inserted when calling from native->interp, so we
5252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * don't need to worry about one being here.
5262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         */
5272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGV("##### init step while in native method\n");
5282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        fp = prevFp;
5292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(!dvmIsBreakFrame(fp));
5302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
5312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
5322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
5352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Pull the goodies out.  "xtra.currentPc" should be accurate since
5362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we update it on every instruction while the debugger is connected.
5372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->method = saveArea->method;
5392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    // Clear out any old address set
5402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (pCtrl->pAddressSet != NULL) {
5412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        // (discard const)
5422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        free((void *)pCtrl->pAddressSet);
5432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->pAddressSet = NULL;
5442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsNativeMethod(pCtrl->method)) {
5462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line = -1;
5472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    } else {
5482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line = dvmLineNumFromPC(saveArea->method,
5492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                        saveArea->xtra.currentPc - saveArea->method->insns);
55038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        pCtrl->pAddressSet
5512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                = dvmAddressSetForLine(saveArea->method, pCtrl->line);
5522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
5542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->active = true;
5552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
5572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->thread, pCtrl->method, pCtrl->method->name,
5582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line, pCtrl->frameDepth,
5592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmJdwpStepDepthStr(pCtrl->depth),
5602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmJdwpStepSizeStr(pCtrl->size));
5612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return true;
5632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
5642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
5652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return false;
5662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
5672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
5682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
5702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Disable a single step event.
5712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
5722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmClearSingleStep(Thread* thread)
5732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
5742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
5752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    UNUSED_PARAMETER(thread);
5762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    gDvm.stepControl.active = false;
5782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
5792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
5802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
5812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
5822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
5852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Recover the "this" pointer from the current interpreted method.  "this"
5862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * is always in "in0" for non-static methods.
5872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
5882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The "ins" start at (#of registers - #of ins).  Note in0 != v0.
5892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
5902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This works because "dx" guarantees that it will work.  It's probably
5912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * fairly common to have a virtual method that doesn't use its "this"
5922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * pointer, in which case we're potentially wasting a register.  However,
5932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the debugger doesn't treat "this" as just another argument.  For
5942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * example, events (such as breakpoints) can be enabled for specific
5952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * values of "this".  There is also a separate StackFrame.ThisObject call
5962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * in JDWP that is expected to work for any non-native non-static method.
5972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
5982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Because we need it when setting up debugger event filters, we want to
5992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * be able to do this quickly.
6002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
6012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectObject* dvmGetThisPtr(const Method* method, const u4* fp)
6022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
6032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsStaticMethod(method))
6042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
6052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return (Object*)fp[method->registersSize - method->insSize];
6062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
6072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS)
6102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
6112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Verify that all internally-tracked references have been released.  If
6122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * they haven't, print them and abort the VM.
6132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
6142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "debugTrackedRefStart" indicates how many refs were on the list when
6152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we were first invoked.
6162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
6172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
6182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int debugTrackedRefStart)
6192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
6202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmReferenceTableEntries(&self->internalLocalRefTable)
6212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        != (size_t) debugTrackedRefStart)
6222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    {
6232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        char* desc;
6242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        Object** top;
6252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        int count;
6262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        count = dvmReferenceTableEntries(&self->internalLocalRefTable);
6282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
6302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            debugTrackedRefStart, count);
6312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        desc = dexProtoCopyMethodDescriptor(&method->prototype);
6322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("       current method is %s.%s %s\n", method->clazz->descriptor,
6332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            method->name, desc);
6342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        free(desc);
6352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        top = self->internalLocalRefTable.table + debugTrackedRefStart;
6362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        while (top < self->internalLocalRefTable.nextEntry) {
6372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGE("  %p (%s)\n",
6382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                 *top,
6392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
6402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            top++;
6412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
6422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmDumpThread(self, false);
6432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmAbort();
6452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
6462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    //LOGI("TRACK OK\n");
6472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
6482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
6492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef LOG_INSTR
6522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
6532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Dump the v-registers.  Sent to the ILOG log tag.
6542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
6552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
6562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
6572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i, localCount;
6582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    localCount = method->registersSize - method->insSize;
6602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
6622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = method->registersSize-1; i >= 0; i--) {
6632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (i >= localCount) {
6642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d in%-2d : 0x%08x\n",
6652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                i, i-localCount, framePtr[i]);
6662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        } else {
6672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            if (inOnly) {
6682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                LOG(LOG_VERBOSE, LOG_TAG"i", "  [...]\n");
6692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                break;
6702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            }
6712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const char* name = "";
6722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            int j;
6732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0   // "locals" structure has changed -- need to rewrite this
6742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            DexFile* pDexFile = method->clazz->pDexFile;
6752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const DexCode* pDexCode = dvmGetMethodCode(method);
6762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
6772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
6782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            for (j = 0; j < localsSize, j++) {
6792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                if (locals[j].registerNum == (u4) i) {
6802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                    name = dvmDexStringStr(locals[j].pName);
6812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                    break;
6822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                }
6832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            }
6842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
6852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d      : 0x%08x %s\n",
6862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                i, framePtr[i], name);
6872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
6882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
6892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
6902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
6912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
6942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
6952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *      Entry point and general support functions
6962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
6972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
6982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
69938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng/*
7002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Construct an s4 from two consecutive half-words of switch data.
7012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This needs to check endianness because the DEX optimizer only swaps
7022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * half-words in instruction stream.
7032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
7042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "switchData" must be 32-bit aligned.
7052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
7062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if __BYTE_ORDER == __LITTLE_ENDIAN
7072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectstatic inline s4 s4FromSwitchData(const void* switchData) {
7082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return *(s4*) switchData;
7092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
7102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
7112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectstatic inline s4 s4FromSwitchData(const void* switchData) {
7122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2* data = switchData;
7132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return data[0] | (((s4) data[1]) << 16);
714ffa5c29a95ee5cb32c5bb4c46eccb5a57f5f493bJay Freeman (saurik)}
7152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
7162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
7182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case.  Returns the offset to the handler instructions.
7192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
7202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the packed-switch
7212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction).
7222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
7232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
7242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
7252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const int kInstrLen = 3;
7262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 size;
7272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    s4 firstKey;
7282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* entries;
7292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
7312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Packed switch data format:
7322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0100   magic value
7332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort size             number of entries in the table
7342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int first_key           first (and lowest) switch case value
7352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int targets[size]       branch targets, relative to switch opcode
7362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
7372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is (4+size*2) 16-bit code units.
7382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
7392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (*switchData++ != kPackedSwitchSignature) {
7402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* should have been caught by verifier */
7412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/InternalError;",
7422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "bad packed switch magic");
7432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
7442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
7452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = *switchData++;
7472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(size > 0);
7482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    firstKey = *switchData++;
7502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    firstKey |= (*switchData++) << 16;
7512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (testVal < firstKey || testVal >= firstKey + size) {
7532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGVV("Value %d not found in switch (%d-%d)\n",
7542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            testVal, firstKey, firstKey+size-1);
7552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
7562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
7572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The entries are guaranteed to be aligned on a 32-bit boundary;
7592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
7602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
7612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    entries = (const s4*) switchData;
7622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)entries & 0x3) == 0);
7632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(testVal - firstKey >= 0 && testVal - firstKey < size);
7652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
7662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        testVal, testVal - firstKey,
7672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        s4FromSwitchData(&entries[testVal - firstKey]));
7682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return s4FromSwitchData(&entries[testVal - firstKey]);
7692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
7702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
7722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case.  Returns the offset to the handler instructions.
7732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
7742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the sparse-switch
7752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction).
7762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
7772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
7782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
7792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const int kInstrLen = 3;
7802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 ident, size;
7812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* keys;
7822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* entries;
7832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
7852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Sparse switch data format:
7862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0200   magic value
7872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort size             number of entries in the table; > 0
7882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
7892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int targets[size]       branch targets, relative to switch opcode
7902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
7912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is (2+size*4) 16-bit code units.
7922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
7932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (*switchData++ != kSparseSwitchSignature) {
7952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* should have been caught by verifier */
7962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/InternalError;",
7972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "bad sparse switch magic");
7982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
7992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
8002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
8012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = *switchData++;
8022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(size > 0);
80338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng
8042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The keys are guaranteed to be aligned on a 32-bit boundary;
8052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
8062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
8072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    keys = (const s4*) switchData;
8082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)keys & 0x3) == 0);
8092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
8102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The entries are guaranteed to be aligned on a 32-bit boundary;
8112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
8122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
8132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    entries = keys + size;
8142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)entries & 0x3) == 0);
8152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
8162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
81762f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden     * Binary-search through the array of keys, which are guaranteed to
8182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * be sorted low-to-high.
8192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
82062f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden    int lo = 0;
82162f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden    int hi = size - 1;
82262f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden    while (lo <= hi) {
82362f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        int mid = (lo + hi) >> 1;
82462f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden
82562f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        s4 foundVal = s4FromSwitchData(&keys[mid]);
82662f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        if (testVal < foundVal) {
82762f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden            hi = mid - 1;
82862f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        } else if (testVal > foundVal) {
82962f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden            lo = mid + 1;
83062f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden        } else {
8312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
83262f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden                testVal, mid, s4FromSwitchData(&entries[mid]));
83362f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden            return s4FromSwitchData(&entries[mid]);
8342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
8352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
8362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
8372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGVV("Value %d not found in switch\n", testVal);
8382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return kInstrLen;
8392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
8402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
8412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
8426f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * Copy data for a fill-array-data instruction.  On a little-endian machine
8436f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * we can just do a memcpy(), on a big-endian system we have work to do.
8446f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden *
8456f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * The trick here is that dexopt has byte-swapped each code unit, which is
8466f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * exactly what we want for short/char data.  For byte data we need to undo
8476f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * the swap, and for 4- or 8-byte values we need to swap pieces within
8486f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * each word.
8496f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden */
8506f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFaddenstatic void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
8516f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden{
8526f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#if __BYTE_ORDER == __LITTLE_ENDIAN
8536f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    memcpy(dest, src, size*width);
8546f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#else
8556f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    int i;
8566f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden
8576f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    switch (width) {
8586f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 1:
8596f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* un-swap pairs of bytes as we go */
8606f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        for (i = (size-1) & ~1; i >= 0; i -= 2) {
8616f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u1*)dest)[i] = ((u1*)src)[i+1];
8626f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u1*)dest)[i+1] = ((u1*)src)[i];
8636f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
8646f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /*
8656f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden         * "src" is padded to end on a two-byte boundary, but we don't want to
8666f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden         * assume "dest" is, so we handle odd length specially.
8676f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden         */
8686f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        if ((size & 1) != 0) {
8696f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u1*)dest)[size-1] = ((u1*)src)[size];
8706f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
8716f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
8726f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 2:
8736f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* already swapped correctly */
8746f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        memcpy(dest, src, size*width);
8756f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
8766f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 4:
8776f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* swap word halves */
8786f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        for (i = 0; i < (int) size; i++) {
8796f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
8806f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
8816f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
8826f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    case 8:
8836f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        /* swap word halves and words */
8846f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        for (i = 0; i < (int) (size << 1); i += 2) {
8856f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
8866f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden            ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
8876f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        }
8886f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
8896f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    default:
8906f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        LOGE("Unexpected width %d in copySwappedArrayData\n", width);
8916f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        dvmAbort();
8926f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden        break;
8936f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    }
8946f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#endif
8956f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden}
8966f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden
8976f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden/*
8982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Fill the array with predefined constant values.
8992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
9002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns true if job is completed, otherwise false to indicate that
9012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * an exception has been thrown.
9022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
90389c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Projectbool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
9042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
9052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 width;
9062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u4 size;
9072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
90889c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project    if (arrayObj == NULL) {
90989c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
9102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
9112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9127dc966014df20fea6a4643ce2736922d0a7ee2c8Barry Hayes    assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
9137dc966014df20fea6a4643ce2736922d0a7ee2c8Barry Hayes                               CLASS_ISOBJECTARRAY));
91489c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project
9152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
9162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Array data table format:
9172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0300   magic value
9182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort width            width of each element in the table
9192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  uint   size             number of elements in the table
9202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ubyte  data[size*width] table of data values (may contain a single-byte
9212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *                          padding at the end)
9222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
9232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is 4+(width * size + 1)/2 16-bit code units.
9242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
9252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (arrayData[0] != kArrayDataSignature) {
9262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/InternalError;", "bad array data magic");
9272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
9282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    width = arrayData[1];
9312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = arrayData[2] | (((u4)arrayData[3]) << 16);
9322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (size > arrayObj->length) {
9342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL);
9352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
9362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9376f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden    copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
9382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return true;
9392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
9402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
9422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the concrete method that corresponds to "methodIdx".  The code in
9432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "method" is executing invoke-method with "thisClass" as its first argument.
9442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
9452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns NULL with an exception raised on failure.
9462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
9472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectMethod* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
9482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const Method* method, DvmDex* methodClassDex)
9492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
9502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Method* absMethod;
9512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Method* methodToCall;
9522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i, vtableIndex;
9532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
9552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Resolve the method.  This gives us the abstract method from the
9562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * interface class declaration.
9572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
9582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
9592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (absMethod == NULL) {
9602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
9612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (absMethod == NULL) {
9622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGV("+ unknown method\n");
9632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            return NULL;
9642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
9652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* make sure absMethod->methodIndex means what we think it means */
9682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(dvmIsAbstractMethod(absMethod));
9692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
9712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Run through the "this" object's iftable.  Find the entry for
9722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * absMethod's class, then use absMethod->methodIndex to find
9732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * the method's entry.  The value there is the offset into our
9742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * vtable of the actual method to execute.
9752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
9762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * The verifier does not guarantee that objects stored into
9772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * interface references actually implement the interface, so this
9782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * check cannot be eliminated.
9792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
9802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = 0; i < thisClass->iftableCount; i++) {
9812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (thisClass->iftable[i].clazz == absMethod->clazz)
9822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
9832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (i == thisClass->iftableCount) {
9852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* impossible in verified DEX, need to check for it in unverified */
9862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
9872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "interface not implemented");
9882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
9892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
9902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(absMethod->methodIndex <
9922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        thisClass->iftable[i].clazz->virtualMethodCount);
9932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    vtableIndex =
9952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
9962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
9972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    methodToCall = thisClass->vtable[vtableIndex];
9982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
9992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0
10002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* this can happen when there's a stale class file */
10012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsAbstractMethod(methodToCall)) {
10022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/AbstractMethodError;",
10032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "interface method not implemented");
10042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
10052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
10062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
10072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(!dvmIsAbstractMethod(methodToCall) ||
10082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        methodToCall->nativeFunc != NULL);
10092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
10102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
10122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        absMethod->clazz->descriptor, absMethod->name,
10132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        methodToCall->clazz->descriptor, methodToCall->name);
10142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(methodToCall != NULL);
10152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return methodToCall;
10172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
10182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
10192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1020b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1021b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/*
1022b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Helpers for dvmThrowVerificationError().
1023b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
1024b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Each returns a newly-allocated string.
1025b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */
1026b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden#define kThrowShow_accessFromClass     1
1027af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFaddenstatic char* classNameFromIndex(const Method* method, int ref,
1028af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType, int flags)
1029b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
1030b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    static const int kBufLen = 256;
1031b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const DvmDex* pDvmDex = method->clazz->pDvmDex;
1032af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1033af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    if (refType == VERIFY_ERROR_REF_FIELD) {
1034af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        /* get class ID from field ID */
1035af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1036af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        ref = pFieldId->classIdx;
1037af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    } else if (refType == VERIFY_ERROR_REF_METHOD) {
1038af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        /* get class ID from method ID */
1039af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1040af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        ref = pMethodId->classIdx;
1041af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    }
1042af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1043b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
1044b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* dotClassName = dvmDescriptorToDot(className);
1045b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if (flags == 0)
1046b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        return dotClassName;
1047b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1048b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* result = (char*) malloc(kBufLen);
1049b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1050b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if ((flags & kThrowShow_accessFromClass) != 0) {
1051b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
1052b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        snprintf(result, kBufLen, "tried to access class %s from class %s",
1053b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden            dotClassName, dotFromName);
1054b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        free(dotFromName);
1055b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    } else {
1056b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        assert(false);      // should've been caught above
1057b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        result[0] = '\0';
1058b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1059b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1060b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    free(dotClassName);
1061b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    return result;
1062b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
1063af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFaddenstatic char* fieldNameFromIndex(const Method* method, int ref,
1064af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType, int flags)
1065b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
1066b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    static const int kBufLen = 256;
1067b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const DvmDex* pDvmDex = method->clazz->pDvmDex;
1068b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const DexFieldId* pFieldId;
1069b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* className;
1070b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* fieldName;
1071b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1072af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    if (refType != VERIFY_ERROR_REF_FIELD) {
1073af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1074af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        return NULL;    /* no message */
1075af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    }
1076af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1077b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1078b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1079b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1080b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1081b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* dotName = dvmDescriptorToDot(className);
1082b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* result = (char*) malloc(kBufLen);
1083b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1084b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if ((flags & kThrowShow_accessFromClass) != 0) {
1085b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
1086b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1087b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden            dotName, fieldName, dotFromName);
1088b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        free(dotFromName);
1089b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    } else {
1090b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1091b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1092b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1093b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    free(dotName);
1094b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    return result;
1095b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
1096af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFaddenstatic char* methodNameFromIndex(const Method* method, int ref,
1097af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType, int flags)
1098b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
1099b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    static const int kBufLen = 384;
1100b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const DvmDex* pDvmDex = method->clazz->pDvmDex;
1101b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const DexMethodId* pMethodId;
1102b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* className;
1103b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* methodName;
1104b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1105af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    if (refType != VERIFY_ERROR_REF_METHOD) {
1106af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1107af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        return NULL;    /* no message */
1108af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    }
1109af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden
1110b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1111b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1112b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1113b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1114b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* dotName = dvmDescriptorToDot(className);
1115b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* result = (char*) malloc(kBufLen);
1116b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1117b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if ((flags & kThrowShow_accessFromClass) != 0) {
1118b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
1119b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1120b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        snprintf(result, kBufLen,
1121b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden            "tried to access method %s.%s:%s from class %s",
1122b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden            dotName, methodName, desc, dotFromName);
1123b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        free(dotFromName);
1124b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        free(desc);
1125b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    } else {
1126b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1127b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1128b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1129b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    free(dotName);
1130b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    return result;
1131b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
1132b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
11332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
11343a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * Throw an exception for a problem identified by the verifier.
11353a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden *
11363a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * This is used by the invoke-verification-error instruction.  It always
11373a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * throws an exception.
11383a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden *
1139af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden * "kind" indicates the kind of failure encountered by the verifier.  It
1140af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden * has two parts, an error code and an indication of the reference type.
11413a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden */
1142b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmThrowVerificationError(const Method* method, int kind, int ref)
11433a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden{
1144af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1145af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyError errorKind = kind & ~typeMask;
1146af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
1147b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    const char* exceptionName = "Ljava/lang/VerifyError;";
1148b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    char* msg = NULL;
1149b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1150af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden    switch ((VerifyError) errorKind) {
1151b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NO_CLASS:
1152b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/NoClassDefFoundError;";
1153af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType, 0);
1154b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1155b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NO_FIELD:
1156b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/NoSuchFieldError;";
1157af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = fieldNameFromIndex(method, ref, refType, 0);
1158b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1159b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NO_METHOD:
1160b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/NoSuchMethodError;";
1161af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = methodNameFromIndex(method, ref, refType, 0);
1162b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1163b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_ACCESS_CLASS:
1164b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/IllegalAccessError;";
1165af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType,
1166af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden            kThrowShow_accessFromClass);
1167b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1168b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_ACCESS_FIELD:
1169b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/IllegalAccessError;";
1170af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = fieldNameFromIndex(method, ref, refType,
1171af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden            kThrowShow_accessFromClass);
1172b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1173b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_ACCESS_METHOD:
1174b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/IllegalAccessError;";
1175af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = methodNameFromIndex(method, ref, refType,
1176af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden            kThrowShow_accessFromClass);
1177b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1178b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_CLASS_CHANGE:
1179b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
1180af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType, 0);
1181b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1182b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_INSTANTIATION:
1183b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        exceptionName = "Ljava/lang/InstantiationError;";
1184af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden        msg = classNameFromIndex(method, ref, refType, 0);
1185b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1186b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1187b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_GENERIC:
1188b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        /* generic VerifyError; use default exception, no message */
1189b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1190b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    case VERIFY_ERROR_NONE:
1191b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        /* should never happen; use default exception */
1192b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        assert(false);
1193b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        msg = strdup("weird - no error specified");
1194b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        break;
1195b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1196b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    /* no default clause -- want warning if enum updated */
1197b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
1198b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
1199b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    dvmThrowException(exceptionName, msg);
1200b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    free(msg);
12013a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden}
12023a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden
12033a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden/*
12042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Main interpreter loop entry point.  Select "standard" or "debug"
12052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * interpreter and switch between them as required.
12062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
12072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This begins executing code at the start of "method".  On exit, "pResult"
12082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * holds the return value of the method (or, if "method" returns NULL, it
12092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * holds an undefined value).
12102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
12112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The interpreted stack frame, which holds the method arguments, has
12122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * already been set up.
12132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
12142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInterpret(Thread* self, const Method* method, JValue* pResult)
12152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
12162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    InterpState interpState;
12172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    bool change;
1218ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
1219342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee    /* Target-specific save/restore */
1220342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee    extern void dvmJitCalleeSave(double *saveArea);
1221342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee    extern void dvmJitCalleeRestore(double *saveArea);
1222ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Interpreter entry points from compiled code */
1223ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    extern void dvmJitToInterpNormal();
1224ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    extern void dvmJitToInterpNoChain();
1225ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    extern void dvmJitToInterpPunt();
1226ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    extern void dvmJitToInterpSingleStep();
122740094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng    extern void dvmJitToInterpTraceSelectNoChain();
122840094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng    extern void dvmJitToInterpTraceSelect();
122938329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    extern void dvmJitToPatchPredictedChain();
123097319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#if defined(WITH_SELF_VERIFICATION)
123140094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng    extern void dvmJitToInterpBackwardBranch();
123297319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#endif
1233ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
123438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng    /*
1235ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Reserve a static entity here to quickly setup runtime contents as
1236ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * gcc will issue block copy instructions.
1237ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
1238ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    static struct JitToInterpEntries jitToInterpEntries = {
1239ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpNormal,
1240ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpNoChain,
1241ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpPunt,
1242ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmJitToInterpSingleStep,
124340094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng        dvmJitToInterpTraceSelectNoChain,
124440094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng        dvmJitToInterpTraceSelect,
124538329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng        dvmJitToPatchPredictedChain,
124697319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#if defined(WITH_SELF_VERIFICATION)
124740094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng        dvmJitToInterpBackwardBranch,
124897319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#endif
1249ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    };
12507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
12517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    assert(self->inJitCodeCache == NULL);
1252ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
1253ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
12542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS)
12562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.debugTrackedRefStart =
12572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmReferenceTableEntries(&self->internalLocalRefTable);
12582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
12592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
12602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.debugIsMethodEntry = true;
12612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
1262ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
1263342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee    dvmJitCalleeSave(interpState.calleeSave);
1264a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /* Initialize the state to kJitNot */
1265a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    interpState.jitState = kJitNot;
1266ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1267ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Setup the Jit-to-interpreter entry points */
1268ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    interpState.jitToInterpEntries = jitToInterpEntries;
126948f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee
127048f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee    /*
127148f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee     * Initialize the threshold filter [don't bother to zero out the
127248f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee     * actual table.  We're looking for matches, and an occasional
127348f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee     * false positive is acceptible.
127448f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee     */
127548f1824fd36241067e7bed2302cc00b2d880be7fBill Buzbee    interpState.lastThreshFilter = 0;
1276ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
12772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
12792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Initialize working state.
12802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
12812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * No need to initialize "retval".
12822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
12832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.method = method;
12842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.fp = (u4*) self->curFrame;
12852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.pc = method->insns;
12862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.entryPoint = kInterpEntryInstr;
12872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmDebuggerOrProfilerActive())
12892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        interpState.nextMode = INTERP_DBG;
12902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    else
12912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        interpState.nextMode = INTERP_STD;
12922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(!dvmIsNativeMethod(method));
12942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
12952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
12962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Make sure the class is ready to go.  Shouldn't be possible to get
12972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * here otherwise.
12982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
12992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (method->clazz->status < CLASS_INITIALIZING ||
13002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        method->clazz->status == CLASS_ERROR)
13012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    {
13022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
13032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            method->clazz->descriptor, method->clazz->status);
13042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmDumpThread(self, false);
13052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmAbort();
13062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
13072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
13082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    typedef bool (*Interpreter)(Thread*, InterpState*);
13092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Interpreter stdInterp;
13102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (gDvm.executionMode == kExecutionModeInterpFast)
13112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        stdInterp = dvmMterpStd;
1312ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
1313ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    else if (gDvm.executionMode == kExecutionModeJit)
1314ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* If profiling overhead can be kept low enough, we can use a profiling
1315ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * mterp fast for both Jit and "fast" modes.  If overhead is too high,
1316ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * create a specialized profiling interpreter.
1317ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
1318ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        stdInterp = dvmMterpStd;
1319ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
13202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    else
13212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        stdInterp = dvmInterpretStd;
13222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
13232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    change = true;
13242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    while (change) {
13252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        switch (interpState.nextMode) {
13262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        case INTERP_STD:
13272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGVV("threadid=%d: interp STD\n", self->threadId);
13282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            change = (*stdInterp)(self, &interpState);
13292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
1330ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) || defined(WITH_JIT)
13312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        case INTERP_DBG:
13322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGVV("threadid=%d: interp DBG\n", self->threadId);
13332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            change = dvmInterpretDbg(self, &interpState);
13342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
13352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
13362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        default:
13372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            dvmAbort();
13382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
13392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
13402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
13412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    *pResult = interpState.retval;
1342342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee#if defined(WITH_JIT)
1343342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee    dvmJitCalleeRestore(interpState.calleeSave);
1344342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee#endif
13452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
1346