1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * C footer.  This has some common code shared by the various targets.
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Everything from here on is a "goto target".  In the basic interpreter
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we jump into these targets and then jump directly to the handler for
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * next instruction.  Here, these are subroutines that return to the caller.
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
11ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(filledNewArray, bool methodCallRange, bool)
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* arrayClass;
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayObject* newArray;
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4* contents;
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char typeCh;
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int i;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 arg5;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ref = FETCH(1);             /* class ref */
23ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vdst = FETCH(2);            /* first 4 regs -or- range base */
24ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes
25ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        if (methodCallRange) {
26ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            vsrc1 = INST_AA(inst);  /* #of elements */
27ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            arg5 = -1;              /* silence compiler warning */
28ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
31ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            arg5 = INST_A(inst);
32ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            vsrc1 = INST_B(inst);   /* #of elements */
33ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
34ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes               vsrc1, ref, vdst, arg5);
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Resolve the array class.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (arrayClass == NULL) {
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arrayClass == NULL)
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsArrayClass(arrayClass)) {
48d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowRuntimeException(
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "filled-new-array needs array class");
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        */
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verifier guarantees this is an array class */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmIsArrayClass(arrayClass));
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmIsClassInitialized(arrayClass));
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Create an array of the specified type.
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
6060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ filled-new-array type is '%s'", arrayClass->descriptor);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        typeCh = arrayClass->descriptor[1];
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (typeCh == 'D' || typeCh == 'J') {
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* category 2 primitives not allowed */
64d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowRuntimeException("bad filled array req");
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* TODO: requires multiple "fill in" loops with different widths */
68c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("non-int primitives not implemented");
6970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowInternalError(
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "filled-new-array not implemented for anything but 'int'");
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newArray == NULL)
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Fill in the elements.  It's legal for vsrc1 to be zero.
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
81cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro        contents = (u4*)(void*)newArray->contents;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < vsrc1; i++)
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                contents[i] = GET_REGISTER(vdst+i);
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 <= 5);
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (vsrc1 == 5) {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                contents[4] = GET_REGISTER(arg5);
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1--;
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < vsrc1; i++) {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                contents[i] = GET_REGISTER(vdst & 0x0f);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vdst >>= 4;
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
96364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        if (typeCh == 'L' || typeCh == '[') {
97364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            dvmWriteBarrierArray(newArray, 0, newArray->length);
98364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10092a3b69286a757afff76402d8a0d5ec04d7f177cCarl Shapiro        retval.l = (Object*)newArray;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
102ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    FINISH(3);
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeVirtual, bool methodCallRange, bool)
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* baseMethod;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* thisPtr;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
114ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ref = FETCH(1);             /* method ref */
115ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vdst = FETCH(2);            /* 4 regs -or- first reg */
116ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes
117ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        /*
118ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes         * The object against which we are executing a method is always
119ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes         * in the first argument.
120ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes         */
121ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        if (methodCallRange) {
122ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            assert(vsrc1 > 0);
123ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst);
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
127ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            assert((vsrc1>>4) > 0);
128ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
129ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
130ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull(thisPtr))
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Resolve the method.  This is the correct method for the static
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * type of the object.  We also verify access permissions here.
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (baseMethod == NULL) {
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (baseMethod == NULL) {
14460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                ILOGV("+ unknown method or access denied");
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method.
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1569a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB)
1579a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->methodToCall = methodToCall;
1589a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->callsiteClass = thisPtr->clazz;
1597a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
1607a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This can happen if you create two classes, Base and Sub, where
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Sub is a sub-class of Base.  Declare a protected abstract
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method foo() in Base, and invoke foo() from a method in Base.
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Base is an "abstract base class" and is never instantiated
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * directly.  Now, Override foo() in Sub, and use Sub.  This
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Works fine unless Sub stops providing an implementation of
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the method.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
172d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowAbstractMethodError("abstract method not implemented");
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ base=%s.%s virtual[%d]=%s.%s",
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod->clazz->descriptor, baseMethod->name,
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (u4) baseMethod->methodIndex,
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->clazz->descriptor, methodToCall->name);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (vsrc1 != methodToCall->insSize) {
188e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s",
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                baseMethod->clazz->descriptor, baseMethod->name,
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) baseMethod->methodIndex,
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                methodToCall->clazz->descriptor, methodToCall->name);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmDumpClass(baseMethod->clazz);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmDumpClass(methodToCall->clazz);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpAllClasses(0);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeSuper, bool methodCallRange)
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* baseMethod;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 thisReg;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
210ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ref = FETCH(1);             /* method ref */
211ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vdst = FETCH(2);            /* 4 regs -or- first reg */
212ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes
213ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        if (methodCallRange) {
214ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
218ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
219ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
220ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            thisReg = vdst & 0x0f;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
22271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* impossible in well-formed code, but we must check nevertheless */
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Resolve the method.  This is the correct method for the static
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * type of the object.  We also verify access permissions here.
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The first arg to dvmResolveMethod() is just the referring class
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (used for class loaders and such), so we don't want to pass
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the superclass into the resolution call.
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (baseMethod == NULL) {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (baseMethod == NULL) {
23860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                ILOGV("+ unknown method or access denied");
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method's class.
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're using the current method's class' superclass, not the
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * superclass of "this".  This is because we might be executing
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in a method inherited from a superclass, and we want to run
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in that class' superclass.
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Method does not exist in the superclass.  Could happen if
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * superclass gets updated.
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
257d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowNoSuchMethodError(baseMethod->name);
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
2619a3147c7412f4794434b4c2604aa2ba784867774buzbee
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
264d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowAbstractMethodError("abstract method not implemented");
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
27160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ base=%s.%s super-virtual=%s.%s",
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod->clazz->descriptor, baseMethod->name,
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->clazz->descriptor, methodToCall->name);
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeInterface, bool methodCallRange)
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* thisPtr;
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* thisClass;
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
287ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
288ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ref = FETCH(1);             /* method ref */
289ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vdst = FETCH(2);            /* 4 regs -or- first reg */
290ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes
291ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        /*
292ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes         * The object against which we are executing a method is always
293ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes         * in the first argument.
294ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes         */
295ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        if (methodCallRange) {
296ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            assert(vsrc1 > 0);
297ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst);
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
301ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            assert((vsrc1>>4) > 0);
302ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
303ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
304ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
30671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull(thisPtr))
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        thisClass = thisPtr->clazz;
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Given a class and a method index, find the Method* with the
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * actual code we want to execute.
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        methodClassDex);
3189a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB)
3199a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->callsiteClass = thisClass;
3209a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->methodToCall = methodToCall;
3219a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall == NULL) {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeDirect, bool methodCallRange)
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 thisReg;
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
337ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
338ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ref = FETCH(1);             /* method ref */
339ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        vdst = FETCH(2);            /* 4 regs -or- first reg */
340ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes
341ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        if (methodCallRange) {
342ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst;
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
346ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
347ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
348ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            thisReg = vdst & 0x0f;
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
35071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall == NULL) {
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall = dvmResolveMethod(curMethod->clazz, ref,
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            METHOD_DIRECT);
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (methodToCall == NULL) {
35960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                ILOGV("+ unknown direct method");     // should be impossible
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
367ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeStatic, bool methodCallRange)
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    EXPORT_PC();
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
370ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
371ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    ref = FETCH(1);             /* method ref */
372ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    vdst = FETCH(2);            /* 4 regs -or- first reg */
37371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao
374ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    if (methodCallRange)
375ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
376ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            vsrc1, ref, vdst, vdst+vsrc1-1);
377ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes    else
378ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
379ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes            vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodToCall == NULL) {
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall == NULL) {
38560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            ILOGV("+ unknown method");
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
388dd6e87095071e4e987910732062545f7303023e5Ben Cheng
3899a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB)
390dd6e87095071e4e987910732062545f7303023e5Ben Cheng        /*
391dd6e87095071e4e987910732062545f7303023e5Ben Cheng         * The JIT needs dvmDexGetResolvedMethod() to return non-null.
3929a3147c7412f4794434b4c2604aa2ba784867774buzbee         * Include the check if this code is being used as a stub
3939a3147c7412f4794434b4c2604aa2ba784867774buzbee         * called from the assembly interpreter.
394dd6e87095071e4e987910732062545f7303023e5Ben Cheng         */
3959a3147c7412f4794434b4c2604aa2ba784867774buzbee        if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) &&
3969a3147c7412f4794434b4c2604aa2ba784867774buzbee            (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) {
397dd6e87095071e4e987910732062545f7303023e5Ben Cheng            /* Class initialization is still ongoing */
3989a3147c7412f4794434b4c2604aa2ba784867774buzbee            dvmJitEndTraceSelect(self,pc);
399dd6e87095071e4e987910732062545f7303023e5Ben Cheng        }
4009a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
405ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeVirtualQuick, bool methodCallRange)
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* thisPtr;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* vtable index */
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The object against which we are executing a method is always
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in the first argument.
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 > 0);
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst);
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((vsrc1>>4) > 0);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull(thisPtr))
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method.
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
43971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao        assert(ref < (unsigned int) thisPtr->clazz->vtableCount);
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = thisPtr->clazz->vtable[ref];
4419a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB)
4429a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->callsiteClass = thisPtr->clazz;
4439a3147c7412f4794434b4c2604aa2ba784867774buzbee        self->methodToCall = methodToCall;
4449a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
448d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowAbstractMethodError("abstract method not implemented");
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ virtual[%d]=%s.%s",
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ref, methodToCall->clazz->descriptor, methodToCall->name);
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
464ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET(invokeSuperQuick, bool methodCallRange)
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 thisReg;
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* vtable index */
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst;
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst & 0x0f;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* impossible in well-formed code, but we must check nevertheless */
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0   /* impossible in optimized + verified code */
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ref >= curMethod->clazz->super->vtableCount) {
489d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowNoSuchMethodError(NULL);
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
49371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao        assert(ref < (unsigned int) curMethod->clazz->super->vtableCount);
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method's class.
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're using the current method's class' superclass, not the
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * superclass of "this".  This is because we might be executing
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in a method inherited from a superclass, and we want to run
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in the method's class' superclass.
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = curMethod->clazz->super->vtable[ref];
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
509d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowAbstractMethodError("abstract method not implemented");
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
51660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ super-virtual[%d]=%s.%s",
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ref, methodToCall->clazz->descriptor, methodToCall->name);
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * General handling for return-void, return, and return-wide.  Put the
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return value in "retval" before jumping here.
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(returnFromMethod)
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* saveArea;
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We must do this BEFORE we pop the previous stack frame off, so
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that the GC can see the return value (if any) in the local vars.
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Since this is now an interpreter switch point, we must do it before
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we do anything at all.
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
5399a3147c7412f4794434b4c2604aa2ba784867774buzbee        PERIODIC_CHECKS(0);
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("> retval=0x%llx (leaving %s.%s %s)",
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            retval.j, curMethod->clazz->descriptor, curMethod->name,
54385745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            curMethod->shorty);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //DUMP_REGS(curMethod, fp);
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        debugSaveArea = saveArea;
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* back up to previous frame and see if we hit a break */
553fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fp = (u4*)saveArea->prevFrame;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != NULL);
5559a3147c7412f4794434b4c2604aa2ba784867774buzbee
5569a3147c7412f4794434b4c2604aa2ba784867774buzbee        /* Handle any special subMode requirements */
5579a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->interpBreak.ctl.subMode != 0) {
55899e3e6e72e3471eb85fc2e405866392b01c080febuzbee            PC_FP_TO_SELF();
55999e3e6e72e3471eb85fc2e405866392b01c080febuzbee            dvmReportReturn(self);
5609a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
5619a3147c7412f4794434b4c2604aa2ba784867774buzbee
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsBreakFrame(fp)) {
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* bail without popping the method frame from stack */
56460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGVV("+++ returned into break frame");
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_bail();
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* update thread FP, and reset local variables */
56930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame = fp;
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        curMethod = SAVEAREA_FROM_FP(fp)->method;
57199e3e6e72e3471eb85fc2e405866392b01c080febuzbee        self->interpSave.method = curMethod;
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //methodClass = curMethod->clazz;
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodClassDex = curMethod->clazz->pDvmDex;
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = saveArea->savedPc;
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
57685745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            curMethod->name, curMethod->shorty);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* use FINISH on the caller's invoke instruction */
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //u2 invokeInstr = INST_INST(FETCH(0));
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            invokeInstr <= OP_INVOKE_INTERFACE*/)
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            FINISH(3);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
585c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            //ALOGE("Unknown invoke instr %02x at %d",
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    invokeInstr, (int) (pc - curMethod->insns));
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Jump here when the code throws an exception.
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * By the time we get here, the Throwable has been created and the stack
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * trace has been saved off.
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(exceptionThrown)
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* exception;
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int catchRelPc;
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6049a3147c7412f4794434b4c2604aa2ba784867774buzbee        PERIODIC_CHECKS(0);
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We save off the exception and clear the exception status.  While
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * processing the exception we might need to load some Throwable
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * classes, and we don't want class loader exceptions to get
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * confused with this one.
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exception = dvmGetException(self);
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAddTrackedAlloc(exception, self);
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(self);
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Handling exception %s at %s:%d",
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            exception->clazz->descriptor, curMethod->name,
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLineNumFromPC(curMethod, pc - curMethod->insns));
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
6229a3147c7412f4794434b4c2604aa2ba784867774buzbee         * Report the exception throw to any "subMode" watchers.
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: if the exception was thrown by interpreted code, control
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * fell through native, and then back to us, we will report the
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception at the point of the throw and again here.  We can avoid
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * this by not reporting exceptions when we jump here directly from
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the native call code above, but then we won't report exceptions
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that were thrown *from* the JNI code (as opposed to *through* it).
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The correct solution is probably to ignore from-native exceptions
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * here, and have the JNI exception code do the reporting to the
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * debugger.
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
6359a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->interpBreak.ctl.subMode != 0) {
63699e3e6e72e3471eb85fc2e405866392b01c080febuzbee            PC_FP_TO_SELF();
63799e3e6e72e3471eb85fc2e405866392b01c080febuzbee            dvmReportExceptionThrow(self, exception);
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to unroll to the catch block or the nearest "break"
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * frame.
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * A break frame could indicate that we have reached an intermediate
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * native call, or have gone off the top of the stack and the thread
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * needs to exit.  Either way, we return from here, leaving the
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception raised.
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we do find a catch block, we want to transfer execution to
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that point.
6514fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         *
6524fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * Note this can cause an exception while resolving classes in
6534fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * the "catch" blocks.
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
656fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                    exception, false, (void**)(void*)&fp);
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Restore the stack bounds after an overflow.  This isn't going to
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be correct in all circumstances, e.g. if JNI code devours the
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception this won't happen until some other exception gets
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * thrown.  If the code keeps pushing the stack bounds we'll end
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * up aborting the VM.
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note we want to do this *after* the call to dvmFindCatchBlock,
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because that may need extra stack space to resolve exception
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * classes (e.g. through a class loader).
6684fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         *
6694fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * It's possible for the stack overflow handling to cause an
6704fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * exception (specifically, class resolution in a "catch" block
6714fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * during the call above), so we could see the thread's overflow
6724fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * flag raised but actually be running in a "nested" interpreter
6734fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * frame.  We don't allow doubled-up StackOverflowErrors, so
6744fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * we can check for this by just looking at the exception type
6754fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * in the cleanup function.  Also, we won't unroll past the SOE
6764fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * point because the more-recent exception will hit a break frame
6774fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * as it unrolls to here.
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->stackOverflowed)
6804fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden            dvmCleanupStackOverflow(self, exception);
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catchRelPc < 0) {
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* falling through to JNI code or off the bottom of the stack */
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 2
685062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Exception %s from %s:%d not caught locally",
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(curMethod, pc - curMethod->insns));
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmSetException(self, exception);
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(exception, self);
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_bail();
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 3
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
697062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Exception %s thrown from %s:%d to %s:%d",
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(curMethod, pc - curMethod->insns),
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetMethodSourceFile(catchMethod),
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(catchMethod, catchRelPc));
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
70630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee         * Adjust local variables to match self->interpSave.curFrame and the
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * updated PC.
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
70930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        //fp = (u4*) self->interpSave.curFrame;
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        curMethod = SAVEAREA_FROM_FP(fp)->method;
71199e3e6e72e3471eb85fc2e405866392b01c080febuzbee        self->interpSave.method = curMethod;
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //methodClass = curMethod->clazz;
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodClassDex = curMethod->clazz->pDvmDex;
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = curMethod->insns + catchRelPc;
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
71685745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            curMethod->name, curMethod->shorty);
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DUMP_REGS(curMethod, fp, false);            // show all regs
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Restore the exception if the handler wants it.
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The Dalvik spec mandates that, if an exception handler wants to
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * do something with the exception, the first instruction executed
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * must be "move-exception".  We can pass the exception along
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * through the thread struct, and let the move-exception instruction
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * clear it for us.
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If the handler doesn't call move-exception, we don't want to
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * finish here with an exception still pending.
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmSetException(self, exception);
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(exception, self);
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FINISH(0);
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7408afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * General handling for invoke-{virtual,super,direct,static,interface},
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * including "quick" variants.
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set "methodToCall" to the Method we're calling, and "methodCallRange"
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * depending on whether this is a "/range" instruction.
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For a range call:
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vsrc1" holds the argument count (8 bits)
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vdst" holds the first argument in the range
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For a non-range call:
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vsrc1" holds the argument count (4 bits) and the 5th argument index
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vdst" holds four 4-bit register indices
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The caller must EXPORT_PC before jumping here, because any method
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call can throw a stack overflow exception.
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2 count, u2 regs)
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("range=%d call=%p count=%d regs=0x%04x\n",
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    methodCallRange, methodToCall, count, regs);
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
76685745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood        //    methodToCall->name, methodToCall->shorty);
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4* outs;
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int i;
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Copy args.  This may corrupt vsrc1/vdst.
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // could use memcpy or a "Duff's device"; most functions have
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // so few args it won't matter much
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 <= curMethod->outsSize);
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 == methodToCall->insSize);
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            outs = OUTS_FROM_FP(fp, vsrc1);
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < vsrc1; i++)
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[i] = GET_REGISTER(vdst+i);
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 count = vsrc1 >> 4;
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(count <= curMethod->outsSize);
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(count == methodToCall->insSize);
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(count <= 5);
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            outs = OUTS_FROM_FP(fp, count);
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (count == 5) {
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[4] = GET_REGISTER(vsrc1 & 0x0f);
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count--;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < (int) count; i++) {
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[i] = GET_REGISTER(vdst & 0x0f);
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vdst >>= 4;
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This version executes fewer instructions but is larger
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // overall.  Seems to be a teensy bit faster.
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((vdst >> 16) == 0);  // 16 bits -or- high 16 bits clear
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (count) {
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 5:
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[4] = GET_REGISTER(vsrc1 & 0x0f);
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 4:
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[3] = GET_REGISTER(vdst >> 12);
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 3:
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 2:
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 1:
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[0] = GET_REGISTER(vdst & 0x0f);
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ;
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This was originally a "goto" target; I've kept it separate from the
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stuff above in case we want to refactor things again.)
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * At this point, we have the arguments stored in the "outs" area of
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the current method's stack frame, and the method to call in
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "methodToCall".  Push a new stack frame.
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* newSaveArea;
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4* newFp;
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("> %s%s.%s %s",
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->clazz->descriptor, methodToCall->name,
83685745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            methodToCall->shorty);
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea = SAVEAREA_FROM_FP(newFp);
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify that we have enough space */
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (true) {
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u1* bottom;
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (bottom < self->interpStackEnd) {
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* stack overflow */
84792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                ALOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')",
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    self->interpStackStart, self->interpStackEnd, bottom,
8496ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                    (u1*) fp - bottom, self->interpStackSize,
8506ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                    methodToCall->name);
8516ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                dvmHandleStackOverflow(self, methodToCall);
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(self));
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
855062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            //ALOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p",
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    fp, newFp, newSaveArea, bottom);
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef LOG_INSTR
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall->registersSize > methodToCall->insSize) {
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This makes valgrind quiet when we print registers that
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * haven't been initialized.  Turn it off when the debug
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * messages are disabled -- we want valgrind to report any
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * used-before-initialized issues.
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            memset(newFp, 0xcc,
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (methodToCall->registersSize - methodToCall->insSize) * 4);
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->prevFrame = fp;
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->savedPc = pc;
8779a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB)
878ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        newSaveArea->returnAddr = 0;
879ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->method = methodToCall;
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8829a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->interpBreak.ctl.subMode != 0) {
8839a3147c7412f4794434b4c2604aa2ba784867774buzbee            /*
8849a3147c7412f4794434b4c2604aa2ba784867774buzbee             * We mark ENTER here for both native and non-native
8859a3147c7412f4794434b4c2604aa2ba784867774buzbee             * calls.  For native calls, we'll mark EXIT on return.
8869a3147c7412f4794434b4c2604aa2ba784867774buzbee             * For non-native calls, EXIT is marked in the RETURN op.
8879a3147c7412f4794434b4c2604aa2ba784867774buzbee             */
88830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee            PC_TO_SELF();
8899a3147c7412f4794434b4c2604aa2ba784867774buzbee            dvmReportInvoke(self, methodToCall);
8909a3147c7412f4794434b4c2604aa2ba784867774buzbee        }
8919a3147c7412f4794434b4c2604aa2ba784867774buzbee
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsNativeMethod(methodToCall)) {
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "Call" interpreted code.  Reposition the PC, update the
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * frame pointer and other local state, and continue.
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curMethod = methodToCall;
89899e3e6e72e3471eb85fc2e405866392b01c080febuzbee            self->interpSave.method = curMethod;
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodClassDex = curMethod->clazz->pDvmDex;
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pc = methodToCall->insns;
9013185a41fe8b3223003a07685c1acdf44bfe148d0buzbee            fp = newFp;
9023185a41fe8b3223003a07685c1acdf44bfe148d0buzbee            self->interpSave.curFrame = fp;
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugSaveArea = SAVEAREA_FROM_FP(newFp);
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
9069a3147c7412f4794434b4c2604aa2ba784867774buzbee            self->debugIsMethodEntry = true;        // profiling, debugging
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
90885745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood                curMethod->name, curMethod->shorty);
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DUMP_REGS(curMethod, fp, true);         // show input args
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            FINISH(0);                              // jump to method start
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* set this up for JNI locals, even if not a JNI native */
913d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee            self->interpSave.curFrame = newFp;
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DUMP_REGS(methodToCall, newFp, true);   // show input args
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9199a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (self->interpBreak.ctl.subMode != 0) {
9207882ef9e459373e31c5e06eb2d2fe96c2e948300Chris Dearman                dvmReportPreNativeInvoke(methodToCall, self, newSaveArea->prevFrame);
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9239a3147c7412f4794434b4c2604aa2ba784867774buzbee            ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
9249a3147c7412f4794434b4c2604aa2ba784867774buzbee                  methodToCall->name, methodToCall->shorty);
925d726991ba52466cde88e37aba4de2395b62477faBill Buzbee
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Jump through native call bridge.  Because we leave no
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * space for locals on native calls, "newFp" points directly
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to the method arguments.
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9339a3147c7412f4794434b4c2604aa2ba784867774buzbee            if (self->interpBreak.ctl.subMode != 0) {
9347882ef9e459373e31c5e06eb2d2fe96c2e948300Chris Dearman                dvmReportPostNativeInvoke(methodToCall, self, newSaveArea->prevFrame);
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* pop frame off */
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPopJniLocals(self, newSaveArea);
9390d5443d0ef4c5538112a9ae1d1c8b93b8ab18736Chris Dearman            self->interpSave.curFrame = newSaveArea->prevFrame;
9400d5443d0ef4c5538112a9ae1d1c8b93b8ab18736Chris Dearman            fp = newSaveArea->prevFrame;
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If the native code threw an exception, or interpreted code
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * invoked by the native call threw one and nobody has cleared
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it, jump to our local exception handling.
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmCheckException(self)) {
94892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                ALOGV("Exception thrown by/below native code");
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGD("> retval=0x%llx (leaving native)", retval.j);
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGD("> (return from native %s.%s to %s.%s %s)",
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                methodToCall->clazz->descriptor, methodToCall->name,
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                curMethod->clazz->descriptor, curMethod->name,
95685745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood                curMethod->shorty);
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //u2 invokeInstr = INST_INST(FETCH(0));
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                invokeInstr <= OP_INVOKE_INTERFACE*/)
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                FINISH(3);
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
964c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                //ALOGE("Unknown invoke instr %02x at %d",
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //    invokeInstr, (int) (pc - curMethod->insns));
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(false);      // should not get here
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
972