gotoTargets.cpp revision fc75f3ed87b55d625b6054e18645da5cbdba31c6
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
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(filledNewArray, bool methodCallRange)
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
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* class ref */
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* first 4 regs -or- range base */
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vsrc1 = INST_AA(inst);  /* #of elements */
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            arg5 = -1;              /* silence compiler warning */
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            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 {
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            arg5 = INST_A(inst);
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vsrc1 = INST_B(inst);   /* #of elements */
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                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)) {
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/RuntimeError;",
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         */
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ filled-new-array type is '%s'\n", 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 */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/RuntimeError;",
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "bad filled array req");
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* TODO: requires multiple "fill in" loops with different widths */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("non-int primitives not implemented\n");
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/InternalError;",
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "filled-new-array not implemented for anything but 'int'");
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newArray == NULL)
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Fill in the elements.  It's legal for vsrc1 to be zero.
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        contents = (u4*) newArray->contents;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < vsrc1; i++)
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                contents[i] = GET_REGISTER(vdst+i);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 <= 5);
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (vsrc1 == 5) {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                contents[4] = GET_REGISTER(arg5);
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1--;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < vsrc1; i++) {
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                contents[i] = GET_REGISTER(vdst & 0x0f);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vdst >>= 4;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
97364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        if (typeCh == 'L' || typeCh == '[') {
98364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            dvmWriteBarrierArray(newArray, 0, newArray->length);
99364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        retval.l = newArray;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FINISH(3);
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeVirtual, bool methodCallRange)
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* baseMethod;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* thisPtr;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* method ref */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The object against which we are executing a method is always
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in the first argument.
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 > 0);
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst);
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((vsrc1>>4) > 0);
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull(thisPtr))
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Resolve the method.  This is the correct method for the static
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * type of the object.  We also verify access permissions here.
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (baseMethod == NULL) {
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (baseMethod == NULL) {
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ILOGV("+ unknown method or access denied\n");
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method.
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1577a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
1587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        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             */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/AbstractMethodError;",
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "abstract method not implemented");
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod->clazz->descriptor, baseMethod->name,
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (u4) baseMethod->methodIndex,
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->clazz->descriptor, methodToCall->name);
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (vsrc1 != methodToCall->insSize) {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                baseMethod->clazz->descriptor, baseMethod->name,
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) baseMethod->methodIndex,
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                methodToCall->clazz->descriptor, methodToCall->name);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmDumpClass(baseMethod->clazz);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmDumpClass(methodToCall->clazz);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpAllClasses(0);
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeSuper, bool methodCallRange)
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* baseMethod;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 thisReg;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* method ref */
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst;
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst & 0x0f;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
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) {
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ILOGV("+ unknown method or access denied\n");
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             */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/NoSuchMethodError;",
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                baseMethod->name);
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/AbstractMethodError;",
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "abstract method not implemented");
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            baseMethod->clazz->descriptor, baseMethod->name,
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->clazz->descriptor, methodToCall->name);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeInterface, bool methodCallRange)
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* thisPtr;
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* thisClass;
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* method ref */
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The object against which we are executing a method is always
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in the first argument.
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 > 0);
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst);
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((vsrc1>>4) > 0);
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
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
3127a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
3137a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        callsiteClass = thisClass;
3147a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
3157a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Given a class and a method index, find the Method* with the
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * actual code we want to execute.
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        methodClassDex);
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
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_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        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* method ref */
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            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 {
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst & 0x0f;
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall == NULL) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall = dvmResolveMethod(curMethod->clazz, ref,
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            METHOD_DIRECT);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (methodToCall == NULL) {
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ILOGV("+ unknown direct method\n");     // should be impossible
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeStatic, bool methodCallRange)
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ref = FETCH(1);             /* method ref */
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    vdst = FETCH(2);            /* 4 regs -or- first reg */
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    EXPORT_PC();
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodCallRange)
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vsrc1, ref, vdst, vdst+vsrc1-1);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodToCall == NULL) {
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall == NULL) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("+ unknown method\n");
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
387dd6e87095071e4e987910732062545f7303023e5Ben Cheng
388dd6e87095071e4e987910732062545f7303023e5Ben Cheng        /*
389dd6e87095071e4e987910732062545f7303023e5Ben Cheng         * The JIT needs dvmDexGetResolvedMethod() to return non-null.
390dd6e87095071e4e987910732062545f7303023e5Ben Cheng         * Since we use the portable interpreter to build the trace, this extra
391dd6e87095071e4e987910732062545f7303023e5Ben Cheng         * check is not needed for mterp.
392dd6e87095071e4e987910732062545f7303023e5Ben Cheng         */
393dd6e87095071e4e987910732062545f7303023e5Ben Cheng        if (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL) {
394dd6e87095071e4e987910732062545f7303023e5Ben Cheng            /* Class initialization is still ongoing */
395dd6e87095071e4e987910732062545f7303023e5Ben Cheng            ABORT_JIT_TSELECT();
396dd6e87095071e4e987910732062545f7303023e5Ben Cheng        }
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeVirtualQuick, bool methodCallRange)
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* thisPtr;
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* vtable index */
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The object against which we are executing a method is always
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in the first argument.
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 > 0);
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((vsrc1>>4) > 0);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull(thisPtr))
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4307a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT) && (INTERP_TYPE == INTERP_DBG)
4317a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        callsiteClass = thisPtr->clazz;
4327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
4337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method.
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(ref < thisPtr->clazz->vtableCount);
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = thisPtr->clazz->vtable[ref];
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/AbstractMethodError;",
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "abstract method not implemented");
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ virtual[%d]=%s.%s\n",
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ref, methodToCall->clazz->descriptor, methodToCall->name);
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeSuperQuick, bool methodCallRange)
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 thisReg;
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ref = FETCH(1);             /* vtable index */
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vdst = FETCH(2);            /* 4 regs -or- first reg */
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1, ref, vdst, vdst+vsrc1-1);
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst;
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisReg = vdst & 0x0f;
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* impossible in well-formed code, but we must check nevertheless */
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0   /* impossible in optimized + verified code */
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ref >= curMethod->clazz->super->vtableCount) {
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/NoSuchMethodError;", NULL);
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(ref < curMethod->clazz->super->vtableCount);
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Combine the object we found with the vtable offset in the
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method's class.
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're using the current method's class' superclass, not the
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * superclass of "this".  This is because we might be executing
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in a method inherited from a superclass, and we want to run
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in the method's class' superclass.
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodToCall = curMethod->clazz->super->vtable[ref];
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(methodToCall)) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/AbstractMethodError;",
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "abstract method not implemented");
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_exceptionThrown();
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsAbstractMethod(methodToCall) ||
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->nativeFunc != NULL);
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ super-virtual[%d]=%s.%s\n",
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ref, methodToCall->clazz->descriptor, methodToCall->name);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodToCall != NULL);
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * General handling for return-void, return, and return-wide.  Put the
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return value in "retval" before jumping here.
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(returnFromMethod)
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* saveArea;
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We must do this BEFORE we pop the previous stack frame off, so
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that the GC can see the return value (if any) in the local vars.
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Since this is now an interpreter switch point, we must do it before
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we do anything at all.
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PERIODIC_CHECKS(kInterpEntryReturn, 0);
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("> retval=0x%llx (leaving %s.%s %s)",
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            retval.j, curMethod->clazz->descriptor, curMethod->name,
54185745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            curMethod->shorty);
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //DUMP_REGS(curMethod, fp);
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        saveArea = SAVEAREA_FROM_FP(fp);
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        debugSaveArea = saveArea;
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
5490d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if (INTERP_TYPE == INTERP_DBG)
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TRACE_METHOD_EXIT(self, curMethod);
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* back up to previous frame and see if we hit a break */
554fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fp = (u4*)saveArea->prevFrame;
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != NULL);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsBreakFrame(fp)) {
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* bail without popping the method frame from stack */
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++ returned into break frame\n");
559d726991ba52466cde88e37aba4de2395b62477faBill Buzbee#if defined(WITH_JIT)
560d726991ba52466cde88e37aba4de2395b62477faBill Buzbee            /* Let the Jit know the return is terminating normally */
561fc075c2d1ae63c26f96e0c6eeb72efc898dbebbfBen Cheng            CHECK_JIT_VOID();
562d726991ba52466cde88e37aba4de2395b62477faBill Buzbee#endif
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_bail();
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* update thread FP, and reset local variables */
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame = fp;
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        curMethod = SAVEAREA_FROM_FP(fp)->method;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //methodClass = curMethod->clazz;
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodClassDex = curMethod->clazz->pDvmDex;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = saveArea->savedPc;
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
57385745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            curMethod->name, curMethod->shorty);
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* use FINISH on the caller's invoke instruction */
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //u2 invokeInstr = INST_INST(FETCH(0));
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            invokeInstr <= OP_INVOKE_INTERFACE*/)
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            FINISH(3);
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGE("Unknown invoke instr %02x at %d\n",
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    invokeInstr, (int) (pc - curMethod->insns));
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Jump here when the code throws an exception.
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * By the time we get here, the Throwable has been created and the stack
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * trace has been saved off.
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(exceptionThrown)
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* exception;
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int catchRelPc;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Since this is now an interpreter switch point, we must do it before
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we do anything at all.
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PERIODIC_CHECKS(kInterpEntryThrow, 0);
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60779d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng#if defined(WITH_JIT)
60879d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng        // Something threw during trace selection - abort the current trace
6095540f6e420ffab7bb0c39dc508bdc3a2e0d67507Bill Buzbee        ABORT_JIT_TSELECT();
61079d173cad420b2ef99a09688e603df7ea4f890e9Ben Cheng#endif
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We save off the exception and clear the exception status.  While
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * processing the exception we might need to load some Throwable
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * classes, and we don't want class loader exceptions to get
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * confused with this one.
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exception = dvmGetException(self);
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAddTrackedAlloc(exception, self);
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(self);
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Handling exception %s at %s:%d\n",
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            exception->clazz->descriptor, curMethod->name,
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLineNumFromPC(curMethod, pc - curMethod->insns));
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6260d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if (INTERP_TYPE == INTERP_DBG)
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Tell the debugger about it.
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: if the exception was thrown by interpreted code, control
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * fell through native, and then back to us, we will report the
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception at the point of the throw and again here.  We can avoid
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * this by not reporting exceptions when we jump here directly from
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the native call code above, but then we won't report exceptions
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that were thrown *from* the JNI code (as opposed to *through* it).
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The correct solution is probably to ignore from-native exceptions
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * here, and have the JNI exception code do the reporting to the
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * debugger.
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.debuggerActive) {
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            void* catchFrame;
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception, true, &catchFrame);
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDbgPostException(fp, pc - curMethod->insns, catchFrame,
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                catchRelPc, exception);
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to unroll to the catch block or the nearest "break"
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * frame.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * A break frame could indicate that we have reached an intermediate
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * native call, or have gone off the top of the stack and the thread
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * needs to exit.  Either way, we return from here, leaving the
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception raised.
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we do find a catch block, we want to transfer execution to
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that point.
6614fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         *
6624fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * Note this can cause an exception while resolving classes in
6634fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * the "catch" blocks.
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
666fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                    exception, false, (void**)(void*)&fp);
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Restore the stack bounds after an overflow.  This isn't going to
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be correct in all circumstances, e.g. if JNI code devours the
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception this won't happen until some other exception gets
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * thrown.  If the code keeps pushing the stack bounds we'll end
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * up aborting the VM.
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note we want to do this *after* the call to dvmFindCatchBlock,
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because that may need extra stack space to resolve exception
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * classes (e.g. through a class loader).
6784fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         *
6794fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * It's possible for the stack overflow handling to cause an
6804fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * exception (specifically, class resolution in a "catch" block
6814fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * during the call above), so we could see the thread's overflow
6824fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * flag raised but actually be running in a "nested" interpreter
6834fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * frame.  We don't allow doubled-up StackOverflowErrors, so
6844fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * we can check for this by just looking at the exception type
6854fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * in the cleanup function.  Also, we won't unroll past the SOE
6864fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * point because the more-recent exception will hit a break frame
6874fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden         * as it unrolls to here.
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (self->stackOverflowed)
6904fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden            dvmCleanupStackOverflow(self, exception);
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catchRelPc < 0) {
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* falling through to JNI code or off the bottom of the stack */
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 2
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD("Exception %s from %s:%d not caught locally\n",
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(curMethod, pc - curMethod->insns));
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmSetException(self, exception);
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(exception, self);
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            GOTO_bail();
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 3
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD("Exception %s thrown from %s:%d to %s:%d\n",
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(curMethod, pc - curMethod->insns),
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetMethodSourceFile(catchMethod),
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(catchMethod, catchRelPc));
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Adjust local variables to match self->curFrame and the
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * updated PC.
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //fp = (u4*) self->curFrame;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        curMethod = SAVEAREA_FROM_FP(fp)->method;
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //methodClass = curMethod->clazz;
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodClassDex = curMethod->clazz->pDvmDex;
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = curMethod->insns + catchRelPc;
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
72585745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            curMethod->name, curMethod->shorty);
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DUMP_REGS(curMethod, fp, false);            // show all regs
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Restore the exception if the handler wants it.
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The Dalvik spec mandates that, if an exception handler wants to
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * do something with the exception, the first instruction executed
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * must be "move-exception".  We can pass the exception along
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * through the thread struct, and let the move-exception instruction
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * clear it for us.
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If the handler doesn't call move-exception, we don't want to
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * finish here with an exception still pending.
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmSetException(self, exception);
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(exception, self);
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FINISH(0);
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7498afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * General handling for invoke-{virtual,super,direct,static,interface},
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * including "quick" variants.
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set "methodToCall" to the Method we're calling, and "methodCallRange"
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * depending on whether this is a "/range" instruction.
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For a range call:
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vsrc1" holds the argument count (8 bits)
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vdst" holds the first argument in the range
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For a non-range call:
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vsrc1" holds the argument count (4 bits) and the 5th argument index
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  "vdst" holds four 4-bit register indices
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The caller must EXPORT_PC before jumping here, because any method
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call can throw a stack overflow exception.
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2 count, u2 regs)
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("range=%d call=%p count=%d regs=0x%04x\n",
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    methodCallRange, methodToCall, count, regs);
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
77585745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood        //    methodToCall->name, methodToCall->shorty);
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4* outs;
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int i;
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Copy args.  This may corrupt vsrc1/vdst.
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodCallRange) {
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // could use memcpy or a "Duff's device"; most functions have
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // so few args it won't matter much
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 <= curMethod->outsSize);
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(vsrc1 == methodToCall->insSize);
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            outs = OUTS_FROM_FP(fp, vsrc1);
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < vsrc1; i++)
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[i] = GET_REGISTER(vdst+i);
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 count = vsrc1 >> 4;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(count <= curMethod->outsSize);
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(count == methodToCall->insSize);
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(count <= 5);
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            outs = OUTS_FROM_FP(fp, count);
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (count == 5) {
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[4] = GET_REGISTER(vsrc1 & 0x0f);
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count--;
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < (int) count; i++) {
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[i] = GET_REGISTER(vdst & 0x0f);
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vdst >>= 4;
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This version executes fewer instructions but is larger
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // overall.  Seems to be a teensy bit faster.
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((vdst >> 16) == 0);  // 16 bits -or- high 16 bits clear
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (count) {
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 5:
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[4] = GET_REGISTER(vsrc1 & 0x0f);
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 4:
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[3] = GET_REGISTER(vdst >> 12);
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 3:
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 2:
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 1:
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outs[0] = GET_REGISTER(vdst & 0x0f);
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ;
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This was originally a "goto" target; I've kept it separate from the
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stuff above in case we want to refactor things again.)
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * At this point, we have the arguments stored in the "outs" area of
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the current method's stack frame, and the method to call in
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "methodToCall".  Push a new stack frame.
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* newSaveArea;
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4* newFp;
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ILOGV("> %s%s.%s %s",
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodToCall->clazz->descriptor, methodToCall->name,
84585745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood            methodToCall->shorty);
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea = SAVEAREA_FROM_FP(newFp);
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify that we have enough space */
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (true) {
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u1* bottom;
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (bottom < self->interpStackEnd) {
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* stack overflow */
8566ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    self->interpStackStart, self->interpStackEnd, bottom,
8586ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                    (u1*) fp - bottom, self->interpStackSize,
8596ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                    methodToCall->name);
8606ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden                dvmHandleStackOverflow(self, methodToCall);
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(self));
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n",
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    fp, newFp, newSaveArea, bottom);
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef LOG_INSTR
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodToCall->registersSize > methodToCall->insSize) {
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This makes valgrind quiet when we print registers that
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * haven't been initialized.  Turn it off when the debug
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * messages are disabled -- we want valgrind to report any
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * used-before-initialized issues.
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            memset(newFp, 0xcc,
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (methodToCall->registersSize - methodToCall->insSize) * 4);
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->prevFrame = fp;
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->savedPc = pc;
886ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT)
887ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        newSaveArea->returnAddr = 0;
888ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newSaveArea->method = methodToCall;
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsNativeMethod(methodToCall)) {
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "Call" interpreted code.  Reposition the PC, update the
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * frame pointer and other local state, and continue.
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curMethod = methodToCall;
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            methodClassDex = curMethod->clazz->pDvmDex;
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pc = methodToCall->insns;
899fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            self->curFrame = fp = newFp;
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugSaveArea = SAVEAREA_FROM_FP(newFp);
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if INTERP_TYPE == INTERP_DBG
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugIsMethodEntry = true;              // profiling, debugging
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
90785745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood                curMethod->name, curMethod->shorty);
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DUMP_REGS(curMethod, fp, true);         // show input args
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            FINISH(0);                              // jump to method start
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* set this up for JNI locals, even if not a JNI native */
912d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#ifdef USE_INDIRECT_REF
913d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
914d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#else
915d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
916d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden#endif
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->curFrame = newFp;
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DUMP_REGS(methodToCall, newFp, true);   // show input args
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9220d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if (INTERP_TYPE == INTERP_DBG)
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.debuggerActive) {
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmDbgPostLocationEvent(methodToCall, -1,
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmGetThisPtr(curMethod, fp), DBG_METHOD_ENTRY);
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
9280d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if (INTERP_TYPE == INTERP_DBG)
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TRACE_METHOD_ENTER(self, methodToCall);
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9328afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes            {
9338afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes                ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
9348afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes                        methodToCall->name, methodToCall->shorty);
9358afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes            }
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
937d726991ba52466cde88e37aba4de2395b62477faBill Buzbee#if defined(WITH_JIT)
938d726991ba52466cde88e37aba4de2395b62477faBill Buzbee            /* Allow the Jit to end any pending trace building */
939fc075c2d1ae63c26f96e0c6eeb72efc898dbebbfBen Cheng            CHECK_JIT_VOID();
940d726991ba52466cde88e37aba4de2395b62477faBill Buzbee#endif
941d726991ba52466cde88e37aba4de2395b62477faBill Buzbee
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Jump through native call bridge.  Because we leave no
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * space for locals on native calls, "newFp" points directly
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to the method arguments.
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9490d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if (INTERP_TYPE == INTERP_DBG)
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.debuggerActive) {
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmDbgPostLocationEvent(methodToCall, -1,
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmGetThisPtr(curMethod, fp), DBG_METHOD_EXIT);
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
9550d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden#if (INTERP_TYPE == INTERP_DBG)
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TRACE_METHOD_EXIT(self, methodToCall);
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* pop frame off */
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmPopJniLocals(self, newSaveArea);
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->curFrame = fp;
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If the native code threw an exception, or interpreted code
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * invoked by the native call threw one and nobody has cleared
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it, jump to our local exception handling.
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmCheckException(self)) {
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Exception thrown by/below native code\n");
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                GOTO_exceptionThrown();
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGD("> retval=0x%llx (leaving native)", retval.j);
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ILOGD("> (return from native %s.%s to %s.%s %s)",
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                methodToCall->clazz->descriptor, methodToCall->name,
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                curMethod->clazz->descriptor, curMethod->name,
97785745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood                curMethod->shorty);
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //u2 invokeInstr = INST_INST(FETCH(0));
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                invokeInstr <= OP_INVOKE_INTERFACE*/)
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                FINISH(3);
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //LOGE("Unknown invoke instr %02x at %d\n",
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //    invokeInstr, (int) (pc - curMethod->insns));
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(false);      // should not get here
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END
993