blob: 3d8fe6a366ee224c774ff4f8bc58742841ea8521 [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.
buzbee98f3eb12011-02-28 16:38:50 -0800320 * those created by the various exception throw routines, so that the
321 * exception stack trace can be generated correctly. If we don't do this,
322 * the offset within the current method won't be shown correctly. See the
323 * notes in Exception.c.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800324 *
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); \
buzbee9f601a92011-02-11 17:48:20 -0800517 self->entryPoint = _entryPoint; \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800518 LOGVV("threadid=%d: switch to %s ep=%d adj=%d\n", \
519 self->threadId, \
buzbee9f601a92011-02-11 17:48:20 -0800520 (self->nextMode == INTERP_STD) ? "STD" : "DBG", \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800521 (_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) { \
Dan Bornstein74501e62011-02-24 10:32:47 -0800981 dvmThrowArrayIndexOutOfBoundsException( \
982 GET_REGISTER(vsrc2), arrayObj->length); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800983 GOTO_exceptionThrown(); \
984 } \
985 SET_REGISTER##_regsize(vdst, \
986 ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]); \
987 ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
988 } \
989 FINISH(2);
990
991#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
992 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
993 { \
994 ArrayObject* arrayObj; \
995 u2 arrayInfo; \
996 EXPORT_PC(); \
997 vdst = INST_AA(inst); /* AA: source value */ \
998 arrayInfo = FETCH(1); \
999 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
1000 vsrc2 = arrayInfo >> 8; /* CC: index */ \
1001 ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
1002 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
1003 if (!checkForNull((Object*) arrayObj)) \
1004 GOTO_exceptionThrown(); \
1005 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
Dan Bornstein74501e62011-02-24 10:32:47 -08001006 dvmThrowArrayIndexOutOfBoundsException( \
1007 GET_REGISTER(vsrc2), arrayObj->length); \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001008 GOTO_exceptionThrown(); \
1009 } \
1010 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
1011 ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] = \
1012 GET_REGISTER##_regsize(vdst); \
1013 } \
1014 FINISH(2);
1015
1016/*
1017 * It's possible to get a bad value out of a field with sub-32-bit stores
1018 * because the -quick versions always operate on 32 bits. Consider:
1019 * short foo = -1 (sets a 32-bit register to 0xffffffff)
1020 * iput-quick foo (writes all 32 bits to the field)
1021 * short bar = 1 (sets a 32-bit register to 0x00000001)
1022 * iput-short (writes the low 16 bits to the field)
1023 * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
1024 * This can only happen when optimized and non-optimized code has interleaved
1025 * access to the same field. This is unlikely but possible.
1026 *
1027 * The easiest way to fix this is to always read/write 32 bits at a time. On
1028 * a device with a 16-bit data bus this is sub-optimal. (The alternative
1029 * approach is to have sub-int versions of iget-quick, but now we're wasting
1030 * Dalvik instruction space and making it less likely that handler code will
1031 * already be in the CPU i-cache.)
1032 */
1033#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
1034 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1035 { \
1036 InstField* ifield; \
1037 Object* obj; \
1038 EXPORT_PC(); \
1039 vdst = INST_A(inst); \
1040 vsrc1 = INST_B(inst); /* object ptr */ \
1041 ref = FETCH(1); /* field ref */ \
1042 ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1043 obj = (Object*) GET_REGISTER(vsrc1); \
1044 if (!checkForNull(obj)) \
1045 GOTO_exceptionThrown(); \
1046 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1047 if (ifield == NULL) { \
1048 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1049 if (ifield == NULL) \
1050 GOTO_exceptionThrown(); \
1051 } \
1052 SET_REGISTER##_regsize(vdst, \
1053 dvmGetField##_ftype(obj, ifield->byteOffset)); \
1054 ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
1055 (u8) GET_REGISTER##_regsize(vdst)); \
1056 UPDATE_FIELD_GET(&ifield->field); \
1057 } \
1058 FINISH(2);
1059
jeffhao71eee1f2011-01-04 14:18:54 -08001060#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1061 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
1062 { \
1063 InstField* ifield; \
1064 Object* obj; \
1065 EXPORT_PC(); \
1066 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1067 vdst = FETCH(3); \
1068 vsrc1 = FETCH(4); /* object ptr */ \
1069 ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
1070 (_opname), vdst, vsrc1, ref); \
1071 obj = (Object*) GET_REGISTER(vsrc1); \
1072 if (!checkForNull(obj)) \
1073 GOTO_exceptionThrown(); \
1074 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1075 if (ifield == NULL) { \
1076 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1077 if (ifield == NULL) \
1078 GOTO_exceptionThrown(); \
1079 } \
1080 SET_REGISTER##_regsize(vdst, \
1081 dvmGetField##_ftype(obj, ifield->byteOffset)); \
1082 ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
1083 (u8) GET_REGISTER##_regsize(vdst)); \
1084 UPDATE_FIELD_GET(&ifield->field); \
1085 } \
1086 FINISH(5);
1087
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001088#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
1089 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1090 { \
1091 Object* obj; \
1092 vdst = INST_A(inst); \
1093 vsrc1 = INST_B(inst); /* object ptr */ \
1094 ref = FETCH(1); /* field offset */ \
1095 ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
1096 (_opname), vdst, vsrc1, ref); \
1097 obj = (Object*) GET_REGISTER(vsrc1); \
1098 if (!checkForNullExportPC(obj, fp, pc)) \
1099 GOTO_exceptionThrown(); \
1100 SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
1101 ILOGV("+ IGETQ %d=0x%08llx", ref, \
1102 (u8) GET_REGISTER##_regsize(vdst)); \
1103 } \
1104 FINISH(2);
1105
1106#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
1107 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1108 { \
1109 InstField* ifield; \
1110 Object* obj; \
1111 EXPORT_PC(); \
1112 vdst = INST_A(inst); \
1113 vsrc1 = INST_B(inst); /* object ptr */ \
1114 ref = FETCH(1); /* field ref */ \
1115 ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1116 obj = (Object*) GET_REGISTER(vsrc1); \
1117 if (!checkForNull(obj)) \
1118 GOTO_exceptionThrown(); \
1119 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1120 if (ifield == NULL) { \
1121 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1122 if (ifield == NULL) \
1123 GOTO_exceptionThrown(); \
1124 } \
1125 dvmSetField##_ftype(obj, ifield->byteOffset, \
1126 GET_REGISTER##_regsize(vdst)); \
1127 ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
1128 (u8) GET_REGISTER##_regsize(vdst)); \
1129 UPDATE_FIELD_PUT(&ifield->field); \
1130 } \
1131 FINISH(2);
1132
jeffhao71eee1f2011-01-04 14:18:54 -08001133#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1134 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
1135 { \
1136 InstField* ifield; \
1137 Object* obj; \
1138 EXPORT_PC(); \
1139 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1140 vdst = FETCH(3); \
1141 vsrc1 = FETCH(4); /* object ptr */ \
1142 ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
1143 (_opname), vdst, vsrc1, ref); \
1144 obj = (Object*) GET_REGISTER(vsrc1); \
1145 if (!checkForNull(obj)) \
1146 GOTO_exceptionThrown(); \
1147 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1148 if (ifield == NULL) { \
1149 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1150 if (ifield == NULL) \
1151 GOTO_exceptionThrown(); \
1152 } \
1153 dvmSetField##_ftype(obj, ifield->byteOffset, \
1154 GET_REGISTER##_regsize(vdst)); \
1155 ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
1156 (u8) GET_REGISTER##_regsize(vdst)); \
1157 UPDATE_FIELD_PUT(&ifield->field); \
1158 } \
1159 FINISH(5);
1160
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001161#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
1162 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1163 { \
1164 Object* obj; \
1165 vdst = INST_A(inst); \
1166 vsrc1 = INST_B(inst); /* object ptr */ \
1167 ref = FETCH(1); /* field offset */ \
1168 ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
1169 (_opname), vdst, vsrc1, ref); \
1170 obj = (Object*) GET_REGISTER(vsrc1); \
1171 if (!checkForNullExportPC(obj, fp, pc)) \
1172 GOTO_exceptionThrown(); \
1173 dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
1174 ILOGV("+ IPUTQ %d=0x%08llx", ref, \
1175 (u8) GET_REGISTER##_regsize(vdst)); \
1176 } \
1177 FINISH(2);
1178
Ben Chengdd6e8702010-05-07 13:05:47 -07001179/*
1180 * The JIT needs dvmDexGetResolvedField() to return non-null.
1181 * Since we use the portable interpreter to build the trace, the extra
1182 * checks in HANDLE_SGET_X and HANDLE_SPUT_X are not needed for mterp.
1183 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001184#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
1185 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
1186 { \
1187 StaticField* sfield; \
1188 vdst = INST_AA(inst); \
1189 ref = FETCH(1); /* field ref */ \
1190 ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
1191 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1192 if (sfield == NULL) { \
1193 EXPORT_PC(); \
1194 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1195 if (sfield == NULL) \
1196 GOTO_exceptionThrown(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001197 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001198 END_JIT_TSELECT(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001199 } \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001200 } \
1201 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
1202 ILOGV("+ SGET '%s'=0x%08llx", \
1203 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1204 UPDATE_FIELD_GET(&sfield->field); \
1205 } \
1206 FINISH(2);
1207
jeffhao71eee1f2011-01-04 14:18:54 -08001208#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1209 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
1210 { \
1211 StaticField* sfield; \
1212 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1213 vdst = FETCH(3); \
1214 ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
1215 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1216 if (sfield == NULL) { \
1217 EXPORT_PC(); \
1218 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1219 if (sfield == NULL) \
1220 GOTO_exceptionThrown(); \
1221 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001222 END_JIT_TSELECT(); \
jeffhao71eee1f2011-01-04 14:18:54 -08001223 } \
1224 } \
1225 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
1226 ILOGV("+ SGET '%s'=0x%08llx", \
1227 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1228 UPDATE_FIELD_GET(&sfield->field); \
1229 } \
1230 FINISH(4);
1231
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001232#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
1233 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
1234 { \
1235 StaticField* sfield; \
1236 vdst = INST_AA(inst); \
1237 ref = FETCH(1); /* field ref */ \
1238 ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
1239 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1240 if (sfield == NULL) { \
1241 EXPORT_PC(); \
1242 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1243 if (sfield == NULL) \
1244 GOTO_exceptionThrown(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001245 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001246 END_JIT_TSELECT(); \
Ben Chengdd6e8702010-05-07 13:05:47 -07001247 } \
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001248 } \
1249 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
1250 ILOGV("+ SPUT '%s'=0x%08llx", \
1251 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1252 UPDATE_FIELD_PUT(&sfield->field); \
1253 } \
1254 FINISH(2);
1255
jeffhao71eee1f2011-01-04 14:18:54 -08001256#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1257 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
1258 { \
1259 StaticField* sfield; \
1260 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1261 vdst = FETCH(3); \
1262 ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
1263 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1264 if (sfield == NULL) { \
1265 EXPORT_PC(); \
1266 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1267 if (sfield == NULL) \
1268 GOTO_exceptionThrown(); \
1269 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
Bill Buzbee1b3da592011-02-03 07:38:22 -08001270 END_JIT_TSELECT(); \
jeffhao71eee1f2011-01-04 14:18:54 -08001271 } \
1272 } \
1273 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
1274 ILOGV("+ SPUT '%s'=0x%08llx", \
1275 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
1276 UPDATE_FIELD_PUT(&sfield->field); \
1277 } \
1278 FINISH(4);
1279
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001280/* File: portable/entry.c */
1281/*
1282 * Main interpreter loop.
1283 *
1284 * This was written with an ARM implementation in mind.
1285 */
buzbee9f601a92011-02-11 17:48:20 -08001286bool INTERP_FUNC_NAME(Thread* self)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001287{
1288#if defined(EASY_GDB)
1289 StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->curFrame);
1290#endif
1291#if INTERP_TYPE == INTERP_DBG
Andy McFaddenc95e0fb2010-04-29 14:13:01 -07001292 bool debugIsMethodEntry = false;
buzbee9f601a92011-02-11 17:48:20 -08001293 debugIsMethodEntry = self->debugIsMethodEntry;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001294#endif
1295#if defined(WITH_TRACKREF_CHECKS)
buzbeeef5db622011-02-22 14:01:46 -08001296 int debugTrackedRefStart = self->interpSave.debugTrackedRefStart;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001297#endif
1298 DvmDex* methodClassDex; // curMethod->clazz->pDvmDex
1299 JValue retval;
1300
1301 /* core state */
1302 const Method* curMethod; // method we're interpreting
1303 const u2* pc; // program counter
1304 u4* fp; // frame pointer
1305 u2 inst; // current instruction
1306 /* instruction decoding */
jeffhao71eee1f2011-01-04 14:18:54 -08001307 u4 ref; // 16 or 32-bit quantity fetched directly
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001308 u2 vsrc1, vsrc2, vdst; // usually used for register indexes
1309 /* method call setup */
1310 const Method* methodToCall;
1311 bool methodCallRange;
jeffhao71eee1f2011-01-04 14:18:54 -08001312 bool jumboFormat;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001313
Ben Chengba4fc8b2009-06-01 13:00:29 -07001314
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001315#if defined(THREADED_INTERP)
1316 /* static computed goto table */
1317 DEFINE_GOTO_TABLE(handlerTable);
1318#endif
1319
Ben Chengba4fc8b2009-06-01 13:00:29 -07001320#if defined(WITH_JIT)
1321#if 0
1322 LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n",
buzbee9f601a92011-02-11 17:48:20 -08001323 self->entryPoint,
1324 self->interpSave.pc,
1325 self->interpSave.method->name);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001326#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001327#if INTERP_TYPE == INTERP_DBG
Ben Cheng7a2697d2010-06-07 13:44:23 -07001328 const ClassObject* callsiteClass = NULL;
1329
1330#if defined(WITH_SELF_VERIFICATION)
buzbee9f601a92011-02-11 17:48:20 -08001331 if (self->jitState != kJitSelfVerification) {
1332 self->shadowSpace->jitExitState = kSVSIdle;
Ben Cheng7a2697d2010-06-07 13:44:23 -07001333 }
1334#endif
1335
Bill Buzbee06bb8392010-01-31 18:53:15 -08001336 /* Check to see if we've got a trace selection request. */
1337 if (
Ben Cheng95cd9ac2010-03-12 16:58:24 -08001338 /*
Ben Chenga4973592010-03-31 11:59:18 -07001339 * Only perform dvmJitCheckTraceRequest if the entry point is
1340 * EntryInstr and the jit state is either kJitTSelectRequest or
1341 * kJitTSelectRequestHot. If debugger/profiler happens to be attached,
1342 * dvmJitCheckTraceRequest will change the jitState to kJitDone but
1343 * but stay in the dbg interpreter.
Ben Cheng95cd9ac2010-03-12 16:58:24 -08001344 */
buzbee9f601a92011-02-11 17:48:20 -08001345 (self->entryPoint == kInterpEntryInstr) &&
1346 (self->jitState == kJitTSelectRequest ||
1347 self->jitState == kJitTSelectRequestHot) &&
1348 dvmJitCheckTraceRequest(self)) {
1349 self->nextMode = INTERP_STD;
Bill Buzbee06bb8392010-01-31 18:53:15 -08001350 //LOGD("Invalid trace request, exiting\n");
Ben Chengba4fc8b2009-06-01 13:00:29 -07001351 return true;
1352 }
Jeff Hao97319a82009-08-12 16:57:15 -07001353#endif /* INTERP_TYPE == INTERP_DBG */
1354#endif /* WITH_JIT */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001355
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001356 /* copy state in */
buzbee9f601a92011-02-11 17:48:20 -08001357 curMethod = self->interpSave.method;
1358 pc = self->interpSave.pc;
1359 fp = self->interpSave.fp;
1360 retval = self->retval; /* only need for kInterpEntryReturn? */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001361
1362 methodClassDex = curMethod->clazz->pDvmDex;
1363
1364 LOGVV("threadid=%d: entry(%s) %s.%s pc=0x%x fp=%p ep=%d\n",
buzbee9f601a92011-02-11 17:48:20 -08001365 self->threadId, (self->nextMode == INTERP_STD) ? "STD" : "DBG",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001366 curMethod->clazz->descriptor, curMethod->name, pc - curMethod->insns,
buzbee9f601a92011-02-11 17:48:20 -08001367 fp, self->entryPoint);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001368
1369 /*
1370 * DEBUG: scramble this to ensure we're not relying on it.
1371 */
1372 methodToCall = (const Method*) -1;
1373
1374#if INTERP_TYPE == INTERP_DBG
1375 if (debugIsMethodEntry) {
1376 ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
1377 curMethod->name);
buzbee9f601a92011-02-11 17:48:20 -08001378 DUMP_REGS(curMethod, self->interpSave.fp, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001379 }
1380#endif
1381
buzbee9f601a92011-02-11 17:48:20 -08001382 switch (self->entryPoint) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001383 case kInterpEntryInstr:
1384 /* just fall through to instruction loop or threaded kickstart */
1385 break;
1386 case kInterpEntryReturn:
Ben Chengfc075c22010-05-28 15:20:08 -07001387 CHECK_JIT_VOID();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001388 goto returnFromMethod;
1389 case kInterpEntryThrow:
1390 goto exceptionThrown;
1391 default:
1392 dvmAbort();
1393 }
1394
1395#ifdef THREADED_INTERP
1396 FINISH(0); /* fetch and execute first instruction */
1397#else
1398 while (1) {
1399 CHECK_DEBUG_AND_PROF(); /* service debugger and profiling */
1400 CHECK_TRACKED_REFS(); /* check local reference tracking */
1401
1402 /* fetch the next 16 bits from the instruction stream */
1403 inst = FETCH(0);
1404
1405 switch (INST_INST(inst)) {
1406#endif
1407
1408/*--- start of opcodes ---*/
1409
1410/* File: c/OP_NOP.c */
1411HANDLE_OPCODE(OP_NOP)
1412 FINISH(1);
1413OP_END
1414
1415/* File: c/OP_MOVE.c */
1416HANDLE_OPCODE(OP_MOVE /*vA, vB*/)
1417 vdst = INST_A(inst);
1418 vsrc1 = INST_B(inst);
1419 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",
1420 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
1421 kSpacing, vdst, GET_REGISTER(vsrc1));
1422 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1423 FINISH(1);
1424OP_END
1425
1426/* File: c/OP_MOVE_FROM16.c */
1427HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/)
1428 vdst = INST_AA(inst);
1429 vsrc1 = FETCH(1);
1430 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)",
1431 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1,
1432 kSpacing, vdst, GET_REGISTER(vsrc1));
1433 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1434 FINISH(2);
1435OP_END
1436
1437/* File: c/OP_MOVE_16.c */
1438HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/)
1439 vdst = FETCH(1);
1440 vsrc1 = FETCH(2);
1441 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)",
1442 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1,
1443 kSpacing, vdst, GET_REGISTER(vsrc1));
1444 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1445 FINISH(3);
1446OP_END
1447
1448/* File: c/OP_MOVE_WIDE.c */
1449HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/)
1450 /* IMPORTANT: must correctly handle overlapping registers, e.g. both
1451 * "move-wide v6, v7" and "move-wide v7, v6" */
1452 vdst = INST_A(inst);
1453 vsrc1 = INST_B(inst);
1454 ILOGV("|move-wide v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1,
1455 kSpacing+5, vdst, GET_REGISTER_WIDE(vsrc1));
1456 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1457 FINISH(1);
1458OP_END
1459
1460/* File: c/OP_MOVE_WIDE_FROM16.c */
1461HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/)
1462 vdst = INST_AA(inst);
1463 vsrc1 = FETCH(1);
1464 ILOGV("|move-wide/from16 v%d,v%d (v%d=0x%08llx)", vdst, vsrc1,
1465 vdst, GET_REGISTER_WIDE(vsrc1));
1466 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1467 FINISH(2);
1468OP_END
1469
1470/* File: c/OP_MOVE_WIDE_16.c */
1471HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/)
1472 vdst = FETCH(1);
1473 vsrc1 = FETCH(2);
1474 ILOGV("|move-wide/16 v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1,
1475 kSpacing+8, vdst, GET_REGISTER_WIDE(vsrc1));
1476 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1477 FINISH(3);
1478OP_END
1479
1480/* File: c/OP_MOVE_OBJECT.c */
1481/* File: c/OP_MOVE.c */
1482HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/)
1483 vdst = INST_A(inst);
1484 vsrc1 = INST_B(inst);
1485 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",
1486 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
1487 kSpacing, vdst, GET_REGISTER(vsrc1));
1488 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1489 FINISH(1);
1490OP_END
1491
1492
1493/* File: c/OP_MOVE_OBJECT_FROM16.c */
1494/* File: c/OP_MOVE_FROM16.c */
1495HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/)
1496 vdst = INST_AA(inst);
1497 vsrc1 = FETCH(1);
1498 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)",
1499 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1,
1500 kSpacing, vdst, GET_REGISTER(vsrc1));
1501 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1502 FINISH(2);
1503OP_END
1504
1505
1506/* File: c/OP_MOVE_OBJECT_16.c */
1507/* File: c/OP_MOVE_16.c */
1508HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/)
1509 vdst = FETCH(1);
1510 vsrc1 = FETCH(2);
1511 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)",
1512 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1,
1513 kSpacing, vdst, GET_REGISTER(vsrc1));
1514 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1515 FINISH(3);
1516OP_END
1517
1518
1519/* File: c/OP_MOVE_RESULT.c */
1520HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/)
1521 vdst = INST_AA(inst);
1522 ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
1523 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object",
1524 vdst, kSpacing+4, vdst,retval.i);
1525 SET_REGISTER(vdst, retval.i);
1526 FINISH(1);
1527OP_END
1528
1529/* File: c/OP_MOVE_RESULT_WIDE.c */
1530HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/)
1531 vdst = INST_AA(inst);
1532 ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j);
1533 SET_REGISTER_WIDE(vdst, retval.j);
1534 FINISH(1);
1535OP_END
1536
1537/* File: c/OP_MOVE_RESULT_OBJECT.c */
1538/* File: c/OP_MOVE_RESULT.c */
1539HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/)
1540 vdst = INST_AA(inst);
1541 ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
1542 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object",
1543 vdst, kSpacing+4, vdst,retval.i);
1544 SET_REGISTER(vdst, retval.i);
1545 FINISH(1);
1546OP_END
1547
1548
1549/* File: c/OP_MOVE_EXCEPTION.c */
1550HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/)
1551 vdst = INST_AA(inst);
1552 ILOGV("|move-exception v%d", vdst);
1553 assert(self->exception != NULL);
1554 SET_REGISTER(vdst, (u4)self->exception);
1555 dvmClearException(self);
1556 FINISH(1);
1557OP_END
1558
1559/* File: c/OP_RETURN_VOID.c */
1560HANDLE_OPCODE(OP_RETURN_VOID /**/)
1561 ILOGV("|return-void");
1562#ifndef NDEBUG
1563 retval.j = 0xababababULL; // placate valgrind
1564#endif
1565 GOTO_returnFromMethod();
1566OP_END
1567
1568/* File: c/OP_RETURN.c */
1569HANDLE_OPCODE(OP_RETURN /*vAA*/)
1570 vsrc1 = INST_AA(inst);
1571 ILOGV("|return%s v%d",
1572 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
1573 retval.i = GET_REGISTER(vsrc1);
1574 GOTO_returnFromMethod();
1575OP_END
1576
1577/* File: c/OP_RETURN_WIDE.c */
1578HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/)
1579 vsrc1 = INST_AA(inst);
1580 ILOGV("|return-wide v%d", vsrc1);
1581 retval.j = GET_REGISTER_WIDE(vsrc1);
1582 GOTO_returnFromMethod();
1583OP_END
1584
1585/* File: c/OP_RETURN_OBJECT.c */
1586/* File: c/OP_RETURN.c */
1587HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/)
1588 vsrc1 = INST_AA(inst);
1589 ILOGV("|return%s v%d",
1590 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
1591 retval.i = GET_REGISTER(vsrc1);
1592 GOTO_returnFromMethod();
1593OP_END
1594
1595
1596/* File: c/OP_CONST_4.c */
1597HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/)
1598 {
1599 s4 tmp;
1600
1601 vdst = INST_A(inst);
1602 tmp = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
1603 ILOGV("|const/4 v%d,#0x%02x", vdst, (s4)tmp);
1604 SET_REGISTER(vdst, tmp);
1605 }
1606 FINISH(1);
1607OP_END
1608
1609/* File: c/OP_CONST_16.c */
1610HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/)
1611 vdst = INST_AA(inst);
1612 vsrc1 = FETCH(1);
1613 ILOGV("|const/16 v%d,#0x%04x", vdst, (s2)vsrc1);
1614 SET_REGISTER(vdst, (s2) vsrc1);
1615 FINISH(2);
1616OP_END
1617
1618/* File: c/OP_CONST.c */
1619HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/)
1620 {
1621 u4 tmp;
1622
1623 vdst = INST_AA(inst);
1624 tmp = FETCH(1);
1625 tmp |= (u4)FETCH(2) << 16;
1626 ILOGV("|const v%d,#0x%08x", vdst, tmp);
1627 SET_REGISTER(vdst, tmp);
1628 }
1629 FINISH(3);
1630OP_END
1631
1632/* File: c/OP_CONST_HIGH16.c */
1633HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/)
1634 vdst = INST_AA(inst);
1635 vsrc1 = FETCH(1);
1636 ILOGV("|const/high16 v%d,#0x%04x0000", vdst, vsrc1);
1637 SET_REGISTER(vdst, vsrc1 << 16);
1638 FINISH(2);
1639OP_END
1640
1641/* File: c/OP_CONST_WIDE_16.c */
1642HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/)
1643 vdst = INST_AA(inst);
1644 vsrc1 = FETCH(1);
1645 ILOGV("|const-wide/16 v%d,#0x%04x", vdst, (s2)vsrc1);
1646 SET_REGISTER_WIDE(vdst, (s2)vsrc1);
1647 FINISH(2);
1648OP_END
1649
1650/* File: c/OP_CONST_WIDE_32.c */
1651HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/)
1652 {
1653 u4 tmp;
1654
1655 vdst = INST_AA(inst);
1656 tmp = FETCH(1);
1657 tmp |= (u4)FETCH(2) << 16;
1658 ILOGV("|const-wide/32 v%d,#0x%08x", vdst, tmp);
1659 SET_REGISTER_WIDE(vdst, (s4) tmp);
1660 }
1661 FINISH(3);
1662OP_END
1663
1664/* File: c/OP_CONST_WIDE.c */
1665HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/)
1666 {
1667 u8 tmp;
1668
1669 vdst = INST_AA(inst);
1670 tmp = FETCH(1);
1671 tmp |= (u8)FETCH(2) << 16;
1672 tmp |= (u8)FETCH(3) << 32;
1673 tmp |= (u8)FETCH(4) << 48;
1674 ILOGV("|const-wide v%d,#0x%08llx", vdst, tmp);
1675 SET_REGISTER_WIDE(vdst, tmp);
1676 }
1677 FINISH(5);
1678OP_END
1679
1680/* File: c/OP_CONST_WIDE_HIGH16.c */
1681HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/)
1682 vdst = INST_AA(inst);
1683 vsrc1 = FETCH(1);
1684 ILOGV("|const-wide/high16 v%d,#0x%04x000000000000", vdst, vsrc1);
1685 SET_REGISTER_WIDE(vdst, ((u8) vsrc1) << 48);
1686 FINISH(2);
1687OP_END
1688
1689/* File: c/OP_CONST_STRING.c */
1690HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/)
1691 {
1692 StringObject* strObj;
1693
1694 vdst = INST_AA(inst);
1695 ref = FETCH(1);
1696 ILOGV("|const-string v%d string@0x%04x", vdst, ref);
1697 strObj = dvmDexGetResolvedString(methodClassDex, ref);
1698 if (strObj == NULL) {
1699 EXPORT_PC();
1700 strObj = dvmResolveString(curMethod->clazz, ref);
1701 if (strObj == NULL)
1702 GOTO_exceptionThrown();
1703 }
1704 SET_REGISTER(vdst, (u4) strObj);
1705 }
1706 FINISH(2);
1707OP_END
1708
1709/* File: c/OP_CONST_STRING_JUMBO.c */
1710HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/)
1711 {
1712 StringObject* strObj;
1713 u4 tmp;
1714
1715 vdst = INST_AA(inst);
1716 tmp = FETCH(1);
1717 tmp |= (u4)FETCH(2) << 16;
1718 ILOGV("|const-string/jumbo v%d string@0x%08x", vdst, tmp);
1719 strObj = dvmDexGetResolvedString(methodClassDex, tmp);
1720 if (strObj == NULL) {
1721 EXPORT_PC();
1722 strObj = dvmResolveString(curMethod->clazz, tmp);
1723 if (strObj == NULL)
1724 GOTO_exceptionThrown();
1725 }
1726 SET_REGISTER(vdst, (u4) strObj);
1727 }
1728 FINISH(3);
1729OP_END
1730
1731/* File: c/OP_CONST_CLASS.c */
1732HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/)
1733 {
1734 ClassObject* clazz;
1735
1736 vdst = INST_AA(inst);
1737 ref = FETCH(1);
1738 ILOGV("|const-class v%d class@0x%04x", vdst, ref);
1739 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1740 if (clazz == NULL) {
1741 EXPORT_PC();
1742 clazz = dvmResolveClass(curMethod->clazz, ref, true);
1743 if (clazz == NULL)
1744 GOTO_exceptionThrown();
1745 }
1746 SET_REGISTER(vdst, (u4) clazz);
1747 }
1748 FINISH(2);
1749OP_END
1750
1751/* File: c/OP_MONITOR_ENTER.c */
1752HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/)
1753 {
1754 Object* obj;
1755
1756 vsrc1 = INST_AA(inst);
1757 ILOGV("|monitor-enter v%d %s(0x%08x)",
1758 vsrc1, kSpacing+6, GET_REGISTER(vsrc1));
1759 obj = (Object*)GET_REGISTER(vsrc1);
1760 if (!checkForNullExportPC(obj, fp, pc))
1761 GOTO_exceptionThrown();
1762 ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
Carl Shapiro01605d22011-02-01 11:32:44 -08001763 EXPORT_PC(); /* need for precise GC */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001764 dvmLockObject(self, obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001765 }
1766 FINISH(1);
1767OP_END
1768
1769/* File: c/OP_MONITOR_EXIT.c */
1770HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/)
1771 {
1772 Object* obj;
1773
1774 EXPORT_PC();
1775
1776 vsrc1 = INST_AA(inst);
1777 ILOGV("|monitor-exit v%d %s(0x%08x)",
1778 vsrc1, kSpacing+5, GET_REGISTER(vsrc1));
1779 obj = (Object*)GET_REGISTER(vsrc1);
1780 if (!checkForNull(obj)) {
1781 /*
1782 * The exception needs to be processed at the *following*
1783 * instruction, not the current instruction (see the Dalvik
1784 * spec). Because we're jumping to an exception handler,
1785 * we're not actually at risk of skipping an instruction
1786 * by doing so.
1787 */
1788 ADJUST_PC(1); /* monitor-exit width is 1 */
1789 GOTO_exceptionThrown();
1790 }
1791 ILOGV("+ unlocking %p %s\n", obj, obj->clazz->descriptor);
1792 if (!dvmUnlockObject(self, obj)) {
1793 assert(dvmCheckException(self));
1794 ADJUST_PC(1);
1795 GOTO_exceptionThrown();
1796 }
1797 }
1798 FINISH(1);
1799OP_END
1800
1801/* File: c/OP_CHECK_CAST.c */
1802HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/)
1803 {
1804 ClassObject* clazz;
1805 Object* obj;
1806
1807 EXPORT_PC();
1808
1809 vsrc1 = INST_AA(inst);
1810 ref = FETCH(1); /* class to check against */
1811 ILOGV("|check-cast v%d,class@0x%04x", vsrc1, ref);
1812
1813 obj = (Object*)GET_REGISTER(vsrc1);
1814 if (obj != NULL) {
1815#if defined(WITH_EXTRA_OBJECT_VALIDATION)
1816 if (!checkForNull(obj))
1817 GOTO_exceptionThrown();
1818#endif
1819 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1820 if (clazz == NULL) {
1821 clazz = dvmResolveClass(curMethod->clazz, ref, false);
1822 if (clazz == NULL)
1823 GOTO_exceptionThrown();
1824 }
1825 if (!dvmInstanceof(obj->clazz, clazz)) {
Elliott Hughesc560e302010-11-18 11:49:04 -08001826 dvmThrowClassCastException(obj->clazz, clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001827 GOTO_exceptionThrown();
1828 }
1829 }
1830 }
1831 FINISH(2);
1832OP_END
1833
1834/* File: c/OP_INSTANCE_OF.c */
1835HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/)
1836 {
1837 ClassObject* clazz;
1838 Object* obj;
1839
1840 vdst = INST_A(inst);
1841 vsrc1 = INST_B(inst); /* object to check */
1842 ref = FETCH(1); /* class to check against */
1843 ILOGV("|instance-of v%d,v%d,class@0x%04x", vdst, vsrc1, ref);
1844
1845 obj = (Object*)GET_REGISTER(vsrc1);
1846 if (obj == NULL) {
1847 SET_REGISTER(vdst, 0);
1848 } else {
1849#if defined(WITH_EXTRA_OBJECT_VALIDATION)
1850 if (!checkForNullExportPC(obj, fp, pc))
1851 GOTO_exceptionThrown();
1852#endif
1853 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1854 if (clazz == NULL) {
1855 EXPORT_PC();
1856 clazz = dvmResolveClass(curMethod->clazz, ref, true);
1857 if (clazz == NULL)
1858 GOTO_exceptionThrown();
1859 }
1860 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz));
1861 }
1862 }
1863 FINISH(2);
1864OP_END
1865
1866/* File: c/OP_ARRAY_LENGTH.c */
1867HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/)
1868 {
1869 ArrayObject* arrayObj;
1870
1871 vdst = INST_A(inst);
1872 vsrc1 = INST_B(inst);
1873 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
1874 ILOGV("|array-length v%d,v%d (%p)", vdst, vsrc1, arrayObj);
1875 if (!checkForNullExportPC((Object*) arrayObj, fp, pc))
1876 GOTO_exceptionThrown();
1877 /* verifier guarantees this is an array reference */
1878 SET_REGISTER(vdst, arrayObj->length);
1879 }
1880 FINISH(1);
1881OP_END
1882
1883/* File: c/OP_NEW_INSTANCE.c */
1884HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/)
1885 {
1886 ClassObject* clazz;
1887 Object* newObj;
1888
1889 EXPORT_PC();
1890
1891 vdst = INST_AA(inst);
1892 ref = FETCH(1);
1893 ILOGV("|new-instance v%d,class@0x%04x", vdst, ref);
1894 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1895 if (clazz == NULL) {
1896 clazz = dvmResolveClass(curMethod->clazz, ref, false);
1897 if (clazz == NULL)
1898 GOTO_exceptionThrown();
1899 }
1900
1901 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))
1902 GOTO_exceptionThrown();
1903
1904 /*
Ben Chengdd6e8702010-05-07 13:05:47 -07001905 * The JIT needs dvmDexGetResolvedClass() to return non-null.
1906 * Since we use the portable interpreter to build the trace, this extra
1907 * check is not needed for mterp.
1908 */
1909 if (!dvmDexGetResolvedClass(methodClassDex, ref)) {
Bill Buzbee1b3da592011-02-03 07:38:22 -08001910 /* Class initialization is still ongoing - end the trace */
1911 END_JIT_TSELECT();
Ben Chengdd6e8702010-05-07 13:05:47 -07001912 }
1913
1914 /*
Andy McFaddenb51ea112009-05-08 16:50:17 -07001915 * Verifier now tests for interface/abstract class.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001916 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001917 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
Dan Bornstein0b8b2932011-03-04 11:53:40 -08001918 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
Andy McFaddenb51ea112009-05-08 16:50:17 -07001919 // clazz->descriptor);
1920 // GOTO_exceptionThrown();
1921 //}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001922 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1923 if (newObj == NULL)
1924 GOTO_exceptionThrown();
1925 SET_REGISTER(vdst, (u4) newObj);
1926 }
1927 FINISH(2);
1928OP_END
1929
1930/* File: c/OP_NEW_ARRAY.c */
1931HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/)
1932 {
1933 ClassObject* arrayClass;
1934 ArrayObject* newArray;
1935 s4 length;
1936
1937 EXPORT_PC();
1938
1939 vdst = INST_A(inst);
1940 vsrc1 = INST_B(inst); /* length reg */
1941 ref = FETCH(1);
1942 ILOGV("|new-array v%d,v%d,class@0x%04x (%d elements)",
1943 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1));
1944 length = (s4) GET_REGISTER(vsrc1);
1945 if (length < 0) {
Dan Bornstein2c8e25b2011-02-25 15:49:29 -08001946 dvmThrowNegativeArraySizeException(length);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001947 GOTO_exceptionThrown();
1948 }
1949 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
1950 if (arrayClass == NULL) {
1951 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
1952 if (arrayClass == NULL)
1953 GOTO_exceptionThrown();
1954 }
1955 /* verifier guarantees this is an array class */
1956 assert(dvmIsArrayClass(arrayClass));
1957 assert(dvmIsClassInitialized(arrayClass));
1958
1959 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK);
1960 if (newArray == NULL)
1961 GOTO_exceptionThrown();
1962 SET_REGISTER(vdst, (u4) newArray);
1963 }
1964 FINISH(2);
1965OP_END
1966
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001967/* File: c/OP_FILLED_NEW_ARRAY.c */
1968HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08001969 GOTO_invoke(filledNewArray, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001970OP_END
1971
1972/* File: c/OP_FILLED_NEW_ARRAY_RANGE.c */
1973HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08001974 GOTO_invoke(filledNewArray, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001975OP_END
1976
1977/* File: c/OP_FILL_ARRAY_DATA.c */
1978HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/
1979 {
1980 const u2* arrayData;
1981 s4 offset;
1982 ArrayObject* arrayObj;
1983
1984 EXPORT_PC();
1985 vsrc1 = INST_AA(inst);
1986 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
1987 ILOGV("|fill-array-data v%d +0x%04x", vsrc1, offset);
1988 arrayData = pc + offset; // offset in 16-bit units
1989#ifndef NDEBUG
1990 if (arrayData < curMethod->insns ||
1991 arrayData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
1992 {
1993 /* should have been caught in verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001994 dvmThrowInternalError("bad fill array data");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001995 GOTO_exceptionThrown();
1996 }
1997#endif
1998 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
1999 if (!dvmInterpHandleFillArrayData(arrayObj, arrayData)) {
2000 GOTO_exceptionThrown();
2001 }
2002 FINISH(3);
2003 }
2004OP_END
2005
2006/* File: c/OP_THROW.c */
2007HANDLE_OPCODE(OP_THROW /*vAA*/)
2008 {
2009 Object* obj;
2010
Andy McFadden8ba27082010-05-21 12:20:23 -07002011 /*
2012 * We don't create an exception here, but the process of searching
2013 * for a catch block can do class lookups and throw exceptions.
2014 * We need to update the saved PC.
2015 */
2016 EXPORT_PC();
2017
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002018 vsrc1 = INST_AA(inst);
2019 ILOGV("|throw v%d (%p)", vsrc1, (void*)GET_REGISTER(vsrc1));
2020 obj = (Object*) GET_REGISTER(vsrc1);
Andy McFadden8ba27082010-05-21 12:20:23 -07002021 if (!checkForNull(obj)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002022 /* will throw a null pointer exception */
2023 LOGVV("Bad exception\n");
2024 } else {
2025 /* use the requested exception */
2026 dvmSetException(self, obj);
2027 }
2028 GOTO_exceptionThrown();
2029 }
2030OP_END
2031
2032/* File: c/OP_GOTO.c */
2033HANDLE_OPCODE(OP_GOTO /*+AA*/)
2034 vdst = INST_AA(inst);
2035 if ((s1)vdst < 0)
2036 ILOGV("|goto -0x%02x", -((s1)vdst));
2037 else
2038 ILOGV("|goto +0x%02x", ((s1)vdst));
2039 ILOGV("> branch taken");
2040 if ((s1)vdst < 0)
2041 PERIODIC_CHECKS(kInterpEntryInstr, (s1)vdst);
2042 FINISH((s1)vdst);
2043OP_END
2044
2045/* File: c/OP_GOTO_16.c */
2046HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/)
2047 {
2048 s4 offset = (s2) FETCH(1); /* sign-extend next code unit */
2049
2050 if (offset < 0)
2051 ILOGV("|goto/16 -0x%04x", -offset);
2052 else
2053 ILOGV("|goto/16 +0x%04x", offset);
2054 ILOGV("> branch taken");
2055 if (offset < 0)
2056 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2057 FINISH(offset);
2058 }
2059OP_END
2060
2061/* File: c/OP_GOTO_32.c */
2062HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/)
2063 {
2064 s4 offset = FETCH(1); /* low-order 16 bits */
2065 offset |= ((s4) FETCH(2)) << 16; /* high-order 16 bits */
2066
2067 if (offset < 0)
2068 ILOGV("|goto/32 -0x%08x", -offset);
2069 else
2070 ILOGV("|goto/32 +0x%08x", offset);
2071 ILOGV("> branch taken");
2072 if (offset <= 0) /* allowed to branch to self */
2073 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2074 FINISH(offset);
2075 }
2076OP_END
2077
2078/* File: c/OP_PACKED_SWITCH.c */
2079HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/)
2080 {
2081 const u2* switchData;
2082 u4 testVal;
2083 s4 offset;
2084
2085 vsrc1 = INST_AA(inst);
2086 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
2087 ILOGV("|packed-switch v%d +0x%04x", vsrc1, vsrc2);
2088 switchData = pc + offset; // offset in 16-bit units
2089#ifndef NDEBUG
2090 if (switchData < curMethod->insns ||
2091 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
2092 {
2093 /* should have been caught in verifier */
2094 EXPORT_PC();
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08002095 dvmThrowInternalError("bad packed switch");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002096 GOTO_exceptionThrown();
2097 }
2098#endif
2099 testVal = GET_REGISTER(vsrc1);
2100
2101 offset = dvmInterpHandlePackedSwitch(switchData, testVal);
2102 ILOGV("> branch taken (0x%04x)\n", offset);
2103 if (offset <= 0) /* uncommon */
2104 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2105 FINISH(offset);
2106 }
2107OP_END
2108
2109/* File: c/OP_SPARSE_SWITCH.c */
2110HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/)
2111 {
2112 const u2* switchData;
2113 u4 testVal;
2114 s4 offset;
2115
2116 vsrc1 = INST_AA(inst);
2117 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
2118 ILOGV("|sparse-switch v%d +0x%04x", vsrc1, vsrc2);
2119 switchData = pc + offset; // offset in 16-bit units
2120#ifndef NDEBUG
2121 if (switchData < curMethod->insns ||
2122 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
2123 {
2124 /* should have been caught in verifier */
2125 EXPORT_PC();
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08002126 dvmThrowInternalError("bad sparse switch");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002127 GOTO_exceptionThrown();
2128 }
2129#endif
2130 testVal = GET_REGISTER(vsrc1);
2131
2132 offset = dvmInterpHandleSparseSwitch(switchData, testVal);
2133 ILOGV("> branch taken (0x%04x)\n", offset);
2134 if (offset <= 0) /* uncommon */
2135 PERIODIC_CHECKS(kInterpEntryInstr, offset);
2136 FINISH(offset);
2137 }
2138OP_END
2139
2140/* File: c/OP_CMPL_FLOAT.c */
2141HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1)
2142OP_END
2143
2144/* File: c/OP_CMPG_FLOAT.c */
2145HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1)
2146OP_END
2147
2148/* File: c/OP_CMPL_DOUBLE.c */
2149HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1)
2150OP_END
2151
2152/* File: c/OP_CMPG_DOUBLE.c */
2153HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1)
2154OP_END
2155
2156/* File: c/OP_CMP_LONG.c */
2157HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0)
2158OP_END
2159
2160/* File: c/OP_IF_EQ.c */
2161HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==)
2162OP_END
2163
2164/* File: c/OP_IF_NE.c */
2165HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=)
2166OP_END
2167
2168/* File: c/OP_IF_LT.c */
2169HANDLE_OP_IF_XX(OP_IF_LT, "lt", <)
2170OP_END
2171
2172/* File: c/OP_IF_GE.c */
2173HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=)
2174OP_END
2175
2176/* File: c/OP_IF_GT.c */
2177HANDLE_OP_IF_XX(OP_IF_GT, "gt", >)
2178OP_END
2179
2180/* File: c/OP_IF_LE.c */
2181HANDLE_OP_IF_XX(OP_IF_LE, "le", <=)
2182OP_END
2183
2184/* File: c/OP_IF_EQZ.c */
2185HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==)
2186OP_END
2187
2188/* File: c/OP_IF_NEZ.c */
2189HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=)
2190OP_END
2191
2192/* File: c/OP_IF_LTZ.c */
2193HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <)
2194OP_END
2195
2196/* File: c/OP_IF_GEZ.c */
2197HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=)
2198OP_END
2199
2200/* File: c/OP_IF_GTZ.c */
2201HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >)
2202OP_END
2203
2204/* File: c/OP_IF_LEZ.c */
2205HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=)
2206OP_END
2207
2208/* File: c/OP_UNUSED_3E.c */
2209HANDLE_OPCODE(OP_UNUSED_3E)
2210OP_END
2211
2212/* File: c/OP_UNUSED_3F.c */
2213HANDLE_OPCODE(OP_UNUSED_3F)
2214OP_END
2215
2216/* File: c/OP_UNUSED_40.c */
2217HANDLE_OPCODE(OP_UNUSED_40)
2218OP_END
2219
2220/* File: c/OP_UNUSED_41.c */
2221HANDLE_OPCODE(OP_UNUSED_41)
2222OP_END
2223
2224/* File: c/OP_UNUSED_42.c */
2225HANDLE_OPCODE(OP_UNUSED_42)
2226OP_END
2227
2228/* File: c/OP_UNUSED_43.c */
2229HANDLE_OPCODE(OP_UNUSED_43)
2230OP_END
2231
2232/* File: c/OP_AGET.c */
2233HANDLE_OP_AGET(OP_AGET, "", u4, )
2234OP_END
2235
2236/* File: c/OP_AGET_WIDE.c */
2237HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE)
2238OP_END
2239
2240/* File: c/OP_AGET_OBJECT.c */
2241HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, )
2242OP_END
2243
2244/* File: c/OP_AGET_BOOLEAN.c */
2245HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, )
2246OP_END
2247
2248/* File: c/OP_AGET_BYTE.c */
2249HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, )
2250OP_END
2251
2252/* File: c/OP_AGET_CHAR.c */
2253HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, )
2254OP_END
2255
2256/* File: c/OP_AGET_SHORT.c */
2257HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, )
2258OP_END
2259
2260/* File: c/OP_APUT.c */
2261HANDLE_OP_APUT(OP_APUT, "", u4, )
2262OP_END
2263
2264/* File: c/OP_APUT_WIDE.c */
2265HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE)
2266OP_END
2267
2268/* File: c/OP_APUT_OBJECT.c */
2269HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/)
2270 {
2271 ArrayObject* arrayObj;
2272 Object* obj;
2273 u2 arrayInfo;
2274 EXPORT_PC();
2275 vdst = INST_AA(inst); /* AA: source value */
2276 arrayInfo = FETCH(1);
2277 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */
2278 vsrc2 = arrayInfo >> 8; /* CC: index */
2279 ILOGV("|aput%s v%d,v%d,v%d", "-object", vdst, vsrc1, vsrc2);
2280 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
2281 if (!checkForNull((Object*) arrayObj))
2282 GOTO_exceptionThrown();
2283 if (GET_REGISTER(vsrc2) >= arrayObj->length) {
Dan Bornstein74501e62011-02-24 10:32:47 -08002284 dvmThrowArrayIndexOutOfBoundsException(
2285 GET_REGISTER(vsrc2), arrayObj->length);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002286 GOTO_exceptionThrown();
2287 }
2288 obj = (Object*) GET_REGISTER(vdst);
2289 if (obj != NULL) {
2290 if (!checkForNull(obj))
2291 GOTO_exceptionThrown();
2292 if (!dvmCanPutArrayElement(obj->clazz, arrayObj->obj.clazz)) {
2293 LOGV("Can't put a '%s'(%p) into array type='%s'(%p)\n",
2294 obj->clazz->descriptor, obj,
2295 arrayObj->obj.clazz->descriptor, arrayObj);
Elliott Hughes63644652010-11-19 16:35:05 -08002296 dvmThrowArrayStoreException(obj->clazz, arrayObj->obj.clazz);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002297 GOTO_exceptionThrown();
2298 }
2299 }
2300 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
Barry Hayes364f9d92010-06-11 16:12:47 -07002301 dvmSetObjectArrayElement(arrayObj,
2302 GET_REGISTER(vsrc2),
2303 (Object *)GET_REGISTER(vdst));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002304 }
2305 FINISH(2);
2306OP_END
2307
2308/* File: c/OP_APUT_BOOLEAN.c */
2309HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, )
2310OP_END
2311
2312/* File: c/OP_APUT_BYTE.c */
2313HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, )
2314OP_END
2315
2316/* File: c/OP_APUT_CHAR.c */
2317HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, )
2318OP_END
2319
2320/* File: c/OP_APUT_SHORT.c */
2321HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, )
2322OP_END
2323
2324/* File: c/OP_IGET.c */
2325HANDLE_IGET_X(OP_IGET, "", Int, )
2326OP_END
2327
2328/* File: c/OP_IGET_WIDE.c */
2329HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE)
2330OP_END
2331
2332/* File: c/OP_IGET_OBJECT.c */
2333HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT)
2334OP_END
2335
2336/* File: c/OP_IGET_BOOLEAN.c */
2337HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, )
2338OP_END
2339
2340/* File: c/OP_IGET_BYTE.c */
2341HANDLE_IGET_X(OP_IGET_BYTE, "", Int, )
2342OP_END
2343
2344/* File: c/OP_IGET_CHAR.c */
2345HANDLE_IGET_X(OP_IGET_CHAR, "", Int, )
2346OP_END
2347
2348/* File: c/OP_IGET_SHORT.c */
2349HANDLE_IGET_X(OP_IGET_SHORT, "", Int, )
2350OP_END
2351
2352/* File: c/OP_IPUT.c */
2353HANDLE_IPUT_X(OP_IPUT, "", Int, )
2354OP_END
2355
2356/* File: c/OP_IPUT_WIDE.c */
2357HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE)
2358OP_END
2359
2360/* File: c/OP_IPUT_OBJECT.c */
2361/*
2362 * The VM spec says we should verify that the reference being stored into
2363 * the field is assignment compatible. In practice, many popular VMs don't
2364 * do this because it slows down a very common operation. It's not so bad
2365 * for us, since "dexopt" quickens it whenever possible, but it's still an
2366 * issue.
2367 *
2368 * To make this spec-complaint, we'd need to add a ClassObject pointer to
2369 * the Field struct, resolve the field's type descriptor at link or class
2370 * init time, and then verify the type here.
2371 */
2372HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT)
2373OP_END
2374
2375/* File: c/OP_IPUT_BOOLEAN.c */
2376HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, )
2377OP_END
2378
2379/* File: c/OP_IPUT_BYTE.c */
2380HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, )
2381OP_END
2382
2383/* File: c/OP_IPUT_CHAR.c */
2384HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, )
2385OP_END
2386
2387/* File: c/OP_IPUT_SHORT.c */
2388HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, )
2389OP_END
2390
2391/* File: c/OP_SGET.c */
2392HANDLE_SGET_X(OP_SGET, "", Int, )
2393OP_END
2394
2395/* File: c/OP_SGET_WIDE.c */
2396HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE)
2397OP_END
2398
2399/* File: c/OP_SGET_OBJECT.c */
2400HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT)
2401OP_END
2402
2403/* File: c/OP_SGET_BOOLEAN.c */
2404HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, )
2405OP_END
2406
2407/* File: c/OP_SGET_BYTE.c */
2408HANDLE_SGET_X(OP_SGET_BYTE, "", Int, )
2409OP_END
2410
2411/* File: c/OP_SGET_CHAR.c */
2412HANDLE_SGET_X(OP_SGET_CHAR, "", Int, )
2413OP_END
2414
2415/* File: c/OP_SGET_SHORT.c */
2416HANDLE_SGET_X(OP_SGET_SHORT, "", Int, )
2417OP_END
2418
2419/* File: c/OP_SPUT.c */
2420HANDLE_SPUT_X(OP_SPUT, "", Int, )
2421OP_END
2422
2423/* File: c/OP_SPUT_WIDE.c */
2424HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE)
2425OP_END
2426
2427/* File: c/OP_SPUT_OBJECT.c */
2428HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT)
2429OP_END
2430
2431/* File: c/OP_SPUT_BOOLEAN.c */
2432HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, )
2433OP_END
2434
2435/* File: c/OP_SPUT_BYTE.c */
2436HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, )
2437OP_END
2438
2439/* File: c/OP_SPUT_CHAR.c */
2440HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, )
2441OP_END
2442
2443/* File: c/OP_SPUT_SHORT.c */
2444HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, )
2445OP_END
2446
2447/* File: c/OP_INVOKE_VIRTUAL.c */
2448HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002449 GOTO_invoke(invokeVirtual, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002450OP_END
2451
2452/* File: c/OP_INVOKE_SUPER.c */
2453HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002454 GOTO_invoke(invokeSuper, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002455OP_END
2456
2457/* File: c/OP_INVOKE_DIRECT.c */
2458HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002459 GOTO_invoke(invokeDirect, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002460OP_END
2461
2462/* File: c/OP_INVOKE_STATIC.c */
2463HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002464 GOTO_invoke(invokeStatic, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002465OP_END
2466
2467/* File: c/OP_INVOKE_INTERFACE.c */
2468HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002469 GOTO_invoke(invokeInterface, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002470OP_END
2471
2472/* File: c/OP_UNUSED_73.c */
2473HANDLE_OPCODE(OP_UNUSED_73)
2474OP_END
2475
2476/* File: c/OP_INVOKE_VIRTUAL_RANGE.c */
2477HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002478 GOTO_invoke(invokeVirtual, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002479OP_END
2480
2481/* File: c/OP_INVOKE_SUPER_RANGE.c */
2482HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002483 GOTO_invoke(invokeSuper, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002484OP_END
2485
2486/* File: c/OP_INVOKE_DIRECT_RANGE.c */
2487HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002488 GOTO_invoke(invokeDirect, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002489OP_END
2490
2491/* File: c/OP_INVOKE_STATIC_RANGE.c */
2492HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002493 GOTO_invoke(invokeStatic, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002494OP_END
2495
2496/* File: c/OP_INVOKE_INTERFACE_RANGE.c */
2497HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08002498 GOTO_invoke(invokeInterface, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002499OP_END
2500
2501/* File: c/OP_UNUSED_79.c */
2502HANDLE_OPCODE(OP_UNUSED_79)
2503OP_END
2504
2505/* File: c/OP_UNUSED_7A.c */
2506HANDLE_OPCODE(OP_UNUSED_7A)
2507OP_END
2508
2509/* File: c/OP_NEG_INT.c */
2510HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , )
2511OP_END
2512
2513/* File: c/OP_NOT_INT.c */
2514HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, )
2515OP_END
2516
2517/* File: c/OP_NEG_LONG.c */
2518HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE)
2519OP_END
2520
2521/* File: c/OP_NOT_LONG.c */
2522HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE)
2523OP_END
2524
2525/* File: c/OP_NEG_FLOAT.c */
2526HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT)
2527OP_END
2528
2529/* File: c/OP_NEG_DOUBLE.c */
2530HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE)
2531OP_END
2532
2533/* File: c/OP_INT_TO_LONG.c */
2534HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE)
2535OP_END
2536
2537/* File: c/OP_INT_TO_FLOAT.c */
2538HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT)
2539OP_END
2540
2541/* File: c/OP_INT_TO_DOUBLE.c */
2542HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE)
2543OP_END
2544
2545/* File: c/OP_LONG_TO_INT.c */
2546HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT)
2547OP_END
2548
2549/* File: c/OP_LONG_TO_FLOAT.c */
2550HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT)
2551OP_END
2552
2553/* File: c/OP_LONG_TO_DOUBLE.c */
2554HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE)
2555OP_END
2556
2557/* File: c/OP_FLOAT_TO_INT.c */
2558HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int",
2559 float, _FLOAT, s4, _INT)
2560OP_END
2561
2562/* File: c/OP_FLOAT_TO_LONG.c */
2563HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long",
2564 float, _FLOAT, s8, _WIDE)
2565OP_END
2566
2567/* File: c/OP_FLOAT_TO_DOUBLE.c */
2568HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE)
2569OP_END
2570
2571/* File: c/OP_DOUBLE_TO_INT.c */
2572HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int",
2573 double, _DOUBLE, s4, _INT)
2574OP_END
2575
2576/* File: c/OP_DOUBLE_TO_LONG.c */
2577HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long",
2578 double, _DOUBLE, s8, _WIDE)
2579OP_END
2580
2581/* File: c/OP_DOUBLE_TO_FLOAT.c */
2582HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT)
2583OP_END
2584
2585/* File: c/OP_INT_TO_BYTE.c */
2586HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1)
2587OP_END
2588
2589/* File: c/OP_INT_TO_CHAR.c */
2590HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2)
2591OP_END
2592
2593/* File: c/OP_INT_TO_SHORT.c */
2594HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */
2595OP_END
2596
2597/* File: c/OP_ADD_INT.c */
2598HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0)
2599OP_END
2600
2601/* File: c/OP_SUB_INT.c */
2602HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0)
2603OP_END
2604
2605/* File: c/OP_MUL_INT.c */
2606HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0)
2607OP_END
2608
2609/* File: c/OP_DIV_INT.c */
2610HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1)
2611OP_END
2612
2613/* File: c/OP_REM_INT.c */
2614HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2)
2615OP_END
2616
2617/* File: c/OP_AND_INT.c */
2618HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0)
2619OP_END
2620
2621/* File: c/OP_OR_INT.c */
2622HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0)
2623OP_END
2624
2625/* File: c/OP_XOR_INT.c */
2626HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0)
2627OP_END
2628
2629/* File: c/OP_SHL_INT.c */
2630HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<)
2631OP_END
2632
2633/* File: c/OP_SHR_INT.c */
2634HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>)
2635OP_END
2636
2637/* File: c/OP_USHR_INT.c */
2638HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>)
2639OP_END
2640
2641/* File: c/OP_ADD_LONG.c */
2642HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0)
2643OP_END
2644
2645/* File: c/OP_SUB_LONG.c */
2646HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0)
2647OP_END
2648
2649/* File: c/OP_MUL_LONG.c */
2650HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0)
2651OP_END
2652
2653/* File: c/OP_DIV_LONG.c */
2654HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1)
2655OP_END
2656
2657/* File: c/OP_REM_LONG.c */
2658HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2)
2659OP_END
2660
2661/* File: c/OP_AND_LONG.c */
2662HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0)
2663OP_END
2664
2665/* File: c/OP_OR_LONG.c */
2666HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0)
2667OP_END
2668
2669/* File: c/OP_XOR_LONG.c */
2670HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0)
2671OP_END
2672
2673/* File: c/OP_SHL_LONG.c */
2674HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<)
2675OP_END
2676
2677/* File: c/OP_SHR_LONG.c */
2678HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>)
2679OP_END
2680
2681/* File: c/OP_USHR_LONG.c */
2682HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>)
2683OP_END
2684
2685/* File: c/OP_ADD_FLOAT.c */
2686HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +)
2687OP_END
2688
2689/* File: c/OP_SUB_FLOAT.c */
2690HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -)
2691OP_END
2692
2693/* File: c/OP_MUL_FLOAT.c */
2694HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *)
2695OP_END
2696
2697/* File: c/OP_DIV_FLOAT.c */
2698HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /)
2699OP_END
2700
2701/* File: c/OP_REM_FLOAT.c */
2702HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/)
2703 {
2704 u2 srcRegs;
2705 vdst = INST_AA(inst);
2706 srcRegs = FETCH(1);
2707 vsrc1 = srcRegs & 0xff;
2708 vsrc2 = srcRegs >> 8;
2709 ILOGV("|%s-float v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2);
2710 SET_REGISTER_FLOAT(vdst,
2711 fmodf(GET_REGISTER_FLOAT(vsrc1), GET_REGISTER_FLOAT(vsrc2)));
2712 }
2713 FINISH(2);
2714OP_END
2715
2716/* File: c/OP_ADD_DOUBLE.c */
2717HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +)
2718OP_END
2719
2720/* File: c/OP_SUB_DOUBLE.c */
2721HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -)
2722OP_END
2723
2724/* File: c/OP_MUL_DOUBLE.c */
2725HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *)
2726OP_END
2727
2728/* File: c/OP_DIV_DOUBLE.c */
2729HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /)
2730OP_END
2731
2732/* File: c/OP_REM_DOUBLE.c */
2733HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/)
2734 {
2735 u2 srcRegs;
2736 vdst = INST_AA(inst);
2737 srcRegs = FETCH(1);
2738 vsrc1 = srcRegs & 0xff;
2739 vsrc2 = srcRegs >> 8;
2740 ILOGV("|%s-double v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2);
2741 SET_REGISTER_DOUBLE(vdst,
2742 fmod(GET_REGISTER_DOUBLE(vsrc1), GET_REGISTER_DOUBLE(vsrc2)));
2743 }
2744 FINISH(2);
2745OP_END
2746
2747/* File: c/OP_ADD_INT_2ADDR.c */
2748HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0)
2749OP_END
2750
2751/* File: c/OP_SUB_INT_2ADDR.c */
2752HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0)
2753OP_END
2754
2755/* File: c/OP_MUL_INT_2ADDR.c */
2756HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0)
2757OP_END
2758
2759/* File: c/OP_DIV_INT_2ADDR.c */
2760HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1)
2761OP_END
2762
2763/* File: c/OP_REM_INT_2ADDR.c */
2764HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2)
2765OP_END
2766
2767/* File: c/OP_AND_INT_2ADDR.c */
2768HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0)
2769OP_END
2770
2771/* File: c/OP_OR_INT_2ADDR.c */
2772HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0)
2773OP_END
2774
2775/* File: c/OP_XOR_INT_2ADDR.c */
2776HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0)
2777OP_END
2778
2779/* File: c/OP_SHL_INT_2ADDR.c */
2780HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<)
2781OP_END
2782
2783/* File: c/OP_SHR_INT_2ADDR.c */
2784HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>)
2785OP_END
2786
2787/* File: c/OP_USHR_INT_2ADDR.c */
2788HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>)
2789OP_END
2790
2791/* File: c/OP_ADD_LONG_2ADDR.c */
2792HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0)
2793OP_END
2794
2795/* File: c/OP_SUB_LONG_2ADDR.c */
2796HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0)
2797OP_END
2798
2799/* File: c/OP_MUL_LONG_2ADDR.c */
2800HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0)
2801OP_END
2802
2803/* File: c/OP_DIV_LONG_2ADDR.c */
2804HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1)
2805OP_END
2806
2807/* File: c/OP_REM_LONG_2ADDR.c */
2808HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2)
2809OP_END
2810
2811/* File: c/OP_AND_LONG_2ADDR.c */
2812HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0)
2813OP_END
2814
2815/* File: c/OP_OR_LONG_2ADDR.c */
2816HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0)
2817OP_END
2818
2819/* File: c/OP_XOR_LONG_2ADDR.c */
2820HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0)
2821OP_END
2822
2823/* File: c/OP_SHL_LONG_2ADDR.c */
2824HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<)
2825OP_END
2826
2827/* File: c/OP_SHR_LONG_2ADDR.c */
2828HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>)
2829OP_END
2830
2831/* File: c/OP_USHR_LONG_2ADDR.c */
2832HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>)
2833OP_END
2834
2835/* File: c/OP_ADD_FLOAT_2ADDR.c */
2836HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +)
2837OP_END
2838
2839/* File: c/OP_SUB_FLOAT_2ADDR.c */
2840HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -)
2841OP_END
2842
2843/* File: c/OP_MUL_FLOAT_2ADDR.c */
2844HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *)
2845OP_END
2846
2847/* File: c/OP_DIV_FLOAT_2ADDR.c */
2848HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /)
2849OP_END
2850
2851/* File: c/OP_REM_FLOAT_2ADDR.c */
2852HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/)
2853 vdst = INST_A(inst);
2854 vsrc1 = INST_B(inst);
2855 ILOGV("|%s-float-2addr v%d,v%d", "mod", vdst, vsrc1);
2856 SET_REGISTER_FLOAT(vdst,
2857 fmodf(GET_REGISTER_FLOAT(vdst), GET_REGISTER_FLOAT(vsrc1)));
2858 FINISH(1);
2859OP_END
2860
2861/* File: c/OP_ADD_DOUBLE_2ADDR.c */
2862HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +)
2863OP_END
2864
2865/* File: c/OP_SUB_DOUBLE_2ADDR.c */
2866HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -)
2867OP_END
2868
2869/* File: c/OP_MUL_DOUBLE_2ADDR.c */
2870HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *)
2871OP_END
2872
2873/* File: c/OP_DIV_DOUBLE_2ADDR.c */
2874HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /)
2875OP_END
2876
2877/* File: c/OP_REM_DOUBLE_2ADDR.c */
2878HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/)
2879 vdst = INST_A(inst);
2880 vsrc1 = INST_B(inst);
2881 ILOGV("|%s-double-2addr v%d,v%d", "mod", vdst, vsrc1);
2882 SET_REGISTER_DOUBLE(vdst,
2883 fmod(GET_REGISTER_DOUBLE(vdst), GET_REGISTER_DOUBLE(vsrc1)));
2884 FINISH(1);
2885OP_END
2886
2887/* File: c/OP_ADD_INT_LIT16.c */
2888HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0)
2889OP_END
2890
2891/* File: c/OP_RSUB_INT.c */
2892HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/)
2893 {
2894 vdst = INST_A(inst);
2895 vsrc1 = INST_B(inst);
2896 vsrc2 = FETCH(1);
2897 ILOGV("|rsub-int v%d,v%d,#+0x%04x", vdst, vsrc1, vsrc2);
2898 SET_REGISTER(vdst, (s2) vsrc2 - (s4) GET_REGISTER(vsrc1));
2899 }
2900 FINISH(2);
2901OP_END
2902
2903/* File: c/OP_MUL_INT_LIT16.c */
2904HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0)
2905OP_END
2906
2907/* File: c/OP_DIV_INT_LIT16.c */
2908HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1)
2909OP_END
2910
2911/* File: c/OP_REM_INT_LIT16.c */
2912HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2)
2913OP_END
2914
2915/* File: c/OP_AND_INT_LIT16.c */
2916HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0)
2917OP_END
2918
2919/* File: c/OP_OR_INT_LIT16.c */
2920HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0)
2921OP_END
2922
2923/* File: c/OP_XOR_INT_LIT16.c */
2924HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0)
2925OP_END
2926
2927/* File: c/OP_ADD_INT_LIT8.c */
2928HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0)
2929OP_END
2930
2931/* File: c/OP_RSUB_INT_LIT8.c */
2932HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/)
2933 {
2934 u2 litInfo;
2935 vdst = INST_AA(inst);
2936 litInfo = FETCH(1);
2937 vsrc1 = litInfo & 0xff;
2938 vsrc2 = litInfo >> 8;
2939 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", "rsub", vdst, vsrc1, vsrc2);
2940 SET_REGISTER(vdst, (s1) vsrc2 - (s4) GET_REGISTER(vsrc1));
2941 }
2942 FINISH(2);
2943OP_END
2944
2945/* File: c/OP_MUL_INT_LIT8.c */
2946HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0)
2947OP_END
2948
2949/* File: c/OP_DIV_INT_LIT8.c */
2950HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1)
2951OP_END
2952
2953/* File: c/OP_REM_INT_LIT8.c */
2954HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2)
2955OP_END
2956
2957/* File: c/OP_AND_INT_LIT8.c */
2958HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0)
2959OP_END
2960
2961/* File: c/OP_OR_INT_LIT8.c */
2962HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0)
2963OP_END
2964
2965/* File: c/OP_XOR_INT_LIT8.c */
2966HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0)
2967OP_END
2968
2969/* File: c/OP_SHL_INT_LIT8.c */
2970HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<)
2971OP_END
2972
2973/* File: c/OP_SHR_INT_LIT8.c */
2974HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>)
2975OP_END
2976
2977/* File: c/OP_USHR_INT_LIT8.c */
2978HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>)
2979OP_END
2980
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002981/* File: c/OP_IGET_VOLATILE.c */
2982HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002983OP_END
2984
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002985/* File: c/OP_IPUT_VOLATILE.c */
2986HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002987OP_END
2988
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002989/* File: c/OP_SGET_VOLATILE.c */
2990HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002991OP_END
2992
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002993/* File: c/OP_SPUT_VOLATILE.c */
2994HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, )
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002995OP_END
2996
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07002997/* File: c/OP_IGET_OBJECT_VOLATILE.c */
2998HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002999OP_END
3000
Andy McFadden53878242010-03-05 07:24:27 -08003001/* File: c/OP_IGET_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003002HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003003OP_END
3004
Andy McFadden53878242010-03-05 07:24:27 -08003005/* File: c/OP_IPUT_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003006HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003007OP_END
3008
Andy McFadden53878242010-03-05 07:24:27 -08003009/* File: c/OP_SGET_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003010HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003011OP_END
3012
Andy McFadden53878242010-03-05 07:24:27 -08003013/* File: c/OP_SPUT_WIDE_VOLATILE.c */
Andy McFadden861b3382010-03-05 15:58:31 -08003014HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003015OP_END
3016
Andy McFadden96516932009-10-28 17:39:02 -07003017/* File: c/OP_BREAKPOINT.c */
3018HANDLE_OPCODE(OP_BREAKPOINT)
Andy McFadden0d615c32010-08-18 12:19:51 -07003019#if (INTERP_TYPE == INTERP_DBG)
Andy McFadden96516932009-10-28 17:39:02 -07003020 {
3021 /*
3022 * Restart this instruction with the original opcode. We do
3023 * this by simply jumping to the handler.
3024 *
3025 * It's probably not necessary to update "inst", but we do it
3026 * for the sake of anything that needs to do disambiguation in a
3027 * common handler with INST_INST.
3028 *
3029 * The breakpoint itself is handled over in updateDebugger(),
3030 * because we need to detect other events (method entry, single
3031 * step) and report them in the same event packet, and we're not
3032 * yet handling those through breakpoint instructions. By the
3033 * time we get here, the breakpoint has already been handled and
3034 * the thread resumed.
3035 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -08003036 u1 originalOpcode = dvmGetOriginalOpcode(pc);
3037 LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpcode, inst,
3038 INST_REPLACE_OP(inst, originalOpcode));
3039 inst = INST_REPLACE_OP(inst, originalOpcode);
3040 FINISH_BKPT(originalOpcode);
Andy McFadden96516932009-10-28 17:39:02 -07003041 }
3042#else
3043 LOGE("Breakpoint hit in non-debug interpreter\n");
3044 dvmAbort();
3045#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003046OP_END
3047
Andy McFadden3a1aedb2009-05-07 13:30:23 -07003048/* File: c/OP_THROW_VERIFICATION_ERROR.c */
3049HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
Andy McFaddenb51ea112009-05-08 16:50:17 -07003050 EXPORT_PC();
Andy McFadden3a1aedb2009-05-07 13:30:23 -07003051 vsrc1 = INST_AA(inst);
3052 ref = FETCH(1); /* class/field/method ref */
Andy McFaddenb51ea112009-05-08 16:50:17 -07003053 dvmThrowVerificationError(curMethod, vsrc1, ref);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07003054 GOTO_exceptionThrown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003055OP_END
3056
3057/* File: c/OP_EXECUTE_INLINE.c */
3058HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/)
3059 {
3060 /*
3061 * This has the same form as other method calls, but we ignore
3062 * the 5th argument (vA). This is chiefly because the first four
3063 * arguments to a function on ARM are in registers.
3064 *
3065 * We only set the arguments that are actually used, leaving
3066 * the rest uninitialized. We're assuming that, if the method
3067 * needs them, they'll be specified in the call.
3068 *
Carl Shapiro7bbb9ce2009-12-21 18:34:11 -08003069 * However, this annoys gcc when optimizations are enabled,
3070 * causing a "may be used uninitialized" warning. Quieting
3071 * the warnings incurs a slight penalty (5%: 373ns vs. 393ns
3072 * on empty method). Note that valgrind is perfectly happy
3073 * either way as the uninitialiezd values are never actually
3074 * used.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003075 */
3076 u4 arg0, arg1, arg2, arg3;
Carl Shapiro7bbb9ce2009-12-21 18:34:11 -08003077 arg0 = arg1 = arg2 = arg3 = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003078
3079 EXPORT_PC();
3080
3081 vsrc1 = INST_B(inst); /* #of args */
3082 ref = FETCH(1); /* inline call "ref" */
3083 vdst = FETCH(2); /* 0-4 register indices */
3084 ILOGV("|execute-inline args=%d @%d {regs=0x%04x}",
3085 vsrc1, ref, vdst);
3086
3087 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
3088 assert(vsrc1 <= 4);
3089
3090 switch (vsrc1) {
3091 case 4:
3092 arg3 = GET_REGISTER(vdst >> 12);
3093 /* fall through */
3094 case 3:
3095 arg2 = GET_REGISTER((vdst & 0x0f00) >> 8);
3096 /* fall through */
3097 case 2:
3098 arg1 = GET_REGISTER((vdst & 0x00f0) >> 4);
3099 /* fall through */
3100 case 1:
3101 arg0 = GET_REGISTER(vdst & 0x0f);
3102 /* fall through */
3103 default: // case 0
3104 ;
3105 }
3106
3107#if INTERP_TYPE == INTERP_DBG
3108 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
3109 GOTO_exceptionThrown();
3110#else
3111 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
3112 GOTO_exceptionThrown();
3113#endif
3114 }
3115 FINISH(3);
3116OP_END
3117
Andy McFaddenb0a05412009-11-19 10:23:41 -08003118/* File: c/OP_EXECUTE_INLINE_RANGE.c */
3119HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
3120 {
3121 u4 arg0, arg1, arg2, arg3;
3122 arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */
3123
3124 EXPORT_PC();
3125
3126 vsrc1 = INST_AA(inst); /* #of args */
3127 ref = FETCH(1); /* inline call "ref" */
3128 vdst = FETCH(2); /* range base */
3129 ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}",
3130 vsrc1, ref, vdst, vdst+vsrc1-1);
3131
3132 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
3133 assert(vsrc1 <= 4);
3134
3135 switch (vsrc1) {
3136 case 4:
3137 arg3 = GET_REGISTER(vdst+3);
3138 /* fall through */
3139 case 3:
3140 arg2 = GET_REGISTER(vdst+2);
3141 /* fall through */
3142 case 2:
3143 arg1 = GET_REGISTER(vdst+1);
3144 /* fall through */
3145 case 1:
3146 arg0 = GET_REGISTER(vdst+0);
3147 /* fall through */
3148 default: // case 0
3149 ;
3150 }
3151
3152#if INTERP_TYPE == INTERP_DBG
3153 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
3154 GOTO_exceptionThrown();
3155#else
3156 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
3157 GOTO_exceptionThrown();
3158#endif
3159 }
3160 FINISH(3);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003161OP_END
3162
Andy McFadden0346e9d2011-03-01 15:47:46 -08003163/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.c */
3164HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003165 {
3166 Object* obj;
3167
Andy McFadden0346e9d2011-03-01 15:47:46 -08003168 vsrc1 = FETCH(2); /* reg number of "this" pointer */
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003169 obj = GET_REGISTER_AS_OBJECT(vsrc1);
3170
3171 if (!checkForNullExportPC(obj, fp, pc))
3172 GOTO_exceptionThrown();
3173
3174 /*
3175 * The object should be marked "finalizable" when Object.<init>
3176 * completes normally. We're going to assume it does complete
3177 * (by virtue of being nothing but a return-void) and set it now.
3178 */
3179 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) {
3180 dvmSetFinalizable(obj);
3181 }
3182
3183#if INTERP_TYPE == INTERP_DBG
3184 if (!DEBUGGER_ACTIVE) {
3185 /* skip method invocation */
3186 FINISH(3);
3187 } else {
Andy McFadden0346e9d2011-03-01 15:47:46 -08003188 /* behave like OP_INVOKE_DIRECT_RANGE */
3189 GOTO_invoke(invokeDirect, true, false);
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003190 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003191#else
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003192 /* debugger can't be attached, skip method invocation */
3193 FINISH(3);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003194#endif
Andy McFadden6af2ddd2011-02-16 16:50:40 -08003195 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003196OP_END
3197
Andy McFadden291758c2010-09-10 08:04:52 -07003198/* File: c/OP_RETURN_VOID_BARRIER.c */
3199HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
3200 ILOGV("|return-void");
3201#ifndef NDEBUG
3202 retval.j = 0xababababULL; /* placate valgrind */
3203#endif
Andy McFadden1df319e2010-09-15 13:40:01 -07003204 ANDROID_MEMBAR_STORE();
Andy McFadden291758c2010-09-10 08:04:52 -07003205 GOTO_returnFromMethod();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003206OP_END
3207
3208/* File: c/OP_IGET_QUICK.c */
3209HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, )
3210OP_END
3211
3212/* File: c/OP_IGET_WIDE_QUICK.c */
3213HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE)
3214OP_END
3215
3216/* File: c/OP_IGET_OBJECT_QUICK.c */
3217HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
3218OP_END
3219
3220/* File: c/OP_IPUT_QUICK.c */
3221HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, )
3222OP_END
3223
3224/* File: c/OP_IPUT_WIDE_QUICK.c */
3225HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE)
3226OP_END
3227
3228/* File: c/OP_IPUT_OBJECT_QUICK.c */
3229HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
3230OP_END
3231
3232/* File: c/OP_INVOKE_VIRTUAL_QUICK.c */
3233HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003234 GOTO_invoke(invokeVirtualQuick, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003235OP_END
3236
3237/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.c */
3238HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003239 GOTO_invoke(invokeVirtualQuick, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003240OP_END
3241
3242/* File: c/OP_INVOKE_SUPER_QUICK.c */
3243HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003244 GOTO_invoke(invokeSuperQuick, false, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003245OP_END
3246
3247/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.c */
3248HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
jeffhao71eee1f2011-01-04 14:18:54 -08003249 GOTO_invoke(invokeSuperQuick, true, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003250OP_END
3251
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07003252/* File: c/OP_IPUT_OBJECT_VOLATILE.c */
3253HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003254OP_END
3255
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07003256/* File: c/OP_SGET_OBJECT_VOLATILE.c */
3257HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003258OP_END
3259
Andy McFaddenc35a2ef2010-06-17 12:36:00 -07003260/* File: c/OP_SPUT_OBJECT_VOLATILE.c */
3261HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003262OP_END
3263
Dan Bornstein90f15432010-12-02 16:46:25 -08003264/* File: c/OP_DISPATCH_FF.c */
3265HANDLE_OPCODE(OP_DISPATCH_FF)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003266 /*
jeffhao71eee1f2011-01-04 14:18:54 -08003267 * Indicates extended opcode. Use next 8 bits to choose where to branch.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003268 */
jeffhao71eee1f2011-01-04 14:18:54 -08003269 DISPATCH_EXTENDED(INST_AA(inst));
3270OP_END
3271
3272/* File: c/OP_CONST_CLASS_JUMBO.c */
3273HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/)
3274 {
3275 ClassObject* clazz;
3276
3277 ref = FETCH(1) | (u4)FETCH(2) << 16;
3278 vdst = FETCH(3);
3279 ILOGV("|const-class/jumbo v%d class@0x%08x", vdst, ref);
3280 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3281 if (clazz == NULL) {
3282 EXPORT_PC();
3283 clazz = dvmResolveClass(curMethod->clazz, ref, true);
3284 if (clazz == NULL)
3285 GOTO_exceptionThrown();
3286 }
3287 SET_REGISTER(vdst, (u4) clazz);
3288 }
3289 FINISH(4);
3290OP_END
3291
3292/* File: c/OP_CHECK_CAST_JUMBO.c */
3293HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/)
3294 {
3295 ClassObject* clazz;
3296 Object* obj;
3297
3298 EXPORT_PC();
3299
3300 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */
3301 vsrc1 = FETCH(3);
3302 ILOGV("|check-cast/jumbo v%d,class@0x%08x", vsrc1, ref);
3303
3304 obj = (Object*)GET_REGISTER(vsrc1);
3305 if (obj != NULL) {
3306#if defined(WITH_EXTRA_OBJECT_VALIDATION)
3307 if (!checkForNull(obj))
3308 GOTO_exceptionThrown();
3309#endif
3310 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3311 if (clazz == NULL) {
3312 clazz = dvmResolveClass(curMethod->clazz, ref, false);
3313 if (clazz == NULL)
3314 GOTO_exceptionThrown();
3315 }
3316 if (!dvmInstanceof(obj->clazz, clazz)) {
3317 dvmThrowClassCastException(obj->clazz, clazz);
3318 GOTO_exceptionThrown();
3319 }
3320 }
3321 }
3322 FINISH(4);
3323OP_END
3324
3325/* File: c/OP_INSTANCE_OF_JUMBO.c */
3326HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
3327 {
3328 ClassObject* clazz;
3329 Object* obj;
3330
3331 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */
3332 vdst = FETCH(3);
3333 vsrc1 = FETCH(4); /* object to check */
3334 ILOGV("|instance-of/jumbo v%d,v%d,class@0x%08x", vdst, vsrc1, ref);
3335
3336 obj = (Object*)GET_REGISTER(vsrc1);
3337 if (obj == NULL) {
3338 SET_REGISTER(vdst, 0);
3339 } else {
3340#if defined(WITH_EXTRA_OBJECT_VALIDATION)
3341 if (!checkForNullExportPC(obj, fp, pc))
3342 GOTO_exceptionThrown();
3343#endif
3344 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3345 if (clazz == NULL) {
3346 EXPORT_PC();
3347 clazz = dvmResolveClass(curMethod->clazz, ref, true);
3348 if (clazz == NULL)
3349 GOTO_exceptionThrown();
3350 }
3351 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz));
3352 }
3353 }
3354 FINISH(5);
3355OP_END
3356
3357/* File: c/OP_NEW_INSTANCE_JUMBO.c */
3358HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/)
3359 {
3360 ClassObject* clazz;
3361 Object* newObj;
3362
3363 EXPORT_PC();
3364
3365 ref = FETCH(1) | (u4)FETCH(2) << 16;
3366 vdst = FETCH(3);
3367 ILOGV("|new-instance/jumbo v%d,class@0x%08x", vdst, ref);
3368 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3369 if (clazz == NULL) {
3370 clazz = dvmResolveClass(curMethod->clazz, ref, false);
3371 if (clazz == NULL)
3372 GOTO_exceptionThrown();
3373 }
3374
3375 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))
3376 GOTO_exceptionThrown();
3377
3378 /*
3379 * The JIT needs dvmDexGetResolvedClass() to return non-null.
3380 * Since we use the portable interpreter to build the trace, this extra
3381 * check is not needed for mterp.
3382 */
3383 if (!dvmDexGetResolvedClass(methodClassDex, ref)) {
Bill Buzbee1b3da592011-02-03 07:38:22 -08003384 /* Class initialization is still ongoing - end the trace */
3385 END_JIT_TSELECT();
jeffhao71eee1f2011-01-04 14:18:54 -08003386 }
3387
3388 /*
3389 * Verifier now tests for interface/abstract class.
3390 */
3391 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
Dan Bornstein0b8b2932011-03-04 11:53:40 -08003392 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
jeffhao71eee1f2011-01-04 14:18:54 -08003393 // clazz->descriptor);
3394 // GOTO_exceptionThrown();
3395 //}
3396 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
3397 if (newObj == NULL)
3398 GOTO_exceptionThrown();
3399 SET_REGISTER(vdst, (u4) newObj);
3400 }
3401 FINISH(4);
3402OP_END
3403
3404/* File: c/OP_NEW_ARRAY_JUMBO.c */
3405HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
3406 {
3407 ClassObject* arrayClass;
3408 ArrayObject* newArray;
3409 s4 length;
3410
3411 EXPORT_PC();
3412
3413 ref = FETCH(1) | (u4)FETCH(2) << 16;
3414 vdst = FETCH(3);
3415 vsrc1 = FETCH(4); /* length reg */
3416 ILOGV("|new-array/jumbo v%d,v%d,class@0x%08x (%d elements)",
3417 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1));
3418 length = (s4) GET_REGISTER(vsrc1);
3419 if (length < 0) {
Dan Bornstein2c8e25b2011-02-25 15:49:29 -08003420 dvmThrowNegativeArraySizeException(length);
jeffhao71eee1f2011-01-04 14:18:54 -08003421 GOTO_exceptionThrown();
3422 }
3423 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
3424 if (arrayClass == NULL) {
3425 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
3426 if (arrayClass == NULL)
3427 GOTO_exceptionThrown();
3428 }
3429 /* verifier guarantees this is an array class */
3430 assert(dvmIsArrayClass(arrayClass));
3431 assert(dvmIsClassInitialized(arrayClass));
3432
3433 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK);
3434 if (newArray == NULL)
3435 GOTO_exceptionThrown();
3436 SET_REGISTER(vdst, (u4) newArray);
3437 }
3438 FINISH(5);
3439OP_END
3440
3441/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.c */
3442HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/)
3443 GOTO_invoke(filledNewArray, true, true);
3444OP_END
3445
3446/* File: c/OP_IGET_JUMBO.c */
3447HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, )
3448OP_END
3449
3450/* File: c/OP_IGET_WIDE_JUMBO.c */
3451HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE)
3452OP_END
3453
3454/* File: c/OP_IGET_OBJECT_JUMBO.c */
3455HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3456OP_END
3457
3458/* File: c/OP_IGET_BOOLEAN_JUMBO.c */
3459HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, )
3460OP_END
3461
3462/* File: c/OP_IGET_BYTE_JUMBO.c */
3463HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, )
3464OP_END
3465
3466/* File: c/OP_IGET_CHAR_JUMBO.c */
3467HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, )
3468OP_END
3469
3470/* File: c/OP_IGET_SHORT_JUMBO.c */
3471HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, )
3472OP_END
3473
3474/* File: c/OP_IPUT_JUMBO.c */
3475HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, )
3476OP_END
3477
3478/* File: c/OP_IPUT_WIDE_JUMBO.c */
3479HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
3480OP_END
3481
3482/* File: c/OP_IPUT_OBJECT_JUMBO.c */
3483/*
3484 * The VM spec says we should verify that the reference being stored into
3485 * the field is assignment compatible. In practice, many popular VMs don't
3486 * do this because it slows down a very common operation. It's not so bad
3487 * for us, since "dexopt" quickens it whenever possible, but it's still an
3488 * issue.
3489 *
3490 * To make this spec-complaint, we'd need to add a ClassObject pointer to
3491 * the Field struct, resolve the field's type descriptor at link or class
3492 * init time, and then verify the type here.
3493 */
3494HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3495OP_END
3496
3497/* File: c/OP_IPUT_BOOLEAN_JUMBO.c */
3498HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, )
3499OP_END
3500
3501/* File: c/OP_IPUT_BYTE_JUMBO.c */
3502HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, )
3503OP_END
3504
3505/* File: c/OP_IPUT_CHAR_JUMBO.c */
3506HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, )
3507OP_END
3508
3509/* File: c/OP_IPUT_SHORT_JUMBO.c */
3510HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, )
3511OP_END
3512
3513/* File: c/OP_SGET_JUMBO.c */
3514HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, )
3515OP_END
3516
3517/* File: c/OP_SGET_WIDE_JUMBO.c */
3518HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE)
3519OP_END
3520
3521/* File: c/OP_SGET_OBJECT_JUMBO.c */
3522HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3523OP_END
3524
3525/* File: c/OP_SGET_BOOLEAN_JUMBO.c */
3526HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, )
3527OP_END
3528
3529/* File: c/OP_SGET_BYTE_JUMBO.c */
3530HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, )
3531OP_END
3532
3533/* File: c/OP_SGET_CHAR_JUMBO.c */
3534HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, )
3535OP_END
3536
3537/* File: c/OP_SGET_SHORT_JUMBO.c */
3538HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, )
3539OP_END
3540
3541/* File: c/OP_SPUT_JUMBO.c */
3542HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, )
3543OP_END
3544
3545/* File: c/OP_SPUT_WIDE_JUMBO.c */
3546HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
3547OP_END
3548
3549/* File: c/OP_SPUT_OBJECT_JUMBO.c */
3550HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3551OP_END
3552
3553/* File: c/OP_SPUT_BOOLEAN_JUMBO.c */
3554HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, )
3555OP_END
3556
3557/* File: c/OP_SPUT_BYTE_JUMBO.c */
3558HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, )
3559OP_END
3560
3561/* File: c/OP_SPUT_CHAR_JUMBO.c */
3562HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, )
3563OP_END
3564
3565/* File: c/OP_SPUT_SHORT_JUMBO.c */
3566HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, )
3567OP_END
3568
3569/* File: c/OP_INVOKE_VIRTUAL_JUMBO.c */
3570HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3571 GOTO_invoke(invokeVirtual, true, true);
3572OP_END
3573
3574/* File: c/OP_INVOKE_SUPER_JUMBO.c */
3575HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3576 GOTO_invoke(invokeSuper, true, true);
3577OP_END
3578
3579/* File: c/OP_INVOKE_DIRECT_JUMBO.c */
3580HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3581 GOTO_invoke(invokeDirect, true, true);
3582OP_END
3583
3584/* File: c/OP_INVOKE_STATIC_JUMBO.c */
3585HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3586 GOTO_invoke(invokeStatic, true, true);
3587OP_END
3588
3589/* File: c/OP_INVOKE_INTERFACE_JUMBO.c */
3590HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3591 GOTO_invoke(invokeInterface, true, true);
3592OP_END
3593
3594/* File: c/OP_UNUSED_27FF.c */
3595HANDLE_OPCODE(OP_UNUSED_27FF)
3596OP_END
3597
3598/* File: c/OP_UNUSED_28FF.c */
3599HANDLE_OPCODE(OP_UNUSED_28FF)
3600OP_END
3601
3602/* File: c/OP_UNUSED_29FF.c */
3603HANDLE_OPCODE(OP_UNUSED_29FF)
3604OP_END
3605
3606/* File: c/OP_UNUSED_2AFF.c */
3607HANDLE_OPCODE(OP_UNUSED_2AFF)
3608OP_END
3609
3610/* File: c/OP_UNUSED_2BFF.c */
3611HANDLE_OPCODE(OP_UNUSED_2BFF)
3612OP_END
3613
3614/* File: c/OP_UNUSED_2CFF.c */
3615HANDLE_OPCODE(OP_UNUSED_2CFF)
3616OP_END
3617
3618/* File: c/OP_UNUSED_2DFF.c */
3619HANDLE_OPCODE(OP_UNUSED_2DFF)
3620OP_END
3621
3622/* File: c/OP_UNUSED_2EFF.c */
3623HANDLE_OPCODE(OP_UNUSED_2EFF)
3624OP_END
3625
3626/* File: c/OP_UNUSED_2FFF.c */
3627HANDLE_OPCODE(OP_UNUSED_2FFF)
3628OP_END
3629
3630/* File: c/OP_UNUSED_30FF.c */
3631HANDLE_OPCODE(OP_UNUSED_30FF)
3632OP_END
3633
3634/* File: c/OP_UNUSED_31FF.c */
3635HANDLE_OPCODE(OP_UNUSED_31FF)
3636OP_END
3637
3638/* File: c/OP_UNUSED_32FF.c */
3639HANDLE_OPCODE(OP_UNUSED_32FF)
3640OP_END
3641
3642/* File: c/OP_UNUSED_33FF.c */
3643HANDLE_OPCODE(OP_UNUSED_33FF)
3644OP_END
3645
3646/* File: c/OP_UNUSED_34FF.c */
3647HANDLE_OPCODE(OP_UNUSED_34FF)
3648OP_END
3649
3650/* File: c/OP_UNUSED_35FF.c */
3651HANDLE_OPCODE(OP_UNUSED_35FF)
3652OP_END
3653
3654/* File: c/OP_UNUSED_36FF.c */
3655HANDLE_OPCODE(OP_UNUSED_36FF)
3656OP_END
3657
3658/* File: c/OP_UNUSED_37FF.c */
3659HANDLE_OPCODE(OP_UNUSED_37FF)
3660OP_END
3661
3662/* File: c/OP_UNUSED_38FF.c */
3663HANDLE_OPCODE(OP_UNUSED_38FF)
3664OP_END
3665
3666/* File: c/OP_UNUSED_39FF.c */
3667HANDLE_OPCODE(OP_UNUSED_39FF)
3668OP_END
3669
3670/* File: c/OP_UNUSED_3AFF.c */
3671HANDLE_OPCODE(OP_UNUSED_3AFF)
3672OP_END
3673
3674/* File: c/OP_UNUSED_3BFF.c */
3675HANDLE_OPCODE(OP_UNUSED_3BFF)
3676OP_END
3677
3678/* File: c/OP_UNUSED_3CFF.c */
3679HANDLE_OPCODE(OP_UNUSED_3CFF)
3680OP_END
3681
3682/* File: c/OP_UNUSED_3DFF.c */
3683HANDLE_OPCODE(OP_UNUSED_3DFF)
3684OP_END
3685
3686/* File: c/OP_UNUSED_3EFF.c */
3687HANDLE_OPCODE(OP_UNUSED_3EFF)
3688OP_END
3689
3690/* File: c/OP_UNUSED_3FFF.c */
3691HANDLE_OPCODE(OP_UNUSED_3FFF)
3692OP_END
3693
3694/* File: c/OP_UNUSED_40FF.c */
3695HANDLE_OPCODE(OP_UNUSED_40FF)
3696OP_END
3697
3698/* File: c/OP_UNUSED_41FF.c */
3699HANDLE_OPCODE(OP_UNUSED_41FF)
3700OP_END
3701
3702/* File: c/OP_UNUSED_42FF.c */
3703HANDLE_OPCODE(OP_UNUSED_42FF)
3704OP_END
3705
3706/* File: c/OP_UNUSED_43FF.c */
3707HANDLE_OPCODE(OP_UNUSED_43FF)
3708OP_END
3709
3710/* File: c/OP_UNUSED_44FF.c */
3711HANDLE_OPCODE(OP_UNUSED_44FF)
3712OP_END
3713
3714/* File: c/OP_UNUSED_45FF.c */
3715HANDLE_OPCODE(OP_UNUSED_45FF)
3716OP_END
3717
3718/* File: c/OP_UNUSED_46FF.c */
3719HANDLE_OPCODE(OP_UNUSED_46FF)
3720OP_END
3721
3722/* File: c/OP_UNUSED_47FF.c */
3723HANDLE_OPCODE(OP_UNUSED_47FF)
3724OP_END
3725
3726/* File: c/OP_UNUSED_48FF.c */
3727HANDLE_OPCODE(OP_UNUSED_48FF)
3728OP_END
3729
3730/* File: c/OP_UNUSED_49FF.c */
3731HANDLE_OPCODE(OP_UNUSED_49FF)
3732OP_END
3733
3734/* File: c/OP_UNUSED_4AFF.c */
3735HANDLE_OPCODE(OP_UNUSED_4AFF)
3736OP_END
3737
3738/* File: c/OP_UNUSED_4BFF.c */
3739HANDLE_OPCODE(OP_UNUSED_4BFF)
3740OP_END
3741
3742/* File: c/OP_UNUSED_4CFF.c */
3743HANDLE_OPCODE(OP_UNUSED_4CFF)
3744OP_END
3745
3746/* File: c/OP_UNUSED_4DFF.c */
3747HANDLE_OPCODE(OP_UNUSED_4DFF)
3748OP_END
3749
3750/* File: c/OP_UNUSED_4EFF.c */
3751HANDLE_OPCODE(OP_UNUSED_4EFF)
3752OP_END
3753
3754/* File: c/OP_UNUSED_4FFF.c */
3755HANDLE_OPCODE(OP_UNUSED_4FFF)
3756OP_END
3757
3758/* File: c/OP_UNUSED_50FF.c */
3759HANDLE_OPCODE(OP_UNUSED_50FF)
3760OP_END
3761
3762/* File: c/OP_UNUSED_51FF.c */
3763HANDLE_OPCODE(OP_UNUSED_51FF)
3764OP_END
3765
3766/* File: c/OP_UNUSED_52FF.c */
3767HANDLE_OPCODE(OP_UNUSED_52FF)
3768OP_END
3769
3770/* File: c/OP_UNUSED_53FF.c */
3771HANDLE_OPCODE(OP_UNUSED_53FF)
3772OP_END
3773
3774/* File: c/OP_UNUSED_54FF.c */
3775HANDLE_OPCODE(OP_UNUSED_54FF)
3776OP_END
3777
3778/* File: c/OP_UNUSED_55FF.c */
3779HANDLE_OPCODE(OP_UNUSED_55FF)
3780OP_END
3781
3782/* File: c/OP_UNUSED_56FF.c */
3783HANDLE_OPCODE(OP_UNUSED_56FF)
3784OP_END
3785
3786/* File: c/OP_UNUSED_57FF.c */
3787HANDLE_OPCODE(OP_UNUSED_57FF)
3788OP_END
3789
3790/* File: c/OP_UNUSED_58FF.c */
3791HANDLE_OPCODE(OP_UNUSED_58FF)
3792OP_END
3793
3794/* File: c/OP_UNUSED_59FF.c */
3795HANDLE_OPCODE(OP_UNUSED_59FF)
3796OP_END
3797
3798/* File: c/OP_UNUSED_5AFF.c */
3799HANDLE_OPCODE(OP_UNUSED_5AFF)
3800OP_END
3801
3802/* File: c/OP_UNUSED_5BFF.c */
3803HANDLE_OPCODE(OP_UNUSED_5BFF)
3804OP_END
3805
3806/* File: c/OP_UNUSED_5CFF.c */
3807HANDLE_OPCODE(OP_UNUSED_5CFF)
3808OP_END
3809
3810/* File: c/OP_UNUSED_5DFF.c */
3811HANDLE_OPCODE(OP_UNUSED_5DFF)
3812OP_END
3813
3814/* File: c/OP_UNUSED_5EFF.c */
3815HANDLE_OPCODE(OP_UNUSED_5EFF)
3816OP_END
3817
3818/* File: c/OP_UNUSED_5FFF.c */
3819HANDLE_OPCODE(OP_UNUSED_5FFF)
3820OP_END
3821
3822/* File: c/OP_UNUSED_60FF.c */
3823HANDLE_OPCODE(OP_UNUSED_60FF)
3824OP_END
3825
3826/* File: c/OP_UNUSED_61FF.c */
3827HANDLE_OPCODE(OP_UNUSED_61FF)
3828OP_END
3829
3830/* File: c/OP_UNUSED_62FF.c */
3831HANDLE_OPCODE(OP_UNUSED_62FF)
3832OP_END
3833
3834/* File: c/OP_UNUSED_63FF.c */
3835HANDLE_OPCODE(OP_UNUSED_63FF)
3836OP_END
3837
3838/* File: c/OP_UNUSED_64FF.c */
3839HANDLE_OPCODE(OP_UNUSED_64FF)
3840OP_END
3841
3842/* File: c/OP_UNUSED_65FF.c */
3843HANDLE_OPCODE(OP_UNUSED_65FF)
3844OP_END
3845
3846/* File: c/OP_UNUSED_66FF.c */
3847HANDLE_OPCODE(OP_UNUSED_66FF)
3848OP_END
3849
3850/* File: c/OP_UNUSED_67FF.c */
3851HANDLE_OPCODE(OP_UNUSED_67FF)
3852OP_END
3853
3854/* File: c/OP_UNUSED_68FF.c */
3855HANDLE_OPCODE(OP_UNUSED_68FF)
3856OP_END
3857
3858/* File: c/OP_UNUSED_69FF.c */
3859HANDLE_OPCODE(OP_UNUSED_69FF)
3860OP_END
3861
3862/* File: c/OP_UNUSED_6AFF.c */
3863HANDLE_OPCODE(OP_UNUSED_6AFF)
3864OP_END
3865
3866/* File: c/OP_UNUSED_6BFF.c */
3867HANDLE_OPCODE(OP_UNUSED_6BFF)
3868OP_END
3869
3870/* File: c/OP_UNUSED_6CFF.c */
3871HANDLE_OPCODE(OP_UNUSED_6CFF)
3872OP_END
3873
3874/* File: c/OP_UNUSED_6DFF.c */
3875HANDLE_OPCODE(OP_UNUSED_6DFF)
3876OP_END
3877
3878/* File: c/OP_UNUSED_6EFF.c */
3879HANDLE_OPCODE(OP_UNUSED_6EFF)
3880OP_END
3881
3882/* File: c/OP_UNUSED_6FFF.c */
3883HANDLE_OPCODE(OP_UNUSED_6FFF)
3884OP_END
3885
3886/* File: c/OP_UNUSED_70FF.c */
3887HANDLE_OPCODE(OP_UNUSED_70FF)
3888OP_END
3889
3890/* File: c/OP_UNUSED_71FF.c */
3891HANDLE_OPCODE(OP_UNUSED_71FF)
3892OP_END
3893
3894/* File: c/OP_UNUSED_72FF.c */
3895HANDLE_OPCODE(OP_UNUSED_72FF)
3896OP_END
3897
3898/* File: c/OP_UNUSED_73FF.c */
3899HANDLE_OPCODE(OP_UNUSED_73FF)
3900OP_END
3901
3902/* File: c/OP_UNUSED_74FF.c */
3903HANDLE_OPCODE(OP_UNUSED_74FF)
3904OP_END
3905
3906/* File: c/OP_UNUSED_75FF.c */
3907HANDLE_OPCODE(OP_UNUSED_75FF)
3908OP_END
3909
3910/* File: c/OP_UNUSED_76FF.c */
3911HANDLE_OPCODE(OP_UNUSED_76FF)
3912OP_END
3913
3914/* File: c/OP_UNUSED_77FF.c */
3915HANDLE_OPCODE(OP_UNUSED_77FF)
3916OP_END
3917
3918/* File: c/OP_UNUSED_78FF.c */
3919HANDLE_OPCODE(OP_UNUSED_78FF)
3920OP_END
3921
3922/* File: c/OP_UNUSED_79FF.c */
3923HANDLE_OPCODE(OP_UNUSED_79FF)
3924OP_END
3925
3926/* File: c/OP_UNUSED_7AFF.c */
3927HANDLE_OPCODE(OP_UNUSED_7AFF)
3928OP_END
3929
3930/* File: c/OP_UNUSED_7BFF.c */
3931HANDLE_OPCODE(OP_UNUSED_7BFF)
3932OP_END
3933
3934/* File: c/OP_UNUSED_7CFF.c */
3935HANDLE_OPCODE(OP_UNUSED_7CFF)
3936OP_END
3937
3938/* File: c/OP_UNUSED_7DFF.c */
3939HANDLE_OPCODE(OP_UNUSED_7DFF)
3940OP_END
3941
3942/* File: c/OP_UNUSED_7EFF.c */
3943HANDLE_OPCODE(OP_UNUSED_7EFF)
3944OP_END
3945
3946/* File: c/OP_UNUSED_7FFF.c */
3947HANDLE_OPCODE(OP_UNUSED_7FFF)
3948OP_END
3949
3950/* File: c/OP_UNUSED_80FF.c */
3951HANDLE_OPCODE(OP_UNUSED_80FF)
3952OP_END
3953
3954/* File: c/OP_UNUSED_81FF.c */
3955HANDLE_OPCODE(OP_UNUSED_81FF)
3956OP_END
3957
3958/* File: c/OP_UNUSED_82FF.c */
3959HANDLE_OPCODE(OP_UNUSED_82FF)
3960OP_END
3961
3962/* File: c/OP_UNUSED_83FF.c */
3963HANDLE_OPCODE(OP_UNUSED_83FF)
3964OP_END
3965
3966/* File: c/OP_UNUSED_84FF.c */
3967HANDLE_OPCODE(OP_UNUSED_84FF)
3968OP_END
3969
3970/* File: c/OP_UNUSED_85FF.c */
3971HANDLE_OPCODE(OP_UNUSED_85FF)
3972OP_END
3973
3974/* File: c/OP_UNUSED_86FF.c */
3975HANDLE_OPCODE(OP_UNUSED_86FF)
3976OP_END
3977
3978/* File: c/OP_UNUSED_87FF.c */
3979HANDLE_OPCODE(OP_UNUSED_87FF)
3980OP_END
3981
3982/* File: c/OP_UNUSED_88FF.c */
3983HANDLE_OPCODE(OP_UNUSED_88FF)
3984OP_END
3985
3986/* File: c/OP_UNUSED_89FF.c */
3987HANDLE_OPCODE(OP_UNUSED_89FF)
3988OP_END
3989
3990/* File: c/OP_UNUSED_8AFF.c */
3991HANDLE_OPCODE(OP_UNUSED_8AFF)
3992OP_END
3993
3994/* File: c/OP_UNUSED_8BFF.c */
3995HANDLE_OPCODE(OP_UNUSED_8BFF)
3996OP_END
3997
3998/* File: c/OP_UNUSED_8CFF.c */
3999HANDLE_OPCODE(OP_UNUSED_8CFF)
4000OP_END
4001
4002/* File: c/OP_UNUSED_8DFF.c */
4003HANDLE_OPCODE(OP_UNUSED_8DFF)
4004OP_END
4005
4006/* File: c/OP_UNUSED_8EFF.c */
4007HANDLE_OPCODE(OP_UNUSED_8EFF)
4008OP_END
4009
4010/* File: c/OP_UNUSED_8FFF.c */
4011HANDLE_OPCODE(OP_UNUSED_8FFF)
4012OP_END
4013
4014/* File: c/OP_UNUSED_90FF.c */
4015HANDLE_OPCODE(OP_UNUSED_90FF)
4016OP_END
4017
4018/* File: c/OP_UNUSED_91FF.c */
4019HANDLE_OPCODE(OP_UNUSED_91FF)
4020OP_END
4021
4022/* File: c/OP_UNUSED_92FF.c */
4023HANDLE_OPCODE(OP_UNUSED_92FF)
4024OP_END
4025
4026/* File: c/OP_UNUSED_93FF.c */
4027HANDLE_OPCODE(OP_UNUSED_93FF)
4028OP_END
4029
4030/* File: c/OP_UNUSED_94FF.c */
4031HANDLE_OPCODE(OP_UNUSED_94FF)
4032OP_END
4033
4034/* File: c/OP_UNUSED_95FF.c */
4035HANDLE_OPCODE(OP_UNUSED_95FF)
4036OP_END
4037
4038/* File: c/OP_UNUSED_96FF.c */
4039HANDLE_OPCODE(OP_UNUSED_96FF)
4040OP_END
4041
4042/* File: c/OP_UNUSED_97FF.c */
4043HANDLE_OPCODE(OP_UNUSED_97FF)
4044OP_END
4045
4046/* File: c/OP_UNUSED_98FF.c */
4047HANDLE_OPCODE(OP_UNUSED_98FF)
4048OP_END
4049
4050/* File: c/OP_UNUSED_99FF.c */
4051HANDLE_OPCODE(OP_UNUSED_99FF)
4052OP_END
4053
4054/* File: c/OP_UNUSED_9AFF.c */
4055HANDLE_OPCODE(OP_UNUSED_9AFF)
4056OP_END
4057
4058/* File: c/OP_UNUSED_9BFF.c */
4059HANDLE_OPCODE(OP_UNUSED_9BFF)
4060OP_END
4061
4062/* File: c/OP_UNUSED_9CFF.c */
4063HANDLE_OPCODE(OP_UNUSED_9CFF)
4064OP_END
4065
4066/* File: c/OP_UNUSED_9DFF.c */
4067HANDLE_OPCODE(OP_UNUSED_9DFF)
4068OP_END
4069
4070/* File: c/OP_UNUSED_9EFF.c */
4071HANDLE_OPCODE(OP_UNUSED_9EFF)
4072OP_END
4073
4074/* File: c/OP_UNUSED_9FFF.c */
4075HANDLE_OPCODE(OP_UNUSED_9FFF)
4076OP_END
4077
4078/* File: c/OP_UNUSED_A0FF.c */
4079HANDLE_OPCODE(OP_UNUSED_A0FF)
4080OP_END
4081
4082/* File: c/OP_UNUSED_A1FF.c */
4083HANDLE_OPCODE(OP_UNUSED_A1FF)
4084OP_END
4085
4086/* File: c/OP_UNUSED_A2FF.c */
4087HANDLE_OPCODE(OP_UNUSED_A2FF)
4088OP_END
4089
4090/* File: c/OP_UNUSED_A3FF.c */
4091HANDLE_OPCODE(OP_UNUSED_A3FF)
4092OP_END
4093
4094/* File: c/OP_UNUSED_A4FF.c */
4095HANDLE_OPCODE(OP_UNUSED_A4FF)
4096OP_END
4097
4098/* File: c/OP_UNUSED_A5FF.c */
4099HANDLE_OPCODE(OP_UNUSED_A5FF)
4100OP_END
4101
4102/* File: c/OP_UNUSED_A6FF.c */
4103HANDLE_OPCODE(OP_UNUSED_A6FF)
4104OP_END
4105
4106/* File: c/OP_UNUSED_A7FF.c */
4107HANDLE_OPCODE(OP_UNUSED_A7FF)
4108OP_END
4109
4110/* File: c/OP_UNUSED_A8FF.c */
4111HANDLE_OPCODE(OP_UNUSED_A8FF)
4112OP_END
4113
4114/* File: c/OP_UNUSED_A9FF.c */
4115HANDLE_OPCODE(OP_UNUSED_A9FF)
4116OP_END
4117
4118/* File: c/OP_UNUSED_AAFF.c */
4119HANDLE_OPCODE(OP_UNUSED_AAFF)
4120OP_END
4121
4122/* File: c/OP_UNUSED_ABFF.c */
4123HANDLE_OPCODE(OP_UNUSED_ABFF)
4124OP_END
4125
4126/* File: c/OP_UNUSED_ACFF.c */
4127HANDLE_OPCODE(OP_UNUSED_ACFF)
4128OP_END
4129
4130/* File: c/OP_UNUSED_ADFF.c */
4131HANDLE_OPCODE(OP_UNUSED_ADFF)
4132OP_END
4133
4134/* File: c/OP_UNUSED_AEFF.c */
4135HANDLE_OPCODE(OP_UNUSED_AEFF)
4136OP_END
4137
4138/* File: c/OP_UNUSED_AFFF.c */
4139HANDLE_OPCODE(OP_UNUSED_AFFF)
4140OP_END
4141
4142/* File: c/OP_UNUSED_B0FF.c */
4143HANDLE_OPCODE(OP_UNUSED_B0FF)
4144OP_END
4145
4146/* File: c/OP_UNUSED_B1FF.c */
4147HANDLE_OPCODE(OP_UNUSED_B1FF)
4148OP_END
4149
4150/* File: c/OP_UNUSED_B2FF.c */
4151HANDLE_OPCODE(OP_UNUSED_B2FF)
4152OP_END
4153
4154/* File: c/OP_UNUSED_B3FF.c */
4155HANDLE_OPCODE(OP_UNUSED_B3FF)
4156OP_END
4157
4158/* File: c/OP_UNUSED_B4FF.c */
4159HANDLE_OPCODE(OP_UNUSED_B4FF)
4160OP_END
4161
4162/* File: c/OP_UNUSED_B5FF.c */
4163HANDLE_OPCODE(OP_UNUSED_B5FF)
4164OP_END
4165
4166/* File: c/OP_UNUSED_B6FF.c */
4167HANDLE_OPCODE(OP_UNUSED_B6FF)
4168OP_END
4169
4170/* File: c/OP_UNUSED_B7FF.c */
4171HANDLE_OPCODE(OP_UNUSED_B7FF)
4172OP_END
4173
4174/* File: c/OP_UNUSED_B8FF.c */
4175HANDLE_OPCODE(OP_UNUSED_B8FF)
4176OP_END
4177
4178/* File: c/OP_UNUSED_B9FF.c */
4179HANDLE_OPCODE(OP_UNUSED_B9FF)
4180OP_END
4181
4182/* File: c/OP_UNUSED_BAFF.c */
4183HANDLE_OPCODE(OP_UNUSED_BAFF)
4184OP_END
4185
4186/* File: c/OP_UNUSED_BBFF.c */
4187HANDLE_OPCODE(OP_UNUSED_BBFF)
4188OP_END
4189
4190/* File: c/OP_UNUSED_BCFF.c */
4191HANDLE_OPCODE(OP_UNUSED_BCFF)
4192OP_END
4193
4194/* File: c/OP_UNUSED_BDFF.c */
4195HANDLE_OPCODE(OP_UNUSED_BDFF)
4196OP_END
4197
4198/* File: c/OP_UNUSED_BEFF.c */
4199HANDLE_OPCODE(OP_UNUSED_BEFF)
4200OP_END
4201
4202/* File: c/OP_UNUSED_BFFF.c */
4203HANDLE_OPCODE(OP_UNUSED_BFFF)
4204OP_END
4205
4206/* File: c/OP_UNUSED_C0FF.c */
4207HANDLE_OPCODE(OP_UNUSED_C0FF)
4208OP_END
4209
4210/* File: c/OP_UNUSED_C1FF.c */
4211HANDLE_OPCODE(OP_UNUSED_C1FF)
4212OP_END
4213
4214/* File: c/OP_UNUSED_C2FF.c */
4215HANDLE_OPCODE(OP_UNUSED_C2FF)
4216OP_END
4217
4218/* File: c/OP_UNUSED_C3FF.c */
4219HANDLE_OPCODE(OP_UNUSED_C3FF)
4220OP_END
4221
4222/* File: c/OP_UNUSED_C4FF.c */
4223HANDLE_OPCODE(OP_UNUSED_C4FF)
4224OP_END
4225
4226/* File: c/OP_UNUSED_C5FF.c */
4227HANDLE_OPCODE(OP_UNUSED_C5FF)
4228OP_END
4229
4230/* File: c/OP_UNUSED_C6FF.c */
4231HANDLE_OPCODE(OP_UNUSED_C6FF)
4232OP_END
4233
4234/* File: c/OP_UNUSED_C7FF.c */
4235HANDLE_OPCODE(OP_UNUSED_C7FF)
4236OP_END
4237
4238/* File: c/OP_UNUSED_C8FF.c */
4239HANDLE_OPCODE(OP_UNUSED_C8FF)
4240OP_END
4241
4242/* File: c/OP_UNUSED_C9FF.c */
4243HANDLE_OPCODE(OP_UNUSED_C9FF)
4244OP_END
4245
4246/* File: c/OP_UNUSED_CAFF.c */
4247HANDLE_OPCODE(OP_UNUSED_CAFF)
4248OP_END
4249
4250/* File: c/OP_UNUSED_CBFF.c */
4251HANDLE_OPCODE(OP_UNUSED_CBFF)
4252OP_END
4253
4254/* File: c/OP_UNUSED_CCFF.c */
4255HANDLE_OPCODE(OP_UNUSED_CCFF)
4256OP_END
4257
4258/* File: c/OP_UNUSED_CDFF.c */
4259HANDLE_OPCODE(OP_UNUSED_CDFF)
4260OP_END
4261
4262/* File: c/OP_UNUSED_CEFF.c */
4263HANDLE_OPCODE(OP_UNUSED_CEFF)
4264OP_END
4265
4266/* File: c/OP_UNUSED_CFFF.c */
4267HANDLE_OPCODE(OP_UNUSED_CFFF)
4268OP_END
4269
4270/* File: c/OP_UNUSED_D0FF.c */
4271HANDLE_OPCODE(OP_UNUSED_D0FF)
4272OP_END
4273
4274/* File: c/OP_UNUSED_D1FF.c */
4275HANDLE_OPCODE(OP_UNUSED_D1FF)
4276OP_END
4277
4278/* File: c/OP_UNUSED_D2FF.c */
4279HANDLE_OPCODE(OP_UNUSED_D2FF)
4280OP_END
4281
4282/* File: c/OP_UNUSED_D3FF.c */
4283HANDLE_OPCODE(OP_UNUSED_D3FF)
4284OP_END
4285
4286/* File: c/OP_UNUSED_D4FF.c */
4287HANDLE_OPCODE(OP_UNUSED_D4FF)
4288OP_END
4289
4290/* File: c/OP_UNUSED_D5FF.c */
4291HANDLE_OPCODE(OP_UNUSED_D5FF)
4292OP_END
4293
4294/* File: c/OP_UNUSED_D6FF.c */
4295HANDLE_OPCODE(OP_UNUSED_D6FF)
4296OP_END
4297
4298/* File: c/OP_UNUSED_D7FF.c */
4299HANDLE_OPCODE(OP_UNUSED_D7FF)
4300OP_END
4301
4302/* File: c/OP_UNUSED_D8FF.c */
4303HANDLE_OPCODE(OP_UNUSED_D8FF)
4304OP_END
4305
4306/* File: c/OP_UNUSED_D9FF.c */
4307HANDLE_OPCODE(OP_UNUSED_D9FF)
4308OP_END
4309
4310/* File: c/OP_UNUSED_DAFF.c */
4311HANDLE_OPCODE(OP_UNUSED_DAFF)
4312OP_END
4313
4314/* File: c/OP_UNUSED_DBFF.c */
4315HANDLE_OPCODE(OP_UNUSED_DBFF)
4316OP_END
4317
4318/* File: c/OP_UNUSED_DCFF.c */
4319HANDLE_OPCODE(OP_UNUSED_DCFF)
4320OP_END
4321
4322/* File: c/OP_UNUSED_DDFF.c */
4323HANDLE_OPCODE(OP_UNUSED_DDFF)
4324OP_END
4325
4326/* File: c/OP_UNUSED_DEFF.c */
4327HANDLE_OPCODE(OP_UNUSED_DEFF)
4328OP_END
4329
4330/* File: c/OP_UNUSED_DFFF.c */
4331HANDLE_OPCODE(OP_UNUSED_DFFF)
4332OP_END
4333
4334/* File: c/OP_UNUSED_E0FF.c */
4335HANDLE_OPCODE(OP_UNUSED_E0FF)
4336OP_END
4337
4338/* File: c/OP_UNUSED_E1FF.c */
4339HANDLE_OPCODE(OP_UNUSED_E1FF)
4340OP_END
4341
4342/* File: c/OP_UNUSED_E2FF.c */
4343HANDLE_OPCODE(OP_UNUSED_E2FF)
4344OP_END
4345
4346/* File: c/OP_UNUSED_E3FF.c */
4347HANDLE_OPCODE(OP_UNUSED_E3FF)
4348OP_END
4349
4350/* File: c/OP_UNUSED_E4FF.c */
4351HANDLE_OPCODE(OP_UNUSED_E4FF)
4352OP_END
4353
4354/* File: c/OP_UNUSED_E5FF.c */
4355HANDLE_OPCODE(OP_UNUSED_E5FF)
4356OP_END
4357
4358/* File: c/OP_UNUSED_E6FF.c */
4359HANDLE_OPCODE(OP_UNUSED_E6FF)
4360OP_END
4361
4362/* File: c/OP_UNUSED_E7FF.c */
4363HANDLE_OPCODE(OP_UNUSED_E7FF)
4364OP_END
4365
4366/* File: c/OP_UNUSED_E8FF.c */
4367HANDLE_OPCODE(OP_UNUSED_E8FF)
4368OP_END
4369
4370/* File: c/OP_UNUSED_E9FF.c */
4371HANDLE_OPCODE(OP_UNUSED_E9FF)
4372OP_END
4373
4374/* File: c/OP_UNUSED_EAFF.c */
4375HANDLE_OPCODE(OP_UNUSED_EAFF)
4376OP_END
4377
4378/* File: c/OP_UNUSED_EBFF.c */
4379HANDLE_OPCODE(OP_UNUSED_EBFF)
4380OP_END
4381
4382/* File: c/OP_UNUSED_ECFF.c */
4383HANDLE_OPCODE(OP_UNUSED_ECFF)
4384OP_END
4385
4386/* File: c/OP_UNUSED_EDFF.c */
4387HANDLE_OPCODE(OP_UNUSED_EDFF)
4388OP_END
4389
4390/* File: c/OP_UNUSED_EEFF.c */
4391HANDLE_OPCODE(OP_UNUSED_EEFF)
4392OP_END
4393
4394/* File: c/OP_UNUSED_EFFF.c */
4395HANDLE_OPCODE(OP_UNUSED_EFFF)
4396OP_END
4397
4398/* File: c/OP_UNUSED_F0FF.c */
4399HANDLE_OPCODE(OP_UNUSED_F0FF)
4400OP_END
4401
4402/* File: c/OP_UNUSED_F1FF.c */
4403HANDLE_OPCODE(OP_UNUSED_F1FF)
4404OP_END
4405
4406/* File: c/OP_UNUSED_F2FF.c */
4407HANDLE_OPCODE(OP_UNUSED_F2FF)
4408OP_END
4409
4410/* File: c/OP_UNUSED_F3FF.c */
4411HANDLE_OPCODE(OP_UNUSED_F3FF)
4412OP_END
4413
4414/* File: c/OP_UNUSED_F4FF.c */
4415HANDLE_OPCODE(OP_UNUSED_F4FF)
4416OP_END
4417
4418/* File: c/OP_UNUSED_F5FF.c */
4419HANDLE_OPCODE(OP_UNUSED_F5FF)
4420OP_END
4421
4422/* File: c/OP_UNUSED_F6FF.c */
4423HANDLE_OPCODE(OP_UNUSED_F6FF)
4424OP_END
4425
4426/* File: c/OP_UNUSED_F7FF.c */
4427HANDLE_OPCODE(OP_UNUSED_F7FF)
4428OP_END
4429
4430/* File: c/OP_UNUSED_F8FF.c */
4431HANDLE_OPCODE(OP_UNUSED_F8FF)
4432OP_END
4433
4434/* File: c/OP_UNUSED_F9FF.c */
4435HANDLE_OPCODE(OP_UNUSED_F9FF)
4436OP_END
4437
4438/* File: c/OP_UNUSED_FAFF.c */
4439HANDLE_OPCODE(OP_UNUSED_FAFF)
4440OP_END
4441
4442/* File: c/OP_UNUSED_FBFF.c */
4443HANDLE_OPCODE(OP_UNUSED_FBFF)
4444OP_END
4445
4446/* File: c/OP_UNUSED_FCFF.c */
4447HANDLE_OPCODE(OP_UNUSED_FCFF)
4448OP_END
4449
4450/* File: c/OP_UNUSED_FDFF.c */
4451HANDLE_OPCODE(OP_UNUSED_FDFF)
4452OP_END
4453
4454/* File: c/OP_UNUSED_FEFF.c */
4455HANDLE_OPCODE(OP_UNUSED_FEFF)
4456 /*
4457 * In portable interp, most unused opcodes will fall through to here.
4458 */
4459 LOGE("unknown opcode 0x%04x\n", INST_INST(inst));
4460 dvmAbort();
4461 FINISH(1);
4462OP_END
4463
4464/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.c */
4465HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
4466 EXPORT_PC();
buzbee6a52d1d2011-03-06 13:14:46 -08004467 vsrc1 = FETCH(3);
4468 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */
jeffhao71eee1f2011-01-04 14:18:54 -08004469 dvmThrowVerificationError(curMethod, vsrc1, ref);
4470 GOTO_exceptionThrown();
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004471OP_END
4472
4473/* File: c/gotoTargets.c */
4474/*
4475 * C footer. This has some common code shared by the various targets.
4476 */
4477
4478/*
4479 * Everything from here on is a "goto target". In the basic interpreter
4480 * we jump into these targets and then jump directly to the handler for
4481 * next instruction. Here, these are subroutines that return to the caller.
4482 */
4483
jeffhao71eee1f2011-01-04 14:18:54 -08004484GOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004485 {
4486 ClassObject* arrayClass;
4487 ArrayObject* newArray;
4488 u4* contents;
4489 char typeCh;
4490 int i;
4491 u4 arg5;
4492
4493 EXPORT_PC();
4494
jeffhao71eee1f2011-01-04 14:18:54 -08004495 if (jumboFormat) {
4496 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */
4497 vsrc1 = FETCH(3); /* #of elements */
4498 vdst = FETCH(4); /* range base */
4499 arg5 = -1; /* silence compiler warning */
4500 ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004501 vsrc1, ref, vdst, vdst+vsrc1-1);
4502 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004503 ref = FETCH(1); /* class ref */
4504 vdst = FETCH(2); /* first 4 regs -or- range base */
4505
4506 if (methodCallRange) {
4507 vsrc1 = INST_AA(inst); /* #of elements */
4508 arg5 = -1; /* silence compiler warning */
4509 ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
4510 vsrc1, ref, vdst, vdst+vsrc1-1);
4511 } else {
4512 arg5 = INST_A(inst);
4513 vsrc1 = INST_B(inst); /* #of elements */
4514 ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
4515 vsrc1, ref, vdst, arg5);
4516 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004517 }
4518
4519 /*
4520 * Resolve the array class.
4521 */
4522 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
4523 if (arrayClass == NULL) {
4524 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
4525 if (arrayClass == NULL)
4526 GOTO_exceptionThrown();
4527 }
4528 /*
4529 if (!dvmIsArrayClass(arrayClass)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004530 dvmThrowRuntimeException(
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004531 "filled-new-array needs array class");
4532 GOTO_exceptionThrown();
4533 }
4534 */
4535 /* verifier guarantees this is an array class */
4536 assert(dvmIsArrayClass(arrayClass));
4537 assert(dvmIsClassInitialized(arrayClass));
4538
4539 /*
4540 * Create an array of the specified type.
4541 */
4542 LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
4543 typeCh = arrayClass->descriptor[1];
4544 if (typeCh == 'D' || typeCh == 'J') {
4545 /* category 2 primitives not allowed */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004546 dvmThrowRuntimeException("bad filled array req");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004547 GOTO_exceptionThrown();
4548 } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
4549 /* TODO: requires multiple "fill in" loops with different widths */
4550 LOGE("non-int primitives not implemented\n");
Dan Bornstein70b00ab2011-02-23 14:11:27 -08004551 dvmThrowInternalError(
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004552 "filled-new-array not implemented for anything but 'int'");
4553 GOTO_exceptionThrown();
4554 }
4555
4556 newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
4557 if (newArray == NULL)
4558 GOTO_exceptionThrown();
4559
4560 /*
4561 * Fill in the elements. It's legal for vsrc1 to be zero.
4562 */
4563 contents = (u4*) newArray->contents;
4564 if (methodCallRange) {
4565 for (i = 0; i < vsrc1; i++)
4566 contents[i] = GET_REGISTER(vdst+i);
4567 } else {
4568 assert(vsrc1 <= 5);
4569 if (vsrc1 == 5) {
4570 contents[4] = GET_REGISTER(arg5);
4571 vsrc1--;
4572 }
4573 for (i = 0; i < vsrc1; i++) {
4574 contents[i] = GET_REGISTER(vdst & 0x0f);
4575 vdst >>= 4;
4576 }
4577 }
Barry Hayes364f9d92010-06-11 16:12:47 -07004578 if (typeCh == 'L' || typeCh == '[') {
4579 dvmWriteBarrierArray(newArray, 0, newArray->length);
4580 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004581
4582 retval.l = newArray;
4583 }
jeffhao71eee1f2011-01-04 14:18:54 -08004584 if (jumboFormat) {
4585 FINISH(5);
4586 } else {
4587 FINISH(3);
4588 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004589GOTO_TARGET_END
4590
4591
jeffhao71eee1f2011-01-04 14:18:54 -08004592GOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004593 {
4594 Method* baseMethod;
4595 Object* thisPtr;
4596
4597 EXPORT_PC();
4598
jeffhao71eee1f2011-01-04 14:18:54 -08004599 if (jumboFormat) {
4600 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4601 vsrc1 = FETCH(3); /* count */
4602 vdst = FETCH(4); /* first reg */
4603 ADJUST_PC(2); /* advance pc partially to make returns easier */
4604 ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004605 vsrc1, ref, vdst, vdst+vsrc1-1);
4606 thisPtr = (Object*) GET_REGISTER(vdst);
4607 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004608 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4609 ref = FETCH(1); /* method ref */
4610 vdst = FETCH(2); /* 4 regs -or- first reg */
4611
4612 /*
4613 * The object against which we are executing a method is always
4614 * in the first argument.
4615 */
4616 if (methodCallRange) {
4617 assert(vsrc1 > 0);
4618 ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
4619 vsrc1, ref, vdst, vdst+vsrc1-1);
4620 thisPtr = (Object*) GET_REGISTER(vdst);
4621 } else {
4622 assert((vsrc1>>4) > 0);
4623 ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
4624 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4625 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4626 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004627 }
4628
4629 if (!checkForNull(thisPtr))
4630 GOTO_exceptionThrown();
4631
4632 /*
4633 * Resolve the method. This is the correct method for the static
4634 * type of the object. We also verify access permissions here.
4635 */
4636 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
4637 if (baseMethod == NULL) {
4638 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
4639 if (baseMethod == NULL) {
4640 ILOGV("+ unknown method or access denied\n");
4641 GOTO_exceptionThrown();
4642 }
4643 }
4644
4645 /*
4646 * Combine the object we found with the vtable offset in the
4647 * method.
4648 */
4649 assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
4650 methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
4651
Ben Cheng7a2697d2010-06-07 13:44:23 -07004652#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4653 callsiteClass = thisPtr->clazz;
4654#endif
4655
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004656#if 0
4657 if (dvmIsAbstractMethod(methodToCall)) {
4658 /*
4659 * This can happen if you create two classes, Base and Sub, where
4660 * Sub is a sub-class of Base. Declare a protected abstract
4661 * method foo() in Base, and invoke foo() from a method in Base.
4662 * Base is an "abstract base class" and is never instantiated
4663 * directly. Now, Override foo() in Sub, and use Sub. This
4664 * Works fine unless Sub stops providing an implementation of
4665 * the method.
4666 */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004667 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004668 GOTO_exceptionThrown();
4669 }
4670#else
4671 assert(!dvmIsAbstractMethod(methodToCall) ||
4672 methodToCall->nativeFunc != NULL);
4673#endif
4674
4675 LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
4676 baseMethod->clazz->descriptor, baseMethod->name,
4677 (u4) baseMethod->methodIndex,
4678 methodToCall->clazz->descriptor, methodToCall->name);
4679 assert(methodToCall != NULL);
4680
4681#if 0
4682 if (vsrc1 != methodToCall->insSize) {
4683 LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
4684 baseMethod->clazz->descriptor, baseMethod->name,
4685 (u4) baseMethod->methodIndex,
4686 methodToCall->clazz->descriptor, methodToCall->name);
4687 //dvmDumpClass(baseMethod->clazz);
4688 //dvmDumpClass(methodToCall->clazz);
4689 dvmDumpAllClasses(0);
4690 }
4691#endif
4692
4693 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4694 }
4695GOTO_TARGET_END
4696
jeffhao71eee1f2011-01-04 14:18:54 -08004697GOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004698 {
4699 Method* baseMethod;
4700 u2 thisReg;
4701
4702 EXPORT_PC();
4703
jeffhao71eee1f2011-01-04 14:18:54 -08004704 if (jumboFormat) {
4705 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4706 vsrc1 = FETCH(3); /* count */
4707 vdst = FETCH(4); /* first reg */
4708 ADJUST_PC(2); /* advance pc partially to make returns easier */
4709 ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004710 vsrc1, ref, vdst, vdst+vsrc1-1);
4711 thisReg = vdst;
4712 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004713 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4714 ref = FETCH(1); /* method ref */
4715 vdst = FETCH(2); /* 4 regs -or- first reg */
4716
4717 if (methodCallRange) {
4718 ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
4719 vsrc1, ref, vdst, vdst+vsrc1-1);
4720 thisReg = vdst;
4721 } else {
4722 ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
4723 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4724 thisReg = vdst & 0x0f;
4725 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004726 }
jeffhao71eee1f2011-01-04 14:18:54 -08004727
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004728 /* impossible in well-formed code, but we must check nevertheless */
4729 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4730 GOTO_exceptionThrown();
4731
4732 /*
4733 * Resolve the method. This is the correct method for the static
4734 * type of the object. We also verify access permissions here.
4735 * The first arg to dvmResolveMethod() is just the referring class
4736 * (used for class loaders and such), so we don't want to pass
4737 * the superclass into the resolution call.
4738 */
4739 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
4740 if (baseMethod == NULL) {
4741 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
4742 if (baseMethod == NULL) {
4743 ILOGV("+ unknown method or access denied\n");
4744 GOTO_exceptionThrown();
4745 }
4746 }
4747
4748 /*
4749 * Combine the object we found with the vtable offset in the
4750 * method's class.
4751 *
4752 * We're using the current method's class' superclass, not the
4753 * superclass of "this". This is because we might be executing
4754 * in a method inherited from a superclass, and we want to run
4755 * in that class' superclass.
4756 */
4757 if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
4758 /*
4759 * Method does not exist in the superclass. Could happen if
4760 * superclass gets updated.
4761 */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004762 dvmThrowNoSuchMethodError(baseMethod->name);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004763 GOTO_exceptionThrown();
4764 }
4765 methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
4766#if 0
4767 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004768 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004769 GOTO_exceptionThrown();
4770 }
4771#else
4772 assert(!dvmIsAbstractMethod(methodToCall) ||
4773 methodToCall->nativeFunc != NULL);
4774#endif
4775 LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
4776 baseMethod->clazz->descriptor, baseMethod->name,
4777 methodToCall->clazz->descriptor, methodToCall->name);
4778 assert(methodToCall != NULL);
4779
4780 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4781 }
4782GOTO_TARGET_END
4783
jeffhao71eee1f2011-01-04 14:18:54 -08004784GOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004785 {
4786 Object* thisPtr;
4787 ClassObject* thisClass;
4788
4789 EXPORT_PC();
4790
jeffhao71eee1f2011-01-04 14:18:54 -08004791 if (jumboFormat) {
4792 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4793 vsrc1 = FETCH(3); /* count */
4794 vdst = FETCH(4); /* first reg */
4795 ADJUST_PC(2); /* advance pc partially to make returns easier */
4796 ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004797 vsrc1, ref, vdst, vdst+vsrc1-1);
4798 thisPtr = (Object*) GET_REGISTER(vdst);
4799 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004800 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4801 ref = FETCH(1); /* method ref */
4802 vdst = FETCH(2); /* 4 regs -or- first reg */
4803
4804 /*
4805 * The object against which we are executing a method is always
4806 * in the first argument.
4807 */
4808 if (methodCallRange) {
4809 assert(vsrc1 > 0);
4810 ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
4811 vsrc1, ref, vdst, vdst+vsrc1-1);
4812 thisPtr = (Object*) GET_REGISTER(vdst);
4813 } else {
4814 assert((vsrc1>>4) > 0);
4815 ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
4816 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4817 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4818 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004819 }
jeffhao71eee1f2011-01-04 14:18:54 -08004820
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004821 if (!checkForNull(thisPtr))
4822 GOTO_exceptionThrown();
4823
4824 thisClass = thisPtr->clazz;
4825
Ben Cheng7a2697d2010-06-07 13:44:23 -07004826#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4827 callsiteClass = thisClass;
4828#endif
4829
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004830 /*
4831 * Given a class and a method index, find the Method* with the
4832 * actual code we want to execute.
4833 */
4834 methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
4835 methodClassDex);
4836 if (methodToCall == NULL) {
4837 assert(dvmCheckException(self));
4838 GOTO_exceptionThrown();
4839 }
4840
4841 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4842 }
4843GOTO_TARGET_END
4844
jeffhao71eee1f2011-01-04 14:18:54 -08004845GOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004846 {
4847 u2 thisReg;
4848
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004849 EXPORT_PC();
4850
jeffhao71eee1f2011-01-04 14:18:54 -08004851 if (jumboFormat) {
4852 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4853 vsrc1 = FETCH(3); /* count */
4854 vdst = FETCH(4); /* first reg */
4855 ADJUST_PC(2); /* advance pc partially to make returns easier */
4856 ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004857 vsrc1, ref, vdst, vdst+vsrc1-1);
4858 thisReg = vdst;
4859 } else {
jeffhao71eee1f2011-01-04 14:18:54 -08004860 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4861 ref = FETCH(1); /* method ref */
4862 vdst = FETCH(2); /* 4 regs -or- first reg */
4863
4864 if (methodCallRange) {
4865 ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
4866 vsrc1, ref, vdst, vdst+vsrc1-1);
4867 thisReg = vdst;
4868 } else {
4869 ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
4870 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4871 thisReg = vdst & 0x0f;
4872 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004873 }
jeffhao71eee1f2011-01-04 14:18:54 -08004874
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004875 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4876 GOTO_exceptionThrown();
4877
4878 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
4879 if (methodToCall == NULL) {
4880 methodToCall = dvmResolveMethod(curMethod->clazz, ref,
4881 METHOD_DIRECT);
4882 if (methodToCall == NULL) {
4883 ILOGV("+ unknown direct method\n"); // should be impossible
4884 GOTO_exceptionThrown();
4885 }
4886 }
4887 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4888 }
4889GOTO_TARGET_END
4890
jeffhao71eee1f2011-01-04 14:18:54 -08004891GOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004892 EXPORT_PC();
4893
jeffhao71eee1f2011-01-04 14:18:54 -08004894 if (jumboFormat) {
4895 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4896 vsrc1 = FETCH(3); /* count */
4897 vdst = FETCH(4); /* first reg */
4898 ADJUST_PC(2); /* advance pc partially to make returns easier */
4899 ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004900 vsrc1, ref, vdst, vdst+vsrc1-1);
jeffhao71eee1f2011-01-04 14:18:54 -08004901 } else {
4902 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4903 ref = FETCH(1); /* method ref */
4904 vdst = FETCH(2); /* 4 regs -or- first reg */
4905
4906 if (methodCallRange)
4907 ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
4908 vsrc1, ref, vdst, vdst+vsrc1-1);
4909 else
4910 ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
4911 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4912 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004913
4914 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
4915 if (methodToCall == NULL) {
4916 methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
4917 if (methodToCall == NULL) {
4918 ILOGV("+ unknown method\n");
4919 GOTO_exceptionThrown();
4920 }
Ben Chengdd6e8702010-05-07 13:05:47 -07004921
4922 /*
4923 * The JIT needs dvmDexGetResolvedMethod() to return non-null.
4924 * Since we use the portable interpreter to build the trace, this extra
4925 * check is not needed for mterp.
4926 */
4927 if (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL) {
4928 /* Class initialization is still ongoing */
Bill Buzbee1b3da592011-02-03 07:38:22 -08004929 END_JIT_TSELECT();
Ben Chengdd6e8702010-05-07 13:05:47 -07004930 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004931 }
4932 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4933GOTO_TARGET_END
4934
jeffhao71eee1f2011-01-04 14:18:54 -08004935GOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004936 {
4937 Object* thisPtr;
4938
4939 EXPORT_PC();
4940
4941 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4942 ref = FETCH(1); /* vtable index */
4943 vdst = FETCH(2); /* 4 regs -or- first reg */
4944
4945 /*
4946 * The object against which we are executing a method is always
4947 * in the first argument.
4948 */
4949 if (methodCallRange) {
4950 assert(vsrc1 > 0);
4951 ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
4952 vsrc1, ref, vdst, vdst+vsrc1-1);
4953 thisPtr = (Object*) GET_REGISTER(vdst);
4954 } else {
4955 assert((vsrc1>>4) > 0);
4956 ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
4957 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4958 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4959 }
4960
4961 if (!checkForNull(thisPtr))
4962 GOTO_exceptionThrown();
4963
Ben Cheng7a2697d2010-06-07 13:44:23 -07004964#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4965 callsiteClass = thisPtr->clazz;
4966#endif
4967
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004968 /*
4969 * Combine the object we found with the vtable offset in the
4970 * method.
4971 */
jeffhao71eee1f2011-01-04 14:18:54 -08004972 assert(ref < (unsigned int) thisPtr->clazz->vtableCount);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004973 methodToCall = thisPtr->clazz->vtable[ref];
4974
4975#if 0
4976 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08004977 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004978 GOTO_exceptionThrown();
4979 }
4980#else
4981 assert(!dvmIsAbstractMethod(methodToCall) ||
4982 methodToCall->nativeFunc != NULL);
4983#endif
4984
4985 LOGVV("+++ virtual[%d]=%s.%s\n",
4986 ref, methodToCall->clazz->descriptor, methodToCall->name);
4987 assert(methodToCall != NULL);
4988
4989 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4990 }
4991GOTO_TARGET_END
4992
jeffhao71eee1f2011-01-04 14:18:54 -08004993GOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08004994 {
4995 u2 thisReg;
4996
4997 EXPORT_PC();
4998
4999 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
5000 ref = FETCH(1); /* vtable index */
5001 vdst = FETCH(2); /* 4 regs -or- first reg */
5002
5003 if (methodCallRange) {
5004 ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
5005 vsrc1, ref, vdst, vdst+vsrc1-1);
5006 thisReg = vdst;
5007 } else {
5008 ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
5009 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
5010 thisReg = vdst & 0x0f;
5011 }
5012 /* impossible in well-formed code, but we must check nevertheless */
5013 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
5014 GOTO_exceptionThrown();
5015
5016#if 0 /* impossible in optimized + verified code */
5017 if (ref >= curMethod->clazz->super->vtableCount) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08005018 dvmThrowNoSuchMethodError(NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005019 GOTO_exceptionThrown();
5020 }
5021#else
jeffhao71eee1f2011-01-04 14:18:54 -08005022 assert(ref < (unsigned int) curMethod->clazz->super->vtableCount);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005023#endif
5024
5025 /*
5026 * Combine the object we found with the vtable offset in the
5027 * method's class.
5028 *
5029 * We're using the current method's class' superclass, not the
5030 * superclass of "this". This is because we might be executing
5031 * in a method inherited from a superclass, and we want to run
5032 * in the method's class' superclass.
5033 */
5034 methodToCall = curMethod->clazz->super->vtable[ref];
5035
5036#if 0
5037 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08005038 dvmThrowAbstractMethodError("abstract method not implemented");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005039 GOTO_exceptionThrown();
5040 }
5041#else
5042 assert(!dvmIsAbstractMethod(methodToCall) ||
5043 methodToCall->nativeFunc != NULL);
5044#endif
5045 LOGVV("+++ super-virtual[%d]=%s.%s\n",
5046 ref, methodToCall->clazz->descriptor, methodToCall->name);
5047 assert(methodToCall != NULL);
5048
5049 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
5050 }
5051GOTO_TARGET_END
5052
5053
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005054 /*
5055 * General handling for return-void, return, and return-wide. Put the
5056 * return value in "retval" before jumping here.
5057 */
5058GOTO_TARGET(returnFromMethod)
5059 {
5060 StackSaveArea* saveArea;
5061
5062 /*
5063 * We must do this BEFORE we pop the previous stack frame off, so
5064 * that the GC can see the return value (if any) in the local vars.
5065 *
5066 * Since this is now an interpreter switch point, we must do it before
5067 * we do anything at all.
5068 */
5069 PERIODIC_CHECKS(kInterpEntryReturn, 0);
5070
5071 ILOGV("> retval=0x%llx (leaving %s.%s %s)",
5072 retval.j, curMethod->clazz->descriptor, curMethod->name,
Mike Lockwood85745e12009-07-08 12:39:37 -04005073 curMethod->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005074 //DUMP_REGS(curMethod, fp);
5075
5076 saveArea = SAVEAREA_FROM_FP(fp);
5077
5078#ifdef EASY_GDB
5079 debugSaveArea = saveArea;
5080#endif
Andy McFadden0d615c32010-08-18 12:19:51 -07005081#if (INTERP_TYPE == INTERP_DBG)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005082 TRACE_METHOD_EXIT(self, curMethod);
5083#endif
5084
5085 /* back up to previous frame and see if we hit a break */
Carl Shapirofc75f3e2010-12-07 11:43:38 -08005086 fp = (u4*)saveArea->prevFrame;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005087 assert(fp != NULL);
5088 if (dvmIsBreakFrame(fp)) {
5089 /* bail without popping the method frame from stack */
5090 LOGVV("+++ returned into break frame\n");
Bill Buzbeed7269912009-11-10 14:31:32 -08005091#if defined(WITH_JIT)
5092 /* Let the Jit know the return is terminating normally */
Ben Chengfc075c22010-05-28 15:20:08 -07005093 CHECK_JIT_VOID();
Bill Buzbeed7269912009-11-10 14:31:32 -08005094#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005095 GOTO_bail();
5096 }
5097
5098 /* update thread FP, and reset local variables */
5099 self->curFrame = fp;
5100 curMethod = SAVEAREA_FROM_FP(fp)->method;
5101 //methodClass = curMethod->clazz;
5102 methodClassDex = curMethod->clazz->pDvmDex;
5103 pc = saveArea->savedPc;
5104 ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
Mike Lockwood85745e12009-07-08 12:39:37 -04005105 curMethod->name, curMethod->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005106
5107 /* use FINISH on the caller's invoke instruction */
5108 //u2 invokeInstr = INST_INST(FETCH(0));
5109 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
5110 invokeInstr <= OP_INVOKE_INTERFACE*/)
5111 {
5112 FINISH(3);
5113 } else {
5114 //LOGE("Unknown invoke instr %02x at %d\n",
5115 // invokeInstr, (int) (pc - curMethod->insns));
5116 assert(false);
5117 }
5118 }
5119GOTO_TARGET_END
5120
5121
5122 /*
5123 * Jump here when the code throws an exception.
5124 *
5125 * By the time we get here, the Throwable has been created and the stack
5126 * trace has been saved off.
5127 */
5128GOTO_TARGET(exceptionThrown)
5129 {
5130 Object* exception;
5131 int catchRelPc;
5132
5133 /*
5134 * Since this is now an interpreter switch point, we must do it before
5135 * we do anything at all.
5136 */
5137 PERIODIC_CHECKS(kInterpEntryThrow, 0);
5138
Ben Cheng79d173c2009-09-29 16:12:51 -07005139#if defined(WITH_JIT)
Bill Buzbee1b3da592011-02-03 07:38:22 -08005140 // Something threw during trace selection - end the current trace
5141 END_JIT_TSELECT();
Ben Cheng79d173c2009-09-29 16:12:51 -07005142#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005143 /*
5144 * We save off the exception and clear the exception status. While
5145 * processing the exception we might need to load some Throwable
5146 * classes, and we don't want class loader exceptions to get
5147 * confused with this one.
5148 */
5149 assert(dvmCheckException(self));
5150 exception = dvmGetException(self);
5151 dvmAddTrackedAlloc(exception, self);
5152 dvmClearException(self);
5153
5154 LOGV("Handling exception %s at %s:%d\n",
5155 exception->clazz->descriptor, curMethod->name,
5156 dvmLineNumFromPC(curMethod, pc - curMethod->insns));
5157
Andy McFadden0d615c32010-08-18 12:19:51 -07005158#if (INTERP_TYPE == INTERP_DBG)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005159 /*
5160 * Tell the debugger about it.
5161 *
5162 * TODO: if the exception was thrown by interpreted code, control
5163 * fell through native, and then back to us, we will report the
5164 * exception at the point of the throw and again here. We can avoid
5165 * this by not reporting exceptions when we jump here directly from
5166 * the native call code above, but then we won't report exceptions
5167 * that were thrown *from* the JNI code (as opposed to *through* it).
5168 *
5169 * The correct solution is probably to ignore from-native exceptions
5170 * here, and have the JNI exception code do the reporting to the
5171 * debugger.
5172 */
buzbeecb3081f2011-01-14 13:37:31 -08005173 if (DEBUGGER_ACTIVE) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005174 void* catchFrame;
5175 catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
5176 exception, true, &catchFrame);
5177 dvmDbgPostException(fp, pc - curMethod->insns, catchFrame,
5178 catchRelPc, exception);
5179 }
5180#endif
5181
5182 /*
5183 * We need to unroll to the catch block or the nearest "break"
5184 * frame.
5185 *
5186 * A break frame could indicate that we have reached an intermediate
5187 * native call, or have gone off the top of the stack and the thread
5188 * needs to exit. Either way, we return from here, leaving the
5189 * exception raised.
5190 *
5191 * If we do find a catch block, we want to transfer execution to
5192 * that point.
Andy McFadden4fbba1f2010-02-03 07:21:14 -08005193 *
5194 * Note this can cause an exception while resolving classes in
5195 * the "catch" blocks.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005196 */
5197 catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
Carl Shapirofc75f3e2010-12-07 11:43:38 -08005198 exception, false, (void**)(void*)&fp);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005199
5200 /*
5201 * Restore the stack bounds after an overflow. This isn't going to
5202 * be correct in all circumstances, e.g. if JNI code devours the
5203 * exception this won't happen until some other exception gets
5204 * thrown. If the code keeps pushing the stack bounds we'll end
5205 * up aborting the VM.
5206 *
5207 * Note we want to do this *after* the call to dvmFindCatchBlock,
5208 * because that may need extra stack space to resolve exception
5209 * classes (e.g. through a class loader).
Andy McFadden4fbba1f2010-02-03 07:21:14 -08005210 *
5211 * It's possible for the stack overflow handling to cause an
5212 * exception (specifically, class resolution in a "catch" block
5213 * during the call above), so we could see the thread's overflow
5214 * flag raised but actually be running in a "nested" interpreter
5215 * frame. We don't allow doubled-up StackOverflowErrors, so
5216 * we can check for this by just looking at the exception type
5217 * in the cleanup function. Also, we won't unroll past the SOE
5218 * point because the more-recent exception will hit a break frame
5219 * as it unrolls to here.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005220 */
5221 if (self->stackOverflowed)
Andy McFadden4fbba1f2010-02-03 07:21:14 -08005222 dvmCleanupStackOverflow(self, exception);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005223
5224 if (catchRelPc < 0) {
5225 /* falling through to JNI code or off the bottom of the stack */
5226#if DVM_SHOW_EXCEPTION >= 2
5227 LOGD("Exception %s from %s:%d not caught locally\n",
5228 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
5229 dvmLineNumFromPC(curMethod, pc - curMethod->insns));
5230#endif
5231 dvmSetException(self, exception);
5232 dvmReleaseTrackedAlloc(exception, self);
5233 GOTO_bail();
5234 }
5235
5236#if DVM_SHOW_EXCEPTION >= 3
5237 {
5238 const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
5239 LOGD("Exception %s thrown from %s:%d to %s:%d\n",
5240 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
5241 dvmLineNumFromPC(curMethod, pc - curMethod->insns),
5242 dvmGetMethodSourceFile(catchMethod),
5243 dvmLineNumFromPC(catchMethod, catchRelPc));
5244 }
5245#endif
5246
5247 /*
5248 * Adjust local variables to match self->curFrame and the
5249 * updated PC.
5250 */
5251 //fp = (u4*) self->curFrame;
5252 curMethod = SAVEAREA_FROM_FP(fp)->method;
5253 //methodClass = curMethod->clazz;
5254 methodClassDex = curMethod->clazz->pDvmDex;
5255 pc = curMethod->insns + catchRelPc;
5256 ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
Mike Lockwood85745e12009-07-08 12:39:37 -04005257 curMethod->name, curMethod->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005258 DUMP_REGS(curMethod, fp, false); // show all regs
5259
5260 /*
5261 * Restore the exception if the handler wants it.
5262 *
5263 * The Dalvik spec mandates that, if an exception handler wants to
5264 * do something with the exception, the first instruction executed
5265 * must be "move-exception". We can pass the exception along
5266 * through the thread struct, and let the move-exception instruction
5267 * clear it for us.
5268 *
5269 * If the handler doesn't call move-exception, we don't want to
5270 * finish here with an exception still pending.
5271 */
5272 if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
5273 dvmSetException(self, exception);
5274
5275 dvmReleaseTrackedAlloc(exception, self);
5276 FINISH(0);
5277 }
5278GOTO_TARGET_END
5279
5280
Elliott Hughes8afa9df2010-07-07 14:47:25 -07005281
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005282 /*
5283 * General handling for invoke-{virtual,super,direct,static,interface},
5284 * including "quick" variants.
5285 *
5286 * Set "methodToCall" to the Method we're calling, and "methodCallRange"
5287 * depending on whether this is a "/range" instruction.
5288 *
5289 * For a range call:
5290 * "vsrc1" holds the argument count (8 bits)
5291 * "vdst" holds the first argument in the range
5292 * For a non-range call:
5293 * "vsrc1" holds the argument count (4 bits) and the 5th argument index
5294 * "vdst" holds four 4-bit register indices
5295 *
5296 * The caller must EXPORT_PC before jumping here, because any method
5297 * call can throw a stack overflow exception.
5298 */
5299GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
5300 u2 count, u2 regs)
5301 {
5302 STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
5303
5304 //printf("range=%d call=%p count=%d regs=0x%04x\n",
5305 // methodCallRange, methodToCall, count, regs);
5306 //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
Mike Lockwood85745e12009-07-08 12:39:37 -04005307 // methodToCall->name, methodToCall->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005308
5309 u4* outs;
5310 int i;
5311
5312 /*
5313 * Copy args. This may corrupt vsrc1/vdst.
5314 */
5315 if (methodCallRange) {
5316 // could use memcpy or a "Duff's device"; most functions have
5317 // so few args it won't matter much
5318 assert(vsrc1 <= curMethod->outsSize);
5319 assert(vsrc1 == methodToCall->insSize);
5320 outs = OUTS_FROM_FP(fp, vsrc1);
5321 for (i = 0; i < vsrc1; i++)
5322 outs[i] = GET_REGISTER(vdst+i);
5323 } else {
5324 u4 count = vsrc1 >> 4;
5325
5326 assert(count <= curMethod->outsSize);
5327 assert(count == methodToCall->insSize);
5328 assert(count <= 5);
5329
5330 outs = OUTS_FROM_FP(fp, count);
5331#if 0
5332 if (count == 5) {
5333 outs[4] = GET_REGISTER(vsrc1 & 0x0f);
5334 count--;
5335 }
5336 for (i = 0; i < (int) count; i++) {
5337 outs[i] = GET_REGISTER(vdst & 0x0f);
5338 vdst >>= 4;
5339 }
5340#else
5341 // This version executes fewer instructions but is larger
5342 // overall. Seems to be a teensy bit faster.
5343 assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear
5344 switch (count) {
5345 case 5:
5346 outs[4] = GET_REGISTER(vsrc1 & 0x0f);
5347 case 4:
5348 outs[3] = GET_REGISTER(vdst >> 12);
5349 case 3:
5350 outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
5351 case 2:
5352 outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
5353 case 1:
5354 outs[0] = GET_REGISTER(vdst & 0x0f);
5355 default:
5356 ;
5357 }
5358#endif
5359 }
5360 }
5361
5362 /*
5363 * (This was originally a "goto" target; I've kept it separate from the
5364 * stuff above in case we want to refactor things again.)
5365 *
5366 * At this point, we have the arguments stored in the "outs" area of
5367 * the current method's stack frame, and the method to call in
5368 * "methodToCall". Push a new stack frame.
5369 */
5370 {
5371 StackSaveArea* newSaveArea;
5372 u4* newFp;
5373
5374 ILOGV("> %s%s.%s %s",
5375 dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
5376 methodToCall->clazz->descriptor, methodToCall->name,
Mike Lockwood85745e12009-07-08 12:39:37 -04005377 methodToCall->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005378
5379 newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
5380 newSaveArea = SAVEAREA_FROM_FP(newFp);
5381
5382 /* verify that we have enough space */
5383 if (true) {
5384 u1* bottom;
5385 bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
5386 if (bottom < self->interpStackEnd) {
5387 /* stack overflow */
Andy McFadden6ed1a0f2009-09-10 15:34:19 -07005388 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 -08005389 self->interpStackStart, self->interpStackEnd, bottom,
Andy McFadden6ed1a0f2009-09-10 15:34:19 -07005390 (u1*) fp - bottom, self->interpStackSize,
5391 methodToCall->name);
5392 dvmHandleStackOverflow(self, methodToCall);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005393 assert(dvmCheckException(self));
5394 GOTO_exceptionThrown();
5395 }
5396 //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n",
5397 // fp, newFp, newSaveArea, bottom);
5398 }
5399
5400#ifdef LOG_INSTR
5401 if (methodToCall->registersSize > methodToCall->insSize) {
5402 /*
5403 * This makes valgrind quiet when we print registers that
5404 * haven't been initialized. Turn it off when the debug
5405 * messages are disabled -- we want valgrind to report any
5406 * used-before-initialized issues.
5407 */
5408 memset(newFp, 0xcc,
5409 (methodToCall->registersSize - methodToCall->insSize) * 4);
5410 }
5411#endif
5412
5413#ifdef EASY_GDB
5414 newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
5415#endif
5416 newSaveArea->prevFrame = fp;
5417 newSaveArea->savedPc = pc;
Ben Chengba4fc8b2009-06-01 13:00:29 -07005418#if defined(WITH_JIT)
5419 newSaveArea->returnAddr = 0;
5420#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005421 newSaveArea->method = methodToCall;
5422
5423 if (!dvmIsNativeMethod(methodToCall)) {
5424 /*
5425 * "Call" interpreted code. Reposition the PC, update the
5426 * frame pointer and other local state, and continue.
5427 */
5428 curMethod = methodToCall;
5429 methodClassDex = curMethod->clazz->pDvmDex;
5430 pc = methodToCall->insns;
Carl Shapirofc75f3e2010-12-07 11:43:38 -08005431 self->curFrame = fp = newFp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005432#ifdef EASY_GDB
5433 debugSaveArea = SAVEAREA_FROM_FP(newFp);
5434#endif
5435#if INTERP_TYPE == INTERP_DBG
5436 debugIsMethodEntry = true; // profiling, debugging
5437#endif
5438 ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
Mike Lockwood85745e12009-07-08 12:39:37 -04005439 curMethod->name, curMethod->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005440 DUMP_REGS(curMethod, fp, true); // show input args
5441 FINISH(0); // jump to method start
5442 } else {
5443 /* set this up for JNI locals, even if not a JNI native */
Andy McFaddend5ab7262009-08-25 07:19:34 -07005444#ifdef USE_INDIRECT_REF
5445 newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
5446#else
5447 newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
5448#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005449
5450 self->curFrame = newFp;
5451
5452 DUMP_REGS(methodToCall, newFp, true); // show input args
5453
Andy McFadden0d615c32010-08-18 12:19:51 -07005454#if (INTERP_TYPE == INTERP_DBG)
buzbeecb3081f2011-01-14 13:37:31 -08005455 if (DEBUGGER_ACTIVE) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005456 dvmDbgPostLocationEvent(methodToCall, -1,
5457 dvmGetThisPtr(curMethod, fp), DBG_METHOD_ENTRY);
5458 }
5459#endif
Andy McFadden0d615c32010-08-18 12:19:51 -07005460#if (INTERP_TYPE == INTERP_DBG)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005461 TRACE_METHOD_ENTER(self, methodToCall);
5462#endif
5463
Elliott Hughes8afa9df2010-07-07 14:47:25 -07005464 {
5465 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
5466 methodToCall->name, methodToCall->shorty);
5467 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005468
Bill Buzbeed7269912009-11-10 14:31:32 -08005469#if defined(WITH_JIT)
5470 /* Allow the Jit to end any pending trace building */
Ben Chengfc075c22010-05-28 15:20:08 -07005471 CHECK_JIT_VOID();
Bill Buzbeed7269912009-11-10 14:31:32 -08005472#endif
5473
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005474 /*
5475 * Jump through native call bridge. Because we leave no
5476 * space for locals on native calls, "newFp" points directly
5477 * to the method arguments.
5478 */
5479 (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
5480
Andy McFadden0d615c32010-08-18 12:19:51 -07005481#if (INTERP_TYPE == INTERP_DBG)
buzbeecb3081f2011-01-14 13:37:31 -08005482 if (DEBUGGER_ACTIVE) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005483 dvmDbgPostLocationEvent(methodToCall, -1,
5484 dvmGetThisPtr(curMethod, fp), DBG_METHOD_EXIT);
5485 }
5486#endif
Andy McFadden0d615c32010-08-18 12:19:51 -07005487#if (INTERP_TYPE == INTERP_DBG)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005488 TRACE_METHOD_EXIT(self, methodToCall);
5489#endif
5490
5491 /* pop frame off */
5492 dvmPopJniLocals(self, newSaveArea);
5493 self->curFrame = fp;
5494
5495 /*
5496 * If the native code threw an exception, or interpreted code
5497 * invoked by the native call threw one and nobody has cleared
5498 * it, jump to our local exception handling.
5499 */
5500 if (dvmCheckException(self)) {
5501 LOGV("Exception thrown by/below native code\n");
5502 GOTO_exceptionThrown();
5503 }
5504
5505 ILOGD("> retval=0x%llx (leaving native)", retval.j);
5506 ILOGD("> (return from native %s.%s to %s.%s %s)",
5507 methodToCall->clazz->descriptor, methodToCall->name,
5508 curMethod->clazz->descriptor, curMethod->name,
Mike Lockwood85745e12009-07-08 12:39:37 -04005509 curMethod->shorty);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005510
5511 //u2 invokeInstr = INST_INST(FETCH(0));
5512 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
5513 invokeInstr <= OP_INVOKE_INTERFACE*/)
5514 {
5515 FINISH(3);
5516 } else {
5517 //LOGE("Unknown invoke instr %02x at %d\n",
5518 // invokeInstr, (int) (pc - curMethod->insns));
5519 assert(false);
5520 }
5521 }
5522 }
5523 assert(false); // should not get here
5524GOTO_TARGET_END
5525
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005526/* File: portable/enddefs.c */
5527/*--- end of opcodes ---*/
5528
5529#ifndef THREADED_INTERP
5530 } // end of "switch"
5531 } // end of "while"
5532#endif
5533
5534bail:
5535 ILOGD("|-- Leaving interpreter loop"); // note "curMethod" may be NULL
5536
buzbee9f601a92011-02-11 17:48:20 -08005537 self->retval = retval;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005538 return false;
5539
5540bail_switch:
5541 /*
5542 * The standard interpreter currently doesn't set or care about the
5543 * "debugIsMethodEntry" value, so setting this is only of use if we're
5544 * switching between two "debug" interpreters, which we never do.
5545 *
5546 * TODO: figure out if preserving this makes any sense.
5547 */
Andy McFadden0d615c32010-08-18 12:19:51 -07005548#if INTERP_TYPE == INTERP_DBG
buzbee9f601a92011-02-11 17:48:20 -08005549 self->debugIsMethodEntry = debugIsMethodEntry;
Andy McFadden0d615c32010-08-18 12:19:51 -07005550#else
buzbee9f601a92011-02-11 17:48:20 -08005551 self->debugIsMethodEntry = false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005552#endif
5553
5554 /* export state changes */
buzbee9f601a92011-02-11 17:48:20 -08005555 self->interpSave.method = curMethod;
5556 self->interpSave.pc = pc;
5557 self->interpSave.fp = fp;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005558 /* debugTrackedRefStart doesn't change */
buzbee9f601a92011-02-11 17:48:20 -08005559 self->retval = retval; /* need for _entryPoint=ret */
5560 self->nextMode =
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08005561 (INTERP_TYPE == INTERP_STD) ? INTERP_DBG : INTERP_STD;
5562 LOGVV(" meth='%s.%s' pc=0x%x fp=%p\n",
5563 curMethod->clazz->descriptor, curMethod->name,
5564 pc - curMethod->insns, fp);
5565 return true;
5566}
5567