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