gotoTargets.cpp revision 9a3147c7412f4794434b4c2604aa2ba784867774
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 1171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat) 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 2271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 2371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */ 2471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = FETCH(3); /* #of elements */ 2571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(4); /* range base */ 2671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao arg5 = -1; /* silence compiler warning */ 2771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}", 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 3071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1); /* class ref */ 3171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(2); /* first 4 regs -or- range base */ 3271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 3371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (methodCallRange) { 3471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_AA(inst); /* #of elements */ 3571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao arg5 = -1; /* silence compiler warning */ 3671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}", 3771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, vdst+vsrc1-1); 3871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 3971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao arg5 = INST_A(inst); 4071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_B(inst); /* #of elements */ 4171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}", 4271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, arg5); 4371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Resolve the array class. 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (arrayClass == NULL) { 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (arrayClass == NULL) 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsArrayClass(arrayClass)) { 57d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowRuntimeException( 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "filled-new-array needs array class"); 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verifier guarantees this is an array class */ 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsArrayClass(arrayClass)); 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsClassInitialized(arrayClass)); 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an array of the specified type. 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor); 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project typeCh = arrayClass->descriptor[1]; 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (typeCh == 'D' || typeCh == 'J') { 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* category 2 primitives not allowed */ 73d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowRuntimeException("bad filled array req"); 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') { 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* TODO: requires multiple "fill in" loops with different widths */ 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("non-int primitives not implemented\n"); 7870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein dvmThrowInternalError( 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "filled-new-array not implemented for anything but 'int'"); 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK); 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newArray == NULL) 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fill in the elements. It's legal for vsrc1 to be zero. 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project contents = (u4*) newArray->contents; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodCallRange) { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < vsrc1; i++) 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project contents[i] = GET_REGISTER(vdst+i); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(vsrc1 <= 5); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (vsrc1 == 5) { 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project contents[4] = GET_REGISTER(arg5); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1--; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < vsrc1; i++) { 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project contents[i] = GET_REGISTER(vdst & 0x0f); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vdst >>= 4; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 105364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes if (typeCh == 'L' || typeCh == '[') { 106364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes dvmWriteBarrierArray(newArray, 0, newArray->length); 107364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes } 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project retval.l = newArray; 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 11171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 11271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao FINISH(5); 11371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 11471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao FINISH(3); 11571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 11971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat) 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* baseMethod; 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* thisPtr; 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 12771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 12871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = FETCH(3); /* count */ 12971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(4); /* first reg */ 13071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ADJUST_PC(2); /* advance pc partially to make returns easier */ 13171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}", 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisPtr = (Object*) GET_REGISTER(vdst); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 13571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 13671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1); /* method ref */ 13771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(2); /* 4 regs -or- first reg */ 13871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 13971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao /* 14071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao * The object against which we are executing a method is always 14171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao * in the first argument. 14271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao */ 14371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (methodCallRange) { 14471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao assert(vsrc1 > 0); 14571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}", 14671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, vdst+vsrc1-1); 14771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisPtr = (Object*) GET_REGISTER(vdst); 14871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 14971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao assert((vsrc1>>4) > 0); 15071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}", 15171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 15271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 15371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!checkForNull(thisPtr)) 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Resolve the method. This is the correct method for the static 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * type of the object. We also verify access permissions here. 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (baseMethod == NULL) { 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (baseMethod == NULL) { 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("+ unknown method or access denied\n"); 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Combine the object we found with the vtable offset in the 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method. 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex]; 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1799a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB) 1809a3147c7412f4794434b4c2604aa2ba784867774buzbee self->methodToCall = methodToCall; 1819a3147c7412f4794434b4c2604aa2ba784867774buzbee self->callsiteClass = thisPtr->clazz; 1827a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif 1837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsAbstractMethod(methodToCall)) { 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can happen if you create two classes, Base and Sub, where 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sub is a sub-class of Base. Declare a protected abstract 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method foo() in Base, and invoke foo() from a method in Base. 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Base is an "abstract base class" and is never instantiated 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly. Now, Override foo() in Sub, and use Sub. This 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Works fine unless Sub stops providing an implementation of 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the method. 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 195d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowAbstractMethodError("abstract method not implemented"); 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(methodToCall) || 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->nativeFunc != NULL); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n", 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod->clazz->descriptor, baseMethod->name, 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u4) baseMethod->methodIndex, 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->clazz->descriptor, methodToCall->name); 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(methodToCall != NULL); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (vsrc1 != methodToCall->insSize) { 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n", 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod->clazz->descriptor, baseMethod->name, 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (u4) baseMethod->methodIndex, 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->clazz->descriptor, methodToCall->name); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpClass(baseMethod->clazz); 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpClass(methodToCall->clazz); 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpAllClasses(0); 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat) 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* baseMethod; 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 thisReg; 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 23371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 23471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = FETCH(3); /* count */ 23571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(4); /* first reg */ 23671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ADJUST_PC(2); /* advance pc partially to make returns easier */ 23771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}", 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisReg = vdst; 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 24171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 24271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1); /* method ref */ 24371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(2); /* 4 regs -or- first reg */ 24471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 24571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (methodCallRange) { 24671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}", 24771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, vdst+vsrc1-1); 24871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisReg = vdst; 24971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 25071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}", 25171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 25271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisReg = vdst & 0x0f; 25371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 25571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* impossible in well-formed code, but we must check nevertheless */ 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!checkForNull((Object*) GET_REGISTER(thisReg))) 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Resolve the method. This is the correct method for the static 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * type of the object. We also verify access permissions here. 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The first arg to dvmResolveMethod() is just the referring class 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (used for class loaders and such), so we don't want to pass 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the superclass into the resolution call. 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (baseMethod == NULL) { 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (baseMethod == NULL) { 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("+ unknown method or access denied\n"); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Combine the object we found with the vtable offset in the 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method's class. 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're using the current method's class' superclass, not the 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass of "this". This is because we might be executing 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in a method inherited from a superclass, and we want to run 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in that class' superclass. 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) { 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Method does not exist in the superclass. Could happen if 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass gets updated. 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 290d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowNoSuchMethodError(baseMethod->name); 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex]; 2949a3147c7412f4794434b4c2604aa2ba784867774buzbee 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsAbstractMethod(methodToCall)) { 297d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowAbstractMethodError("abstract method not implemented"); 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(methodToCall) || 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->nativeFunc != NULL); 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ base=%s.%s super-virtual=%s.%s\n", 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project baseMethod->clazz->descriptor, baseMethod->name, 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->clazz->descriptor, methodToCall->name); 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(methodToCall != NULL); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat) 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* thisPtr; 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* thisClass; 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 32171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 32271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = FETCH(3); /* count */ 32371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(4); /* first reg */ 32471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ADJUST_PC(2); /* advance pc partially to make returns easier */ 32571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}", 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisPtr = (Object*) GET_REGISTER(vdst); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 32971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 33071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1); /* method ref */ 33171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(2); /* 4 regs -or- first reg */ 33271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 33371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao /* 33471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao * The object against which we are executing a method is always 33571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao * in the first argument. 33671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao */ 33771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (methodCallRange) { 33871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao assert(vsrc1 > 0); 33971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}", 34071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, vdst+vsrc1-1); 34171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisPtr = (Object*) GET_REGISTER(vdst); 34271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 34371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao assert((vsrc1>>4) > 0); 34471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}", 34571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 34671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 34771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 34971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!checkForNull(thisPtr)) 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisClass = thisPtr->clazz; 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3557a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given a class and a method index, find the Method* with the 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * actual code we want to execute. 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod, 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodClassDex); 3629a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB) 3639a3147c7412f4794434b4c2604aa2ba784867774buzbee self->callsiteClass = thisClass; 3649a3147c7412f4794434b4c2604aa2ba784867774buzbee self->methodToCall = methodToCall; 3659a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodToCall == NULL) { 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat) 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 thisReg; 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 38171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 38271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 38371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = FETCH(3); /* count */ 38471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(4); /* first reg */ 38571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ADJUST_PC(2); /* advance pc partially to make returns easier */ 38671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}", 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisReg = vdst; 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 39071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 39171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1); /* method ref */ 39271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(2); /* 4 regs -or- first reg */ 39371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 39471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (methodCallRange) { 39571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}", 39671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, vdst+vsrc1-1); 39771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisReg = vdst; 39871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 39971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}", 40071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 40171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao thisReg = vdst & 0x0f; 40271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 40471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!checkForNull((Object*) GET_REGISTER(thisReg))) 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodToCall == NULL) { 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = dvmResolveMethod(curMethod->clazz, ref, 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project METHOD_DIRECT); 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodToCall == NULL) { 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("+ unknown direct method\n"); // should be impossible 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat) 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (jumboFormat) { 42571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 42671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = FETCH(3); /* count */ 42771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(4); /* first reg */ 42871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ADJUST_PC(2); /* advance pc partially to make returns easier */ 42971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}", 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 43171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } else { 43271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 43371eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ref = FETCH(1); /* method ref */ 43471eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vdst = FETCH(2); /* 4 regs -or- first reg */ 43571eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao 43671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao if (methodCallRange) 43771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}", 43871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1, ref, vdst, vdst+vsrc1-1); 43971eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao else 44071eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}", 44171eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 44271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao } 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodToCall == NULL) { 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC); 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodToCall == NULL) { 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("+ unknown method\n"); 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 451dd6e87095071e4e987910732062545f7303023e5Ben Cheng 4529a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB) 453dd6e87095071e4e987910732062545f7303023e5Ben Cheng /* 454dd6e87095071e4e987910732062545f7303023e5Ben Cheng * The JIT needs dvmDexGetResolvedMethod() to return non-null. 4559a3147c7412f4794434b4c2604aa2ba784867774buzbee * Include the check if this code is being used as a stub 4569a3147c7412f4794434b4c2604aa2ba784867774buzbee * called from the assembly interpreter. 457dd6e87095071e4e987910732062545f7303023e5Ben Cheng */ 4589a3147c7412f4794434b4c2604aa2ba784867774buzbee if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 4599a3147c7412f4794434b4c2604aa2ba784867774buzbee (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) { 460dd6e87095071e4e987910732062545f7303023e5Ben Cheng /* Class initialization is still ongoing */ 4619a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmJitEndTraceSelect(self,pc); 462dd6e87095071e4e987910732062545f7303023e5Ben Cheng } 4639a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46871eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat) 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* thisPtr; 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ref = FETCH(1); /* vtable index */ 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vdst = FETCH(2); /* 4 regs -or- first reg */ 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The object against which we are executing a method is always 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in the first argument. 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodCallRange) { 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(vsrc1 > 0); 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}", 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisPtr = (Object*) GET_REGISTER(vdst); 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert((vsrc1>>4) > 0); 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}", 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!checkForNull(thisPtr)) 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4977a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Combine the object we found with the vtable offset in the 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method. 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 50271eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao assert(ref < (unsigned int) thisPtr->clazz->vtableCount); 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = thisPtr->clazz->vtable[ref]; 5049a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB) 5059a3147c7412f4794434b4c2604aa2ba784867774buzbee self->callsiteClass = thisPtr->clazz; 5069a3147c7412f4794434b4c2604aa2ba784867774buzbee self->methodToCall = methodToCall; 5079a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsAbstractMethod(methodToCall)) { 511d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowAbstractMethodError("abstract method not implemented"); 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(methodToCall) || 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->nativeFunc != NULL); 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ virtual[%d]=%s.%s\n", 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ref, methodToCall->clazz->descriptor, methodToCall->name); 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(methodToCall != NULL); 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 52771eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhaoGOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat) 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 thisReg; 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EXPORT_PC(); 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ref = FETCH(1); /* vtable index */ 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vdst = FETCH(2); /* 4 regs -or- first reg */ 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodCallRange) { 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}", 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1, ref, vdst, vdst+vsrc1-1); 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisReg = vdst; 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}", 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisReg = vdst & 0x0f; 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* impossible in well-formed code, but we must check nevertheless */ 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!checkForNull((Object*) GET_REGISTER(thisReg))) 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 /* impossible in optimized + verified code */ 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ref >= curMethod->clazz->super->vtableCount) { 552d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowNoSuchMethodError(NULL); 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 55671eee1f0c2eb514585fdbee16730c9c2209e8f68jeffhao assert(ref < (unsigned int) curMethod->clazz->super->vtableCount); 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Combine the object we found with the vtable offset in the 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method's class. 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're using the current method's class' superclass, not the 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass of "this". This is because we might be executing 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in a method inherited from a superclass, and we want to run 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in the method's class' superclass. 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall = curMethod->clazz->super->vtable[ref]; 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsAbstractMethod(methodToCall)) { 572d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowAbstractMethodError("abstract method not implemented"); 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(methodToCall) || 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->nativeFunc != NULL); 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ super-virtual[%d]=%s.%s\n", 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ref, methodToCall->clazz->descriptor, methodToCall->name); 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(methodToCall != NULL); 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * General handling for return-void, return, and return-wide. Put the 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return value in "retval" before jumping here. 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(returnFromMethod) 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We must do this BEFORE we pop the previous stack frame off, so 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the GC can see the return value (if any) in the local vars. 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since this is now an interpreter switch point, we must do it before 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we do anything at all. 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 6029a3147c7412f4794434b4c2604aa2ba784867774buzbee PERIODIC_CHECKS(0); 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("> retval=0x%llx (leaving %s.%s %s)", 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project retval.j, curMethod->clazz->descriptor, curMethod->name, 60685745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood curMethod->shorty); 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //DUMP_REGS(curMethod, fp); 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugSaveArea = saveArea; 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* back up to previous frame and see if we hit a break */ 616fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro fp = (u4*)saveArea->prevFrame; 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(fp != NULL); 6189a3147c7412f4794434b4c2604aa2ba784867774buzbee 6199a3147c7412f4794434b4c2604aa2ba784867774buzbee /* Handle any special subMode requirements */ 6209a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode != 0) { 6219a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmReportReturn(self, pc, fp); 6229a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6239a3147c7412f4794434b4c2604aa2ba784867774buzbee 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(fp)) { 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* bail without popping the method frame from stack */ 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ returned into break frame\n"); 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_bail(); 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* update thread FP, and reset local variables */ 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = fp; 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project curMethod = SAVEAREA_FROM_FP(fp)->method; 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //methodClass = curMethod->clazz; 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodClassDex = curMethod->clazz->pDvmDex; 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pc = saveArea->savedPc; 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor, 63785745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood curMethod->name, curMethod->shorty); 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* use FINISH on the caller's invoke instruction */ 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //u2 invokeInstr = INST_INST(FETCH(0)); 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project invokeInstr <= OP_INVOKE_INTERFACE*/) 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FINISH(3); 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGE("Unknown invoke instr %02x at %d\n", 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // invokeInstr, (int) (pc - curMethod->insns)); 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Jump here when the code throws an exception. 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * By the time we get here, the Throwable has been created and the stack 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * trace has been saved off. 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(exceptionThrown) 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* exception; 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int catchRelPc; 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6659a3147c7412f4794434b4c2604aa2ba784867774buzbee PERIODIC_CHECKS(0); 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We save off the exception and clear the exception status. While 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * processing the exception we might need to load some Throwable 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes, and we don't want class loader exceptions to get 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * confused with this one. 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception = dvmGetException(self); 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddTrackedAlloc(exception, self); 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Handling exception %s at %s:%d\n", 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception->clazz->descriptor, curMethod->name, 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 6839a3147c7412f4794434b4c2604aa2ba784867774buzbee * Report the exception throw to any "subMode" watchers. 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: if the exception was thrown by interpreted code, control 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fell through native, and then back to us, we will report the 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception at the point of the throw and again here. We can avoid 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this by not reporting exceptions when we jump here directly from 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the native call code above, but then we won't report exceptions 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that were thrown *from* the JNI code (as opposed to *through* it). 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The correct solution is probably to ignore from-native exceptions 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * here, and have the JNI exception code do the reporting to the 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * debugger. 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 6969a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode != 0) { 6979a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmReportExceptionThrow(self, curMethod, pc, fp); 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to unroll to the catch block or the nearest "break" 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame. 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A break frame could indicate that we have reached an intermediate 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * native call, or have gone off the top of the stack and the thread 706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * needs to exit. Either way, we return from here, leaving the 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception raised. 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we do find a catch block, we want to transfer execution to 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that point. 7114fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * 7124fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * Note this can cause an exception while resolving classes in 7134fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * the "catch" blocks. 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns, 716fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro exception, false, (void**)(void*)&fp); 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Restore the stack bounds after an overflow. This isn't going to 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * be correct in all circumstances, e.g. if JNI code devours the 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception this won't happen until some other exception gets 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thrown. If the code keeps pushing the stack bounds we'll end 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up aborting the VM. 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note we want to do this *after* the call to dvmFindCatchBlock, 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because that may need extra stack space to resolve exception 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes (e.g. through a class loader). 7284fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * 7294fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * It's possible for the stack overflow handling to cause an 7304fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * exception (specifically, class resolution in a "catch" block 7314fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * during the call above), so we could see the thread's overflow 7324fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * flag raised but actually be running in a "nested" interpreter 7334fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * frame. We don't allow doubled-up StackOverflowErrors, so 7344fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * we can check for this by just looking at the exception type 7354fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * in the cleanup function. Also, we won't unroll past the SOE 7364fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * point because the more-recent exception will hit a break frame 7374fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden * as it unrolls to here. 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->stackOverflowed) 7404fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden dvmCleanupStackOverflow(self, exception); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (catchRelPc < 0) { 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* falling through to JNI code or off the bottom of the stack */ 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 2 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD("Exception %s from %s:%d not caught locally\n", 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetException(self, exception); 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(exception, self); 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_bail(); 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 3 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method; 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD("Exception %s thrown from %s:%d to %s:%d\n", 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLineNumFromPC(curMethod, pc - curMethod->insns), 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmGetMethodSourceFile(catchMethod), 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLineNumFromPC(catchMethod, catchRelPc)); 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Adjust local variables to match self->curFrame and the 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * updated PC. 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //fp = (u4*) self->curFrame; 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project curMethod = SAVEAREA_FROM_FP(fp)->method; 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //methodClass = curMethod->clazz; 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodClassDex = curMethod->clazz->pDvmDex; 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pc = curMethod->insns + catchRelPc; 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 77585745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood curMethod->name, curMethod->shorty); 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DUMP_REGS(curMethod, fp, false); // show all regs 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Restore the exception if the handler wants it. 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The Dalvik spec mandates that, if an exception handler wants to 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * do something with the exception, the first instruction executed 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * must be "move-exception". We can pass the exception along 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * through the thread struct, and let the move-exception instruction 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * clear it for us. 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the handler doesn't call move-exception, we don't want to 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finish here with an exception still pending. 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION) 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetException(self, exception); 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(exception, self); 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FINISH(0); 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7998afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * General handling for invoke-{virtual,super,direct,static,interface}, 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * including "quick" variants. 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set "methodToCall" to the Method we're calling, and "methodCallRange" 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * depending on whether this is a "/range" instruction. 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For a range call: 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vsrc1" holds the argument count (8 bits) 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vdst" holds the first argument in the range 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For a non-range call: 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vsrc1" holds the argument count (4 bits) and the 5th argument index 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vdst" holds four 4-bit register indices 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must EXPORT_PC before jumping here, because any method 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call can throw a stack overflow exception. 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 count, u2 regs) 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;); 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //printf("range=%d call=%p count=%d regs=0x%04x\n", 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // methodCallRange, methodToCall, count, regs); 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor, 82585745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood // methodToCall->name, methodToCall->shorty); 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* outs; 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy args. This may corrupt vsrc1/vdst. 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodCallRange) { 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // could use memcpy or a "Duff's device"; most functions have 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // so few args it won't matter much 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(vsrc1 <= curMethod->outsSize); 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(vsrc1 == methodToCall->insSize); 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs = OUTS_FROM_FP(fp, vsrc1); 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < vsrc1; i++) 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[i] = GET_REGISTER(vdst+i); 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 count = vsrc1 >> 4; 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(count <= curMethod->outsSize); 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(count == methodToCall->insSize); 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(count <= 5); 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs = OUTS_FROM_FP(fp, count); 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count == 5) { 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[4] = GET_REGISTER(vsrc1 & 0x0f); 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count--; 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < (int) count; i++) { 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[i] = GET_REGISTER(vdst & 0x0f); 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vdst >>= 4; 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This version executes fewer instructions but is larger 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // overall. Seems to be a teensy bit faster. 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (count) { 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 5: 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[4] = GET_REGISTER(vsrc1 & 0x0f); 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 4: 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[3] = GET_REGISTER(vdst >> 12); 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 3: 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8); 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 2: 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4); 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 1: 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outs[0] = GET_REGISTER(vdst & 0x0f); 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ; 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This was originally a "goto" target; I've kept it separate from the 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stuff above in case we want to refactor things again.) 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * At this point, we have the arguments stored in the "outs" area of 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the current method's stack frame, and the method to call in 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "methodToCall". Push a new stack frame. 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* newSaveArea; 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* newFp; 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGV("> %s%s.%s %s", 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "", 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->clazz->descriptor, methodToCall->name, 89585745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood methodToCall->shorty); 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize; 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSaveArea = SAVEAREA_FROM_FP(newFp); 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verify that we have enough space */ 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (true) { 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* bottom; 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4); 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (bottom < self->interpStackEnd) { 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* stack overflow */ 9066ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n", 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart, self->interpStackEnd, bottom, 9086ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden (u1*) fp - bottom, self->interpStackSize, 9096ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden methodToCall->name); 9106ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, methodToCall); 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n", 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // fp, newFp, newSaveArea, bottom); 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef LOG_INSTR 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (methodToCall->registersSize > methodToCall->insSize) { 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This makes valgrind quiet when we print registers that 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * haven't been initialized. Turn it off when the debug 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * messages are disabled -- we want valgrind to report any 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used-before-initialized issues. 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(newFp, 0xcc, 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (methodToCall->registersSize - methodToCall->insSize) * 4); 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSaveArea->prevSave = SAVEAREA_FROM_FP(fp); 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSaveArea->prevFrame = fp; 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSaveArea->savedPc = pc; 9369a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) && defined(MTERP_STUB) 937ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng newSaveArea->returnAddr = 0; 938ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSaveArea->method = methodToCall; 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 9419a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode != 0) { 9429a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 9439a3147c7412f4794434b4c2604aa2ba784867774buzbee * We mark ENTER here for both native and non-native 9449a3147c7412f4794434b4c2604aa2ba784867774buzbee * calls. For native calls, we'll mark EXIT on return. 9459a3147c7412f4794434b4c2604aa2ba784867774buzbee * For non-native calls, EXIT is marked in the RETURN op. 9469a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 9479a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmReportInvoke(self, methodToCall); 9489a3147c7412f4794434b4c2604aa2ba784867774buzbee } 9499a3147c7412f4794434b4c2604aa2ba784867774buzbee 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsNativeMethod(methodToCall)) { 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "Call" interpreted code. Reposition the PC, update the 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame pointer and other local state, and continue. 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project curMethod = methodToCall; 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodClassDex = curMethod->clazz->pDvmDex; 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pc = methodToCall->insns; 958fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro self->curFrame = fp = newFp; 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugSaveArea = SAVEAREA_FROM_FP(newFp); 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 9629a3147c7412f4794434b4c2604aa2ba784867774buzbee self->debugIsMethodEntry = true; // profiling, debugging 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 96485745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood curMethod->name, curMethod->shorty); 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DUMP_REGS(curMethod, fp, true); // show input args 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FINISH(0); // jump to method start 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* set this up for JNI locals, even if not a JNI native */ 969d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = newFp; 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DUMP_REGS(methodToCall, newFp, true); // show input args 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 9759a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode != 0) { 9769a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmReportPreNativeInvoke(pc, self, methodToCall); 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 9799a3147c7412f4794434b4c2604aa2ba784867774buzbee ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor, 9809a3147c7412f4794434b4c2604aa2ba784867774buzbee methodToCall->name, methodToCall->shorty); 981d726991ba52466cde88e37aba4de2395b62477faBill Buzbee 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Jump through native call bridge. Because we leave no 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * space for locals on native calls, "newFp" points directly 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the method arguments. 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self); 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 9899a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode != 0) { 9909a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmReportPostNativeInvoke(pc, self, methodToCall); 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* pop frame off */ 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, newSaveArea); 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = fp; 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the native code threw an exception, or interpreted code 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked by the native call threw one and nobody has cleared 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it, jump to our local exception handling. 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Exception thrown by/below native code\n"); 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GOTO_exceptionThrown(); 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGD("> retval=0x%llx (leaving native)", retval.j); 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ILOGD("> (return from native %s.%s to %s.%s %s)", 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodToCall->clazz->descriptor, methodToCall->name, 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project curMethod->clazz->descriptor, curMethod->name, 101185745e148153894aac52ad3d7f6a36a7767b45a0Mike Lockwood curMethod->shorty); 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //u2 invokeInstr = INST_INST(FETCH(0)); 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project invokeInstr <= OP_INVOKE_INTERFACE*/) 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FINISH(3); 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGE("Unknown invoke instr %02x at %d\n", 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // invokeInstr, (int) (pc - curMethod->insns)); 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); // should not get here 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectGOTO_TARGET_END 1027