1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* common includes */
18 #include "Dalvik.h"
19 #include "interp/InterpDefs.h"
20 #include "mterp/Mterp.h"
21 #include <math.h> // needed for fmod, fmodf
22
23 /*
24 * Configuration defines. These affect the C implementations, i.e. the
25 * portable interpreter(s) and C stubs.
26 *
27 * Some defines are controlled by the Makefile, e.g.:
28 * WITH_PROFILER
29 * WITH_DEBUGGER
30 * WITH_INSTR_CHECKS
31 * WITH_TRACKREF_CHECKS
32 * EASY_GDB
33 * NDEBUG
34 *
35 * If THREADED_INTERP is not defined, we use a classic "while true / switch"
36 * interpreter. If it is defined, then the tail end of each instruction
37 * handler fetches the next instruction and jumps directly to the handler.
38 * This increases the size of the "Std" interpreter by about 10%, but
39 * provides a speedup of about the same magnitude.
40 *
41 * There's a "hybrid" approach that uses a goto table instead of a switch
42 * statement, avoiding the "is the opcode in range" tests required for switch.
43 * The performance is close to the threaded version, and without the 10%
44 * size increase, but the benchmark results are off enough that it's not
45 * worth adding as a third option.
46 */
47 #define THREADED_INTERP /* threaded vs. while-loop interpreter */
48
49 #ifdef WITH_INSTR_CHECKS /* instruction-level paranoia */
50 # define CHECK_BRANCH_OFFSETS
51 # define CHECK_REGISTER_INDICES
52 #endif
53
54 /*
55 * ARM EABI requires 64-bit alignment for access to 64-bit data types. We
56 * can't just use pointers to copy 64-bit values out of our interpreted
57 * register set, because gcc will generate ldrd/strd.
58 *
59 * The __UNION version copies data in and out of a union. The __MEMCPY
60 * version uses a memcpy() call to do the transfer; gcc is smart enough to
61 * not actually call memcpy(). The __UNION version is very bad on ARM;
62 * it only uses one more instruction than __MEMCPY, but for some reason
63 * gcc thinks it needs separate storage for every instance of the union.
64 * On top of that, it feels the need to zero them out at the start of the
65 * method. Net result is we zero out ~700 bytes of stack space at the top
66 * of the interpreter using ARM STM instructions.
67 */
68 #if defined(__ARM_EABI__)
69 //# define NO_UNALIGN_64__UNION
70 # define NO_UNALIGN_64__MEMCPY
71 #endif
72
73 //#define LOG_INSTR /* verbose debugging */
74 /* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
75
76 /*
77 * Keep a tally of accesses to fields. Currently only works if full DEX
78 * optimization is disabled.
79 */
80 #ifdef PROFILE_FIELD_ACCESS
81 # define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
82 # define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
83 #else
84 # define UPDATE_FIELD_GET(_field) ((void)0)
85 # define UPDATE_FIELD_PUT(_field) ((void)0)
86 #endif
87
88 /*
89 * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
90 *
91 * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
92 *
93 * We don't advance the program counter until we finish an instruction or
94 * branch, because we do want to have to unroll the PC if there's an
95 * exception.
96 */
97 #ifdef CHECK_BRANCH_OFFSETS
98 # define ADJUST_PC(_offset) do { \
99 int myoff = _offset; /* deref only once */ \
100 if (pc + myoff < curMethod->insns || \
101 pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
102 { \
103 char* desc; \
104 desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
105 LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
106 myoff, (int) (pc - curMethod->insns), \
107 curMethod->clazz->descriptor, curMethod->name, desc); \
108 free(desc); \
109 dvmAbort(); \
110 } \
111 pc += myoff; \
112 } while (false)
113 #else
114 # define ADJUST_PC(_offset) (pc += _offset)
115 #endif
116
117 /*
118 * If enabled, log instructions as we execute them.
119 */
120 #ifdef LOG_INSTR
121 # define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
122 # define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
123 # define ILOG(_level, ...) do { \
124 char debugStrBuf[128]; \
125 snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
126 if (curMethod != NULL) \
127 LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
128 self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
129 else \
130 LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
131 self->threadId, debugStrBuf); \
132 } while(false)
133 void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
134 # define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
135 static const char kSpacing[] = " ";
136 #else
137 # define ILOGD(...) ((void)0)
138 # define ILOGV(...) ((void)0)
139 # define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
140 #endif
141
142 /* get a long from an array of u4 */
getLongFromArray(const u4 * ptr,int idx)143 static inline s8 getLongFromArray(const u4* ptr, int idx)
144 {
145 #if defined(NO_UNALIGN_64__UNION)
146 union { s8 ll; u4 parts[2]; } conv;
147
148 ptr += idx;
149 conv.parts[0] = ptr[0];
150 conv.parts[1] = ptr[1];
151 return conv.ll;
152 #elif defined(NO_UNALIGN_64__MEMCPY)
153 s8 val;
154 memcpy(&val, &ptr[idx], 8);
155 return val;
156 #else
157 return *((s8*) &ptr[idx]);
158 #endif
159 }
160
161 /* store a long into an array of u4 */
putLongToArray(u4 * ptr,int idx,s8 val)162 static inline void putLongToArray(u4* ptr, int idx, s8 val)
163 {
164 #if defined(NO_UNALIGN_64__UNION)
165 union { s8 ll; u4 parts[2]; } conv;
166
167 ptr += idx;
168 conv.ll = val;
169 ptr[0] = conv.parts[0];
170 ptr[1] = conv.parts[1];
171 #elif defined(NO_UNALIGN_64__MEMCPY)
172 memcpy(&ptr[idx], &val, 8);
173 #else
174 *((s8*) &ptr[idx]) = val;
175 #endif
176 }
177
178 /* get a double from an array of u4 */
getDoubleFromArray(const u4 * ptr,int idx)179 static inline double getDoubleFromArray(const u4* ptr, int idx)
180 {
181 #if defined(NO_UNALIGN_64__UNION)
182 union { double d; u4 parts[2]; } conv;
183
184 ptr += idx;
185 conv.parts[0] = ptr[0];
186 conv.parts[1] = ptr[1];
187 return conv.d;
188 #elif defined(NO_UNALIGN_64__MEMCPY)
189 double dval;
190 memcpy(&dval, &ptr[idx], 8);
191 return dval;
192 #else
193 return *((double*) &ptr[idx]);
194 #endif
195 }
196
197 /* store a double into an array of u4 */
putDoubleToArray(u4 * ptr,int idx,double dval)198 static inline void putDoubleToArray(u4* ptr, int idx, double dval)
199 {
200 #if defined(NO_UNALIGN_64__UNION)
201 union { double d; u4 parts[2]; } conv;
202
203 ptr += idx;
204 conv.d = dval;
205 ptr[0] = conv.parts[0];
206 ptr[1] = conv.parts[1];
207 #elif defined(NO_UNALIGN_64__MEMCPY)
208 memcpy(&ptr[idx], &dval, 8);
209 #else
210 *((double*) &ptr[idx]) = dval;
211 #endif
212 }
213
214 /*
215 * If enabled, validate the register number on every access. Otherwise,
216 * just do an array access.
217 *
218 * Assumes the existence of "u4* fp".
219 *
220 * "_idx" may be referenced more than once.
221 */
222 #ifdef CHECK_REGISTER_INDICES
223 # define GET_REGISTER(_idx) \
224 ( (_idx) < curMethod->registersSize ? \
225 (fp[(_idx)]) : (assert(!"bad reg"),1969) )
226 # define SET_REGISTER(_idx, _val) \
227 ( (_idx) < curMethod->registersSize ? \
228 (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
229 # define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
230 # define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
231 # define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
232 # define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
233 # define GET_REGISTER_WIDE(_idx) \
234 ( (_idx) < curMethod->registersSize-1 ? \
235 getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
236 # define SET_REGISTER_WIDE(_idx, _val) \
237 ( (_idx) < curMethod->registersSize-1 ? \
238 putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
239 # define GET_REGISTER_FLOAT(_idx) \
240 ( (_idx) < curMethod->registersSize ? \
241 (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
242 # define SET_REGISTER_FLOAT(_idx, _val) \
243 ( (_idx) < curMethod->registersSize ? \
244 (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
245 # define GET_REGISTER_DOUBLE(_idx) \
246 ( (_idx) < curMethod->registersSize-1 ? \
247 getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
248 # define SET_REGISTER_DOUBLE(_idx, _val) \
249 ( (_idx) < curMethod->registersSize-1 ? \
250 putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
251 #else
252 # define GET_REGISTER(_idx) (fp[(_idx)])
253 # define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
254 # define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
255 # define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
256 # define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
257 # define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
258 # define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
259 # define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
260 # define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
261 # define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
262 # define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
263 # define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
264 #endif
265
266 /*
267 * Get 16 bits from the specified offset of the program counter. We always
268 * want to load 16 bits at a time from the instruction stream -- it's more
269 * efficient than 8 and won't have the alignment problems that 32 might.
270 *
271 * Assumes existence of "const u2* pc".
272 */
273 #define FETCH(_offset) (pc[(_offset)])
274
275 /*
276 * Extract instruction byte from 16-bit fetch (_inst is a u2).
277 */
278 #define INST_INST(_inst) ((_inst) & 0xff)
279
280 /*
281 * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
282 */
283 #define INST_A(_inst) (((_inst) >> 8) & 0x0f)
284 #define INST_B(_inst) ((_inst) >> 12)
285
286 /*
287 * Get the 8-bit "vAA" 8-bit register index from the instruction word.
288 * (_inst is u2)
289 */
290 #define INST_AA(_inst) ((_inst) >> 8)
291
292 /*
293 * The current PC must be available to Throwable constructors, e.g.
294 * those created by dvmThrowException(), so that the exception stack
295 * trace can be generated correctly. If we don't do this, the offset
296 * within the current method won't be shown correctly. See the notes
297 * in Exception.c.
298 *
299 * Assumes existence of "u4* fp" and "const u2* pc".
300 */
301 #define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
302
303 /*
304 * Determine if we need to switch to a different interpreter. "_current"
305 * is either INTERP_STD or INTERP_DBG. It should be fixed for a given
306 * interpreter generation file, which should remove the outer conditional
307 * from the following.
308 *
309 * If we're building without debug and profiling support, we never switch.
310 */
311 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
312 # define NEED_INTERP_SWITCH(_current) ( \
313 (_current == INTERP_STD) ? \
314 dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
315 #else
316 # define NEED_INTERP_SWITCH(_current) (false)
317 #endif
318
319 /*
320 * Look up an interface on a class using the cache.
321 */
dvmFindInterfaceMethodInCache(ClassObject * thisClass,u4 methodIdx,const Method * method,DvmDex * methodClassDex)322 INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
323 u4 methodIdx, const Method* method, DvmDex* methodClassDex)
324 {
325 #define ATOMIC_CACHE_CALC \
326 dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
327
328 return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
329 DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
330
331 #undef ATOMIC_CACHE_CALC
332 }
333
334 /*
335 * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
336 * pc has already been exported to the stack.
337 *
338 * Perform additional checks on debug builds.
339 *
340 * Use this to check for NULL when the instruction handler calls into
341 * something that could throw an exception (so we have already called
342 * EXPORT_PC at the top).
343 */
checkForNull(Object * obj)344 static inline bool checkForNull(Object* obj)
345 {
346 if (obj == NULL) {
347 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
348 return false;
349 }
350 #ifdef WITH_EXTRA_OBJECT_VALIDATION
351 if (!dvmIsValidObject(obj)) {
352 LOGE("Invalid object %p\n", obj);
353 dvmAbort();
354 }
355 #endif
356 #ifndef NDEBUG
357 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
358 /* probable heap corruption */
359 LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
360 dvmAbort();
361 }
362 #endif
363 return true;
364 }
365
366 /*
367 * Check to see if "obj" is NULL. If so, export the PC into the stack
368 * frame and throw an exception.
369 *
370 * Perform additional checks on debug builds.
371 *
372 * Use this to check for NULL when the instruction handler doesn't do
373 * anything else that can throw an exception.
374 */
checkForNullExportPC(Object * obj,u4 * fp,const u2 * pc)375 static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
376 {
377 if (obj == NULL) {
378 EXPORT_PC();
379 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
380 return false;
381 }
382 #ifdef WITH_EXTRA_OBJECT_VALIDATION
383 if (!dvmIsValidObject(obj)) {
384 LOGE("Invalid object %p\n", obj);
385 dvmAbort();
386 }
387 #endif
388 #ifndef NDEBUG
389 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
390 /* probable heap corruption */
391 LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
392 dvmAbort();
393 }
394 #endif
395 return true;
396 }
397
398