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 ALOGV("+++ 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 ALOGV("Class %s verified, adding breakpoint at %p", 279 method->clazz->descriptor, addr); 280 if (instructionIsMagicNop(addr)) { 281 ALOGV("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 ALOGV("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 ALOGE("Unable to restore breakpoint opcode (%s.%s +%#x)", 321 method->clazz->descriptor, method->name, instrOffset); 322 dvmAbort(); 323 } else { 324 ALOGW("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 ALOGV("Flushing breakpoint at %p for %s", 376 pBreak->addr, clazz->descriptor); 377 if (instructionIsMagicNop(pBreak->addr)) { 378 ALOGV("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 ALOGW("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 ALOGE("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 ALOGW("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 ALOGW("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 ALOGV("##### 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 ALOGV("##### 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 ALOGV("+++ 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 ALOGV("#####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 || opcode == OP_RETURN_VOID_BARRIER || 850 opcode == OP_RETURN_OBJECT || opcode == OP_RETURN_WIDE) 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 ALOGE("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 ALOGE("TRACK: unreleased internal reference (prev=%d total=%d)", 924 debugTrackedRefStart, count); 925 desc = dexProtoCopyMethodDescriptor(&method->prototype); 926 ALOGE(" 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 ALOGE(" %p (%s)", 932 *top, 933 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : ""); 934 top++; 935 } 936 dvmDumpThread(self, false); 937 938 dvmAbort(); 939 } 940 //ALOGI("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 ALOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):", framePtr); 956 for (i = method->registersSize-1; i >= 0; i--) { 957 if (i >= localCount) { 958 ALOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x", 959 i, i-localCount, framePtr[i]); 960 } else { 961 if (inOnly) { 962 ALOG(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 ALOG(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 * Find the matching case. Returns the offset to the handler instructions. 995 * 996 * Returns 3 if we don't find a match (it's the size of the packed-switch 997 * instruction). 998 */ 999 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal) 1000 { 1001 const int kInstrLen = 3; 1002 u2 size; 1003 s4 firstKey; 1004 const s4* entries; 1005 1006 /* 1007 * Packed switch data format: 1008 * ushort ident = 0x0100 magic value 1009 * ushort size number of entries in the table 1010 * int first_key first (and lowest) switch case value 1011 * int targets[size] branch targets, relative to switch opcode 1012 * 1013 * Total size is (4+size*2) 16-bit code units. 1014 */ 1015 if (*switchData++ != kPackedSwitchSignature) { 1016 /* should have been caught by verifier */ 1017 dvmThrowInternalError("bad packed switch magic"); 1018 return kInstrLen; 1019 } 1020 1021 size = *switchData++; 1022 assert(size > 0); 1023 1024 firstKey = *switchData++; 1025 firstKey |= (*switchData++) << 16; 1026 1027 if (testVal < firstKey || testVal >= firstKey + size) { 1028 LOGVV("Value %d not found in switch (%d-%d)", 1029 testVal, firstKey, firstKey+size-1); 1030 return kInstrLen; 1031 } 1032 1033 /* The entries are guaranteed to be aligned on a 32-bit boundary; 1034 * we can treat them as a native int array. 1035 */ 1036 entries = (const s4*) switchData; 1037 assert(((u4)entries & 0x3) == 0); 1038 1039 assert(testVal - firstKey >= 0 && testVal - firstKey < size); 1040 LOGVV("Value %d found in slot %d (goto 0x%02x)", 1041 testVal, testVal - firstKey, 1042 s4FromSwitchData(&entries[testVal - firstKey])); 1043 return s4FromSwitchData(&entries[testVal - firstKey]); 1044 } 1045 1046 /* 1047 * Find the matching case. Returns the offset to the handler instructions. 1048 * 1049 * Returns 3 if we don't find a match (it's the size of the sparse-switch 1050 * instruction). 1051 */ 1052 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal) 1053 { 1054 const int kInstrLen = 3; 1055 u2 size; 1056 const s4* keys; 1057 const s4* entries; 1058 1059 /* 1060 * Sparse switch data format: 1061 * ushort ident = 0x0200 magic value 1062 * ushort size number of entries in the table; > 0 1063 * int keys[size] keys, sorted low-to-high; 32-bit aligned 1064 * int targets[size] branch targets, relative to switch opcode 1065 * 1066 * Total size is (2+size*4) 16-bit code units. 1067 */ 1068 1069 if (*switchData++ != kSparseSwitchSignature) { 1070 /* should have been caught by verifier */ 1071 dvmThrowInternalError("bad sparse switch magic"); 1072 return kInstrLen; 1073 } 1074 1075 size = *switchData++; 1076 assert(size > 0); 1077 1078 /* The keys are guaranteed to be aligned on a 32-bit boundary; 1079 * we can treat them as a native int array. 1080 */ 1081 keys = (const s4*) switchData; 1082 assert(((u4)keys & 0x3) == 0); 1083 1084 /* The entries are guaranteed to be aligned on a 32-bit boundary; 1085 * we can treat them as a native int array. 1086 */ 1087 entries = keys + size; 1088 assert(((u4)entries & 0x3) == 0); 1089 1090 /* 1091 * Binary-search through the array of keys, which are guaranteed to 1092 * be sorted low-to-high. 1093 */ 1094 int lo = 0; 1095 int hi = size - 1; 1096 while (lo <= hi) { 1097 int mid = (lo + hi) >> 1; 1098 1099 s4 foundVal = s4FromSwitchData(&keys[mid]); 1100 if (testVal < foundVal) { 1101 hi = mid - 1; 1102 } else if (testVal > foundVal) { 1103 lo = mid + 1; 1104 } else { 1105 LOGVV("Value %d found in entry %d (goto 0x%02x)", 1106 testVal, mid, s4FromSwitchData(&entries[mid])); 1107 return s4FromSwitchData(&entries[mid]); 1108 } 1109 } 1110 1111 LOGVV("Value %d not found in switch", testVal); 1112 return kInstrLen; 1113 } 1114 1115 /* 1116 * Copy data for a fill-array-data instruction. On a little-endian machine 1117 * we can just do a memcpy(), on a big-endian system we have work to do. 1118 * 1119 * The trick here is that dexopt has byte-swapped each code unit, which is 1120 * exactly what we want for short/char data. For byte data we need to undo 1121 * the swap, and for 4- or 8-byte values we need to swap pieces within 1122 * each word. 1123 */ 1124 static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width) 1125 { 1126 #if __BYTE_ORDER == __LITTLE_ENDIAN 1127 memcpy(dest, src, size*width); 1128 #else 1129 int i; 1130 1131 switch (width) { 1132 case 1: 1133 /* un-swap pairs of bytes as we go */ 1134 for (i = (size-1) & ~1; i >= 0; i -= 2) { 1135 ((u1*)dest)[i] = ((u1*)src)[i+1]; 1136 ((u1*)dest)[i+1] = ((u1*)src)[i]; 1137 } 1138 /* 1139 * "src" is padded to end on a two-byte boundary, but we don't want to 1140 * assume "dest" is, so we handle odd length specially. 1141 */ 1142 if ((size & 1) != 0) { 1143 ((u1*)dest)[size-1] = ((u1*)src)[size]; 1144 } 1145 break; 1146 case 2: 1147 /* already swapped correctly */ 1148 memcpy(dest, src, size*width); 1149 break; 1150 case 4: 1151 /* swap word halves */ 1152 for (i = 0; i < (int) size; i++) { 1153 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1]; 1154 } 1155 break; 1156 case 8: 1157 /* swap word halves and words */ 1158 for (i = 0; i < (int) (size << 1); i += 2) { 1159 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2]; 1160 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1]; 1161 } 1162 break; 1163 default: 1164 ALOGE("Unexpected width %d in copySwappedArrayData", width); 1165 dvmAbort(); 1166 break; 1167 } 1168 #endif 1169 } 1170 1171 /* 1172 * Fill the array with predefined constant values. 1173 * 1174 * Returns true if job is completed, otherwise false to indicate that 1175 * an exception has been thrown. 1176 */ 1177 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData) 1178 { 1179 u2 width; 1180 u4 size; 1181 1182 if (arrayObj == NULL) { 1183 dvmThrowNullPointerException(NULL); 1184 return false; 1185 } 1186 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz, 1187 CLASS_ISOBJECTARRAY)); 1188 1189 /* 1190 * Array data table format: 1191 * ushort ident = 0x0300 magic value 1192 * ushort width width of each element in the table 1193 * uint size number of elements in the table 1194 * ubyte data[size*width] table of data values (may contain a single-byte 1195 * padding at the end) 1196 * 1197 * Total size is 4+(width * size + 1)/2 16-bit code units. 1198 */ 1199 if (arrayData[0] != kArrayDataSignature) { 1200 dvmThrowInternalError("bad array data magic"); 1201 return false; 1202 } 1203 1204 width = arrayData[1]; 1205 size = arrayData[2] | (((u4)arrayData[3]) << 16); 1206 1207 if (size > arrayObj->length) { 1208 dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size); 1209 return false; 1210 } 1211 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width); 1212 return true; 1213 } 1214 1215 /* 1216 * Find the concrete method that corresponds to "methodIdx". The code in 1217 * "method" is executing invoke-method with "thisClass" as its first argument. 1218 * 1219 * Returns NULL with an exception raised on failure. 1220 */ 1221 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx, 1222 const Method* method, DvmDex* methodClassDex) 1223 { 1224 Method* absMethod; 1225 Method* methodToCall; 1226 int i, vtableIndex; 1227 1228 /* 1229 * Resolve the method. This gives us the abstract method from the 1230 * interface class declaration. 1231 */ 1232 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx); 1233 if (absMethod == NULL) { 1234 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx); 1235 if (absMethod == NULL) { 1236 ALOGV("+ unknown method"); 1237 return NULL; 1238 } 1239 } 1240 1241 /* make sure absMethod->methodIndex means what we think it means */ 1242 assert(dvmIsAbstractMethod(absMethod)); 1243 1244 /* 1245 * Run through the "this" object's iftable. Find the entry for 1246 * absMethod's class, then use absMethod->methodIndex to find 1247 * the method's entry. The value there is the offset into our 1248 * vtable of the actual method to execute. 1249 * 1250 * The verifier does not guarantee that objects stored into 1251 * interface references actually implement the interface, so this 1252 * check cannot be eliminated. 1253 */ 1254 for (i = 0; i < thisClass->iftableCount; i++) { 1255 if (thisClass->iftable[i].clazz == absMethod->clazz) 1256 break; 1257 } 1258 if (i == thisClass->iftableCount) { 1259 /* impossible in verified DEX, need to check for it in unverified */ 1260 dvmThrowIncompatibleClassChangeError("interface not implemented"); 1261 return NULL; 1262 } 1263 1264 assert(absMethod->methodIndex < 1265 thisClass->iftable[i].clazz->virtualMethodCount); 1266 1267 vtableIndex = 1268 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex]; 1269 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount); 1270 methodToCall = thisClass->vtable[vtableIndex]; 1271 1272 #if 0 1273 /* this can happen when there's a stale class file */ 1274 if (dvmIsAbstractMethod(methodToCall)) { 1275 dvmThrowAbstractMethodError("interface method not implemented"); 1276 return NULL; 1277 } 1278 #else 1279 assert(!dvmIsAbstractMethod(methodToCall) || 1280 methodToCall->nativeFunc != NULL); 1281 #endif 1282 1283 LOGVV("+++ interface=%s.%s concrete=%s.%s", 1284 absMethod->clazz->descriptor, absMethod->name, 1285 methodToCall->clazz->descriptor, methodToCall->name); 1286 assert(methodToCall != NULL); 1287 1288 return methodToCall; 1289 } 1290 1291 1292 1293 /* 1294 * Helpers for dvmThrowVerificationError(). 1295 * 1296 * Each returns a newly-allocated string. 1297 */ 1298 #define kThrowShow_accessFromClass 1 1299 static std::string classNameFromIndex(const Method* method, int ref, 1300 VerifyErrorRefType refType, int flags) 1301 { 1302 const DvmDex* pDvmDex = method->clazz->pDvmDex; 1303 if (refType == VERIFY_ERROR_REF_FIELD) { 1304 /* get class ID from field ID */ 1305 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref); 1306 ref = pFieldId->classIdx; 1307 } else if (refType == VERIFY_ERROR_REF_METHOD) { 1308 /* get class ID from method ID */ 1309 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref); 1310 ref = pMethodId->classIdx; 1311 } 1312 1313 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref); 1314 std::string dotClassName(dvmHumanReadableDescriptor(className)); 1315 if (flags == 0) { 1316 return dotClassName; 1317 } 1318 1319 std::string result; 1320 if ((flags & kThrowShow_accessFromClass) != 0) { 1321 result += "tried to access class " + dotClassName; 1322 result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor); 1323 } else { 1324 assert(false); // should've been caught above 1325 } 1326 1327 return result; 1328 } 1329 static std::string fieldNameFromIndex(const Method* method, int ref, 1330 VerifyErrorRefType refType, int flags) 1331 { 1332 if (refType != VERIFY_ERROR_REF_FIELD) { 1333 ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_FIELD, refType); 1334 return NULL; /* no message */ 1335 } 1336 1337 const DvmDex* pDvmDex = method->clazz->pDvmDex; 1338 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref); 1339 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx); 1340 const char* fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx); 1341 1342 std::string dotName(dvmHumanReadableDescriptor(className)); 1343 1344 if ((flags & kThrowShow_accessFromClass) != 0) { 1345 std::string result; 1346 result += "tried to access field "; 1347 result += dotName + "." + fieldName; 1348 result += " from class "; 1349 result += dvmHumanReadableDescriptor(method->clazz->descriptor); 1350 return result; 1351 } 1352 return dotName + "." + fieldName; 1353 } 1354 static std::string methodNameFromIndex(const Method* method, int ref, 1355 VerifyErrorRefType refType, int flags) 1356 { 1357 if (refType != VERIFY_ERROR_REF_METHOD) { 1358 ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_METHOD,refType); 1359 return NULL; /* no message */ 1360 } 1361 1362 const DvmDex* pDvmDex = method->clazz->pDvmDex; 1363 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref); 1364 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx); 1365 const char* methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx); 1366 1367 std::string dotName(dvmHumanReadableDescriptor(className)); 1368 1369 if ((flags & kThrowShow_accessFromClass) != 0) { 1370 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 1371 std::string result; 1372 result += "tried to access method "; 1373 result += dotName + "." + methodName + ":" + desc; 1374 result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor); 1375 free(desc); 1376 return result; 1377 } 1378 return dotName + "." + methodName; 1379 } 1380 1381 /* 1382 * Throw an exception for a problem identified by the verifier. 1383 * 1384 * This is used by the invoke-verification-error instruction. It always 1385 * throws an exception. 1386 * 1387 * "kind" indicates the kind of failure encountered by the verifier. It 1388 * has two parts, an error code and an indication of the reference type. 1389 */ 1390 void dvmThrowVerificationError(const Method* method, int kind, int ref) 1391 { 1392 int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift); 1393 int errorRefPart = kind >> kVerifyErrorRefTypeShift; 1394 VerifyError errorKind = static_cast<VerifyError>(errorPart); 1395 VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart); 1396 ClassObject* exceptionClass = gDvm.exVerifyError; 1397 std::string msg; 1398 1399 switch ((VerifyError) errorKind) { 1400 case VERIFY_ERROR_NO_CLASS: 1401 exceptionClass = gDvm.exNoClassDefFoundError; 1402 msg = classNameFromIndex(method, ref, refType, 0); 1403 break; 1404 case VERIFY_ERROR_NO_FIELD: 1405 exceptionClass = gDvm.exNoSuchFieldError; 1406 msg = fieldNameFromIndex(method, ref, refType, 0); 1407 break; 1408 case VERIFY_ERROR_NO_METHOD: 1409 exceptionClass = gDvm.exNoSuchMethodError; 1410 msg = methodNameFromIndex(method, ref, refType, 0); 1411 break; 1412 case VERIFY_ERROR_ACCESS_CLASS: 1413 exceptionClass = gDvm.exIllegalAccessError; 1414 msg = classNameFromIndex(method, ref, refType, 1415 kThrowShow_accessFromClass); 1416 break; 1417 case VERIFY_ERROR_ACCESS_FIELD: 1418 exceptionClass = gDvm.exIllegalAccessError; 1419 msg = fieldNameFromIndex(method, ref, refType, 1420 kThrowShow_accessFromClass); 1421 break; 1422 case VERIFY_ERROR_ACCESS_METHOD: 1423 exceptionClass = gDvm.exIllegalAccessError; 1424 msg = methodNameFromIndex(method, ref, refType, 1425 kThrowShow_accessFromClass); 1426 break; 1427 case VERIFY_ERROR_CLASS_CHANGE: 1428 exceptionClass = gDvm.exIncompatibleClassChangeError; 1429 msg = classNameFromIndex(method, ref, refType, 0); 1430 break; 1431 case VERIFY_ERROR_INSTANTIATION: 1432 exceptionClass = gDvm.exInstantiationError; 1433 msg = classNameFromIndex(method, ref, refType, 0); 1434 break; 1435 1436 case VERIFY_ERROR_GENERIC: 1437 /* generic VerifyError; use default exception, no message */ 1438 break; 1439 case VERIFY_ERROR_NONE: 1440 /* should never happen; use default exception */ 1441 assert(false); 1442 msg = "weird - no error specified"; 1443 break; 1444 1445 /* no default clause -- want warning if enum updated */ 1446 } 1447 1448 dvmThrowException(exceptionClass, msg.c_str()); 1449 } 1450 1451 /* 1452 * Update interpBreak for a single thread. 1453 */ 1454 void updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable) 1455 { 1456 InterpBreak oldValue, newValue; 1457 do { 1458 oldValue = newValue = thread->interpBreak; 1459 newValue.ctl.breakFlags = kInterpNoBreak; // Assume full reset 1460 if (enable) 1461 newValue.ctl.subMode |= subMode; 1462 else 1463 newValue.ctl.subMode &= ~subMode; 1464 if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK) 1465 newValue.ctl.breakFlags |= kInterpSingleStep; 1466 if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK) 1467 newValue.ctl.breakFlags |= kInterpSafePoint; 1468 #ifndef DVM_NO_ASM_INTERP 1469 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ? 1470 thread->altHandlerTable : thread->mainHandlerTable; 1471 #endif 1472 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all, 1473 &thread->interpBreak.all) != 0); 1474 } 1475 1476 /* 1477 * Update interpBreak for all threads. 1478 */ 1479 void updateAllInterpBreak(ExecutionSubModes subMode, bool enable) 1480 { 1481 Thread* self = dvmThreadSelf(); 1482 Thread* thread; 1483 1484 dvmLockThreadList(self); 1485 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 1486 updateInterpBreak(thread, subMode, enable); 1487 } 1488 dvmUnlockThreadList(); 1489 } 1490 1491 /* 1492 * Update the normal and debugger suspend counts for a thread. 1493 * threadSuspendCount must be acquired before calling this to 1494 * ensure a clean update of suspendCount, dbgSuspendCount and 1495 * sumThreadSuspendCount. 1496 * 1497 * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount. 1498 * Move under WITH_JIT ifdefs. 1499 */ 1500 void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta) 1501 { 1502 thread->suspendCount += delta; 1503 thread->dbgSuspendCount += dbgDelta; 1504 updateInterpBreak(thread, kSubModeSuspendPending, 1505 (thread->suspendCount != 0)); 1506 // Update the global suspend count total 1507 gDvm.sumThreadSuspendCount += delta; 1508 } 1509 1510 1511 void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode) 1512 { 1513 updateInterpBreak(thread, subMode, false); 1514 } 1515 1516 void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode) 1517 { 1518 updateInterpBreak(thread, subMode, true); 1519 } 1520 1521 void dvmEnableAllSubMode(ExecutionSubModes subMode) 1522 { 1523 updateAllInterpBreak(subMode, true); 1524 } 1525 1526 void dvmDisableAllSubMode(ExecutionSubModes subMode) 1527 { 1528 updateAllInterpBreak(subMode, false); 1529 } 1530 1531 /* 1532 * Do a sanity check on interpreter state saved to Thread. 1533 * A failure here doesn't necessarily mean that something is wrong, 1534 * so this code should only be used during development to suggest 1535 * a possible problem. 1536 */ 1537 void dvmCheckInterpStateConsistency() 1538 { 1539 Thread* self = dvmThreadSelf(); 1540 Thread* thread; 1541 uint8_t breakFlags; 1542 uint8_t subMode; 1543 #ifndef DVM_NO_ASM_INTERP 1544 void* handlerTable; 1545 #endif 1546 1547 dvmLockThreadList(self); 1548 breakFlags = self->interpBreak.ctl.breakFlags; 1549 subMode = self->interpBreak.ctl.subMode; 1550 #ifndef DVM_NO_ASM_INTERP 1551 handlerTable = self->interpBreak.ctl.curHandlerTable; 1552 #endif 1553 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 1554 if (subMode != thread->interpBreak.ctl.subMode) { 1555 ALOGD("Warning: subMode mismatch - %#x:%#x, tid[%d]", 1556 subMode,thread->interpBreak.ctl.subMode,thread->threadId); 1557 } 1558 if (breakFlags != thread->interpBreak.ctl.breakFlags) { 1559 ALOGD("Warning: breakFlags mismatch - %#x:%#x, tid[%d]", 1560 breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId); 1561 } 1562 #ifndef DVM_NO_ASM_INTERP 1563 if (handlerTable != thread->interpBreak.ctl.curHandlerTable) { 1564 ALOGD("Warning: curHandlerTable mismatch - %#x:%#x, tid[%d]", 1565 (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable, 1566 thread->threadId); 1567 } 1568 #endif 1569 #if defined(WITH_JIT) 1570 if (thread->pJitProfTable != gDvmJit.pProfTable) { 1571 ALOGD("Warning: pJitProfTable mismatch - %#x:%#x, tid[%d]", 1572 (int)thread->pJitProfTable,(int)gDvmJit.pProfTable, 1573 thread->threadId); 1574 } 1575 if (thread->jitThreshold != gDvmJit.threshold) { 1576 ALOGD("Warning: jitThreshold mismatch - %#x:%#x, tid[%d]", 1577 (int)thread->jitThreshold,(int)gDvmJit.threshold, 1578 thread->threadId); 1579 } 1580 #endif 1581 } 1582 dvmUnlockThreadList(); 1583 } 1584 1585 /* 1586 * Arm a safepoint callback for a thread. If funct is null, 1587 * clear any pending callback. 1588 * TODO: only gc is currently using this feature, and will have 1589 * at most a single outstanding callback request. Until we need 1590 * something more capable and flexible, enforce this limit. 1591 */ 1592 void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct, 1593 void* arg) 1594 { 1595 dvmLockMutex(&thread->callbackMutex); 1596 if ((funct == NULL) || (thread->callback == NULL)) { 1597 thread->callback = funct; 1598 thread->callbackArg = arg; 1599 if (funct != NULL) { 1600 dvmEnableSubMode(thread, kSubModeCallbackPending); 1601 } else { 1602 dvmDisableSubMode(thread, kSubModeCallbackPending); 1603 } 1604 } else { 1605 // Already armed. Different? 1606 if ((funct != thread->callback) || 1607 (arg != thread->callbackArg)) { 1608 // Yes - report failure and die 1609 ALOGE("ArmSafePointCallback failed, thread %d", thread->threadId); 1610 dvmUnlockMutex(&thread->callbackMutex); 1611 dvmAbort(); 1612 } 1613 } 1614 dvmUnlockMutex(&thread->callbackMutex); 1615 } 1616 1617 /* 1618 * One-time initialization at thread creation. Here we initialize 1619 * useful constants. 1620 */ 1621 void dvmInitInterpreterState(Thread* self) 1622 { 1623 #if defined(WITH_JIT) 1624 /* 1625 * Reserve a static entity here to quickly setup runtime contents as 1626 * gcc will issue block copy instructions. 1627 */ 1628 static struct JitToInterpEntries jitToInterpEntries = { 1629 dvmJitToInterpNormal, 1630 dvmJitToInterpNoChain, 1631 dvmJitToInterpPunt, 1632 dvmJitToInterpSingleStep, 1633 dvmJitToInterpTraceSelect, 1634 #if defined(WITH_SELF_VERIFICATION) 1635 dvmJitToInterpBackwardBranch, 1636 #else 1637 NULL, 1638 #endif 1639 }; 1640 #endif 1641 1642 // Begin initialization 1643 self->cardTable = gDvm.biasedCardTableBase; 1644 #if defined(WITH_JIT) 1645 // One-time initializations 1646 self->jitToInterpEntries = jitToInterpEntries; 1647 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN; 1648 self->pProfileCountdown = &gDvmJit.profileCountdown; 1649 // Jit state that can change 1650 dvmJitUpdateThreadStateSingle(self); 1651 #endif 1652 dvmInitializeInterpBreak(self); 1653 } 1654 1655 /* 1656 * For a newly-created thread, we need to start off with interpBreak 1657 * set to any existing global modes. The caller must hold the 1658 * thread list lock. 1659 */ 1660 void dvmInitializeInterpBreak(Thread* thread) 1661 { 1662 if (gDvm.instructionCountEnableCount > 0) { 1663 dvmEnableSubMode(thread, kSubModeInstCounting); 1664 } 1665 if (dvmIsMethodTraceActive()) { 1666 dvmEnableSubMode(thread, kSubModeMethodTrace); 1667 } 1668 if (gDvm.emulatorTraceEnableCount > 0) { 1669 dvmEnableSubMode(thread, kSubModeEmulatorTrace); 1670 } 1671 if (gDvm.debuggerActive) { 1672 dvmEnableSubMode(thread, kSubModeDebuggerActive); 1673 } 1674 #if 0 1675 // Debugging stress mode - force checkBefore 1676 dvmEnableSubMode(thread, kSubModeCheckAlways); 1677 #endif 1678 } 1679 1680 /* 1681 * Inter-instruction handler invoked in between instruction interpretations 1682 * to handle exceptional events such as debugging housekeeping, instruction 1683 * count profiling, JIT trace building, etc. Dalvik PC has been exported 1684 * prior to call, but Thread copy of dPC & fp are not current. 1685 */ 1686 void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self) 1687 { 1688 const Method* method = self->interpSave.method; 1689 assert(pc >= method->insns && pc < 1690 method->insns + dvmGetMethodInsnsSize(method)); 1691 1692 #if 0 1693 /* 1694 * When we hit a specific method, enable verbose instruction logging. 1695 * Sometimes it's helpful to use the debugger attach as a trigger too. 1696 */ 1697 if (*pIsMethodEntry) { 1698 static const char* cd = "Landroid/test/Arithmetic;"; 1699 static const char* mn = "shiftTest2"; 1700 static const char* sg = "()V"; 1701 1702 if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/ 1703 strcmp(method->clazz->descriptor, cd) == 0 && 1704 strcmp(method->name, mn) == 0 && 1705 strcmp(method->shorty, sg) == 0) 1706 { 1707 ALOGW("Reached %s.%s, enabling verbose mode", 1708 method->clazz->descriptor, method->name); 1709 android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE); 1710 dumpRegs(method, fp, true); 1711 } 1712 1713 if (!gDvm.debuggerActive) 1714 *pIsMethodEntry = false; 1715 } 1716 #endif 1717 1718 /* Safe point handling */ 1719 if (self->suspendCount || 1720 (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) { 1721 // Are we are a safe point? 1722 int flags; 1723 flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc)); 1724 if (flags & (VERIFY_GC_INST_MASK & ~kInstrCanThrow)) { 1725 // Yes, at a safe point. Pending callback? 1726 if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) { 1727 SafePointCallback callback; 1728 void* arg; 1729 // Get consistent funct/arg pair 1730 dvmLockMutex(&self->callbackMutex); 1731 callback = self->callback; 1732 arg = self->callbackArg; 1733 dvmUnlockMutex(&self->callbackMutex); 1734 // Update Thread structure 1735 self->interpSave.pc = pc; 1736 self->interpSave.curFrame = fp; 1737 if (callback != NULL) { 1738 // Do the callback 1739 if (!callback(self,arg)) { 1740 // disarm 1741 dvmArmSafePointCallback(self, NULL, NULL); 1742 } 1743 } 1744 } 1745 // Need to suspend? 1746 if (self->suspendCount) { 1747 dvmExportPC(pc, fp); 1748 dvmCheckSuspendPending(self); 1749 } 1750 } 1751 } 1752 1753 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 1754 updateDebugger(method, pc, fp, self); 1755 } 1756 if (gDvm.instructionCountEnableCount != 0) { 1757 /* 1758 * Count up the #of executed instructions. This isn't synchronized 1759 * for thread-safety; if we need that we should make this 1760 * thread-local and merge counts into the global area when threads 1761 * exit (perhaps suspending all other threads GC-style and pulling 1762 * the data out of them). 1763 */ 1764 gDvm.executedInstrCounts[GET_OPCODE(*pc)]++; 1765 } 1766 1767 1768 #if defined(WITH_TRACKREF_CHECKS) 1769 dvmInterpCheckTrackedRefs(self, method, 1770 self->interpSave.debugTrackedRefStart); 1771 #endif 1772 1773 #if defined(WITH_JIT) 1774 // Does the JIT need anything done now? 1775 if (self->interpBreak.ctl.subMode & 1776 (kSubModeJitTraceBuild | kSubModeJitSV)) { 1777 // Are we building a trace? 1778 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 1779 dvmCheckJit(pc, self); 1780 } 1781 1782 #if defined(WITH_SELF_VERIFICATION) 1783 // Are we replaying a trace? 1784 if (self->interpBreak.ctl.subMode & kSubModeJitSV) { 1785 dvmCheckSelfVerification(pc, self); 1786 } 1787 #endif 1788 } 1789 #endif 1790 1791 /* 1792 * CountedStep processing. NOTE: must be the last here to allow 1793 * preceeding special case handler to manipulate single-step count. 1794 */ 1795 if (self->interpBreak.ctl.subMode & kSubModeCountedStep) { 1796 if (self->singleStepCount == 0) { 1797 // We've exhausted our single step count 1798 dvmDisableSubMode(self, kSubModeCountedStep); 1799 #if defined(WITH_JIT) 1800 #if 0 1801 /* 1802 * For debugging. If jitResumeDPC is non-zero, then 1803 * we expect to return to a trace in progress. There 1804 * are valid reasons why we wouldn't (such as an exception 1805 * throw), but here we can keep track. 1806 */ 1807 if (self->jitResumeDPC != NULL) { 1808 if (self->jitResumeDPC == pc) { 1809 if (self->jitResumeNPC != NULL) { 1810 ALOGD("SS return to trace - pc:%#x to 0x:%x", 1811 (int)pc, (int)self->jitResumeNPC); 1812 } else { 1813 ALOGD("SS return to interp - pc:%#x",(int)pc); 1814 } 1815 } else { 1816 ALOGD("SS failed to return. Expected %#x, now at %#x", 1817 (int)self->jitResumeDPC, (int)pc); 1818 } 1819 } 1820 #endif 1821 #if 0 1822 // TODO - fix JIT single-stepping resume mode (b/5551114) 1823 // self->jitResumeNPC needs to be cleared in callPrep 1824 1825 // If we've got a native return and no other reasons to 1826 // remain in singlestep/break mode, do a long jump 1827 if (self->jitResumeNPC != NULL && 1828 self->interpBreak.ctl.breakFlags == 0) { 1829 assert(self->jitResumeDPC == pc); 1830 self->jitResumeDPC = NULL; 1831 dvmJitResumeTranslation(self, pc, fp); 1832 // Doesn't return 1833 dvmAbort(); 1834 } 1835 // In case resume is blocked by non-zero breakFlags, clear 1836 // jitResumeNPC here. 1837 self->jitResumeNPC = NULL; 1838 self->jitResumeDPC = NULL; 1839 self->inJitCodeCache = NULL; 1840 #endif 1841 #endif 1842 } else { 1843 self->singleStepCount--; 1844 #if defined(WITH_JIT) 1845 if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) { 1846 /* 1847 * Direct return to an existing translation following a 1848 * single step is valid only if we step once. If we're 1849 * here, an additional step was added so we need to invalidate 1850 * the return to translation. 1851 */ 1852 self->jitResumeNPC = NULL; 1853 self->inJitCodeCache = NULL; 1854 } 1855 #endif 1856 } 1857 } 1858 } 1859 1860 /* 1861 * Main interpreter loop entry point. 1862 * 1863 * This begins executing code at the start of "method". On exit, "pResult" 1864 * holds the return value of the method (or, if "method" returns NULL, it 1865 * holds an undefined value). 1866 * 1867 * The interpreted stack frame, which holds the method arguments, has 1868 * already been set up. 1869 */ 1870 void dvmInterpret(Thread* self, const Method* method, JValue* pResult) 1871 { 1872 InterpSaveState interpSaveState; 1873 ExecutionSubModes savedSubModes; 1874 1875 #if defined(WITH_JIT) 1876 /* Target-specific save/restore */ 1877 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT]; 1878 /* 1879 * If the previous VM left the code cache through single-stepping the 1880 * inJitCodeCache flag will be set when the VM is re-entered (for example, 1881 * in self-verification mode we single-step NEW_INSTANCE which may re-enter 1882 * the VM through findClassFromLoaderNoInit). Because of that, we cannot 1883 * assert that self->inJitCodeCache is NULL here. 1884 */ 1885 #endif 1886 1887 /* 1888 * Save interpreter state from previous activation, linking 1889 * new to last. 1890 */ 1891 interpSaveState = self->interpSave; 1892 self->interpSave.prev = &interpSaveState; 1893 /* 1894 * Strip out and save any flags that should not be inherited by 1895 * nested interpreter activation. 1896 */ 1897 savedSubModes = (ExecutionSubModes)( 1898 self->interpBreak.ctl.subMode & LOCAL_SUBMODE); 1899 if (savedSubModes != kSubModeNormal) { 1900 dvmDisableSubMode(self, savedSubModes); 1901 } 1902 #if defined(WITH_JIT) 1903 dvmJitCalleeSave(calleeSave); 1904 #endif 1905 1906 1907 #if defined(WITH_TRACKREF_CHECKS) 1908 self->interpSave.debugTrackedRefStart = 1909 dvmReferenceTableEntries(&self->internalLocalRefTable); 1910 #endif 1911 self->debugIsMethodEntry = true; 1912 #if defined(WITH_JIT) 1913 dvmJitCalleeSave(calleeSave); 1914 /* Initialize the state to kJitNot */ 1915 self->jitState = kJitNot; 1916 #endif 1917 1918 /* 1919 * Initialize working state. 1920 * 1921 * No need to initialize "retval". 1922 */ 1923 self->interpSave.method = method; 1924 self->interpSave.curFrame = (u4*) self->interpSave.curFrame; 1925 self->interpSave.pc = method->insns; 1926 1927 assert(!dvmIsNativeMethod(method)); 1928 1929 /* 1930 * Make sure the class is ready to go. Shouldn't be possible to get 1931 * here otherwise. 1932 */ 1933 if (method->clazz->status < CLASS_INITIALIZING || 1934 method->clazz->status == CLASS_ERROR) 1935 { 1936 ALOGE("ERROR: tried to execute code in unprepared class '%s' (%d)", 1937 method->clazz->descriptor, method->clazz->status); 1938 dvmDumpThread(self, false); 1939 dvmAbort(); 1940 } 1941 1942 typedef void (*Interpreter)(Thread*); 1943 Interpreter stdInterp; 1944 if (gDvm.executionMode == kExecutionModeInterpFast) 1945 stdInterp = dvmMterpStd; 1946 #if defined(WITH_JIT) 1947 else if (gDvm.executionMode == kExecutionModeJit || 1948 gDvm.executionMode == kExecutionModeNcgO0 || 1949 gDvm.executionMode == kExecutionModeNcgO1) 1950 stdInterp = dvmMterpStd; 1951 #endif 1952 else 1953 stdInterp = dvmInterpretPortable; 1954 1955 // Call the interpreter 1956 (*stdInterp)(self); 1957 1958 *pResult = self->interpSave.retval; 1959 1960 /* Restore interpreter state from previous activation */ 1961 self->interpSave = interpSaveState; 1962 #if defined(WITH_JIT) 1963 dvmJitCalleeRestore(calleeSave); 1964 #endif 1965 if (savedSubModes != kSubModeNormal) { 1966 dvmEnableSubMode(self, savedSubModes); 1967 } 1968 } 1969