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