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