OSDN Git Service

Fix trace builder to not confuse self-verification.
[android-x86/dalvik.git] / vm / mterp / c / gotoTargets.c
1 /*
2  * C footer.  This has some common code shared by the various targets.
3  */
4
5 /*
6  * Everything from here on is a "goto target".  In the basic interpreter
7  * we jump into these targets and then jump directly to the handler for
8  * next instruction.  Here, these are subroutines that return to the caller.
9  */
10
11 GOTO_TARGET(filledNewArray, bool methodCallRange)
12     {
13         ClassObject* arrayClass;
14         ArrayObject* newArray;
15         u4* contents;
16         char typeCh;
17         int i;
18         u4 arg5;
19
20         EXPORT_PC();
21
22         ref = FETCH(1);             /* class ref */
23         vdst = FETCH(2);            /* first 4 regs -or- range base */
24
25         if (methodCallRange) {
26             vsrc1 = INST_AA(inst);  /* #of elements */
27             arg5 = -1;              /* silence compiler warning */
28             ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
29                 vsrc1, ref, vdst, vdst+vsrc1-1);
30         } else {
31             arg5 = INST_A(inst);
32             vsrc1 = INST_B(inst);   /* #of elements */
33             ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
34                 vsrc1, ref, vdst, arg5);
35         }
36
37         /*
38          * Resolve the array class.
39          */
40         arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
41         if (arrayClass == NULL) {
42             arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
43             if (arrayClass == NULL)
44                 GOTO_exceptionThrown();
45         }
46         /*
47         if (!dvmIsArrayClass(arrayClass)) {
48             dvmThrowException("Ljava/lang/RuntimeError;",
49                 "filled-new-array needs array class");
50             GOTO_exceptionThrown();
51         }
52         */
53         /* verifier guarantees this is an array class */
54         assert(dvmIsArrayClass(arrayClass));
55         assert(dvmIsClassInitialized(arrayClass));
56
57         /*
58          * Create an array of the specified type.
59          */
60         LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
61         typeCh = arrayClass->descriptor[1];
62         if (typeCh == 'D' || typeCh == 'J') {
63             /* category 2 primitives not allowed */
64             dvmThrowException("Ljava/lang/RuntimeError;",
65                 "bad filled array req");
66             GOTO_exceptionThrown();
67         } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
68             /* TODO: requires multiple "fill in" loops with different widths */
69             LOGE("non-int primitives not implemented\n");
70             dvmThrowException("Ljava/lang/InternalError;",
71                 "filled-new-array not implemented for anything but 'int'");
72             GOTO_exceptionThrown();
73         }
74
75         newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
76         if (newArray == NULL)
77             GOTO_exceptionThrown();
78
79         /*
80          * Fill in the elements.  It's legal for vsrc1 to be zero.
81          */
82         contents = (u4*) newArray->contents;
83         if (methodCallRange) {
84             for (i = 0; i < vsrc1; i++)
85                 contents[i] = GET_REGISTER(vdst+i);
86         } else {
87             assert(vsrc1 <= 5);
88             if (vsrc1 == 5) {
89                 contents[4] = GET_REGISTER(arg5);
90                 vsrc1--;
91             }
92             for (i = 0; i < vsrc1; i++) {
93                 contents[i] = GET_REGISTER(vdst & 0x0f);
94                 vdst >>= 4;
95             }
96         }
97
98         retval.l = newArray;
99     }
100     FINISH(3);
101 GOTO_TARGET_END
102
103
104 GOTO_TARGET(invokeVirtual, bool methodCallRange)
105     {
106         Method* baseMethod;
107         Object* thisPtr;
108
109         EXPORT_PC();
110
111         vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
112         ref = FETCH(1);             /* method ref */
113         vdst = FETCH(2);            /* 4 regs -or- first reg */
114
115         /*
116          * The object against which we are executing a method is always
117          * in the first argument.
118          */
119         if (methodCallRange) {
120             assert(vsrc1 > 0);
121             ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
122                 vsrc1, ref, vdst, vdst+vsrc1-1);
123             thisPtr = (Object*) GET_REGISTER(vdst);
124         } else {
125             assert((vsrc1>>4) > 0);
126             ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
127                 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
128             thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
129         }
130
131         if (!checkForNull(thisPtr))
132             GOTO_exceptionThrown();
133
134         /*
135          * Resolve the method.  This is the correct method for the static
136          * type of the object.  We also verify access permissions here.
137          */
138         baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
139         if (baseMethod == NULL) {
140             baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
141             if (baseMethod == NULL) {
142                 ILOGV("+ unknown method or access denied\n");
143                 GOTO_exceptionThrown();
144             }
145         }
146
147         /*
148          * Combine the object we found with the vtable offset in the
149          * method.
150          */
151         assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
152         methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
153
154 #if 0
155         if (dvmIsAbstractMethod(methodToCall)) {
156             /*
157              * This can happen if you create two classes, Base and Sub, where
158              * Sub is a sub-class of Base.  Declare a protected abstract
159              * method foo() in Base, and invoke foo() from a method in Base.
160              * Base is an "abstract base class" and is never instantiated
161              * directly.  Now, Override foo() in Sub, and use Sub.  This
162              * Works fine unless Sub stops providing an implementation of
163              * the method.
164              */
165             dvmThrowException("Ljava/lang/AbstractMethodError;",
166                 "abstract method not implemented");
167             GOTO_exceptionThrown();
168         }
169 #else
170         assert(!dvmIsAbstractMethod(methodToCall) ||
171             methodToCall->nativeFunc != NULL);
172 #endif
173
174         LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
175             baseMethod->clazz->descriptor, baseMethod->name,
176             (u4) baseMethod->methodIndex,
177             methodToCall->clazz->descriptor, methodToCall->name);
178         assert(methodToCall != NULL);
179
180 #if 0
181         if (vsrc1 != methodToCall->insSize) {
182             LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
183                 baseMethod->clazz->descriptor, baseMethod->name,
184                 (u4) baseMethod->methodIndex,
185                 methodToCall->clazz->descriptor, methodToCall->name);
186             //dvmDumpClass(baseMethod->clazz);
187             //dvmDumpClass(methodToCall->clazz);
188             dvmDumpAllClasses(0);
189         }
190 #endif
191
192         GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
193     }
194 GOTO_TARGET_END
195
196 GOTO_TARGET(invokeSuper, bool methodCallRange)
197     {
198         Method* baseMethod;
199         u2 thisReg;
200
201         EXPORT_PC();
202
203         vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
204         ref = FETCH(1);             /* method ref */
205         vdst = FETCH(2);            /* 4 regs -or- first reg */
206
207         if (methodCallRange) {
208             ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
209                 vsrc1, ref, vdst, vdst+vsrc1-1);
210             thisReg = vdst;
211         } else {
212             ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
213                 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
214             thisReg = vdst & 0x0f;
215         }
216         /* impossible in well-formed code, but we must check nevertheless */
217         if (!checkForNull((Object*) GET_REGISTER(thisReg)))
218             GOTO_exceptionThrown();
219
220         /*
221          * Resolve the method.  This is the correct method for the static
222          * type of the object.  We also verify access permissions here.
223          * The first arg to dvmResolveMethod() is just the referring class
224          * (used for class loaders and such), so we don't want to pass
225          * the superclass into the resolution call.
226          */
227         baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
228         if (baseMethod == NULL) {
229             baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
230             if (baseMethod == NULL) {
231                 ILOGV("+ unknown method or access denied\n");
232                 GOTO_exceptionThrown();
233             }
234         }
235
236         /*
237          * Combine the object we found with the vtable offset in the
238          * method's class.
239          *
240          * We're using the current method's class' superclass, not the
241          * superclass of "this".  This is because we might be executing
242          * in a method inherited from a superclass, and we want to run
243          * in that class' superclass.
244          */
245         if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
246             /*
247              * Method does not exist in the superclass.  Could happen if
248              * superclass gets updated.
249              */
250             dvmThrowException("Ljava/lang/NoSuchMethodError;",
251                 baseMethod->name);
252             GOTO_exceptionThrown();
253         }
254         methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
255 #if 0
256         if (dvmIsAbstractMethod(methodToCall)) {
257             dvmThrowException("Ljava/lang/AbstractMethodError;",
258                 "abstract method not implemented");
259             GOTO_exceptionThrown();
260         }
261 #else
262         assert(!dvmIsAbstractMethod(methodToCall) ||
263             methodToCall->nativeFunc != NULL);
264 #endif
265         LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
266             baseMethod->clazz->descriptor, baseMethod->name,
267             methodToCall->clazz->descriptor, methodToCall->name);
268         assert(methodToCall != NULL);
269
270         GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
271     }
272 GOTO_TARGET_END
273
274 GOTO_TARGET(invokeInterface, bool methodCallRange)
275     {
276         Object* thisPtr;
277         ClassObject* thisClass;
278
279         EXPORT_PC();
280
281         vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
282         ref = FETCH(1);             /* method ref */
283         vdst = FETCH(2);            /* 4 regs -or- first reg */
284
285         /*
286          * The object against which we are executing a method is always
287          * in the first argument.
288          */
289         if (methodCallRange) {
290             assert(vsrc1 > 0);
291             ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
292                 vsrc1, ref, vdst, vdst+vsrc1-1);
293             thisPtr = (Object*) GET_REGISTER(vdst);
294         } else {
295             assert((vsrc1>>4) > 0);
296             ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
297                 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
298             thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
299         }
300         if (!checkForNull(thisPtr))
301             GOTO_exceptionThrown();
302
303         thisClass = thisPtr->clazz;
304
305         /*
306          * Given a class and a method index, find the Method* with the
307          * actual code we want to execute.
308          */
309         methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
310                         methodClassDex);
311         if (methodToCall == NULL) {
312             assert(dvmCheckException(self));
313             GOTO_exceptionThrown();
314         }
315
316         GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
317     }
318 GOTO_TARGET_END
319
320 GOTO_TARGET(invokeDirect, bool methodCallRange)
321     {
322         u2 thisReg;
323
324         vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
325         ref = FETCH(1);             /* method ref */
326         vdst = FETCH(2);            /* 4 regs -or- first reg */
327
328         EXPORT_PC();
329
330         if (methodCallRange) {
331             ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
332                 vsrc1, ref, vdst, vdst+vsrc1-1);
333             thisReg = vdst;
334         } else {
335             ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
336                 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
337             thisReg = vdst & 0x0f;
338         }
339         if (!checkForNull((Object*) GET_REGISTER(thisReg)))
340             GOTO_exceptionThrown();
341
342         methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
343         if (methodToCall == NULL) {
344             methodToCall = dvmResolveMethod(curMethod->clazz, ref,
345                             METHOD_DIRECT);
346             if (methodToCall == NULL) {
347                 ILOGV("+ unknown direct method\n");     // should be impossible
348                 GOTO_exceptionThrown();
349             }
350         }
351         GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
352     }
353 GOTO_TARGET_END
354
355 GOTO_TARGET(invokeStatic, bool methodCallRange)
356     vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
357     ref = FETCH(1);             /* method ref */
358     vdst = FETCH(2);            /* 4 regs -or- first reg */
359
360     EXPORT_PC();
361
362     if (methodCallRange)
363         ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
364             vsrc1, ref, vdst, vdst+vsrc1-1);
365     else
366         ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
367             vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
368
369     methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
370     if (methodToCall == NULL) {
371         methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
372         if (methodToCall == NULL) {
373             ILOGV("+ unknown method\n");
374             GOTO_exceptionThrown();
375         }
376     }
377     GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
378 GOTO_TARGET_END
379
380 GOTO_TARGET(invokeVirtualQuick, bool methodCallRange)
381     {
382         Object* thisPtr;
383
384         EXPORT_PC();
385
386         vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
387         ref = FETCH(1);             /* vtable index */
388         vdst = FETCH(2);            /* 4 regs -or- first reg */
389
390         /*
391          * The object against which we are executing a method is always
392          * in the first argument.
393          */
394         if (methodCallRange) {
395             assert(vsrc1 > 0);
396             ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
397                 vsrc1, ref, vdst, vdst+vsrc1-1);
398             thisPtr = (Object*) GET_REGISTER(vdst);
399         } else {
400             assert((vsrc1>>4) > 0);
401             ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
402                 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
403             thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
404         }
405
406         if (!checkForNull(thisPtr))
407             GOTO_exceptionThrown();
408
409         /*
410          * Combine the object we found with the vtable offset in the
411          * method.
412          */
413         assert(ref < thisPtr->clazz->vtableCount);
414         methodToCall = thisPtr->clazz->vtable[ref];
415
416 #if 0
417         if (dvmIsAbstractMethod(methodToCall)) {
418             dvmThrowException("Ljava/lang/AbstractMethodError;",
419                 "abstract method not implemented");
420             GOTO_exceptionThrown();
421         }
422 #else
423         assert(!dvmIsAbstractMethod(methodToCall) ||
424             methodToCall->nativeFunc != NULL);
425 #endif
426
427         LOGVV("+++ virtual[%d]=%s.%s\n",
428             ref, methodToCall->clazz->descriptor, methodToCall->name);
429         assert(methodToCall != NULL);
430
431         GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
432     }
433 GOTO_TARGET_END
434
435 GOTO_TARGET(invokeSuperQuick, bool methodCallRange)
436     {
437         u2 thisReg;
438
439         EXPORT_PC();
440
441         vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
442         ref = FETCH(1);             /* vtable index */
443         vdst = FETCH(2);            /* 4 regs -or- first reg */
444
445         if (methodCallRange) {
446             ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
447                 vsrc1, ref, vdst, vdst+vsrc1-1);
448             thisReg = vdst;
449         } else {
450             ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
451                 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
452             thisReg = vdst & 0x0f;
453         }
454         /* impossible in well-formed code, but we must check nevertheless */
455         if (!checkForNull((Object*) GET_REGISTER(thisReg)))
456             GOTO_exceptionThrown();
457
458 #if 0   /* impossible in optimized + verified code */
459         if (ref >= curMethod->clazz->super->vtableCount) {
460             dvmThrowException("Ljava/lang/NoSuchMethodError;", NULL);
461             GOTO_exceptionThrown();
462         }
463 #else
464         assert(ref < curMethod->clazz->super->vtableCount);
465 #endif
466
467         /*
468          * Combine the object we found with the vtable offset in the
469          * method's class.
470          *
471          * We're using the current method's class' superclass, not the
472          * superclass of "this".  This is because we might be executing
473          * in a method inherited from a superclass, and we want to run
474          * in the method's class' superclass.
475          */
476         methodToCall = curMethod->clazz->super->vtable[ref];
477
478 #if 0
479         if (dvmIsAbstractMethod(methodToCall)) {
480             dvmThrowException("Ljava/lang/AbstractMethodError;",
481                 "abstract method not implemented");
482             GOTO_exceptionThrown();
483         }
484 #else
485         assert(!dvmIsAbstractMethod(methodToCall) ||
486             methodToCall->nativeFunc != NULL);
487 #endif
488         LOGVV("+++ super-virtual[%d]=%s.%s\n",
489             ref, methodToCall->clazz->descriptor, methodToCall->name);
490         assert(methodToCall != NULL);
491
492         GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
493     }
494 GOTO_TARGET_END
495
496
497
498     /*
499      * General handling for return-void, return, and return-wide.  Put the
500      * return value in "retval" before jumping here.
501      */
502 GOTO_TARGET(returnFromMethod)
503     {
504         StackSaveArea* saveArea;
505
506         /*
507          * We must do this BEFORE we pop the previous stack frame off, so
508          * that the GC can see the return value (if any) in the local vars.
509          *
510          * Since this is now an interpreter switch point, we must do it before
511          * we do anything at all.
512          */
513         PERIODIC_CHECKS(kInterpEntryReturn, 0);
514
515         ILOGV("> retval=0x%llx (leaving %s.%s %s)",
516             retval.j, curMethod->clazz->descriptor, curMethod->name,
517             curMethod->shorty);
518         //DUMP_REGS(curMethod, fp);
519
520         saveArea = SAVEAREA_FROM_FP(fp);
521
522 #ifdef EASY_GDB
523         debugSaveArea = saveArea;
524 #endif
525 #if (INTERP_TYPE == INTERP_DBG) && defined(WITH_PROFILER)
526         TRACE_METHOD_EXIT(self, curMethod);
527 #endif
528
529         /* back up to previous frame and see if we hit a break */
530         fp = saveArea->prevFrame;
531         assert(fp != NULL);
532         if (dvmIsBreakFrame(fp)) {
533             /* bail without popping the method frame from stack */
534             LOGVV("+++ returned into break frame\n");
535             GOTO_bail();
536         }
537
538         /* update thread FP, and reset local variables */
539         self->curFrame = fp;
540         curMethod = SAVEAREA_FROM_FP(fp)->method;
541         //methodClass = curMethod->clazz;
542         methodClassDex = curMethod->clazz->pDvmDex;
543         pc = saveArea->savedPc;
544         ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
545             curMethod->name, curMethod->shorty);
546
547         /* use FINISH on the caller's invoke instruction */
548         //u2 invokeInstr = INST_INST(FETCH(0));
549         if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
550             invokeInstr <= OP_INVOKE_INTERFACE*/)
551         {
552             FINISH(3);
553         } else {
554             //LOGE("Unknown invoke instr %02x at %d\n",
555             //    invokeInstr, (int) (pc - curMethod->insns));
556             assert(false);
557         }
558     }
559 GOTO_TARGET_END
560
561
562     /*
563      * Jump here when the code throws an exception.
564      *
565      * By the time we get here, the Throwable has been created and the stack
566      * trace has been saved off.
567      */
568 GOTO_TARGET(exceptionThrown)
569     {
570         Object* exception;
571         int catchRelPc;
572
573         /*
574          * Since this is now an interpreter switch point, we must do it before
575          * we do anything at all.
576          */
577         PERIODIC_CHECKS(kInterpEntryThrow, 0);
578
579 #if defined(WITH_JIT)
580         // Something threw during trace selection - abort the current trace
581         if (interpState->jitState == kJitTSelect) {
582             interpState->jitState = kJitTSelectEnd;
583         }
584 #endif
585         /*
586          * We save off the exception and clear the exception status.  While
587          * processing the exception we might need to load some Throwable
588          * classes, and we don't want class loader exceptions to get
589          * confused with this one.
590          */
591         assert(dvmCheckException(self));
592         exception = dvmGetException(self);
593         dvmAddTrackedAlloc(exception, self);
594         dvmClearException(self);
595
596         LOGV("Handling exception %s at %s:%d\n",
597             exception->clazz->descriptor, curMethod->name,
598             dvmLineNumFromPC(curMethod, pc - curMethod->insns));
599
600 #if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
601         /*
602          * Tell the debugger about it.
603          *
604          * TODO: if the exception was thrown by interpreted code, control
605          * fell through native, and then back to us, we will report the
606          * exception at the point of the throw and again here.  We can avoid
607          * this by not reporting exceptions when we jump here directly from
608          * the native call code above, but then we won't report exceptions
609          * that were thrown *from* the JNI code (as opposed to *through* it).
610          *
611          * The correct solution is probably to ignore from-native exceptions
612          * here, and have the JNI exception code do the reporting to the
613          * debugger.
614          */
615         if (gDvm.debuggerActive) {
616             void* catchFrame;
617             catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
618                         exception, true, &catchFrame);
619             dvmDbgPostException(fp, pc - curMethod->insns, catchFrame,
620                 catchRelPc, exception);
621         }
622 #endif
623
624         /*
625          * We need to unroll to the catch block or the nearest "break"
626          * frame.
627          *
628          * A break frame could indicate that we have reached an intermediate
629          * native call, or have gone off the top of the stack and the thread
630          * needs to exit.  Either way, we return from here, leaving the
631          * exception raised.
632          *
633          * If we do find a catch block, we want to transfer execution to
634          * that point.
635          */
636         catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
637                     exception, false, (void*)&fp);
638
639         /*
640          * Restore the stack bounds after an overflow.  This isn't going to
641          * be correct in all circumstances, e.g. if JNI code devours the
642          * exception this won't happen until some other exception gets
643          * thrown.  If the code keeps pushing the stack bounds we'll end
644          * up aborting the VM.
645          *
646          * Note we want to do this *after* the call to dvmFindCatchBlock,
647          * because that may need extra stack space to resolve exception
648          * classes (e.g. through a class loader).
649          */
650         if (self->stackOverflowed)
651             dvmCleanupStackOverflow(self);
652
653         if (catchRelPc < 0) {
654             /* falling through to JNI code or off the bottom of the stack */
655 #if DVM_SHOW_EXCEPTION >= 2
656             LOGD("Exception %s from %s:%d not caught locally\n",
657                 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
658                 dvmLineNumFromPC(curMethod, pc - curMethod->insns));
659 #endif
660             dvmSetException(self, exception);
661             dvmReleaseTrackedAlloc(exception, self);
662             GOTO_bail();
663         }
664
665 #if DVM_SHOW_EXCEPTION >= 3
666         {
667             const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
668             LOGD("Exception %s thrown from %s:%d to %s:%d\n",
669                 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
670                 dvmLineNumFromPC(curMethod, pc - curMethod->insns),
671                 dvmGetMethodSourceFile(catchMethod),
672                 dvmLineNumFromPC(catchMethod, catchRelPc));
673         }
674 #endif
675
676         /*
677          * Adjust local variables to match self->curFrame and the
678          * updated PC.
679          */
680         //fp = (u4*) self->curFrame;
681         curMethod = SAVEAREA_FROM_FP(fp)->method;
682         //methodClass = curMethod->clazz;
683         methodClassDex = curMethod->clazz->pDvmDex;
684         pc = curMethod->insns + catchRelPc;
685         ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
686             curMethod->name, curMethod->shorty);
687         DUMP_REGS(curMethod, fp, false);            // show all regs
688
689         /*
690          * Restore the exception if the handler wants it.
691          *
692          * The Dalvik spec mandates that, if an exception handler wants to
693          * do something with the exception, the first instruction executed
694          * must be "move-exception".  We can pass the exception along
695          * through the thread struct, and let the move-exception instruction
696          * clear it for us.
697          *
698          * If the handler doesn't call move-exception, we don't want to
699          * finish here with an exception still pending.
700          */
701         if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
702             dvmSetException(self, exception);
703
704         dvmReleaseTrackedAlloc(exception, self);
705         FINISH(0);
706     }
707 GOTO_TARGET_END
708
709
710     /*
711      * General handling for invoke-{virtual,super,direct,static,interface},
712      * including "quick" variants.
713      *
714      * Set "methodToCall" to the Method we're calling, and "methodCallRange"
715      * depending on whether this is a "/range" instruction.
716      *
717      * For a range call:
718      *  "vsrc1" holds the argument count (8 bits)
719      *  "vdst" holds the first argument in the range
720      * For a non-range call:
721      *  "vsrc1" holds the argument count (4 bits) and the 5th argument index
722      *  "vdst" holds four 4-bit register indices
723      *
724      * The caller must EXPORT_PC before jumping here, because any method
725      * call can throw a stack overflow exception.
726      */
727 GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
728     u2 count, u2 regs)
729     {
730         STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
731
732         //printf("range=%d call=%p count=%d regs=0x%04x\n",
733         //    methodCallRange, methodToCall, count, regs);
734         //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
735         //    methodToCall->name, methodToCall->shorty);
736
737         u4* outs;
738         int i;
739
740         /*
741          * Copy args.  This may corrupt vsrc1/vdst.
742          */
743         if (methodCallRange) {
744             // could use memcpy or a "Duff's device"; most functions have
745             // so few args it won't matter much
746             assert(vsrc1 <= curMethod->outsSize);
747             assert(vsrc1 == methodToCall->insSize);
748             outs = OUTS_FROM_FP(fp, vsrc1);
749             for (i = 0; i < vsrc1; i++)
750                 outs[i] = GET_REGISTER(vdst+i);
751         } else {
752             u4 count = vsrc1 >> 4;
753
754             assert(count <= curMethod->outsSize);
755             assert(count == methodToCall->insSize);
756             assert(count <= 5);
757
758             outs = OUTS_FROM_FP(fp, count);
759 #if 0
760             if (count == 5) {
761                 outs[4] = GET_REGISTER(vsrc1 & 0x0f);
762                 count--;
763             }
764             for (i = 0; i < (int) count; i++) {
765                 outs[i] = GET_REGISTER(vdst & 0x0f);
766                 vdst >>= 4;
767             }
768 #else
769             // This version executes fewer instructions but is larger
770             // overall.  Seems to be a teensy bit faster.
771             assert((vdst >> 16) == 0);  // 16 bits -or- high 16 bits clear
772             switch (count) {
773             case 5:
774                 outs[4] = GET_REGISTER(vsrc1 & 0x0f);
775             case 4:
776                 outs[3] = GET_REGISTER(vdst >> 12);
777             case 3:
778                 outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
779             case 2:
780                 outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
781             case 1:
782                 outs[0] = GET_REGISTER(vdst & 0x0f);
783             default:
784                 ;
785             }
786 #endif
787         }
788     }
789
790     /*
791      * (This was originally a "goto" target; I've kept it separate from the
792      * stuff above in case we want to refactor things again.)
793      *
794      * At this point, we have the arguments stored in the "outs" area of
795      * the current method's stack frame, and the method to call in
796      * "methodToCall".  Push a new stack frame.
797      */
798     {
799         StackSaveArea* newSaveArea;
800         u4* newFp;
801
802         ILOGV("> %s%s.%s %s",
803             dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
804             methodToCall->clazz->descriptor, methodToCall->name,
805             methodToCall->shorty);
806
807         newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
808         newSaveArea = SAVEAREA_FROM_FP(newFp);
809
810         /* verify that we have enough space */
811         if (true) {
812             u1* bottom;
813             bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
814             if (bottom < self->interpStackEnd) {
815                 /* stack overflow */
816                 LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
817                     self->interpStackStart, self->interpStackEnd, bottom,
818                     (u1*) fp - bottom, self->interpStackSize,
819                     methodToCall->name);
820                 dvmHandleStackOverflow(self, methodToCall);
821                 assert(dvmCheckException(self));
822                 GOTO_exceptionThrown();
823             }
824             //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n",
825             //    fp, newFp, newSaveArea, bottom);
826         }
827
828 #ifdef LOG_INSTR
829         if (methodToCall->registersSize > methodToCall->insSize) {
830             /*
831              * This makes valgrind quiet when we print registers that
832              * haven't been initialized.  Turn it off when the debug
833              * messages are disabled -- we want valgrind to report any
834              * used-before-initialized issues.
835              */
836             memset(newFp, 0xcc,
837                 (methodToCall->registersSize - methodToCall->insSize) * 4);
838         }
839 #endif
840
841 #ifdef EASY_GDB
842         newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
843 #endif
844         newSaveArea->prevFrame = fp;
845         newSaveArea->savedPc = pc;
846 #if defined(WITH_JIT)
847         newSaveArea->returnAddr = 0;
848 #endif
849         newSaveArea->method = methodToCall;
850
851         if (!dvmIsNativeMethod(methodToCall)) {
852             /*
853              * "Call" interpreted code.  Reposition the PC, update the
854              * frame pointer and other local state, and continue.
855              */
856             curMethod = methodToCall;
857             methodClassDex = curMethod->clazz->pDvmDex;
858             pc = methodToCall->insns;
859             fp = self->curFrame = newFp;
860 #ifdef EASY_GDB
861             debugSaveArea = SAVEAREA_FROM_FP(newFp);
862 #endif
863 #if INTERP_TYPE == INTERP_DBG
864             debugIsMethodEntry = true;              // profiling, debugging
865 #endif
866             ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
867                 curMethod->name, curMethod->shorty);
868             DUMP_REGS(curMethod, fp, true);         // show input args
869             FINISH(0);                              // jump to method start
870         } else {
871             /* set this up for JNI locals, even if not a JNI native */
872 #ifdef USE_INDIRECT_REF
873             newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
874 #else
875             newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
876 #endif
877
878             self->curFrame = newFp;
879
880             DUMP_REGS(methodToCall, newFp, true);   // show input args
881
882 #if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
883             if (gDvm.debuggerActive) {
884                 dvmDbgPostLocationEvent(methodToCall, -1,
885                     dvmGetThisPtr(curMethod, fp), DBG_METHOD_ENTRY);
886             }
887 #endif
888 #if (INTERP_TYPE == INTERP_DBG) && defined(WITH_PROFILER)
889             TRACE_METHOD_ENTER(self, methodToCall);
890 #endif
891
892             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
893                 methodToCall->name, methodToCall->shorty);
894
895             /*
896              * Jump through native call bridge.  Because we leave no
897              * space for locals on native calls, "newFp" points directly
898              * to the method arguments.
899              */
900             (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
901
902 #if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
903             if (gDvm.debuggerActive) {
904                 dvmDbgPostLocationEvent(methodToCall, -1,
905                     dvmGetThisPtr(curMethod, fp), DBG_METHOD_EXIT);
906             }
907 #endif
908 #if (INTERP_TYPE == INTERP_DBG) && defined(WITH_PROFILER)
909             TRACE_METHOD_EXIT(self, methodToCall);
910 #endif
911
912             /* pop frame off */
913             dvmPopJniLocals(self, newSaveArea);
914             self->curFrame = fp;
915
916             /*
917              * If the native code threw an exception, or interpreted code
918              * invoked by the native call threw one and nobody has cleared
919              * it, jump to our local exception handling.
920              */
921             if (dvmCheckException(self)) {
922                 LOGV("Exception thrown by/below native code\n");
923                 GOTO_exceptionThrown();
924             }
925
926             ILOGD("> retval=0x%llx (leaving native)", retval.j);
927             ILOGD("> (return from native %s.%s to %s.%s %s)",
928                 methodToCall->clazz->descriptor, methodToCall->name,
929                 curMethod->clazz->descriptor, curMethod->name,
930                 curMethod->shorty);
931
932             //u2 invokeInstr = INST_INST(FETCH(0));
933             if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
934                 invokeInstr <= OP_INVOKE_INTERFACE*/)
935             {
936                 FINISH(3);
937             } else {
938                 //LOGE("Unknown invoke instr %02x at %d\n",
939                 //    invokeInstr, (int) (pc - curMethod->insns));
940                 assert(false);
941             }
942         }
943     }
944     assert(false);      // should not get here
945 GOTO_TARGET_END