package com.lody.legend.dalvik; import static com.lody.legend.dalvik.DalvikConstants.*; /** * @author Lody * @version 1.0 */ public class DalvikHelper { public static int dvmComputeJniArgInfo(String shorty) { int returnType, jniArgInfo; int hints; /* The first shorty character is the return type. */ switch (shorty.charAt(0)) { 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; }//end switch jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT; hints = dvmPlatformInvokeHints(shorty); if ((hints & DALVIK_JNI_NO_ARG_INFO) != 0) { jniArgInfo |= DALVIK_JNI_NO_ARG_INFO; } else { jniArgInfo |= hints; } return jniArgInfo; } public static int dvmPlatformInvokeHints(String shorty) { int padFlags, jniHints; char sigByte; int stackOffset, padMask; stackOffset = padFlags = 0; padMask = 0x00000001; /* Skip past the return type */ int index = 1; while (index < shorty.length()) { sigByte = shorty.charAt(index); index++; 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 { stackOffset -= 2; // r2/r3 holds first two items if (stackOffset < 0) stackOffset = 0; jniHints |= ((stackOffset + 1) / 2) << DALVIK_JNI_COUNT_SHIFT; jniHints |= padFlags; } return jniHints; } public static int dvmCalcMethodArgsSize(String shorty) { int count = 0; /* Skip the return type. */ int index = 1; char currentChar; while (index < shorty.length()) { currentChar = shorty.charAt(index); index++; switch (currentChar) { case 'D': case 'J':{ count += 2; break; } default: count++; break; }//end switch }//end while return count; } }