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