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