Interp.c revision 89c1feb0a69a7707b271086e749975b3f7acacf7
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
382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Initialize the breakpoint address lookup table when the debugger attaches.
402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This shouldn't be necessary -- the global area is initially zeroed out,
422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * and the events should be cleaning up after themselves.
432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInitBreakpoints(void)
452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    memset(gDvm.debugBreakAddr, 0, sizeof(gDvm.debugBreakAddr));
482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add an address to the list, putting it in the first non-empty slot.
552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Sometimes the debugger likes to add two entries for one breakpoint.
572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We add two entries here, so that we get the right behavior when it's
582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * removed twice.
592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This will only be run from the JDWP thread, and it will happen while
612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we are updating the event list, which is synchronized.  We're guaranteed
622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * to be the only one adding entries, and the lock ensures that nobody
632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * will be trying to remove them while we're in here.
642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "addr" is the absolute address of the breakpoint bytecode.
662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmAddBreakAddr(Method* method, int instrOffset)
682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const u2* addr = method->insns + instrOffset;
712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const u2** ptr = gDvm.debugBreakAddr;
722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i;
732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGV("BKP: add %p %s.%s (%s:%d)\n",
752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        addr, method->clazz->descriptor, method->name,
762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmGetMethodSourceFile(method), dvmLineNumFromPC(method, instrOffset));
772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    method->debugBreakpointCount++;
792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = 0; i < MAX_BREAKPOINTS; i++, ptr++) {
802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (*ptr == NULL) {
812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            *ptr = addr;
822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (i == MAX_BREAKPOINTS) {
862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* no room; size is too small or we're not cleaning up properly */
872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("ERROR: max breakpoints exceeded\n");
882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(false);
892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Remove an address from the list by setting the entry to NULL.
972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This can be called from the JDWP thread (because the debugger has
992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * cancelled the breakpoint) or from an event thread (because it's a
1002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * single-shot breakpoint, e.g. "run to line").  We only get here as
1012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the result of removing an entry from the event list, which is
1022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * synchronized, so it should not be possible for two threads to be
1032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * updating breakpoints at the same time.
1042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
1052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmClearBreakAddr(Method* method, int instrOffset)
1062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
1072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
1082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const u2* addr = method->insns + instrOffset;
1092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const u2** ptr = gDvm.debugBreakAddr;
1102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i;
1112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGV("BKP: clear %p %s.%s (%s:%d)\n",
1132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        addr, method->clazz->descriptor, method->name,
1142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmGetMethodSourceFile(method), dvmLineNumFromPC(method, instrOffset));
1152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    method->debugBreakpointCount--;
1172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(method->debugBreakpointCount >= 0);
1182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = 0; i < MAX_BREAKPOINTS; i++, ptr++) {
1192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (*ptr == addr) {
1202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            *ptr = NULL;
1212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
1222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
1232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
1242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (i == MAX_BREAKPOINTS) {
1252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* didn't find it */
1262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("ERROR: breakpoint on %p not found\n", addr);
1272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(false);
1282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
1292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
1302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
1312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
1322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
1332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
1352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add a single step event.  Currently this is a global item.
1362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
1372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We set up some initial values based on the thread's current state.  This
1382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * won't work well if the thread is running, so it's up to the caller to
1392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * verify that it's suspended.
1402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
1412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This is only called from the JDWP thread.
1422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
1432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectbool dvmAddSingleStep(Thread* thread, int size, int depth)
1442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
1452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
1462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    StepControl* pCtrl = &gDvm.stepControl;
1472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (pCtrl->active && thread != pCtrl->thread) {
1492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGW("WARNING: single-step active for %p; adding %p\n",
1502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            pCtrl->thread, thread);
1512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /*
1532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * Keep going, overwriting previous.  This can happen if you
1542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * suspend a thread in Object.wait, hit the single-step key, then
1552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * switch to another thread and do the same thing again.
1562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * The first thread's step is still pending.
1572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         *
1582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * TODO: consider making single-step per-thread.  Adds to the
1592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * overhead, but could be useful in rare situations.
1602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         */
1612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
1622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->size = size;
1642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->depth = depth;
1652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->thread = thread;
1662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
1682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * We may be stepping into or over method calls, or running until we
1692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * return from the current method.  To make this work we need to track
1702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * the current line, current method, and current stack depth.  We need
1712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * to be checking these after most instructions, notably those that
1722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * call methods, return from methods, or are on a different line from the
1732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * previous instruction.
1742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
1752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * We have to start with a snapshot of the current state.  If we're in
1762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * an interpreted method, everything we need is in the current frame.  If
1772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we're in a native method, possibly with some extra JNI frames pushed
1782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * on by PushLocalFrame, we want to use the topmost native method.
1792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
1802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const StackSaveArea* saveArea;
1812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    void* fp;
1822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    void* prevFp = NULL;
1832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
1852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        const Method* method;
1862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
1882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        method = saveArea->method;
1892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
1902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (!dvmIsBreakFrame(fp) && !dvmIsNativeMethod(method))
1912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
1922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        prevFp = fp;
1932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
1942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (fp == NULL) {
1952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGW("Unexpected: step req in native-only threadid=%d\n",
1962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            thread->threadId);
1972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
1982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
1992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (prevFp != NULL) {
2002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /*
2012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * First interpreted frame wasn't the one at the bottom.  Break
2022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * frames are only inserted when calling from native->interp, so we
2032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         * don't need to worry about one being here.
2042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project         */
2052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGV("##### init step while in native method\n");
2062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        fp = prevFp;
2072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(!dvmIsBreakFrame(fp));
2082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
2092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
2102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
2112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
2132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Pull the goodies out.  "xtra.currentPc" should be accurate since
2142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we update it on every instruction while the debugger is connected.
2152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
2162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->method = saveArea->method;
2172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    // Clear out any old address set
2182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (pCtrl->pAddressSet != NULL) {
2192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        // (discard const)
2202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        free((void *)pCtrl->pAddressSet);
2212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->pAddressSet = NULL;
2222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
2232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsNativeMethod(pCtrl->method)) {
2242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line = -1;
2252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    } else {
2262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line = dvmLineNumFromPC(saveArea->method,
2272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                        saveArea->xtra.currentPc - saveArea->method->insns);
2282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->pAddressSet
2292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                = dvmAddressSetForLine(saveArea->method, pCtrl->line);
2302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
2312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
2322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    pCtrl->active = true;
2332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
2352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->thread, pCtrl->method, pCtrl->method->name,
2362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        pCtrl->line, pCtrl->frameDepth,
2372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmJdwpStepDepthStr(pCtrl->depth),
2382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmJdwpStepSizeStr(pCtrl->size));
2392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return true;
2412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
2422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
2432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return false;
2442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
2452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
2462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
2482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Disable a single step event.
2492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
2502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmClearSingleStep(Thread* thread)
2512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
2522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef WITH_DEBUGGER
2532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    UNUSED_PARAMETER(thread);
2542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    gDvm.stepControl.active = false;
2562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
2572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(false);
2582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
2592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
2602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
2632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Recover the "this" pointer from the current interpreted method.  "this"
2642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * is always in "in0" for non-static methods.
2652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
2662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The "ins" start at (#of registers - #of ins).  Note in0 != v0.
2672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
2682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This works because "dx" guarantees that it will work.  It's probably
2692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * fairly common to have a virtual method that doesn't use its "this"
2702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * pointer, in which case we're potentially wasting a register.  However,
2712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the debugger doesn't treat "this" as just another argument.  For
2722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * example, events (such as breakpoints) can be enabled for specific
2732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * values of "this".  There is also a separate StackFrame.ThisObject call
2742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * in JDWP that is expected to work for any non-native non-static method.
2752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
2762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Because we need it when setting up debugger event filters, we want to
2772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * be able to do this quickly.
2782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
2792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectObject* dvmGetThisPtr(const Method* method, const u4* fp)
2802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
2812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsStaticMethod(method))
2822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
2832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return (Object*)fp[method->registersSize - method->insSize];
2842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
2852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
2872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS)
2882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
2892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Verify that all internally-tracked references have been released.  If
2902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * they haven't, print them and abort the VM.
2912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
2922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "debugTrackedRefStart" indicates how many refs were on the list when
2932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we were first invoked.
2942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
2952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
2962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int debugTrackedRefStart)
2972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
2982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmReferenceTableEntries(&self->internalLocalRefTable)
2992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        != (size_t) debugTrackedRefStart)
3002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    {
3012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        char* desc;
3022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        Object** top;
3032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        int count;
3042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        count = dvmReferenceTableEntries(&self->internalLocalRefTable);
3062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
3082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            debugTrackedRefStart, count);
3092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        desc = dexProtoCopyMethodDescriptor(&method->prototype);
3102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("       current method is %s.%s %s\n", method->clazz->descriptor,
3112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            method->name, desc);
3122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        free(desc);
3132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        top = self->internalLocalRefTable.table + debugTrackedRefStart;
3142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        while (top < self->internalLocalRefTable.nextEntry) {
3152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGE("  %p (%s)\n",
3162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                 *top,
3172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
3182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            top++;
3192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
3202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmDumpThread(self, false);
3212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmAbort();
3232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
3242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    //LOGI("TRACK OK\n");
3252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
3262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
3272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef LOG_INSTR
3302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
3312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Dump the v-registers.  Sent to the ILOG log tag.
3322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
3332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
3342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
3352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i, localCount;
3362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    localCount = method->registersSize - method->insSize;
3382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
3402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = method->registersSize-1; i >= 0; i--) {
3412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (i >= localCount) {
3422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d in%-2d : 0x%08x\n",
3432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                i, i-localCount, framePtr[i]);
3442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        } else {
3452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            if (inOnly) {
3462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                LOG(LOG_VERBOSE, LOG_TAG"i", "  [...]\n");
3472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                break;
3482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            }
3492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const char* name = "";
3502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            int j;
3512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0   // "locals" structure has changed -- need to rewrite this
3522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            DexFile* pDexFile = method->clazz->pDexFile;
3532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const DexCode* pDexCode = dvmGetMethodCode(method);
3542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
3552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
3562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            for (j = 0; j < localsSize, j++) {
3572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                if (locals[j].registerNum == (u4) i) {
3582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                    name = dvmDexStringStr(locals[j].pName);
3592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                    break;
3602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                }
3612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            }
3622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
3632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d      : 0x%08x %s\n",
3642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                i, framePtr[i], name);
3652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
3662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
3672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
3682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
3692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
3722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
3732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *      Entry point and general support functions
3742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ===========================================================================
3752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
3762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
3782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Construct an s4 from two consecutive half-words of switch data.
3792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This needs to check endianness because the DEX optimizer only swaps
3802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * half-words in instruction stream.
3812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
3822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "switchData" must be 32-bit aligned.
3832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
3842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if __BYTE_ORDER == __LITTLE_ENDIAN
3852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectstatic inline s4 s4FromSwitchData(const void* switchData) {
3862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return *(s4*) switchData;
3872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
3882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
3892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectstatic inline s4 s4FromSwitchData(const void* switchData) {
3902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2* data = switchData;
3912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return data[0] | (((s4) data[1]) << 16);
3922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
3932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
3942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
3952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case.  Returns the offset to the handler instructions.
3962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
3972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the packed-switch
3982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction).
3992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
4002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
4012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
4022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const int kInstrLen = 3;
4032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 size;
4042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    s4 firstKey;
4052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* entries;
4062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
4082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Packed switch data format:
4092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0100   magic value
4102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort size             number of entries in the table
4112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int first_key           first (and lowest) switch case value
4122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int targets[size]       branch targets, relative to switch opcode
4132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
4142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is (4+size*2) 16-bit code units.
4152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
4162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (*switchData++ != kPackedSwitchSignature) {
4172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* should have been caught by verifier */
4182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/InternalError;",
4192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "bad packed switch magic");
4202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
4212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
4222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = *switchData++;
4242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(size > 0);
4252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    firstKey = *switchData++;
4272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    firstKey |= (*switchData++) << 16;
4282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (testVal < firstKey || testVal >= firstKey + size) {
4302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGVV("Value %d not found in switch (%d-%d)\n",
4312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            testVal, firstKey, firstKey+size-1);
4322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
4332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
4342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The entries are guaranteed to be aligned on a 32-bit boundary;
4362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
4372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
4382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    entries = (const s4*) switchData;
4392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)entries & 0x3) == 0);
4402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(testVal - firstKey >= 0 && testVal - firstKey < size);
4422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
4432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        testVal, testVal - firstKey,
4442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        s4FromSwitchData(&entries[testVal - firstKey]));
4452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return s4FromSwitchData(&entries[testVal - firstKey]);
4462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
4472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
4492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case.  Returns the offset to the handler instructions.
4502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
4512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the sparse-switch
4522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction).
4532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
4542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
4552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
4562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const int kInstrLen = 3;
4572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 ident, size;
4582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* keys;
4592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const s4* entries;
4602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i;
4612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
4632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Sparse switch data format:
4642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0200   magic value
4652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort size             number of entries in the table; > 0
4662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
4672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  int targets[size]       branch targets, relative to switch opcode
4682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
4692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is (2+size*4) 16-bit code units.
4702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
4712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (*switchData++ != kSparseSwitchSignature) {
4732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* should have been caught by verifier */
4742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/InternalError;",
4752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "bad sparse switch magic");
4762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return kInstrLen;
4772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
4782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = *switchData++;
4802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(size > 0);
4812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The keys are guaranteed to be aligned on a 32-bit boundary;
4832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
4842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
4852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    keys = (const s4*) switchData;
4862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)keys & 0x3) == 0);
4872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* The entries are guaranteed to be aligned on a 32-bit boundary;
4892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * we can treat them as a native int array.
4902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
4912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    entries = keys + size;
4922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(((u4)entries & 0x3) == 0);
4932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
4942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
4952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Run through the list of keys, which are guaranteed to
4962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * be sorted low-to-high.
4972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
4982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Most tables have 3-4 entries.  Few have more than 10.  A binary
4992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * search here is probably not useful.
5002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = 0; i < size; i++) {
5022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        s4 k = s4FromSwitchData(&keys[i]);
5032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (k == testVal) {
5042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
5052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project                testVal, i, s4FromSwitchData(&entries[i]));
5062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            return s4FromSwitchData(&entries[i]);
5072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        } else if (k > testVal) {
5082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
5092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
5102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGVV("Value %d not found in switch\n", testVal);
5132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return kInstrLen;
5142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
5152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
5172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Fill the array with predefined constant values.
5182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
5192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns true if job is completed, otherwise false to indicate that
5202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * an exception has been thrown.
5212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
52289c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Projectbool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
5232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
5242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u2 width;
5252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    u4 size;
5262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
52789c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project    if (arrayObj == NULL) {
52889c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
5292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
5302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
53189c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project
5322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
5332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Array data table format:
5342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort ident = 0x0300   magic value
5352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ushort width            width of each element in the table
5362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  uint   size             number of elements in the table
5372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *  ubyte  data[size*width] table of data values (may contain a single-byte
5382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *                          padding at the end)
5392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
5402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Total size is 4+(width * size + 1)/2 16-bit code units.
5412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (arrayData[0] != kArrayDataSignature) {
5432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/InternalError;", "bad array data magic");
5442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
5452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    width = arrayData[1];
5482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    size = arrayData[2] | (((u4)arrayData[3]) << 16);
5492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (size != arrayObj->length) {
5512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL);
5522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return false;
5532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    memcpy(arrayObj->contents, &arrayData[4], size*width);
5552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return true;
5562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
5572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
5592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the concrete method that corresponds to "methodIdx".  The code in
5602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "method" is executing invoke-method with "thisClass" as its first argument.
5612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
5622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns NULL with an exception raised on failure.
5632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
5642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectMethod* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
5652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    const Method* method, DvmDex* methodClassDex)
5662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
5672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Method* absMethod;
5682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Method* methodToCall;
5692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    int i, vtableIndex;
5702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
5722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Resolve the method.  This gives us the abstract method from the
5732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * interface class declaration.
5742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
5762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (absMethod == NULL) {
5772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
5782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (absMethod == NULL) {
5792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGV("+ unknown method\n");
5802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            return NULL;
5812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
5822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
5832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* make sure absMethod->methodIndex means what we think it means */
5852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(dvmIsAbstractMethod(absMethod));
5862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
5872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
5882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Run through the "this" object's iftable.  Find the entry for
5892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * absMethod's class, then use absMethod->methodIndex to find
5902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * the method's entry.  The value there is the offset into our
5912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * vtable of the actual method to execute.
5922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
5932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * The verifier does not guarantee that objects stored into
5942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * interface references actually implement the interface, so this
5952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * check cannot be eliminated.
5962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
5972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    for (i = 0; i < thisClass->iftableCount; i++) {
5982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        if (thisClass->iftable[i].clazz == absMethod->clazz)
5992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
6002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
6012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (i == thisClass->iftableCount) {
6022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        /* impossible in verified DEX, need to check for it in unverified */
6032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
6042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "interface not implemented");
6052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
6062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
6072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(absMethod->methodIndex <
6092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        thisClass->iftable[i].clazz->virtualMethodCount);
6102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    vtableIndex =
6122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
6132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
6142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    methodToCall = thisClass->vtable[vtableIndex];
6152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0
6172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /* this can happen when there's a stale class file */
6182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmIsAbstractMethod(methodToCall)) {
6192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmThrowException("Ljava/lang/AbstractMethodError;",
6202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            "interface method not implemented");
6212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        return NULL;
6222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
6232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else
6242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(!dvmIsAbstractMethod(methodToCall) ||
6252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        methodToCall->nativeFunc != NULL);
6262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
6272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
6292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        absMethod->clazz->descriptor, absMethod->name,
6302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        methodToCall->clazz->descriptor, methodToCall->name);
6312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(methodToCall != NULL);
6322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    return methodToCall;
6342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
6352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/*
6382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Main interpreter loop entry point.  Select "standard" or "debug"
6392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * interpreter and switch between them as required.
6402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
6412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This begins executing code at the start of "method".  On exit, "pResult"
6422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * holds the return value of the method (or, if "method" returns NULL, it
6432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * holds an undefined value).
6442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *
6452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The interpreted stack frame, which holds the method arguments, has
6462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * already been set up.
6472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */
6482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInterpret(Thread* self, const Method* method, JValue* pResult)
6492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{
6502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    InterpState interpState;
6512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    bool change;
6522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS)
6542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.debugTrackedRefStart =
6552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmReferenceTableEntries(&self->internalLocalRefTable);
6562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
6572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
6582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.debugIsMethodEntry = true;
6592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
6602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
6622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Initialize working state.
6632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     *
6642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * No need to initialize "retval".
6652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
6662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.method = method;
6672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.fp = (u4*) self->curFrame;
6682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.pc = method->insns;
6692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    interpState.entryPoint = kInterpEntryInstr;
6702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (dvmDebuggerOrProfilerActive())
6722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        interpState.nextMode = INTERP_DBG;
6732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    else
6742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        interpState.nextMode = INTERP_STD;
6752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    assert(!dvmIsNativeMethod(method));
6772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    /*
6792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * Make sure the class is ready to go.  Shouldn't be possible to get
6802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     * here otherwise.
6812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project     */
6822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (method->clazz->status < CLASS_INITIALIZING ||
6832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        method->clazz->status == CLASS_ERROR)
6842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    {
6852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
6862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            method->clazz->descriptor, method->clazz->status);
6872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmDumpThread(self, false);
6882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        dvmAbort();
6892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
6902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    typedef bool (*Interpreter)(Thread*, InterpState*);
6922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    Interpreter stdInterp;
6932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    if (gDvm.executionMode == kExecutionModeInterpFast)
6942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        stdInterp = dvmMterpStd;
6952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    else
6962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        stdInterp = dvmInterpretStd;
6972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
6982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    change = true;
6992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    while (change) {
7002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        switch (interpState.nextMode) {
7012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        case INTERP_STD:
7022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGVV("threadid=%d: interp STD\n", self->threadId);
7032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            change = (*stdInterp)(self, &interpState);
7042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
7052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
7062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        case INTERP_DBG:
7072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            LOGVV("threadid=%d: interp DBG\n", self->threadId);
7082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            change = dvmInterpretDbg(self, &interpState);
7092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            break;
7102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif
7112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        default:
7122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project            dvmAbort();
7132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project        }
7142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    }
7152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project
7162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project    *pResult = interpState.retval;
7172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project}
71889c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project
719