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