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