u4 dvmPlatformInvokeHints(const DexProto* proto) { const char* sig = dexProtoGetShorty(proto); unsigned int wordCount = 0; char sigByte; while (1) { /* * Move past return type; dereference sigByte */ sigByte = *(++sig); if (sigByte == '\0') { break; } ++wordCount; if (sigByte == 'D' || sigByte == 'J') { ++wordCount; } } /* * Check for Dex file limitation and return */ if (wordCount > 0xFFFF) { return DALVIK_JNI_NO_ARG_INFO; } return wordCount; }
/* (documented in header file) */ int dexProtoComputeArgsSize(const DexProto* pProto) { #ifdef FASTIVA if (FASTIVA_IS_FASTIVA_PROTO(pProto)) { JNI_ArgIterator pIterator[1]; int argList_id = FASTIVA_ARG_LIST_ID(pProto); int cntArg = ((JNI_ArgIterator*)pIterator)->init(argList_id); return cntArg; } #endif const char* shorty = dexProtoGetShorty(pProto); int count = 0; /* Skip the return type. */ shorty++; for (;;) { switch (*(shorty++)) { case '\0': { return count; } case 'D': case 'J': { count += 2; break; } default: { count++; break; } } } }
/* * The class loader will associate with each method a 32-bit info word * (jniArgInfo) to support JNI calls. The high order 4 bits of this word * are the same for all targets, while the lower 28 are used for hints to * allow accelerated JNI bridge transfers. * * jniArgInfo (32-bit int) layout: * * SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH * * S - if set, ignore the hints and do things the hard way (scan signature) * R - return-type enumeration * H - target-specific hints (see below for details) * * This function produces mips-specific hints - specifically a description * of padding required to keep all 64-bit parameters properly aligned. * * MIPS JNI hint format(Same as ARM) * * LLLL FFFFFFFF FFFFFFFF FFFFFFFF * * L - number of double-words of storage required on the stack (0-30 words) * F - pad flag -- if set, the stack increases 8 bytes, else the stack increases 4 bytes * after copying 32 bits args into stack. (little different from ARM) * * If there are too many arguments to construct valid hints, this function will * return a result with the S bit set. */ u4 dvmPlatformInvokeHints(const DexProto* proto) { #ifdef FASTIVA u4 fastiva_dvmPlatformInvokeHints( const char* sig); const char* sig = dexProtoGetShorty(proto); return fastiva_dvmPlatformInvokeHints(sig); }
u4 fastiva_dvmPlatformInvokeHints( const char* sig) { #else const char* sig = dexProtoGetShorty(proto); #endif int padFlags, jniHints; char sigByte; int stackOffset, padMask, hints; stackOffset = padFlags = 0; padMask = 0x00000001; /* Skip past the return type */ sig++; while (true) { sigByte = *(sig++); if (sigByte == '\0') break; if (sigByte == 'D' || sigByte == 'J') { if ((stackOffset & 1) != 0) { padFlags |= padMask; stackOffset++; padMask <<= 1; } stackOffset += 2; padMask <<= 2; } else { stackOffset++; padMask <<= 1; } } jniHints = 0; if (stackOffset > DALVIK_JNI_COUNT_SHIFT) { /* too big for "fast" version */ jniHints = DALVIK_JNI_NO_ARG_INFO; } else { assert((padFlags & (0xffffffff << DALVIK_JNI_COUNT_SHIFT)) == 0); /* * StackOffset includes the space for a2/a3. However we have reserved * 16 bytes on stack in CallO32.S, so we should subtract 2 from stackOffset. */ stackOffset -= 2; if (stackOffset < 0) stackOffset = 0; jniHints |= ((stackOffset+1) / 2) << DALVIK_JNI_COUNT_SHIFT; jniHints |= padFlags; } return jniHints; }
static int computeJniArgInfo(const DexProto* proto) { const char* sig = dexProtoGetShorty(proto); int returnType, jniArgInfo; u4 hints; /* The first shorty character is the return type. */ switch (*(sig++)) { case 'V': returnType = DALVIK_JNI_RETURN_VOID; break; case 'F': returnType = DALVIK_JNI_RETURN_FLOAT; break; case 'D': returnType = DALVIK_JNI_RETURN_DOUBLE; break; case 'J': returnType = DALVIK_JNI_RETURN_S8; break; case 'Z': case 'B': returnType = DALVIK_JNI_RETURN_S1; break; case 'C': returnType = DALVIK_JNI_RETURN_U2; break; case 'S': returnType = DALVIK_JNI_RETURN_S2; break; default: returnType = DALVIK_JNI_RETURN_S4; break; } jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT; hints = dvmPlatformInvokeHints(proto); if (hints & DALVIK_JNI_NO_ARG_INFO) { jniArgInfo |= DALVIK_JNI_NO_ARG_INFO; } else { assert((hints & DALVIK_JNI_RETURN_MASK) == 0); jniArgInfo |= hints; } return jniArgInfo; }