InterpC-allstubs.cpp revision a8b91c52fd8a90b784835dfe1f8898035266c4dd
1/* 2 * This file was generated automatically by gen-mterp.py for 'allstubs'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: c/header.cpp */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* common includes */ 25#include "Dalvik.h" 26#include "interp/InterpDefs.h" 27#include "mterp/Mterp.h" 28#include <math.h> // needed for fmod, fmodf 29#include "mterp/common/FindInterface.h" 30 31/* 32 * Configuration defines. These affect the C implementations, i.e. the 33 * portable interpreter(s) and C stubs. 34 * 35 * Some defines are controlled by the Makefile, e.g.: 36 * WITH_INSTR_CHECKS 37 * WITH_TRACKREF_CHECKS 38 * EASY_GDB 39 * NDEBUG 40 */ 41 42#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */ 43# define CHECK_BRANCH_OFFSETS 44# define CHECK_REGISTER_INDICES 45#endif 46 47/* 48 * Some architectures require 64-bit alignment for access to 64-bit data 49 * types. We can't just use pointers to copy 64-bit values out of our 50 * interpreted register set, because gcc may assume the pointer target is 51 * aligned and generate invalid code. 52 * 53 * There are two common approaches: 54 * (1) Use a union that defines a 32-bit pair and a 64-bit value. 55 * (2) Call memcpy(). 56 * 57 * Depending upon what compiler you're using and what options are specified, 58 * one may be faster than the other. For example, the compiler might 59 * convert a memcpy() of 8 bytes into a series of instructions and omit 60 * the call. The union version could cause some strange side-effects, 61 * e.g. for a while ARM gcc thought it needed separate storage for each 62 * inlined instance, and generated instructions to zero out ~700 bytes of 63 * stack space at the top of the interpreter. 64 * 65 * The default is to use memcpy(). The current gcc for ARM seems to do 66 * better with the union. 67 */ 68#if defined(__ARM_EABI__) 69# define NO_UNALIGN_64__UNION 70#endif 71/* 72 * MIPS ABI requires 64-bit alignment for access to 64-bit data types. 73 * 74 * Use memcpy() to do the transfer 75 */ 76#if defined(__mips__) 77/* # define NO_UNALIGN_64__UNION */ 78#endif 79 80 81//#define LOG_INSTR /* verbose debugging */ 82/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */ 83 84/* 85 * Export another copy of the PC on every instruction; this is largely 86 * redundant with EXPORT_PC and the debugger code. This value can be 87 * compared against what we have stored on the stack with EXPORT_PC to 88 * help ensure that we aren't missing any export calls. 89 */ 90#if WITH_EXTRA_GC_CHECKS > 1 91# define EXPORT_EXTRA_PC() (self->currentPc2 = pc) 92#else 93# define EXPORT_EXTRA_PC() 94#endif 95 96/* 97 * Adjust the program counter. "_offset" is a signed int, in 16-bit units. 98 * 99 * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns". 100 * 101 * We don't advance the program counter until we finish an instruction or 102 * branch, because we do want to have to unroll the PC if there's an 103 * exception. 104 */ 105#ifdef CHECK_BRANCH_OFFSETS 106# define ADJUST_PC(_offset) do { \ 107 int myoff = _offset; /* deref only once */ \ 108 if (pc + myoff < curMethod->insns || \ 109 pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \ 110 { \ 111 char* desc; \ 112 desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \ 113 LOGE("Invalid branch %d at 0x%04x in %s.%s %s", \ 114 myoff, (int) (pc - curMethod->insns), \ 115 curMethod->clazz->descriptor, curMethod->name, desc); \ 116 free(desc); \ 117 dvmAbort(); \ 118 } \ 119 pc += myoff; \ 120 EXPORT_EXTRA_PC(); \ 121 } while (false) 122#else 123# define ADJUST_PC(_offset) do { \ 124 pc += _offset; \ 125 EXPORT_EXTRA_PC(); \ 126 } while (false) 127#endif 128 129/* 130 * If enabled, log instructions as we execute them. 131 */ 132#ifdef LOG_INSTR 133# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__) 134# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__) 135# define ILOG(_level, ...) do { \ 136 char debugStrBuf[128]; \ 137 snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \ 138 if (curMethod != NULL) \ 139 LOG(_level, LOG_TAG"i", "%-2d|%04x%s", \ 140 self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \ 141 else \ 142 LOG(_level, LOG_TAG"i", "%-2d|####%s", \ 143 self->threadId, debugStrBuf); \ 144 } while(false) 145void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly); 146# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly) 147static const char kSpacing[] = " "; 148#else 149# define ILOGD(...) ((void)0) 150# define ILOGV(...) ((void)0) 151# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0) 152#endif 153 154/* get a long from an array of u4 */ 155static inline s8 getLongFromArray(const u4* ptr, int idx) 156{ 157#if defined(NO_UNALIGN_64__UNION) 158 union { s8 ll; u4 parts[2]; } conv; 159 160 ptr += idx; 161 conv.parts[0] = ptr[0]; 162 conv.parts[1] = ptr[1]; 163 return conv.ll; 164#else 165 s8 val; 166 memcpy(&val, &ptr[idx], 8); 167 return val; 168#endif 169} 170 171/* store a long into an array of u4 */ 172static inline void putLongToArray(u4* ptr, int idx, s8 val) 173{ 174#if defined(NO_UNALIGN_64__UNION) 175 union { s8 ll; u4 parts[2]; } conv; 176 177 ptr += idx; 178 conv.ll = val; 179 ptr[0] = conv.parts[0]; 180 ptr[1] = conv.parts[1]; 181#else 182 memcpy(&ptr[idx], &val, 8); 183#endif 184} 185 186/* get a double from an array of u4 */ 187static inline double getDoubleFromArray(const u4* ptr, int idx) 188{ 189#if defined(NO_UNALIGN_64__UNION) 190 union { double d; u4 parts[2]; } conv; 191 192 ptr += idx; 193 conv.parts[0] = ptr[0]; 194 conv.parts[1] = ptr[1]; 195 return conv.d; 196#else 197 double dval; 198 memcpy(&dval, &ptr[idx], 8); 199 return dval; 200#endif 201} 202 203/* store a double into an array of u4 */ 204static inline void putDoubleToArray(u4* ptr, int idx, double dval) 205{ 206#if defined(NO_UNALIGN_64__UNION) 207 union { double d; u4 parts[2]; } conv; 208 209 ptr += idx; 210 conv.d = dval; 211 ptr[0] = conv.parts[0]; 212 ptr[1] = conv.parts[1]; 213#else 214 memcpy(&ptr[idx], &dval, 8); 215#endif 216} 217 218/* 219 * If enabled, validate the register number on every access. Otherwise, 220 * just do an array access. 221 * 222 * Assumes the existence of "u4* fp". 223 * 224 * "_idx" may be referenced more than once. 225 */ 226#ifdef CHECK_REGISTER_INDICES 227# define GET_REGISTER(_idx) \ 228 ( (_idx) < curMethod->registersSize ? \ 229 (fp[(_idx)]) : (assert(!"bad reg"),1969) ) 230# define SET_REGISTER(_idx, _val) \ 231 ( (_idx) < curMethod->registersSize ? \ 232 (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) ) 233# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx)) 234# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 235# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx)) 236# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 237# define GET_REGISTER_WIDE(_idx) \ 238 ( (_idx) < curMethod->registersSize-1 ? \ 239 getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) ) 240# define SET_REGISTER_WIDE(_idx, _val) \ 241 ( (_idx) < curMethod->registersSize-1 ? \ 242 (void)putLongToArray(fp, (_idx), (_val)) : assert(!"bad reg") ) 243# define GET_REGISTER_FLOAT(_idx) \ 244 ( (_idx) < curMethod->registersSize ? \ 245 (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) ) 246# define SET_REGISTER_FLOAT(_idx, _val) \ 247 ( (_idx) < curMethod->registersSize ? \ 248 (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) ) 249# define GET_REGISTER_DOUBLE(_idx) \ 250 ( (_idx) < curMethod->registersSize-1 ? \ 251 getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) ) 252# define SET_REGISTER_DOUBLE(_idx, _val) \ 253 ( (_idx) < curMethod->registersSize-1 ? \ 254 (void)putDoubleToArray(fp, (_idx), (_val)) : assert(!"bad reg") ) 255#else 256# define GET_REGISTER(_idx) (fp[(_idx)]) 257# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val)) 258# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)]) 259# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val)) 260# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx)) 261# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 262# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx)) 263# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val)) 264# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)])) 265# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val)) 266# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx)) 267# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val)) 268#endif 269 270/* 271 * Get 16 bits from the specified offset of the program counter. We always 272 * want to load 16 bits at a time from the instruction stream -- it's more 273 * efficient than 8 and won't have the alignment problems that 32 might. 274 * 275 * Assumes existence of "const u2* pc". 276 */ 277#define FETCH(_offset) (pc[(_offset)]) 278 279/* 280 * Extract instruction byte from 16-bit fetch (_inst is a u2). 281 */ 282#define INST_INST(_inst) ((_inst) & 0xff) 283 284/* 285 * Replace the opcode (used when handling breakpoints). _opcode is a u1. 286 */ 287#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode) 288 289/* 290 * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2). 291 */ 292#define INST_A(_inst) (((_inst) >> 8) & 0x0f) 293#define INST_B(_inst) ((_inst) >> 12) 294 295/* 296 * Get the 8-bit "vAA" 8-bit register index from the instruction word. 297 * (_inst is u2) 298 */ 299#define INST_AA(_inst) ((_inst) >> 8) 300 301/* 302 * The current PC must be available to Throwable constructors, e.g. 303 * those created by the various exception throw routines, so that the 304 * exception stack trace can be generated correctly. If we don't do this, 305 * the offset within the current method won't be shown correctly. See the 306 * notes in Exception.c. 307 * 308 * This is also used to determine the address for precise GC. 309 * 310 * Assumes existence of "u4* fp" and "const u2* pc". 311 */ 312#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc) 313 314/* 315 * Check to see if "obj" is NULL. If so, throw an exception. Assumes the 316 * pc has already been exported to the stack. 317 * 318 * Perform additional checks on debug builds. 319 * 320 * Use this to check for NULL when the instruction handler calls into 321 * something that could throw an exception (so we have already called 322 * EXPORT_PC at the top). 323 */ 324static inline bool checkForNull(Object* obj) 325{ 326 if (obj == NULL) { 327 dvmThrowNullPointerException(NULL); 328 return false; 329 } 330#ifdef WITH_EXTRA_OBJECT_VALIDATION 331 if (!dvmIsHeapAddressObject(obj)) { 332 LOGE("Invalid object %p", obj); 333 dvmAbort(); 334 } 335#endif 336#ifndef NDEBUG 337 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) { 338 /* probable heap corruption */ 339 LOGE("Invalid object class %p (in %p)", obj->clazz, obj); 340 dvmAbort(); 341 } 342#endif 343 return true; 344} 345 346/* 347 * Check to see if "obj" is NULL. If so, export the PC into the stack 348 * frame and throw an exception. 349 * 350 * Perform additional checks on debug builds. 351 * 352 * Use this to check for NULL when the instruction handler doesn't do 353 * anything else that can throw an exception. 354 */ 355static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc) 356{ 357 if (obj == NULL) { 358 EXPORT_PC(); 359 dvmThrowNullPointerException(NULL); 360 return false; 361 } 362#ifdef WITH_EXTRA_OBJECT_VALIDATION 363 if (!dvmIsHeapAddress(obj)) { 364 LOGE("Invalid object %p", obj); 365 dvmAbort(); 366 } 367#endif 368#ifndef NDEBUG 369 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) { 370 /* probable heap corruption */ 371 LOGE("Invalid object class %p (in %p)", obj->clazz, obj); 372 dvmAbort(); 373 } 374#endif 375 return true; 376} 377 378/* File: cstubs/stubdefs.cpp */ 379/* 380 * In the C mterp stubs, "goto" is a function call followed immediately 381 * by a return. 382 */ 383 384#define GOTO_TARGET_DECL(_target, ...) \ 385 extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__); 386 387/* (void)xxx to quiet unused variable compiler warnings. */ 388#define GOTO_TARGET(_target, ...) \ 389 void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) { \ 390 u2 ref, vsrc1, vsrc2, vdst; \ 391 u2 inst = FETCH(0); \ 392 const Method* methodToCall; \ 393 StackSaveArea* debugSaveArea; \ 394 (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; \ 395 (void)methodToCall; (void)debugSaveArea; 396 397#define GOTO_TARGET_END } 398 399/* 400 * Redefine what used to be local variable accesses into Thread struct 401 * references. (These are undefined down in "footer.cpp".) 402 */ 403#define retval self->interpSave.retval 404#define pc self->interpSave.pc 405#define fp self->interpSave.curFrame 406#define curMethod self->interpSave.method 407#define methodClassDex self->interpSave.methodClassDex 408#define debugTrackedRefStart self->interpSave.debugTrackedRefStart 409 410/* ugh */ 411#define STUB_HACK(x) x 412#if defined(WITH_JIT) 413#define JIT_STUB_HACK(x) x 414#else 415#define JIT_STUB_HACK(x) 416#endif 417 418/* 419 * InterpSave's pc and fp must be valid when breaking out to a 420 * "Reportxxx" routine. Because the portable interpreter uses local 421 * variables for these, we must flush prior. Stubs, however, use 422 * the interpSave vars directly, so this is a nop for stubs. 423 */ 424#define PC_FP_TO_SELF() 425#define PC_TO_SELF() 426 427/* 428 * Opcode handler framing macros. Here, each opcode is a separate function 429 * that takes a "self" argument and returns void. We can't declare 430 * these "static" because they may be called from an assembly stub. 431 * (void)xxx to quiet unused variable compiler warnings. 432 */ 433#define HANDLE_OPCODE(_op) \ 434 extern "C" void dvmMterp_##_op(Thread* self); \ 435 void dvmMterp_##_op(Thread* self) { \ 436 u4 ref; \ 437 u2 vsrc1, vsrc2, vdst; \ 438 u2 inst = FETCH(0); \ 439 (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; 440 441#define OP_END } 442 443/* 444 * Like the "portable" FINISH, but don't reload "inst", and return to caller 445 * when done. Further, debugger/profiler checks are handled 446 * before handler execution in mterp, so we don't do them here either. 447 */ 448#if defined(WITH_JIT) 449#define FINISH(_offset) { \ 450 ADJUST_PC(_offset); \ 451 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { \ 452 dvmCheckJit(pc, self); \ 453 } \ 454 return; \ 455 } 456#else 457#define FINISH(_offset) { \ 458 ADJUST_PC(_offset); \ 459 return; \ 460 } 461#endif 462 463#define FINISH_BKPT(_opcode) /* FIXME? */ 464#define DISPATCH_EXTENDED(_opcode) /* FIXME? */ 465 466/* 467 * The "goto label" statements turn into function calls followed by 468 * return statements. Some of the functions take arguments, which in the 469 * portable interpreter are handled by assigning values to globals. 470 */ 471 472#define GOTO_exceptionThrown() \ 473 do { \ 474 dvmMterp_exceptionThrown(self); \ 475 return; \ 476 } while(false) 477 478#define GOTO_returnFromMethod() \ 479 do { \ 480 dvmMterp_returnFromMethod(self); \ 481 return; \ 482 } while(false) 483 484#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \ 485 do { \ 486 dvmMterp_##_target(self, _methodCallRange, _jumboFormat); \ 487 return; \ 488 } while(false) 489 490#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \ 491 do { \ 492 dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall, \ 493 _vsrc1, _vdst); \ 494 return; \ 495 } while(false) 496 497/* 498 * As a special case, "goto bail" turns into a longjmp. 499 */ 500#define GOTO_bail() \ 501 dvmMterpStdBail(self) 502 503/* 504 * Periodically check for thread suspension. 505 * 506 * While we're at it, see if a debugger has attached or the profiler has 507 * started. 508 */ 509#define PERIODIC_CHECKS(_pcadj) { \ 510 if (dvmCheckSuspendQuick(self)) { \ 511 EXPORT_PC(); /* need for precise GC */ \ 512 dvmCheckSuspendPending(self); \ 513 } \ 514 } 515 516/* File: c/opcommon.cpp */ 517/* forward declarations of goto targets */ 518GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat); 519GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat); 520GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat); 521GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat); 522GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat); 523GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat); 524GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat); 525GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat); 526GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall, 527 u2 count, u2 regs); 528GOTO_TARGET_DECL(returnFromMethod); 529GOTO_TARGET_DECL(exceptionThrown); 530 531/* 532 * =========================================================================== 533 * 534 * What follows are opcode definitions shared between multiple opcodes with 535 * minor substitutions handled by the C pre-processor. These should probably 536 * use the mterp substitution mechanism instead, with the code here moved 537 * into common fragment files (like the asm "binop.S"), although it's hard 538 * to give up the C preprocessor in favor of the much simpler text subst. 539 * 540 * =========================================================================== 541 */ 542 543#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \ 544 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 545 vdst = INST_A(inst); \ 546 vsrc1 = INST_B(inst); \ 547 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 548 SET_REGISTER##_totype(vdst, \ 549 GET_REGISTER##_fromtype(vsrc1)); \ 550 FINISH(1); 551 552#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \ 553 _tovtype, _tortype) \ 554 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 555 { \ 556 /* spec defines specific handling for +/- inf and NaN values */ \ 557 _fromvtype val; \ 558 _tovtype intMin, intMax, result; \ 559 vdst = INST_A(inst); \ 560 vsrc1 = INST_B(inst); \ 561 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 562 val = GET_REGISTER##_fromrtype(vsrc1); \ 563 intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \ 564 intMax = ~intMin; \ 565 result = (_tovtype) val; \ 566 if (val >= intMax) /* +inf */ \ 567 result = intMax; \ 568 else if (val <= intMin) /* -inf */ \ 569 result = intMin; \ 570 else if (val != val) /* NaN */ \ 571 result = 0; \ 572 else \ 573 result = (_tovtype) val; \ 574 SET_REGISTER##_tortype(vdst, result); \ 575 } \ 576 FINISH(1); 577 578#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \ 579 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 580 vdst = INST_A(inst); \ 581 vsrc1 = INST_B(inst); \ 582 ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \ 583 SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \ 584 FINISH(1); 585 586/* NOTE: the comparison result is always a signed 4-byte integer */ 587#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \ 588 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 589 { \ 590 int result; \ 591 u2 regs; \ 592 _varType val1, val2; \ 593 vdst = INST_AA(inst); \ 594 regs = FETCH(1); \ 595 vsrc1 = regs & 0xff; \ 596 vsrc2 = regs >> 8; \ 597 ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 598 val1 = GET_REGISTER##_type(vsrc1); \ 599 val2 = GET_REGISTER##_type(vsrc2); \ 600 if (val1 == val2) \ 601 result = 0; \ 602 else if (val1 < val2) \ 603 result = -1; \ 604 else if (val1 > val2) \ 605 result = 1; \ 606 else \ 607 result = (_nanVal); \ 608 ILOGV("+ result=%d", result); \ 609 SET_REGISTER(vdst, result); \ 610 } \ 611 FINISH(2); 612 613#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \ 614 HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \ 615 vsrc1 = INST_A(inst); \ 616 vsrc2 = INST_B(inst); \ 617 if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \ 618 int branchOffset = (s2)FETCH(1); /* sign-extended */ \ 619 ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \ 620 branchOffset); \ 621 ILOGV("> branch taken"); \ 622 if (branchOffset < 0) \ 623 PERIODIC_CHECKS(branchOffset); \ 624 FINISH(branchOffset); \ 625 } else { \ 626 ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \ 627 FINISH(2); \ 628 } 629 630#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \ 631 HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \ 632 vsrc1 = INST_AA(inst); \ 633 if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \ 634 int branchOffset = (s2)FETCH(1); /* sign-extended */ \ 635 ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \ 636 ILOGV("> branch taken"); \ 637 if (branchOffset < 0) \ 638 PERIODIC_CHECKS(branchOffset); \ 639 FINISH(branchOffset); \ 640 } else { \ 641 ILOGV("|if-%s v%d,-", (_opname), vsrc1); \ 642 FINISH(2); \ 643 } 644 645#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \ 646 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 647 vdst = INST_A(inst); \ 648 vsrc1 = INST_B(inst); \ 649 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 650 SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \ 651 FINISH(1); 652 653#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \ 654 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 655 { \ 656 u2 srcRegs; \ 657 vdst = INST_AA(inst); \ 658 srcRegs = FETCH(1); \ 659 vsrc1 = srcRegs & 0xff; \ 660 vsrc2 = srcRegs >> 8; \ 661 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \ 662 if (_chkdiv != 0) { \ 663 s4 firstVal, secondVal, result; \ 664 firstVal = GET_REGISTER(vsrc1); \ 665 secondVal = GET_REGISTER(vsrc2); \ 666 if (secondVal == 0) { \ 667 EXPORT_PC(); \ 668 dvmThrowArithmeticException("divide by zero"); \ 669 GOTO_exceptionThrown(); \ 670 } \ 671 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \ 672 if (_chkdiv == 1) \ 673 result = firstVal; /* division */ \ 674 else \ 675 result = 0; /* remainder */ \ 676 } else { \ 677 result = firstVal _op secondVal; \ 678 } \ 679 SET_REGISTER(vdst, result); \ 680 } else { \ 681 /* non-div/rem case */ \ 682 SET_REGISTER(vdst, \ 683 (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \ 684 } \ 685 } \ 686 FINISH(2); 687 688#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \ 689 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 690 { \ 691 u2 srcRegs; \ 692 vdst = INST_AA(inst); \ 693 srcRegs = FETCH(1); \ 694 vsrc1 = srcRegs & 0xff; \ 695 vsrc2 = srcRegs >> 8; \ 696 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \ 697 SET_REGISTER(vdst, \ 698 _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \ 699 } \ 700 FINISH(2); 701 702#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \ 703 HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \ 704 vdst = INST_A(inst); \ 705 vsrc1 = INST_B(inst); \ 706 vsrc2 = FETCH(1); \ 707 ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \ 708 (_opname), vdst, vsrc1, vsrc2); \ 709 if (_chkdiv != 0) { \ 710 s4 firstVal, result; \ 711 firstVal = GET_REGISTER(vsrc1); \ 712 if ((s2) vsrc2 == 0) { \ 713 EXPORT_PC(); \ 714 dvmThrowArithmeticException("divide by zero"); \ 715 GOTO_exceptionThrown(); \ 716 } \ 717 if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \ 718 /* won't generate /lit16 instr for this; check anyway */ \ 719 if (_chkdiv == 1) \ 720 result = firstVal; /* division */ \ 721 else \ 722 result = 0; /* remainder */ \ 723 } else { \ 724 result = firstVal _op (s2) vsrc2; \ 725 } \ 726 SET_REGISTER(vdst, result); \ 727 } else { \ 728 /* non-div/rem case */ \ 729 SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \ 730 } \ 731 FINISH(2); 732 733#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \ 734 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \ 735 { \ 736 u2 litInfo; \ 737 vdst = INST_AA(inst); \ 738 litInfo = FETCH(1); \ 739 vsrc1 = litInfo & 0xff; \ 740 vsrc2 = litInfo >> 8; /* constant */ \ 741 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \ 742 (_opname), vdst, vsrc1, vsrc2); \ 743 if (_chkdiv != 0) { \ 744 s4 firstVal, result; \ 745 firstVal = GET_REGISTER(vsrc1); \ 746 if ((s1) vsrc2 == 0) { \ 747 EXPORT_PC(); \ 748 dvmThrowArithmeticException("divide by zero"); \ 749 GOTO_exceptionThrown(); \ 750 } \ 751 if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \ 752 if (_chkdiv == 1) \ 753 result = firstVal; /* division */ \ 754 else \ 755 result = 0; /* remainder */ \ 756 } else { \ 757 result = firstVal _op ((s1) vsrc2); \ 758 } \ 759 SET_REGISTER(vdst, result); \ 760 } else { \ 761 SET_REGISTER(vdst, \ 762 (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \ 763 } \ 764 } \ 765 FINISH(2); 766 767#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \ 768 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \ 769 { \ 770 u2 litInfo; \ 771 vdst = INST_AA(inst); \ 772 litInfo = FETCH(1); \ 773 vsrc1 = litInfo & 0xff; \ 774 vsrc2 = litInfo >> 8; /* constant */ \ 775 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \ 776 (_opname), vdst, vsrc1, vsrc2); \ 777 SET_REGISTER(vdst, \ 778 _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \ 779 } \ 780 FINISH(2); 781 782#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \ 783 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 784 vdst = INST_A(inst); \ 785 vsrc1 = INST_B(inst); \ 786 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 787 if (_chkdiv != 0) { \ 788 s4 firstVal, secondVal, result; \ 789 firstVal = GET_REGISTER(vdst); \ 790 secondVal = GET_REGISTER(vsrc1); \ 791 if (secondVal == 0) { \ 792 EXPORT_PC(); \ 793 dvmThrowArithmeticException("divide by zero"); \ 794 GOTO_exceptionThrown(); \ 795 } \ 796 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \ 797 if (_chkdiv == 1) \ 798 result = firstVal; /* division */ \ 799 else \ 800 result = 0; /* remainder */ \ 801 } else { \ 802 result = firstVal _op secondVal; \ 803 } \ 804 SET_REGISTER(vdst, result); \ 805 } else { \ 806 SET_REGISTER(vdst, \ 807 (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \ 808 } \ 809 FINISH(1); 810 811#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \ 812 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 813 vdst = INST_A(inst); \ 814 vsrc1 = INST_B(inst); \ 815 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 816 SET_REGISTER(vdst, \ 817 _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \ 818 FINISH(1); 819 820#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \ 821 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 822 { \ 823 u2 srcRegs; \ 824 vdst = INST_AA(inst); \ 825 srcRegs = FETCH(1); \ 826 vsrc1 = srcRegs & 0xff; \ 827 vsrc2 = srcRegs >> 8; \ 828 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 829 if (_chkdiv != 0) { \ 830 s8 firstVal, secondVal, result; \ 831 firstVal = GET_REGISTER_WIDE(vsrc1); \ 832 secondVal = GET_REGISTER_WIDE(vsrc2); \ 833 if (secondVal == 0LL) { \ 834 EXPORT_PC(); \ 835 dvmThrowArithmeticException("divide by zero"); \ 836 GOTO_exceptionThrown(); \ 837 } \ 838 if ((u8)firstVal == 0x8000000000000000ULL && \ 839 secondVal == -1LL) \ 840 { \ 841 if (_chkdiv == 1) \ 842 result = firstVal; /* division */ \ 843 else \ 844 result = 0; /* remainder */ \ 845 } else { \ 846 result = firstVal _op secondVal; \ 847 } \ 848 SET_REGISTER_WIDE(vdst, result); \ 849 } else { \ 850 SET_REGISTER_WIDE(vdst, \ 851 (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \ 852 } \ 853 } \ 854 FINISH(2); 855 856#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \ 857 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 858 { \ 859 u2 srcRegs; \ 860 vdst = INST_AA(inst); \ 861 srcRegs = FETCH(1); \ 862 vsrc1 = srcRegs & 0xff; \ 863 vsrc2 = srcRegs >> 8; \ 864 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 865 SET_REGISTER_WIDE(vdst, \ 866 _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \ 867 } \ 868 FINISH(2); 869 870#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \ 871 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 872 vdst = INST_A(inst); \ 873 vsrc1 = INST_B(inst); \ 874 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 875 if (_chkdiv != 0) { \ 876 s8 firstVal, secondVal, result; \ 877 firstVal = GET_REGISTER_WIDE(vdst); \ 878 secondVal = GET_REGISTER_WIDE(vsrc1); \ 879 if (secondVal == 0LL) { \ 880 EXPORT_PC(); \ 881 dvmThrowArithmeticException("divide by zero"); \ 882 GOTO_exceptionThrown(); \ 883 } \ 884 if ((u8)firstVal == 0x8000000000000000ULL && \ 885 secondVal == -1LL) \ 886 { \ 887 if (_chkdiv == 1) \ 888 result = firstVal; /* division */ \ 889 else \ 890 result = 0; /* remainder */ \ 891 } else { \ 892 result = firstVal _op secondVal; \ 893 } \ 894 SET_REGISTER_WIDE(vdst, result); \ 895 } else { \ 896 SET_REGISTER_WIDE(vdst, \ 897 (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\ 898 } \ 899 FINISH(1); 900 901#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \ 902 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 903 vdst = INST_A(inst); \ 904 vsrc1 = INST_B(inst); \ 905 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 906 SET_REGISTER_WIDE(vdst, \ 907 _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \ 908 FINISH(1); 909 910#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \ 911 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 912 { \ 913 u2 srcRegs; \ 914 vdst = INST_AA(inst); \ 915 srcRegs = FETCH(1); \ 916 vsrc1 = srcRegs & 0xff; \ 917 vsrc2 = srcRegs >> 8; \ 918 ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 919 SET_REGISTER_FLOAT(vdst, \ 920 GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \ 921 } \ 922 FINISH(2); 923 924#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \ 925 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 926 { \ 927 u2 srcRegs; \ 928 vdst = INST_AA(inst); \ 929 srcRegs = FETCH(1); \ 930 vsrc1 = srcRegs & 0xff; \ 931 vsrc2 = srcRegs >> 8; \ 932 ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 933 SET_REGISTER_DOUBLE(vdst, \ 934 GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \ 935 } \ 936 FINISH(2); 937 938#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \ 939 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 940 vdst = INST_A(inst); \ 941 vsrc1 = INST_B(inst); \ 942 ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 943 SET_REGISTER_FLOAT(vdst, \ 944 GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \ 945 FINISH(1); 946 947#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \ 948 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 949 vdst = INST_A(inst); \ 950 vsrc1 = INST_B(inst); \ 951 ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 952 SET_REGISTER_DOUBLE(vdst, \ 953 GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \ 954 FINISH(1); 955 956#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \ 957 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 958 { \ 959 ArrayObject* arrayObj; \ 960 u2 arrayInfo; \ 961 EXPORT_PC(); \ 962 vdst = INST_AA(inst); \ 963 arrayInfo = FETCH(1); \ 964 vsrc1 = arrayInfo & 0xff; /* array ptr */ \ 965 vsrc2 = arrayInfo >> 8; /* index */ \ 966 ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 967 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \ 968 if (!checkForNull((Object*) arrayObj)) \ 969 GOTO_exceptionThrown(); \ 970 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \ 971 dvmThrowArrayIndexOutOfBoundsException( \ 972 arrayObj->length, GET_REGISTER(vsrc2)); \ 973 GOTO_exceptionThrown(); \ 974 } \ 975 SET_REGISTER##_regsize(vdst, \ 976 ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \ 977 ILOGV("+ AGET[%d]=%#x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \ 978 } \ 979 FINISH(2); 980 981#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \ 982 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 983 { \ 984 ArrayObject* arrayObj; \ 985 u2 arrayInfo; \ 986 EXPORT_PC(); \ 987 vdst = INST_AA(inst); /* AA: source value */ \ 988 arrayInfo = FETCH(1); \ 989 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \ 990 vsrc2 = arrayInfo >> 8; /* CC: index */ \ 991 ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 992 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \ 993 if (!checkForNull((Object*) arrayObj)) \ 994 GOTO_exceptionThrown(); \ 995 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \ 996 dvmThrowArrayIndexOutOfBoundsException( \ 997 arrayObj->length, GET_REGISTER(vsrc2)); \ 998 GOTO_exceptionThrown(); \ 999 } \ 1000 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\ 1001 ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \ 1002 GET_REGISTER##_regsize(vdst); \ 1003 } \ 1004 FINISH(2); 1005 1006/* 1007 * It's possible to get a bad value out of a field with sub-32-bit stores 1008 * because the -quick versions always operate on 32 bits. Consider: 1009 * short foo = -1 (sets a 32-bit register to 0xffffffff) 1010 * iput-quick foo (writes all 32 bits to the field) 1011 * short bar = 1 (sets a 32-bit register to 0x00000001) 1012 * iput-short (writes the low 16 bits to the field) 1013 * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001) 1014 * This can only happen when optimized and non-optimized code has interleaved 1015 * access to the same field. This is unlikely but possible. 1016 * 1017 * The easiest way to fix this is to always read/write 32 bits at a time. On 1018 * a device with a 16-bit data bus this is sub-optimal. (The alternative 1019 * approach is to have sub-int versions of iget-quick, but now we're wasting 1020 * Dalvik instruction space and making it less likely that handler code will 1021 * already be in the CPU i-cache.) 1022 */ 1023#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \ 1024 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1025 { \ 1026 InstField* ifield; \ 1027 Object* obj; \ 1028 EXPORT_PC(); \ 1029 vdst = INST_A(inst); \ 1030 vsrc1 = INST_B(inst); /* object ptr */ \ 1031 ref = FETCH(1); /* field ref */ \ 1032 ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ 1033 obj = (Object*) GET_REGISTER(vsrc1); \ 1034 if (!checkForNull(obj)) \ 1035 GOTO_exceptionThrown(); \ 1036 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1037 if (ifield == NULL) { \ 1038 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1039 if (ifield == NULL) \ 1040 GOTO_exceptionThrown(); \ 1041 } \ 1042 SET_REGISTER##_regsize(vdst, \ 1043 dvmGetField##_ftype(obj, ifield->byteOffset)); \ 1044 ILOGV("+ IGET '%s'=0x%08llx", ifield->name, \ 1045 (u8) GET_REGISTER##_regsize(vdst)); \ 1046 } \ 1047 FINISH(2); 1048 1049#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1050 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \ 1051 { \ 1052 InstField* ifield; \ 1053 Object* obj; \ 1054 EXPORT_PC(); \ 1055 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1056 vdst = FETCH(3); \ 1057 vsrc1 = FETCH(4); /* object ptr */ \ 1058 ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \ 1059 (_opname), vdst, vsrc1, ref); \ 1060 obj = (Object*) GET_REGISTER(vsrc1); \ 1061 if (!checkForNull(obj)) \ 1062 GOTO_exceptionThrown(); \ 1063 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1064 if (ifield == NULL) { \ 1065 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1066 if (ifield == NULL) \ 1067 GOTO_exceptionThrown(); \ 1068 } \ 1069 SET_REGISTER##_regsize(vdst, \ 1070 dvmGetField##_ftype(obj, ifield->byteOffset)); \ 1071 ILOGV("+ IGET '%s'=0x%08llx", ifield->name, \ 1072 (u8) GET_REGISTER##_regsize(vdst)); \ 1073 } \ 1074 FINISH(5); 1075 1076#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \ 1077 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1078 { \ 1079 Object* obj; \ 1080 vdst = INST_A(inst); \ 1081 vsrc1 = INST_B(inst); /* object ptr */ \ 1082 ref = FETCH(1); /* field offset */ \ 1083 ILOGV("|iget%s-quick v%d,v%d,field@+%u", \ 1084 (_opname), vdst, vsrc1, ref); \ 1085 obj = (Object*) GET_REGISTER(vsrc1); \ 1086 if (!checkForNullExportPC(obj, fp, pc)) \ 1087 GOTO_exceptionThrown(); \ 1088 SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \ 1089 ILOGV("+ IGETQ %d=0x%08llx", ref, \ 1090 (u8) GET_REGISTER##_regsize(vdst)); \ 1091 } \ 1092 FINISH(2); 1093 1094#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \ 1095 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1096 { \ 1097 InstField* ifield; \ 1098 Object* obj; \ 1099 EXPORT_PC(); \ 1100 vdst = INST_A(inst); \ 1101 vsrc1 = INST_B(inst); /* object ptr */ \ 1102 ref = FETCH(1); /* field ref */ \ 1103 ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ 1104 obj = (Object*) GET_REGISTER(vsrc1); \ 1105 if (!checkForNull(obj)) \ 1106 GOTO_exceptionThrown(); \ 1107 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1108 if (ifield == NULL) { \ 1109 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1110 if (ifield == NULL) \ 1111 GOTO_exceptionThrown(); \ 1112 } \ 1113 dvmSetField##_ftype(obj, ifield->byteOffset, \ 1114 GET_REGISTER##_regsize(vdst)); \ 1115 ILOGV("+ IPUT '%s'=0x%08llx", ifield->name, \ 1116 (u8) GET_REGISTER##_regsize(vdst)); \ 1117 } \ 1118 FINISH(2); 1119 1120#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1121 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \ 1122 { \ 1123 InstField* ifield; \ 1124 Object* obj; \ 1125 EXPORT_PC(); \ 1126 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1127 vdst = FETCH(3); \ 1128 vsrc1 = FETCH(4); /* object ptr */ \ 1129 ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \ 1130 (_opname), vdst, vsrc1, ref); \ 1131 obj = (Object*) GET_REGISTER(vsrc1); \ 1132 if (!checkForNull(obj)) \ 1133 GOTO_exceptionThrown(); \ 1134 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1135 if (ifield == NULL) { \ 1136 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1137 if (ifield == NULL) \ 1138 GOTO_exceptionThrown(); \ 1139 } \ 1140 dvmSetField##_ftype(obj, ifield->byteOffset, \ 1141 GET_REGISTER##_regsize(vdst)); \ 1142 ILOGV("+ IPUT '%s'=0x%08llx", ifield->name, \ 1143 (u8) GET_REGISTER##_regsize(vdst)); \ 1144 } \ 1145 FINISH(5); 1146 1147#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \ 1148 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1149 { \ 1150 Object* obj; \ 1151 vdst = INST_A(inst); \ 1152 vsrc1 = INST_B(inst); /* object ptr */ \ 1153 ref = FETCH(1); /* field offset */ \ 1154 ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \ 1155 (_opname), vdst, vsrc1, ref); \ 1156 obj = (Object*) GET_REGISTER(vsrc1); \ 1157 if (!checkForNullExportPC(obj, fp, pc)) \ 1158 GOTO_exceptionThrown(); \ 1159 dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \ 1160 ILOGV("+ IPUTQ %d=0x%08llx", ref, \ 1161 (u8) GET_REGISTER##_regsize(vdst)); \ 1162 } \ 1163 FINISH(2); 1164 1165/* 1166 * The JIT needs dvmDexGetResolvedField() to return non-null. 1167 * Because the portable interpreter is not involved with the JIT 1168 * and trace building, we only need the extra check here when this 1169 * code is massaged into a stub called from an assembly interpreter. 1170 * This is controlled by the JIT_STUB_HACK maco. 1171 */ 1172 1173#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \ 1174 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \ 1175 { \ 1176 StaticField* sfield; \ 1177 vdst = INST_AA(inst); \ 1178 ref = FETCH(1); /* field ref */ \ 1179 ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \ 1180 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1181 if (sfield == NULL) { \ 1182 EXPORT_PC(); \ 1183 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1184 if (sfield == NULL) \ 1185 GOTO_exceptionThrown(); \ 1186 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1187 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1188 } \ 1189 } \ 1190 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \ 1191 ILOGV("+ SGET '%s'=0x%08llx", \ 1192 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1193 } \ 1194 FINISH(2); 1195 1196#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1197 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \ 1198 { \ 1199 StaticField* sfield; \ 1200 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1201 vdst = FETCH(3); \ 1202 ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \ 1203 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1204 if (sfield == NULL) { \ 1205 EXPORT_PC(); \ 1206 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1207 if (sfield == NULL) \ 1208 GOTO_exceptionThrown(); \ 1209 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1210 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1211 } \ 1212 } \ 1213 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \ 1214 ILOGV("+ SGET '%s'=0x%08llx", \ 1215 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1216 } \ 1217 FINISH(4); 1218 1219#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \ 1220 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \ 1221 { \ 1222 StaticField* sfield; \ 1223 vdst = INST_AA(inst); \ 1224 ref = FETCH(1); /* field ref */ \ 1225 ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \ 1226 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1227 if (sfield == NULL) { \ 1228 EXPORT_PC(); \ 1229 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1230 if (sfield == NULL) \ 1231 GOTO_exceptionThrown(); \ 1232 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1233 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1234 } \ 1235 } \ 1236 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \ 1237 ILOGV("+ SPUT '%s'=0x%08llx", \ 1238 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1239 } \ 1240 FINISH(2); 1241 1242#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1243 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \ 1244 { \ 1245 StaticField* sfield; \ 1246 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1247 vdst = FETCH(3); \ 1248 ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \ 1249 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1250 if (sfield == NULL) { \ 1251 EXPORT_PC(); \ 1252 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1253 if (sfield == NULL) \ 1254 GOTO_exceptionThrown(); \ 1255 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1256 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1257 } \ 1258 } \ 1259 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \ 1260 ILOGV("+ SPUT '%s'=0x%08llx", \ 1261 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1262 } \ 1263 FINISH(4); 1264 1265/* File: c/OP_NOP.cpp */ 1266HANDLE_OPCODE(OP_NOP) 1267 FINISH(1); 1268OP_END 1269 1270/* File: c/OP_MOVE.cpp */ 1271HANDLE_OPCODE(OP_MOVE /*vA, vB*/) 1272 vdst = INST_A(inst); 1273 vsrc1 = INST_B(inst); 1274 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)", 1275 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1, 1276 kSpacing, vdst, GET_REGISTER(vsrc1)); 1277 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1278 FINISH(1); 1279OP_END 1280 1281/* File: c/OP_MOVE_FROM16.cpp */ 1282HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/) 1283 vdst = INST_AA(inst); 1284 vsrc1 = FETCH(1); 1285 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)", 1286 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1, 1287 kSpacing, vdst, GET_REGISTER(vsrc1)); 1288 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1289 FINISH(2); 1290OP_END 1291 1292/* File: c/OP_MOVE_16.cpp */ 1293HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/) 1294 vdst = FETCH(1); 1295 vsrc1 = FETCH(2); 1296 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)", 1297 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1, 1298 kSpacing, vdst, GET_REGISTER(vsrc1)); 1299 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1300 FINISH(3); 1301OP_END 1302 1303/* File: c/OP_MOVE_WIDE.cpp */ 1304HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/) 1305 /* IMPORTANT: must correctly handle overlapping registers, e.g. both 1306 * "move-wide v6, v7" and "move-wide v7, v6" */ 1307 vdst = INST_A(inst); 1308 vsrc1 = INST_B(inst); 1309 ILOGV("|move-wide v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1, 1310 kSpacing+5, vdst, GET_REGISTER_WIDE(vsrc1)); 1311 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1)); 1312 FINISH(1); 1313OP_END 1314 1315/* File: c/OP_MOVE_WIDE_FROM16.cpp */ 1316HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/) 1317 vdst = INST_AA(inst); 1318 vsrc1 = FETCH(1); 1319 ILOGV("|move-wide/from16 v%d,v%d (v%d=0x%08llx)", vdst, vsrc1, 1320 vdst, GET_REGISTER_WIDE(vsrc1)); 1321 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1)); 1322 FINISH(2); 1323OP_END 1324 1325/* File: c/OP_MOVE_WIDE_16.cpp */ 1326HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/) 1327 vdst = FETCH(1); 1328 vsrc1 = FETCH(2); 1329 ILOGV("|move-wide/16 v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1, 1330 kSpacing+8, vdst, GET_REGISTER_WIDE(vsrc1)); 1331 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1)); 1332 FINISH(3); 1333OP_END 1334 1335/* File: c/OP_MOVE_OBJECT.cpp */ 1336/* File: c/OP_MOVE.cpp */ 1337HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/) 1338 vdst = INST_A(inst); 1339 vsrc1 = INST_B(inst); 1340 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)", 1341 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1, 1342 kSpacing, vdst, GET_REGISTER(vsrc1)); 1343 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1344 FINISH(1); 1345OP_END 1346 1347 1348/* File: c/OP_MOVE_OBJECT_FROM16.cpp */ 1349/* File: c/OP_MOVE_FROM16.cpp */ 1350HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/) 1351 vdst = INST_AA(inst); 1352 vsrc1 = FETCH(1); 1353 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)", 1354 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1, 1355 kSpacing, vdst, GET_REGISTER(vsrc1)); 1356 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1357 FINISH(2); 1358OP_END 1359 1360 1361/* File: c/OP_MOVE_OBJECT_16.cpp */ 1362/* File: c/OP_MOVE_16.cpp */ 1363HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/) 1364 vdst = FETCH(1); 1365 vsrc1 = FETCH(2); 1366 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)", 1367 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1, 1368 kSpacing, vdst, GET_REGISTER(vsrc1)); 1369 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1370 FINISH(3); 1371OP_END 1372 1373 1374/* File: c/OP_MOVE_RESULT.cpp */ 1375HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/) 1376 vdst = INST_AA(inst); 1377 ILOGV("|move-result%s v%d %s(v%d=0x%08x)", 1378 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object", 1379 vdst, kSpacing+4, vdst,retval.i); 1380 SET_REGISTER(vdst, retval.i); 1381 FINISH(1); 1382OP_END 1383 1384/* File: c/OP_MOVE_RESULT_WIDE.cpp */ 1385HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/) 1386 vdst = INST_AA(inst); 1387 ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j); 1388 SET_REGISTER_WIDE(vdst, retval.j); 1389 FINISH(1); 1390OP_END 1391 1392/* File: c/OP_MOVE_RESULT_OBJECT.cpp */ 1393/* File: c/OP_MOVE_RESULT.cpp */ 1394HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/) 1395 vdst = INST_AA(inst); 1396 ILOGV("|move-result%s v%d %s(v%d=0x%08x)", 1397 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object", 1398 vdst, kSpacing+4, vdst,retval.i); 1399 SET_REGISTER(vdst, retval.i); 1400 FINISH(1); 1401OP_END 1402 1403 1404/* File: c/OP_MOVE_EXCEPTION.cpp */ 1405HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/) 1406 vdst = INST_AA(inst); 1407 ILOGV("|move-exception v%d", vdst); 1408 assert(self->exception != NULL); 1409 SET_REGISTER(vdst, (u4)self->exception); 1410 dvmClearException(self); 1411 FINISH(1); 1412OP_END 1413 1414/* File: c/OP_RETURN_VOID.cpp */ 1415HANDLE_OPCODE(OP_RETURN_VOID /**/) 1416 ILOGV("|return-void"); 1417#ifndef NDEBUG 1418 retval.j = 0xababababULL; // placate valgrind 1419#endif 1420 GOTO_returnFromMethod(); 1421OP_END 1422 1423/* File: c/OP_RETURN.cpp */ 1424HANDLE_OPCODE(OP_RETURN /*vAA*/) 1425 vsrc1 = INST_AA(inst); 1426 ILOGV("|return%s v%d", 1427 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1); 1428 retval.i = GET_REGISTER(vsrc1); 1429 GOTO_returnFromMethod(); 1430OP_END 1431 1432/* File: c/OP_RETURN_WIDE.cpp */ 1433HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/) 1434 vsrc1 = INST_AA(inst); 1435 ILOGV("|return-wide v%d", vsrc1); 1436 retval.j = GET_REGISTER_WIDE(vsrc1); 1437 GOTO_returnFromMethod(); 1438OP_END 1439 1440/* File: c/OP_RETURN_OBJECT.cpp */ 1441/* File: c/OP_RETURN.cpp */ 1442HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/) 1443 vsrc1 = INST_AA(inst); 1444 ILOGV("|return%s v%d", 1445 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1); 1446 retval.i = GET_REGISTER(vsrc1); 1447 GOTO_returnFromMethod(); 1448OP_END 1449 1450 1451/* File: c/OP_CONST_4.cpp */ 1452HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/) 1453 { 1454 s4 tmp; 1455 1456 vdst = INST_A(inst); 1457 tmp = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value 1458 ILOGV("|const/4 v%d,#0x%02x", vdst, (s4)tmp); 1459 SET_REGISTER(vdst, tmp); 1460 } 1461 FINISH(1); 1462OP_END 1463 1464/* File: c/OP_CONST_16.cpp */ 1465HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/) 1466 vdst = INST_AA(inst); 1467 vsrc1 = FETCH(1); 1468 ILOGV("|const/16 v%d,#0x%04x", vdst, (s2)vsrc1); 1469 SET_REGISTER(vdst, (s2) vsrc1); 1470 FINISH(2); 1471OP_END 1472 1473/* File: c/OP_CONST.cpp */ 1474HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/) 1475 { 1476 u4 tmp; 1477 1478 vdst = INST_AA(inst); 1479 tmp = FETCH(1); 1480 tmp |= (u4)FETCH(2) << 16; 1481 ILOGV("|const v%d,#0x%08x", vdst, tmp); 1482 SET_REGISTER(vdst, tmp); 1483 } 1484 FINISH(3); 1485OP_END 1486 1487/* File: c/OP_CONST_HIGH16.cpp */ 1488HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/) 1489 vdst = INST_AA(inst); 1490 vsrc1 = FETCH(1); 1491 ILOGV("|const/high16 v%d,#0x%04x0000", vdst, vsrc1); 1492 SET_REGISTER(vdst, vsrc1 << 16); 1493 FINISH(2); 1494OP_END 1495 1496/* File: c/OP_CONST_WIDE_16.cpp */ 1497HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/) 1498 vdst = INST_AA(inst); 1499 vsrc1 = FETCH(1); 1500 ILOGV("|const-wide/16 v%d,#0x%04x", vdst, (s2)vsrc1); 1501 SET_REGISTER_WIDE(vdst, (s2)vsrc1); 1502 FINISH(2); 1503OP_END 1504 1505/* File: c/OP_CONST_WIDE_32.cpp */ 1506HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/) 1507 { 1508 u4 tmp; 1509 1510 vdst = INST_AA(inst); 1511 tmp = FETCH(1); 1512 tmp |= (u4)FETCH(2) << 16; 1513 ILOGV("|const-wide/32 v%d,#0x%08x", vdst, tmp); 1514 SET_REGISTER_WIDE(vdst, (s4) tmp); 1515 } 1516 FINISH(3); 1517OP_END 1518 1519/* File: c/OP_CONST_WIDE.cpp */ 1520HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/) 1521 { 1522 u8 tmp; 1523 1524 vdst = INST_AA(inst); 1525 tmp = FETCH(1); 1526 tmp |= (u8)FETCH(2) << 16; 1527 tmp |= (u8)FETCH(3) << 32; 1528 tmp |= (u8)FETCH(4) << 48; 1529 ILOGV("|const-wide v%d,#0x%08llx", vdst, tmp); 1530 SET_REGISTER_WIDE(vdst, tmp); 1531 } 1532 FINISH(5); 1533OP_END 1534 1535/* File: c/OP_CONST_WIDE_HIGH16.cpp */ 1536HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/) 1537 vdst = INST_AA(inst); 1538 vsrc1 = FETCH(1); 1539 ILOGV("|const-wide/high16 v%d,#0x%04x000000000000", vdst, vsrc1); 1540 SET_REGISTER_WIDE(vdst, ((u8) vsrc1) << 48); 1541 FINISH(2); 1542OP_END 1543 1544/* File: c/OP_CONST_STRING.cpp */ 1545HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/) 1546 { 1547 StringObject* strObj; 1548 1549 vdst = INST_AA(inst); 1550 ref = FETCH(1); 1551 ILOGV("|const-string v%d string@0x%04x", vdst, ref); 1552 strObj = dvmDexGetResolvedString(methodClassDex, ref); 1553 if (strObj == NULL) { 1554 EXPORT_PC(); 1555 strObj = dvmResolveString(curMethod->clazz, ref); 1556 if (strObj == NULL) 1557 GOTO_exceptionThrown(); 1558 } 1559 SET_REGISTER(vdst, (u4) strObj); 1560 } 1561 FINISH(2); 1562OP_END 1563 1564/* File: c/OP_CONST_STRING_JUMBO.cpp */ 1565HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/) 1566 { 1567 StringObject* strObj; 1568 u4 tmp; 1569 1570 vdst = INST_AA(inst); 1571 tmp = FETCH(1); 1572 tmp |= (u4)FETCH(2) << 16; 1573 ILOGV("|const-string/jumbo v%d string@0x%08x", vdst, tmp); 1574 strObj = dvmDexGetResolvedString(methodClassDex, tmp); 1575 if (strObj == NULL) { 1576 EXPORT_PC(); 1577 strObj = dvmResolveString(curMethod->clazz, tmp); 1578 if (strObj == NULL) 1579 GOTO_exceptionThrown(); 1580 } 1581 SET_REGISTER(vdst, (u4) strObj); 1582 } 1583 FINISH(3); 1584OP_END 1585 1586/* File: c/OP_CONST_CLASS.cpp */ 1587HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/) 1588 { 1589 ClassObject* clazz; 1590 1591 vdst = INST_AA(inst); 1592 ref = FETCH(1); 1593 ILOGV("|const-class v%d class@0x%04x", vdst, ref); 1594 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1595 if (clazz == NULL) { 1596 EXPORT_PC(); 1597 clazz = dvmResolveClass(curMethod->clazz, ref, true); 1598 if (clazz == NULL) 1599 GOTO_exceptionThrown(); 1600 } 1601 SET_REGISTER(vdst, (u4) clazz); 1602 } 1603 FINISH(2); 1604OP_END 1605 1606/* File: c/OP_MONITOR_ENTER.cpp */ 1607HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/) 1608 { 1609 Object* obj; 1610 1611 vsrc1 = INST_AA(inst); 1612 ILOGV("|monitor-enter v%d %s(0x%08x)", 1613 vsrc1, kSpacing+6, GET_REGISTER(vsrc1)); 1614 obj = (Object*)GET_REGISTER(vsrc1); 1615 if (!checkForNullExportPC(obj, fp, pc)) 1616 GOTO_exceptionThrown(); 1617 ILOGV("+ locking %p %s", obj, obj->clazz->descriptor); 1618 EXPORT_PC(); /* need for precise GC */ 1619 dvmLockObject(self, obj); 1620 } 1621 FINISH(1); 1622OP_END 1623 1624/* File: c/OP_MONITOR_EXIT.cpp */ 1625HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/) 1626 { 1627 Object* obj; 1628 1629 EXPORT_PC(); 1630 1631 vsrc1 = INST_AA(inst); 1632 ILOGV("|monitor-exit v%d %s(0x%08x)", 1633 vsrc1, kSpacing+5, GET_REGISTER(vsrc1)); 1634 obj = (Object*)GET_REGISTER(vsrc1); 1635 if (!checkForNull(obj)) { 1636 /* 1637 * The exception needs to be processed at the *following* 1638 * instruction, not the current instruction (see the Dalvik 1639 * spec). Because we're jumping to an exception handler, 1640 * we're not actually at risk of skipping an instruction 1641 * by doing so. 1642 */ 1643 ADJUST_PC(1); /* monitor-exit width is 1 */ 1644 GOTO_exceptionThrown(); 1645 } 1646 ILOGV("+ unlocking %p %s", obj, obj->clazz->descriptor); 1647 if (!dvmUnlockObject(self, obj)) { 1648 assert(dvmCheckException(self)); 1649 ADJUST_PC(1); 1650 GOTO_exceptionThrown(); 1651 } 1652 } 1653 FINISH(1); 1654OP_END 1655 1656/* File: c/OP_CHECK_CAST.cpp */ 1657HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/) 1658 { 1659 ClassObject* clazz; 1660 Object* obj; 1661 1662 EXPORT_PC(); 1663 1664 vsrc1 = INST_AA(inst); 1665 ref = FETCH(1); /* class to check against */ 1666 ILOGV("|check-cast v%d,class@0x%04x", vsrc1, ref); 1667 1668 obj = (Object*)GET_REGISTER(vsrc1); 1669 if (obj != NULL) { 1670#if defined(WITH_EXTRA_OBJECT_VALIDATION) 1671 if (!checkForNull(obj)) 1672 GOTO_exceptionThrown(); 1673#endif 1674 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1675 if (clazz == NULL) { 1676 clazz = dvmResolveClass(curMethod->clazz, ref, false); 1677 if (clazz == NULL) 1678 GOTO_exceptionThrown(); 1679 } 1680 if (!dvmInstanceof(obj->clazz, clazz)) { 1681 dvmThrowClassCastException(obj->clazz, clazz); 1682 GOTO_exceptionThrown(); 1683 } 1684 } 1685 } 1686 FINISH(2); 1687OP_END 1688 1689/* File: c/OP_INSTANCE_OF.cpp */ 1690HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/) 1691 { 1692 ClassObject* clazz; 1693 Object* obj; 1694 1695 vdst = INST_A(inst); 1696 vsrc1 = INST_B(inst); /* object to check */ 1697 ref = FETCH(1); /* class to check against */ 1698 ILOGV("|instance-of v%d,v%d,class@0x%04x", vdst, vsrc1, ref); 1699 1700 obj = (Object*)GET_REGISTER(vsrc1); 1701 if (obj == NULL) { 1702 SET_REGISTER(vdst, 0); 1703 } else { 1704#if defined(WITH_EXTRA_OBJECT_VALIDATION) 1705 if (!checkForNullExportPC(obj, fp, pc)) 1706 GOTO_exceptionThrown(); 1707#endif 1708 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1709 if (clazz == NULL) { 1710 EXPORT_PC(); 1711 clazz = dvmResolveClass(curMethod->clazz, ref, true); 1712 if (clazz == NULL) 1713 GOTO_exceptionThrown(); 1714 } 1715 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz)); 1716 } 1717 } 1718 FINISH(2); 1719OP_END 1720 1721/* File: c/OP_ARRAY_LENGTH.cpp */ 1722HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/) 1723 { 1724 ArrayObject* arrayObj; 1725 1726 vdst = INST_A(inst); 1727 vsrc1 = INST_B(inst); 1728 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); 1729 ILOGV("|array-length v%d,v%d (%p)", vdst, vsrc1, arrayObj); 1730 if (!checkForNullExportPC((Object*) arrayObj, fp, pc)) 1731 GOTO_exceptionThrown(); 1732 /* verifier guarantees this is an array reference */ 1733 SET_REGISTER(vdst, arrayObj->length); 1734 } 1735 FINISH(1); 1736OP_END 1737 1738/* File: c/OP_NEW_INSTANCE.cpp */ 1739HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/) 1740 { 1741 ClassObject* clazz; 1742 Object* newObj; 1743 1744 EXPORT_PC(); 1745 1746 vdst = INST_AA(inst); 1747 ref = FETCH(1); 1748 ILOGV("|new-instance v%d,class@0x%04x", vdst, ref); 1749 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1750 if (clazz == NULL) { 1751 clazz = dvmResolveClass(curMethod->clazz, ref, false); 1752 if (clazz == NULL) 1753 GOTO_exceptionThrown(); 1754 } 1755 1756 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) 1757 GOTO_exceptionThrown(); 1758 1759#if defined(WITH_JIT) 1760 /* 1761 * The JIT needs dvmDexGetResolvedClass() to return non-null. 1762 * Since we use the portable interpreter to build the trace, this extra 1763 * check is not needed for mterp. 1764 */ 1765 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 1766 (!dvmDexGetResolvedClass(methodClassDex, ref))) { 1767 /* Class initialization is still ongoing - end the trace */ 1768 dvmJitEndTraceSelect(self,pc); 1769 } 1770#endif 1771 1772 /* 1773 * Verifier now tests for interface/abstract class. 1774 */ 1775 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) { 1776 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError, 1777 // clazz->descriptor); 1778 // GOTO_exceptionThrown(); 1779 //} 1780 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK); 1781 if (newObj == NULL) 1782 GOTO_exceptionThrown(); 1783 SET_REGISTER(vdst, (u4) newObj); 1784 } 1785 FINISH(2); 1786OP_END 1787 1788/* File: c/OP_NEW_ARRAY.cpp */ 1789HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/) 1790 { 1791 ClassObject* arrayClass; 1792 ArrayObject* newArray; 1793 s4 length; 1794 1795 EXPORT_PC(); 1796 1797 vdst = INST_A(inst); 1798 vsrc1 = INST_B(inst); /* length reg */ 1799 ref = FETCH(1); 1800 ILOGV("|new-array v%d,v%d,class@0x%04x (%d elements)", 1801 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1)); 1802 length = (s4) GET_REGISTER(vsrc1); 1803 if (length < 0) { 1804 dvmThrowNegativeArraySizeException(length); 1805 GOTO_exceptionThrown(); 1806 } 1807 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 1808 if (arrayClass == NULL) { 1809 arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 1810 if (arrayClass == NULL) 1811 GOTO_exceptionThrown(); 1812 } 1813 /* verifier guarantees this is an array class */ 1814 assert(dvmIsArrayClass(arrayClass)); 1815 assert(dvmIsClassInitialized(arrayClass)); 1816 1817 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK); 1818 if (newArray == NULL) 1819 GOTO_exceptionThrown(); 1820 SET_REGISTER(vdst, (u4) newArray); 1821 } 1822 FINISH(2); 1823OP_END 1824 1825/* File: c/OP_FILLED_NEW_ARRAY.cpp */ 1826HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/) 1827 GOTO_invoke(filledNewArray, false, false); 1828OP_END 1829 1830/* File: c/OP_FILLED_NEW_ARRAY_RANGE.cpp */ 1831HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/) 1832 GOTO_invoke(filledNewArray, true, false); 1833OP_END 1834 1835/* File: c/OP_FILL_ARRAY_DATA.cpp */ 1836HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/ 1837 { 1838 const u2* arrayData; 1839 s4 offset; 1840 ArrayObject* arrayObj; 1841 1842 EXPORT_PC(); 1843 vsrc1 = INST_AA(inst); 1844 offset = FETCH(1) | (((s4) FETCH(2)) << 16); 1845 ILOGV("|fill-array-data v%d +0x%04x", vsrc1, offset); 1846 arrayData = pc + offset; // offset in 16-bit units 1847#ifndef NDEBUG 1848 if (arrayData < curMethod->insns || 1849 arrayData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) 1850 { 1851 /* should have been caught in verifier */ 1852 dvmThrowInternalError("bad fill array data"); 1853 GOTO_exceptionThrown(); 1854 } 1855#endif 1856 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); 1857 if (!dvmInterpHandleFillArrayData(arrayObj, arrayData)) { 1858 GOTO_exceptionThrown(); 1859 } 1860 FINISH(3); 1861 } 1862OP_END 1863 1864/* File: c/OP_THROW.cpp */ 1865HANDLE_OPCODE(OP_THROW /*vAA*/) 1866 { 1867 Object* obj; 1868 1869 /* 1870 * We don't create an exception here, but the process of searching 1871 * for a catch block can do class lookups and throw exceptions. 1872 * We need to update the saved PC. 1873 */ 1874 EXPORT_PC(); 1875 1876 vsrc1 = INST_AA(inst); 1877 ILOGV("|throw v%d (%p)", vsrc1, (void*)GET_REGISTER(vsrc1)); 1878 obj = (Object*) GET_REGISTER(vsrc1); 1879 if (!checkForNull(obj)) { 1880 /* will throw a null pointer exception */ 1881 LOGVV("Bad exception"); 1882 } else { 1883 /* use the requested exception */ 1884 dvmSetException(self, obj); 1885 } 1886 GOTO_exceptionThrown(); 1887 } 1888OP_END 1889 1890/* File: c/OP_GOTO.cpp */ 1891HANDLE_OPCODE(OP_GOTO /*+AA*/) 1892 vdst = INST_AA(inst); 1893 if ((s1)vdst < 0) 1894 ILOGV("|goto -0x%02x", -((s1)vdst)); 1895 else 1896 ILOGV("|goto +0x%02x", ((s1)vdst)); 1897 ILOGV("> branch taken"); 1898 if ((s1)vdst < 0) 1899 PERIODIC_CHECKS((s1)vdst); 1900 FINISH((s1)vdst); 1901OP_END 1902 1903/* File: c/OP_GOTO_16.cpp */ 1904HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/) 1905 { 1906 s4 offset = (s2) FETCH(1); /* sign-extend next code unit */ 1907 1908 if (offset < 0) 1909 ILOGV("|goto/16 -0x%04x", -offset); 1910 else 1911 ILOGV("|goto/16 +0x%04x", offset); 1912 ILOGV("> branch taken"); 1913 if (offset < 0) 1914 PERIODIC_CHECKS(offset); 1915 FINISH(offset); 1916 } 1917OP_END 1918 1919/* File: c/OP_GOTO_32.cpp */ 1920HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/) 1921 { 1922 s4 offset = FETCH(1); /* low-order 16 bits */ 1923 offset |= ((s4) FETCH(2)) << 16; /* high-order 16 bits */ 1924 1925 if (offset < 0) 1926 ILOGV("|goto/32 -0x%08x", -offset); 1927 else 1928 ILOGV("|goto/32 +0x%08x", offset); 1929 ILOGV("> branch taken"); 1930 if (offset <= 0) /* allowed to branch to self */ 1931 PERIODIC_CHECKS(offset); 1932 FINISH(offset); 1933 } 1934OP_END 1935 1936/* File: c/OP_PACKED_SWITCH.cpp */ 1937HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/) 1938 { 1939 const u2* switchData; 1940 u4 testVal; 1941 s4 offset; 1942 1943 vsrc1 = INST_AA(inst); 1944 offset = FETCH(1) | (((s4) FETCH(2)) << 16); 1945 ILOGV("|packed-switch v%d +0x%04x", vsrc1, offset); 1946 switchData = pc + offset; // offset in 16-bit units 1947#ifndef NDEBUG 1948 if (switchData < curMethod->insns || 1949 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) 1950 { 1951 /* should have been caught in verifier */ 1952 EXPORT_PC(); 1953 dvmThrowInternalError("bad packed switch"); 1954 GOTO_exceptionThrown(); 1955 } 1956#endif 1957 testVal = GET_REGISTER(vsrc1); 1958 1959 offset = dvmInterpHandlePackedSwitch(switchData, testVal); 1960 ILOGV("> branch taken (0x%04x)", offset); 1961 if (offset <= 0) /* uncommon */ 1962 PERIODIC_CHECKS(offset); 1963 FINISH(offset); 1964 } 1965OP_END 1966 1967/* File: c/OP_SPARSE_SWITCH.cpp */ 1968HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/) 1969 { 1970 const u2* switchData; 1971 u4 testVal; 1972 s4 offset; 1973 1974 vsrc1 = INST_AA(inst); 1975 offset = FETCH(1) | (((s4) FETCH(2)) << 16); 1976 ILOGV("|sparse-switch v%d +0x%04x", vsrc1, offset); 1977 switchData = pc + offset; // offset in 16-bit units 1978#ifndef NDEBUG 1979 if (switchData < curMethod->insns || 1980 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) 1981 { 1982 /* should have been caught in verifier */ 1983 EXPORT_PC(); 1984 dvmThrowInternalError("bad sparse switch"); 1985 GOTO_exceptionThrown(); 1986 } 1987#endif 1988 testVal = GET_REGISTER(vsrc1); 1989 1990 offset = dvmInterpHandleSparseSwitch(switchData, testVal); 1991 ILOGV("> branch taken (0x%04x)", offset); 1992 if (offset <= 0) /* uncommon */ 1993 PERIODIC_CHECKS(offset); 1994 FINISH(offset); 1995 } 1996OP_END 1997 1998/* File: c/OP_CMPL_FLOAT.cpp */ 1999HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1) 2000OP_END 2001 2002/* File: c/OP_CMPG_FLOAT.cpp */ 2003HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1) 2004OP_END 2005 2006/* File: c/OP_CMPL_DOUBLE.cpp */ 2007HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1) 2008OP_END 2009 2010/* File: c/OP_CMPG_DOUBLE.cpp */ 2011HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1) 2012OP_END 2013 2014/* File: c/OP_CMP_LONG.cpp */ 2015HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0) 2016OP_END 2017 2018/* File: c/OP_IF_EQ.cpp */ 2019HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==) 2020OP_END 2021 2022/* File: c/OP_IF_NE.cpp */ 2023HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=) 2024OP_END 2025 2026/* File: c/OP_IF_LT.cpp */ 2027HANDLE_OP_IF_XX(OP_IF_LT, "lt", <) 2028OP_END 2029 2030/* File: c/OP_IF_GE.cpp */ 2031HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=) 2032OP_END 2033 2034/* File: c/OP_IF_GT.cpp */ 2035HANDLE_OP_IF_XX(OP_IF_GT, "gt", >) 2036OP_END 2037 2038/* File: c/OP_IF_LE.cpp */ 2039HANDLE_OP_IF_XX(OP_IF_LE, "le", <=) 2040OP_END 2041 2042/* File: c/OP_IF_EQZ.cpp */ 2043HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==) 2044OP_END 2045 2046/* File: c/OP_IF_NEZ.cpp */ 2047HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=) 2048OP_END 2049 2050/* File: c/OP_IF_LTZ.cpp */ 2051HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <) 2052OP_END 2053 2054/* File: c/OP_IF_GEZ.cpp */ 2055HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=) 2056OP_END 2057 2058/* File: c/OP_IF_GTZ.cpp */ 2059HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >) 2060OP_END 2061 2062/* File: c/OP_IF_LEZ.cpp */ 2063HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=) 2064OP_END 2065 2066/* File: c/OP_UNUSED_3E.cpp */ 2067HANDLE_OPCODE(OP_UNUSED_3E) 2068OP_END 2069 2070/* File: c/OP_UNUSED_3F.cpp */ 2071HANDLE_OPCODE(OP_UNUSED_3F) 2072OP_END 2073 2074/* File: c/OP_UNUSED_40.cpp */ 2075HANDLE_OPCODE(OP_UNUSED_40) 2076OP_END 2077 2078/* File: c/OP_UNUSED_41.cpp */ 2079HANDLE_OPCODE(OP_UNUSED_41) 2080OP_END 2081 2082/* File: c/OP_UNUSED_42.cpp */ 2083HANDLE_OPCODE(OP_UNUSED_42) 2084OP_END 2085 2086/* File: c/OP_UNUSED_43.cpp */ 2087HANDLE_OPCODE(OP_UNUSED_43) 2088OP_END 2089 2090/* File: c/OP_AGET.cpp */ 2091HANDLE_OP_AGET(OP_AGET, "", u4, ) 2092OP_END 2093 2094/* File: c/OP_AGET_WIDE.cpp */ 2095HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE) 2096OP_END 2097 2098/* File: c/OP_AGET_OBJECT.cpp */ 2099HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, ) 2100OP_END 2101 2102/* File: c/OP_AGET_BOOLEAN.cpp */ 2103HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, ) 2104OP_END 2105 2106/* File: c/OP_AGET_BYTE.cpp */ 2107HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, ) 2108OP_END 2109 2110/* File: c/OP_AGET_CHAR.cpp */ 2111HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, ) 2112OP_END 2113 2114/* File: c/OP_AGET_SHORT.cpp */ 2115HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, ) 2116OP_END 2117 2118/* File: c/OP_APUT.cpp */ 2119HANDLE_OP_APUT(OP_APUT, "", u4, ) 2120OP_END 2121 2122/* File: c/OP_APUT_WIDE.cpp */ 2123HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE) 2124OP_END 2125 2126/* File: c/OP_APUT_OBJECT.cpp */ 2127HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/) 2128 { 2129 ArrayObject* arrayObj; 2130 Object* obj; 2131 u2 arrayInfo; 2132 EXPORT_PC(); 2133 vdst = INST_AA(inst); /* AA: source value */ 2134 arrayInfo = FETCH(1); 2135 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ 2136 vsrc2 = arrayInfo >> 8; /* CC: index */ 2137 ILOGV("|aput%s v%d,v%d,v%d", "-object", vdst, vsrc1, vsrc2); 2138 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); 2139 if (!checkForNull((Object*) arrayObj)) 2140 GOTO_exceptionThrown(); 2141 if (GET_REGISTER(vsrc2) >= arrayObj->length) { 2142 dvmThrowArrayIndexOutOfBoundsException( 2143 arrayObj->length, GET_REGISTER(vsrc2)); 2144 GOTO_exceptionThrown(); 2145 } 2146 obj = (Object*) GET_REGISTER(vdst); 2147 if (obj != NULL) { 2148 if (!checkForNull(obj)) 2149 GOTO_exceptionThrown(); 2150 if (!dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) { 2151 LOGV("Can't put a '%s'(%p) into array type='%s'(%p)", 2152 obj->clazz->descriptor, obj, 2153 arrayObj->obj.clazz->descriptor, arrayObj); 2154 dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz); 2155 GOTO_exceptionThrown(); 2156 } 2157 } 2158 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); 2159 dvmSetObjectArrayElement(arrayObj, 2160 GET_REGISTER(vsrc2), 2161 (Object *)GET_REGISTER(vdst)); 2162 } 2163 FINISH(2); 2164OP_END 2165 2166/* File: c/OP_APUT_BOOLEAN.cpp */ 2167HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, ) 2168OP_END 2169 2170/* File: c/OP_APUT_BYTE.cpp */ 2171HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, ) 2172OP_END 2173 2174/* File: c/OP_APUT_CHAR.cpp */ 2175HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, ) 2176OP_END 2177 2178/* File: c/OP_APUT_SHORT.cpp */ 2179HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, ) 2180OP_END 2181 2182/* File: c/OP_IGET.cpp */ 2183HANDLE_IGET_X(OP_IGET, "", Int, ) 2184OP_END 2185 2186/* File: c/OP_IGET_WIDE.cpp */ 2187HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE) 2188OP_END 2189 2190/* File: c/OP_IGET_OBJECT.cpp */ 2191HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT) 2192OP_END 2193 2194/* File: c/OP_IGET_BOOLEAN.cpp */ 2195HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, ) 2196OP_END 2197 2198/* File: c/OP_IGET_BYTE.cpp */ 2199HANDLE_IGET_X(OP_IGET_BYTE, "", Int, ) 2200OP_END 2201 2202/* File: c/OP_IGET_CHAR.cpp */ 2203HANDLE_IGET_X(OP_IGET_CHAR, "", Int, ) 2204OP_END 2205 2206/* File: c/OP_IGET_SHORT.cpp */ 2207HANDLE_IGET_X(OP_IGET_SHORT, "", Int, ) 2208OP_END 2209 2210/* File: c/OP_IPUT.cpp */ 2211HANDLE_IPUT_X(OP_IPUT, "", Int, ) 2212OP_END 2213 2214/* File: c/OP_IPUT_WIDE.cpp */ 2215HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE) 2216OP_END 2217 2218/* File: c/OP_IPUT_OBJECT.cpp */ 2219/* 2220 * The VM spec says we should verify that the reference being stored into 2221 * the field is assignment compatible. In practice, many popular VMs don't 2222 * do this because it slows down a very common operation. It's not so bad 2223 * for us, since "dexopt" quickens it whenever possible, but it's still an 2224 * issue. 2225 * 2226 * To make this spec-complaint, we'd need to add a ClassObject pointer to 2227 * the Field struct, resolve the field's type descriptor at link or class 2228 * init time, and then verify the type here. 2229 */ 2230HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT) 2231OP_END 2232 2233/* File: c/OP_IPUT_BOOLEAN.cpp */ 2234HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, ) 2235OP_END 2236 2237/* File: c/OP_IPUT_BYTE.cpp */ 2238HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, ) 2239OP_END 2240 2241/* File: c/OP_IPUT_CHAR.cpp */ 2242HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, ) 2243OP_END 2244 2245/* File: c/OP_IPUT_SHORT.cpp */ 2246HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, ) 2247OP_END 2248 2249/* File: c/OP_SGET.cpp */ 2250HANDLE_SGET_X(OP_SGET, "", Int, ) 2251OP_END 2252 2253/* File: c/OP_SGET_WIDE.cpp */ 2254HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE) 2255OP_END 2256 2257/* File: c/OP_SGET_OBJECT.cpp */ 2258HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT) 2259OP_END 2260 2261/* File: c/OP_SGET_BOOLEAN.cpp */ 2262HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, ) 2263OP_END 2264 2265/* File: c/OP_SGET_BYTE.cpp */ 2266HANDLE_SGET_X(OP_SGET_BYTE, "", Int, ) 2267OP_END 2268 2269/* File: c/OP_SGET_CHAR.cpp */ 2270HANDLE_SGET_X(OP_SGET_CHAR, "", Int, ) 2271OP_END 2272 2273/* File: c/OP_SGET_SHORT.cpp */ 2274HANDLE_SGET_X(OP_SGET_SHORT, "", Int, ) 2275OP_END 2276 2277/* File: c/OP_SPUT.cpp */ 2278HANDLE_SPUT_X(OP_SPUT, "", Int, ) 2279OP_END 2280 2281/* File: c/OP_SPUT_WIDE.cpp */ 2282HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE) 2283OP_END 2284 2285/* File: c/OP_SPUT_OBJECT.cpp */ 2286HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT) 2287OP_END 2288 2289/* File: c/OP_SPUT_BOOLEAN.cpp */ 2290HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, ) 2291OP_END 2292 2293/* File: c/OP_SPUT_BYTE.cpp */ 2294HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, ) 2295OP_END 2296 2297/* File: c/OP_SPUT_CHAR.cpp */ 2298HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, ) 2299OP_END 2300 2301/* File: c/OP_SPUT_SHORT.cpp */ 2302HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, ) 2303OP_END 2304 2305/* File: c/OP_INVOKE_VIRTUAL.cpp */ 2306HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2307 GOTO_invoke(invokeVirtual, false, false); 2308OP_END 2309 2310/* File: c/OP_INVOKE_SUPER.cpp */ 2311HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2312 GOTO_invoke(invokeSuper, false, false); 2313OP_END 2314 2315/* File: c/OP_INVOKE_DIRECT.cpp */ 2316HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2317 GOTO_invoke(invokeDirect, false, false); 2318OP_END 2319 2320/* File: c/OP_INVOKE_STATIC.cpp */ 2321HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2322 GOTO_invoke(invokeStatic, false, false); 2323OP_END 2324 2325/* File: c/OP_INVOKE_INTERFACE.cpp */ 2326HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2327 GOTO_invoke(invokeInterface, false, false); 2328OP_END 2329 2330/* File: c/OP_UNUSED_73.cpp */ 2331HANDLE_OPCODE(OP_UNUSED_73) 2332OP_END 2333 2334/* File: c/OP_INVOKE_VIRTUAL_RANGE.cpp */ 2335HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2336 GOTO_invoke(invokeVirtual, true, false); 2337OP_END 2338 2339/* File: c/OP_INVOKE_SUPER_RANGE.cpp */ 2340HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2341 GOTO_invoke(invokeSuper, true, false); 2342OP_END 2343 2344/* File: c/OP_INVOKE_DIRECT_RANGE.cpp */ 2345HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2346 GOTO_invoke(invokeDirect, true, false); 2347OP_END 2348 2349/* File: c/OP_INVOKE_STATIC_RANGE.cpp */ 2350HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2351 GOTO_invoke(invokeStatic, true, false); 2352OP_END 2353 2354/* File: c/OP_INVOKE_INTERFACE_RANGE.cpp */ 2355HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2356 GOTO_invoke(invokeInterface, true, false); 2357OP_END 2358 2359/* File: c/OP_UNUSED_79.cpp */ 2360HANDLE_OPCODE(OP_UNUSED_79) 2361OP_END 2362 2363/* File: c/OP_UNUSED_7A.cpp */ 2364HANDLE_OPCODE(OP_UNUSED_7A) 2365OP_END 2366 2367/* File: c/OP_NEG_INT.cpp */ 2368HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , ) 2369OP_END 2370 2371/* File: c/OP_NOT_INT.cpp */ 2372HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, ) 2373OP_END 2374 2375/* File: c/OP_NEG_LONG.cpp */ 2376HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE) 2377OP_END 2378 2379/* File: c/OP_NOT_LONG.cpp */ 2380HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE) 2381OP_END 2382 2383/* File: c/OP_NEG_FLOAT.cpp */ 2384HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT) 2385OP_END 2386 2387/* File: c/OP_NEG_DOUBLE.cpp */ 2388HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE) 2389OP_END 2390 2391/* File: c/OP_INT_TO_LONG.cpp */ 2392HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE) 2393OP_END 2394 2395/* File: c/OP_INT_TO_FLOAT.cpp */ 2396HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT) 2397OP_END 2398 2399/* File: c/OP_INT_TO_DOUBLE.cpp */ 2400HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE) 2401OP_END 2402 2403/* File: c/OP_LONG_TO_INT.cpp */ 2404HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT) 2405OP_END 2406 2407/* File: c/OP_LONG_TO_FLOAT.cpp */ 2408HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT) 2409OP_END 2410 2411/* File: c/OP_LONG_TO_DOUBLE.cpp */ 2412HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE) 2413OP_END 2414 2415/* File: c/OP_FLOAT_TO_INT.cpp */ 2416HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int", 2417 float, _FLOAT, s4, _INT) 2418OP_END 2419 2420/* File: c/OP_FLOAT_TO_LONG.cpp */ 2421HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long", 2422 float, _FLOAT, s8, _WIDE) 2423OP_END 2424 2425/* File: c/OP_FLOAT_TO_DOUBLE.cpp */ 2426HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE) 2427OP_END 2428 2429/* File: c/OP_DOUBLE_TO_INT.cpp */ 2430HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int", 2431 double, _DOUBLE, s4, _INT) 2432OP_END 2433 2434/* File: c/OP_DOUBLE_TO_LONG.cpp */ 2435HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long", 2436 double, _DOUBLE, s8, _WIDE) 2437OP_END 2438 2439/* File: c/OP_DOUBLE_TO_FLOAT.cpp */ 2440HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT) 2441OP_END 2442 2443/* File: c/OP_INT_TO_BYTE.cpp */ 2444HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1) 2445OP_END 2446 2447/* File: c/OP_INT_TO_CHAR.cpp */ 2448HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2) 2449OP_END 2450 2451/* File: c/OP_INT_TO_SHORT.cpp */ 2452HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */ 2453OP_END 2454 2455/* File: c/OP_ADD_INT.cpp */ 2456HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0) 2457OP_END 2458 2459/* File: c/OP_SUB_INT.cpp */ 2460HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0) 2461OP_END 2462 2463/* File: c/OP_MUL_INT.cpp */ 2464HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0) 2465OP_END 2466 2467/* File: c/OP_DIV_INT.cpp */ 2468HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1) 2469OP_END 2470 2471/* File: c/OP_REM_INT.cpp */ 2472HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2) 2473OP_END 2474 2475/* File: c/OP_AND_INT.cpp */ 2476HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0) 2477OP_END 2478 2479/* File: c/OP_OR_INT.cpp */ 2480HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0) 2481OP_END 2482 2483/* File: c/OP_XOR_INT.cpp */ 2484HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0) 2485OP_END 2486 2487/* File: c/OP_SHL_INT.cpp */ 2488HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<) 2489OP_END 2490 2491/* File: c/OP_SHR_INT.cpp */ 2492HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>) 2493OP_END 2494 2495/* File: c/OP_USHR_INT.cpp */ 2496HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>) 2497OP_END 2498 2499/* File: c/OP_ADD_LONG.cpp */ 2500HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0) 2501OP_END 2502 2503/* File: c/OP_SUB_LONG.cpp */ 2504HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0) 2505OP_END 2506 2507/* File: c/OP_MUL_LONG.cpp */ 2508HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0) 2509OP_END 2510 2511/* File: c/OP_DIV_LONG.cpp */ 2512HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1) 2513OP_END 2514 2515/* File: c/OP_REM_LONG.cpp */ 2516HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2) 2517OP_END 2518 2519/* File: c/OP_AND_LONG.cpp */ 2520HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0) 2521OP_END 2522 2523/* File: c/OP_OR_LONG.cpp */ 2524HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0) 2525OP_END 2526 2527/* File: c/OP_XOR_LONG.cpp */ 2528HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0) 2529OP_END 2530 2531/* File: c/OP_SHL_LONG.cpp */ 2532HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<) 2533OP_END 2534 2535/* File: c/OP_SHR_LONG.cpp */ 2536HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>) 2537OP_END 2538 2539/* File: c/OP_USHR_LONG.cpp */ 2540HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>) 2541OP_END 2542 2543/* File: c/OP_ADD_FLOAT.cpp */ 2544HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +) 2545OP_END 2546 2547/* File: c/OP_SUB_FLOAT.cpp */ 2548HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -) 2549OP_END 2550 2551/* File: c/OP_MUL_FLOAT.cpp */ 2552HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *) 2553OP_END 2554 2555/* File: c/OP_DIV_FLOAT.cpp */ 2556HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /) 2557OP_END 2558 2559/* File: c/OP_REM_FLOAT.cpp */ 2560HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/) 2561 { 2562 u2 srcRegs; 2563 vdst = INST_AA(inst); 2564 srcRegs = FETCH(1); 2565 vsrc1 = srcRegs & 0xff; 2566 vsrc2 = srcRegs >> 8; 2567 ILOGV("|%s-float v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2); 2568 SET_REGISTER_FLOAT(vdst, 2569 fmodf(GET_REGISTER_FLOAT(vsrc1), GET_REGISTER_FLOAT(vsrc2))); 2570 } 2571 FINISH(2); 2572OP_END 2573 2574/* File: c/OP_ADD_DOUBLE.cpp */ 2575HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +) 2576OP_END 2577 2578/* File: c/OP_SUB_DOUBLE.cpp */ 2579HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -) 2580OP_END 2581 2582/* File: c/OP_MUL_DOUBLE.cpp */ 2583HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *) 2584OP_END 2585 2586/* File: c/OP_DIV_DOUBLE.cpp */ 2587HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /) 2588OP_END 2589 2590/* File: c/OP_REM_DOUBLE.cpp */ 2591HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/) 2592 { 2593 u2 srcRegs; 2594 vdst = INST_AA(inst); 2595 srcRegs = FETCH(1); 2596 vsrc1 = srcRegs & 0xff; 2597 vsrc2 = srcRegs >> 8; 2598 ILOGV("|%s-double v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2); 2599 SET_REGISTER_DOUBLE(vdst, 2600 fmod(GET_REGISTER_DOUBLE(vsrc1), GET_REGISTER_DOUBLE(vsrc2))); 2601 } 2602 FINISH(2); 2603OP_END 2604 2605/* File: c/OP_ADD_INT_2ADDR.cpp */ 2606HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0) 2607OP_END 2608 2609/* File: c/OP_SUB_INT_2ADDR.cpp */ 2610HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0) 2611OP_END 2612 2613/* File: c/OP_MUL_INT_2ADDR.cpp */ 2614HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0) 2615OP_END 2616 2617/* File: c/OP_DIV_INT_2ADDR.cpp */ 2618HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1) 2619OP_END 2620 2621/* File: c/OP_REM_INT_2ADDR.cpp */ 2622HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2) 2623OP_END 2624 2625/* File: c/OP_AND_INT_2ADDR.cpp */ 2626HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0) 2627OP_END 2628 2629/* File: c/OP_OR_INT_2ADDR.cpp */ 2630HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0) 2631OP_END 2632 2633/* File: c/OP_XOR_INT_2ADDR.cpp */ 2634HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0) 2635OP_END 2636 2637/* File: c/OP_SHL_INT_2ADDR.cpp */ 2638HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<) 2639OP_END 2640 2641/* File: c/OP_SHR_INT_2ADDR.cpp */ 2642HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>) 2643OP_END 2644 2645/* File: c/OP_USHR_INT_2ADDR.cpp */ 2646HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>) 2647OP_END 2648 2649/* File: c/OP_ADD_LONG_2ADDR.cpp */ 2650HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0) 2651OP_END 2652 2653/* File: c/OP_SUB_LONG_2ADDR.cpp */ 2654HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0) 2655OP_END 2656 2657/* File: c/OP_MUL_LONG_2ADDR.cpp */ 2658HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0) 2659OP_END 2660 2661/* File: c/OP_DIV_LONG_2ADDR.cpp */ 2662HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1) 2663OP_END 2664 2665/* File: c/OP_REM_LONG_2ADDR.cpp */ 2666HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2) 2667OP_END 2668 2669/* File: c/OP_AND_LONG_2ADDR.cpp */ 2670HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0) 2671OP_END 2672 2673/* File: c/OP_OR_LONG_2ADDR.cpp */ 2674HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0) 2675OP_END 2676 2677/* File: c/OP_XOR_LONG_2ADDR.cpp */ 2678HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0) 2679OP_END 2680 2681/* File: c/OP_SHL_LONG_2ADDR.cpp */ 2682HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<) 2683OP_END 2684 2685/* File: c/OP_SHR_LONG_2ADDR.cpp */ 2686HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>) 2687OP_END 2688 2689/* File: c/OP_USHR_LONG_2ADDR.cpp */ 2690HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>) 2691OP_END 2692 2693/* File: c/OP_ADD_FLOAT_2ADDR.cpp */ 2694HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +) 2695OP_END 2696 2697/* File: c/OP_SUB_FLOAT_2ADDR.cpp */ 2698HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -) 2699OP_END 2700 2701/* File: c/OP_MUL_FLOAT_2ADDR.cpp */ 2702HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *) 2703OP_END 2704 2705/* File: c/OP_DIV_FLOAT_2ADDR.cpp */ 2706HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /) 2707OP_END 2708 2709/* File: c/OP_REM_FLOAT_2ADDR.cpp */ 2710HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/) 2711 vdst = INST_A(inst); 2712 vsrc1 = INST_B(inst); 2713 ILOGV("|%s-float-2addr v%d,v%d", "mod", vdst, vsrc1); 2714 SET_REGISTER_FLOAT(vdst, 2715 fmodf(GET_REGISTER_FLOAT(vdst), GET_REGISTER_FLOAT(vsrc1))); 2716 FINISH(1); 2717OP_END 2718 2719/* File: c/OP_ADD_DOUBLE_2ADDR.cpp */ 2720HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +) 2721OP_END 2722 2723/* File: c/OP_SUB_DOUBLE_2ADDR.cpp */ 2724HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -) 2725OP_END 2726 2727/* File: c/OP_MUL_DOUBLE_2ADDR.cpp */ 2728HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *) 2729OP_END 2730 2731/* File: c/OP_DIV_DOUBLE_2ADDR.cpp */ 2732HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /) 2733OP_END 2734 2735/* File: c/OP_REM_DOUBLE_2ADDR.cpp */ 2736HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/) 2737 vdst = INST_A(inst); 2738 vsrc1 = INST_B(inst); 2739 ILOGV("|%s-double-2addr v%d,v%d", "mod", vdst, vsrc1); 2740 SET_REGISTER_DOUBLE(vdst, 2741 fmod(GET_REGISTER_DOUBLE(vdst), GET_REGISTER_DOUBLE(vsrc1))); 2742 FINISH(1); 2743OP_END 2744 2745/* File: c/OP_ADD_INT_LIT16.cpp */ 2746HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0) 2747OP_END 2748 2749/* File: c/OP_RSUB_INT.cpp */ 2750HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/) 2751 { 2752 vdst = INST_A(inst); 2753 vsrc1 = INST_B(inst); 2754 vsrc2 = FETCH(1); 2755 ILOGV("|rsub-int v%d,v%d,#+0x%04x", vdst, vsrc1, vsrc2); 2756 SET_REGISTER(vdst, (s2) vsrc2 - (s4) GET_REGISTER(vsrc1)); 2757 } 2758 FINISH(2); 2759OP_END 2760 2761/* File: c/OP_MUL_INT_LIT16.cpp */ 2762HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0) 2763OP_END 2764 2765/* File: c/OP_DIV_INT_LIT16.cpp */ 2766HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1) 2767OP_END 2768 2769/* File: c/OP_REM_INT_LIT16.cpp */ 2770HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2) 2771OP_END 2772 2773/* File: c/OP_AND_INT_LIT16.cpp */ 2774HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0) 2775OP_END 2776 2777/* File: c/OP_OR_INT_LIT16.cpp */ 2778HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0) 2779OP_END 2780 2781/* File: c/OP_XOR_INT_LIT16.cpp */ 2782HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0) 2783OP_END 2784 2785/* File: c/OP_ADD_INT_LIT8.cpp */ 2786HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0) 2787OP_END 2788 2789/* File: c/OP_RSUB_INT_LIT8.cpp */ 2790HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/) 2791 { 2792 u2 litInfo; 2793 vdst = INST_AA(inst); 2794 litInfo = FETCH(1); 2795 vsrc1 = litInfo & 0xff; 2796 vsrc2 = litInfo >> 8; 2797 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", "rsub", vdst, vsrc1, vsrc2); 2798 SET_REGISTER(vdst, (s1) vsrc2 - (s4) GET_REGISTER(vsrc1)); 2799 } 2800 FINISH(2); 2801OP_END 2802 2803/* File: c/OP_MUL_INT_LIT8.cpp */ 2804HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0) 2805OP_END 2806 2807/* File: c/OP_DIV_INT_LIT8.cpp */ 2808HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1) 2809OP_END 2810 2811/* File: c/OP_REM_INT_LIT8.cpp */ 2812HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2) 2813OP_END 2814 2815/* File: c/OP_AND_INT_LIT8.cpp */ 2816HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0) 2817OP_END 2818 2819/* File: c/OP_OR_INT_LIT8.cpp */ 2820HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0) 2821OP_END 2822 2823/* File: c/OP_XOR_INT_LIT8.cpp */ 2824HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0) 2825OP_END 2826 2827/* File: c/OP_SHL_INT_LIT8.cpp */ 2828HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<) 2829OP_END 2830 2831/* File: c/OP_SHR_INT_LIT8.cpp */ 2832HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>) 2833OP_END 2834 2835/* File: c/OP_USHR_INT_LIT8.cpp */ 2836HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>) 2837OP_END 2838 2839/* File: c/OP_IGET_VOLATILE.cpp */ 2840HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) 2841OP_END 2842 2843/* File: c/OP_IPUT_VOLATILE.cpp */ 2844HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) 2845OP_END 2846 2847/* File: c/OP_SGET_VOLATILE.cpp */ 2848HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) 2849OP_END 2850 2851/* File: c/OP_SPUT_VOLATILE.cpp */ 2852HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) 2853OP_END 2854 2855/* File: c/OP_IGET_OBJECT_VOLATILE.cpp */ 2856HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 2857OP_END 2858 2859/* File: c/OP_IGET_WIDE_VOLATILE.cpp */ 2860HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2861OP_END 2862 2863/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */ 2864HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2865OP_END 2866 2867/* File: c/OP_SGET_WIDE_VOLATILE.cpp */ 2868HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2869OP_END 2870 2871/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */ 2872HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2873OP_END 2874 2875/* File: c/OP_BREAKPOINT.cpp */ 2876HANDLE_OPCODE(OP_BREAKPOINT) 2877 { 2878 /* 2879 * Restart this instruction with the original opcode. We do 2880 * this by simply jumping to the handler. 2881 * 2882 * It's probably not necessary to update "inst", but we do it 2883 * for the sake of anything that needs to do disambiguation in a 2884 * common handler with INST_INST. 2885 * 2886 * The breakpoint itself is handled over in updateDebugger(), 2887 * because we need to detect other events (method entry, single 2888 * step) and report them in the same event packet, and we're not 2889 * yet handling those through breakpoint instructions. By the 2890 * time we get here, the breakpoint has already been handled and 2891 * the thread resumed. 2892 */ 2893 u1 originalOpcode = dvmGetOriginalOpcode(pc); 2894 LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)", originalOpcode, inst, 2895 INST_REPLACE_OP(inst, originalOpcode)); 2896 inst = INST_REPLACE_OP(inst, originalOpcode); 2897 FINISH_BKPT(originalOpcode); 2898 } 2899OP_END 2900 2901/* File: c/OP_THROW_VERIFICATION_ERROR.cpp */ 2902HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR) 2903 EXPORT_PC(); 2904 vsrc1 = INST_AA(inst); 2905 ref = FETCH(1); /* class/field/method ref */ 2906 dvmThrowVerificationError(curMethod, vsrc1, ref); 2907 GOTO_exceptionThrown(); 2908OP_END 2909 2910/* File: c/OP_EXECUTE_INLINE.cpp */ 2911HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/) 2912 { 2913 /* 2914 * This has the same form as other method calls, but we ignore 2915 * the 5th argument (vA). This is chiefly because the first four 2916 * arguments to a function on ARM are in registers. 2917 * 2918 * We only set the arguments that are actually used, leaving 2919 * the rest uninitialized. We're assuming that, if the method 2920 * needs them, they'll be specified in the call. 2921 * 2922 * However, this annoys gcc when optimizations are enabled, 2923 * causing a "may be used uninitialized" warning. Quieting 2924 * the warnings incurs a slight penalty (5%: 373ns vs. 393ns 2925 * on empty method). Note that valgrind is perfectly happy 2926 * either way as the uninitialiezd values are never actually 2927 * used. 2928 */ 2929 u4 arg0, arg1, arg2, arg3; 2930 arg0 = arg1 = arg2 = arg3 = 0; 2931 2932 EXPORT_PC(); 2933 2934 vsrc1 = INST_B(inst); /* #of args */ 2935 ref = FETCH(1); /* inline call "ref" */ 2936 vdst = FETCH(2); /* 0-4 register indices */ 2937 ILOGV("|execute-inline args=%d @%d {regs=0x%04x}", 2938 vsrc1, ref, vdst); 2939 2940 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear 2941 assert(vsrc1 <= 4); 2942 2943 switch (vsrc1) { 2944 case 4: 2945 arg3 = GET_REGISTER(vdst >> 12); 2946 /* fall through */ 2947 case 3: 2948 arg2 = GET_REGISTER((vdst & 0x0f00) >> 8); 2949 /* fall through */ 2950 case 2: 2951 arg1 = GET_REGISTER((vdst & 0x00f0) >> 4); 2952 /* fall through */ 2953 case 1: 2954 arg0 = GET_REGISTER(vdst & 0x0f); 2955 /* fall through */ 2956 default: // case 0 2957 ; 2958 } 2959 2960 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 2961 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref)) 2962 GOTO_exceptionThrown(); 2963 } else { 2964 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)) 2965 GOTO_exceptionThrown(); 2966 } 2967 } 2968 FINISH(3); 2969OP_END 2970 2971/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */ 2972HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/) 2973 { 2974 u4 arg0, arg1, arg2, arg3; 2975 arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */ 2976 2977 EXPORT_PC(); 2978 2979 vsrc1 = INST_AA(inst); /* #of args */ 2980 ref = FETCH(1); /* inline call "ref" */ 2981 vdst = FETCH(2); /* range base */ 2982 ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}", 2983 vsrc1, ref, vdst, vdst+vsrc1-1); 2984 2985 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear 2986 assert(vsrc1 <= 4); 2987 2988 switch (vsrc1) { 2989 case 4: 2990 arg3 = GET_REGISTER(vdst+3); 2991 /* fall through */ 2992 case 3: 2993 arg2 = GET_REGISTER(vdst+2); 2994 /* fall through */ 2995 case 2: 2996 arg1 = GET_REGISTER(vdst+1); 2997 /* fall through */ 2998 case 1: 2999 arg0 = GET_REGISTER(vdst+0); 3000 /* fall through */ 3001 default: // case 0 3002 ; 3003 } 3004 3005 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 3006 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref)) 3007 GOTO_exceptionThrown(); 3008 } else { 3009 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)) 3010 GOTO_exceptionThrown(); 3011 } 3012 } 3013 FINISH(3); 3014OP_END 3015 3016/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */ 3017HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 3018 { 3019 Object* obj; 3020 3021 vsrc1 = FETCH(2); /* reg number of "this" pointer */ 3022 obj = GET_REGISTER_AS_OBJECT(vsrc1); 3023 3024 if (!checkForNullExportPC(obj, fp, pc)) 3025 GOTO_exceptionThrown(); 3026 3027 /* 3028 * The object should be marked "finalizable" when Object.<init> 3029 * completes normally. We're going to assume it does complete 3030 * (by virtue of being nothing but a return-void) and set it now. 3031 */ 3032 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) { 3033 EXPORT_PC(); 3034 dvmSetFinalizable(obj); 3035 if (dvmGetException(self)) 3036 GOTO_exceptionThrown(); 3037 } 3038 3039 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 3040 /* behave like OP_INVOKE_DIRECT_RANGE */ 3041 GOTO_invoke(invokeDirect, true, false); 3042 } 3043 FINISH(3); 3044 } 3045OP_END 3046 3047/* File: c/OP_RETURN_VOID_BARRIER.cpp */ 3048HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/) 3049 ILOGV("|return-void"); 3050#ifndef NDEBUG 3051 retval.j = 0xababababULL; /* placate valgrind */ 3052#endif 3053 ANDROID_MEMBAR_STORE(); 3054 GOTO_returnFromMethod(); 3055OP_END 3056 3057/* File: c/OP_IGET_QUICK.cpp */ 3058HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, ) 3059OP_END 3060 3061/* File: c/OP_IGET_WIDE_QUICK.cpp */ 3062HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE) 3063OP_END 3064 3065/* File: c/OP_IGET_OBJECT_QUICK.cpp */ 3066HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT) 3067OP_END 3068 3069/* File: c/OP_IPUT_QUICK.cpp */ 3070HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, ) 3071OP_END 3072 3073/* File: c/OP_IPUT_WIDE_QUICK.cpp */ 3074HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE) 3075OP_END 3076 3077/* File: c/OP_IPUT_OBJECT_QUICK.cpp */ 3078HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT) 3079OP_END 3080 3081/* File: c/OP_INVOKE_VIRTUAL_QUICK.cpp */ 3082HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 3083 GOTO_invoke(invokeVirtualQuick, false, false); 3084OP_END 3085 3086/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp */ 3087HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 3088 GOTO_invoke(invokeVirtualQuick, true, false); 3089OP_END 3090 3091/* File: c/OP_INVOKE_SUPER_QUICK.cpp */ 3092HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 3093 GOTO_invoke(invokeSuperQuick, false, false); 3094OP_END 3095 3096/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.cpp */ 3097HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 3098 GOTO_invoke(invokeSuperQuick, true, false); 3099OP_END 3100 3101/* File: c/OP_IPUT_OBJECT_VOLATILE.cpp */ 3102HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 3103OP_END 3104 3105/* File: c/OP_SGET_OBJECT_VOLATILE.cpp */ 3106HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 3107OP_END 3108 3109/* File: c/OP_SPUT_OBJECT_VOLATILE.cpp */ 3110HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 3111OP_END 3112 3113/* File: c/OP_DISPATCH_FF.cpp */ 3114HANDLE_OPCODE(OP_DISPATCH_FF) 3115 /* 3116 * Indicates extended opcode. Use next 8 bits to choose where to branch. 3117 */ 3118 DISPATCH_EXTENDED(INST_AA(inst)); 3119OP_END 3120 3121/* File: c/OP_CONST_CLASS_JUMBO.cpp */ 3122HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/) 3123 { 3124 ClassObject* clazz; 3125 3126 ref = FETCH(1) | (u4)FETCH(2) << 16; 3127 vdst = FETCH(3); 3128 ILOGV("|const-class/jumbo v%d class@0x%08x", vdst, ref); 3129 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3130 if (clazz == NULL) { 3131 EXPORT_PC(); 3132 clazz = dvmResolveClass(curMethod->clazz, ref, true); 3133 if (clazz == NULL) 3134 GOTO_exceptionThrown(); 3135 } 3136 SET_REGISTER(vdst, (u4) clazz); 3137 } 3138 FINISH(4); 3139OP_END 3140 3141/* File: c/OP_CHECK_CAST_JUMBO.cpp */ 3142HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/) 3143 { 3144 ClassObject* clazz; 3145 Object* obj; 3146 3147 EXPORT_PC(); 3148 3149 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */ 3150 vsrc1 = FETCH(3); 3151 ILOGV("|check-cast/jumbo v%d,class@0x%08x", vsrc1, ref); 3152 3153 obj = (Object*)GET_REGISTER(vsrc1); 3154 if (obj != NULL) { 3155#if defined(WITH_EXTRA_OBJECT_VALIDATION) 3156 if (!checkForNull(obj)) 3157 GOTO_exceptionThrown(); 3158#endif 3159 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3160 if (clazz == NULL) { 3161 clazz = dvmResolveClass(curMethod->clazz, ref, false); 3162 if (clazz == NULL) 3163 GOTO_exceptionThrown(); 3164 } 3165 if (!dvmInstanceof(obj->clazz, clazz)) { 3166 dvmThrowClassCastException(obj->clazz, clazz); 3167 GOTO_exceptionThrown(); 3168 } 3169 } 3170 } 3171 FINISH(4); 3172OP_END 3173 3174/* File: c/OP_INSTANCE_OF_JUMBO.cpp */ 3175HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/) 3176 { 3177 ClassObject* clazz; 3178 Object* obj; 3179 3180 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */ 3181 vdst = FETCH(3); 3182 vsrc1 = FETCH(4); /* object to check */ 3183 ILOGV("|instance-of/jumbo v%d,v%d,class@0x%08x", vdst, vsrc1, ref); 3184 3185 obj = (Object*)GET_REGISTER(vsrc1); 3186 if (obj == NULL) { 3187 SET_REGISTER(vdst, 0); 3188 } else { 3189#if defined(WITH_EXTRA_OBJECT_VALIDATION) 3190 if (!checkForNullExportPC(obj, fp, pc)) 3191 GOTO_exceptionThrown(); 3192#endif 3193 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3194 if (clazz == NULL) { 3195 EXPORT_PC(); 3196 clazz = dvmResolveClass(curMethod->clazz, ref, true); 3197 if (clazz == NULL) 3198 GOTO_exceptionThrown(); 3199 } 3200 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz)); 3201 } 3202 } 3203 FINISH(5); 3204OP_END 3205 3206/* File: c/OP_NEW_INSTANCE_JUMBO.cpp */ 3207HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/) 3208 { 3209 ClassObject* clazz; 3210 Object* newObj; 3211 3212 EXPORT_PC(); 3213 3214 ref = FETCH(1) | (u4)FETCH(2) << 16; 3215 vdst = FETCH(3); 3216 ILOGV("|new-instance/jumbo v%d,class@0x%08x", vdst, ref); 3217 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3218 if (clazz == NULL) { 3219 clazz = dvmResolveClass(curMethod->clazz, ref, false); 3220 if (clazz == NULL) 3221 GOTO_exceptionThrown(); 3222 } 3223 3224 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) 3225 GOTO_exceptionThrown(); 3226 3227#if defined(WITH_JIT) 3228 /* 3229 * The JIT needs dvmDexGetResolvedClass() to return non-null. 3230 * Since we use the portable interpreter to build the trace, this extra 3231 * check is not needed for mterp. 3232 */ 3233 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 3234 (!dvmDexGetResolvedClass(methodClassDex, ref))) { 3235 /* Class initialization is still ongoing - end the trace */ 3236 dvmJitEndTraceSelect(self,pc); 3237 } 3238#endif 3239 3240 /* 3241 * Verifier now tests for interface/abstract class. 3242 */ 3243 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) { 3244 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError, 3245 // clazz->descriptor); 3246 // GOTO_exceptionThrown(); 3247 //} 3248 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK); 3249 if (newObj == NULL) 3250 GOTO_exceptionThrown(); 3251 SET_REGISTER(vdst, (u4) newObj); 3252 } 3253 FINISH(4); 3254OP_END 3255 3256/* File: c/OP_NEW_ARRAY_JUMBO.cpp */ 3257HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/) 3258 { 3259 ClassObject* arrayClass; 3260 ArrayObject* newArray; 3261 s4 length; 3262 3263 EXPORT_PC(); 3264 3265 ref = FETCH(1) | (u4)FETCH(2) << 16; 3266 vdst = FETCH(3); 3267 vsrc1 = FETCH(4); /* length reg */ 3268 ILOGV("|new-array/jumbo v%d,v%d,class@0x%08x (%d elements)", 3269 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1)); 3270 length = (s4) GET_REGISTER(vsrc1); 3271 if (length < 0) { 3272 dvmThrowNegativeArraySizeException(length); 3273 GOTO_exceptionThrown(); 3274 } 3275 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 3276 if (arrayClass == NULL) { 3277 arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 3278 if (arrayClass == NULL) 3279 GOTO_exceptionThrown(); 3280 } 3281 /* verifier guarantees this is an array class */ 3282 assert(dvmIsArrayClass(arrayClass)); 3283 assert(dvmIsClassInitialized(arrayClass)); 3284 3285 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK); 3286 if (newArray == NULL) 3287 GOTO_exceptionThrown(); 3288 SET_REGISTER(vdst, (u4) newArray); 3289 } 3290 FINISH(5); 3291OP_END 3292 3293/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.cpp */ 3294HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/) 3295 GOTO_invoke(filledNewArray, true, true); 3296OP_END 3297 3298/* File: c/OP_IGET_JUMBO.cpp */ 3299HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, ) 3300OP_END 3301 3302/* File: c/OP_IGET_WIDE_JUMBO.cpp */ 3303HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE) 3304OP_END 3305 3306/* File: c/OP_IGET_OBJECT_JUMBO.cpp */ 3307HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3308OP_END 3309 3310/* File: c/OP_IGET_BOOLEAN_JUMBO.cpp */ 3311HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, ) 3312OP_END 3313 3314/* File: c/OP_IGET_BYTE_JUMBO.cpp */ 3315HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, ) 3316OP_END 3317 3318/* File: c/OP_IGET_CHAR_JUMBO.cpp */ 3319HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, ) 3320OP_END 3321 3322/* File: c/OP_IGET_SHORT_JUMBO.cpp */ 3323HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, ) 3324OP_END 3325 3326/* File: c/OP_IPUT_JUMBO.cpp */ 3327HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, ) 3328OP_END 3329 3330/* File: c/OP_IPUT_WIDE_JUMBO.cpp */ 3331HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE) 3332OP_END 3333 3334/* File: c/OP_IPUT_OBJECT_JUMBO.cpp */ 3335/* 3336 * The VM spec says we should verify that the reference being stored into 3337 * the field is assignment compatible. In practice, many popular VMs don't 3338 * do this because it slows down a very common operation. It's not so bad 3339 * for us, since "dexopt" quickens it whenever possible, but it's still an 3340 * issue. 3341 * 3342 * To make this spec-complaint, we'd need to add a ClassObject pointer to 3343 * the Field struct, resolve the field's type descriptor at link or class 3344 * init time, and then verify the type here. 3345 */ 3346HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3347OP_END 3348 3349/* File: c/OP_IPUT_BOOLEAN_JUMBO.cpp */ 3350HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, ) 3351OP_END 3352 3353/* File: c/OP_IPUT_BYTE_JUMBO.cpp */ 3354HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, ) 3355OP_END 3356 3357/* File: c/OP_IPUT_CHAR_JUMBO.cpp */ 3358HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, ) 3359OP_END 3360 3361/* File: c/OP_IPUT_SHORT_JUMBO.cpp */ 3362HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, ) 3363OP_END 3364 3365/* File: c/OP_SGET_JUMBO.cpp */ 3366HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, ) 3367OP_END 3368 3369/* File: c/OP_SGET_WIDE_JUMBO.cpp */ 3370HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE) 3371OP_END 3372 3373/* File: c/OP_SGET_OBJECT_JUMBO.cpp */ 3374HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3375OP_END 3376 3377/* File: c/OP_SGET_BOOLEAN_JUMBO.cpp */ 3378HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, ) 3379OP_END 3380 3381/* File: c/OP_SGET_BYTE_JUMBO.cpp */ 3382HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, ) 3383OP_END 3384 3385/* File: c/OP_SGET_CHAR_JUMBO.cpp */ 3386HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, ) 3387OP_END 3388 3389/* File: c/OP_SGET_SHORT_JUMBO.cpp */ 3390HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, ) 3391OP_END 3392 3393/* File: c/OP_SPUT_JUMBO.cpp */ 3394HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, ) 3395OP_END 3396 3397/* File: c/OP_SPUT_WIDE_JUMBO.cpp */ 3398HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE) 3399OP_END 3400 3401/* File: c/OP_SPUT_OBJECT_JUMBO.cpp */ 3402HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3403OP_END 3404 3405/* File: c/OP_SPUT_BOOLEAN_JUMBO.cpp */ 3406HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, ) 3407OP_END 3408 3409/* File: c/OP_SPUT_BYTE_JUMBO.cpp */ 3410HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, ) 3411OP_END 3412 3413/* File: c/OP_SPUT_CHAR_JUMBO.cpp */ 3414HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, ) 3415OP_END 3416 3417/* File: c/OP_SPUT_SHORT_JUMBO.cpp */ 3418HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, ) 3419OP_END 3420 3421/* File: c/OP_INVOKE_VIRTUAL_JUMBO.cpp */ 3422HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3423 GOTO_invoke(invokeVirtual, true, true); 3424OP_END 3425 3426/* File: c/OP_INVOKE_SUPER_JUMBO.cpp */ 3427HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3428 GOTO_invoke(invokeSuper, true, true); 3429OP_END 3430 3431/* File: c/OP_INVOKE_DIRECT_JUMBO.cpp */ 3432HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3433 GOTO_invoke(invokeDirect, true, true); 3434OP_END 3435 3436/* File: c/OP_INVOKE_STATIC_JUMBO.cpp */ 3437HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3438 GOTO_invoke(invokeStatic, true, true); 3439OP_END 3440 3441/* File: c/OP_INVOKE_INTERFACE_JUMBO.cpp */ 3442HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3443 GOTO_invoke(invokeInterface, true, true); 3444OP_END 3445 3446/* File: c/OP_UNUSED_27FF.cpp */ 3447HANDLE_OPCODE(OP_UNUSED_27FF) 3448OP_END 3449 3450/* File: c/OP_UNUSED_28FF.cpp */ 3451HANDLE_OPCODE(OP_UNUSED_28FF) 3452OP_END 3453 3454/* File: c/OP_UNUSED_29FF.cpp */ 3455HANDLE_OPCODE(OP_UNUSED_29FF) 3456OP_END 3457 3458/* File: c/OP_UNUSED_2AFF.cpp */ 3459HANDLE_OPCODE(OP_UNUSED_2AFF) 3460OP_END 3461 3462/* File: c/OP_UNUSED_2BFF.cpp */ 3463HANDLE_OPCODE(OP_UNUSED_2BFF) 3464OP_END 3465 3466/* File: c/OP_UNUSED_2CFF.cpp */ 3467HANDLE_OPCODE(OP_UNUSED_2CFF) 3468OP_END 3469 3470/* File: c/OP_UNUSED_2DFF.cpp */ 3471HANDLE_OPCODE(OP_UNUSED_2DFF) 3472OP_END 3473 3474/* File: c/OP_UNUSED_2EFF.cpp */ 3475HANDLE_OPCODE(OP_UNUSED_2EFF) 3476OP_END 3477 3478/* File: c/OP_UNUSED_2FFF.cpp */ 3479HANDLE_OPCODE(OP_UNUSED_2FFF) 3480OP_END 3481 3482/* File: c/OP_UNUSED_30FF.cpp */ 3483HANDLE_OPCODE(OP_UNUSED_30FF) 3484OP_END 3485 3486/* File: c/OP_UNUSED_31FF.cpp */ 3487HANDLE_OPCODE(OP_UNUSED_31FF) 3488OP_END 3489 3490/* File: c/OP_UNUSED_32FF.cpp */ 3491HANDLE_OPCODE(OP_UNUSED_32FF) 3492OP_END 3493 3494/* File: c/OP_UNUSED_33FF.cpp */ 3495HANDLE_OPCODE(OP_UNUSED_33FF) 3496OP_END 3497 3498/* File: c/OP_UNUSED_34FF.cpp */ 3499HANDLE_OPCODE(OP_UNUSED_34FF) 3500OP_END 3501 3502/* File: c/OP_UNUSED_35FF.cpp */ 3503HANDLE_OPCODE(OP_UNUSED_35FF) 3504OP_END 3505 3506/* File: c/OP_UNUSED_36FF.cpp */ 3507HANDLE_OPCODE(OP_UNUSED_36FF) 3508OP_END 3509 3510/* File: c/OP_UNUSED_37FF.cpp */ 3511HANDLE_OPCODE(OP_UNUSED_37FF) 3512OP_END 3513 3514/* File: c/OP_UNUSED_38FF.cpp */ 3515HANDLE_OPCODE(OP_UNUSED_38FF) 3516OP_END 3517 3518/* File: c/OP_UNUSED_39FF.cpp */ 3519HANDLE_OPCODE(OP_UNUSED_39FF) 3520OP_END 3521 3522/* File: c/OP_UNUSED_3AFF.cpp */ 3523HANDLE_OPCODE(OP_UNUSED_3AFF) 3524OP_END 3525 3526/* File: c/OP_UNUSED_3BFF.cpp */ 3527HANDLE_OPCODE(OP_UNUSED_3BFF) 3528OP_END 3529 3530/* File: c/OP_UNUSED_3CFF.cpp */ 3531HANDLE_OPCODE(OP_UNUSED_3CFF) 3532OP_END 3533 3534/* File: c/OP_UNUSED_3DFF.cpp */ 3535HANDLE_OPCODE(OP_UNUSED_3DFF) 3536OP_END 3537 3538/* File: c/OP_UNUSED_3EFF.cpp */ 3539HANDLE_OPCODE(OP_UNUSED_3EFF) 3540OP_END 3541 3542/* File: c/OP_UNUSED_3FFF.cpp */ 3543HANDLE_OPCODE(OP_UNUSED_3FFF) 3544OP_END 3545 3546/* File: c/OP_UNUSED_40FF.cpp */ 3547HANDLE_OPCODE(OP_UNUSED_40FF) 3548OP_END 3549 3550/* File: c/OP_UNUSED_41FF.cpp */ 3551HANDLE_OPCODE(OP_UNUSED_41FF) 3552OP_END 3553 3554/* File: c/OP_UNUSED_42FF.cpp */ 3555HANDLE_OPCODE(OP_UNUSED_42FF) 3556OP_END 3557 3558/* File: c/OP_UNUSED_43FF.cpp */ 3559HANDLE_OPCODE(OP_UNUSED_43FF) 3560OP_END 3561 3562/* File: c/OP_UNUSED_44FF.cpp */ 3563HANDLE_OPCODE(OP_UNUSED_44FF) 3564OP_END 3565 3566/* File: c/OP_UNUSED_45FF.cpp */ 3567HANDLE_OPCODE(OP_UNUSED_45FF) 3568OP_END 3569 3570/* File: c/OP_UNUSED_46FF.cpp */ 3571HANDLE_OPCODE(OP_UNUSED_46FF) 3572OP_END 3573 3574/* File: c/OP_UNUSED_47FF.cpp */ 3575HANDLE_OPCODE(OP_UNUSED_47FF) 3576OP_END 3577 3578/* File: c/OP_UNUSED_48FF.cpp */ 3579HANDLE_OPCODE(OP_UNUSED_48FF) 3580OP_END 3581 3582/* File: c/OP_UNUSED_49FF.cpp */ 3583HANDLE_OPCODE(OP_UNUSED_49FF) 3584OP_END 3585 3586/* File: c/OP_UNUSED_4AFF.cpp */ 3587HANDLE_OPCODE(OP_UNUSED_4AFF) 3588OP_END 3589 3590/* File: c/OP_UNUSED_4BFF.cpp */ 3591HANDLE_OPCODE(OP_UNUSED_4BFF) 3592OP_END 3593 3594/* File: c/OP_UNUSED_4CFF.cpp */ 3595HANDLE_OPCODE(OP_UNUSED_4CFF) 3596OP_END 3597 3598/* File: c/OP_UNUSED_4DFF.cpp */ 3599HANDLE_OPCODE(OP_UNUSED_4DFF) 3600OP_END 3601 3602/* File: c/OP_UNUSED_4EFF.cpp */ 3603HANDLE_OPCODE(OP_UNUSED_4EFF) 3604OP_END 3605 3606/* File: c/OP_UNUSED_4FFF.cpp */ 3607HANDLE_OPCODE(OP_UNUSED_4FFF) 3608OP_END 3609 3610/* File: c/OP_UNUSED_50FF.cpp */ 3611HANDLE_OPCODE(OP_UNUSED_50FF) 3612OP_END 3613 3614/* File: c/OP_UNUSED_51FF.cpp */ 3615HANDLE_OPCODE(OP_UNUSED_51FF) 3616OP_END 3617 3618/* File: c/OP_UNUSED_52FF.cpp */ 3619HANDLE_OPCODE(OP_UNUSED_52FF) 3620OP_END 3621 3622/* File: c/OP_UNUSED_53FF.cpp */ 3623HANDLE_OPCODE(OP_UNUSED_53FF) 3624OP_END 3625 3626/* File: c/OP_UNUSED_54FF.cpp */ 3627HANDLE_OPCODE(OP_UNUSED_54FF) 3628OP_END 3629 3630/* File: c/OP_UNUSED_55FF.cpp */ 3631HANDLE_OPCODE(OP_UNUSED_55FF) 3632OP_END 3633 3634/* File: c/OP_UNUSED_56FF.cpp */ 3635HANDLE_OPCODE(OP_UNUSED_56FF) 3636OP_END 3637 3638/* File: c/OP_UNUSED_57FF.cpp */ 3639HANDLE_OPCODE(OP_UNUSED_57FF) 3640OP_END 3641 3642/* File: c/OP_UNUSED_58FF.cpp */ 3643HANDLE_OPCODE(OP_UNUSED_58FF) 3644OP_END 3645 3646/* File: c/OP_UNUSED_59FF.cpp */ 3647HANDLE_OPCODE(OP_UNUSED_59FF) 3648OP_END 3649 3650/* File: c/OP_UNUSED_5AFF.cpp */ 3651HANDLE_OPCODE(OP_UNUSED_5AFF) 3652OP_END 3653 3654/* File: c/OP_UNUSED_5BFF.cpp */ 3655HANDLE_OPCODE(OP_UNUSED_5BFF) 3656OP_END 3657 3658/* File: c/OP_UNUSED_5CFF.cpp */ 3659HANDLE_OPCODE(OP_UNUSED_5CFF) 3660OP_END 3661 3662/* File: c/OP_UNUSED_5DFF.cpp */ 3663HANDLE_OPCODE(OP_UNUSED_5DFF) 3664OP_END 3665 3666/* File: c/OP_UNUSED_5EFF.cpp */ 3667HANDLE_OPCODE(OP_UNUSED_5EFF) 3668OP_END 3669 3670/* File: c/OP_UNUSED_5FFF.cpp */ 3671HANDLE_OPCODE(OP_UNUSED_5FFF) 3672OP_END 3673 3674/* File: c/OP_UNUSED_60FF.cpp */ 3675HANDLE_OPCODE(OP_UNUSED_60FF) 3676OP_END 3677 3678/* File: c/OP_UNUSED_61FF.cpp */ 3679HANDLE_OPCODE(OP_UNUSED_61FF) 3680OP_END 3681 3682/* File: c/OP_UNUSED_62FF.cpp */ 3683HANDLE_OPCODE(OP_UNUSED_62FF) 3684OP_END 3685 3686/* File: c/OP_UNUSED_63FF.cpp */ 3687HANDLE_OPCODE(OP_UNUSED_63FF) 3688OP_END 3689 3690/* File: c/OP_UNUSED_64FF.cpp */ 3691HANDLE_OPCODE(OP_UNUSED_64FF) 3692OP_END 3693 3694/* File: c/OP_UNUSED_65FF.cpp */ 3695HANDLE_OPCODE(OP_UNUSED_65FF) 3696OP_END 3697 3698/* File: c/OP_UNUSED_66FF.cpp */ 3699HANDLE_OPCODE(OP_UNUSED_66FF) 3700OP_END 3701 3702/* File: c/OP_UNUSED_67FF.cpp */ 3703HANDLE_OPCODE(OP_UNUSED_67FF) 3704OP_END 3705 3706/* File: c/OP_UNUSED_68FF.cpp */ 3707HANDLE_OPCODE(OP_UNUSED_68FF) 3708OP_END 3709 3710/* File: c/OP_UNUSED_69FF.cpp */ 3711HANDLE_OPCODE(OP_UNUSED_69FF) 3712OP_END 3713 3714/* File: c/OP_UNUSED_6AFF.cpp */ 3715HANDLE_OPCODE(OP_UNUSED_6AFF) 3716OP_END 3717 3718/* File: c/OP_UNUSED_6BFF.cpp */ 3719HANDLE_OPCODE(OP_UNUSED_6BFF) 3720OP_END 3721 3722/* File: c/OP_UNUSED_6CFF.cpp */ 3723HANDLE_OPCODE(OP_UNUSED_6CFF) 3724OP_END 3725 3726/* File: c/OP_UNUSED_6DFF.cpp */ 3727HANDLE_OPCODE(OP_UNUSED_6DFF) 3728OP_END 3729 3730/* File: c/OP_UNUSED_6EFF.cpp */ 3731HANDLE_OPCODE(OP_UNUSED_6EFF) 3732OP_END 3733 3734/* File: c/OP_UNUSED_6FFF.cpp */ 3735HANDLE_OPCODE(OP_UNUSED_6FFF) 3736OP_END 3737 3738/* File: c/OP_UNUSED_70FF.cpp */ 3739HANDLE_OPCODE(OP_UNUSED_70FF) 3740OP_END 3741 3742/* File: c/OP_UNUSED_71FF.cpp */ 3743HANDLE_OPCODE(OP_UNUSED_71FF) 3744OP_END 3745 3746/* File: c/OP_UNUSED_72FF.cpp */ 3747HANDLE_OPCODE(OP_UNUSED_72FF) 3748OP_END 3749 3750/* File: c/OP_UNUSED_73FF.cpp */ 3751HANDLE_OPCODE(OP_UNUSED_73FF) 3752OP_END 3753 3754/* File: c/OP_UNUSED_74FF.cpp */ 3755HANDLE_OPCODE(OP_UNUSED_74FF) 3756OP_END 3757 3758/* File: c/OP_UNUSED_75FF.cpp */ 3759HANDLE_OPCODE(OP_UNUSED_75FF) 3760OP_END 3761 3762/* File: c/OP_UNUSED_76FF.cpp */ 3763HANDLE_OPCODE(OP_UNUSED_76FF) 3764OP_END 3765 3766/* File: c/OP_UNUSED_77FF.cpp */ 3767HANDLE_OPCODE(OP_UNUSED_77FF) 3768OP_END 3769 3770/* File: c/OP_UNUSED_78FF.cpp */ 3771HANDLE_OPCODE(OP_UNUSED_78FF) 3772OP_END 3773 3774/* File: c/OP_UNUSED_79FF.cpp */ 3775HANDLE_OPCODE(OP_UNUSED_79FF) 3776OP_END 3777 3778/* File: c/OP_UNUSED_7AFF.cpp */ 3779HANDLE_OPCODE(OP_UNUSED_7AFF) 3780OP_END 3781 3782/* File: c/OP_UNUSED_7BFF.cpp */ 3783HANDLE_OPCODE(OP_UNUSED_7BFF) 3784OP_END 3785 3786/* File: c/OP_UNUSED_7CFF.cpp */ 3787HANDLE_OPCODE(OP_UNUSED_7CFF) 3788OP_END 3789 3790/* File: c/OP_UNUSED_7DFF.cpp */ 3791HANDLE_OPCODE(OP_UNUSED_7DFF) 3792OP_END 3793 3794/* File: c/OP_UNUSED_7EFF.cpp */ 3795HANDLE_OPCODE(OP_UNUSED_7EFF) 3796OP_END 3797 3798/* File: c/OP_UNUSED_7FFF.cpp */ 3799HANDLE_OPCODE(OP_UNUSED_7FFF) 3800OP_END 3801 3802/* File: c/OP_UNUSED_80FF.cpp */ 3803HANDLE_OPCODE(OP_UNUSED_80FF) 3804OP_END 3805 3806/* File: c/OP_UNUSED_81FF.cpp */ 3807HANDLE_OPCODE(OP_UNUSED_81FF) 3808OP_END 3809 3810/* File: c/OP_UNUSED_82FF.cpp */ 3811HANDLE_OPCODE(OP_UNUSED_82FF) 3812OP_END 3813 3814/* File: c/OP_UNUSED_83FF.cpp */ 3815HANDLE_OPCODE(OP_UNUSED_83FF) 3816OP_END 3817 3818/* File: c/OP_UNUSED_84FF.cpp */ 3819HANDLE_OPCODE(OP_UNUSED_84FF) 3820OP_END 3821 3822/* File: c/OP_UNUSED_85FF.cpp */ 3823HANDLE_OPCODE(OP_UNUSED_85FF) 3824OP_END 3825 3826/* File: c/OP_UNUSED_86FF.cpp */ 3827HANDLE_OPCODE(OP_UNUSED_86FF) 3828OP_END 3829 3830/* File: c/OP_UNUSED_87FF.cpp */ 3831HANDLE_OPCODE(OP_UNUSED_87FF) 3832OP_END 3833 3834/* File: c/OP_UNUSED_88FF.cpp */ 3835HANDLE_OPCODE(OP_UNUSED_88FF) 3836OP_END 3837 3838/* File: c/OP_UNUSED_89FF.cpp */ 3839HANDLE_OPCODE(OP_UNUSED_89FF) 3840OP_END 3841 3842/* File: c/OP_UNUSED_8AFF.cpp */ 3843HANDLE_OPCODE(OP_UNUSED_8AFF) 3844OP_END 3845 3846/* File: c/OP_UNUSED_8BFF.cpp */ 3847HANDLE_OPCODE(OP_UNUSED_8BFF) 3848OP_END 3849 3850/* File: c/OP_UNUSED_8CFF.cpp */ 3851HANDLE_OPCODE(OP_UNUSED_8CFF) 3852OP_END 3853 3854/* File: c/OP_UNUSED_8DFF.cpp */ 3855HANDLE_OPCODE(OP_UNUSED_8DFF) 3856OP_END 3857 3858/* File: c/OP_UNUSED_8EFF.cpp */ 3859HANDLE_OPCODE(OP_UNUSED_8EFF) 3860OP_END 3861 3862/* File: c/OP_UNUSED_8FFF.cpp */ 3863HANDLE_OPCODE(OP_UNUSED_8FFF) 3864OP_END 3865 3866/* File: c/OP_UNUSED_90FF.cpp */ 3867HANDLE_OPCODE(OP_UNUSED_90FF) 3868OP_END 3869 3870/* File: c/OP_UNUSED_91FF.cpp */ 3871HANDLE_OPCODE(OP_UNUSED_91FF) 3872OP_END 3873 3874/* File: c/OP_UNUSED_92FF.cpp */ 3875HANDLE_OPCODE(OP_UNUSED_92FF) 3876OP_END 3877 3878/* File: c/OP_UNUSED_93FF.cpp */ 3879HANDLE_OPCODE(OP_UNUSED_93FF) 3880OP_END 3881 3882/* File: c/OP_UNUSED_94FF.cpp */ 3883HANDLE_OPCODE(OP_UNUSED_94FF) 3884OP_END 3885 3886/* File: c/OP_UNUSED_95FF.cpp */ 3887HANDLE_OPCODE(OP_UNUSED_95FF) 3888OP_END 3889 3890/* File: c/OP_UNUSED_96FF.cpp */ 3891HANDLE_OPCODE(OP_UNUSED_96FF) 3892OP_END 3893 3894/* File: c/OP_UNUSED_97FF.cpp */ 3895HANDLE_OPCODE(OP_UNUSED_97FF) 3896OP_END 3897 3898/* File: c/OP_UNUSED_98FF.cpp */ 3899HANDLE_OPCODE(OP_UNUSED_98FF) 3900OP_END 3901 3902/* File: c/OP_UNUSED_99FF.cpp */ 3903HANDLE_OPCODE(OP_UNUSED_99FF) 3904OP_END 3905 3906/* File: c/OP_UNUSED_9AFF.cpp */ 3907HANDLE_OPCODE(OP_UNUSED_9AFF) 3908OP_END 3909 3910/* File: c/OP_UNUSED_9BFF.cpp */ 3911HANDLE_OPCODE(OP_UNUSED_9BFF) 3912OP_END 3913 3914/* File: c/OP_UNUSED_9CFF.cpp */ 3915HANDLE_OPCODE(OP_UNUSED_9CFF) 3916OP_END 3917 3918/* File: c/OP_UNUSED_9DFF.cpp */ 3919HANDLE_OPCODE(OP_UNUSED_9DFF) 3920OP_END 3921 3922/* File: c/OP_UNUSED_9EFF.cpp */ 3923HANDLE_OPCODE(OP_UNUSED_9EFF) 3924OP_END 3925 3926/* File: c/OP_UNUSED_9FFF.cpp */ 3927HANDLE_OPCODE(OP_UNUSED_9FFF) 3928OP_END 3929 3930/* File: c/OP_UNUSED_A0FF.cpp */ 3931HANDLE_OPCODE(OP_UNUSED_A0FF) 3932OP_END 3933 3934/* File: c/OP_UNUSED_A1FF.cpp */ 3935HANDLE_OPCODE(OP_UNUSED_A1FF) 3936OP_END 3937 3938/* File: c/OP_UNUSED_A2FF.cpp */ 3939HANDLE_OPCODE(OP_UNUSED_A2FF) 3940OP_END 3941 3942/* File: c/OP_UNUSED_A3FF.cpp */ 3943HANDLE_OPCODE(OP_UNUSED_A3FF) 3944OP_END 3945 3946/* File: c/OP_UNUSED_A4FF.cpp */ 3947HANDLE_OPCODE(OP_UNUSED_A4FF) 3948OP_END 3949 3950/* File: c/OP_UNUSED_A5FF.cpp */ 3951HANDLE_OPCODE(OP_UNUSED_A5FF) 3952OP_END 3953 3954/* File: c/OP_UNUSED_A6FF.cpp */ 3955HANDLE_OPCODE(OP_UNUSED_A6FF) 3956OP_END 3957 3958/* File: c/OP_UNUSED_A7FF.cpp */ 3959HANDLE_OPCODE(OP_UNUSED_A7FF) 3960OP_END 3961 3962/* File: c/OP_UNUSED_A8FF.cpp */ 3963HANDLE_OPCODE(OP_UNUSED_A8FF) 3964OP_END 3965 3966/* File: c/OP_UNUSED_A9FF.cpp */ 3967HANDLE_OPCODE(OP_UNUSED_A9FF) 3968OP_END 3969 3970/* File: c/OP_UNUSED_AAFF.cpp */ 3971HANDLE_OPCODE(OP_UNUSED_AAFF) 3972OP_END 3973 3974/* File: c/OP_UNUSED_ABFF.cpp */ 3975HANDLE_OPCODE(OP_UNUSED_ABFF) 3976OP_END 3977 3978/* File: c/OP_UNUSED_ACFF.cpp */ 3979HANDLE_OPCODE(OP_UNUSED_ACFF) 3980OP_END 3981 3982/* File: c/OP_UNUSED_ADFF.cpp */ 3983HANDLE_OPCODE(OP_UNUSED_ADFF) 3984OP_END 3985 3986/* File: c/OP_UNUSED_AEFF.cpp */ 3987HANDLE_OPCODE(OP_UNUSED_AEFF) 3988OP_END 3989 3990/* File: c/OP_UNUSED_AFFF.cpp */ 3991HANDLE_OPCODE(OP_UNUSED_AFFF) 3992OP_END 3993 3994/* File: c/OP_UNUSED_B0FF.cpp */ 3995HANDLE_OPCODE(OP_UNUSED_B0FF) 3996OP_END 3997 3998/* File: c/OP_UNUSED_B1FF.cpp */ 3999HANDLE_OPCODE(OP_UNUSED_B1FF) 4000OP_END 4001 4002/* File: c/OP_UNUSED_B2FF.cpp */ 4003HANDLE_OPCODE(OP_UNUSED_B2FF) 4004OP_END 4005 4006/* File: c/OP_UNUSED_B3FF.cpp */ 4007HANDLE_OPCODE(OP_UNUSED_B3FF) 4008OP_END 4009 4010/* File: c/OP_UNUSED_B4FF.cpp */ 4011HANDLE_OPCODE(OP_UNUSED_B4FF) 4012OP_END 4013 4014/* File: c/OP_UNUSED_B5FF.cpp */ 4015HANDLE_OPCODE(OP_UNUSED_B5FF) 4016OP_END 4017 4018/* File: c/OP_UNUSED_B6FF.cpp */ 4019HANDLE_OPCODE(OP_UNUSED_B6FF) 4020OP_END 4021 4022/* File: c/OP_UNUSED_B7FF.cpp */ 4023HANDLE_OPCODE(OP_UNUSED_B7FF) 4024OP_END 4025 4026/* File: c/OP_UNUSED_B8FF.cpp */ 4027HANDLE_OPCODE(OP_UNUSED_B8FF) 4028OP_END 4029 4030/* File: c/OP_UNUSED_B9FF.cpp */ 4031HANDLE_OPCODE(OP_UNUSED_B9FF) 4032OP_END 4033 4034/* File: c/OP_UNUSED_BAFF.cpp */ 4035HANDLE_OPCODE(OP_UNUSED_BAFF) 4036OP_END 4037 4038/* File: c/OP_UNUSED_BBFF.cpp */ 4039HANDLE_OPCODE(OP_UNUSED_BBFF) 4040OP_END 4041 4042/* File: c/OP_UNUSED_BCFF.cpp */ 4043HANDLE_OPCODE(OP_UNUSED_BCFF) 4044OP_END 4045 4046/* File: c/OP_UNUSED_BDFF.cpp */ 4047HANDLE_OPCODE(OP_UNUSED_BDFF) 4048OP_END 4049 4050/* File: c/OP_UNUSED_BEFF.cpp */ 4051HANDLE_OPCODE(OP_UNUSED_BEFF) 4052OP_END 4053 4054/* File: c/OP_UNUSED_BFFF.cpp */ 4055HANDLE_OPCODE(OP_UNUSED_BFFF) 4056OP_END 4057 4058/* File: c/OP_UNUSED_C0FF.cpp */ 4059HANDLE_OPCODE(OP_UNUSED_C0FF) 4060OP_END 4061 4062/* File: c/OP_UNUSED_C1FF.cpp */ 4063HANDLE_OPCODE(OP_UNUSED_C1FF) 4064OP_END 4065 4066/* File: c/OP_UNUSED_C2FF.cpp */ 4067HANDLE_OPCODE(OP_UNUSED_C2FF) 4068OP_END 4069 4070/* File: c/OP_UNUSED_C3FF.cpp */ 4071HANDLE_OPCODE(OP_UNUSED_C3FF) 4072OP_END 4073 4074/* File: c/OP_UNUSED_C4FF.cpp */ 4075HANDLE_OPCODE(OP_UNUSED_C4FF) 4076OP_END 4077 4078/* File: c/OP_UNUSED_C5FF.cpp */ 4079HANDLE_OPCODE(OP_UNUSED_C5FF) 4080OP_END 4081 4082/* File: c/OP_UNUSED_C6FF.cpp */ 4083HANDLE_OPCODE(OP_UNUSED_C6FF) 4084OP_END 4085 4086/* File: c/OP_UNUSED_C7FF.cpp */ 4087HANDLE_OPCODE(OP_UNUSED_C7FF) 4088OP_END 4089 4090/* File: c/OP_UNUSED_C8FF.cpp */ 4091HANDLE_OPCODE(OP_UNUSED_C8FF) 4092OP_END 4093 4094/* File: c/OP_UNUSED_C9FF.cpp */ 4095HANDLE_OPCODE(OP_UNUSED_C9FF) 4096OP_END 4097 4098/* File: c/OP_UNUSED_CAFF.cpp */ 4099HANDLE_OPCODE(OP_UNUSED_CAFF) 4100OP_END 4101 4102/* File: c/OP_UNUSED_CBFF.cpp */ 4103HANDLE_OPCODE(OP_UNUSED_CBFF) 4104OP_END 4105 4106/* File: c/OP_UNUSED_CCFF.cpp */ 4107HANDLE_OPCODE(OP_UNUSED_CCFF) 4108OP_END 4109 4110/* File: c/OP_UNUSED_CDFF.cpp */ 4111HANDLE_OPCODE(OP_UNUSED_CDFF) 4112OP_END 4113 4114/* File: c/OP_UNUSED_CEFF.cpp */ 4115HANDLE_OPCODE(OP_UNUSED_CEFF) 4116OP_END 4117 4118/* File: c/OP_UNUSED_CFFF.cpp */ 4119HANDLE_OPCODE(OP_UNUSED_CFFF) 4120OP_END 4121 4122/* File: c/OP_UNUSED_D0FF.cpp */ 4123HANDLE_OPCODE(OP_UNUSED_D0FF) 4124OP_END 4125 4126/* File: c/OP_UNUSED_D1FF.cpp */ 4127HANDLE_OPCODE(OP_UNUSED_D1FF) 4128OP_END 4129 4130/* File: c/OP_UNUSED_D2FF.cpp */ 4131HANDLE_OPCODE(OP_UNUSED_D2FF) 4132OP_END 4133 4134/* File: c/OP_UNUSED_D3FF.cpp */ 4135HANDLE_OPCODE(OP_UNUSED_D3FF) 4136OP_END 4137 4138/* File: c/OP_UNUSED_D4FF.cpp */ 4139HANDLE_OPCODE(OP_UNUSED_D4FF) 4140OP_END 4141 4142/* File: c/OP_UNUSED_D5FF.cpp */ 4143HANDLE_OPCODE(OP_UNUSED_D5FF) 4144OP_END 4145 4146/* File: c/OP_UNUSED_D6FF.cpp */ 4147HANDLE_OPCODE(OP_UNUSED_D6FF) 4148OP_END 4149 4150/* File: c/OP_UNUSED_D7FF.cpp */ 4151HANDLE_OPCODE(OP_UNUSED_D7FF) 4152OP_END 4153 4154/* File: c/OP_UNUSED_D8FF.cpp */ 4155HANDLE_OPCODE(OP_UNUSED_D8FF) 4156OP_END 4157 4158/* File: c/OP_UNUSED_D9FF.cpp */ 4159HANDLE_OPCODE(OP_UNUSED_D9FF) 4160OP_END 4161 4162/* File: c/OP_UNUSED_DAFF.cpp */ 4163HANDLE_OPCODE(OP_UNUSED_DAFF) 4164OP_END 4165 4166/* File: c/OP_UNUSED_DBFF.cpp */ 4167HANDLE_OPCODE(OP_UNUSED_DBFF) 4168OP_END 4169 4170/* File: c/OP_UNUSED_DCFF.cpp */ 4171HANDLE_OPCODE(OP_UNUSED_DCFF) 4172OP_END 4173 4174/* File: c/OP_UNUSED_DDFF.cpp */ 4175HANDLE_OPCODE(OP_UNUSED_DDFF) 4176OP_END 4177 4178/* File: c/OP_UNUSED_DEFF.cpp */ 4179HANDLE_OPCODE(OP_UNUSED_DEFF) 4180OP_END 4181 4182/* File: c/OP_UNUSED_DFFF.cpp */ 4183HANDLE_OPCODE(OP_UNUSED_DFFF) 4184OP_END 4185 4186/* File: c/OP_UNUSED_E0FF.cpp */ 4187HANDLE_OPCODE(OP_UNUSED_E0FF) 4188OP_END 4189 4190/* File: c/OP_UNUSED_E1FF.cpp */ 4191HANDLE_OPCODE(OP_UNUSED_E1FF) 4192OP_END 4193 4194/* File: c/OP_UNUSED_E2FF.cpp */ 4195HANDLE_OPCODE(OP_UNUSED_E2FF) 4196OP_END 4197 4198/* File: c/OP_UNUSED_E3FF.cpp */ 4199HANDLE_OPCODE(OP_UNUSED_E3FF) 4200OP_END 4201 4202/* File: c/OP_UNUSED_E4FF.cpp */ 4203HANDLE_OPCODE(OP_UNUSED_E4FF) 4204OP_END 4205 4206/* File: c/OP_UNUSED_E5FF.cpp */ 4207HANDLE_OPCODE(OP_UNUSED_E5FF) 4208OP_END 4209 4210/* File: c/OP_UNUSED_E6FF.cpp */ 4211HANDLE_OPCODE(OP_UNUSED_E6FF) 4212OP_END 4213 4214/* File: c/OP_UNUSED_E7FF.cpp */ 4215HANDLE_OPCODE(OP_UNUSED_E7FF) 4216OP_END 4217 4218/* File: c/OP_UNUSED_E8FF.cpp */ 4219HANDLE_OPCODE(OP_UNUSED_E8FF) 4220OP_END 4221 4222/* File: c/OP_UNUSED_E9FF.cpp */ 4223HANDLE_OPCODE(OP_UNUSED_E9FF) 4224OP_END 4225 4226/* File: c/OP_UNUSED_EAFF.cpp */ 4227HANDLE_OPCODE(OP_UNUSED_EAFF) 4228OP_END 4229 4230/* File: c/OP_UNUSED_EBFF.cpp */ 4231HANDLE_OPCODE(OP_UNUSED_EBFF) 4232OP_END 4233 4234/* File: c/OP_UNUSED_ECFF.cpp */ 4235HANDLE_OPCODE(OP_UNUSED_ECFF) 4236OP_END 4237 4238/* File: c/OP_UNUSED_EDFF.cpp */ 4239HANDLE_OPCODE(OP_UNUSED_EDFF) 4240OP_END 4241 4242/* File: c/OP_UNUSED_EEFF.cpp */ 4243HANDLE_OPCODE(OP_UNUSED_EEFF) 4244OP_END 4245 4246/* File: c/OP_UNUSED_EFFF.cpp */ 4247HANDLE_OPCODE(OP_UNUSED_EFFF) 4248OP_END 4249 4250/* File: c/OP_UNUSED_F0FF.cpp */ 4251HANDLE_OPCODE(OP_UNUSED_F0FF) 4252OP_END 4253 4254/* File: c/OP_UNUSED_F1FF.cpp */ 4255HANDLE_OPCODE(OP_UNUSED_F1FF) 4256 /* 4257 * In portable interp, most unused opcodes will fall through to here. 4258 */ 4259 LOGE("unknown opcode 0x%04x", inst); 4260 dvmAbort(); 4261 FINISH(1); 4262OP_END 4263 4264/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */ 4265HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/) 4266 { 4267 Object* obj; 4268 4269 vsrc1 = FETCH(4); /* reg number of "this" pointer */ 4270 obj = GET_REGISTER_AS_OBJECT(vsrc1); 4271 4272 if (!checkForNullExportPC(obj, fp, pc)) 4273 GOTO_exceptionThrown(); 4274 4275 /* 4276 * The object should be marked "finalizable" when Object.<init> 4277 * completes normally. We're going to assume it does complete 4278 * (by virtue of being nothing but a return-void) and set it now. 4279 */ 4280 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) { 4281 EXPORT_PC(); 4282 dvmSetFinalizable(obj); 4283 if (dvmGetException(self)) 4284 GOTO_exceptionThrown(); 4285 } 4286 4287 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 4288 /* behave like OP_INVOKE_DIRECT_RANGE */ 4289 GOTO_invoke(invokeDirect, true, true); 4290 } 4291 FINISH(5); 4292 } 4293OP_END 4294 4295/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */ 4296HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, ) 4297OP_END 4298 4299/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */ 4300HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4301OP_END 4302 4303/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */ 4304HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4305OP_END 4306 4307/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */ 4308HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, ) 4309OP_END 4310 4311/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */ 4312HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4313OP_END 4314 4315/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */ 4316HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4317OP_END 4318 4319/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */ 4320HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, ) 4321OP_END 4322 4323/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */ 4324HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4325OP_END 4326 4327/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */ 4328HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4329OP_END 4330 4331/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */ 4332HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, ) 4333OP_END 4334 4335/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */ 4336HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4337OP_END 4338 4339/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */ 4340HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4341OP_END 4342 4343/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp */ 4344HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO) 4345 EXPORT_PC(); 4346 vsrc1 = FETCH(3); 4347 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */ 4348 dvmThrowVerificationError(curMethod, vsrc1, ref); 4349 GOTO_exceptionThrown(); 4350OP_END 4351 4352/* File: cstubs/entry.cpp */ 4353/* 4354 * Handler function table, one entry per opcode. 4355 */ 4356#undef H 4357#define H(_op) (const void*) dvmMterp_##_op 4358DEFINE_GOTO_TABLE(gDvmMterpHandlers) 4359 4360#undef H 4361#define H(_op) #_op 4362DEFINE_GOTO_TABLE(gDvmMterpHandlerNames) 4363 4364#include <setjmp.h> 4365 4366/* 4367 * C mterp entry point. This just calls the various C fallbacks, making 4368 * this a slow but portable interpeter. 4369 * 4370 * This is only used for the "allstubs" variant. 4371 */ 4372void dvmMterpStdRun(Thread* self) 4373{ 4374 jmp_buf jmpBuf; 4375 4376 self->interpSave.bailPtr = &jmpBuf; 4377 4378 /* We exit via a longjmp */ 4379 if (setjmp(jmpBuf)) { 4380 LOGVV("mterp threadid=%d returning", dvmThreadSelf()->threadId); 4381 return; 4382 } 4383 4384 /* run until somebody longjmp()s out */ 4385 while (true) { 4386 typedef void (*Handler)(Thread* self); 4387 4388 u2 inst = /*self->interpSave.*/pc[0]; 4389 /* 4390 * In mterp, dvmCheckBefore is handled via the altHandlerTable, 4391 * while in the portable interpreter it is part of the handler 4392 * FINISH code. For allstubs, we must do an explicit check 4393 * in the interpretation loop. 4394 */ 4395 if (self->interpBreak.ctl.subMode) { 4396 dvmCheckBefore(pc, fp, self); 4397 } 4398 Handler handler = (Handler) gDvmMterpHandlers[inst & 0xff]; 4399 (void) gDvmMterpHandlerNames; /* avoid gcc "defined but not used" */ 4400 LOGVV("handler %p %s", 4401 handler, (const char*) gDvmMterpHandlerNames[inst & 0xff]); 4402 (*handler)(self); 4403 } 4404} 4405 4406/* 4407 * C mterp exit point. Call here to bail out of the interpreter. 4408 */ 4409void dvmMterpStdBail(Thread* self) 4410{ 4411 jmp_buf* pJmpBuf = (jmp_buf*) self->interpSave.bailPtr; 4412 longjmp(*pJmpBuf, 1); 4413} 4414 4415/* File: c/gotoTargets.cpp */ 4416/* 4417 * C footer. This has some common code shared by the various targets. 4418 */ 4419 4420/* 4421 * Everything from here on is a "goto target". In the basic interpreter 4422 * we jump into these targets and then jump directly to the handler for 4423 * next instruction. Here, these are subroutines that return to the caller. 4424 */ 4425 4426GOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat) 4427 { 4428 ClassObject* arrayClass; 4429 ArrayObject* newArray; 4430 u4* contents; 4431 char typeCh; 4432 int i; 4433 u4 arg5; 4434 4435 EXPORT_PC(); 4436 4437 if (jumboFormat) { 4438 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */ 4439 vsrc1 = FETCH(3); /* #of elements */ 4440 vdst = FETCH(4); /* range base */ 4441 arg5 = -1; /* silence compiler warning */ 4442 ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4443 vsrc1, ref, vdst, vdst+vsrc1-1); 4444 } else { 4445 ref = FETCH(1); /* class ref */ 4446 vdst = FETCH(2); /* first 4 regs -or- range base */ 4447 4448 if (methodCallRange) { 4449 vsrc1 = INST_AA(inst); /* #of elements */ 4450 arg5 = -1; /* silence compiler warning */ 4451 ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}", 4452 vsrc1, ref, vdst, vdst+vsrc1-1); 4453 } else { 4454 arg5 = INST_A(inst); 4455 vsrc1 = INST_B(inst); /* #of elements */ 4456 ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}", 4457 vsrc1, ref, vdst, arg5); 4458 } 4459 } 4460 4461 /* 4462 * Resolve the array class. 4463 */ 4464 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 4465 if (arrayClass == NULL) { 4466 arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 4467 if (arrayClass == NULL) 4468 GOTO_exceptionThrown(); 4469 } 4470 /* 4471 if (!dvmIsArrayClass(arrayClass)) { 4472 dvmThrowRuntimeException( 4473 "filled-new-array needs array class"); 4474 GOTO_exceptionThrown(); 4475 } 4476 */ 4477 /* verifier guarantees this is an array class */ 4478 assert(dvmIsArrayClass(arrayClass)); 4479 assert(dvmIsClassInitialized(arrayClass)); 4480 4481 /* 4482 * Create an array of the specified type. 4483 */ 4484 LOGVV("+++ filled-new-array type is '%s'", arrayClass->descriptor); 4485 typeCh = arrayClass->descriptor[1]; 4486 if (typeCh == 'D' || typeCh == 'J') { 4487 /* category 2 primitives not allowed */ 4488 dvmThrowRuntimeException("bad filled array req"); 4489 GOTO_exceptionThrown(); 4490 } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') { 4491 /* TODO: requires multiple "fill in" loops with different widths */ 4492 LOGE("non-int primitives not implemented"); 4493 dvmThrowInternalError( 4494 "filled-new-array not implemented for anything but 'int'"); 4495 GOTO_exceptionThrown(); 4496 } 4497 4498 newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK); 4499 if (newArray == NULL) 4500 GOTO_exceptionThrown(); 4501 4502 /* 4503 * Fill in the elements. It's legal for vsrc1 to be zero. 4504 */ 4505 contents = (u4*)(void*)newArray->contents; 4506 if (methodCallRange) { 4507 for (i = 0; i < vsrc1; i++) 4508 contents[i] = GET_REGISTER(vdst+i); 4509 } else { 4510 assert(vsrc1 <= 5); 4511 if (vsrc1 == 5) { 4512 contents[4] = GET_REGISTER(arg5); 4513 vsrc1--; 4514 } 4515 for (i = 0; i < vsrc1; i++) { 4516 contents[i] = GET_REGISTER(vdst & 0x0f); 4517 vdst >>= 4; 4518 } 4519 } 4520 if (typeCh == 'L' || typeCh == '[') { 4521 dvmWriteBarrierArray(newArray, 0, newArray->length); 4522 } 4523 4524 retval.l = (Object*)newArray; 4525 } 4526 if (jumboFormat) { 4527 FINISH(5); 4528 } else { 4529 FINISH(3); 4530 } 4531GOTO_TARGET_END 4532 4533 4534GOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat) 4535 { 4536 Method* baseMethod; 4537 Object* thisPtr; 4538 4539 EXPORT_PC(); 4540 4541 if (jumboFormat) { 4542 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4543 vsrc1 = FETCH(3); /* count */ 4544 vdst = FETCH(4); /* first reg */ 4545 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4546 ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4547 vsrc1, ref, vdst, vdst+vsrc1-1); 4548 thisPtr = (Object*) GET_REGISTER(vdst); 4549 } else { 4550 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4551 ref = FETCH(1); /* method ref */ 4552 vdst = FETCH(2); /* 4 regs -or- first reg */ 4553 4554 /* 4555 * The object against which we are executing a method is always 4556 * in the first argument. 4557 */ 4558 if (methodCallRange) { 4559 assert(vsrc1 > 0); 4560 ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}", 4561 vsrc1, ref, vdst, vdst+vsrc1-1); 4562 thisPtr = (Object*) GET_REGISTER(vdst); 4563 } else { 4564 assert((vsrc1>>4) > 0); 4565 ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}", 4566 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4567 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 4568 } 4569 } 4570 4571 if (!checkForNull(thisPtr)) 4572 GOTO_exceptionThrown(); 4573 4574 /* 4575 * Resolve the method. This is the correct method for the static 4576 * type of the object. We also verify access permissions here. 4577 */ 4578 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 4579 if (baseMethod == NULL) { 4580 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 4581 if (baseMethod == NULL) { 4582 ILOGV("+ unknown method or access denied"); 4583 GOTO_exceptionThrown(); 4584 } 4585 } 4586 4587 /* 4588 * Combine the object we found with the vtable offset in the 4589 * method. 4590 */ 4591 assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount); 4592 methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex]; 4593 4594#if defined(WITH_JIT) && defined(MTERP_STUB) 4595 self->methodToCall = methodToCall; 4596 self->callsiteClass = thisPtr->clazz; 4597#endif 4598 4599#if 0 4600 if (dvmIsAbstractMethod(methodToCall)) { 4601 /* 4602 * This can happen if you create two classes, Base and Sub, where 4603 * Sub is a sub-class of Base. Declare a protected abstract 4604 * method foo() in Base, and invoke foo() from a method in Base. 4605 * Base is an "abstract base class" and is never instantiated 4606 * directly. Now, Override foo() in Sub, and use Sub. This 4607 * Works fine unless Sub stops providing an implementation of 4608 * the method. 4609 */ 4610 dvmThrowAbstractMethodError("abstract method not implemented"); 4611 GOTO_exceptionThrown(); 4612 } 4613#else 4614 assert(!dvmIsAbstractMethod(methodToCall) || 4615 methodToCall->nativeFunc != NULL); 4616#endif 4617 4618 LOGVV("+++ base=%s.%s virtual[%d]=%s.%s", 4619 baseMethod->clazz->descriptor, baseMethod->name, 4620 (u4) baseMethod->methodIndex, 4621 methodToCall->clazz->descriptor, methodToCall->name); 4622 assert(methodToCall != NULL); 4623 4624#if 0 4625 if (vsrc1 != methodToCall->insSize) { 4626 LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s", 4627 baseMethod->clazz->descriptor, baseMethod->name, 4628 (u4) baseMethod->methodIndex, 4629 methodToCall->clazz->descriptor, methodToCall->name); 4630 //dvmDumpClass(baseMethod->clazz); 4631 //dvmDumpClass(methodToCall->clazz); 4632 dvmDumpAllClasses(0); 4633 } 4634#endif 4635 4636 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4637 } 4638GOTO_TARGET_END 4639 4640GOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat) 4641 { 4642 Method* baseMethod; 4643 u2 thisReg; 4644 4645 EXPORT_PC(); 4646 4647 if (jumboFormat) { 4648 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4649 vsrc1 = FETCH(3); /* count */ 4650 vdst = FETCH(4); /* first reg */ 4651 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4652 ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4653 vsrc1, ref, vdst, vdst+vsrc1-1); 4654 thisReg = vdst; 4655 } else { 4656 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4657 ref = FETCH(1); /* method ref */ 4658 vdst = FETCH(2); /* 4 regs -or- first reg */ 4659 4660 if (methodCallRange) { 4661 ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}", 4662 vsrc1, ref, vdst, vdst+vsrc1-1); 4663 thisReg = vdst; 4664 } else { 4665 ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}", 4666 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4667 thisReg = vdst & 0x0f; 4668 } 4669 } 4670 4671 /* impossible in well-formed code, but we must check nevertheless */ 4672 if (!checkForNull((Object*) GET_REGISTER(thisReg))) 4673 GOTO_exceptionThrown(); 4674 4675 /* 4676 * Resolve the method. This is the correct method for the static 4677 * type of the object. We also verify access permissions here. 4678 * The first arg to dvmResolveMethod() is just the referring class 4679 * (used for class loaders and such), so we don't want to pass 4680 * the superclass into the resolution call. 4681 */ 4682 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 4683 if (baseMethod == NULL) { 4684 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 4685 if (baseMethod == NULL) { 4686 ILOGV("+ unknown method or access denied"); 4687 GOTO_exceptionThrown(); 4688 } 4689 } 4690 4691 /* 4692 * Combine the object we found with the vtable offset in the 4693 * method's class. 4694 * 4695 * We're using the current method's class' superclass, not the 4696 * superclass of "this". This is because we might be executing 4697 * in a method inherited from a superclass, and we want to run 4698 * in that class' superclass. 4699 */ 4700 if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) { 4701 /* 4702 * Method does not exist in the superclass. Could happen if 4703 * superclass gets updated. 4704 */ 4705 dvmThrowNoSuchMethodError(baseMethod->name); 4706 GOTO_exceptionThrown(); 4707 } 4708 methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex]; 4709 4710#if 0 4711 if (dvmIsAbstractMethod(methodToCall)) { 4712 dvmThrowAbstractMethodError("abstract method not implemented"); 4713 GOTO_exceptionThrown(); 4714 } 4715#else 4716 assert(!dvmIsAbstractMethod(methodToCall) || 4717 methodToCall->nativeFunc != NULL); 4718#endif 4719 LOGVV("+++ base=%s.%s super-virtual=%s.%s", 4720 baseMethod->clazz->descriptor, baseMethod->name, 4721 methodToCall->clazz->descriptor, methodToCall->name); 4722 assert(methodToCall != NULL); 4723 4724 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4725 } 4726GOTO_TARGET_END 4727 4728GOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat) 4729 { 4730 Object* thisPtr; 4731 ClassObject* thisClass; 4732 4733 EXPORT_PC(); 4734 4735 if (jumboFormat) { 4736 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4737 vsrc1 = FETCH(3); /* count */ 4738 vdst = FETCH(4); /* first reg */ 4739 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4740 ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4741 vsrc1, ref, vdst, vdst+vsrc1-1); 4742 thisPtr = (Object*) GET_REGISTER(vdst); 4743 } else { 4744 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4745 ref = FETCH(1); /* method ref */ 4746 vdst = FETCH(2); /* 4 regs -or- first reg */ 4747 4748 /* 4749 * The object against which we are executing a method is always 4750 * in the first argument. 4751 */ 4752 if (methodCallRange) { 4753 assert(vsrc1 > 0); 4754 ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}", 4755 vsrc1, ref, vdst, vdst+vsrc1-1); 4756 thisPtr = (Object*) GET_REGISTER(vdst); 4757 } else { 4758 assert((vsrc1>>4) > 0); 4759 ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}", 4760 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4761 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 4762 } 4763 } 4764 4765 if (!checkForNull(thisPtr)) 4766 GOTO_exceptionThrown(); 4767 4768 thisClass = thisPtr->clazz; 4769 4770 4771 /* 4772 * Given a class and a method index, find the Method* with the 4773 * actual code we want to execute. 4774 */ 4775 methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod, 4776 methodClassDex); 4777#if defined(WITH_JIT) && defined(MTERP_STUB) 4778 self->callsiteClass = thisClass; 4779 self->methodToCall = methodToCall; 4780#endif 4781 if (methodToCall == NULL) { 4782 assert(dvmCheckException(self)); 4783 GOTO_exceptionThrown(); 4784 } 4785 4786 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4787 } 4788GOTO_TARGET_END 4789 4790GOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat) 4791 { 4792 u2 thisReg; 4793 4794 EXPORT_PC(); 4795 4796 if (jumboFormat) { 4797 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4798 vsrc1 = FETCH(3); /* count */ 4799 vdst = FETCH(4); /* first reg */ 4800 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4801 ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4802 vsrc1, ref, vdst, vdst+vsrc1-1); 4803 thisReg = vdst; 4804 } else { 4805 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4806 ref = FETCH(1); /* method ref */ 4807 vdst = FETCH(2); /* 4 regs -or- first reg */ 4808 4809 if (methodCallRange) { 4810 ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}", 4811 vsrc1, ref, vdst, vdst+vsrc1-1); 4812 thisReg = vdst; 4813 } else { 4814 ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}", 4815 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4816 thisReg = vdst & 0x0f; 4817 } 4818 } 4819 4820 if (!checkForNull((Object*) GET_REGISTER(thisReg))) 4821 GOTO_exceptionThrown(); 4822 4823 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 4824 if (methodToCall == NULL) { 4825 methodToCall = dvmResolveMethod(curMethod->clazz, ref, 4826 METHOD_DIRECT); 4827 if (methodToCall == NULL) { 4828 ILOGV("+ unknown direct method"); // should be impossible 4829 GOTO_exceptionThrown(); 4830 } 4831 } 4832 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4833 } 4834GOTO_TARGET_END 4835 4836GOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat) 4837 EXPORT_PC(); 4838 4839 if (jumboFormat) { 4840 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4841 vsrc1 = FETCH(3); /* count */ 4842 vdst = FETCH(4); /* first reg */ 4843 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4844 ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4845 vsrc1, ref, vdst, vdst+vsrc1-1); 4846 } else { 4847 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4848 ref = FETCH(1); /* method ref */ 4849 vdst = FETCH(2); /* 4 regs -or- first reg */ 4850 4851 if (methodCallRange) 4852 ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}", 4853 vsrc1, ref, vdst, vdst+vsrc1-1); 4854 else 4855 ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}", 4856 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4857 } 4858 4859 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 4860 if (methodToCall == NULL) { 4861 methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC); 4862 if (methodToCall == NULL) { 4863 ILOGV("+ unknown method"); 4864 GOTO_exceptionThrown(); 4865 } 4866 4867#if defined(WITH_JIT) && defined(MTERP_STUB) 4868 /* 4869 * The JIT needs dvmDexGetResolvedMethod() to return non-null. 4870 * Include the check if this code is being used as a stub 4871 * called from the assembly interpreter. 4872 */ 4873 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 4874 (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) { 4875 /* Class initialization is still ongoing */ 4876 dvmJitEndTraceSelect(self,pc); 4877 } 4878#endif 4879 } 4880 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4881GOTO_TARGET_END 4882 4883GOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat) 4884 { 4885 Object* thisPtr; 4886 4887 EXPORT_PC(); 4888 4889 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4890 ref = FETCH(1); /* vtable index */ 4891 vdst = FETCH(2); /* 4 regs -or- first reg */ 4892 4893 /* 4894 * The object against which we are executing a method is always 4895 * in the first argument. 4896 */ 4897 if (methodCallRange) { 4898 assert(vsrc1 > 0); 4899 ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}", 4900 vsrc1, ref, vdst, vdst+vsrc1-1); 4901 thisPtr = (Object*) GET_REGISTER(vdst); 4902 } else { 4903 assert((vsrc1>>4) > 0); 4904 ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}", 4905 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4906 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 4907 } 4908 4909 if (!checkForNull(thisPtr)) 4910 GOTO_exceptionThrown(); 4911 4912 4913 /* 4914 * Combine the object we found with the vtable offset in the 4915 * method. 4916 */ 4917 assert(ref < (unsigned int) thisPtr->clazz->vtableCount); 4918 methodToCall = thisPtr->clazz->vtable[ref]; 4919#if defined(WITH_JIT) && defined(MTERP_STUB) 4920 self->callsiteClass = thisPtr->clazz; 4921 self->methodToCall = methodToCall; 4922#endif 4923 4924#if 0 4925 if (dvmIsAbstractMethod(methodToCall)) { 4926 dvmThrowAbstractMethodError("abstract method not implemented"); 4927 GOTO_exceptionThrown(); 4928 } 4929#else 4930 assert(!dvmIsAbstractMethod(methodToCall) || 4931 methodToCall->nativeFunc != NULL); 4932#endif 4933 4934 LOGVV("+++ virtual[%d]=%s.%s", 4935 ref, methodToCall->clazz->descriptor, methodToCall->name); 4936 assert(methodToCall != NULL); 4937 4938 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4939 } 4940GOTO_TARGET_END 4941 4942GOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat) 4943 { 4944 u2 thisReg; 4945 4946 EXPORT_PC(); 4947 4948 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4949 ref = FETCH(1); /* vtable index */ 4950 vdst = FETCH(2); /* 4 regs -or- first reg */ 4951 4952 if (methodCallRange) { 4953 ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}", 4954 vsrc1, ref, vdst, vdst+vsrc1-1); 4955 thisReg = vdst; 4956 } else { 4957 ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}", 4958 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4959 thisReg = vdst & 0x0f; 4960 } 4961 /* impossible in well-formed code, but we must check nevertheless */ 4962 if (!checkForNull((Object*) GET_REGISTER(thisReg))) 4963 GOTO_exceptionThrown(); 4964 4965#if 0 /* impossible in optimized + verified code */ 4966 if (ref >= curMethod->clazz->super->vtableCount) { 4967 dvmThrowNoSuchMethodError(NULL); 4968 GOTO_exceptionThrown(); 4969 } 4970#else 4971 assert(ref < (unsigned int) curMethod->clazz->super->vtableCount); 4972#endif 4973 4974 /* 4975 * Combine the object we found with the vtable offset in the 4976 * method's class. 4977 * 4978 * We're using the current method's class' superclass, not the 4979 * superclass of "this". This is because we might be executing 4980 * in a method inherited from a superclass, and we want to run 4981 * in the method's class' superclass. 4982 */ 4983 methodToCall = curMethod->clazz->super->vtable[ref]; 4984 4985#if 0 4986 if (dvmIsAbstractMethod(methodToCall)) { 4987 dvmThrowAbstractMethodError("abstract method not implemented"); 4988 GOTO_exceptionThrown(); 4989 } 4990#else 4991 assert(!dvmIsAbstractMethod(methodToCall) || 4992 methodToCall->nativeFunc != NULL); 4993#endif 4994 LOGVV("+++ super-virtual[%d]=%s.%s", 4995 ref, methodToCall->clazz->descriptor, methodToCall->name); 4996 assert(methodToCall != NULL); 4997 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4998 } 4999GOTO_TARGET_END 5000 5001 5002 /* 5003 * General handling for return-void, return, and return-wide. Put the 5004 * return value in "retval" before jumping here. 5005 */ 5006GOTO_TARGET(returnFromMethod) 5007 { 5008 StackSaveArea* saveArea; 5009 5010 /* 5011 * We must do this BEFORE we pop the previous stack frame off, so 5012 * that the GC can see the return value (if any) in the local vars. 5013 * 5014 * Since this is now an interpreter switch point, we must do it before 5015 * we do anything at all. 5016 */ 5017 PERIODIC_CHECKS(0); 5018 5019 ILOGV("> retval=0x%llx (leaving %s.%s %s)", 5020 retval.j, curMethod->clazz->descriptor, curMethod->name, 5021 curMethod->shorty); 5022 //DUMP_REGS(curMethod, fp); 5023 5024 saveArea = SAVEAREA_FROM_FP(fp); 5025 5026#ifdef EASY_GDB 5027 debugSaveArea = saveArea; 5028#endif 5029 5030 /* back up to previous frame and see if we hit a break */ 5031 fp = (u4*)saveArea->prevFrame; 5032 assert(fp != NULL); 5033 5034 /* Handle any special subMode requirements */ 5035 if (self->interpBreak.ctl.subMode != 0) { 5036 PC_FP_TO_SELF(); 5037 dvmReportReturn(self); 5038 } 5039 5040 if (dvmIsBreakFrame(fp)) { 5041 /* bail without popping the method frame from stack */ 5042 LOGVV("+++ returned into break frame"); 5043 GOTO_bail(); 5044 } 5045 5046 /* update thread FP, and reset local variables */ 5047 self->interpSave.curFrame = fp; 5048 curMethod = SAVEAREA_FROM_FP(fp)->method; 5049 self->interpSave.method = curMethod; 5050 //methodClass = curMethod->clazz; 5051 methodClassDex = curMethod->clazz->pDvmDex; 5052 pc = saveArea->savedPc; 5053 ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor, 5054 curMethod->name, curMethod->shorty); 5055 5056 /* use FINISH on the caller's invoke instruction */ 5057 //u2 invokeInstr = INST_INST(FETCH(0)); 5058 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 5059 invokeInstr <= OP_INVOKE_INTERFACE*/) 5060 { 5061 FINISH(3); 5062 } else { 5063 //LOGE("Unknown invoke instr %02x at %d", 5064 // invokeInstr, (int) (pc - curMethod->insns)); 5065 assert(false); 5066 } 5067 } 5068GOTO_TARGET_END 5069 5070 5071 /* 5072 * Jump here when the code throws an exception. 5073 * 5074 * By the time we get here, the Throwable has been created and the stack 5075 * trace has been saved off. 5076 */ 5077GOTO_TARGET(exceptionThrown) 5078 { 5079 Object* exception; 5080 int catchRelPc; 5081 5082 PERIODIC_CHECKS(0); 5083 5084 /* 5085 * We save off the exception and clear the exception status. While 5086 * processing the exception we might need to load some Throwable 5087 * classes, and we don't want class loader exceptions to get 5088 * confused with this one. 5089 */ 5090 assert(dvmCheckException(self)); 5091 exception = dvmGetException(self); 5092 dvmAddTrackedAlloc(exception, self); 5093 dvmClearException(self); 5094 5095 LOGV("Handling exception %s at %s:%d", 5096 exception->clazz->descriptor, curMethod->name, 5097 dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 5098 5099 /* 5100 * Report the exception throw to any "subMode" watchers. 5101 * 5102 * TODO: if the exception was thrown by interpreted code, control 5103 * fell through native, and then back to us, we will report the 5104 * exception at the point of the throw and again here. We can avoid 5105 * this by not reporting exceptions when we jump here directly from 5106 * the native call code above, but then we won't report exceptions 5107 * that were thrown *from* the JNI code (as opposed to *through* it). 5108 * 5109 * The correct solution is probably to ignore from-native exceptions 5110 * here, and have the JNI exception code do the reporting to the 5111 * debugger. 5112 */ 5113 if (self->interpBreak.ctl.subMode != 0) { 5114 PC_FP_TO_SELF(); 5115 dvmReportExceptionThrow(self, exception); 5116 } 5117 5118 /* 5119 * We need to unroll to the catch block or the nearest "break" 5120 * frame. 5121 * 5122 * A break frame could indicate that we have reached an intermediate 5123 * native call, or have gone off the top of the stack and the thread 5124 * needs to exit. Either way, we return from here, leaving the 5125 * exception raised. 5126 * 5127 * If we do find a catch block, we want to transfer execution to 5128 * that point. 5129 * 5130 * Note this can cause an exception while resolving classes in 5131 * the "catch" blocks. 5132 */ 5133 catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns, 5134 exception, false, (void**)(void*)&fp); 5135 5136 /* 5137 * Restore the stack bounds after an overflow. This isn't going to 5138 * be correct in all circumstances, e.g. if JNI code devours the 5139 * exception this won't happen until some other exception gets 5140 * thrown. If the code keeps pushing the stack bounds we'll end 5141 * up aborting the VM. 5142 * 5143 * Note we want to do this *after* the call to dvmFindCatchBlock, 5144 * because that may need extra stack space to resolve exception 5145 * classes (e.g. through a class loader). 5146 * 5147 * It's possible for the stack overflow handling to cause an 5148 * exception (specifically, class resolution in a "catch" block 5149 * during the call above), so we could see the thread's overflow 5150 * flag raised but actually be running in a "nested" interpreter 5151 * frame. We don't allow doubled-up StackOverflowErrors, so 5152 * we can check for this by just looking at the exception type 5153 * in the cleanup function. Also, we won't unroll past the SOE 5154 * point because the more-recent exception will hit a break frame 5155 * as it unrolls to here. 5156 */ 5157 if (self->stackOverflowed) 5158 dvmCleanupStackOverflow(self, exception); 5159 5160 if (catchRelPc < 0) { 5161 /* falling through to JNI code or off the bottom of the stack */ 5162#if DVM_SHOW_EXCEPTION >= 2 5163 LOGD("Exception %s from %s:%d not caught locally", 5164 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 5165 dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 5166#endif 5167 dvmSetException(self, exception); 5168 dvmReleaseTrackedAlloc(exception, self); 5169 GOTO_bail(); 5170 } 5171 5172#if DVM_SHOW_EXCEPTION >= 3 5173 { 5174 const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method; 5175 LOGD("Exception %s thrown from %s:%d to %s:%d", 5176 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 5177 dvmLineNumFromPC(curMethod, pc - curMethod->insns), 5178 dvmGetMethodSourceFile(catchMethod), 5179 dvmLineNumFromPC(catchMethod, catchRelPc)); 5180 } 5181#endif 5182 5183 /* 5184 * Adjust local variables to match self->interpSave.curFrame and the 5185 * updated PC. 5186 */ 5187 //fp = (u4*) self->interpSave.curFrame; 5188 curMethod = SAVEAREA_FROM_FP(fp)->method; 5189 self->interpSave.method = curMethod; 5190 //methodClass = curMethod->clazz; 5191 methodClassDex = curMethod->clazz->pDvmDex; 5192 pc = curMethod->insns + catchRelPc; 5193 ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 5194 curMethod->name, curMethod->shorty); 5195 DUMP_REGS(curMethod, fp, false); // show all regs 5196 5197 /* 5198 * Restore the exception if the handler wants it. 5199 * 5200 * The Dalvik spec mandates that, if an exception handler wants to 5201 * do something with the exception, the first instruction executed 5202 * must be "move-exception". We can pass the exception along 5203 * through the thread struct, and let the move-exception instruction 5204 * clear it for us. 5205 * 5206 * If the handler doesn't call move-exception, we don't want to 5207 * finish here with an exception still pending. 5208 */ 5209 if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION) 5210 dvmSetException(self, exception); 5211 5212 dvmReleaseTrackedAlloc(exception, self); 5213 FINISH(0); 5214 } 5215GOTO_TARGET_END 5216 5217 5218 5219 /* 5220 * General handling for invoke-{virtual,super,direct,static,interface}, 5221 * including "quick" variants. 5222 * 5223 * Set "methodToCall" to the Method we're calling, and "methodCallRange" 5224 * depending on whether this is a "/range" instruction. 5225 * 5226 * For a range call: 5227 * "vsrc1" holds the argument count (8 bits) 5228 * "vdst" holds the first argument in the range 5229 * For a non-range call: 5230 * "vsrc1" holds the argument count (4 bits) and the 5th argument index 5231 * "vdst" holds four 4-bit register indices 5232 * 5233 * The caller must EXPORT_PC before jumping here, because any method 5234 * call can throw a stack overflow exception. 5235 */ 5236GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, 5237 u2 count, u2 regs) 5238 { 5239 STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;); 5240 5241 //printf("range=%d call=%p count=%d regs=0x%04x\n", 5242 // methodCallRange, methodToCall, count, regs); 5243 //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor, 5244 // methodToCall->name, methodToCall->shorty); 5245 5246 u4* outs; 5247 int i; 5248 5249 /* 5250 * Copy args. This may corrupt vsrc1/vdst. 5251 */ 5252 if (methodCallRange) { 5253 // could use memcpy or a "Duff's device"; most functions have 5254 // so few args it won't matter much 5255 assert(vsrc1 <= curMethod->outsSize); 5256 assert(vsrc1 == methodToCall->insSize); 5257 outs = OUTS_FROM_FP(fp, vsrc1); 5258 for (i = 0; i < vsrc1; i++) 5259 outs[i] = GET_REGISTER(vdst+i); 5260 } else { 5261 u4 count = vsrc1 >> 4; 5262 5263 assert(count <= curMethod->outsSize); 5264 assert(count == methodToCall->insSize); 5265 assert(count <= 5); 5266 5267 outs = OUTS_FROM_FP(fp, count); 5268#if 0 5269 if (count == 5) { 5270 outs[4] = GET_REGISTER(vsrc1 & 0x0f); 5271 count--; 5272 } 5273 for (i = 0; i < (int) count; i++) { 5274 outs[i] = GET_REGISTER(vdst & 0x0f); 5275 vdst >>= 4; 5276 } 5277#else 5278 // This version executes fewer instructions but is larger 5279 // overall. Seems to be a teensy bit faster. 5280 assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear 5281 switch (count) { 5282 case 5: 5283 outs[4] = GET_REGISTER(vsrc1 & 0x0f); 5284 case 4: 5285 outs[3] = GET_REGISTER(vdst >> 12); 5286 case 3: 5287 outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8); 5288 case 2: 5289 outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4); 5290 case 1: 5291 outs[0] = GET_REGISTER(vdst & 0x0f); 5292 default: 5293 ; 5294 } 5295#endif 5296 } 5297 } 5298 5299 /* 5300 * (This was originally a "goto" target; I've kept it separate from the 5301 * stuff above in case we want to refactor things again.) 5302 * 5303 * At this point, we have the arguments stored in the "outs" area of 5304 * the current method's stack frame, and the method to call in 5305 * "methodToCall". Push a new stack frame. 5306 */ 5307 { 5308 StackSaveArea* newSaveArea; 5309 u4* newFp; 5310 5311 ILOGV("> %s%s.%s %s", 5312 dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "", 5313 methodToCall->clazz->descriptor, methodToCall->name, 5314 methodToCall->shorty); 5315 5316 newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize; 5317 newSaveArea = SAVEAREA_FROM_FP(newFp); 5318 5319 /* verify that we have enough space */ 5320 if (true) { 5321 u1* bottom; 5322 bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4); 5323 if (bottom < self->interpStackEnd) { 5324 /* stack overflow */ 5325 LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')", 5326 self->interpStackStart, self->interpStackEnd, bottom, 5327 (u1*) fp - bottom, self->interpStackSize, 5328 methodToCall->name); 5329 dvmHandleStackOverflow(self, methodToCall); 5330 assert(dvmCheckException(self)); 5331 GOTO_exceptionThrown(); 5332 } 5333 //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p", 5334 // fp, newFp, newSaveArea, bottom); 5335 } 5336 5337#ifdef LOG_INSTR 5338 if (methodToCall->registersSize > methodToCall->insSize) { 5339 /* 5340 * This makes valgrind quiet when we print registers that 5341 * haven't been initialized. Turn it off when the debug 5342 * messages are disabled -- we want valgrind to report any 5343 * used-before-initialized issues. 5344 */ 5345 memset(newFp, 0xcc, 5346 (methodToCall->registersSize - methodToCall->insSize) * 4); 5347 } 5348#endif 5349 5350#ifdef EASY_GDB 5351 newSaveArea->prevSave = SAVEAREA_FROM_FP(fp); 5352#endif 5353 newSaveArea->prevFrame = fp; 5354 newSaveArea->savedPc = pc; 5355#if defined(WITH_JIT) && defined(MTERP_STUB) 5356 newSaveArea->returnAddr = 0; 5357#endif 5358 newSaveArea->method = methodToCall; 5359 5360 if (self->interpBreak.ctl.subMode != 0) { 5361 /* 5362 * We mark ENTER here for both native and non-native 5363 * calls. For native calls, we'll mark EXIT on return. 5364 * For non-native calls, EXIT is marked in the RETURN op. 5365 */ 5366 PC_TO_SELF(); 5367 dvmReportInvoke(self, methodToCall); 5368 } 5369 5370 if (!dvmIsNativeMethod(methodToCall)) { 5371 /* 5372 * "Call" interpreted code. Reposition the PC, update the 5373 * frame pointer and other local state, and continue. 5374 */ 5375 curMethod = methodToCall; 5376 self->interpSave.method = curMethod; 5377 methodClassDex = curMethod->clazz->pDvmDex; 5378 pc = methodToCall->insns; 5379 self->interpSave.curFrame = newFp; 5380 fp = newFp; 5381#ifdef EASY_GDB 5382 debugSaveArea = SAVEAREA_FROM_FP(newFp); 5383#endif 5384 self->debugIsMethodEntry = true; // profiling, debugging 5385 ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 5386 curMethod->name, curMethod->shorty); 5387 DUMP_REGS(curMethod, fp, true); // show input args 5388 FINISH(0); // jump to method start 5389 } else { 5390 /* set this up for JNI locals, even if not a JNI native */ 5391 newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 5392 5393 self->interpSave.curFrame = newFp; 5394 5395 DUMP_REGS(methodToCall, newFp, true); // show input args 5396 5397 if (self->interpBreak.ctl.subMode != 0) { 5398 dvmReportPreNativeInvoke(methodToCall, self, newSaveArea->prevFrame); 5399 } 5400 5401 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor, 5402 methodToCall->name, methodToCall->shorty); 5403 5404 /* 5405 * Jump through native call bridge. Because we leave no 5406 * space for locals on native calls, "newFp" points directly 5407 * to the method arguments. 5408 */ 5409 (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self); 5410 5411 if (self->interpBreak.ctl.subMode != 0) { 5412 dvmReportPostNativeInvoke(methodToCall, self, newSaveArea->prevFrame); 5413 } 5414 5415 /* pop frame off */ 5416 dvmPopJniLocals(self, newSaveArea); 5417 self->interpSave.curFrame = newSaveArea->prevFrame; 5418 fp = newSaveArea->prevFrame; 5419 5420 /* 5421 * If the native code threw an exception, or interpreted code 5422 * invoked by the native call threw one and nobody has cleared 5423 * it, jump to our local exception handling. 5424 */ 5425 if (dvmCheckException(self)) { 5426 LOGV("Exception thrown by/below native code"); 5427 GOTO_exceptionThrown(); 5428 } 5429 5430 ILOGD("> retval=0x%llx (leaving native)", retval.j); 5431 ILOGD("> (return from native %s.%s to %s.%s %s)", 5432 methodToCall->clazz->descriptor, methodToCall->name, 5433 curMethod->clazz->descriptor, curMethod->name, 5434 curMethod->shorty); 5435 5436 //u2 invokeInstr = INST_INST(FETCH(0)); 5437 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 5438 invokeInstr <= OP_INVOKE_INTERFACE*/) 5439 { 5440 FINISH(3); 5441 } else { 5442 //LOGE("Unknown invoke instr %02x at %d", 5443 // invokeInstr, (int) (pc - curMethod->insns)); 5444 assert(false); 5445 } 5446 } 5447 } 5448 assert(false); // should not get here 5449GOTO_TARGET_END 5450 5451/* File: cstubs/enddefs.cpp */ 5452 5453/* undefine "magic" name remapping */ 5454#undef retval 5455#undef pc 5456#undef fp 5457#undef curMethod 5458#undef methodClassDex 5459#undef self 5460#undef debugTrackedRefStart 5461 5462