1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Main interpreter entry point and support functions. 19 * 20 * The entry point selects the "standard" or "debug" interpreter and 21 * facilitates switching between them. The standard interpreter may 22 * use the "fast" or "portable" implementation. 23 * 24 * Some debugger support functions are included here. 25 */ 26 #include "Dalvik.h" 27 #include "interp/InterpDefs.h" 28 #if defined(WITH_JIT) 29 #include "interp/Jit.h" 30 #endif 31 32 33 /* 34 * =========================================================================== 35 * Debugger support 36 * =========================================================================== 37 */ 38 39 // fwd 40 static BreakpointSet* dvmBreakpointSetAlloc(); 41 static void dvmBreakpointSetFree(BreakpointSet* pSet); 42 43 #if defined(WITH_JIT) 44 /* Target-specific save/restore */ 45 extern "C" void dvmJitCalleeSave(double *saveArea); 46 extern "C" void dvmJitCalleeRestore(double *saveArea); 47 /* Interpreter entry points from compiled code */ 48 extern "C" void dvmJitToInterpNormal(); 49 extern "C" void dvmJitToInterpNoChain(); 50 extern "C" void dvmJitToInterpPunt(); 51 extern "C" void dvmJitToInterpSingleStep(); 52 extern "C" void dvmJitToInterpTraceSelect(); 53 #if defined(WITH_SELF_VERIFICATION) 54 extern "C" void dvmJitToInterpBackwardBranch(); 55 #endif 56 #endif 57 58 /* 59 * Initialize global breakpoint structures. 60 */ 61 bool dvmBreakpointStartup() 62 { 63 gDvm.breakpointSet = dvmBreakpointSetAlloc(); 64 return (gDvm.breakpointSet != NULL); 65 } 66 67 /* 68 * Free resources. 69 */ 70 void dvmBreakpointShutdown() 71 { 72 dvmBreakpointSetFree(gDvm.breakpointSet); 73 } 74 75 76 /* 77 * This represents a breakpoint inserted in the instruction stream. 78 * 79 * The debugger may ask us to create the same breakpoint multiple times. 80 * We only remove the breakpoint when the last instance is cleared. 81 */ 82 struct Breakpoint { 83 Method* method; /* method we're associated with */ 84 u2* addr; /* absolute memory address */ 85 u1 originalOpcode; /* original 8-bit opcode value */ 86 int setCount; /* #of times this breakpoint was set */ 87 }; 88 89 /* 90 * Set of breakpoints. 91 */ 92 struct BreakpointSet { 93 /* grab lock before reading or writing anything else in here */ 94 pthread_mutex_t lock; 95 96 /* vector of breakpoint structures */ 97 int alloc; 98 int count; 99 Breakpoint* breakpoints; 100 }; 101 102 /* 103 * Initialize a BreakpointSet. Initially empty. 104 */ 105 static BreakpointSet* dvmBreakpointSetAlloc() 106 { 107 BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet)); 108 109 dvmInitMutex(&pSet->lock); 110 /* leave the rest zeroed -- will alloc on first use */ 111 112 return pSet; 113 } 114 115 /* 116 * Free storage associated with a BreakpointSet. 117 */ 118 static void dvmBreakpointSetFree(BreakpointSet* pSet) 119 { 120 if (pSet == NULL) 121 return; 122 123 free(pSet->breakpoints); 124 free(pSet); 125 } 126 127 /* 128 * Lock the breakpoint set. 129 * 130 * It's not currently necessary to switch to VMWAIT in the event of 131 * contention, because nothing in here can block. However, it's possible 132 * that the bytecode-updater code could become fancier in the future, so 133 * we do the trylock dance as a bit of future-proofing. 134 */ 135 static void dvmBreakpointSetLock(BreakpointSet* pSet) 136 { 137 if (dvmTryLockMutex(&pSet->lock) != 0) { 138 Thread* self = dvmThreadSelf(); 139 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 140 dvmLockMutex(&pSet->lock); 141 dvmChangeStatus(self, oldStatus); 142 } 143 } 144 145 /* 146 * Unlock the breakpoint set. 147 */ 148 static void dvmBreakpointSetUnlock(BreakpointSet* pSet) 149 { 150 dvmUnlockMutex(&pSet->lock); 151 } 152 153 /* 154 * Return the #of breakpoints. 155 */ 156 static int dvmBreakpointSetCount(const BreakpointSet* pSet) 157 { 158 return pSet->count; 159 } 160 161 /* 162 * See if we already have an entry for this address. 163 * 164 * The BreakpointSet's lock must be acquired before calling here. 165 * 166 * Returns the index of the breakpoint entry, or -1 if not found. 167 */ 168 static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr) 169 { 170 int i; 171 172 for (i = 0; i < pSet->count; i++) { 173 Breakpoint* pBreak = &pSet->breakpoints[i]; 174 if (pBreak->addr == addr) 175 return i; 176 } 177 178 return -1; 179 } 180 181 /* 182 * Retrieve the opcode that was originally at the specified location. 183 * 184 * The BreakpointSet's lock must be acquired before calling here. 185 * 186 * Returns "true" with the opcode in *pOrig on success. 187 */ 188 static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet, 189 const u2* addr, u1* pOrig) 190 { 191 int idx = dvmBreakpointSetFind(pSet, addr); 192 if (idx < 0) 193 return false; 194 195 *pOrig = pSet->breakpoints[idx].originalOpcode; 196 return true; 197 } 198 199 /* 200 * Check the opcode. If it's a "magic" NOP, indicating the start of 201 * switch or array data in the instruction stream, we don't want to set 202 * a breakpoint. 203 * 204 * This can happen because the line number information dx generates 205 * associates the switch data with the switch statement's line number, 206 * and some debuggers put breakpoints at every address associated with 207 * a given line. The result is that the breakpoint stomps on the NOP 208 * instruction that doubles as a data table magic number, and an explicit 209 * check in the interpreter results in an exception being thrown. 210 * 211 * We don't want to simply refuse to add the breakpoint to the table, 212 * because that confuses the housekeeping. We don't want to reject the 213 * debugger's event request, and we want to be sure that there's exactly 214 * one un-set operation for every set op. 215 */ 216 static bool instructionIsMagicNop(const u2* addr) 217 { 218 u2 curVal = *addr; 219 return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0); 220 } 221 222 /* 223 * Add a breakpoint at a specific address. If the address is already 224 * present in the table, this just increments the count. 225 * 226 * For a new entry, this will extract and preserve the current opcode from 227 * the instruction stream, and replace it with a breakpoint opcode. 228 * 229 * The BreakpointSet's lock must be acquired before calling here. 230 * 231 * Returns "true" on success. 232 */ 233 static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method, 234 unsigned int instrOffset) 235 { 236 const int kBreakpointGrowth = 10; 237 const u2* addr = method->insns + instrOffset; 238 int idx = dvmBreakpointSetFind(pSet, addr); 239 Breakpoint* pBreak; 240 241 if (idx < 0) { 242 if (pSet->count == pSet->alloc) { 243 int newSize = pSet->alloc + kBreakpointGrowth; 244 Breakpoint* newVec; 245 246 LOGV("+++ increasing breakpoint set size to %d", newSize); 247 248 /* pSet->breakpoints will be NULL on first entry */ 249 newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint)); 250 if (newVec == NULL) 251 return false; 252 253 pSet->breakpoints = newVec; 254 pSet->alloc = newSize; 255 } 256 257 pBreak = &pSet->breakpoints[pSet->count++]; 258 pBreak->method = method; 259 pBreak->addr = (u2*)addr; 260 pBreak->originalOpcode = *(u1*)addr; 261 pBreak->setCount = 1; 262 263 /* 264 * Change the opcode. We must ensure that the BreakpointSet 265 * updates happen before we change the opcode. 266 * 267 * If the method has not been verified, we do NOT insert the 268 * breakpoint yet, since that will screw up the verifier. The 269 * debugger is allowed to insert breakpoints in unverified code, 270 * but since we don't execute unverified code we don't need to 271 * alter the bytecode yet. 272 * 273 * The class init code will "flush" all pending opcode writes 274 * before verification completes. 275 */ 276 assert(*(u1*)addr != OP_BREAKPOINT); 277 if (dvmIsClassVerified(method->clazz)) { 278 LOGV("Class %s verified, adding breakpoint at %p", 279 method->clazz->descriptor, addr); 280 if (instructionIsMagicNop(addr)) { 281 LOGV("Refusing to set breakpoint on %04x at %s.%s + %#x", 282 *addr, method->clazz->descriptor, method->name, 283 instrOffset); 284 } else { 285 ANDROID_MEMBAR_FULL(); 286 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr, 287 OP_BREAKPOINT); 288 } 289 } else { 290 LOGV("Class %s NOT verified, deferring breakpoint at %p", 291 method->clazz->descriptor, addr); 292 } 293 } else { 294 /* 295 * Breakpoint already exists, just increase the count. 296 */ 297 pBreak = &pSet->breakpoints[idx]; 298 pBreak->setCount++; 299 } 300 301 return true; 302 } 303 304 /* 305 * Remove one instance of the specified breakpoint. When the count 306 * reaches zero, the entry is removed from the table, and the original 307 * opcode is restored. 308 * 309 * The BreakpointSet's lock must be acquired before calling here. 310 */ 311 static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method, 312 unsigned int instrOffset) 313 { 314 const u2* addr = method->insns + instrOffset; 315 int idx = dvmBreakpointSetFind(pSet, addr); 316 317 if (idx < 0) { 318 /* breakpoint not found in set -- unexpected */ 319 if (*(u1*)addr == OP_BREAKPOINT) { 320 LOGE("Unable to restore breakpoint opcode (%s.%s +%#x)", 321 method->clazz->descriptor, method->name, instrOffset); 322 dvmAbort(); 323 } else { 324 LOGW("Breakpoint was already restored? (%s.%s +%#x)", 325 method->clazz->descriptor, method->name, instrOffset); 326 } 327 } else { 328 Breakpoint* pBreak = &pSet->breakpoints[idx]; 329 if (pBreak->setCount == 1) { 330 /* 331 * Must restore opcode before removing set entry. 332 * 333 * If the breakpoint was never flushed, we could be ovewriting 334 * a value with the same value. Not a problem, though we 335 * could end up causing a copy-on-write here when we didn't 336 * need to. (Not worth worrying about.) 337 */ 338 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr, 339 pBreak->originalOpcode); 340 ANDROID_MEMBAR_FULL(); 341 342 if (idx != pSet->count-1) { 343 /* shift down */ 344 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1], 345 (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0])); 346 } 347 pSet->count--; 348 pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug 349 } else { 350 pBreak->setCount--; 351 assert(pBreak->setCount > 0); 352 } 353 } 354 } 355 356 /* 357 * Flush any breakpoints associated with methods in "clazz". We want to 358 * change the opcode, which might not have happened when the breakpoint 359 * was initially set because the class was in the process of being 360 * verified. 361 * 362 * The BreakpointSet's lock must be acquired before calling here. 363 */ 364 static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz) 365 { 366 int i; 367 for (i = 0; i < pSet->count; i++) { 368 Breakpoint* pBreak = &pSet->breakpoints[i]; 369 if (pBreak->method->clazz == clazz) { 370 /* 371 * The breakpoint is associated with a method in this class. 372 * It might already be there or it might not; either way, 373 * flush it out. 374 */ 375 LOGV("Flushing breakpoint at %p for %s", 376 pBreak->addr, clazz->descriptor); 377 if (instructionIsMagicNop(pBreak->addr)) { 378 LOGV("Refusing to flush breakpoint on %04x at %s.%s + %#x", 379 *pBreak->addr, pBreak->method->clazz->descriptor, 380 pBreak->method->name, pBreak->addr - pBreak->method->insns); 381 } else { 382 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr, 383 OP_BREAKPOINT); 384 } 385 } 386 } 387 } 388 389 390 /* 391 * Do any debugger-attach-time initialization. 392 */ 393 void dvmInitBreakpoints() 394 { 395 /* quick sanity check */ 396 BreakpointSet* pSet = gDvm.breakpointSet; 397 dvmBreakpointSetLock(pSet); 398 if (dvmBreakpointSetCount(pSet) != 0) { 399 LOGW("WARNING: %d leftover breakpoints", dvmBreakpointSetCount(pSet)); 400 /* generally not good, but we can keep going */ 401 } 402 dvmBreakpointSetUnlock(pSet); 403 } 404 405 /* 406 * Add an address to the list, putting it in the first non-empty slot. 407 * 408 * Sometimes the debugger likes to add two entries for one breakpoint. 409 * We add two entries here, so that we get the right behavior when it's 410 * removed twice. 411 * 412 * This will only be run from the JDWP thread, and it will happen while 413 * we are updating the event list, which is synchronized. We're guaranteed 414 * to be the only one adding entries, and the lock ensures that nobody 415 * will be trying to remove them while we're in here. 416 * 417 * "addr" is the absolute address of the breakpoint bytecode. 418 */ 419 void dvmAddBreakAddr(Method* method, unsigned int instrOffset) 420 { 421 BreakpointSet* pSet = gDvm.breakpointSet; 422 dvmBreakpointSetLock(pSet); 423 dvmBreakpointSetAdd(pSet, method, instrOffset); 424 dvmBreakpointSetUnlock(pSet); 425 } 426 427 /* 428 * Remove an address from the list by setting the entry to NULL. 429 * 430 * This can be called from the JDWP thread (because the debugger has 431 * cancelled the breakpoint) or from an event thread (because it's a 432 * single-shot breakpoint, e.g. "run to line"). We only get here as 433 * the result of removing an entry from the event list, which is 434 * synchronized, so it should not be possible for two threads to be 435 * updating breakpoints at the same time. 436 */ 437 void dvmClearBreakAddr(Method* method, unsigned int instrOffset) 438 { 439 BreakpointSet* pSet = gDvm.breakpointSet; 440 dvmBreakpointSetLock(pSet); 441 dvmBreakpointSetRemove(pSet, method, instrOffset); 442 dvmBreakpointSetUnlock(pSet); 443 } 444 445 /* 446 * Get the original opcode from under a breakpoint. 447 * 448 * On SMP hardware it's possible one core might try to execute a breakpoint 449 * after another core has cleared it. We need to handle the case where 450 * there's no entry in the breakpoint set. (The memory barriers in the 451 * locks and in the breakpoint update code should ensure that, once we've 452 * observed the absence of a breakpoint entry, we will also now observe 453 * the restoration of the original opcode. The fact that we're holding 454 * the lock prevents other threads from confusing things further.) 455 */ 456 u1 dvmGetOriginalOpcode(const u2* addr) 457 { 458 BreakpointSet* pSet = gDvm.breakpointSet; 459 u1 orig = 0; 460 461 dvmBreakpointSetLock(pSet); 462 if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) { 463 orig = *(u1*)addr; 464 if (orig == OP_BREAKPOINT) { 465 LOGE("GLITCH: can't find breakpoint, opcode is still set"); 466 dvmAbort(); 467 } 468 } 469 dvmBreakpointSetUnlock(pSet); 470 471 return orig; 472 } 473 474 /* 475 * Flush any breakpoints associated with methods in "clazz". 476 * 477 * We don't want to modify the bytecode of a method before the verifier 478 * gets a chance to look at it, so we postpone opcode replacement until 479 * after verification completes. 480 */ 481 void dvmFlushBreakpoints(ClassObject* clazz) 482 { 483 BreakpointSet* pSet = gDvm.breakpointSet; 484 485 if (pSet == NULL) 486 return; 487 488 assert(dvmIsClassVerified(clazz)); 489 dvmBreakpointSetLock(pSet); 490 dvmBreakpointSetFlush(pSet, clazz); 491 dvmBreakpointSetUnlock(pSet); 492 } 493 494 /* 495 * Add a single step event. Currently this is a global item. 496 * 497 * We set up some initial values based on the thread's current state. This 498 * won't work well if the thread is running, so it's up to the caller to 499 * verify that it's suspended. 500 * 501 * This is only called from the JDWP thread. 502 */ 503 bool dvmAddSingleStep(Thread* thread, int size, int depth) 504 { 505 StepControl* pCtrl = &gDvm.stepControl; 506 507 if (pCtrl->active && thread != pCtrl->thread) { 508 LOGW("WARNING: single-step active for %p; adding %p", 509 pCtrl->thread, thread); 510 511 /* 512 * Keep going, overwriting previous. This can happen if you 513 * suspend a thread in Object.wait, hit the single-step key, then 514 * switch to another thread and do the same thing again. 515 * The first thread's step is still pending. 516 * 517 * TODO: consider making single-step per-thread. Adds to the 518 * overhead, but could be useful in rare situations. 519 */ 520 } 521 522 pCtrl->size = static_cast<JdwpStepSize>(size); 523 pCtrl->depth = static_cast<JdwpStepDepth>(depth); 524 pCtrl->thread = thread; 525 526 /* 527 * We may be stepping into or over method calls, or running until we 528 * return from the current method. To make this work we need to track 529 * the current line, current method, and current stack depth. We need 530 * to be checking these after most instructions, notably those that 531 * call methods, return from methods, or are on a different line from the 532 * previous instruction. 533 * 534 * We have to start with a snapshot of the current state. If we're in 535 * an interpreted method, everything we need is in the current frame. If 536 * we're in a native method, possibly with some extra JNI frames pushed 537 * on by PushLocalFrame, we want to use the topmost native method. 538 */ 539 const StackSaveArea* saveArea; 540 u4* fp; 541 u4* prevFp = NULL; 542 543 for (fp = thread->interpSave.curFrame; fp != NULL; 544 fp = saveArea->prevFrame) { 545 const Method* method; 546 547 saveArea = SAVEAREA_FROM_FP(fp); 548 method = saveArea->method; 549 550 if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method)) 551 break; 552 prevFp = fp; 553 } 554 if (fp == NULL) { 555 LOGW("Unexpected: step req in native-only threadid=%d", 556 thread->threadId); 557 return false; 558 } 559 if (prevFp != NULL) { 560 /* 561 * First interpreted frame wasn't the one at the bottom. Break 562 * frames are only inserted when calling from native->interp, so we 563 * don't need to worry about one being here. 564 */ 565 LOGV("##### init step while in native method"); 566 fp = prevFp; 567 assert(!dvmIsBreakFrame((u4*)fp)); 568 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method)); 569 saveArea = SAVEAREA_FROM_FP(fp); 570 } 571 572 /* 573 * Pull the goodies out. "xtra.currentPc" should be accurate since 574 * we update it on every instruction while the debugger is connected. 575 */ 576 pCtrl->method = saveArea->method; 577 // Clear out any old address set 578 if (pCtrl->pAddressSet != NULL) { 579 // (discard const) 580 free((void *)pCtrl->pAddressSet); 581 pCtrl->pAddressSet = NULL; 582 } 583 if (dvmIsNativeMethod(pCtrl->method)) { 584 pCtrl->line = -1; 585 } else { 586 pCtrl->line = dvmLineNumFromPC(saveArea->method, 587 saveArea->xtra.currentPc - saveArea->method->insns); 588 pCtrl->pAddressSet 589 = dvmAddressSetForLine(saveArea->method, pCtrl->line); 590 } 591 pCtrl->frameDepth = 592 dvmComputeVagueFrameDepth(thread, thread->interpSave.curFrame); 593 pCtrl->active = true; 594 595 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s", 596 pCtrl->thread, pCtrl->method, pCtrl->method->name, 597 pCtrl->line, pCtrl->frameDepth, 598 dvmJdwpStepDepthStr(pCtrl->depth), 599 dvmJdwpStepSizeStr(pCtrl->size)); 600 601 return true; 602 } 603 604 /* 605 * Disable a single step event. 606 */ 607 void dvmClearSingleStep(Thread* thread) 608 { 609 UNUSED_PARAMETER(thread); 610 611 gDvm.stepControl.active = false; 612 } 613 614 /* 615 * The interpreter just threw. Handle any special subMode requirements. 616 * All interpSave state must be valid on entry. 617 */ 618 void dvmReportExceptionThrow(Thread* self, Object* exception) 619 { 620 const Method* curMethod = self->interpSave.method; 621 #if defined(WITH_JIT) 622 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 623 dvmJitEndTraceSelect(self, self->interpSave.pc); 624 } 625 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) { 626 /* Discard any single-step native returns to translation */ 627 self->jitResumeNPC = NULL; 628 } 629 #endif 630 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 631 void *catchFrame; 632 int offset = self->interpSave.pc - curMethod->insns; 633 int catchRelPc = dvmFindCatchBlock(self, offset, exception, 634 true, &catchFrame); 635 dvmDbgPostException(self->interpSave.curFrame, offset, catchFrame, 636 catchRelPc, exception); 637 } 638 } 639 640 /* 641 * The interpreter is preparing to do an invoke (both native & normal). 642 * Handle any special subMode requirements. All interpSave state 643 * must be valid on entry. 644 */ 645 void dvmReportInvoke(Thread* self, const Method* methodToCall) 646 { 647 TRACE_METHOD_ENTER(self, methodToCall); 648 } 649 650 /* 651 * The interpreter is preparing to do a native invoke. Handle any 652 * special subMode requirements. NOTE: for a native invoke, 653 * dvmReportInvoke() and dvmReportPreNativeInvoke() will both 654 * be called prior to the invoke. fp is the Dalvik FP of the calling 655 * method. 656 */ 657 void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp) 658 { 659 #if defined(WITH_JIT) 660 /* 661 * Actively building a trace? If so, end it now. The trace 662 * builder can't follow into or through a native method. 663 */ 664 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 665 dvmCheckJit(self->interpSave.pc, self); 666 } 667 #endif 668 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 669 Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp); 670 assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr)); 671 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY); 672 } 673 } 674 675 /* 676 * The interpreter has returned from a native invoke. Handle any 677 * special subMode requirements. fp is the Dalvik FP of the calling 678 * method. 679 */ 680 void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp) 681 { 682 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 683 Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp); 684 assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr)); 685 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT); 686 } 687 if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) { 688 dvmFastNativeMethodTraceExit(methodToCall, self); 689 } 690 } 691 692 /* 693 * The interpreter has returned from a normal method. Handle any special 694 * subMode requirements. All interpSave state must be valid on entry. 695 */ 696 void dvmReportReturn(Thread* self) 697 { 698 TRACE_METHOD_EXIT(self, self->interpSave.method); 699 #if defined(WITH_JIT) 700 if (dvmIsBreakFrame(self->interpSave.curFrame) && 701 (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) { 702 dvmCheckJit(self->interpSave.pc, self); 703 } 704 #endif 705 } 706 707 /* 708 * Update the debugger on interesting events, such as hitting a breakpoint 709 * or a single-step point. This is called from the top of the interpreter 710 * loop, before the current instruction is processed. 711 * 712 * Set "methodEntry" if we've just entered the method. This detects 713 * method exit by checking to see if the next instruction is "return". 714 * 715 * This can't catch native method entry/exit, so we have to handle that 716 * at the point of invocation. We also need to catch it in dvmCallMethod 717 * if we want to capture native->native calls made through JNI. 718 * 719 * Notes to self: 720 * - Don't want to switch to VMWAIT while posting events to the debugger. 721 * Let the debugger code decide if we need to change state. 722 * - We may want to check for debugger-induced thread suspensions on 723 * every instruction. That would make a "suspend all" more responsive 724 * and reduce the chances of multiple simultaneous events occurring. 725 * However, it could change the behavior some. 726 * 727 * TODO: method entry/exit events are probably less common than location 728 * breakpoints. We may be able to speed things up a bit if we don't query 729 * the event list unless we know there's at least one lurking within. 730 */ 731 static void updateDebugger(const Method* method, const u2* pc, const u4* fp, 732 Thread* self) 733 { 734 int eventFlags = 0; 735 736 /* 737 * Update xtra.currentPc on every instruction. We need to do this if 738 * there's a chance that we could get suspended. This can happen if 739 * eventFlags != 0 here, or somebody manually requests a suspend 740 * (which gets handled at PERIOD_CHECKS time). One place where this 741 * needs to be correct is in dvmAddSingleStep(). 742 */ 743 dvmExportPC(pc, fp); 744 745 if (self->debugIsMethodEntry) { 746 eventFlags |= DBG_METHOD_ENTRY; 747 self->debugIsMethodEntry = false; 748 } 749 750 /* 751 * See if we have a breakpoint here. 752 * 753 * Depending on the "mods" associated with event(s) on this address, 754 * we may or may not actually send a message to the debugger. 755 */ 756 if (GET_OPCODE(*pc) == OP_BREAKPOINT) { 757 LOGV("+++ breakpoint hit at %p", pc); 758 eventFlags |= DBG_BREAKPOINT; 759 } 760 761 /* 762 * If the debugger is single-stepping one of our threads, check to 763 * see if we're that thread and we've reached a step point. 764 */ 765 const StepControl* pCtrl = &gDvm.stepControl; 766 if (pCtrl->active && pCtrl->thread == self) { 767 int frameDepth; 768 bool doStop = false; 769 const char* msg = NULL; 770 771 assert(!dvmIsNativeMethod(method)); 772 773 if (pCtrl->depth == SD_INTO) { 774 /* 775 * Step into method calls. We break when the line number 776 * or method pointer changes. If we're in SS_MIN mode, we 777 * always stop. 778 */ 779 if (pCtrl->method != method) { 780 doStop = true; 781 msg = "new method"; 782 } else if (pCtrl->size == SS_MIN) { 783 doStop = true; 784 msg = "new instruction"; 785 } else if (!dvmAddressSetGet( 786 pCtrl->pAddressSet, pc - method->insns)) { 787 doStop = true; 788 msg = "new line"; 789 } 790 } else if (pCtrl->depth == SD_OVER) { 791 /* 792 * Step over method calls. We break when the line number is 793 * different and the frame depth is <= the original frame 794 * depth. (We can't just compare on the method, because we 795 * might get unrolled past it by an exception, and it's tricky 796 * to identify recursion.) 797 */ 798 frameDepth = dvmComputeVagueFrameDepth(self, fp); 799 if (frameDepth < pCtrl->frameDepth) { 800 /* popped up one or more frames, always trigger */ 801 doStop = true; 802 msg = "method pop"; 803 } else if (frameDepth == pCtrl->frameDepth) { 804 /* same depth, see if we moved */ 805 if (pCtrl->size == SS_MIN) { 806 doStop = true; 807 msg = "new instruction"; 808 } else if (!dvmAddressSetGet(pCtrl->pAddressSet, 809 pc - method->insns)) { 810 doStop = true; 811 msg = "new line"; 812 } 813 } 814 } else { 815 assert(pCtrl->depth == SD_OUT); 816 /* 817 * Return from the current method. We break when the frame 818 * depth pops up. 819 * 820 * This differs from the "method exit" break in that it stops 821 * with the PC at the next instruction in the returned-to 822 * function, rather than the end of the returning function. 823 */ 824 frameDepth = dvmComputeVagueFrameDepth(self, fp); 825 if (frameDepth < pCtrl->frameDepth) { 826 doStop = true; 827 msg = "method pop"; 828 } 829 } 830 831 if (doStop) { 832 LOGV("#####S %s", msg); 833 eventFlags |= DBG_SINGLE_STEP; 834 } 835 } 836 837 /* 838 * Check to see if this is a "return" instruction. JDWP says we should 839 * send the event *after* the code has been executed, but it also says 840 * the location we provide is the last instruction. Since the "return" 841 * instruction has no interesting side effects, we should be safe. 842 * (We can't just move this down to the returnFromMethod label because 843 * we potentially need to combine it with other events.) 844 * 845 * We're also not supposed to generate a method exit event if the method 846 * terminates "with a thrown exception". 847 */ 848 u2 opcode = GET_OPCODE(*pc); 849 if (opcode == OP_RETURN_VOID || opcode == OP_RETURN || 850 opcode == OP_RETURN_WIDE ||opcode == OP_RETURN_OBJECT) 851 { 852 eventFlags |= DBG_METHOD_EXIT; 853 } 854 855 /* 856 * If there's something interesting going on, see if it matches one 857 * of the debugger filters. 858 */ 859 if (eventFlags != 0) { 860 Object* thisPtr = dvmGetThisPtr(method, fp); 861 if (thisPtr != NULL && !dvmIsHeapAddress(thisPtr)) { 862 /* 863 * TODO: remove this check if we're confident that the "this" 864 * pointer is where it should be -- slows us down, especially 865 * during single-step. 866 */ 867 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 868 LOGE("HEY: invalid 'this' ptr %p (%s.%s %s)", thisPtr, 869 method->clazz->descriptor, method->name, desc); 870 free(desc); 871 dvmAbort(); 872 } 873 dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr, 874 eventFlags); 875 } 876 } 877 878 /* 879 * Recover the "this" pointer from the current interpreted method. "this" 880 * is always in "in0" for non-static methods. 881 * 882 * The "ins" start at (#of registers - #of ins). Note in0 != v0. 883 * 884 * This works because "dx" guarantees that it will work. It's probably 885 * fairly common to have a virtual method that doesn't use its "this" 886 * pointer, in which case we're potentially wasting a register. However, 887 * the debugger doesn't treat "this" as just another argument. For 888 * example, events (such as breakpoints) can be enabled for specific 889 * values of "this". There is also a separate StackFrame.ThisObject call 890 * in JDWP that is expected to work for any non-native non-static method. 891 * 892 * Because we need it when setting up debugger event filters, we want to 893 * be able to do this quickly. 894 */ 895 Object* dvmGetThisPtr(const Method* method, const u4* fp) 896 { 897 if (dvmIsStaticMethod(method)) 898 return NULL; 899 return (Object*)fp[method->registersSize - method->insSize]; 900 } 901 902 903 #if defined(WITH_TRACKREF_CHECKS) 904 /* 905 * Verify that all internally-tracked references have been released. If 906 * they haven't, print them and abort the VM. 907 * 908 * "debugTrackedRefStart" indicates how many refs were on the list when 909 * we were first invoked. 910 */ 911 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method, 912 int debugTrackedRefStart) 913 { 914 if (dvmReferenceTableEntries(&self->internalLocalRefTable) 915 != (size_t) debugTrackedRefStart) 916 { 917 char* desc; 918 Object** top; 919 int count; 920 921 count = dvmReferenceTableEntries(&self->internalLocalRefTable); 922 923 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)", 924 debugTrackedRefStart, count); 925 desc = dexProtoCopyMethodDescriptor(&method->prototype); 926 LOGE(" current method is %s.%s %s", method->clazz->descriptor, 927 method->name, desc); 928 free(desc); 929 top = self->internalLocalRefTable.table + debugTrackedRefStart; 930 while (top < self->internalLocalRefTable.nextEntry) { 931 LOGE(" %p (%s)", 932 *top, 933 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : ""); 934 top++; 935 } 936 dvmDumpThread(self, false); 937 938 dvmAbort(); 939 } 940 //LOGI("TRACK OK"); 941 } 942 #endif 943 944 945 #ifdef LOG_INSTR 946 /* 947 * Dump the v-registers. Sent to the ILOG log tag. 948 */ 949 void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly) 950 { 951 int i, localCount; 952 953 localCount = method->registersSize - method->insSize; 954 955 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):", framePtr); 956 for (i = method->registersSize-1; i >= 0; i--) { 957 if (i >= localCount) { 958 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x", 959 i, i-localCount, framePtr[i]); 960 } else { 961 if (inOnly) { 962 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]"); 963 break; 964 } 965 const char* name = ""; 966 #if 0 // "locals" structure has changed -- need to rewrite this 967 int j; 968 DexFile* pDexFile = method->clazz->pDexFile; 969 const DexCode* pDexCode = dvmGetMethodCode(method); 970 int localsSize = dexGetLocalsSize(pDexFile, pDexCode); 971 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode); 972 for (j = 0; j < localsSize, j++) { 973 if (locals[j].registerNum == (u4) i) { 974 name = dvmDexStringStr(locals[j].pName); 975 break; 976 } 977 } 978 #endif 979 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s", 980 i, framePtr[i], name); 981 } 982 } 983 } 984 #endif 985 986 987 /* 988 * =========================================================================== 989 * Entry point and general support functions 990 * =========================================================================== 991 */ 992 993 /* 994 * Construct an s4 from two consecutive half-words of switch data. 995 * This needs to check endianness because the DEX optimizer only swaps 996 * half-words in instruction stream. 997 * 998 * "switchData" must be 32-bit aligned. 999 */ 1000 #if __BYTE_ORDER == __LITTLE_ENDIAN 1001 static inline s4 s4FromSwitchData(const void* switchData) { 1002 return *(s4*) switchData; 1003 } 1004 #else 1005 static inline s4 s4FromSwitchData(const void* switchData) { 1006 u2* data = switchData; 1007 return data[0] | (((s4) data[1]) << 16); 1008 } 1009 #endif 1010 1011 /* 1012 * Find the matching case. Returns the offset to the handler instructions. 1013 * 1014 * Returns 3 if we don't find a match (it's the size of the packed-switch 1015 * instruction). 1016 */ 1017 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal) 1018 { 1019 const int kInstrLen = 3; 1020 u2 size; 1021 s4 firstKey; 1022 const s4* entries; 1023 1024 /* 1025 * Packed switch data format: 1026 * ushort ident = 0x0100 magic value 1027 * ushort size number of entries in the table 1028 * int first_key first (and lowest) switch case value 1029 * int targets[size] branch targets, relative to switch opcode 1030 * 1031 * Total size is (4+size*2) 16-bit code units. 1032 */ 1033 if (*switchData++ != kPackedSwitchSignature) { 1034 /* should have been caught by verifier */ 1035 dvmThrowInternalError("bad packed switch magic"); 1036 return kInstrLen; 1037 } 1038 1039 size = *switchData++; 1040 assert(size > 0); 1041 1042 firstKey = *switchData++; 1043 firstKey |= (*switchData++) << 16; 1044 1045 if (testVal < firstKey || testVal >= firstKey + size) { 1046 LOGVV("Value %d not found in switch (%d-%d)", 1047 testVal, firstKey, firstKey+size-1); 1048 return kInstrLen; 1049 } 1050 1051 /* The entries are guaranteed to be aligned on a 32-bit boundary; 1052 * we can treat them as a native int array. 1053 */ 1054 entries = (const s4*) switchData; 1055 assert(((u4)entries & 0x3) == 0); 1056 1057 assert(testVal - firstKey >= 0 && testVal - firstKey < size); 1058 LOGVV("Value %d found in slot %d (goto 0x%02x)", 1059 testVal, testVal - firstKey, 1060 s4FromSwitchData(&entries[testVal - firstKey])); 1061 return s4FromSwitchData(&entries[testVal - firstKey]); 1062 } 1063 1064 /* 1065 * Find the matching case. Returns the offset to the handler instructions. 1066 * 1067 * Returns 3 if we don't find a match (it's the size of the sparse-switch 1068 * instruction). 1069 */ 1070 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal) 1071 { 1072 const int kInstrLen = 3; 1073 u2 size; 1074 const s4* keys; 1075 const s4* entries; 1076 1077 /* 1078 * Sparse switch data format: 1079 * ushort ident = 0x0200 magic value 1080 * ushort size number of entries in the table; > 0 1081 * int keys[size] keys, sorted low-to-high; 32-bit aligned 1082 * int targets[size] branch targets, relative to switch opcode 1083 * 1084 * Total size is (2+size*4) 16-bit code units. 1085 */ 1086 1087 if (*switchData++ != kSparseSwitchSignature) { 1088 /* should have been caught by verifier */ 1089 dvmThrowInternalError("bad sparse switch magic"); 1090 return kInstrLen; 1091 } 1092 1093 size = *switchData++; 1094 assert(size > 0); 1095 1096 /* The keys are guaranteed to be aligned on a 32-bit boundary; 1097 * we can treat them as a native int array. 1098 */ 1099 keys = (const s4*) switchData; 1100 assert(((u4)keys & 0x3) == 0); 1101 1102 /* The entries are guaranteed to be aligned on a 32-bit boundary; 1103 * we can treat them as a native int array. 1104 */ 1105 entries = keys + size; 1106 assert(((u4)entries & 0x3) == 0); 1107 1108 /* 1109 * Binary-search through the array of keys, which are guaranteed to 1110 * be sorted low-to-high. 1111 */ 1112 int lo = 0; 1113 int hi = size - 1; 1114 while (lo <= hi) { 1115 int mid = (lo + hi) >> 1; 1116 1117 s4 foundVal = s4FromSwitchData(&keys[mid]); 1118 if (testVal < foundVal) { 1119 hi = mid - 1; 1120 } else if (testVal > foundVal) { 1121 lo = mid + 1; 1122 } else { 1123 LOGVV("Value %d found in entry %d (goto 0x%02x)", 1124 testVal, mid, s4FromSwitchData(&entries[mid])); 1125 return s4FromSwitchData(&entries[mid]); 1126 } 1127 } 1128 1129 LOGVV("Value %d not found in switch", testVal); 1130 return kInstrLen; 1131 } 1132 1133 /* 1134 * Copy data for a fill-array-data instruction. On a little-endian machine 1135 * we can just do a memcpy(), on a big-endian system we have work to do. 1136 * 1137 * The trick here is that dexopt has byte-swapped each code unit, which is 1138 * exactly what we want for short/char data. For byte data we need to undo 1139 * the swap, and for 4- or 8-byte values we need to swap pieces within 1140 * each word. 1141 */ 1142 static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width) 1143 { 1144 #if __BYTE_ORDER == __LITTLE_ENDIAN 1145 memcpy(dest, src, size*width); 1146 #else 1147 int i; 1148 1149 switch (width) { 1150 case 1: 1151 /* un-swap pairs of bytes as we go */ 1152 for (i = (size-1) & ~1; i >= 0; i -= 2) { 1153 ((u1*)dest)[i] = ((u1*)src)[i+1]; 1154 ((u1*)dest)[i+1] = ((u1*)src)[i]; 1155 } 1156 /* 1157 * "src" is padded to end on a two-byte boundary, but we don't want to 1158 * assume "dest" is, so we handle odd length specially. 1159 */ 1160 if ((size & 1) != 0) { 1161 ((u1*)dest)[size-1] = ((u1*)src)[size]; 1162 } 1163 break; 1164 case 2: 1165 /* already swapped correctly */ 1166 memcpy(dest, src, size*width); 1167 break; 1168 case 4: 1169 /* swap word halves */ 1170 for (i = 0; i < (int) size; i++) { 1171 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1]; 1172 } 1173 break; 1174 case 8: 1175 /* swap word halves and words */ 1176 for (i = 0; i < (int) (size << 1); i += 2) { 1177 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2]; 1178 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1]; 1179 } 1180 break; 1181 default: 1182 LOGE("Unexpected width %d in copySwappedArrayData", width); 1183 dvmAbort(); 1184 break; 1185 } 1186 #endif 1187 } 1188 1189 /* 1190 * Fill the array with predefined constant values. 1191 * 1192 * Returns true if job is completed, otherwise false to indicate that 1193 * an exception has been thrown. 1194 */ 1195 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData) 1196 { 1197 u2 width; 1198 u4 size; 1199 1200 if (arrayObj == NULL) { 1201 dvmThrowNullPointerException(NULL); 1202 return false; 1203 } 1204 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz, 1205 CLASS_ISOBJECTARRAY)); 1206 1207 /* 1208 * Array data table format: 1209 * ushort ident = 0x0300 magic value 1210 * ushort width width of each element in the table 1211 * uint size number of elements in the table 1212 * ubyte data[size*width] table of data values (may contain a single-byte 1213 * padding at the end) 1214 * 1215 * Total size is 4+(width * size + 1)/2 16-bit code units. 1216 */ 1217 if (arrayData[0] != kArrayDataSignature) { 1218 dvmThrowInternalError("bad array data magic"); 1219 return false; 1220 } 1221 1222 width = arrayData[1]; 1223 size = arrayData[2] | (((u4)arrayData[3]) << 16); 1224 1225 if (size > arrayObj->length) { 1226 dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size); 1227 return false; 1228 } 1229 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width); 1230 return true; 1231 } 1232 1233 /* 1234 * Find the concrete method that corresponds to "methodIdx". The code in 1235 * "method" is executing invoke-method with "thisClass" as its first argument. 1236 * 1237 * Returns NULL with an exception raised on failure. 1238 */ 1239 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx, 1240 const Method* method, DvmDex* methodClassDex) 1241 { 1242 Method* absMethod; 1243 Method* methodToCall; 1244 int i, vtableIndex; 1245 1246 /* 1247 * Resolve the method. This gives us the abstract method from the 1248 * interface class declaration. 1249 */ 1250 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx); 1251 if (absMethod == NULL) { 1252 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx); 1253 if (absMethod == NULL) { 1254 LOGV("+ unknown method"); 1255 return NULL; 1256 } 1257 } 1258 1259 /* make sure absMethod->methodIndex means what we think it means */ 1260 assert(dvmIsAbstractMethod(absMethod)); 1261 1262 /* 1263 * Run through the "this" object's iftable. Find the entry for 1264 * absMethod's class, then use absMethod->methodIndex to find 1265 * the method's entry. The value there is the offset into our 1266 * vtable of the actual method to execute. 1267 * 1268 * The verifier does not guarantee that objects stored into 1269 * interface references actually implement the interface, so this 1270 * check cannot be eliminated. 1271 */ 1272 for (i = 0; i < thisClass->iftableCount; i++) { 1273 if (thisClass->iftable[i].clazz == absMethod->clazz) 1274 break; 1275 } 1276 if (i == thisClass->iftableCount) { 1277 /* impossible in verified DEX, need to check for it in unverified */ 1278 dvmThrowIncompatibleClassChangeError("interface not implemented"); 1279 return NULL; 1280 } 1281 1282 assert(absMethod->methodIndex < 1283 thisClass->iftable[i].clazz->virtualMethodCount); 1284 1285 vtableIndex = 1286 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex]; 1287 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount); 1288 methodToCall = thisClass->vtable[vtableIndex]; 1289 1290 #if 0 1291 /* this can happen when there's a stale class file */ 1292 if (dvmIsAbstractMethod(methodToCall)) { 1293 dvmThrowAbstractMethodError("interface method not implemented"); 1294 return NULL; 1295 } 1296 #else 1297 assert(!dvmIsAbstractMethod(methodToCall) || 1298 methodToCall->nativeFunc != NULL); 1299 #endif 1300 1301 LOGVV("+++ interface=%s.%s concrete=%s.%s", 1302 absMethod->clazz->descriptor, absMethod->name, 1303 methodToCall->clazz->descriptor, methodToCall->name); 1304 assert(methodToCall != NULL); 1305 1306 return methodToCall; 1307 } 1308 1309 1310 1311 /* 1312 * Helpers for dvmThrowVerificationError(). 1313 * 1314 * Each returns a newly-allocated string. 1315 */ 1316 #define kThrowShow_accessFromClass 1 1317 static std::string classNameFromIndex(const Method* method, int ref, 1318 VerifyErrorRefType refType, int flags) 1319 { 1320 const DvmDex* pDvmDex = method->clazz->pDvmDex; 1321 if (refType == VERIFY_ERROR_REF_FIELD) { 1322 /* get class ID from field ID */ 1323 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref); 1324 ref = pFieldId->classIdx; 1325 } else if (refType == VERIFY_ERROR_REF_METHOD) { 1326 /* get class ID from method ID */ 1327 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref); 1328 ref = pMethodId->classIdx; 1329 } 1330 1331 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref); 1332 std::string dotClassName(dvmHumanReadableDescriptor(className)); 1333 if (flags == 0) { 1334 return dotClassName; 1335 } 1336 1337 std::string result; 1338 if ((flags & kThrowShow_accessFromClass) != 0) { 1339 result += "tried to access class " + dotClassName; 1340 result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor); 1341 } else { 1342 assert(false); // should've been caught above 1343 } 1344 1345 return result; 1346 } 1347 static std::string fieldNameFromIndex(const Method* method, int ref, 1348 VerifyErrorRefType refType, int flags) 1349 { 1350 if (refType != VERIFY_ERROR_REF_FIELD) { 1351 LOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_FIELD, refType); 1352 return NULL; /* no message */ 1353 } 1354 1355 const DvmDex* pDvmDex = method->clazz->pDvmDex; 1356 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref); 1357 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx); 1358 const char* fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx); 1359 1360 std::string dotName(dvmHumanReadableDescriptor(className)); 1361 1362 if ((flags & kThrowShow_accessFromClass) != 0) { 1363 std::string result; 1364 result += "tried to access field "; 1365 result += dotName + "." + fieldName; 1366 result += " from class "; 1367 result += dvmHumanReadableDescriptor(method->clazz->descriptor); 1368 return result; 1369 } 1370 return dotName + "." + fieldName; 1371 } 1372 static std::string methodNameFromIndex(const Method* method, int ref, 1373 VerifyErrorRefType refType, int flags) 1374 { 1375 if (refType != VERIFY_ERROR_REF_METHOD) { 1376 LOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_METHOD,refType); 1377 return NULL; /* no message */ 1378 } 1379 1380 const DvmDex* pDvmDex = method->clazz->pDvmDex; 1381 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref); 1382 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx); 1383 const char* methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx); 1384 1385 std::string dotName(dvmHumanReadableDescriptor(className)); 1386 1387 if ((flags & kThrowShow_accessFromClass) != 0) { 1388 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 1389 std::string result; 1390 result += "tried to access method "; 1391 result += dotName + "." + methodName + ":" + desc; 1392 result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor); 1393 free(desc); 1394 return result; 1395 } 1396 return dotName + "." + methodName; 1397 } 1398 1399 /* 1400 * Throw an exception for a problem identified by the verifier. 1401 * 1402 * This is used by the invoke-verification-error instruction. It always 1403 * throws an exception. 1404 * 1405 * "kind" indicates the kind of failure encountered by the verifier. It 1406 * has two parts, an error code and an indication of the reference type. 1407 */ 1408 void dvmThrowVerificationError(const Method* method, int kind, int ref) 1409 { 1410 int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift); 1411 int errorRefPart = kind >> kVerifyErrorRefTypeShift; 1412 VerifyError errorKind = static_cast<VerifyError>(errorPart); 1413 VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart); 1414 ClassObject* exceptionClass = gDvm.exVerifyError; 1415 std::string msg; 1416 1417 switch ((VerifyError) errorKind) { 1418 case VERIFY_ERROR_NO_CLASS: 1419 exceptionClass = gDvm.exNoClassDefFoundError; 1420 msg = classNameFromIndex(method, ref, refType, 0); 1421 break; 1422 case VERIFY_ERROR_NO_FIELD: 1423 exceptionClass = gDvm.exNoSuchFieldError; 1424 msg = fieldNameFromIndex(method, ref, refType, 0); 1425 break; 1426 case VERIFY_ERROR_NO_METHOD: 1427 exceptionClass = gDvm.exNoSuchMethodError; 1428 msg = methodNameFromIndex(method, ref, refType, 0); 1429 break; 1430 case VERIFY_ERROR_ACCESS_CLASS: 1431 exceptionClass = gDvm.exIllegalAccessError; 1432 msg = classNameFromIndex(method, ref, refType, 1433 kThrowShow_accessFromClass); 1434 break; 1435 case VERIFY_ERROR_ACCESS_FIELD: 1436 exceptionClass = gDvm.exIllegalAccessError; 1437 msg = fieldNameFromIndex(method, ref, refType, 1438 kThrowShow_accessFromClass); 1439 break; 1440 case VERIFY_ERROR_ACCESS_METHOD: 1441 exceptionClass = gDvm.exIllegalAccessError; 1442 msg = methodNameFromIndex(method, ref, refType, 1443 kThrowShow_accessFromClass); 1444 break; 1445 case VERIFY_ERROR_CLASS_CHANGE: 1446 exceptionClass = gDvm.exIncompatibleClassChangeError; 1447 msg = classNameFromIndex(method, ref, refType, 0); 1448 break; 1449 case VERIFY_ERROR_INSTANTIATION: 1450 exceptionClass = gDvm.exInstantiationError; 1451 msg = classNameFromIndex(method, ref, refType, 0); 1452 break; 1453 1454 case VERIFY_ERROR_GENERIC: 1455 /* generic VerifyError; use default exception, no message */ 1456 break; 1457 case VERIFY_ERROR_NONE: 1458 /* should never happen; use default exception */ 1459 assert(false); 1460 msg = strdup("weird - no error specified"); 1461 break; 1462 1463 /* no default clause -- want warning if enum updated */ 1464 } 1465 1466 dvmThrowException(exceptionClass, msg.c_str()); 1467 } 1468 1469 /* 1470 * Update interpBreak for a single thread. 1471 */ 1472 void updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable) 1473 { 1474 InterpBreak oldValue, newValue; 1475 do { 1476 oldValue = newValue = thread->interpBreak; 1477 newValue.ctl.breakFlags = kInterpNoBreak; // Assume full reset 1478 if (enable) 1479 newValue.ctl.subMode |= subMode; 1480 else 1481 newValue.ctl.subMode &= ~subMode; 1482 if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK) 1483 newValue.ctl.breakFlags |= kInterpSingleStep; 1484 if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK) 1485 newValue.ctl.breakFlags |= kInterpSafePoint; 1486 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ? 1487 thread->altHandlerTable : thread->mainHandlerTable; 1488 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all, 1489 &thread->interpBreak.all) != 0); 1490 } 1491 1492 /* 1493 * Update interpBreak for all threads. 1494 */ 1495 void updateAllInterpBreak(ExecutionSubModes subMode, bool enable) 1496 { 1497 Thread* self = dvmThreadSelf(); 1498 Thread* thread; 1499 1500 dvmLockThreadList(self); 1501 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 1502 updateInterpBreak(thread, subMode, enable); 1503 } 1504 dvmUnlockThreadList(); 1505 } 1506 1507 /* 1508 * Update the normal and debugger suspend counts for a thread. 1509 * threadSuspendCount must be acquired before calling this to 1510 * ensure a clean update of suspendCount, dbgSuspendCount and 1511 * sumThreadSuspendCount. 1512 * 1513 * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount. 1514 * Move under WITH_JIT ifdefs. 1515 */ 1516 void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta) 1517 { 1518 thread->suspendCount += delta; 1519 thread->dbgSuspendCount += dbgDelta; 1520 updateInterpBreak(thread, kSubModeSuspendPending, 1521 (thread->suspendCount != 0)); 1522 // Update the global suspend count total 1523 gDvm.sumThreadSuspendCount += delta; 1524 } 1525 1526 1527 void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode) 1528 { 1529 updateInterpBreak(thread, subMode, false); 1530 } 1531 1532 void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode) 1533 { 1534 updateInterpBreak(thread, subMode, true); 1535 } 1536 1537 void dvmEnableAllSubMode(ExecutionSubModes subMode) 1538 { 1539 updateAllInterpBreak(subMode, true); 1540 } 1541 1542 void dvmDisableAllSubMode(ExecutionSubModes subMode) 1543 { 1544 updateAllInterpBreak(subMode, false); 1545 } 1546 1547 /* 1548 * Do a sanity check on interpreter state saved to Thread. 1549 * A failure here doesn't necessarily mean that something is wrong, 1550 * so this code should only be used during development to suggest 1551 * a possible problem. 1552 */ 1553 void dvmCheckInterpStateConsistency() 1554 { 1555 Thread* self = dvmThreadSelf(); 1556 Thread* thread; 1557 uint8_t breakFlags; 1558 uint8_t subMode; 1559 void* handlerTable; 1560 1561 dvmLockThreadList(self); 1562 breakFlags = self->interpBreak.ctl.breakFlags; 1563 subMode = self->interpBreak.ctl.subMode; 1564 handlerTable = self->interpBreak.ctl.curHandlerTable; 1565 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 1566 if (subMode != thread->interpBreak.ctl.subMode) { 1567 LOGD("Warning: subMode mismatch - %#x:%#x, tid[%d]", 1568 subMode,thread->interpBreak.ctl.subMode,thread->threadId); 1569 } 1570 if (breakFlags != thread->interpBreak.ctl.breakFlags) { 1571 LOGD("Warning: breakFlags mismatch - %#x:%#x, tid[%d]", 1572 breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId); 1573 } 1574 if (handlerTable != thread->interpBreak.ctl.curHandlerTable) { 1575 LOGD("Warning: curHandlerTable mismatch - %#x:%#x, tid[%d]", 1576 (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable, 1577 thread->threadId); 1578 } 1579 #if defined(WITH_JIT) 1580 if (thread->pJitProfTable != gDvmJit.pProfTable) { 1581 LOGD("Warning: pJitProfTable mismatch - %#x:%#x, tid[%d]", 1582 (int)thread->pJitProfTable,(int)gDvmJit.pProfTable, 1583 thread->threadId); 1584 } 1585 if (thread->jitThreshold != gDvmJit.threshold) { 1586 LOGD("Warning: jitThreshold mismatch - %#x:%#x, tid[%d]", 1587 (int)thread->jitThreshold,(int)gDvmJit.threshold, 1588 thread->threadId); 1589 } 1590 #endif 1591 } 1592 dvmUnlockThreadList(); 1593 } 1594 1595 /* 1596 * Arm a safepoint callback for a thread. If funct is null, 1597 * clear any pending callback. 1598 * TODO: only gc is currently using this feature, and will have 1599 * at most a single outstanding callback request. Until we need 1600 * something more capable and flexible, enforce this limit. 1601 */ 1602 void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct, 1603 void* arg) 1604 { 1605 dvmLockMutex(&thread->callbackMutex); 1606 if ((funct == NULL) || (thread->callback == NULL)) { 1607 thread->callback = funct; 1608 thread->callbackArg = arg; 1609 if (funct != NULL) { 1610 dvmEnableSubMode(thread, kSubModeCallbackPending); 1611 } else { 1612 dvmDisableSubMode(thread, kSubModeCallbackPending); 1613 } 1614 } else { 1615 // Already armed. Different? 1616 if ((funct != thread->callback) || 1617 (arg != thread->callbackArg)) { 1618 // Yes - report failure and die 1619 LOGE("ArmSafePointCallback failed, thread %d", thread->threadId); 1620 dvmUnlockMutex(&thread->callbackMutex); 1621 dvmAbort(); 1622 } 1623 } 1624 dvmUnlockMutex(&thread->callbackMutex); 1625 } 1626 1627 /* 1628 * One-time initialization at thread creation. Here we initialize 1629 * useful constants. 1630 */ 1631 void dvmInitInterpreterState(Thread* self) 1632 { 1633 #if defined(WITH_JIT) 1634 /* 1635 * Reserve a static entity here to quickly setup runtime contents as 1636 * gcc will issue block copy instructions. 1637 */ 1638 static struct JitToInterpEntries jitToInterpEntries = { 1639 dvmJitToInterpNormal, 1640 dvmJitToInterpNoChain, 1641 dvmJitToInterpPunt, 1642 dvmJitToInterpSingleStep, 1643 dvmJitToInterpTraceSelect, 1644 #if defined(WITH_SELF_VERIFICATION) 1645 dvmJitToInterpBackwardBranch, 1646 #else 1647 NULL, 1648 #endif 1649 }; 1650 #endif 1651 1652 // Begin initialization 1653 self->cardTable = gDvm.biasedCardTableBase; 1654 #if defined(WITH_JIT) 1655 // One-time initializations 1656 self->jitToInterpEntries = jitToInterpEntries; 1657 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN; 1658 self->pProfileCountdown = &gDvmJit.profileCountdown; 1659 // Jit state that can change 1660 dvmJitUpdateThreadStateSingle(self); 1661 #endif 1662 dvmInitializeInterpBreak(self); 1663 } 1664 1665 /* 1666 * For a newly-created thread, we need to start off with interpBreak 1667 * set to any existing global modes. The caller must hold the 1668 * thread list lock. 1669 */ 1670 void dvmInitializeInterpBreak(Thread* thread) 1671 { 1672 if (gDvm.instructionCountEnableCount > 0) { 1673 dvmEnableSubMode(thread, kSubModeInstCounting); 1674 } 1675 if (dvmIsMethodTraceActive()) { 1676 dvmEnableSubMode(thread, kSubModeMethodTrace); 1677 } 1678 if (gDvm.emulatorTraceEnableCount > 0) { 1679 dvmEnableSubMode(thread, kSubModeEmulatorTrace); 1680 } 1681 if (gDvm.debuggerActive) { 1682 dvmEnableSubMode(thread, kSubModeDebuggerActive); 1683 } 1684 #if 0 1685 // Debugging stress mode - force checkBefore 1686 dvmEnableSubMode(thread, kSubModeCheckAlways); 1687 #endif 1688 } 1689 1690 /* 1691 * Inter-instruction handler invoked in between instruction interpretations 1692 * to handle exceptional events such as debugging housekeeping, instruction 1693 * count profiling, JIT trace building, etc. Dalvik PC has been exported 1694 * prior to call, but Thread copy of dPC & fp are not current. 1695 */ 1696 void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self) 1697 { 1698 const Method* method = self->interpSave.method; 1699 assert(self->interpBreak.ctl.breakFlags != 0); 1700 assert(pc >= method->insns && pc < 1701 method->insns + dvmGetMethodInsnsSize(method)); 1702 1703 #if 0 1704 /* 1705 * When we hit a specific method, enable verbose instruction logging. 1706 * Sometimes it's helpful to use the debugger attach as a trigger too. 1707 */ 1708 if (*pIsMethodEntry) { 1709 static const char* cd = "Landroid/test/Arithmetic;"; 1710 static const char* mn = "shiftTest2"; 1711 static const char* sg = "()V"; 1712 1713 if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/ 1714 strcmp(method->clazz->descriptor, cd) == 0 && 1715 strcmp(method->name, mn) == 0 && 1716 strcmp(method->shorty, sg) == 0) 1717 { 1718 LOGW("Reached %s.%s, enabling verbose mode", 1719 method->clazz->descriptor, method->name); 1720 android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE); 1721 dumpRegs(method, fp, true); 1722 } 1723 1724 if (!gDvm.debuggerActive) 1725 *pIsMethodEntry = false; 1726 } 1727 #endif 1728 1729 /* Safe point handling */ 1730 if (self->suspendCount || 1731 (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) { 1732 // Are we are a safe point? 1733 int flags; 1734 flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc)); 1735 if (flags & (VERIFY_GC_INST_MASK & ~kInstrCanThrow)) { 1736 // Yes, at a safe point. Pending callback? 1737 if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) { 1738 SafePointCallback callback; 1739 void* arg; 1740 // Get consistent funct/arg pair 1741 dvmLockMutex(&self->callbackMutex); 1742 callback = self->callback; 1743 arg = self->callbackArg; 1744 dvmUnlockMutex(&self->callbackMutex); 1745 // Update Thread structure 1746 self->interpSave.pc = pc; 1747 self->interpSave.curFrame = fp; 1748 if (callback != NULL) { 1749 // Do the callback 1750 if (!callback(self,arg)) { 1751 // disarm 1752 dvmArmSafePointCallback(self, NULL, NULL); 1753 } 1754 } 1755 } 1756 // Need to suspend? 1757 if (self->suspendCount) { 1758 dvmExportPC(pc, fp); 1759 dvmCheckSuspendPending(self); 1760 } 1761 } 1762 } 1763 1764 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 1765 updateDebugger(method, pc, fp, self); 1766 } 1767 if (gDvm.instructionCountEnableCount != 0) { 1768 /* 1769 * Count up the #of executed instructions. This isn't synchronized 1770 * for thread-safety; if we need that we should make this 1771 * thread-local and merge counts into the global area when threads 1772 * exit (perhaps suspending all other threads GC-style and pulling 1773 * the data out of them). 1774 */ 1775 gDvm.executedInstrCounts[GET_OPCODE(*pc)]++; 1776 } 1777 1778 1779 #if defined(WITH_TRACKREF_CHECKS) 1780 dvmInterpCheckTrackedRefs(self, method, 1781 self->interpSave.debugTrackedRefStart); 1782 #endif 1783 1784 #if defined(WITH_JIT) 1785 // Does the JIT need anything done now? 1786 if (self->interpBreak.ctl.subMode & 1787 (kSubModeJitTraceBuild | kSubModeJitSV)) { 1788 // Are we building a trace? 1789 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 1790 dvmCheckJit(pc, self); 1791 } 1792 1793 #if defined(WITH_SELF_VERIFICATION) 1794 // Are we replaying a trace? 1795 if (self->interpBreak.ctl.subMode & kSubModeJitSV) { 1796 dvmCheckSelfVerification(pc, self); 1797 } 1798 #endif 1799 } 1800 #endif 1801 1802 /* 1803 * CountedStep processing. NOTE: must be the last here to allow 1804 * preceeding special case handler to manipulate single-step count. 1805 */ 1806 if (self->interpBreak.ctl.subMode & kSubModeCountedStep) { 1807 if (self->singleStepCount == 0) { 1808 // We've exhausted our single step count 1809 dvmDisableSubMode(self, kSubModeCountedStep); 1810 #if defined(WITH_JIT) 1811 #if 0 1812 /* 1813 * For debugging. If jitResumeDPC is non-zero, then 1814 * we expect to return to a trace in progress. There 1815 * are valid reasons why we wouldn't (such as an exception 1816 * throw), but here we can keep track. 1817 */ 1818 if (self->jitResumeDPC != NULL) { 1819 if (self->jitResumeDPC == pc) { 1820 if (self->jitResumeNPC != NULL) { 1821 LOGD("SS return to trace - pc:%#x to 0x:%x", 1822 (int)pc, (int)self->jitResumeNPC); 1823 } else { 1824 LOGD("SS return to interp - pc:%#x",(int)pc); 1825 } 1826 } else { 1827 LOGD("SS failed to return. Expected %#x, now at %#x", 1828 (int)self->jitResumeDPC, (int)pc); 1829 } 1830 } 1831 #endif 1832 #if 0 1833 // TODO - fix JIT single-stepping resume mode (b/5551114) 1834 // self->jitResumeNPC needs to be cleared in callPrep 1835 1836 // If we've got a native return and no other reasons to 1837 // remain in singlestep/break mode, do a long jump 1838 if (self->jitResumeNPC != NULL && 1839 self->interpBreak.ctl.breakFlags == 0) { 1840 assert(self->jitResumeDPC == pc); 1841 self->jitResumeDPC = NULL; 1842 dvmJitResumeTranslation(self, pc, fp); 1843 // Doesn't return 1844 dvmAbort(); 1845 } 1846 // In case resume is blocked by non-zero breakFlags, clear 1847 // jitResumeNPC here. 1848 self->jitResumeNPC = NULL; 1849 self->jitResumeDPC = NULL; 1850 self->inJitCodeCache = NULL; 1851 #endif 1852 #endif 1853 } else { 1854 self->singleStepCount--; 1855 #if defined(WITH_JIT) 1856 if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) { 1857 /* 1858 * Direct return to an existing translation following a 1859 * single step is valid only if we step once. If we're 1860 * here, an additional step was added so we need to invalidate 1861 * the return to translation. 1862 */ 1863 self->jitResumeNPC = NULL; 1864 self->inJitCodeCache = NULL; 1865 } 1866 #endif 1867 } 1868 } 1869 } 1870 1871 /* 1872 * Main interpreter loop entry point. 1873 * 1874 * This begins executing code at the start of "method". On exit, "pResult" 1875 * holds the return value of the method (or, if "method" returns NULL, it 1876 * holds an undefined value). 1877 * 1878 * The interpreted stack frame, which holds the method arguments, has 1879 * already been set up. 1880 */ 1881 void dvmInterpret(Thread* self, const Method* method, JValue* pResult) 1882 { 1883 InterpSaveState interpSaveState; 1884 ExecutionSubModes savedSubModes; 1885 1886 #if defined(WITH_JIT) 1887 /* Target-specific save/restore */ 1888 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT]; 1889 /* 1890 * If the previous VM left the code cache through single-stepping the 1891 * inJitCodeCache flag will be set when the VM is re-entered (for example, 1892 * in self-verification mode we single-step NEW_INSTANCE which may re-enter 1893 * the VM through findClassFromLoaderNoInit). Because of that, we cannot 1894 * assert that self->inJitCodeCache is NULL here. 1895 */ 1896 #endif 1897 1898 /* 1899 * Save interpreter state from previous activation, linking 1900 * new to last. 1901 */ 1902 interpSaveState = self->interpSave; 1903 self->interpSave.prev = &interpSaveState; 1904 /* 1905 * Strip out and save any flags that should not be inherited by 1906 * nested interpreter activation. 1907 */ 1908 savedSubModes = (ExecutionSubModes)( 1909 self->interpBreak.ctl.subMode & LOCAL_SUBMODE); 1910 if (savedSubModes != kSubModeNormal) { 1911 dvmDisableSubMode(self, savedSubModes); 1912 } 1913 #if defined(WITH_JIT) 1914 dvmJitCalleeSave(calleeSave); 1915 #endif 1916 1917 1918 #if defined(WITH_TRACKREF_CHECKS) 1919 self->interpSave.debugTrackedRefStart = 1920 dvmReferenceTableEntries(&self->internalLocalRefTable); 1921 #endif 1922 self->debugIsMethodEntry = true; 1923 #if defined(WITH_JIT) 1924 dvmJitCalleeSave(calleeSave); 1925 /* Initialize the state to kJitNot */ 1926 self->jitState = kJitNot; 1927 #endif 1928 1929 /* 1930 * Initialize working state. 1931 * 1932 * No need to initialize "retval". 1933 */ 1934 self->interpSave.method = method; 1935 self->interpSave.curFrame = (u4*) self->interpSave.curFrame; 1936 self->interpSave.pc = method->insns; 1937 1938 assert(!dvmIsNativeMethod(method)); 1939 1940 /* 1941 * Make sure the class is ready to go. Shouldn't be possible to get 1942 * here otherwise. 1943 */ 1944 if (method->clazz->status < CLASS_INITIALIZING || 1945 method->clazz->status == CLASS_ERROR) 1946 { 1947 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)", 1948 method->clazz->descriptor, method->clazz->status); 1949 dvmDumpThread(self, false); 1950 dvmAbort(); 1951 } 1952 1953 typedef void (*Interpreter)(Thread*); 1954 Interpreter stdInterp; 1955 if (gDvm.executionMode == kExecutionModeInterpFast) 1956 stdInterp = dvmMterpStd; 1957 #if defined(WITH_JIT) 1958 else if (gDvm.executionMode == kExecutionModeJit) 1959 stdInterp = dvmMterpStd; 1960 #endif 1961 else 1962 stdInterp = dvmInterpretPortable; 1963 1964 // Call the interpreter 1965 (*stdInterp)(self); 1966 1967 *pResult = self->interpSave.retval; 1968 1969 /* Restore interpreter state from previous activation */ 1970 self->interpSave = interpSaveState; 1971 #if defined(WITH_JIT) 1972 dvmJitCalleeRestore(calleeSave); 1973 #endif 1974 if (savedSubModes != kSubModeNormal) { 1975 dvmEnableSubMode(self, savedSubModes); 1976 } 1977 } 1978