blob: 83c612885e681bf574e538c3fb8e6290dbb2b07b [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/*
Andy McFadden529d6b82011-02-10 15:32:16 -080061 * Some architectures require 64-bit alignment for access to 64-bit data
62 * types. We can't just use pointers to copy 64-bit values out of our
63 * interpreted register set, because gcc may assume the pointer target is
64 * aligned and generate invalid code.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080065 *
Andy McFadden529d6b82011-02-10 15:32:16 -080066 * There are two common approaches:
67 * (1) Use a union that defines a 32-bit pair and a 64-bit value.
68 * (2) Call memcpy().
69 *
70 * Depending upon what compiler you're using and what options are specified,
71 * one may be faster than the other. For example, the compiler might
72 * convert a memcpy() of 8 bytes into a series of instructions and omit
73 * the call. The union version could cause some strange side-effects,
74 * e.g. for a while ARM gcc thought it needed separate storage for each
75 * inlined instance, and generated instructions to zero out ~700 bytes of
76 * stack space at the top of the interpreter.
77 *
78 * The default is to use memcpy(). The current gcc for ARM seems to do
79 * better with the union.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080080 */
81#if defined(__ARM_EABI__)
Andy McFadden529d6b82011-02-10 15:32:16 -080082# define NO_UNALIGN_64__UNION
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080083#endif
84
Andy McFadden529d6b82011-02-10 15:32:16 -080085
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080086//#define LOG_INSTR /* verbose debugging */
87/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
88
89/*
90 * Keep a tally of accesses to fields. Currently only works if full DEX
91 * optimization is disabled.
92 */
93#ifdef PROFILE_FIELD_ACCESS
94# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
95# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
96#else
97# define UPDATE_FIELD_GET(_field) ((void)0)
98# define UPDATE_FIELD_PUT(_field) ((void)0)
99#endif
100
101/*
The Android Open Source Project99409882009-03-18 22:20:24 -0700102 * Export another copy of the PC on every instruction; this is largely
103 * redundant with EXPORT_PC and the debugger code. This value can be
104 * compared against what we have stored on the stack with EXPORT_PC to
105 * help ensure that we aren't missing any export calls.
106 */
107#if WITH_EXTRA_GC_CHECKS > 1
108# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
109#else
110# define EXPORT_EXTRA_PC()
111#endif
112
113/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800114 * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
115 *
116 * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
117 *
118 * We don't advance the program counter until we finish an instruction or
119 * branch, because we do want to have to unroll the PC if there's an
120 * exception.
121 */
122#ifdef CHECK_BRANCH_OFFSETS
123# define ADJUST_PC(_offset) do { \
124 int myoff = _offset; /* deref only once */ \
125 if (pc + myoff < curMethod->insns || \
126 pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
127 { \
128 char* desc; \
129 desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
130 LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
131 myoff, (int) (pc - curMethod->insns), \
132 curMethod->clazz->descriptor, curMethod->name, desc); \
133 free(desc); \
134 dvmAbort(); \
135 } \
136 pc += myoff; \
The Android Open Source Project99409882009-03-18 22:20:24 -0700137 EXPORT_EXTRA_PC(); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800138 } while (false)
139#else
The Android Open Source Project99409882009-03-18 22:20:24 -0700140# define ADJUST_PC(_offset) do { \
141 pc += _offset; \
142 EXPORT_EXTRA_PC(); \
143 } while (false)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800144#endif
145
146/*
147 * If enabled, log instructions as we execute them.
148 */
149#ifdef LOG_INSTR
150# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
151# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
152# define ILOG(_level, ...) do { \
153 char debugStrBuf[128]; \
154 snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
155 if (curMethod != NULL) \
156 LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
157 self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
158 else \
159 LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
160 self->threadId, debugStrBuf); \
161 } while(false)
162void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
163# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
164static const char kSpacing[] = " ";
165#else
166# define ILOGD(...) ((void)0)
167# define ILOGV(...) ((void)0)
168# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
169#endif
170
171/* get a long from an array of u4 */
172static inline s8 getLongFromArray(const u4* ptr, int idx)
173{
174#if defined(NO_UNALIGN_64__UNION)
175 union { s8 ll; u4 parts[2]; } conv;
176
177 ptr += idx;
178 conv.parts[0] = ptr[0];
179 conv.parts[1] = ptr[1];
180 return conv.ll;
Andy McFadden529d6b82011-02-10 15:32:16 -0800181#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800182 s8 val;
183 memcpy(&val, &ptr[idx], 8);
184 return val;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800185#endif
186}
187
188/* store a long into an array of u4 */
189static inline void putLongToArray(u4* ptr, int idx, s8 val)
190{
191#if defined(NO_UNALIGN_64__UNION)
192 union { s8 ll; u4 parts[2]; } conv;
193
194 ptr += idx;
195 conv.ll = val;
196 ptr[0] = conv.parts[0];
197 ptr[1] = conv.parts[1];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800198#else
Andy McFadden529d6b82011-02-10 15:32:16 -0800199 memcpy(&ptr[idx], &val, 8);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800200#endif
201}
202
203/* get a double from an array of u4 */
204static inline double getDoubleFromArray(const u4* ptr, int idx)
205{
206#if defined(NO_UNALIGN_64__UNION)
207 union { double d; u4 parts[2]; } conv;
208
209 ptr += idx;
210 conv.parts[0] = ptr[0];
211 conv.parts[1] = ptr[1];
212 return conv.d;
Andy McFadden529d6b82011-02-10 15:32:16 -0800213#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800214 double dval;
215 memcpy(&dval, &ptr[idx], 8);
216 return dval;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800217#endif
218}
219
220/* store a double into an array of u4 */
221static inline void putDoubleToArray(u4* ptr, int idx, double dval)
222{
223#if defined(NO_UNALIGN_64__UNION)
224 union { double d; u4 parts[2]; } conv;
225
226 ptr += idx;
227 conv.d = dval;
228 ptr[0] = conv.parts[0];
229 ptr[1] = conv.parts[1];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800230#else
Andy McFadden529d6b82011-02-10 15:32:16 -0800231 memcpy(&ptr[idx], &dval, 8);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800232#endif
233}
234
235/*
236 * If enabled, validate the register number on every access. Otherwise,
237 * just do an array access.
238 *
239 * Assumes the existence of "u4* fp".
240 *
241 * "_idx" may be referenced more than once.
242 */
243#ifdef CHECK_REGISTER_INDICES
244# define GET_REGISTER(_idx) \
245 ( (_idx) < curMethod->registersSize ? \
246 (fp[(_idx)]) : (assert(!"bad reg"),1969) )
247# define SET_REGISTER(_idx, _val) \
248 ( (_idx) < curMethod->registersSize ? \
249 (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
250# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
251# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
252# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
253# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
254# define GET_REGISTER_WIDE(_idx) \
255 ( (_idx) < curMethod->registersSize-1 ? \
256 getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
257# define SET_REGISTER_WIDE(_idx, _val) \
258 ( (_idx) < curMethod->registersSize-1 ? \
259 putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
260# define GET_REGISTER_FLOAT(_idx) \
261 ( (_idx) < curMethod->registersSize ? \
262 (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
263# define SET_REGISTER_FLOAT(_idx, _val) \
264 ( (_idx) < curMethod->registersSize ? \
265 (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
266# define GET_REGISTER_DOUBLE(_idx) \
267 ( (_idx) < curMethod->registersSize-1 ? \
268 getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
269# define SET_REGISTER_DOUBLE(_idx, _val) \
270 ( (_idx) < curMethod->registersSize-1 ? \
271 putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
272#else
273# define GET_REGISTER(_idx) (fp[(_idx)])
274# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
275# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
276# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
277# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
278# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
279# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
280# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
281# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
282# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
283# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
284# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
285#endif
286
287/*
288 * Get 16 bits from the specified offset of the program counter. We always
289 * want to load 16 bits at a time from the instruction stream -- it's more
290 * efficient than 8 and won't have the alignment problems that 32 might.
291 *
292 * Assumes existence of "const u2* pc".
293 */
294#define FETCH(_offset) (pc[(_offset)])
295
296/*
297 * Extract instruction byte from 16-bit fetch (_inst is a u2).
298 */
299#define INST_INST(_inst) ((_inst) & 0xff)
300
301/*
Andy McFadden96516932009-10-28 17:39:02 -0700302 * Replace the opcode (used when handling breakpoints). _opcode is a u1.
303 */
304#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
305
306/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800307 * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
308 */
309#define INST_A(_inst) (((_inst) >> 8) & 0x0f)
310#define INST_B(_inst) ((_inst) >> 12)
311
312/*
313 * Get the 8-bit "vAA" 8-bit register index from the instruction word.
314 * (_inst is u2)
315 */
316#define INST_AA(_inst) ((_inst) >> 8)
317
318/*
319 * The current PC must be available to Throwable constructors, e.g.
320 * those created by dvmThrowException(), so that the exception stack
321 * trace can be generated correctly. If we don't do this, the offset
322 * within the current method won't be shown correctly. See the notes
323 * in Exception.c.
324 *
The Android Open Source Project99409882009-03-18 22:20:24 -0700325 * This is also used to determine the address for precise GC.
326 *
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800327 * Assumes existence of "u4* fp" and "const u2* pc".
328 */
329#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
330
331/*
332 * Determine if we need to switch to a different interpreter. "_current"
333 * is either INTERP_STD or INTERP_DBG. It should be fixed for a given
334 * interpreter generation file, which should remove the outer conditional
335 * from the following.
336 *
337 * If we're building without debug and profiling support, we never switch.
338 */
Ben Chengba4fc8b2009-06-01 13:00:29 -0700339#if defined(WITH_JIT)
340# define NEED_INTERP_SWITCH(_current) ( \
341 (_current == INTERP_STD) ? \
Bill Buzbee5540f6e2010-02-08 10:41:32 -0800342 dvmJitDebuggerOrProfilerActive() : !dvmJitDebuggerOrProfilerActive() )
Ben Chengba4fc8b2009-06-01 13:00:29 -0700343#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800344# define NEED_INTERP_SWITCH(_current) ( \
345 (_current == INTERP_STD) ? \
346 dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
Ben Chengba4fc8b2009-06-01 13:00:29 -0700347#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800348
349/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800350 * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
351 * pc has already been exported to the stack.
352 *
353 * Perform additional checks on debug builds.
354 *
355 * Use this to check for NULL when the instruction handler calls into
356 * something that could throw an exception (so we have already called
357 * EXPORT_PC at the top).
358 */
359static inline bool checkForNull(Object* obj)
360{
361 if (obj == NULL) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800362 dvmThrowNullPointerException(NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800363 return false;
364 }
365#ifdef WITH_EXTRA_OBJECT_VALIDATION
366 if (!dvmIsValidObject(obj)) {
367 LOGE("Invalid object %p\n", obj);
368 dvmAbort();
369 }
370#endif
371#ifndef NDEBUG
372 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
373 /* probable heap corruption */
374 LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
375 dvmAbort();
376 }
377#endif
378 return true;
379}
380
381/*
382 * Check to see if "obj" is NULL. If so, export the PC into the stack
383 * frame and throw an exception.
384 *
385 * Perform additional checks on debug builds.
386 *
387 * Use this to check for NULL when the instruction handler doesn't do
388 * anything else that can throw an exception.
389 */
390static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
391{
392 if (obj == NULL) {
393 EXPORT_PC();
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800394 dvmThrowNullPointerException(NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800395 return false;
396 }
397#ifdef WITH_EXTRA_OBJECT_VALIDATION
398 if (!dvmIsValidObject(obj)) {
399 LOGE("Invalid object %p\n", obj);
400 dvmAbort();
401 }
402#endif
403#ifndef NDEBUG
404 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
405 /* probable heap corruption */
406 LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
407 dvmAbort();
408 }
409#endif
410 return true;
411}
412
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800413/* File: portable/portstd.c */
414#define INTERP_FUNC_NAME dvmInterpretStd
415#define INTERP_TYPE INTERP_STD
416
417#define CHECK_DEBUG_AND_PROF() ((void)0)
418
Ben Chengfc075c22010-05-28 15:20:08 -0700419#define CHECK_JIT_BOOL() (false)
420#define CHECK_JIT_VOID()
Bill Buzbee1b3da592011-02-03 07:38:22 -0800421#define END_JIT_TSELECT() ((void)0)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700422
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800423/* File: portable/stubdefs.c */
424/*
425 * In the C mterp stubs, "goto" is a function call followed immediately
426 * by a return.
427 */
428
429#define GOTO_TARGET_DECL(_target, ...)
430
431#define GOTO_TARGET(_target, ...) _target:
432
433#define GOTO_TARGET_END
434
435/* ugh */
436#define STUB_HACK(x)
437
438/*
439 * Instruction framing. For a switch-oriented implementation this is
440 * case/break, for a threaded implementation it's a goto label and an
441 * instruction fetch/computed goto.
442 *
443 * Assumes the existence of "const u2* pc" and (for threaded operation)
444 * "u2 inst".
Andy McFadden96516932009-10-28 17:39:02 -0700445 *
446 * TODO: remove "switch" version.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800447 */
448#ifdef THREADED_INTERP
449# define H(_op) &&op_##_op
450# define HANDLE_OPCODE(_op) op_##_op:
451# define FINISH(_offset) { \
452 ADJUST_PC(_offset); \
453 inst = FETCH(0); \
454 CHECK_DEBUG_AND_PROF(); \
455 CHECK_TRACKED_REFS(); \
Ben Chengfc075c22010-05-28 15:20:08 -0700456 if (CHECK_JIT_BOOL()) GOTO_bail_switch(); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800457 goto *handlerTable[INST_INST(inst)]; \
458 }
Andy McFadden96516932009-10-28 17:39:02 -0700459# define FINISH_BKPT(_opcode) { \
460 goto *handlerTable[_opcode]; \
461 }
jeffhao71eee1f2011-01-04 14:18:54 -0800462# define DISPATCH_EXTENDED(_opcode) { \
463 goto *handlerTable[0x100 + _opcode]; \
464 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800465#else
466# define HANDLE_OPCODE(_op) case _op:
467# define FINISH(_offset) { ADJUST_PC(_offset); break; }
Andy McFadden96516932009-10-28 17:39:02 -0700468# define FINISH_BKPT(opcode) { > not implemented < }
jeffhao71eee1f2011-01-04 14:18:54 -0800469# define DISPATCH_EXTENDED(opcode) goto case (0x100 + opcode);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800470#endif
471
472#define OP_END
473
474#if defined(WITH_TRACKREF_CHECKS)
475# define CHECK_TRACKED_REFS() \
476 dvmInterpCheckTrackedRefs(self, curMethod, debugTrackedRefStart)
477#else
478# define CHECK_TRACKED_REFS() ((void)0)
479#endif
480
481
482/*
483 * The "goto" targets just turn into goto statements. The "arguments" are
484 * passed through local variables.
485 */
486
487#define GOTO_exceptionThrown() goto exceptionThrown;
488
489#define GOTO_returnFromMethod() goto returnFromMethod;
490
jeffhao71eee1f2011-01-04 14:18:54 -0800491#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800492 do { \
493 methodCallRange = _methodCallRange; \
jeffhao71eee1f2011-01-04 14:18:54 -0800494 jumboFormat = _jumboFormat; \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800495 goto _target; \
496 } while(false)
497
498/* for this, the "args" are already in the locals */
499#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod;
500
501#define GOTO_bail() goto bail;
502#define GOTO_bail_switch() goto bail_switch;
503
504/*
505 * Periodically check for thread suspension.
506 *
507 * While we're at it, see if a debugger has attached or the profiler has
508 * started. If so, switch to a different "goto" table.
509 */
510#define PERIODIC_CHECKS(_entryPoint, _pcadj) { \
The Android Open Source Project99409882009-03-18 22:20:24 -0700511 if (dvmCheckSuspendQuick(self)) { \
512 EXPORT_PC(); /* need for precise GC */ \
513 dvmCheckSuspendPending(self); \
514 } \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800515 if (NEED_INTERP_SWITCH(INTERP_TYPE)) { \
516 ADJUST_PC(_pcadj); \
517 interpState->entryPoint = _entryPoint; \
518 LOGVV("threadid=%d: switch to %s ep=%d adj=%d\n", \
519 self->threadId, \
520 (interpState->nextMode == INTERP_STD) ? "STD" : "DBG", \
521 (_entryPoint), (_pcadj)); \
522 GOTO_bail_switch(); \
523 } \
524 }
525
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800526/* File: c/opcommon.c */
527/* forward declarations of goto targets */
jeffhao71eee1f2011-01-04 14:18:54 -0800528GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
529GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
530GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat);
531GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat);
532GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat);
533GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat);
534GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat);
535GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800536GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
537 u2 count, u2 regs);
538GOTO_TARGET_DECL(returnFromMethod);
539GOTO_TARGET_DECL(exceptionThrown);
540
541/*
542 * ===========================================================================
543 *
544 * What follows are opcode definitions shared between multiple opcodes with
545 * minor substitutions handled by the C pre-processor. These should probably
546 * use the mterp substitution mechanism instead, with the code here moved
547 * into common fragment files (like the asm "binop.S"), although it's hard
548 * to give up the C preprocessor in favor of the much simpler text subst.
549 *
550 * ===========================================================================
551 */
552
553#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \
554 HANDLE_OPCODE(_opcode /*vA, vB*/) \
555 vdst = INST_A(inst); \
556 vsrc1 = INST_B(inst); \
557 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
558 SET_REGISTER##_totype(vdst, \
559 GET_REGISTER##_fromtype(vsrc1)); \
560 FINISH(1);
561
562#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \
563 _tovtype, _tortype) \
564 HANDLE_OPCODE(_opcode /*vA, vB*/) \
565 { \
566 /* spec defines specific handling for +/- inf and NaN values */ \
567 _fromvtype val; \
568 _tovtype intMin, intMax, result; \
569 vdst = INST_A(inst); \
570 vsrc1 = INST_B(inst); \
571 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
572 val = GET_REGISTER##_fromrtype(vsrc1); \
573 intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \
574 intMax = ~intMin; \
575 result = (_tovtype) val; \
576 if (val >= intMax) /* +inf */ \
577 result = intMax; \
578 else if (val <= intMin) /* -inf */ \
579 result = intMin; \
580 else if (val != val) /* NaN */ \
581 result = 0; \
582 else \
583 result = (_tovtype) val; \
584 SET_REGISTER##_tortype(vdst, result); \
585 } \
586 FINISH(1);
587
588#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \
589 HANDLE_OPCODE(_opcode /*vA, vB*/) \
590 vdst = INST_A(inst); \
591 vsrc1 = INST_B(inst); \
592 ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \
593 SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \
594 FINISH(1);
595
596/* NOTE: the comparison result is always a signed 4-byte integer */
597#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \
598 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
599 { \
600 int result; \
601 u2 regs; \
602 _varType val1, val2; \
603 vdst = INST_AA(inst); \
604 regs = FETCH(1); \
605 vsrc1 = regs & 0xff; \
606 vsrc2 = regs >> 8; \
607 ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
608 val1 = GET_REGISTER##_type(vsrc1); \
609 val2 = GET_REGISTER##_type(vsrc2); \
610 if (val1 == val2) \
611 result = 0; \
612 else if (val1 < val2) \
613 result = -1; \
614 else if (val1 > val2) \
615 result = 1; \
616 else \
617 result = (_nanVal); \
618 ILOGV("+ result=%d\n", result); \
619 SET_REGISTER(vdst, result); \
620 } \
621 FINISH(2);
622
623#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \
624 HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \
625 vsrc1 = INST_A(inst); \
626 vsrc2 = INST_B(inst); \
627 if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \
628 int branchOffset = (s2)FETCH(1); /* sign-extended */ \
629 ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \
630 branchOffset); \
631 ILOGV("> branch taken"); \
632 if (branchOffset < 0) \
633 PERIODIC_CHECKS(kInterpEntryInstr, branchOffset); \
634 FINISH(branchOffset); \
635 } else { \
636 ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \
637 FINISH(2); \
638 }
639
640#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \
641 HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \
642 vsrc1 = INST_AA(inst); \
643 if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \
644 int branchOffset = (s2)FETCH(1); /* sign-extended */ \
645 ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \
646 ILOGV("> branch taken"); \
647 if (branchOffset < 0) \
648 PERIODIC_CHECKS(kInterpEntryInstr, branchOffset); \
649 FINISH(branchOffset); \
650 } else { \
651 ILOGV("|if-%s v%d,-", (_opname), vsrc1); \
652 FINISH(2); \
653 }
654
655#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \
656 HANDLE_OPCODE(_opcode /*vA, vB*/) \
657 vdst = INST_A(inst); \
658 vsrc1 = INST_B(inst); \
659 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
660 SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \
661 FINISH(1);
662
663#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \
664 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
665 { \
666 u2 srcRegs; \
667 vdst = INST_AA(inst); \
668 srcRegs = FETCH(1); \
669 vsrc1 = srcRegs & 0xff; \
670 vsrc2 = srcRegs >> 8; \
671 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
672 if (_chkdiv != 0) { \
673 s4 firstVal, secondVal, result; \
674 firstVal = GET_REGISTER(vsrc1); \
675 secondVal = GET_REGISTER(vsrc2); \
676 if (secondVal == 0) { \
677 EXPORT_PC(); \
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800678 dvmThrowArithmeticException("divide by zero"); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800679 GOTO_exceptionThrown(); \
680 } \
681 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
682 if (_chkdiv == 1) \
683 result = firstVal; /* division */ \
684 else \
685 result = 0; /* remainder */ \
686 } else { \
687 result = firstVal _op secondVal; \
688 } \
689 SET_REGISTER(vdst, result); \
690 } else { \
691 /* non-div/rem case */ \
692 SET_REGISTER(vdst, \
693 (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \
694 } \
695 } \
696 FINISH(2);
697
698#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \
699 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
700 { \
701 u2 srcRegs; \
702 vdst = INST_AA(inst); \
703 srcRegs = FETCH(1); \
704 vsrc1 = srcRegs & 0xff; \
705 vsrc2 = srcRegs >> 8; \
706 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
707 SET_REGISTER(vdst, \
708 _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \
709 } \
710 FINISH(2);
711
712#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \
713 HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \
714 vdst = INST_A(inst); \
715 vsrc1 = INST_B(inst); \
716 vsrc2 = FETCH(1); \
717 ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \
718 (_opname), vdst, vsrc1, vsrc2); \
719 if (_chkdiv != 0) { \
720 s4 firstVal, result; \
721 firstVal = GET_REGISTER(vsrc1); \
722 if ((s2) vsrc2 == 0) { \
723 EXPORT_PC(); \
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800724 dvmThrowArithmeticException("divide by zero"); \
725 GOTO_exceptionThrown(); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800726 } \
727 if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \
728 /* won't generate /lit16 instr for this; check anyway */ \
729 if (_chkdiv == 1) \
730 result = firstVal; /* division */ \
731 else \
732 result = 0; /* remainder */ \
733 } else { \
734 result = firstVal _op (s2) vsrc2; \
735 } \
736 SET_REGISTER(vdst, result); \
737 } else { \
738 /* non-div/rem case */ \
739 SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \
740 } \
741 FINISH(2);
742
743#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \
744 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
745 { \
746 u2 litInfo; \
747 vdst = INST_AA(inst); \
748 litInfo = FETCH(1); \
749 vsrc1 = litInfo & 0xff; \
750 vsrc2 = litInfo >> 8; /* constant */ \
751 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
752 (_opname), vdst, vsrc1, vsrc2); \
753 if (_chkdiv != 0) { \
754 s4 firstVal, result; \
755 firstVal = GET_REGISTER(vsrc1); \
756 if ((s1) vsrc2 == 0) { \
757 EXPORT_PC(); \
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800758 dvmThrowArithmeticException("divide by zero"); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800759 GOTO_exceptionThrown(); \
760 } \
761 if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \
762 if (_chkdiv == 1) \
763 result = firstVal; /* division */ \
764 else \
765 result = 0; /* remainder */ \
766 } else { \
767 result = firstVal _op ((s1) vsrc2); \
768 } \
769 SET_REGISTER(vdst, result); \
770 } else { \
771 SET_REGISTER(vdst, \
772 (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \
773 } \
774 } \
775 FINISH(2);
776
777#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \
778 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
779 { \
780 u2 litInfo; \
781 vdst = INST_AA(inst); \
782 litInfo = FETCH(1); \
783 vsrc1 = litInfo & 0xff; \
784 vsrc2 = litInfo >> 8; /* constant */ \
785 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
786 (_opname), vdst, vsrc1, vsrc2); \
787 SET_REGISTER(vdst, \
788 _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \
789 } \
790 FINISH(2);
791
792#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \
793 HANDLE_OPCODE(_opcode /*vA, vB*/) \
794 vdst = INST_A(inst); \
795 vsrc1 = INST_B(inst); \
796 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
797 if (_chkdiv != 0) { \
798 s4 firstVal, secondVal, result; \
799 firstVal = GET_REGISTER(vdst); \
800 secondVal = GET_REGISTER(vsrc1); \
801 if (secondVal == 0) { \
802 EXPORT_PC(); \
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800803 dvmThrowArithmeticException("divide by zero"); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800804 GOTO_exceptionThrown(); \
805 } \
806 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
807 if (_chkdiv == 1) \
808 result = firstVal; /* division */ \
809 else \
810 result = 0; /* remainder */ \
811 } else { \
812 result = firstVal _op secondVal; \
813 } \
814 SET_REGISTER(vdst, result); \
815 } else { \
816 SET_REGISTER(vdst, \
817 (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \
818 } \
819 FINISH(1);
820
821#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \
822 HANDLE_OPCODE(_opcode /*vA, vB*/) \
823 vdst = INST_A(inst); \
824 vsrc1 = INST_B(inst); \
825 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
826 SET_REGISTER(vdst, \
827 _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \
828 FINISH(1);
829
830#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \
831 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
832 { \
833 u2 srcRegs; \
834 vdst = INST_AA(inst); \
835 srcRegs = FETCH(1); \
836 vsrc1 = srcRegs & 0xff; \
837 vsrc2 = srcRegs >> 8; \
838 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
839 if (_chkdiv != 0) { \
840 s8 firstVal, secondVal, result; \
841 firstVal = GET_REGISTER_WIDE(vsrc1); \
842 secondVal = GET_REGISTER_WIDE(vsrc2); \
843 if (secondVal == 0LL) { \
844 EXPORT_PC(); \
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800845 dvmThrowArithmeticException("divide by zero"); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800846 GOTO_exceptionThrown(); \
847 } \
848 if ((u8)firstVal == 0x8000000000000000ULL && \
849 secondVal == -1LL) \
850 { \
851 if (_chkdiv == 1) \
852 result = firstVal; /* division */ \
853 else \
854 result = 0; /* remainder */ \
855 } else { \
856 result = firstVal _op secondVal; \
857 } \
858 SET_REGISTER_WIDE(vdst, result); \
859 } else { \
860 SET_REGISTER_WIDE(vdst, \
861 (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
862 } \
863 } \
864 FINISH(2);
865
866#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \
867 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
868 { \
869 u2 srcRegs; \
870 vdst = INST_AA(inst); \
871 srcRegs = FETCH(1); \
872 vsrc1 = srcRegs & 0xff; \
873 vsrc2 = srcRegs >> 8; \
874 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
875 SET_REGISTER_WIDE(vdst, \
876 _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
877 } \
878 FINISH(2);
879
880#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \
881 HANDLE_OPCODE(_opcode /*vA, vB*/) \
882 vdst = INST_A(inst); \
883 vsrc1 = INST_B(inst); \
884 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
885 if (_chkdiv != 0) { \
886 s8 firstVal, secondVal, result; \
887 firstVal = GET_REGISTER_WIDE(vdst); \
888 secondVal = GET_REGISTER_WIDE(vsrc1); \
889 if (secondVal == 0LL) { \
890 EXPORT_PC(); \
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800891 dvmThrowArithmeticException("divide by zero"); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800892 GOTO_exceptionThrown(); \
893 } \
894 if ((u8)firstVal == 0x8000000000000000ULL && \
895 secondVal == -1LL) \
896 { \
897 if (_chkdiv == 1) \
898 result = firstVal; /* division */ \
899 else \
900 result = 0; /* remainder */ \
901 } else { \
902 result = firstVal _op secondVal; \
903 } \
904 SET_REGISTER_WIDE(vdst, result); \
905 } else { \
906 SET_REGISTER_WIDE(vdst, \
907 (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
908 } \
909 FINISH(1);
910
911#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \
912 HANDLE_OPCODE(_opcode /*vA, vB*/) \
913 vdst = INST_A(inst); \
914 vsrc1 = INST_B(inst); \
915 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
916 SET_REGISTER_WIDE(vdst, \
917 _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
918 FINISH(1);
919
920#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \
921 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
922 { \
923 u2 srcRegs; \
924 vdst = INST_AA(inst); \
925 srcRegs = FETCH(1); \
926 vsrc1 = srcRegs & 0xff; \
927 vsrc2 = srcRegs >> 8; \
928 ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
929 SET_REGISTER_FLOAT(vdst, \
930 GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \
931 } \
932 FINISH(2);
933
934#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \
935 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
936 { \
937 u2 srcRegs; \
938 vdst = INST_AA(inst); \
939 srcRegs = FETCH(1); \
940 vsrc1 = srcRegs & 0xff; \
941 vsrc2 = srcRegs >> 8; \
942 ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
943 SET_REGISTER_DOUBLE(vdst, \
944 GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \
945 } \
946 FINISH(2);
947
948#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \
949 HANDLE_OPCODE(_opcode /*vA, vB*/) \
950 vdst = INST_A(inst); \
951 vsrc1 = INST_B(inst); \
952 ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \
953 SET_REGISTER_FLOAT(vdst, \
954 GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \
955 FINISH(1);
956
957#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \
958 HANDLE_OPCODE(_opcode /*vA, vB*/) \
959 vdst = INST_A(inst); \
960 vsrc1 = INST_B(inst); \
961 ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \
962 SET_REGISTER_DOUBLE(vdst, \
963 GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \
964 FINISH(1);
965
966#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \
967 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
968 { \
969 ArrayObject* arrayObj; \
970 u2 arrayInfo; \
971 EXPORT_PC(); \
972 vdst = INST_AA(inst); \
973 arrayInfo = FETCH(1); \
974 vsrc1 = arrayInfo & 0xff; /* array ptr */ \
975 vsrc2 = arrayInfo >> 8; /* index */ \
976 ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
977 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
978 if (!checkForNull((Object*) arrayObj)) \
979 GOTO_exceptionThrown(); \
980 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
Elliott Hughes00160242010-10-20 17:14:57 -0700981 dvmThrowAIOOBE(GET_REGISTER(vsrc2), arrayObj->length); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800982 GOTO_exceptionThrown(); \
983 } \
984 SET_REGISTER##_regsize(vdst, \
985 ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
986 ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
987 } \
988 FINISH(2);
989
990#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
991 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
992 { \
993 ArrayObject* arrayObj; \
994 u2 arrayInfo; \
995 EXPORT_PC(); \
996 vdst = INST_AA(inst); /* AA: source value */ \
997 arrayInfo = FETCH(1); \
998 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
999 vsrc2 = arrayInfo >> 8; /* CC: index */ \
1000 ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
1001 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
1002 if (!checkForNull((Object*) arrayObj)) \
1003 GOTO_exceptionThrown(); \
1004 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
Elliott Hughes00160242010-10-20 17:14:57 -07001005 dvmThrowAIOOBE(GET_REGISTER(vsrc2), arrayObj->length); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001006 GOTO_exceptionThrown(); \
1007 } \
1008 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
1009 ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
1010 GET_REGISTER##_regsize(vdst); \
1011 } \
1012 FINISH(2);
1013
1014/*
1015 * It's possible to get a bad value out of a field with sub-32-bit stores
1016 * because the -quick versions always operate on 32 bits. Consider:
1017 * short foo = -1 (sets a 32-bit register to 0xffffffff)
1018 * iput-quick foo (writes all 32 bits to the field)
1019 * short bar = 1 (sets a 32-bit register to 0x00000001)
1020 * iput-short (writes the low 16 bits to the field)
1021 * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
1022 * This can only happen when optimized and non-optimized code has interleaved
1023 * access to the same field. This is unlikely but possible.
1024 *
1025 * The easiest way to fix this is to always read/write 32 bits at a time. On
1026 * a device with a 16-bit data bus this is sub-optimal. (The alternative
1027 * approach is to have sub-int versions of iget-quick, but now we're wasting
1028 * Dalvik instruction space and making it less likely that handler code will
1029 * already be in the CPU i-cache.)
1030 */
1031#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
1032 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1033 { \
1034 InstField* ifield; \
1035 Object* obj; \
1036 EXPORT_PC(); \
1037 vdst = INST_A(inst); \
1038 vsrc1 = INST_B(inst); /* object ptr */ \
1039 ref = FETCH(1); /* field ref */ \
1040 ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1041 obj = (Object*) GET_REGISTER(vsrc1); \
1042 if (!checkForNull(obj)) \
1043 GOTO_exceptionThrown(); \
1044 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1045 if (ifield == NULL) { \
1046 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1047 if (ifield == NULL) \
1048 GOTO_exceptionThrown(); \
1049 } \
1050 SET_REGISTER##_regsize(vdst, \
1051 dvmGetField##_ftype(obj, ifield->byteOffset)); \
1052 ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
1053 (u8) GET_REGISTER##_regsize(vdst)); \
1054 UPDATE_FIELD_GET(&ifield->field); \
1055 } \
1056 FINISH(2);
1057
jeffhao71eee1f2011-01-04 14:18:54 -08001058#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1059 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
1060 { \
1061 InstField* ifield; \
1062 Object* obj; \
1063 EXPORT_PC(); \
1064 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1065 vdst = FETCH(3); \
1066 vsrc1 = FETCH(4); /* object ptr */ \
1067 ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
1068 (_opname), vdst, vsrc1, ref); \
1069 obj = (Object*) GET_REGISTER(vsrc1); \
1070 if (!checkForNull(obj)) \
1071 GOTO_exceptionThrown(); \
1072 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1073 if (ifield == NULL) { \
1074 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1075 if (ifield == NULL) \
1076 GOTO_exceptionThrown(); \
1077 } \
1078 SET_REGISTER##_regsize(vdst, \
1079 dvmGetField##_ftype(obj, ifield->byteOffset)); \
1080 ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
1081 (u8) GET_REGISTER##_regsize(vdst)); \
1082 UPDATE_FIELD_GET(&ifield->field); \
1083 } \
1084 FINISH(5);
1085
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001086#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
1087 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1088 { \
1089 Object* obj; \
1090 vdst = INST_A(inst); \
1091 vsrc1 = INST_B(inst); /* object ptr */ \
1092 ref = FETCH(1); /* field offset */ \
1093 ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
1094 (_opname), vdst, vsrc1, ref); \
1095 obj = (Object*) GET_REGISTER(vsrc1); \
1096 if (!checkForNullExportPC(obj, fp, pc)) \
1097 GOTO_exceptionThrown(); \
1098 SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
1099 ILOGV("+ IGETQ %d=0x%08llx", ref, \
1100 (u8) GET_REGISTER##_regsize(vdst)); \
1101 } \
1102 FINISH(2);
1103
1104#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
1105 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1106 { \
1107 InstField* ifield; \
1108 Object* obj; \
1109 EXPORT_PC(); \
1110 vdst = INST_A(inst); \
1111 vsrc1 = INST_B(inst); /* object ptr */ \
1112 ref = FETCH(1); /* field ref */ \
1113 ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1114 obj = (Object*) GET_REGISTER(vsrc1); \
1115 if (!checkForNull(obj)) \
1116 GOTO_exceptionThrown(); \
1117 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1118 if (ifield == NULL) { \
1119 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1120 if (ifield == NULL) \
1121 GOTO_exceptionThrown(); \
1122 } \
1123 dvmSetField##_ftype(obj, ifield->byteOffset, \
1124 GET_REGISTER##_regsize(vdst)); \
1125 ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
1126 (u8) GET_REGISTER##_regsize(vdst)); \
1127 UPDATE_FIELD_PUT(&ifield->field); \
1128 } \
1129 FINISH(2);
1130
jeffhao71eee1f2011-01-04 14:18:54 -08001131#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1132 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
1133 { \
1134 InstField* ifield; \
1135 Object* obj; \
1136 EXPORT_PC(); \
1137 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1138 vdst = FETCH(3); \
1139 vsrc1 = FETCH(4); /* object ptr */ \
1140 ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
1141 (_opname), vdst, vsrc1, ref); \
1142 obj = (Object*) GET_REGISTER(vsrc1); \
1143 if (!checkForNull(obj)) \
1144 GOTO_exceptionThrown(); \
1145 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1146 if (ifield == NULL) { \
1147 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1148 if (ifield == NULL) \
1149 GOTO_exceptionThrown(); \
1150 } \
1151 dvmSetField##_ftype(obj, ifield->byteOffset, \
1152 GET_REGISTER##_regsize(vdst)); \
1153 ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
1154 (u8) GET_REGISTER##_regsize(vdst)); \
1155 UPDATE_FIELD_PUT(&ifield->field); \
1156 } \
1157 FINISH(5);
1158
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001159#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
1160 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1161 { \
1162 Object* obj; \
1163 vdst = INST_A(inst); \
1164 vsrc1 = INST_B(inst); /* object ptr */ \
1165 ref = FETCH(1); /* field offset */ \
1166 ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
1167 (_opname), vdst, vsrc1, ref); \
1168 obj = (Object*) GET_REGISTER(vsrc1); \
1169 if (!checkForNullExportPC(obj, fp, pc)) \
1170 GOTO_exceptionThrown(); \
1171 dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
1172 ILOGV("+ IPUTQ %d=0x%08llx", ref, \
1173 (u8) GET_REGISTER##_regsize(vdst)); \
1174 } \
1175 FINISH(2);
1176
Ben Chengdd6e8702010-05-07 13:05:47 -07001177/*
1178 * The JIT needs dvmDexGetResolvedField() to return non-null.
1179 * Since we use the portable interpreter to build the trace, the extra
1180 * checks in HANDLE_SGET_X and HANDLE_SPUT_X are not needed for mterp.
1181 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001182#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
1183 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
1184 { \
1185 StaticField* sfield; \
1186 vdst = INST_AA(inst); \
1187 ref = FETCH(1); /* field ref */ \
1188 ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
1189 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1190 if (sfield == NULL) { \
1191 EXPORT_PC(); \
1192 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1193 if (sfield == NULL) \
1194 GOTO_exceptionThrown(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001195 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001196 END_JIT_TSELECT(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001197 } \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001198 } \
1199 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
1200 ILOGV("+ SGET '%s'=0x%08llx", \
1201 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1202 UPDATE_FIELD_GET(&sfield->field); \
1203 } \
1204 FINISH(2);
1205
jeffhao71eee1f2011-01-04 14:18:54 -08001206#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1207 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
1208 { \
1209 StaticField* sfield; \
1210 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1211 vdst = FETCH(3); \
1212 ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
1213 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1214 if (sfield == NULL) { \
1215 EXPORT_PC(); \
1216 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1217 if (sfield == NULL) \
1218 GOTO_exceptionThrown(); \
1219 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001220 END_JIT_TSELECT(); \
jeffhao71eee1f2011-01-04 14:18:54 -08001221 } \
1222 } \
1223 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
1224 ILOGV("+ SGET '%s'=0x%08llx", \
1225 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1226 UPDATE_FIELD_GET(&sfield->field); \
1227 } \
1228 FINISH(4);
1229
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001230#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
1231 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
1232 { \
1233 StaticField* sfield; \
1234 vdst = INST_AA(inst); \
1235 ref = FETCH(1); /* field ref */ \
1236 ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
1237 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1238 if (sfield == NULL) { \
1239 EXPORT_PC(); \
1240 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1241 if (sfield == NULL) \
1242 GOTO_exceptionThrown(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001243 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001244 END_JIT_TSELECT(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001245 } \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001246 } \
1247 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
1248 ILOGV("+ SPUT '%s'=0x%08llx", \
1249 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1250 UPDATE_FIELD_PUT(&sfield->field); \
1251 } \
1252 FINISH(2);
1253
jeffhao71eee1f2011-01-04 14:18:54 -08001254#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1255 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
1256 { \
1257 StaticField* sfield; \
1258 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1259 vdst = FETCH(3); \
1260 ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
1261 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1262 if (sfield == NULL) { \
1263 EXPORT_PC(); \
1264 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1265 if (sfield == NULL) \
1266 GOTO_exceptionThrown(); \
1267 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001268 END_JIT_TSELECT(); \
jeffhao71eee1f2011-01-04 14:18:54 -08001269 } \
1270 } \
1271 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
1272 ILOGV("+ SPUT '%s'=0x%08llx", \
1273 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1274 UPDATE_FIELD_PUT(&sfield->field); \
1275 } \
1276 FINISH(4);
1277
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001278/* File: portable/entry.c */
1279/*
1280 * Main interpreter loop.
1281 *
1282 * This was written with an ARM implementation in mind.
1283 */
1284bool INTERP_FUNC_NAME(Thread* self, InterpState* interpState)
1285{
1286#if defined(EASY_GDB)
1287 StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->curFrame);
1288#endif
1289#if INTERP_TYPE == INTERP_DBG
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07001290 bool debugIsMethodEntry = false;
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07001291 debugIsMethodEntry = interpState->debugIsMethodEntry;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001292#endif
1293#if defined(WITH_TRACKREF_CHECKS)
1294 int debugTrackedRefStart = interpState->debugTrackedRefStart;
1295#endif
1296 DvmDex* methodClassDex; // curMethod->clazz->pDvmDex
1297 JValue retval;
1298
1299 /* core state */
1300 const Method* curMethod; // method we're interpreting
1301 const u2* pc; // program counter
1302 u4* fp; // frame pointer
1303 u2 inst; // current instruction
1304 /* instruction decoding */
jeffhao71eee1f2011-01-04 14:18:54 -08001305 u4 ref; // 16 or 32-bit quantity fetched directly
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001306 u2 vsrc1, vsrc2, vdst; // usually used for register indexes
1307 /* method call setup */
1308 const Method* methodToCall;
1309 bool methodCallRange;
jeffhao71eee1f2011-01-04 14:18:54 -08001310 bool jumboFormat;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001311
Ben Chengba4fc8b2009-06-01 13:00:29 -07001312
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001313#if defined(THREADED_INTERP)
1314 /* static computed goto table */
1315 DEFINE_GOTO_TABLE(handlerTable);
1316#endif
1317
Ben Chengba4fc8b2009-06-01 13:00:29 -07001318#if defined(WITH_JIT)
1319#if 0
1320 LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n",
1321 interpState->entryPoint,
1322 interpState->pc,
1323 interpState->method->name);
1324#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001325#if INTERP_TYPE == INTERP_DBG
Ben Cheng7a2697d2010-06-07 13:44:23 -07001326 const ClassObject* callsiteClass = NULL;
1327
1328#if defined(WITH_SELF_VERIFICATION)
1329 if (interpState->jitState != kJitSelfVerification) {
1330 interpState->self->shadowSpace->jitExitState = kSVSIdle;
1331 }
1332#endif
1333
Bill Buzbee06bb8392010-01-31 18:53:15 -08001334 /* Check to see if we've got a trace selection request. */
1335 if (
Ben Cheng95cd9ac2010-03-12 16:58:24 -08001336 /*
Ben Chenga4973592010-03-31 11:59:18 -07001337 * Only perform dvmJitCheckTraceRequest if the entry point is
1338 * EntryInstr and the jit state is either kJitTSelectRequest or
1339 * kJitTSelectRequestHot. If debugger/profiler happens to be attached,
1340 * dvmJitCheckTraceRequest will change the jitState to kJitDone but
1341 * but stay in the dbg interpreter.
Ben Cheng95cd9ac2010-03-12 16:58:24 -08001342 */
Ben Chenga4973592010-03-31 11:59:18 -07001343 (interpState->entryPoint == kInterpEntryInstr) &&
1344 (interpState->jitState == kJitTSelectRequest ||
1345 interpState->jitState == kJitTSelectRequestHot) &&
Bill Buzbee06bb8392010-01-31 18:53:15 -08001346 dvmJitCheckTraceRequest(self, interpState)) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001347 interpState->nextMode = INTERP_STD;
Bill Buzbee06bb8392010-01-31 18:53:15 -08001348 //LOGD("Invalid trace request, exiting\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -07001349 return true;
1350 }
Jeff Hao97319a82009-08-12 16:57:15 -07001351#endif /* INTERP_TYPE == INTERP_DBG */
1352#endif /* WITH_JIT */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001353
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001354 /* copy state in */
1355 curMethod = interpState->method;
1356 pc = interpState->pc;
1357 fp = interpState->fp;
1358 retval = interpState->retval; /* only need for kInterpEntryReturn? */
1359
1360 methodClassDex = curMethod->clazz->pDvmDex;
1361
1362 LOGVV("threadid=%d: entry(%s) %s.%s pc=0x%x fp=%p ep=%d\n",
1363 self->threadId, (interpState->nextMode == INTERP_STD) ? "STD" : "DBG",
1364 curMethod->clazz->descriptor, curMethod->name, pc - curMethod->insns,
1365 fp, interpState->entryPoint);
1366
1367 /*
1368 * DEBUG: scramble this to ensure we're not relying on it.
1369 */
1370 methodToCall = (const Method*) -1;
1371
1372#if INTERP_TYPE == INTERP_DBG
1373 if (debugIsMethodEntry) {
1374 ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
1375 curMethod->name);
1376 DUMP_REGS(curMethod, interpState->fp, false);
1377 }
1378#endif
1379
1380 switch (interpState->entryPoint) {
1381 case kInterpEntryInstr:
1382 /* just fall through to instruction loop or threaded kickstart */
1383 break;
1384 case kInterpEntryReturn:
Ben Chengfc075c22010-05-28 15:20:08 -07001385 CHECK_JIT_VOID();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001386 goto returnFromMethod;
1387 case kInterpEntryThrow:
1388 goto exceptionThrown;
1389 default:
1390 dvmAbort();
1391 }
1392
1393#ifdef THREADED_INTERP
1394 FINISH(0); /* fetch and execute first instruction */
1395#else
1396 while (1) {
1397 CHECK_DEBUG_AND_PROF(); /* service debugger and profiling */
1398 CHECK_TRACKED_REFS(); /* check local reference tracking */
1399
1400 /* fetch the next 16 bits from the instruction stream */
1401 inst = FETCH(0);
1402
1403 switch (INST_INST(inst)) {
1404#endif
1405
1406/*--- start of opcodes ---*/
1407
1408/* File: c/OP_NOP.c */
1409HANDLE_OPCODE(OP_NOP)
1410 FINISH(1);
1411OP_END
1412
1413/* File: c/OP_MOVE.c */
1414HANDLE_OPCODE(OP_MOVE /*vA, vB*/)
1415 vdst = INST_A(inst);
1416 vsrc1 = INST_B(inst);
1417 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",
1418 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
1419 kSpacing, vdst, GET_REGISTER(vsrc1));
1420 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1421 FINISH(1);
1422OP_END
1423
1424/* File: c/OP_MOVE_FROM16.c */
1425HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/)
1426 vdst = INST_AA(inst);
1427 vsrc1 = FETCH(1);
1428 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)",
1429 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1,
1430 kSpacing, vdst, GET_REGISTER(vsrc1));
1431 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1432 FINISH(2);
1433OP_END
1434
1435/* File: c/OP_MOVE_16.c */
1436HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/)
1437 vdst = FETCH(1);
1438 vsrc1 = FETCH(2);
1439 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)",
1440 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1,
1441 kSpacing, vdst, GET_REGISTER(vsrc1));
1442 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1443 FINISH(3);
1444OP_END
1445
1446/* File: c/OP_MOVE_WIDE.c */
1447HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/)
1448 /* IMPORTANT: must correctly handle overlapping registers, e.g. both
1449 * "move-wide v6, v7" and "move-wide v7, v6" */
1450 vdst = INST_A(inst);
1451 vsrc1 = INST_B(inst);
1452 ILOGV("|move-wide v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1,
1453 kSpacing+5, vdst, GET_REGISTER_WIDE(vsrc1));
1454 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1455 FINISH(1);
1456OP_END
1457
1458/* File: c/OP_MOVE_WIDE_FROM16.c */
1459HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/)
1460 vdst = INST_AA(inst);
1461 vsrc1 = FETCH(1);
1462 ILOGV("|move-wide/from16 v%d,v%d (v%d=0x%08llx)", vdst, vsrc1,
1463 vdst, GET_REGISTER_WIDE(vsrc1));
1464 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1465 FINISH(2);
1466OP_END
1467
1468/* File: c/OP_MOVE_WIDE_16.c */
1469HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/)
1470 vdst = FETCH(1);
1471 vsrc1 = FETCH(2);
1472 ILOGV("|move-wide/16 v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1,
1473 kSpacing+8, vdst, GET_REGISTER_WIDE(vsrc1));
1474 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1475 FINISH(3);
1476OP_END
1477
1478/* File: c/OP_MOVE_OBJECT.c */
1479/* File: c/OP_MOVE.c */
1480HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/)
1481 vdst = INST_A(inst);
1482 vsrc1 = INST_B(inst);
1483 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",
1484 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
1485 kSpacing, vdst, GET_REGISTER(vsrc1));
1486 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1487 FINISH(1);
1488OP_END
1489
1490
1491/* File: c/OP_MOVE_OBJECT_FROM16.c */
1492/* File: c/OP_MOVE_FROM16.c */
1493HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/)
1494 vdst = INST_AA(inst);
1495 vsrc1 = FETCH(1);
1496 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)",
1497 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1,
1498 kSpacing, vdst, GET_REGISTER(vsrc1));
1499 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1500 FINISH(2);
1501OP_END
1502
1503
1504/* File: c/OP_MOVE_OBJECT_16.c */
1505/* File: c/OP_MOVE_16.c */
1506HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/)
1507 vdst = FETCH(1);
1508 vsrc1 = FETCH(2);
1509 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)",
1510 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1,
1511 kSpacing, vdst, GET_REGISTER(vsrc1));
1512 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1513 FINISH(3);
1514OP_END
1515
1516
1517/* File: c/OP_MOVE_RESULT.c */
1518HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/)
1519 vdst = INST_AA(inst);
1520 ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
1521 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object",
1522 vdst, kSpacing+4, vdst,retval.i);
1523 SET_REGISTER(vdst, retval.i);
1524 FINISH(1);
1525OP_END
1526
1527/* File: c/OP_MOVE_RESULT_WIDE.c */
1528HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/)
1529 vdst = INST_AA(inst);
1530 ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j);
1531 SET_REGISTER_WIDE(vdst, retval.j);
1532 FINISH(1);
1533OP_END
1534
1535/* File: c/OP_MOVE_RESULT_OBJECT.c */
1536/* File: c/OP_MOVE_RESULT.c */
1537HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/)
1538 vdst = INST_AA(inst);
1539 ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
1540 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object",
1541 vdst, kSpacing+4, vdst,retval.i);
1542 SET_REGISTER(vdst, retval.i);
1543 FINISH(1);
1544OP_END
1545
1546
1547/* File: c/OP_MOVE_EXCEPTION.c */
1548HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/)
1549 vdst = INST_AA(inst);
1550 ILOGV("|move-exception v%d", vdst);
1551 assert(self->exception != NULL);
1552 SET_REGISTER(vdst, (u4)self->exception);
1553 dvmClearException(self);
1554 FINISH(1);
1555OP_END
1556
1557/* File: c/OP_RETURN_VOID.c */
1558HANDLE_OPCODE(OP_RETURN_VOID /**/)
1559 ILOGV("|return-void");
1560#ifndef NDEBUG
1561 retval.j = 0xababababULL; // placate valgrind
1562#endif
1563 GOTO_returnFromMethod();
1564OP_END
1565
1566/* File: c/OP_RETURN.c */
1567HANDLE_OPCODE(OP_RETURN /*vAA*/)
1568 vsrc1 = INST_AA(inst);
1569 ILOGV("|return%s v%d",
1570 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
1571 retval.i = GET_REGISTER(vsrc1);
1572 GOTO_returnFromMethod();
1573OP_END
1574
1575/* File: c/OP_RETURN_WIDE.c */
1576HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/)
1577 vsrc1 = INST_AA(inst);
1578 ILOGV("|return-wide v%d", vsrc1);
1579 retval.j = GET_REGISTER_WIDE(vsrc1);
1580 GOTO_returnFromMethod();
1581OP_END
1582
1583/* File: c/OP_RETURN_OBJECT.c */
1584/* File: c/OP_RETURN.c */
1585HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/)
1586 vsrc1 = INST_AA(inst);
1587 ILOGV("|return%s v%d",
1588 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
1589 retval.i = GET_REGISTER(vsrc1);
1590 GOTO_returnFromMethod();
1591OP_END
1592
1593
1594/* File: c/OP_CONST_4.c */
1595HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/)
1596 {
1597 s4 tmp;
1598
1599 vdst = INST_A(inst);
1600 tmp = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
1601 ILOGV("|const/4 v%d,#0x%02x", vdst, (s4)tmp);
1602 SET_REGISTER(vdst, tmp);
1603 }
1604 FINISH(1);
1605OP_END
1606
1607/* File: c/OP_CONST_16.c */
1608HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/)
1609 vdst = INST_AA(inst);
1610 vsrc1 = FETCH(1);
1611 ILOGV("|const/16 v%d,#0x%04x", vdst, (s2)vsrc1);
1612 SET_REGISTER(vdst, (s2) vsrc1);
1613 FINISH(2);
1614OP_END
1615
1616/* File: c/OP_CONST.c */
1617HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/)
1618 {
1619 u4 tmp;
1620
1621 vdst = INST_AA(inst);
1622 tmp = FETCH(1);
1623 tmp |= (u4)FETCH(2) << 16;
1624 ILOGV("|const v%d,#0x%08x", vdst, tmp);
1625 SET_REGISTER(vdst, tmp);
1626 }
1627 FINISH(3);
1628OP_END
1629
1630/* File: c/OP_CONST_HIGH16.c */
1631HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/)
1632 vdst = INST_AA(inst);
1633 vsrc1 = FETCH(1);
1634 ILOGV("|const/high16 v%d,#0x%04x0000", vdst, vsrc1);
1635 SET_REGISTER(vdst, vsrc1 << 16);
1636 FINISH(2);
1637OP_END
1638
1639/* File: c/OP_CONST_WIDE_16.c */
1640HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/)
1641 vdst = INST_AA(inst);
1642 vsrc1 = FETCH(1);
1643 ILOGV("|const-wide/16 v%d,#0x%04x", vdst, (s2)vsrc1);
1644 SET_REGISTER_WIDE(vdst, (s2)vsrc1);
1645 FINISH(2);
1646OP_END
1647
1648/* File: c/OP_CONST_WIDE_32.c */
1649HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/)
1650 {
1651 u4 tmp;
1652
1653 vdst = INST_AA(inst);
1654 tmp = FETCH(1);
1655 tmp |= (u4)FETCH(2) << 16;
1656 ILOGV("|const-wide/32 v%d,#0x%08x", vdst, tmp);
1657 SET_REGISTER_WIDE(vdst, (s4) tmp);
1658 }
1659 FINISH(3);
1660OP_END
1661
1662/* File: c/OP_CONST_WIDE.c */
1663HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/)
1664 {
1665 u8 tmp;
1666
1667 vdst = INST_AA(inst);
1668 tmp = FETCH(1);
1669 tmp |= (u8)FETCH(2) << 16;
1670 tmp |= (u8)FETCH(3) << 32;
1671 tmp |= (u8)FETCH(4) << 48;
1672 ILOGV("|const-wide v%d,#0x%08llx", vdst, tmp);
1673 SET_REGISTER_WIDE(vdst, tmp);
1674 }
1675 FINISH(5);
1676OP_END
1677
1678/* File: c/OP_CONST_WIDE_HIGH16.c */
1679HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/)
1680 vdst = INST_AA(inst);
1681 vsrc1 = FETCH(1);
1682 ILOGV("|const-wide/high16 v%d,#0x%04x000000000000", vdst, vsrc1);
1683 SET_REGISTER_WIDE(vdst, ((u8) vsrc1) << 48);
1684 FINISH(2);
1685OP_END
1686
1687/* File: c/OP_CONST_STRING.c */
1688HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/)
1689 {
1690 StringObject* strObj;
1691
1692 vdst = INST_AA(inst);
1693 ref = FETCH(1);
1694 ILOGV("|const-string v%d string@0x%04x", vdst, ref);
1695 strObj = dvmDexGetResolvedString(methodClassDex, ref);
1696 if (strObj == NULL) {
1697 EXPORT_PC();
1698 strObj = dvmResolveString(curMethod->clazz, ref);
1699 if (strObj == NULL)
1700 GOTO_exceptionThrown();
1701 }
1702 SET_REGISTER(vdst, (u4) strObj);
1703 }
1704 FINISH(2);
1705OP_END
1706
1707/* File: c/OP_CONST_STRING_JUMBO.c */
1708HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/)
1709 {
1710 StringObject* strObj;
1711 u4 tmp;
1712
1713 vdst = INST_AA(inst);
1714 tmp = FETCH(1);
1715 tmp |= (u4)FETCH(2) << 16;
1716 ILOGV("|const-string/jumbo v%d string@0x%08x", vdst, tmp);
1717 strObj = dvmDexGetResolvedString(methodClassDex, tmp);
1718 if (strObj == NULL) {
1719 EXPORT_PC();
1720 strObj = dvmResolveString(curMethod->clazz, tmp);
1721 if (strObj == NULL)
1722 GOTO_exceptionThrown();
1723 }
1724 SET_REGISTER(vdst, (u4) strObj);
1725 }
1726 FINISH(3);
1727OP_END
1728
1729/* File: c/OP_CONST_CLASS.c */
1730HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/)
1731 {
1732 ClassObject* clazz;
1733
1734 vdst = INST_AA(inst);
1735 ref = FETCH(1);
1736 ILOGV("|const-class v%d class@0x%04x", vdst, ref);
1737 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1738 if (clazz == NULL) {
1739 EXPORT_PC();
1740 clazz = dvmResolveClass(curMethod->clazz, ref, true);
1741 if (clazz == NULL)
1742 GOTO_exceptionThrown();
1743 }
1744 SET_REGISTER(vdst, (u4) clazz);
1745 }
1746 FINISH(2);
1747OP_END
1748
1749/* File: c/OP_MONITOR_ENTER.c */
1750HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/)
1751 {
1752 Object* obj;
1753
1754 vsrc1 = INST_AA(inst);
1755 ILOGV("|monitor-enter v%d %s(0x%08x)",
1756 vsrc1, kSpacing+6, GET_REGISTER(vsrc1));
1757 obj = (Object*)GET_REGISTER(vsrc1);
1758 if (!checkForNullExportPC(obj, fp, pc))
1759 GOTO_exceptionThrown();
1760 ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
Carl Shapiro01605d22011-02-01 11:32:44 -08001761 EXPORT_PC(); /* need for precise GC */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001762 dvmLockObject(self, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001763 }
1764 FINISH(1);
1765OP_END
1766
1767/* File: c/OP_MONITOR_EXIT.c */
1768HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/)
1769 {
1770 Object* obj;
1771
1772 EXPORT_PC();
1773
1774 vsrc1 = INST_AA(inst);
1775 ILOGV("|monitor-exit v%d %s(0x%08x)",
1776 vsrc1, kSpacing+5, GET_REGISTER(vsrc1));
1777 obj = (Object*)GET_REGISTER(vsrc1);
1778 if (!checkForNull(obj)) {
1779 /*
1780 * The exception needs to be processed at the *following*
1781 * instruction, not the current instruction (see the Dalvik
1782 * spec). Because we're jumping to an exception handler,
1783 * we're not actually at risk of skipping an instruction
1784 * by doing so.
1785 */
1786 ADJUST_PC(1); /* monitor-exit width is 1 */
1787 GOTO_exceptionThrown();
1788 }
1789 ILOGV("+ unlocking %p %s\n", obj, obj->clazz->descriptor);
1790 if (!dvmUnlockObject(self, obj)) {
1791 assert(dvmCheckException(self));
1792 ADJUST_PC(1);
1793 GOTO_exceptionThrown();
1794 }
1795 }
1796 FINISH(1);
1797OP_END
1798
1799/* File: c/OP_CHECK_CAST.c */
1800HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/)
1801 {
1802 ClassObject* clazz;
1803 Object* obj;
1804
1805 EXPORT_PC();
1806
1807 vsrc1 = INST_AA(inst);
1808 ref = FETCH(1); /* class to check against */
1809 ILOGV("|check-cast v%d,class@0x%04x", vsrc1, ref);
1810
1811 obj = (Object*)GET_REGISTER(vsrc1);
1812 if (obj != NULL) {
1813#if defined(WITH_EXTRA_OBJECT_VALIDATION)
1814 if (!checkForNull(obj))
1815 GOTO_exceptionThrown();
1816#endif
1817 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1818 if (clazz == NULL) {
1819 clazz = dvmResolveClass(curMethod->clazz, ref, false);
1820 if (clazz == NULL)
1821 GOTO_exceptionThrown();
1822 }
1823 if (!dvmInstanceof(obj->clazz, clazz)) {
Elliott Hughesc560e302010-11-18 11:49:04 -08001824 dvmThrowClassCastException(obj->clazz, clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001825 GOTO_exceptionThrown();
1826 }
1827 }
1828 }
1829 FINISH(2);
1830OP_END
1831
1832/* File: c/OP_INSTANCE_OF.c */
1833HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/)
1834 {
1835 ClassObject* clazz;
1836 Object* obj;
1837
1838 vdst = INST_A(inst);
1839 vsrc1 = INST_B(inst); /* object to check */
1840 ref = FETCH(1); /* class to check against */
1841 ILOGV("|instance-of v%d,v%d,class@0x%04x", vdst, vsrc1, ref);
1842
1843 obj = (Object*)GET_REGISTER(vsrc1);
1844 if (obj == NULL) {
1845 SET_REGISTER(vdst, 0);
1846 } else {
1847#if defined(WITH_EXTRA_OBJECT_VALIDATION)
1848 if (!checkForNullExportPC(obj, fp, pc))
1849 GOTO_exceptionThrown();
1850#endif
1851 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1852 if (clazz == NULL) {
1853 EXPORT_PC();
1854 clazz = dvmResolveClass(curMethod->clazz, ref, true);
1855 if (clazz == NULL)
1856 GOTO_exceptionThrown();
1857 }
1858 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz));
1859 }
1860 }
1861 FINISH(2);
1862OP_END
1863
1864/* File: c/OP_ARRAY_LENGTH.c */
1865HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/)
1866 {
1867 ArrayObject* arrayObj;
1868
1869 vdst = INST_A(inst);
1870 vsrc1 = INST_B(inst);
1871 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
1872 ILOGV("|array-length v%d,v%d (%p)", vdst, vsrc1, arrayObj);
1873 if (!checkForNullExportPC((Object*) arrayObj, fp, pc))
1874 GOTO_exceptionThrown();
1875 /* verifier guarantees this is an array reference */
1876 SET_REGISTER(vdst, arrayObj->length);
1877 }
1878 FINISH(1);
1879OP_END
1880
1881/* File: c/OP_NEW_INSTANCE.c */
1882HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/)
1883 {
1884 ClassObject* clazz;
1885 Object* newObj;
1886
1887 EXPORT_PC();
1888
1889 vdst = INST_AA(inst);
1890 ref = FETCH(1);
1891 ILOGV("|new-instance v%d,class@0x%04x", vdst, ref);
1892 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1893 if (clazz == NULL) {
1894 clazz = dvmResolveClass(curMethod->clazz, ref, false);
1895 if (clazz == NULL)
1896 GOTO_exceptionThrown();
1897 }
1898
1899 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))
1900 GOTO_exceptionThrown();
1901
1902 /*
Ben Chengdd6e8702010-05-07 13:05:47 -07001903 * The JIT needs dvmDexGetResolvedClass() to return non-null.
1904 * Since we use the portable interpreter to build the trace, this extra
1905 * check is not needed for mterp.
1906 */
1907 if (!dvmDexGetResolvedClass(methodClassDex, ref)) {
Bill Buzbee1b3da592011-02-03 07:38:22 -08001908 /* Class initialization is still ongoing - end the trace */
1909 END_JIT_TSELECT();
Ben Chengdd6e8702010-05-07 13:05:47 -07001910 }
1911
1912 /*
Andy McFaddenb51ea112009-05-08 16:50:17 -07001913 * Verifier now tests for interface/abstract class.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001914 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001915 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
1916 // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
1917 // clazz->descriptor);
1918 // GOTO_exceptionThrown();
1919 //}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001920 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1921 if (newObj == NULL)
1922 GOTO_exceptionThrown();
1923 SET_REGISTER(vdst, (u4) newObj);
1924 }
1925 FINISH(2);
1926OP_END
1927
1928/* File: c/OP_NEW_ARRAY.c */
1929HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/)
1930 {
1931 ClassObject* arrayClass;
1932 ArrayObject* newArray;
1933 s4 length;
1934
1935 EXPORT_PC();
1936
1937 vdst = INST_A(inst);
1938 vsrc1 = INST_B(inst); /* length reg */
1939 ref = FETCH(1);
1940 ILOGV("|new-array v%d,v%d,class@0x%04x (%d elements)",
1941 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1));
1942 length = (s4) GET_REGISTER(vsrc1);
1943 if (length < 0) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001944 dvmThrowNegativeArraySizeException(NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001945 GOTO_exceptionThrown();
1946 }
1947 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
1948 if (arrayClass == NULL) {
1949 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
1950 if (arrayClass == NULL)
1951 GOTO_exceptionThrown();
1952 }
1953 /* verifier guarantees this is an array class */
1954 assert(dvmIsArrayClass(arrayClass));
1955 assert(dvmIsClassInitialized(arrayClass));
1956
1957 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK);
1958 if (newArray == NULL)
1959 GOTO_exceptionThrown();
1960 SET_REGISTER(vdst, (u4) newArray);
1961 }
1962 FINISH(2);
1963OP_END
1964
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001965/* File: c/OP_FILLED_NEW_ARRAY.c */
1966HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08001967 GOTO_invoke(filledNewArray, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001968OP_END
1969
1970/* File: c/OP_FILLED_NEW_ARRAY_RANGE.c */
1971HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08001972 GOTO_invoke(filledNewArray, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001973OP_END
1974
1975/* File: c/OP_FILL_ARRAY_DATA.c */
1976HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/
1977 {
1978 const u2* arrayData;
1979 s4 offset;
1980 ArrayObject* arrayObj;
1981
1982 EXPORT_PC();
1983 vsrc1 = INST_AA(inst);
1984 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
1985 ILOGV("|fill-array-data v%d +0x%04x", vsrc1, offset);
1986 arrayData = pc + offset; // offset in 16-bit units
1987#ifndef NDEBUG
1988 if (arrayData < curMethod->insns ||
1989 arrayData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
1990 {
1991 /* should have been caught in verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001992 dvmThrowInternalError("bad fill array data");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001993 GOTO_exceptionThrown();
1994 }
1995#endif
1996 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
1997 if (!dvmInterpHandleFillArrayData(arrayObj, arrayData)) {
1998 GOTO_exceptionThrown();
1999 }
2000 FINISH(3);
2001 }
2002OP_END
2003
2004/* File: c/OP_THROW.c */
2005HANDLE_OPCODE(OP_THROW /*vAA*/)
2006 {
2007 Object* obj;
2008
Andy McFadden8ba27082010-05-21 12:20:23 -07002009 /*
2010 * We don't create an exception here, but the process of searching
2011 * for a catch block can do class lookups and throw exceptions.
2012 * We need to update the saved PC.
2013 */
2014 EXPORT_PC();
2015
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002016 vsrc1 = INST_AA(inst);
2017 ILOGV("|throw v%d (%p)", vsrc1, (void*)GET_REGISTER(vsrc1));
2018 obj = (Object*) GET_REGISTER(vsrc1);
Andy McFadden8ba27082010-05-21 12:20:23 -07002019 if (!checkForNull(obj)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002020 /* will throw a null pointer exception */
2021 LOGVV("Bad exception\n");
2022 } else {
2023 /* use the requested exception */
2024 dvmSetException(self, obj);
2025 }
2026 GOTO_exceptionThrown();
2027 }
2028OP_END
2029
2030/* File: c/OP_GOTO.c */
2031HANDLE_OPCODE(OP_GOTO /*+AA*/)
2032 vdst = INST_AA(inst);
2033 if ((s1)vdst < 0)
2034 ILOGV("|goto -0x%02x", -((s1)vdst));
2035 else
2036 ILOGV("|goto +0x%02x", ((s1)vdst));
2037 ILOGV("> branch taken");
2038 if ((s1)vdst < 0)
2039 PERIODIC_CHECKS(kInterpEntryInstr, (s1)vdst);
2040 FINISH((s1)vdst);
2041OP_END
2042
2043/* File: c/OP_GOTO_16.c */
2044HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/)
2045 {
2046 s4 offset = (s2) FETCH(1); /* sign-extend next code unit */
2047
2048 if (offset < 0)
2049 ILOGV("|goto/16 -0x%04x", -offset);
2050 else
2051 ILOGV("|goto/16 +0x%04x", offset);
2052 ILOGV("> branch taken");
2053 if (offset < 0)
2054 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2055 FINISH(offset);
2056 }
2057OP_END
2058
2059/* File: c/OP_GOTO_32.c */
2060HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/)
2061 {
2062 s4 offset = FETCH(1); /* low-order 16 bits */
2063 offset |= ((s4) FETCH(2)) << 16; /* high-order 16 bits */
2064
2065 if (offset < 0)
2066 ILOGV("|goto/32 -0x%08x", -offset);
2067 else
2068 ILOGV("|goto/32 +0x%08x", offset);
2069 ILOGV("> branch taken");
2070 if (offset <= 0) /* allowed to branch to self */
2071 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2072 FINISH(offset);
2073 }
2074OP_END
2075
2076/* File: c/OP_PACKED_SWITCH.c */
2077HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/)
2078 {
2079 const u2* switchData;
2080 u4 testVal;
2081 s4 offset;
2082
2083 vsrc1 = INST_AA(inst);
2084 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
2085 ILOGV("|packed-switch v%d +0x%04x", vsrc1, vsrc2);
2086 switchData = pc + offset; // offset in 16-bit units
2087#ifndef NDEBUG
2088 if (switchData < curMethod->insns ||
2089 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
2090 {
2091 /* should have been caught in verifier */
2092 EXPORT_PC();
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08002093 dvmThrowInternalError("bad packed switch");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002094 GOTO_exceptionThrown();
2095 }
2096#endif
2097 testVal = GET_REGISTER(vsrc1);
2098
2099 offset = dvmInterpHandlePackedSwitch(switchData, testVal);
2100 ILOGV("> branch taken (0x%04x)\n", offset);
2101 if (offset <= 0) /* uncommon */
2102 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2103 FINISH(offset);
2104 }
2105OP_END
2106
2107/* File: c/OP_SPARSE_SWITCH.c */
2108HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/)
2109 {
2110 const u2* switchData;
2111 u4 testVal;
2112 s4 offset;
2113
2114 vsrc1 = INST_AA(inst);
2115 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
2116 ILOGV("|sparse-switch v%d +0x%04x", vsrc1, vsrc2);
2117 switchData = pc + offset; // offset in 16-bit units
2118#ifndef NDEBUG
2119 if (switchData < curMethod->insns ||
2120 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
2121 {
2122 /* should have been caught in verifier */
2123 EXPORT_PC();
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08002124 dvmThrowInternalError("bad sparse switch");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002125 GOTO_exceptionThrown();
2126 }
2127#endif
2128 testVal = GET_REGISTER(vsrc1);
2129
2130 offset = dvmInterpHandleSparseSwitch(switchData, testVal);
2131 ILOGV("> branch taken (0x%04x)\n", offset);
2132 if (offset <= 0) /* uncommon */
2133 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2134 FINISH(offset);
2135 }
2136OP_END
2137
2138/* File: c/OP_CMPL_FLOAT.c */
2139HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1)
2140OP_END
2141
2142/* File: c/OP_CMPG_FLOAT.c */
2143HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1)
2144OP_END
2145
2146/* File: c/OP_CMPL_DOUBLE.c */
2147HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1)
2148OP_END
2149
2150/* File: c/OP_CMPG_DOUBLE.c */
2151HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1)
2152OP_END
2153
2154/* File: c/OP_CMP_LONG.c */
2155HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0)
2156OP_END
2157
2158/* File: c/OP_IF_EQ.c */
2159HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==)
2160OP_END
2161
2162/* File: c/OP_IF_NE.c */
2163HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=)
2164OP_END
2165
2166/* File: c/OP_IF_LT.c */
2167HANDLE_OP_IF_XX(OP_IF_LT, "lt", <)
2168OP_END
2169
2170/* File: c/OP_IF_GE.c */
2171HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=)
2172OP_END
2173
2174/* File: c/OP_IF_GT.c */
2175HANDLE_OP_IF_XX(OP_IF_GT, "gt", >)
2176OP_END
2177
2178/* File: c/OP_IF_LE.c */
2179HANDLE_OP_IF_XX(OP_IF_LE, "le", <=)
2180OP_END
2181
2182/* File: c/OP_IF_EQZ.c */
2183HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==)
2184OP_END
2185
2186/* File: c/OP_IF_NEZ.c */
2187HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=)
2188OP_END
2189
2190/* File: c/OP_IF_LTZ.c */
2191HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <)
2192OP_END
2193
2194/* File: c/OP_IF_GEZ.c */
2195HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=)
2196OP_END
2197
2198/* File: c/OP_IF_GTZ.c */
2199HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >)
2200OP_END
2201
2202/* File: c/OP_IF_LEZ.c */
2203HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=)
2204OP_END
2205
2206/* File: c/OP_UNUSED_3E.c */
2207HANDLE_OPCODE(OP_UNUSED_3E)
2208OP_END
2209
2210/* File: c/OP_UNUSED_3F.c */
2211HANDLE_OPCODE(OP_UNUSED_3F)
2212OP_END
2213
2214/* File: c/OP_UNUSED_40.c */
2215HANDLE_OPCODE(OP_UNUSED_40)
2216OP_END
2217
2218/* File: c/OP_UNUSED_41.c */
2219HANDLE_OPCODE(OP_UNUSED_41)
2220OP_END
2221
2222/* File: c/OP_UNUSED_42.c */
2223HANDLE_OPCODE(OP_UNUSED_42)
2224OP_END
2225
2226/* File: c/OP_UNUSED_43.c */
2227HANDLE_OPCODE(OP_UNUSED_43)
2228OP_END
2229
2230/* File: c/OP_AGET.c */
2231HANDLE_OP_AGET(OP_AGET, "", u4, )
2232OP_END
2233
2234/* File: c/OP_AGET_WIDE.c */
2235HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE)
2236OP_END
2237
2238/* File: c/OP_AGET_OBJECT.c */
2239HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, )
2240OP_END
2241
2242/* File: c/OP_AGET_BOOLEAN.c */
2243HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, )
2244OP_END
2245
2246/* File: c/OP_AGET_BYTE.c */
2247HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, )
2248OP_END
2249
2250/* File: c/OP_AGET_CHAR.c */
2251HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, )
2252OP_END
2253
2254/* File: c/OP_AGET_SHORT.c */
2255HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, )
2256OP_END
2257
2258/* File: c/OP_APUT.c */
2259HANDLE_OP_APUT(OP_APUT, "", u4, )
2260OP_END
2261
2262/* File: c/OP_APUT_WIDE.c */
2263HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE)
2264OP_END
2265
2266/* File: c/OP_APUT_OBJECT.c */
2267HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/)
2268 {
2269 ArrayObject* arrayObj;
2270 Object* obj;
2271 u2 arrayInfo;
2272 EXPORT_PC();
2273 vdst = INST_AA(inst); /* AA: source value */
2274 arrayInfo = FETCH(1);
2275 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */
2276 vsrc2 = arrayInfo >> 8; /* CC: index */
2277 ILOGV("|aput%s v%d,v%d,v%d", "-object", vdst, vsrc1, vsrc2);
2278 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
2279 if (!checkForNull((Object*) arrayObj))
2280 GOTO_exceptionThrown();
2281 if (GET_REGISTER(vsrc2) >= arrayObj->length) {
Elliott Hughes00160242010-10-20 17:14:57 -07002282 dvmThrowAIOOBE(GET_REGISTER(vsrc2), arrayObj->length);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002283 GOTO_exceptionThrown();
2284 }
2285 obj = (Object*) GET_REGISTER(vdst);
2286 if (obj != NULL) {
2287 if (!checkForNull(obj))
2288 GOTO_exceptionThrown();
2289 if (!dvmCanPutArrayElement(obj->clazz, arrayObj->obj.clazz)) {
2290 LOGV("Can't put a '%s'(%p) into array type='%s'(%p)\n",
2291 obj->clazz->descriptor, obj,
2292 arrayObj->obj.clazz->descriptor, arrayObj);
Elliott Hughes63644652010-11-19 16:35:05 -08002293 dvmThrowArrayStoreException(obj->clazz, arrayObj->obj.clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002294 GOTO_exceptionThrown();
2295 }
2296 }
2297 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
Barry Hayes364f9d92010-06-11 16:12:47 -07002298 dvmSetObjectArrayElement(arrayObj,
2299 GET_REGISTER(vsrc2),
2300 (Object *)GET_REGISTER(vdst));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002301 }
2302 FINISH(2);
2303OP_END
2304
2305/* File: c/OP_APUT_BOOLEAN.c */
2306HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, )
2307OP_END
2308
2309/* File: c/OP_APUT_BYTE.c */
2310HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, )
2311OP_END
2312
2313/* File: c/OP_APUT_CHAR.c */
2314HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, )
2315OP_END
2316
2317/* File: c/OP_APUT_SHORT.c */
2318HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, )
2319OP_END
2320
2321/* File: c/OP_IGET.c */
2322HANDLE_IGET_X(OP_IGET, "", Int, )
2323OP_END
2324
2325/* File: c/OP_IGET_WIDE.c */
2326HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE)
2327OP_END
2328
2329/* File: c/OP_IGET_OBJECT.c */
2330HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT)
2331OP_END
2332
2333/* File: c/OP_IGET_BOOLEAN.c */
2334HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, )
2335OP_END
2336
2337/* File: c/OP_IGET_BYTE.c */
2338HANDLE_IGET_X(OP_IGET_BYTE, "", Int, )
2339OP_END
2340
2341/* File: c/OP_IGET_CHAR.c */
2342HANDLE_IGET_X(OP_IGET_CHAR, "", Int, )
2343OP_END
2344
2345/* File: c/OP_IGET_SHORT.c */
2346HANDLE_IGET_X(OP_IGET_SHORT, "", Int, )
2347OP_END
2348
2349/* File: c/OP_IPUT.c */
2350HANDLE_IPUT_X(OP_IPUT, "", Int, )
2351OP_END
2352
2353/* File: c/OP_IPUT_WIDE.c */
2354HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE)
2355OP_END
2356
2357/* File: c/OP_IPUT_OBJECT.c */
2358/*
2359 * The VM spec says we should verify that the reference being stored into
2360 * the field is assignment compatible. In practice, many popular VMs don't
2361 * do this because it slows down a very common operation. It's not so bad
2362 * for us, since "dexopt" quickens it whenever possible, but it's still an
2363 * issue.
2364 *
2365 * To make this spec-complaint, we'd need to add a ClassObject pointer to
2366 * the Field struct, resolve the field's type descriptor at link or class
2367 * init time, and then verify the type here.
2368 */
2369HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT)
2370OP_END
2371
2372/* File: c/OP_IPUT_BOOLEAN.c */
2373HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, )
2374OP_END
2375
2376/* File: c/OP_IPUT_BYTE.c */
2377HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, )
2378OP_END
2379
2380/* File: c/OP_IPUT_CHAR.c */
2381HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, )
2382OP_END
2383
2384/* File: c/OP_IPUT_SHORT.c */
2385HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, )
2386OP_END
2387
2388/* File: c/OP_SGET.c */
2389HANDLE_SGET_X(OP_SGET, "", Int, )
2390OP_END
2391
2392/* File: c/OP_SGET_WIDE.c */
2393HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE)
2394OP_END
2395
2396/* File: c/OP_SGET_OBJECT.c */
2397HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT)
2398OP_END
2399
2400/* File: c/OP_SGET_BOOLEAN.c */
2401HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, )
2402OP_END
2403
2404/* File: c/OP_SGET_BYTE.c */
2405HANDLE_SGET_X(OP_SGET_BYTE, "", Int, )
2406OP_END
2407
2408/* File: c/OP_SGET_CHAR.c */
2409HANDLE_SGET_X(OP_SGET_CHAR, "", Int, )
2410OP_END
2411
2412/* File: c/OP_SGET_SHORT.c */
2413HANDLE_SGET_X(OP_SGET_SHORT, "", Int, )
2414OP_END
2415
2416/* File: c/OP_SPUT.c */
2417HANDLE_SPUT_X(OP_SPUT, "", Int, )
2418OP_END
2419
2420/* File: c/OP_SPUT_WIDE.c */
2421HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE)
2422OP_END
2423
2424/* File: c/OP_SPUT_OBJECT.c */
2425HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT)
2426OP_END
2427
2428/* File: c/OP_SPUT_BOOLEAN.c */
2429HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, )
2430OP_END
2431
2432/* File: c/OP_SPUT_BYTE.c */
2433HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, )
2434OP_END
2435
2436/* File: c/OP_SPUT_CHAR.c */
2437HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, )
2438OP_END
2439
2440/* File: c/OP_SPUT_SHORT.c */
2441HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, )
2442OP_END
2443
2444/* File: c/OP_INVOKE_VIRTUAL.c */
2445HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002446 GOTO_invoke(invokeVirtual, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002447OP_END
2448
2449/* File: c/OP_INVOKE_SUPER.c */
2450HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002451 GOTO_invoke(invokeSuper, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002452OP_END
2453
2454/* File: c/OP_INVOKE_DIRECT.c */
2455HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002456 GOTO_invoke(invokeDirect, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002457OP_END
2458
2459/* File: c/OP_INVOKE_STATIC.c */
2460HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002461 GOTO_invoke(invokeStatic, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002462OP_END
2463
2464/* File: c/OP_INVOKE_INTERFACE.c */
2465HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002466 GOTO_invoke(invokeInterface, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002467OP_END
2468
2469/* File: c/OP_UNUSED_73.c */
2470HANDLE_OPCODE(OP_UNUSED_73)
2471OP_END
2472
2473/* File: c/OP_INVOKE_VIRTUAL_RANGE.c */
2474HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002475 GOTO_invoke(invokeVirtual, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002476OP_END
2477
2478/* File: c/OP_INVOKE_SUPER_RANGE.c */
2479HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002480 GOTO_invoke(invokeSuper, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002481OP_END
2482
2483/* File: c/OP_INVOKE_DIRECT_RANGE.c */
2484HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002485 GOTO_invoke(invokeDirect, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002486OP_END
2487
2488/* File: c/OP_INVOKE_STATIC_RANGE.c */
2489HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002490 GOTO_invoke(invokeStatic, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002491OP_END
2492
2493/* File: c/OP_INVOKE_INTERFACE_RANGE.c */
2494HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002495 GOTO_invoke(invokeInterface, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002496OP_END
2497
2498/* File: c/OP_UNUSED_79.c */
2499HANDLE_OPCODE(OP_UNUSED_79)
2500OP_END
2501
2502/* File: c/OP_UNUSED_7A.c */
2503HANDLE_OPCODE(OP_UNUSED_7A)
2504OP_END
2505
2506/* File: c/OP_NEG_INT.c */
2507HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , )
2508OP_END
2509
2510/* File: c/OP_NOT_INT.c */
2511HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, )
2512OP_END
2513
2514/* File: c/OP_NEG_LONG.c */
2515HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE)
2516OP_END
2517
2518/* File: c/OP_NOT_LONG.c */
2519HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE)
2520OP_END
2521
2522/* File: c/OP_NEG_FLOAT.c */
2523HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT)
2524OP_END
2525
2526/* File: c/OP_NEG_DOUBLE.c */
2527HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE)
2528OP_END
2529
2530/* File: c/OP_INT_TO_LONG.c */
2531HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE)
2532OP_END
2533
2534/* File: c/OP_INT_TO_FLOAT.c */
2535HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT)
2536OP_END
2537
2538/* File: c/OP_INT_TO_DOUBLE.c */
2539HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE)
2540OP_END
2541
2542/* File: c/OP_LONG_TO_INT.c */
2543HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT)
2544OP_END
2545
2546/* File: c/OP_LONG_TO_FLOAT.c */
2547HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT)
2548OP_END
2549
2550/* File: c/OP_LONG_TO_DOUBLE.c */
2551HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE)
2552OP_END
2553
2554/* File: c/OP_FLOAT_TO_INT.c */
2555HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int",
2556 float, _FLOAT, s4, _INT)
2557OP_END
2558
2559/* File: c/OP_FLOAT_TO_LONG.c */
2560HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long",
2561 float, _FLOAT, s8, _WIDE)
2562OP_END
2563
2564/* File: c/OP_FLOAT_TO_DOUBLE.c */
2565HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE)
2566OP_END
2567
2568/* File: c/OP_DOUBLE_TO_INT.c */
2569HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int",
2570 double, _DOUBLE, s4, _INT)
2571OP_END
2572
2573/* File: c/OP_DOUBLE_TO_LONG.c */
2574HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long",
2575 double, _DOUBLE, s8, _WIDE)
2576OP_END
2577
2578/* File: c/OP_DOUBLE_TO_FLOAT.c */
2579HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT)
2580OP_END
2581
2582/* File: c/OP_INT_TO_BYTE.c */
2583HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1)
2584OP_END
2585
2586/* File: c/OP_INT_TO_CHAR.c */
2587HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2)
2588OP_END
2589
2590/* File: c/OP_INT_TO_SHORT.c */
2591HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */
2592OP_END
2593
2594/* File: c/OP_ADD_INT.c */
2595HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0)
2596OP_END
2597
2598/* File: c/OP_SUB_INT.c */
2599HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0)
2600OP_END
2601
2602/* File: c/OP_MUL_INT.c */
2603HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0)
2604OP_END
2605
2606/* File: c/OP_DIV_INT.c */
2607HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1)
2608OP_END
2609
2610/* File: c/OP_REM_INT.c */
2611HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2)
2612OP_END
2613
2614/* File: c/OP_AND_INT.c */
2615HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0)
2616OP_END
2617
2618/* File: c/OP_OR_INT.c */
2619HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0)
2620OP_END
2621
2622/* File: c/OP_XOR_INT.c */
2623HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0)
2624OP_END
2625
2626/* File: c/OP_SHL_INT.c */
2627HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<)
2628OP_END
2629
2630/* File: c/OP_SHR_INT.c */
2631HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>)
2632OP_END
2633
2634/* File: c/OP_USHR_INT.c */
2635HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>)
2636OP_END
2637
2638/* File: c/OP_ADD_LONG.c */
2639HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0)
2640OP_END
2641
2642/* File: c/OP_SUB_LONG.c */
2643HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0)
2644OP_END
2645
2646/* File: c/OP_MUL_LONG.c */
2647HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0)
2648OP_END
2649
2650/* File: c/OP_DIV_LONG.c */
2651HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1)
2652OP_END
2653
2654/* File: c/OP_REM_LONG.c */
2655HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2)
2656OP_END
2657
2658/* File: c/OP_AND_LONG.c */
2659HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0)
2660OP_END
2661
2662/* File: c/OP_OR_LONG.c */
2663HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0)
2664OP_END
2665
2666/* File: c/OP_XOR_LONG.c */
2667HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0)
2668OP_END
2669
2670/* File: c/OP_SHL_LONG.c */
2671HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<)
2672OP_END
2673
2674/* File: c/OP_SHR_LONG.c */
2675HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>)
2676OP_END
2677
2678/* File: c/OP_USHR_LONG.c */
2679HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>)
2680OP_END
2681
2682/* File: c/OP_ADD_FLOAT.c */
2683HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +)
2684OP_END
2685
2686/* File: c/OP_SUB_FLOAT.c */
2687HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -)
2688OP_END
2689
2690/* File: c/OP_MUL_FLOAT.c */
2691HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *)
2692OP_END
2693
2694/* File: c/OP_DIV_FLOAT.c */
2695HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /)
2696OP_END
2697
2698/* File: c/OP_REM_FLOAT.c */
2699HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/)
2700 {
2701 u2 srcRegs;
2702 vdst = INST_AA(inst);
2703 srcRegs = FETCH(1);
2704 vsrc1 = srcRegs & 0xff;
2705 vsrc2 = srcRegs >> 8;
2706 ILOGV("|%s-float v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2);
2707 SET_REGISTER_FLOAT(vdst,
2708 fmodf(GET_REGISTER_FLOAT(vsrc1), GET_REGISTER_FLOAT(vsrc2)));
2709 }
2710 FINISH(2);
2711OP_END
2712
2713/* File: c/OP_ADD_DOUBLE.c */
2714HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +)
2715OP_END
2716
2717/* File: c/OP_SUB_DOUBLE.c */
2718HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -)
2719OP_END
2720
2721/* File: c/OP_MUL_DOUBLE.c */
2722HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *)
2723OP_END
2724
2725/* File: c/OP_DIV_DOUBLE.c */
2726HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /)
2727OP_END
2728
2729/* File: c/OP_REM_DOUBLE.c */
2730HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/)
2731 {
2732 u2 srcRegs;
2733 vdst = INST_AA(inst);
2734 srcRegs = FETCH(1);
2735 vsrc1 = srcRegs & 0xff;
2736 vsrc2 = srcRegs >> 8;
2737 ILOGV("|%s-double v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2);
2738 SET_REGISTER_DOUBLE(vdst,
2739 fmod(GET_REGISTER_DOUBLE(vsrc1), GET_REGISTER_DOUBLE(vsrc2)));
2740 }
2741 FINISH(2);
2742OP_END
2743
2744/* File: c/OP_ADD_INT_2ADDR.c */
2745HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0)
2746OP_END
2747
2748/* File: c/OP_SUB_INT_2ADDR.c */
2749HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0)
2750OP_END
2751
2752/* File: c/OP_MUL_INT_2ADDR.c */
2753HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0)
2754OP_END
2755
2756/* File: c/OP_DIV_INT_2ADDR.c */
2757HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1)
2758OP_END
2759
2760/* File: c/OP_REM_INT_2ADDR.c */
2761HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2)
2762OP_END
2763
2764/* File: c/OP_AND_INT_2ADDR.c */
2765HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0)
2766OP_END
2767
2768/* File: c/OP_OR_INT_2ADDR.c */
2769HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0)
2770OP_END
2771
2772/* File: c/OP_XOR_INT_2ADDR.c */
2773HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0)
2774OP_END
2775
2776/* File: c/OP_SHL_INT_2ADDR.c */
2777HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<)
2778OP_END
2779
2780/* File: c/OP_SHR_INT_2ADDR.c */
2781HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>)
2782OP_END
2783
2784/* File: c/OP_USHR_INT_2ADDR.c */
2785HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>)
2786OP_END
2787
2788/* File: c/OP_ADD_LONG_2ADDR.c */
2789HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0)
2790OP_END
2791
2792/* File: c/OP_SUB_LONG_2ADDR.c */
2793HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0)
2794OP_END
2795
2796/* File: c/OP_MUL_LONG_2ADDR.c */
2797HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0)
2798OP_END
2799
2800/* File: c/OP_DIV_LONG_2ADDR.c */
2801HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1)
2802OP_END
2803
2804/* File: c/OP_REM_LONG_2ADDR.c */
2805HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2)
2806OP_END
2807
2808/* File: c/OP_AND_LONG_2ADDR.c */
2809HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0)
2810OP_END
2811
2812/* File: c/OP_OR_LONG_2ADDR.c */
2813HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0)
2814OP_END
2815
2816/* File: c/OP_XOR_LONG_2ADDR.c */
2817HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0)
2818OP_END
2819
2820/* File: c/OP_SHL_LONG_2ADDR.c */
2821HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<)
2822OP_END
2823
2824/* File: c/OP_SHR_LONG_2ADDR.c */
2825HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>)
2826OP_END
2827
2828/* File: c/OP_USHR_LONG_2ADDR.c */
2829HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>)
2830OP_END
2831
2832/* File: c/OP_ADD_FLOAT_2ADDR.c */
2833HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +)
2834OP_END
2835
2836/* File: c/OP_SUB_FLOAT_2ADDR.c */
2837HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -)
2838OP_END
2839
2840/* File: c/OP_MUL_FLOAT_2ADDR.c */
2841HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *)
2842OP_END
2843
2844/* File: c/OP_DIV_FLOAT_2ADDR.c */
2845HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /)
2846OP_END
2847
2848/* File: c/OP_REM_FLOAT_2ADDR.c */
2849HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/)
2850 vdst = INST_A(inst);
2851 vsrc1 = INST_B(inst);
2852 ILOGV("|%s-float-2addr v%d,v%d", "mod", vdst, vsrc1);
2853 SET_REGISTER_FLOAT(vdst,
2854 fmodf(GET_REGISTER_FLOAT(vdst), GET_REGISTER_FLOAT(vsrc1)));
2855 FINISH(1);
2856OP_END
2857
2858/* File: c/OP_ADD_DOUBLE_2ADDR.c */
2859HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +)
2860OP_END
2861
2862/* File: c/OP_SUB_DOUBLE_2ADDR.c */
2863HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -)
2864OP_END
2865
2866/* File: c/OP_MUL_DOUBLE_2ADDR.c */
2867HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *)
2868OP_END
2869
2870/* File: c/OP_DIV_DOUBLE_2ADDR.c */
2871HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /)
2872OP_END
2873
2874/* File: c/OP_REM_DOUBLE_2ADDR.c */
2875HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/)
2876 vdst = INST_A(inst);
2877 vsrc1 = INST_B(inst);
2878 ILOGV("|%s-double-2addr v%d,v%d", "mod", vdst, vsrc1);
2879 SET_REGISTER_DOUBLE(vdst,
2880 fmod(GET_REGISTER_DOUBLE(vdst), GET_REGISTER_DOUBLE(vsrc1)));
2881 FINISH(1);
2882OP_END
2883
2884/* File: c/OP_ADD_INT_LIT16.c */
2885HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0)
2886OP_END
2887
2888/* File: c/OP_RSUB_INT.c */
2889HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/)
2890 {
2891 vdst = INST_A(inst);
2892 vsrc1 = INST_B(inst);
2893 vsrc2 = FETCH(1);
2894 ILOGV("|rsub-int v%d,v%d,#+0x%04x", vdst, vsrc1, vsrc2);
2895 SET_REGISTER(vdst, (s2) vsrc2 - (s4) GET_REGISTER(vsrc1));
2896 }
2897 FINISH(2);
2898OP_END
2899
2900/* File: c/OP_MUL_INT_LIT16.c */
2901HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0)
2902OP_END
2903
2904/* File: c/OP_DIV_INT_LIT16.c */
2905HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1)
2906OP_END
2907
2908/* File: c/OP_REM_INT_LIT16.c */
2909HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2)
2910OP_END
2911
2912/* File: c/OP_AND_INT_LIT16.c */
2913HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0)
2914OP_END
2915
2916/* File: c/OP_OR_INT_LIT16.c */
2917HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0)
2918OP_END
2919
2920/* File: c/OP_XOR_INT_LIT16.c */
2921HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0)
2922OP_END
2923
2924/* File: c/OP_ADD_INT_LIT8.c */
2925HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0)
2926OP_END
2927
2928/* File: c/OP_RSUB_INT_LIT8.c */
2929HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/)
2930 {
2931 u2 litInfo;
2932 vdst = INST_AA(inst);
2933 litInfo = FETCH(1);
2934 vsrc1 = litInfo & 0xff;
2935 vsrc2 = litInfo >> 8;
2936 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", "rsub", vdst, vsrc1, vsrc2);
2937 SET_REGISTER(vdst, (s1) vsrc2 - (s4) GET_REGISTER(vsrc1));
2938 }
2939 FINISH(2);
2940OP_END
2941
2942/* File: c/OP_MUL_INT_LIT8.c */
2943HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0)
2944OP_END
2945
2946/* File: c/OP_DIV_INT_LIT8.c */
2947HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1)
2948OP_END
2949
2950/* File: c/OP_REM_INT_LIT8.c */
2951HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2)
2952OP_END
2953
2954/* File: c/OP_AND_INT_LIT8.c */
2955HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0)
2956OP_END
2957
2958/* File: c/OP_OR_INT_LIT8.c */
2959HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0)
2960OP_END
2961
2962/* File: c/OP_XOR_INT_LIT8.c */
2963HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0)
2964OP_END
2965
2966/* File: c/OP_SHL_INT_LIT8.c */
2967HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<)
2968OP_END
2969
2970/* File: c/OP_SHR_INT_LIT8.c */
2971HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>)
2972OP_END
2973
2974/* File: c/OP_USHR_INT_LIT8.c */
2975HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>)
2976OP_END
2977
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002978/* File: c/OP_IGET_VOLATILE.c */
2979HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002980OP_END
2981
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002982/* File: c/OP_IPUT_VOLATILE.c */
2983HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002984OP_END
2985
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002986/* File: c/OP_SGET_VOLATILE.c */
2987HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002988OP_END
2989
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002990/* File: c/OP_SPUT_VOLATILE.c */
2991HANDLE_SPUT_X(OP_SPUT_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_IGET_OBJECT_VOLATILE.c */
2995HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002996OP_END
2997
Andy McFadden53878242010-03-05 07:24:27 -08002998/* File: c/OP_IGET_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08002999HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003000OP_END
3001
Andy McFadden53878242010-03-05 07:24:27 -08003002/* File: c/OP_IPUT_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003003HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003004OP_END
3005
Andy McFadden53878242010-03-05 07:24:27 -08003006/* File: c/OP_SGET_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003007HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003008OP_END
3009
Andy McFadden53878242010-03-05 07:24:27 -08003010/* File: c/OP_SPUT_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003011HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003012OP_END
3013
Andy McFadden96516932009-10-28 17:39:02 -07003014/* File: c/OP_BREAKPOINT.c */
3015HANDLE_OPCODE(OP_BREAKPOINT)
Andy McFadden0d615c32010-08-18 12:19:51 -07003016#if (INTERP_TYPE == INTERP_DBG)
Andy McFadden96516932009-10-28 17:39:02 -07003017 {
3018 /*
3019 * Restart this instruction with the original opcode. We do
3020 * this by simply jumping to the handler.
3021 *
3022 * It's probably not necessary to update "inst", but we do it
3023 * for the sake of anything that needs to do disambiguation in a
3024 * common handler with INST_INST.
3025 *
3026 * The breakpoint itself is handled over in updateDebugger(),
3027 * because we need to detect other events (method entry, single
3028 * step) and report them in the same event packet, and we're not
3029 * yet handling those through breakpoint instructions. By the
3030 * time we get here, the breakpoint has already been handled and
3031 * the thread resumed.
3032 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -08003033 u1 originalOpcode = dvmGetOriginalOpcode(pc);
3034 LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpcode, inst,
3035 INST_REPLACE_OP(inst, originalOpcode));
3036 inst = INST_REPLACE_OP(inst, originalOpcode);
3037 FINISH_BKPT(originalOpcode);
Andy McFadden96516932009-10-28 17:39:02 -07003038 }
3039#else
3040 LOGE("Breakpoint hit in non-debug interpreter\n");
3041 dvmAbort();
3042#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003043OP_END
3044
Andy McFadden3a1aedb2009-05-07 13:30:23 -07003045/* File: c/OP_THROW_VERIFICATION_ERROR.c */
3046HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
Andy McFaddenb51ea112009-05-08 16:50:17 -07003047 EXPORT_PC();
Andy McFadden3a1aedb2009-05-07 13:30:23 -07003048 vsrc1 = INST_AA(inst);
3049 ref = FETCH(1); /* class/field/method ref */
Andy McFaddenb51ea112009-05-08 16:50:17 -07003050 dvmThrowVerificationError(curMethod, vsrc1, ref);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07003051 GOTO_exceptionThrown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003052OP_END
3053
3054/* File: c/OP_EXECUTE_INLINE.c */
3055HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/)
3056 {
3057 /*
3058 * This has the same form as other method calls, but we ignore
3059 * the 5th argument (vA). This is chiefly because the first four
3060 * arguments to a function on ARM are in registers.
3061 *
3062 * We only set the arguments that are actually used, leaving
3063 * the rest uninitialized. We're assuming that, if the method
3064 * needs them, they'll be specified in the call.
3065 *
Carl Shapiro7bbb9ce2009-12-21 18:34:11 -08003066 * However, this annoys gcc when optimizations are enabled,
3067 * causing a "may be used uninitialized" warning. Quieting
3068 * the warnings incurs a slight penalty (5%: 373ns vs. 393ns
3069 * on empty method). Note that valgrind is perfectly happy
3070 * either way as the uninitialiezd values are never actually
3071 * used.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003072 */
3073 u4 arg0, arg1, arg2, arg3;
Carl Shapiro7bbb9ce2009-12-21 18:34:11 -08003074 arg0 = arg1 = arg2 = arg3 = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003075
3076 EXPORT_PC();
3077
3078 vsrc1 = INST_B(inst); /* #of args */
3079 ref = FETCH(1); /* inline call "ref" */
3080 vdst = FETCH(2); /* 0-4 register indices */
3081 ILOGV("|execute-inline args=%d @%d {regs=0x%04x}",
3082 vsrc1, ref, vdst);
3083
3084 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
3085 assert(vsrc1 <= 4);
3086
3087 switch (vsrc1) {
3088 case 4:
3089 arg3 = GET_REGISTER(vdst >> 12);
3090 /* fall through */
3091 case 3:
3092 arg2 = GET_REGISTER((vdst & 0x0f00) >> 8);
3093 /* fall through */
3094 case 2:
3095 arg1 = GET_REGISTER((vdst & 0x00f0) >> 4);
3096 /* fall through */
3097 case 1:
3098 arg0 = GET_REGISTER(vdst & 0x0f);
3099 /* fall through */
3100 default: // case 0
3101 ;
3102 }
3103
3104#if INTERP_TYPE == INTERP_DBG
3105 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
3106 GOTO_exceptionThrown();
3107#else
3108 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
3109 GOTO_exceptionThrown();
3110#endif
3111 }
3112 FINISH(3);
3113OP_END
3114
Andy McFaddenb0a05412009-11-19 10:23:41 -08003115/* File: c/OP_EXECUTE_INLINE_RANGE.c */
3116HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
3117 {
3118 u4 arg0, arg1, arg2, arg3;
3119 arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */
3120
3121 EXPORT_PC();
3122
3123 vsrc1 = INST_AA(inst); /* #of args */
3124 ref = FETCH(1); /* inline call "ref" */
3125 vdst = FETCH(2); /* range base */
3126 ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}",
3127 vsrc1, ref, vdst, vdst+vsrc1-1);
3128
3129 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
3130 assert(vsrc1 <= 4);
3131
3132 switch (vsrc1) {
3133 case 4:
3134 arg3 = GET_REGISTER(vdst+3);
3135 /* fall through */
3136 case 3:
3137 arg2 = GET_REGISTER(vdst+2);
3138 /* fall through */
3139 case 2:
3140 arg1 = GET_REGISTER(vdst+1);
3141 /* fall through */
3142 case 1:
3143 arg0 = GET_REGISTER(vdst+0);
3144 /* fall through */
3145 default: // case 0
3146 ;
3147 }
3148
3149#if INTERP_TYPE == INTERP_DBG
3150 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
3151 GOTO_exceptionThrown();
3152#else
3153 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
3154 GOTO_exceptionThrown();
3155#endif
3156 }
3157 FINISH(3);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003158OP_END
3159
Andy McFadden750d1102011-02-11 15:26:10 -08003160/* File: c/OP_INVOKE_OBJECT_INIT.c */
3161HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003162 {
3163 Object* obj;
3164
3165 vsrc1 = FETCH(2) & 0x0f; /* reg number of "this" pointer */
3166 obj = GET_REGISTER_AS_OBJECT(vsrc1);
3167
3168 if (!checkForNullExportPC(obj, fp, pc))
3169 GOTO_exceptionThrown();
3170
3171 /*
3172 * The object should be marked "finalizable" when Object.<init>
3173 * completes normally. We're going to assume it does complete
3174 * (by virtue of being nothing but a return-void) and set it now.
3175 */
3176 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) {
3177 dvmSetFinalizable(obj);
3178 }
3179
3180#if INTERP_TYPE == INTERP_DBG
3181 if (!DEBUGGER_ACTIVE) {
3182 /* skip method invocation */
3183 FINISH(3);
3184 } else {
3185 /* behave like OP_INVOKE_DIRECT */
3186 GOTO_invoke(invokeDirect, false, false);
3187 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003188#else
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003189 /* debugger can't be attached, skip method invocation */
3190 FINISH(3);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003191#endif
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003192 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003193OP_END
3194
Andy McFadden291758c2010-09-10 08:04:52 -07003195/* File: c/OP_RETURN_VOID_BARRIER.c */
3196HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
3197 ILOGV("|return-void");
3198#ifndef NDEBUG
3199 retval.j = 0xababababULL; /* placate valgrind */
3200#endif
Andy McFadden1df319e2010-09-15 13:40:01 -07003201 ANDROID_MEMBAR_STORE();
Andy McFadden291758c2010-09-10 08:04:52 -07003202 GOTO_returnFromMethod();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003203OP_END
3204
3205/* File: c/OP_IGET_QUICK.c */
3206HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, )
3207OP_END
3208
3209/* File: c/OP_IGET_WIDE_QUICK.c */
3210HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE)
3211OP_END
3212
3213/* File: c/OP_IGET_OBJECT_QUICK.c */
3214HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
3215OP_END
3216
3217/* File: c/OP_IPUT_QUICK.c */
3218HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, )
3219OP_END
3220
3221/* File: c/OP_IPUT_WIDE_QUICK.c */
3222HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE)
3223OP_END
3224
3225/* File: c/OP_IPUT_OBJECT_QUICK.c */
3226HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
3227OP_END
3228
3229/* File: c/OP_INVOKE_VIRTUAL_QUICK.c */
3230HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003231 GOTO_invoke(invokeVirtualQuick, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003232OP_END
3233
3234/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.c */
3235HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003236 GOTO_invoke(invokeVirtualQuick, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003237OP_END
3238
3239/* File: c/OP_INVOKE_SUPER_QUICK.c */
3240HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003241 GOTO_invoke(invokeSuperQuick, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003242OP_END
3243
3244/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.c */
3245HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003246 GOTO_invoke(invokeSuperQuick, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003247OP_END
3248
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07003249/* File: c/OP_IPUT_OBJECT_VOLATILE.c */
3250HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003251OP_END
3252
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07003253/* File: c/OP_SGET_OBJECT_VOLATILE.c */
3254HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003255OP_END
3256
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07003257/* File: c/OP_SPUT_OBJECT_VOLATILE.c */
3258HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003259OP_END
3260
Dan Bornstein90f15432010-12-02 16:46:25 -08003261/* File: c/OP_DISPATCH_FF.c */
3262HANDLE_OPCODE(OP_DISPATCH_FF)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003263 /*
jeffhao71eee1f2011-01-04 14:18:54 -08003264 * Indicates extended opcode. Use next 8 bits to choose where to branch.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003265 */
jeffhao71eee1f2011-01-04 14:18:54 -08003266 DISPATCH_EXTENDED(INST_AA(inst));
3267OP_END
3268
3269/* File: c/OP_CONST_CLASS_JUMBO.c */
3270HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/)
3271 {
3272 ClassObject* clazz;
3273
3274 ref = FETCH(1) | (u4)FETCH(2) << 16;
3275 vdst = FETCH(3);
3276 ILOGV("|const-class/jumbo v%d class@0x%08x", vdst, ref);
3277 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3278 if (clazz == NULL) {
3279 EXPORT_PC();
3280 clazz = dvmResolveClass(curMethod->clazz, ref, true);
3281 if (clazz == NULL)
3282 GOTO_exceptionThrown();
3283 }
3284 SET_REGISTER(vdst, (u4) clazz);
3285 }
3286 FINISH(4);
3287OP_END
3288
3289/* File: c/OP_CHECK_CAST_JUMBO.c */
3290HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/)
3291 {
3292 ClassObject* clazz;
3293 Object* obj;
3294
3295 EXPORT_PC();
3296
3297 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */
3298 vsrc1 = FETCH(3);
3299 ILOGV("|check-cast/jumbo v%d,class@0x%08x", vsrc1, ref);
3300
3301 obj = (Object*)GET_REGISTER(vsrc1);
3302 if (obj != NULL) {
3303#if defined(WITH_EXTRA_OBJECT_VALIDATION)
3304 if (!checkForNull(obj))
3305 GOTO_exceptionThrown();
3306#endif
3307 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3308 if (clazz == NULL) {
3309 clazz = dvmResolveClass(curMethod->clazz, ref, false);
3310 if (clazz == NULL)
3311 GOTO_exceptionThrown();
3312 }
3313 if (!dvmInstanceof(obj->clazz, clazz)) {
3314 dvmThrowClassCastException(obj->clazz, clazz);
3315 GOTO_exceptionThrown();
3316 }
3317 }
3318 }
3319 FINISH(4);
3320OP_END
3321
3322/* File: c/OP_INSTANCE_OF_JUMBO.c */
3323HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
3324 {
3325 ClassObject* clazz;
3326 Object* obj;
3327
3328 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */
3329 vdst = FETCH(3);
3330 vsrc1 = FETCH(4); /* object to check */
3331 ILOGV("|instance-of/jumbo v%d,v%d,class@0x%08x", vdst, vsrc1, ref);
3332
3333 obj = (Object*)GET_REGISTER(vsrc1);
3334 if (obj == NULL) {
3335 SET_REGISTER(vdst, 0);
3336 } else {
3337#if defined(WITH_EXTRA_OBJECT_VALIDATION)
3338 if (!checkForNullExportPC(obj, fp, pc))
3339 GOTO_exceptionThrown();
3340#endif
3341 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3342 if (clazz == NULL) {
3343 EXPORT_PC();
3344 clazz = dvmResolveClass(curMethod->clazz, ref, true);
3345 if (clazz == NULL)
3346 GOTO_exceptionThrown();
3347 }
3348 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz));
3349 }
3350 }
3351 FINISH(5);
3352OP_END
3353
3354/* File: c/OP_NEW_INSTANCE_JUMBO.c */
3355HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/)
3356 {
3357 ClassObject* clazz;
3358 Object* newObj;
3359
3360 EXPORT_PC();
3361
3362 ref = FETCH(1) | (u4)FETCH(2) << 16;
3363 vdst = FETCH(3);
3364 ILOGV("|new-instance/jumbo v%d,class@0x%08x", vdst, ref);
3365 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3366 if (clazz == NULL) {
3367 clazz = dvmResolveClass(curMethod->clazz, ref, false);
3368 if (clazz == NULL)
3369 GOTO_exceptionThrown();
3370 }
3371
3372 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))
3373 GOTO_exceptionThrown();
3374
3375 /*
3376 * The JIT needs dvmDexGetResolvedClass() to return non-null.
3377 * Since we use the portable interpreter to build the trace, this extra
3378 * check is not needed for mterp.
3379 */
3380 if (!dvmDexGetResolvedClass(methodClassDex, ref)) {
Bill Buzbee1b3da592011-02-03 07:38:22 -08003381 /* Class initialization is still ongoing - end the trace */
3382 END_JIT_TSELECT();
jeffhao71eee1f2011-01-04 14:18:54 -08003383 }
3384
3385 /*
3386 * Verifier now tests for interface/abstract class.
3387 */
3388 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
3389 // dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
3390 // clazz->descriptor);
3391 // GOTO_exceptionThrown();
3392 //}
3393 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
3394 if (newObj == NULL)
3395 GOTO_exceptionThrown();
3396 SET_REGISTER(vdst, (u4) newObj);
3397 }
3398 FINISH(4);
3399OP_END
3400
3401/* File: c/OP_NEW_ARRAY_JUMBO.c */
3402HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
3403 {
3404 ClassObject* arrayClass;
3405 ArrayObject* newArray;
3406 s4 length;
3407
3408 EXPORT_PC();
3409
3410 ref = FETCH(1) | (u4)FETCH(2) << 16;
3411 vdst = FETCH(3);
3412 vsrc1 = FETCH(4); /* length reg */
3413 ILOGV("|new-array/jumbo v%d,v%d,class@0x%08x (%d elements)",
3414 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1));
3415 length = (s4) GET_REGISTER(vsrc1);
3416 if (length < 0) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08003417 dvmThrowNegativeArraySizeException(NULL);
jeffhao71eee1f2011-01-04 14:18:54 -08003418 GOTO_exceptionThrown();
3419 }
3420 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
3421 if (arrayClass == NULL) {
3422 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
3423 if (arrayClass == NULL)
3424 GOTO_exceptionThrown();
3425 }
3426 /* verifier guarantees this is an array class */
3427 assert(dvmIsArrayClass(arrayClass));
3428 assert(dvmIsClassInitialized(arrayClass));
3429
3430 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK);
3431 if (newArray == NULL)
3432 GOTO_exceptionThrown();
3433 SET_REGISTER(vdst, (u4) newArray);
3434 }
3435 FINISH(5);
3436OP_END
3437
3438/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.c */
3439HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/)
3440 GOTO_invoke(filledNewArray, true, true);
3441OP_END
3442
3443/* File: c/OP_IGET_JUMBO.c */
3444HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, )
3445OP_END
3446
3447/* File: c/OP_IGET_WIDE_JUMBO.c */
3448HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE)
3449OP_END
3450
3451/* File: c/OP_IGET_OBJECT_JUMBO.c */
3452HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3453OP_END
3454
3455/* File: c/OP_IGET_BOOLEAN_JUMBO.c */
3456HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, )
3457OP_END
3458
3459/* File: c/OP_IGET_BYTE_JUMBO.c */
3460HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, )
3461OP_END
3462
3463/* File: c/OP_IGET_CHAR_JUMBO.c */
3464HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, )
3465OP_END
3466
3467/* File: c/OP_IGET_SHORT_JUMBO.c */
3468HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, )
3469OP_END
3470
3471/* File: c/OP_IPUT_JUMBO.c */
3472HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, )
3473OP_END
3474
3475/* File: c/OP_IPUT_WIDE_JUMBO.c */
3476HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
3477OP_END
3478
3479/* File: c/OP_IPUT_OBJECT_JUMBO.c */
3480/*
3481 * The VM spec says we should verify that the reference being stored into
3482 * the field is assignment compatible. In practice, many popular VMs don't
3483 * do this because it slows down a very common operation. It's not so bad
3484 * for us, since "dexopt" quickens it whenever possible, but it's still an
3485 * issue.
3486 *
3487 * To make this spec-complaint, we'd need to add a ClassObject pointer to
3488 * the Field struct, resolve the field's type descriptor at link or class
3489 * init time, and then verify the type here.
3490 */
3491HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3492OP_END
3493
3494/* File: c/OP_IPUT_BOOLEAN_JUMBO.c */
3495HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, )
3496OP_END
3497
3498/* File: c/OP_IPUT_BYTE_JUMBO.c */
3499HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, )
3500OP_END
3501
3502/* File: c/OP_IPUT_CHAR_JUMBO.c */
3503HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, )
3504OP_END
3505
3506/* File: c/OP_IPUT_SHORT_JUMBO.c */
3507HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, )
3508OP_END
3509
3510/* File: c/OP_SGET_JUMBO.c */
3511HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, )
3512OP_END
3513
3514/* File: c/OP_SGET_WIDE_JUMBO.c */
3515HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE)
3516OP_END
3517
3518/* File: c/OP_SGET_OBJECT_JUMBO.c */
3519HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3520OP_END
3521
3522/* File: c/OP_SGET_BOOLEAN_JUMBO.c */
3523HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, )
3524OP_END
3525
3526/* File: c/OP_SGET_BYTE_JUMBO.c */
3527HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, )
3528OP_END
3529
3530/* File: c/OP_SGET_CHAR_JUMBO.c */
3531HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, )
3532OP_END
3533
3534/* File: c/OP_SGET_SHORT_JUMBO.c */
3535HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, )
3536OP_END
3537
3538/* File: c/OP_SPUT_JUMBO.c */
3539HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, )
3540OP_END
3541
3542/* File: c/OP_SPUT_WIDE_JUMBO.c */
3543HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
3544OP_END
3545
3546/* File: c/OP_SPUT_OBJECT_JUMBO.c */
3547HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3548OP_END
3549
3550/* File: c/OP_SPUT_BOOLEAN_JUMBO.c */
3551HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, )
3552OP_END
3553
3554/* File: c/OP_SPUT_BYTE_JUMBO.c */
3555HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, )
3556OP_END
3557
3558/* File: c/OP_SPUT_CHAR_JUMBO.c */
3559HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, )
3560OP_END
3561
3562/* File: c/OP_SPUT_SHORT_JUMBO.c */
3563HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, )
3564OP_END
3565
3566/* File: c/OP_INVOKE_VIRTUAL_JUMBO.c */
3567HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3568 GOTO_invoke(invokeVirtual, true, true);
3569OP_END
3570
3571/* File: c/OP_INVOKE_SUPER_JUMBO.c */
3572HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3573 GOTO_invoke(invokeSuper, true, true);
3574OP_END
3575
3576/* File: c/OP_INVOKE_DIRECT_JUMBO.c */
3577HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3578 GOTO_invoke(invokeDirect, true, true);
3579OP_END
3580
3581/* File: c/OP_INVOKE_STATIC_JUMBO.c */
3582HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3583 GOTO_invoke(invokeStatic, true, true);
3584OP_END
3585
3586/* File: c/OP_INVOKE_INTERFACE_JUMBO.c */
3587HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3588 GOTO_invoke(invokeInterface, true, true);
3589OP_END
3590
3591/* File: c/OP_UNUSED_27FF.c */
3592HANDLE_OPCODE(OP_UNUSED_27FF)
3593OP_END
3594
3595/* File: c/OP_UNUSED_28FF.c */
3596HANDLE_OPCODE(OP_UNUSED_28FF)
3597OP_END
3598
3599/* File: c/OP_UNUSED_29FF.c */
3600HANDLE_OPCODE(OP_UNUSED_29FF)
3601OP_END
3602
3603/* File: c/OP_UNUSED_2AFF.c */
3604HANDLE_OPCODE(OP_UNUSED_2AFF)
3605OP_END
3606
3607/* File: c/OP_UNUSED_2BFF.c */
3608HANDLE_OPCODE(OP_UNUSED_2BFF)
3609OP_END
3610
3611/* File: c/OP_UNUSED_2CFF.c */
3612HANDLE_OPCODE(OP_UNUSED_2CFF)
3613OP_END
3614
3615/* File: c/OP_UNUSED_2DFF.c */
3616HANDLE_OPCODE(OP_UNUSED_2DFF)
3617OP_END
3618
3619/* File: c/OP_UNUSED_2EFF.c */
3620HANDLE_OPCODE(OP_UNUSED_2EFF)
3621OP_END
3622
3623/* File: c/OP_UNUSED_2FFF.c */
3624HANDLE_OPCODE(OP_UNUSED_2FFF)
3625OP_END
3626
3627/* File: c/OP_UNUSED_30FF.c */
3628HANDLE_OPCODE(OP_UNUSED_30FF)
3629OP_END
3630
3631/* File: c/OP_UNUSED_31FF.c */
3632HANDLE_OPCODE(OP_UNUSED_31FF)
3633OP_END
3634
3635/* File: c/OP_UNUSED_32FF.c */
3636HANDLE_OPCODE(OP_UNUSED_32FF)
3637OP_END
3638
3639/* File: c/OP_UNUSED_33FF.c */
3640HANDLE_OPCODE(OP_UNUSED_33FF)
3641OP_END
3642
3643/* File: c/OP_UNUSED_34FF.c */
3644HANDLE_OPCODE(OP_UNUSED_34FF)
3645OP_END
3646
3647/* File: c/OP_UNUSED_35FF.c */
3648HANDLE_OPCODE(OP_UNUSED_35FF)
3649OP_END
3650
3651/* File: c/OP_UNUSED_36FF.c */
3652HANDLE_OPCODE(OP_UNUSED_36FF)
3653OP_END
3654
3655/* File: c/OP_UNUSED_37FF.c */
3656HANDLE_OPCODE(OP_UNUSED_37FF)
3657OP_END
3658
3659/* File: c/OP_UNUSED_38FF.c */
3660HANDLE_OPCODE(OP_UNUSED_38FF)
3661OP_END
3662
3663/* File: c/OP_UNUSED_39FF.c */
3664HANDLE_OPCODE(OP_UNUSED_39FF)
3665OP_END
3666
3667/* File: c/OP_UNUSED_3AFF.c */
3668HANDLE_OPCODE(OP_UNUSED_3AFF)
3669OP_END
3670
3671/* File: c/OP_UNUSED_3BFF.c */
3672HANDLE_OPCODE(OP_UNUSED_3BFF)
3673OP_END
3674
3675/* File: c/OP_UNUSED_3CFF.c */
3676HANDLE_OPCODE(OP_UNUSED_3CFF)
3677OP_END
3678
3679/* File: c/OP_UNUSED_3DFF.c */
3680HANDLE_OPCODE(OP_UNUSED_3DFF)
3681OP_END
3682
3683/* File: c/OP_UNUSED_3EFF.c */
3684HANDLE_OPCODE(OP_UNUSED_3EFF)
3685OP_END
3686
3687/* File: c/OP_UNUSED_3FFF.c */
3688HANDLE_OPCODE(OP_UNUSED_3FFF)
3689OP_END
3690
3691/* File: c/OP_UNUSED_40FF.c */
3692HANDLE_OPCODE(OP_UNUSED_40FF)
3693OP_END
3694
3695/* File: c/OP_UNUSED_41FF.c */
3696HANDLE_OPCODE(OP_UNUSED_41FF)
3697OP_END
3698
3699/* File: c/OP_UNUSED_42FF.c */
3700HANDLE_OPCODE(OP_UNUSED_42FF)
3701OP_END
3702
3703/* File: c/OP_UNUSED_43FF.c */
3704HANDLE_OPCODE(OP_UNUSED_43FF)
3705OP_END
3706
3707/* File: c/OP_UNUSED_44FF.c */
3708HANDLE_OPCODE(OP_UNUSED_44FF)
3709OP_END
3710
3711/* File: c/OP_UNUSED_45FF.c */
3712HANDLE_OPCODE(OP_UNUSED_45FF)
3713OP_END
3714
3715/* File: c/OP_UNUSED_46FF.c */
3716HANDLE_OPCODE(OP_UNUSED_46FF)
3717OP_END
3718
3719/* File: c/OP_UNUSED_47FF.c */
3720HANDLE_OPCODE(OP_UNUSED_47FF)
3721OP_END
3722
3723/* File: c/OP_UNUSED_48FF.c */
3724HANDLE_OPCODE(OP_UNUSED_48FF)
3725OP_END
3726
3727/* File: c/OP_UNUSED_49FF.c */
3728HANDLE_OPCODE(OP_UNUSED_49FF)
3729OP_END
3730
3731/* File: c/OP_UNUSED_4AFF.c */
3732HANDLE_OPCODE(OP_UNUSED_4AFF)
3733OP_END
3734
3735/* File: c/OP_UNUSED_4BFF.c */
3736HANDLE_OPCODE(OP_UNUSED_4BFF)
3737OP_END
3738
3739/* File: c/OP_UNUSED_4CFF.c */
3740HANDLE_OPCODE(OP_UNUSED_4CFF)
3741OP_END
3742
3743/* File: c/OP_UNUSED_4DFF.c */
3744HANDLE_OPCODE(OP_UNUSED_4DFF)
3745OP_END
3746
3747/* File: c/OP_UNUSED_4EFF.c */
3748HANDLE_OPCODE(OP_UNUSED_4EFF)
3749OP_END
3750
3751/* File: c/OP_UNUSED_4FFF.c */
3752HANDLE_OPCODE(OP_UNUSED_4FFF)
3753OP_END
3754
3755/* File: c/OP_UNUSED_50FF.c */
3756HANDLE_OPCODE(OP_UNUSED_50FF)
3757OP_END
3758
3759/* File: c/OP_UNUSED_51FF.c */
3760HANDLE_OPCODE(OP_UNUSED_51FF)
3761OP_END
3762
3763/* File: c/OP_UNUSED_52FF.c */
3764HANDLE_OPCODE(OP_UNUSED_52FF)
3765OP_END
3766
3767/* File: c/OP_UNUSED_53FF.c */
3768HANDLE_OPCODE(OP_UNUSED_53FF)
3769OP_END
3770
3771/* File: c/OP_UNUSED_54FF.c */
3772HANDLE_OPCODE(OP_UNUSED_54FF)
3773OP_END
3774
3775/* File: c/OP_UNUSED_55FF.c */
3776HANDLE_OPCODE(OP_UNUSED_55FF)
3777OP_END
3778
3779/* File: c/OP_UNUSED_56FF.c */
3780HANDLE_OPCODE(OP_UNUSED_56FF)
3781OP_END
3782
3783/* File: c/OP_UNUSED_57FF.c */
3784HANDLE_OPCODE(OP_UNUSED_57FF)
3785OP_END
3786
3787/* File: c/OP_UNUSED_58FF.c */
3788HANDLE_OPCODE(OP_UNUSED_58FF)
3789OP_END
3790
3791/* File: c/OP_UNUSED_59FF.c */
3792HANDLE_OPCODE(OP_UNUSED_59FF)
3793OP_END
3794
3795/* File: c/OP_UNUSED_5AFF.c */
3796HANDLE_OPCODE(OP_UNUSED_5AFF)
3797OP_END
3798
3799/* File: c/OP_UNUSED_5BFF.c */
3800HANDLE_OPCODE(OP_UNUSED_5BFF)
3801OP_END
3802
3803/* File: c/OP_UNUSED_5CFF.c */
3804HANDLE_OPCODE(OP_UNUSED_5CFF)
3805OP_END
3806
3807/* File: c/OP_UNUSED_5DFF.c */
3808HANDLE_OPCODE(OP_UNUSED_5DFF)
3809OP_END
3810
3811/* File: c/OP_UNUSED_5EFF.c */
3812HANDLE_OPCODE(OP_UNUSED_5EFF)
3813OP_END
3814
3815/* File: c/OP_UNUSED_5FFF.c */
3816HANDLE_OPCODE(OP_UNUSED_5FFF)
3817OP_END
3818
3819/* File: c/OP_UNUSED_60FF.c */
3820HANDLE_OPCODE(OP_UNUSED_60FF)
3821OP_END
3822
3823/* File: c/OP_UNUSED_61FF.c */
3824HANDLE_OPCODE(OP_UNUSED_61FF)
3825OP_END
3826
3827/* File: c/OP_UNUSED_62FF.c */
3828HANDLE_OPCODE(OP_UNUSED_62FF)
3829OP_END
3830
3831/* File: c/OP_UNUSED_63FF.c */
3832HANDLE_OPCODE(OP_UNUSED_63FF)
3833OP_END
3834
3835/* File: c/OP_UNUSED_64FF.c */
3836HANDLE_OPCODE(OP_UNUSED_64FF)
3837OP_END
3838
3839/* File: c/OP_UNUSED_65FF.c */
3840HANDLE_OPCODE(OP_UNUSED_65FF)
3841OP_END
3842
3843/* File: c/OP_UNUSED_66FF.c */
3844HANDLE_OPCODE(OP_UNUSED_66FF)
3845OP_END
3846
3847/* File: c/OP_UNUSED_67FF.c */
3848HANDLE_OPCODE(OP_UNUSED_67FF)
3849OP_END
3850
3851/* File: c/OP_UNUSED_68FF.c */
3852HANDLE_OPCODE(OP_UNUSED_68FF)
3853OP_END
3854
3855/* File: c/OP_UNUSED_69FF.c */
3856HANDLE_OPCODE(OP_UNUSED_69FF)
3857OP_END
3858
3859/* File: c/OP_UNUSED_6AFF.c */
3860HANDLE_OPCODE(OP_UNUSED_6AFF)
3861OP_END
3862
3863/* File: c/OP_UNUSED_6BFF.c */
3864HANDLE_OPCODE(OP_UNUSED_6BFF)
3865OP_END
3866
3867/* File: c/OP_UNUSED_6CFF.c */
3868HANDLE_OPCODE(OP_UNUSED_6CFF)
3869OP_END
3870
3871/* File: c/OP_UNUSED_6DFF.c */
3872HANDLE_OPCODE(OP_UNUSED_6DFF)
3873OP_END
3874
3875/* File: c/OP_UNUSED_6EFF.c */
3876HANDLE_OPCODE(OP_UNUSED_6EFF)
3877OP_END
3878
3879/* File: c/OP_UNUSED_6FFF.c */
3880HANDLE_OPCODE(OP_UNUSED_6FFF)
3881OP_END
3882
3883/* File: c/OP_UNUSED_70FF.c */
3884HANDLE_OPCODE(OP_UNUSED_70FF)
3885OP_END
3886
3887/* File: c/OP_UNUSED_71FF.c */
3888HANDLE_OPCODE(OP_UNUSED_71FF)
3889OP_END
3890
3891/* File: c/OP_UNUSED_72FF.c */
3892HANDLE_OPCODE(OP_UNUSED_72FF)
3893OP_END
3894
3895/* File: c/OP_UNUSED_73FF.c */
3896HANDLE_OPCODE(OP_UNUSED_73FF)
3897OP_END
3898
3899/* File: c/OP_UNUSED_74FF.c */
3900HANDLE_OPCODE(OP_UNUSED_74FF)
3901OP_END
3902
3903/* File: c/OP_UNUSED_75FF.c */
3904HANDLE_OPCODE(OP_UNUSED_75FF)
3905OP_END
3906
3907/* File: c/OP_UNUSED_76FF.c */
3908HANDLE_OPCODE(OP_UNUSED_76FF)
3909OP_END
3910
3911/* File: c/OP_UNUSED_77FF.c */
3912HANDLE_OPCODE(OP_UNUSED_77FF)
3913OP_END
3914
3915/* File: c/OP_UNUSED_78FF.c */
3916HANDLE_OPCODE(OP_UNUSED_78FF)
3917OP_END
3918
3919/* File: c/OP_UNUSED_79FF.c */
3920HANDLE_OPCODE(OP_UNUSED_79FF)
3921OP_END
3922
3923/* File: c/OP_UNUSED_7AFF.c */
3924HANDLE_OPCODE(OP_UNUSED_7AFF)
3925OP_END
3926
3927/* File: c/OP_UNUSED_7BFF.c */
3928HANDLE_OPCODE(OP_UNUSED_7BFF)
3929OP_END
3930
3931/* File: c/OP_UNUSED_7CFF.c */
3932HANDLE_OPCODE(OP_UNUSED_7CFF)
3933OP_END
3934
3935/* File: c/OP_UNUSED_7DFF.c */
3936HANDLE_OPCODE(OP_UNUSED_7DFF)
3937OP_END
3938
3939/* File: c/OP_UNUSED_7EFF.c */
3940HANDLE_OPCODE(OP_UNUSED_7EFF)
3941OP_END
3942
3943/* File: c/OP_UNUSED_7FFF.c */
3944HANDLE_OPCODE(OP_UNUSED_7FFF)
3945OP_END
3946
3947/* File: c/OP_UNUSED_80FF.c */
3948HANDLE_OPCODE(OP_UNUSED_80FF)
3949OP_END
3950
3951/* File: c/OP_UNUSED_81FF.c */
3952HANDLE_OPCODE(OP_UNUSED_81FF)
3953OP_END
3954
3955/* File: c/OP_UNUSED_82FF.c */
3956HANDLE_OPCODE(OP_UNUSED_82FF)
3957OP_END
3958
3959/* File: c/OP_UNUSED_83FF.c */
3960HANDLE_OPCODE(OP_UNUSED_83FF)
3961OP_END
3962
3963/* File: c/OP_UNUSED_84FF.c */
3964HANDLE_OPCODE(OP_UNUSED_84FF)
3965OP_END
3966
3967/* File: c/OP_UNUSED_85FF.c */
3968HANDLE_OPCODE(OP_UNUSED_85FF)
3969OP_END
3970
3971/* File: c/OP_UNUSED_86FF.c */
3972HANDLE_OPCODE(OP_UNUSED_86FF)
3973OP_END
3974
3975/* File: c/OP_UNUSED_87FF.c */
3976HANDLE_OPCODE(OP_UNUSED_87FF)
3977OP_END
3978
3979/* File: c/OP_UNUSED_88FF.c */
3980HANDLE_OPCODE(OP_UNUSED_88FF)
3981OP_END
3982
3983/* File: c/OP_UNUSED_89FF.c */
3984HANDLE_OPCODE(OP_UNUSED_89FF)
3985OP_END
3986
3987/* File: c/OP_UNUSED_8AFF.c */
3988HANDLE_OPCODE(OP_UNUSED_8AFF)
3989OP_END
3990
3991/* File: c/OP_UNUSED_8BFF.c */
3992HANDLE_OPCODE(OP_UNUSED_8BFF)
3993OP_END
3994
3995/* File: c/OP_UNUSED_8CFF.c */
3996HANDLE_OPCODE(OP_UNUSED_8CFF)
3997OP_END
3998
3999/* File: c/OP_UNUSED_8DFF.c */
4000HANDLE_OPCODE(OP_UNUSED_8DFF)
4001OP_END
4002
4003/* File: c/OP_UNUSED_8EFF.c */
4004HANDLE_OPCODE(OP_UNUSED_8EFF)
4005OP_END
4006
4007/* File: c/OP_UNUSED_8FFF.c */
4008HANDLE_OPCODE(OP_UNUSED_8FFF)
4009OP_END
4010
4011/* File: c/OP_UNUSED_90FF.c */
4012HANDLE_OPCODE(OP_UNUSED_90FF)
4013OP_END
4014
4015/* File: c/OP_UNUSED_91FF.c */
4016HANDLE_OPCODE(OP_UNUSED_91FF)
4017OP_END
4018
4019/* File: c/OP_UNUSED_92FF.c */
4020HANDLE_OPCODE(OP_UNUSED_92FF)
4021OP_END
4022
4023/* File: c/OP_UNUSED_93FF.c */
4024HANDLE_OPCODE(OP_UNUSED_93FF)
4025OP_END
4026
4027/* File: c/OP_UNUSED_94FF.c */
4028HANDLE_OPCODE(OP_UNUSED_94FF)
4029OP_END
4030
4031/* File: c/OP_UNUSED_95FF.c */
4032HANDLE_OPCODE(OP_UNUSED_95FF)
4033OP_END
4034
4035/* File: c/OP_UNUSED_96FF.c */
4036HANDLE_OPCODE(OP_UNUSED_96FF)
4037OP_END
4038
4039/* File: c/OP_UNUSED_97FF.c */
4040HANDLE_OPCODE(OP_UNUSED_97FF)
4041OP_END
4042
4043/* File: c/OP_UNUSED_98FF.c */
4044HANDLE_OPCODE(OP_UNUSED_98FF)
4045OP_END
4046
4047/* File: c/OP_UNUSED_99FF.c */
4048HANDLE_OPCODE(OP_UNUSED_99FF)
4049OP_END
4050
4051/* File: c/OP_UNUSED_9AFF.c */
4052HANDLE_OPCODE(OP_UNUSED_9AFF)
4053OP_END
4054
4055/* File: c/OP_UNUSED_9BFF.c */
4056HANDLE_OPCODE(OP_UNUSED_9BFF)
4057OP_END
4058
4059/* File: c/OP_UNUSED_9CFF.c */
4060HANDLE_OPCODE(OP_UNUSED_9CFF)
4061OP_END
4062
4063/* File: c/OP_UNUSED_9DFF.c */
4064HANDLE_OPCODE(OP_UNUSED_9DFF)
4065OP_END
4066
4067/* File: c/OP_UNUSED_9EFF.c */
4068HANDLE_OPCODE(OP_UNUSED_9EFF)
4069OP_END
4070
4071/* File: c/OP_UNUSED_9FFF.c */
4072HANDLE_OPCODE(OP_UNUSED_9FFF)
4073OP_END
4074
4075/* File: c/OP_UNUSED_A0FF.c */
4076HANDLE_OPCODE(OP_UNUSED_A0FF)
4077OP_END
4078
4079/* File: c/OP_UNUSED_A1FF.c */
4080HANDLE_OPCODE(OP_UNUSED_A1FF)
4081OP_END
4082
4083/* File: c/OP_UNUSED_A2FF.c */
4084HANDLE_OPCODE(OP_UNUSED_A2FF)
4085OP_END
4086
4087/* File: c/OP_UNUSED_A3FF.c */
4088HANDLE_OPCODE(OP_UNUSED_A3FF)
4089OP_END
4090
4091/* File: c/OP_UNUSED_A4FF.c */
4092HANDLE_OPCODE(OP_UNUSED_A4FF)
4093OP_END
4094
4095/* File: c/OP_UNUSED_A5FF.c */
4096HANDLE_OPCODE(OP_UNUSED_A5FF)
4097OP_END
4098
4099/* File: c/OP_UNUSED_A6FF.c */
4100HANDLE_OPCODE(OP_UNUSED_A6FF)
4101OP_END
4102
4103/* File: c/OP_UNUSED_A7FF.c */
4104HANDLE_OPCODE(OP_UNUSED_A7FF)
4105OP_END
4106
4107/* File: c/OP_UNUSED_A8FF.c */
4108HANDLE_OPCODE(OP_UNUSED_A8FF)
4109OP_END
4110
4111/* File: c/OP_UNUSED_A9FF.c */
4112HANDLE_OPCODE(OP_UNUSED_A9FF)
4113OP_END
4114
4115/* File: c/OP_UNUSED_AAFF.c */
4116HANDLE_OPCODE(OP_UNUSED_AAFF)
4117OP_END
4118
4119/* File: c/OP_UNUSED_ABFF.c */
4120HANDLE_OPCODE(OP_UNUSED_ABFF)
4121OP_END
4122
4123/* File: c/OP_UNUSED_ACFF.c */
4124HANDLE_OPCODE(OP_UNUSED_ACFF)
4125OP_END
4126
4127/* File: c/OP_UNUSED_ADFF.c */
4128HANDLE_OPCODE(OP_UNUSED_ADFF)
4129OP_END
4130
4131/* File: c/OP_UNUSED_AEFF.c */
4132HANDLE_OPCODE(OP_UNUSED_AEFF)
4133OP_END
4134
4135/* File: c/OP_UNUSED_AFFF.c */
4136HANDLE_OPCODE(OP_UNUSED_AFFF)
4137OP_END
4138
4139/* File: c/OP_UNUSED_B0FF.c */
4140HANDLE_OPCODE(OP_UNUSED_B0FF)
4141OP_END
4142
4143/* File: c/OP_UNUSED_B1FF.c */
4144HANDLE_OPCODE(OP_UNUSED_B1FF)
4145OP_END
4146
4147/* File: c/OP_UNUSED_B2FF.c */
4148HANDLE_OPCODE(OP_UNUSED_B2FF)
4149OP_END
4150
4151/* File: c/OP_UNUSED_B3FF.c */
4152HANDLE_OPCODE(OP_UNUSED_B3FF)
4153OP_END
4154
4155/* File: c/OP_UNUSED_B4FF.c */
4156HANDLE_OPCODE(OP_UNUSED_B4FF)
4157OP_END
4158
4159/* File: c/OP_UNUSED_B5FF.c */
4160HANDLE_OPCODE(OP_UNUSED_B5FF)
4161OP_END
4162
4163/* File: c/OP_UNUSED_B6FF.c */
4164HANDLE_OPCODE(OP_UNUSED_B6FF)
4165OP_END
4166
4167/* File: c/OP_UNUSED_B7FF.c */
4168HANDLE_OPCODE(OP_UNUSED_B7FF)
4169OP_END
4170
4171/* File: c/OP_UNUSED_B8FF.c */
4172HANDLE_OPCODE(OP_UNUSED_B8FF)
4173OP_END
4174
4175/* File: c/OP_UNUSED_B9FF.c */
4176HANDLE_OPCODE(OP_UNUSED_B9FF)
4177OP_END
4178
4179/* File: c/OP_UNUSED_BAFF.c */
4180HANDLE_OPCODE(OP_UNUSED_BAFF)
4181OP_END
4182
4183/* File: c/OP_UNUSED_BBFF.c */
4184HANDLE_OPCODE(OP_UNUSED_BBFF)
4185OP_END
4186
4187/* File: c/OP_UNUSED_BCFF.c */
4188HANDLE_OPCODE(OP_UNUSED_BCFF)
4189OP_END
4190
4191/* File: c/OP_UNUSED_BDFF.c */
4192HANDLE_OPCODE(OP_UNUSED_BDFF)
4193OP_END
4194
4195/* File: c/OP_UNUSED_BEFF.c */
4196HANDLE_OPCODE(OP_UNUSED_BEFF)
4197OP_END
4198
4199/* File: c/OP_UNUSED_BFFF.c */
4200HANDLE_OPCODE(OP_UNUSED_BFFF)
4201OP_END
4202
4203/* File: c/OP_UNUSED_C0FF.c */
4204HANDLE_OPCODE(OP_UNUSED_C0FF)
4205OP_END
4206
4207/* File: c/OP_UNUSED_C1FF.c */
4208HANDLE_OPCODE(OP_UNUSED_C1FF)
4209OP_END
4210
4211/* File: c/OP_UNUSED_C2FF.c */
4212HANDLE_OPCODE(OP_UNUSED_C2FF)
4213OP_END
4214
4215/* File: c/OP_UNUSED_C3FF.c */
4216HANDLE_OPCODE(OP_UNUSED_C3FF)
4217OP_END
4218
4219/* File: c/OP_UNUSED_C4FF.c */
4220HANDLE_OPCODE(OP_UNUSED_C4FF)
4221OP_END
4222
4223/* File: c/OP_UNUSED_C5FF.c */
4224HANDLE_OPCODE(OP_UNUSED_C5FF)
4225OP_END
4226
4227/* File: c/OP_UNUSED_C6FF.c */
4228HANDLE_OPCODE(OP_UNUSED_C6FF)
4229OP_END
4230
4231/* File: c/OP_UNUSED_C7FF.c */
4232HANDLE_OPCODE(OP_UNUSED_C7FF)
4233OP_END
4234
4235/* File: c/OP_UNUSED_C8FF.c */
4236HANDLE_OPCODE(OP_UNUSED_C8FF)
4237OP_END
4238
4239/* File: c/OP_UNUSED_C9FF.c */
4240HANDLE_OPCODE(OP_UNUSED_C9FF)
4241OP_END
4242
4243/* File: c/OP_UNUSED_CAFF.c */
4244HANDLE_OPCODE(OP_UNUSED_CAFF)
4245OP_END
4246
4247/* File: c/OP_UNUSED_CBFF.c */
4248HANDLE_OPCODE(OP_UNUSED_CBFF)
4249OP_END
4250
4251/* File: c/OP_UNUSED_CCFF.c */
4252HANDLE_OPCODE(OP_UNUSED_CCFF)
4253OP_END
4254
4255/* File: c/OP_UNUSED_CDFF.c */
4256HANDLE_OPCODE(OP_UNUSED_CDFF)
4257OP_END
4258
4259/* File: c/OP_UNUSED_CEFF.c */
4260HANDLE_OPCODE(OP_UNUSED_CEFF)
4261OP_END
4262
4263/* File: c/OP_UNUSED_CFFF.c */
4264HANDLE_OPCODE(OP_UNUSED_CFFF)
4265OP_END
4266
4267/* File: c/OP_UNUSED_D0FF.c */
4268HANDLE_OPCODE(OP_UNUSED_D0FF)
4269OP_END
4270
4271/* File: c/OP_UNUSED_D1FF.c */
4272HANDLE_OPCODE(OP_UNUSED_D1FF)
4273OP_END
4274
4275/* File: c/OP_UNUSED_D2FF.c */
4276HANDLE_OPCODE(OP_UNUSED_D2FF)
4277OP_END
4278
4279/* File: c/OP_UNUSED_D3FF.c */
4280HANDLE_OPCODE(OP_UNUSED_D3FF)
4281OP_END
4282
4283/* File: c/OP_UNUSED_D4FF.c */
4284HANDLE_OPCODE(OP_UNUSED_D4FF)
4285OP_END
4286
4287/* File: c/OP_UNUSED_D5FF.c */
4288HANDLE_OPCODE(OP_UNUSED_D5FF)
4289OP_END
4290
4291/* File: c/OP_UNUSED_D6FF.c */
4292HANDLE_OPCODE(OP_UNUSED_D6FF)
4293OP_END
4294
4295/* File: c/OP_UNUSED_D7FF.c */
4296HANDLE_OPCODE(OP_UNUSED_D7FF)
4297OP_END
4298
4299/* File: c/OP_UNUSED_D8FF.c */
4300HANDLE_OPCODE(OP_UNUSED_D8FF)
4301OP_END
4302
4303/* File: c/OP_UNUSED_D9FF.c */
4304HANDLE_OPCODE(OP_UNUSED_D9FF)
4305OP_END
4306
4307/* File: c/OP_UNUSED_DAFF.c */
4308HANDLE_OPCODE(OP_UNUSED_DAFF)
4309OP_END
4310
4311/* File: c/OP_UNUSED_DBFF.c */
4312HANDLE_OPCODE(OP_UNUSED_DBFF)
4313OP_END
4314
4315/* File: c/OP_UNUSED_DCFF.c */
4316HANDLE_OPCODE(OP_UNUSED_DCFF)
4317OP_END
4318
4319/* File: c/OP_UNUSED_DDFF.c */
4320HANDLE_OPCODE(OP_UNUSED_DDFF)
4321OP_END
4322
4323/* File: c/OP_UNUSED_DEFF.c */
4324HANDLE_OPCODE(OP_UNUSED_DEFF)
4325OP_END
4326
4327/* File: c/OP_UNUSED_DFFF.c */
4328HANDLE_OPCODE(OP_UNUSED_DFFF)
4329OP_END
4330
4331/* File: c/OP_UNUSED_E0FF.c */
4332HANDLE_OPCODE(OP_UNUSED_E0FF)
4333OP_END
4334
4335/* File: c/OP_UNUSED_E1FF.c */
4336HANDLE_OPCODE(OP_UNUSED_E1FF)
4337OP_END
4338
4339/* File: c/OP_UNUSED_E2FF.c */
4340HANDLE_OPCODE(OP_UNUSED_E2FF)
4341OP_END
4342
4343/* File: c/OP_UNUSED_E3FF.c */
4344HANDLE_OPCODE(OP_UNUSED_E3FF)
4345OP_END
4346
4347/* File: c/OP_UNUSED_E4FF.c */
4348HANDLE_OPCODE(OP_UNUSED_E4FF)
4349OP_END
4350
4351/* File: c/OP_UNUSED_E5FF.c */
4352HANDLE_OPCODE(OP_UNUSED_E5FF)
4353OP_END
4354
4355/* File: c/OP_UNUSED_E6FF.c */
4356HANDLE_OPCODE(OP_UNUSED_E6FF)
4357OP_END
4358
4359/* File: c/OP_UNUSED_E7FF.c */
4360HANDLE_OPCODE(OP_UNUSED_E7FF)
4361OP_END
4362
4363/* File: c/OP_UNUSED_E8FF.c */
4364HANDLE_OPCODE(OP_UNUSED_E8FF)
4365OP_END
4366
4367/* File: c/OP_UNUSED_E9FF.c */
4368HANDLE_OPCODE(OP_UNUSED_E9FF)
4369OP_END
4370
4371/* File: c/OP_UNUSED_EAFF.c */
4372HANDLE_OPCODE(OP_UNUSED_EAFF)
4373OP_END
4374
4375/* File: c/OP_UNUSED_EBFF.c */
4376HANDLE_OPCODE(OP_UNUSED_EBFF)
4377OP_END
4378
4379/* File: c/OP_UNUSED_ECFF.c */
4380HANDLE_OPCODE(OP_UNUSED_ECFF)
4381OP_END
4382
4383/* File: c/OP_UNUSED_EDFF.c */
4384HANDLE_OPCODE(OP_UNUSED_EDFF)
4385OP_END
4386
4387/* File: c/OP_UNUSED_EEFF.c */
4388HANDLE_OPCODE(OP_UNUSED_EEFF)
4389OP_END
4390
4391/* File: c/OP_UNUSED_EFFF.c */
4392HANDLE_OPCODE(OP_UNUSED_EFFF)
4393OP_END
4394
4395/* File: c/OP_UNUSED_F0FF.c */
4396HANDLE_OPCODE(OP_UNUSED_F0FF)
4397OP_END
4398
4399/* File: c/OP_UNUSED_F1FF.c */
4400HANDLE_OPCODE(OP_UNUSED_F1FF)
4401OP_END
4402
4403/* File: c/OP_UNUSED_F2FF.c */
4404HANDLE_OPCODE(OP_UNUSED_F2FF)
4405OP_END
4406
4407/* File: c/OP_UNUSED_F3FF.c */
4408HANDLE_OPCODE(OP_UNUSED_F3FF)
4409OP_END
4410
4411/* File: c/OP_UNUSED_F4FF.c */
4412HANDLE_OPCODE(OP_UNUSED_F4FF)
4413OP_END
4414
4415/* File: c/OP_UNUSED_F5FF.c */
4416HANDLE_OPCODE(OP_UNUSED_F5FF)
4417OP_END
4418
4419/* File: c/OP_UNUSED_F6FF.c */
4420HANDLE_OPCODE(OP_UNUSED_F6FF)
4421OP_END
4422
4423/* File: c/OP_UNUSED_F7FF.c */
4424HANDLE_OPCODE(OP_UNUSED_F7FF)
4425OP_END
4426
4427/* File: c/OP_UNUSED_F8FF.c */
4428HANDLE_OPCODE(OP_UNUSED_F8FF)
4429OP_END
4430
4431/* File: c/OP_UNUSED_F9FF.c */
4432HANDLE_OPCODE(OP_UNUSED_F9FF)
4433OP_END
4434
4435/* File: c/OP_UNUSED_FAFF.c */
4436HANDLE_OPCODE(OP_UNUSED_FAFF)
4437OP_END
4438
4439/* File: c/OP_UNUSED_FBFF.c */
4440HANDLE_OPCODE(OP_UNUSED_FBFF)
4441OP_END
4442
4443/* File: c/OP_UNUSED_FCFF.c */
4444HANDLE_OPCODE(OP_UNUSED_FCFF)
4445OP_END
4446
4447/* File: c/OP_UNUSED_FDFF.c */
4448HANDLE_OPCODE(OP_UNUSED_FDFF)
4449OP_END
4450
4451/* File: c/OP_UNUSED_FEFF.c */
4452HANDLE_OPCODE(OP_UNUSED_FEFF)
4453 /*
4454 * In portable interp, most unused opcodes will fall through to here.
4455 */
4456 LOGE("unknown opcode 0x%04x\n", INST_INST(inst));
4457 dvmAbort();
4458 FINISH(1);
4459OP_END
4460
4461/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
4462HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
4463 EXPORT_PC();
4464 vsrc1 = FETCH(1);
4465 ref = FETCH(2) | (u4)FETCH(3) << 16; /* class/field/method ref */
4466 dvmThrowVerificationError(curMethod, vsrc1, ref);
4467 GOTO_exceptionThrown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004468OP_END
4469
4470/* File: c/gotoTargets.c */
4471/*
4472 * C footer. This has some common code shared by the various targets.
4473 */
4474
4475/*
4476 * Everything from here on is a "goto target". In the basic interpreter
4477 * we jump into these targets and then jump directly to the handler for
4478 * next instruction. Here, these are subroutines that return to the caller.
4479 */
4480
jeffhao71eee1f2011-01-04 14:18:54 -08004481GOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004482 {
4483 ClassObject* arrayClass;
4484 ArrayObject* newArray;
4485 u4* contents;
4486 char typeCh;
4487 int i;
4488 u4 arg5;
4489
4490 EXPORT_PC();
4491
jeffhao71eee1f2011-01-04 14:18:54 -08004492 if (jumboFormat) {
4493 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */
4494 vsrc1 = FETCH(3); /* #of elements */
4495 vdst = FETCH(4); /* range base */
4496 arg5 = -1; /* silence compiler warning */
4497 ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004498 vsrc1, ref, vdst, vdst+vsrc1-1);
4499 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004500 ref = FETCH(1); /* class ref */
4501 vdst = FETCH(2); /* first 4 regs -or- range base */
4502
4503 if (methodCallRange) {
4504 vsrc1 = INST_AA(inst); /* #of elements */
4505 arg5 = -1; /* silence compiler warning */
4506 ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
4507 vsrc1, ref, vdst, vdst+vsrc1-1);
4508 } else {
4509 arg5 = INST_A(inst);
4510 vsrc1 = INST_B(inst); /* #of elements */
4511 ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
4512 vsrc1, ref, vdst, arg5);
4513 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004514 }
4515
4516 /*
4517 * Resolve the array class.
4518 */
4519 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
4520 if (arrayClass == NULL) {
4521 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
4522 if (arrayClass == NULL)
4523 GOTO_exceptionThrown();
4524 }
4525 /*
4526 if (!dvmIsArrayClass(arrayClass)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004527 dvmThrowRuntimeException(
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004528 "filled-new-array needs array class");
4529 GOTO_exceptionThrown();
4530 }
4531 */
4532 /* verifier guarantees this is an array class */
4533 assert(dvmIsArrayClass(arrayClass));
4534 assert(dvmIsClassInitialized(arrayClass));
4535
4536 /*
4537 * Create an array of the specified type.
4538 */
4539 LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
4540 typeCh = arrayClass->descriptor[1];
4541 if (typeCh == 'D' || typeCh == 'J') {
4542 /* category 2 primitives not allowed */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004543 dvmThrowRuntimeException("bad filled array req");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004544 GOTO_exceptionThrown();
4545 } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
4546 /* TODO: requires multiple "fill in" loops with different widths */
4547 LOGE("non-int primitives not implemented\n");
4548 dvmThrowException("Ljava/lang/InternalError;",
4549 "filled-new-array not implemented for anything but 'int'");
4550 GOTO_exceptionThrown();
4551 }
4552
4553 newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
4554 if (newArray == NULL)
4555 GOTO_exceptionThrown();
4556
4557 /*
4558 * Fill in the elements. It's legal for vsrc1 to be zero.
4559 */
4560 contents = (u4*) newArray->contents;
4561 if (methodCallRange) {
4562 for (i = 0; i < vsrc1; i++)
4563 contents[i] = GET_REGISTER(vdst+i);
4564 } else {
4565 assert(vsrc1 <= 5);
4566 if (vsrc1 == 5) {
4567 contents[4] = GET_REGISTER(arg5);
4568 vsrc1--;
4569 }
4570 for (i = 0; i < vsrc1; i++) {
4571 contents[i] = GET_REGISTER(vdst & 0x0f);
4572 vdst >>= 4;
4573 }
4574 }
Barry Hayes364f9d92010-06-11 16:12:47 -07004575 if (typeCh == 'L' || typeCh == '[') {
4576 dvmWriteBarrierArray(newArray, 0, newArray->length);
4577 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004578
4579 retval.l = newArray;
4580 }
jeffhao71eee1f2011-01-04 14:18:54 -08004581 if (jumboFormat) {
4582 FINISH(5);
4583 } else {
4584 FINISH(3);
4585 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004586GOTO_TARGET_END
4587
4588
jeffhao71eee1f2011-01-04 14:18:54 -08004589GOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004590 {
4591 Method* baseMethod;
4592 Object* thisPtr;
4593
4594 EXPORT_PC();
4595
jeffhao71eee1f2011-01-04 14:18:54 -08004596 if (jumboFormat) {
4597 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4598 vsrc1 = FETCH(3); /* count */
4599 vdst = FETCH(4); /* first reg */
4600 ADJUST_PC(2); /* advance pc partially to make returns easier */
4601 ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004602 vsrc1, ref, vdst, vdst+vsrc1-1);
4603 thisPtr = (Object*) GET_REGISTER(vdst);
4604 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004605 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4606 ref = FETCH(1); /* method ref */
4607 vdst = FETCH(2); /* 4 regs -or- first reg */
4608
4609 /*
4610 * The object against which we are executing a method is always
4611 * in the first argument.
4612 */
4613 if (methodCallRange) {
4614 assert(vsrc1 > 0);
4615 ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
4616 vsrc1, ref, vdst, vdst+vsrc1-1);
4617 thisPtr = (Object*) GET_REGISTER(vdst);
4618 } else {
4619 assert((vsrc1>>4) > 0);
4620 ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
4621 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4622 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4623 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004624 }
4625
4626 if (!checkForNull(thisPtr))
4627 GOTO_exceptionThrown();
4628
4629 /*
4630 * Resolve the method. This is the correct method for the static
4631 * type of the object. We also verify access permissions here.
4632 */
4633 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
4634 if (baseMethod == NULL) {
4635 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
4636 if (baseMethod == NULL) {
4637 ILOGV("+ unknown method or access denied\n");
4638 GOTO_exceptionThrown();
4639 }
4640 }
4641
4642 /*
4643 * Combine the object we found with the vtable offset in the
4644 * method.
4645 */
4646 assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
4647 methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
4648
Ben Cheng7a2697d2010-06-07 13:44:23 -07004649#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4650 callsiteClass = thisPtr->clazz;
4651#endif
4652
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004653#if 0
4654 if (dvmIsAbstractMethod(methodToCall)) {
4655 /*
4656 * This can happen if you create two classes, Base and Sub, where
4657 * Sub is a sub-class of Base. Declare a protected abstract
4658 * method foo() in Base, and invoke foo() from a method in Base.
4659 * Base is an "abstract base class" and is never instantiated
4660 * directly. Now, Override foo() in Sub, and use Sub. This
4661 * Works fine unless Sub stops providing an implementation of
4662 * the method.
4663 */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004664 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004665 GOTO_exceptionThrown();
4666 }
4667#else
4668 assert(!dvmIsAbstractMethod(methodToCall) ||
4669 methodToCall->nativeFunc != NULL);
4670#endif
4671
4672 LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
4673 baseMethod->clazz->descriptor, baseMethod->name,
4674 (u4) baseMethod->methodIndex,
4675 methodToCall->clazz->descriptor, methodToCall->name);
4676 assert(methodToCall != NULL);
4677
4678#if 0
4679 if (vsrc1 != methodToCall->insSize) {
4680 LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
4681 baseMethod->clazz->descriptor, baseMethod->name,
4682 (u4) baseMethod->methodIndex,
4683 methodToCall->clazz->descriptor, methodToCall->name);
4684 //dvmDumpClass(baseMethod->clazz);
4685 //dvmDumpClass(methodToCall->clazz);
4686 dvmDumpAllClasses(0);
4687 }
4688#endif
4689
4690 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4691 }
4692GOTO_TARGET_END
4693
jeffhao71eee1f2011-01-04 14:18:54 -08004694GOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004695 {
4696 Method* baseMethod;
4697 u2 thisReg;
4698
4699 EXPORT_PC();
4700
jeffhao71eee1f2011-01-04 14:18:54 -08004701 if (jumboFormat) {
4702 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4703 vsrc1 = FETCH(3); /* count */
4704 vdst = FETCH(4); /* first reg */
4705 ADJUST_PC(2); /* advance pc partially to make returns easier */
4706 ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004707 vsrc1, ref, vdst, vdst+vsrc1-1);
4708 thisReg = vdst;
4709 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004710 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4711 ref = FETCH(1); /* method ref */
4712 vdst = FETCH(2); /* 4 regs -or- first reg */
4713
4714 if (methodCallRange) {
4715 ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
4716 vsrc1, ref, vdst, vdst+vsrc1-1);
4717 thisReg = vdst;
4718 } else {
4719 ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
4720 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4721 thisReg = vdst & 0x0f;
4722 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004723 }
jeffhao71eee1f2011-01-04 14:18:54 -08004724
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004725 /* impossible in well-formed code, but we must check nevertheless */
4726 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4727 GOTO_exceptionThrown();
4728
4729 /*
4730 * Resolve the method. This is the correct method for the static
4731 * type of the object. We also verify access permissions here.
4732 * The first arg to dvmResolveMethod() is just the referring class
4733 * (used for class loaders and such), so we don't want to pass
4734 * the superclass into the resolution call.
4735 */
4736 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
4737 if (baseMethod == NULL) {
4738 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
4739 if (baseMethod == NULL) {
4740 ILOGV("+ unknown method or access denied\n");
4741 GOTO_exceptionThrown();
4742 }
4743 }
4744
4745 /*
4746 * Combine the object we found with the vtable offset in the
4747 * method's class.
4748 *
4749 * We're using the current method's class' superclass, not the
4750 * superclass of "this". This is because we might be executing
4751 * in a method inherited from a superclass, and we want to run
4752 * in that class' superclass.
4753 */
4754 if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
4755 /*
4756 * Method does not exist in the superclass. Could happen if
4757 * superclass gets updated.
4758 */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004759 dvmThrowNoSuchMethodError(baseMethod->name);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004760 GOTO_exceptionThrown();
4761 }
4762 methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
4763#if 0
4764 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004765 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004766 GOTO_exceptionThrown();
4767 }
4768#else
4769 assert(!dvmIsAbstractMethod(methodToCall) ||
4770 methodToCall->nativeFunc != NULL);
4771#endif
4772 LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
4773 baseMethod->clazz->descriptor, baseMethod->name,
4774 methodToCall->clazz->descriptor, methodToCall->name);
4775 assert(methodToCall != NULL);
4776
4777 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4778 }
4779GOTO_TARGET_END
4780
jeffhao71eee1f2011-01-04 14:18:54 -08004781GOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004782 {
4783 Object* thisPtr;
4784 ClassObject* thisClass;
4785
4786 EXPORT_PC();
4787
jeffhao71eee1f2011-01-04 14:18:54 -08004788 if (jumboFormat) {
4789 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4790 vsrc1 = FETCH(3); /* count */
4791 vdst = FETCH(4); /* first reg */
4792 ADJUST_PC(2); /* advance pc partially to make returns easier */
4793 ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004794 vsrc1, ref, vdst, vdst+vsrc1-1);
4795 thisPtr = (Object*) GET_REGISTER(vdst);
4796 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004797 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4798 ref = FETCH(1); /* method ref */
4799 vdst = FETCH(2); /* 4 regs -or- first reg */
4800
4801 /*
4802 * The object against which we are executing a method is always
4803 * in the first argument.
4804 */
4805 if (methodCallRange) {
4806 assert(vsrc1 > 0);
4807 ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
4808 vsrc1, ref, vdst, vdst+vsrc1-1);
4809 thisPtr = (Object*) GET_REGISTER(vdst);
4810 } else {
4811 assert((vsrc1>>4) > 0);
4812 ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
4813 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4814 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4815 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004816 }
jeffhao71eee1f2011-01-04 14:18:54 -08004817
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004818 if (!checkForNull(thisPtr))
4819 GOTO_exceptionThrown();
4820
4821 thisClass = thisPtr->clazz;
4822
Ben Cheng7a2697d2010-06-07 13:44:23 -07004823#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4824 callsiteClass = thisClass;
4825#endif
4826
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004827 /*
4828 * Given a class and a method index, find the Method* with the
4829 * actual code we want to execute.
4830 */
4831 methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
4832 methodClassDex);
4833 if (methodToCall == NULL) {
4834 assert(dvmCheckException(self));
4835 GOTO_exceptionThrown();
4836 }
4837
4838 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4839 }
4840GOTO_TARGET_END
4841
jeffhao71eee1f2011-01-04 14:18:54 -08004842GOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004843 {
4844 u2 thisReg;
4845
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004846 EXPORT_PC();
4847
jeffhao71eee1f2011-01-04 14:18:54 -08004848 if (jumboFormat) {
4849 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4850 vsrc1 = FETCH(3); /* count */
4851 vdst = FETCH(4); /* first reg */
4852 ADJUST_PC(2); /* advance pc partially to make returns easier */
4853 ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004854 vsrc1, ref, vdst, vdst+vsrc1-1);
4855 thisReg = vdst;
4856 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004857 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4858 ref = FETCH(1); /* method ref */
4859 vdst = FETCH(2); /* 4 regs -or- first reg */
4860
4861 if (methodCallRange) {
4862 ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
4863 vsrc1, ref, vdst, vdst+vsrc1-1);
4864 thisReg = vdst;
4865 } else {
4866 ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
4867 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4868 thisReg = vdst & 0x0f;
4869 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004870 }
jeffhao71eee1f2011-01-04 14:18:54 -08004871
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004872 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4873 GOTO_exceptionThrown();
4874
4875 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
4876 if (methodToCall == NULL) {
4877 methodToCall = dvmResolveMethod(curMethod->clazz, ref,
4878 METHOD_DIRECT);
4879 if (methodToCall == NULL) {
4880 ILOGV("+ unknown direct method\n"); // should be impossible
4881 GOTO_exceptionThrown();
4882 }
4883 }
4884 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4885 }
4886GOTO_TARGET_END
4887
jeffhao71eee1f2011-01-04 14:18:54 -08004888GOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004889 EXPORT_PC();
4890
jeffhao71eee1f2011-01-04 14:18:54 -08004891 if (jumboFormat) {
4892 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4893 vsrc1 = FETCH(3); /* count */
4894 vdst = FETCH(4); /* first reg */
4895 ADJUST_PC(2); /* advance pc partially to make returns easier */
4896 ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004897 vsrc1, ref, vdst, vdst+vsrc1-1);
jeffhao71eee1f2011-01-04 14:18:54 -08004898 } else {
4899 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4900 ref = FETCH(1); /* method ref */
4901 vdst = FETCH(2); /* 4 regs -or- first reg */
4902
4903 if (methodCallRange)
4904 ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
4905 vsrc1, ref, vdst, vdst+vsrc1-1);
4906 else
4907 ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
4908 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4909 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004910
4911 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
4912 if (methodToCall == NULL) {
4913 methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
4914 if (methodToCall == NULL) {
4915 ILOGV("+ unknown method\n");
4916 GOTO_exceptionThrown();
4917 }
Ben Chengdd6e8702010-05-07 13:05:47 -07004918
4919 /*
4920 * The JIT needs dvmDexGetResolvedMethod() to return non-null.
4921 * Since we use the portable interpreter to build the trace, this extra
4922 * check is not needed for mterp.
4923 */
4924 if (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL) {
4925 /* Class initialization is still ongoing */
Bill Buzbee1b3da592011-02-03 07:38:22 -08004926 END_JIT_TSELECT();
Ben Chengdd6e8702010-05-07 13:05:47 -07004927 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004928 }
4929 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4930GOTO_TARGET_END
4931
jeffhao71eee1f2011-01-04 14:18:54 -08004932GOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004933 {
4934 Object* thisPtr;
4935
4936 EXPORT_PC();
4937
4938 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4939 ref = FETCH(1); /* vtable index */
4940 vdst = FETCH(2); /* 4 regs -or- first reg */
4941
4942 /*
4943 * The object against which we are executing a method is always
4944 * in the first argument.
4945 */
4946 if (methodCallRange) {
4947 assert(vsrc1 > 0);
4948 ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
4949 vsrc1, ref, vdst, vdst+vsrc1-1);
4950 thisPtr = (Object*) GET_REGISTER(vdst);
4951 } else {
4952 assert((vsrc1>>4) > 0);
4953 ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
4954 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4955 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4956 }
4957
4958 if (!checkForNull(thisPtr))
4959 GOTO_exceptionThrown();
4960
Ben Cheng7a2697d2010-06-07 13:44:23 -07004961#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4962 callsiteClass = thisPtr->clazz;
4963#endif
4964
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004965 /*
4966 * Combine the object we found with the vtable offset in the
4967 * method.
4968 */
jeffhao71eee1f2011-01-04 14:18:54 -08004969 assert(ref < (unsigned int) thisPtr->clazz->vtableCount);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004970 methodToCall = thisPtr->clazz->vtable[ref];
4971
4972#if 0
4973 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004974 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004975 GOTO_exceptionThrown();
4976 }
4977#else
4978 assert(!dvmIsAbstractMethod(methodToCall) ||
4979 methodToCall->nativeFunc != NULL);
4980#endif
4981
4982 LOGVV("+++ virtual[%d]=%s.%s\n",
4983 ref, methodToCall->clazz->descriptor, methodToCall->name);
4984 assert(methodToCall != NULL);
4985
4986 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4987 }
4988GOTO_TARGET_END
4989
jeffhao71eee1f2011-01-04 14:18:54 -08004990GOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004991 {
4992 u2 thisReg;
4993
4994 EXPORT_PC();
4995
4996 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4997 ref = FETCH(1); /* vtable index */
4998 vdst = FETCH(2); /* 4 regs -or- first reg */
4999
5000 if (methodCallRange) {
5001 ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
5002 vsrc1, ref, vdst, vdst+vsrc1-1);
5003 thisReg = vdst;
5004 } else {
5005 ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
5006 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
5007 thisReg = vdst & 0x0f;
5008 }
5009 /* impossible in well-formed code, but we must check nevertheless */
5010 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
5011 GOTO_exceptionThrown();
5012
5013#if 0 /* impossible in optimized + verified code */
5014 if (ref >= curMethod->clazz->super->vtableCount) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08005015 dvmThrowNoSuchMethodError(NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005016 GOTO_exceptionThrown();
5017 }
5018#else
jeffhao71eee1f2011-01-04 14:18:54 -08005019 assert(ref < (unsigned int) curMethod->clazz->super->vtableCount);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005020#endif
5021
5022 /*
5023 * Combine the object we found with the vtable offset in the
5024 * method's class.
5025 *
5026 * We're using the current method's class' superclass, not the
5027 * superclass of "this". This is because we might be executing
5028 * in a method inherited from a superclass, and we want to run
5029 * in the method's class' superclass.
5030 */
5031 methodToCall = curMethod->clazz->super->vtable[ref];
5032
5033#if 0
5034 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08005035 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005036 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