X-Git-Url: http://plrg.eecs.uci.edu/git/?p=jpf-core.git;a=blobdiff_plain;f=src%2Fpeers%2Fgov%2Fnasa%2Fjpf%2Fvm%2FJPF_java_lang_reflect_Method.java;h=05c049fa7a9138614cf748bc4777fd5f3598ba28;hp=964968d2b32d92519fb29b5925ac26435986250b;hb=44ae66df31d1ad4f0d390e982e5a4b7a5672e8c0;hpb=af70e60350d4959e783bd2177dffe0ea087c446c diff --git a/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java b/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java index 964968d..05c049f 100644 --- a/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java +++ b/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java @@ -23,6 +23,7 @@ import gov.nasa.jpf.util.MethodInfoRegistry; import gov.nasa.jpf.util.RunListener; import gov.nasa.jpf.util.RunRegistry; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -115,18 +116,237 @@ public class JPF_java_lang_reflect_Method extends NativePeer { } // TODO: Fix for Groovy's model-checking + private static int getGenericArrayTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) { + + ThreadInfo ti = env.getThreadInfo(); + ClassLoaderInfo cli = env.getSystemClassLoaderInfo(); + ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl"); + + // Create a new object of type GenericArrayTypeImpl + int genArrRef = env.newObject(ci); + ElementInfo ei = env.getModifiableElementInfo(genArrRef); + + // Get field information and fill out the fields + String clsSig = Types.getArrayClassName(signature); + int paramTypeRef; + if (Types.isParameterWithType(clsSig)) { + paramTypeRef = getTypeVariableImplObject(env, objRef, clsSig); + } else { + paramTypeRef = getParameterizedTypeImplObj(clsSig, env, objRef, mi); + } + ei.setReferenceField("genericComponentType", paramTypeRef); + + return genArrRef; + } + + private static int getParameterizedTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) { + + ThreadInfo ti = env.getThreadInfo(); + ClassLoaderInfo cli = env.getSystemClassLoaderInfo(); + ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl"); + // Create a new object of type ParameterizedTypeImpl + int paramTypeRef = env.newObject(ci); + ElementInfo ei = env.getModifiableElementInfo(paramTypeRef); + // Get field information and fill out the fields + // rawType field + String className = Types.getGenericClassName(signature); + ClassInfo gci = cli.getResolvedClassInfo(className); + if (!gci.isRegistered()) { + gci.registerClass(ti); + } + ei.setReferenceField("rawType", gci.getClassObjectRef()); + + // actualTypeArguments + String[] parameterizedTypes = Types.getParameterizedTypes(signature); + int[] types = new int[parameterizedTypes.length]; + String classGenericSig = mi.getClassInfo().getGenericSignature(); + String methodGenericSig = mi.getGenericSignature(); + for(int j = 0; j < parameterizedTypes.length; j++) { + if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) || + Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) { + types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]); + } else if (Types.isWildcardType(parameterizedTypes[j])) { + types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j], mi); + } else if (Types.isParameterizedType(parameterizedTypes[j])) { + // Recursion! + types[j] = getParameterizedTypeImplObj(parameterizedTypes[j], env, objRef, mi); + } else { + ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]); + if (!pci.isRegistered()) { + pci.registerClass(ti); + } + types[j] = pci.getClassObjectRef(); + } + } + int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length); + // Set references for every array element + for (int j = 0; j < parameterizedTypes.length; j++) { + env.setReferenceArrayElement(aRef, j, types[j]); + } + ei.setReferenceField("actualTypeArguments", aRef); + + // ownerType + String ownerType = Types.getOwnerClassName(signature); + if (ownerType != null) { + ClassInfo oci = ClassLoaderInfo.getCurrentResolvedClassInfo(ownerType); + if (!oci.isRegistered()) { + oci.registerClass(ti); + } + ei.setReferenceField("ownerType", oci.getClassObjectRef()); + } else { + ei.setReferenceField("ownerType", MJIEnv.NULL); + } + + return paramTypeRef; + } + + private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType, MethodInfo mi) { + ThreadInfo ti = env.getThreadInfo(); + ClassLoaderInfo cli = env.getSystemClassLoaderInfo(); + ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.WildcardTypeImpl"); + + int wildcardRef = env.newObject(ci); + ElementInfo ei = env.getModifiableElementInfo(wildcardRef); + // Type parameter test + // TODO: This test could probably be made cleaner + String classGenericSig = mi.getClassInfo().getGenericSignature(); + String methodGenericSig = mi.getGenericSignature(); + String typeParameter = Types.getTypeParameter(wildcardType); + int uRef = MJIEnv.NULL; + int lRef = MJIEnv.NULL; + if (Types.isTypeParameter(typeParameter, methodGenericSig) || + Types.isTypeParameter(typeParameter, classGenericSig)) { + int tpRef = getTypeVariableImplObject(env, objRef, typeParameter); + if (wildcardType.startsWith("+")) { + // Set upperBounds + uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(uRef, 0, tpRef); + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0); + } else { // wildcardType.startsWith("-") + // Set lowerBounds + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(lRef, 0, tpRef); + uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0); + } + } else { + + String actualType = Types.getWildcardType(wildcardType); + ClassInfo uci = cli.getResolvedClassInfo(actualType); + if (!uci.isRegistered()) { + uci.registerClass(ti); + } + if (wildcardType.startsWith("+L") || wildcardType.equals("*")) { + // Set upperBounds + uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef()); + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0); + } else { // wildcardType.startsWith("-L") + // Set lowerBounds + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef()); + } + } + ei.setReferenceField("upperBounds", uRef); + ei.setReferenceField("lowerBounds", lRef); + + return wildcardRef; + } + + private static int getTypeVariableImplObject(MJIEnv env, int objRef, String parameterizedType) { + + ClassLoaderInfo cli = env.getSystemClassLoaderInfo(); + ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl"); + + int typeVarRef = env.newObject(ci); + ElementInfo ei = env.getModifiableElementInfo(typeVarRef); + // genericDeclaration contains this java.lang.reflect.Method object + ei.setReferenceField("genericDeclaration", objRef); + ei.setReferenceField("name", env.newString(parameterizedType)); + + return typeVarRef; + } + + static int getGenericParameterTypes( MJIEnv env, int objRef, MethodInfo mi) { + ThreadInfo ti = env.getThreadInfo(); + String[] argTypeNames = mi.getArgumentGenericTypeNames(); + int[] ar = new int[argTypeNames.length]; + + String classGenericSig = mi.getClassInfo().getGenericSignature(); + String methodGenericSig = mi.getGenericSignature(); + for (int i = 0; i < argTypeNames.length; i++) { + // Change this into just the generic class type if it is a generic class + if (Types.isGenericSignature(argTypeNames[i])) { + if (Types.isArraySignature(argTypeNames[i])) { + // Generic array + ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi); + } else { + ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env, objRef, mi); + } + } else if (Types.isTypeParameter(argTypeNames[i], methodGenericSig) || + Types.isTypeParameter(argTypeNames[i], classGenericSig)) { + if (Types.isArraySignature(argTypeNames[i])) { + // Generic array + ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi); + } else { + ar[i] = getTypeVariableImplObject(env, objRef, argTypeNames[i]); + } + } else { + ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]); + if (!ci.isRegistered()) { + ci.registerClass(ti); + } + ar[i] = ci.getClassObjectRef(); + } + } + int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", argTypeNames.length); + for (int i = 0; i < argTypeNames.length; i++) { + env.setReferenceArrayElement(aRef, i, ar[i]); + } + return aRef; + } + @MJI public int getGenericParameterTypes_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){ - //return getGenericParameterTypes(env, getMethodInfo(env, objRef)); - return getParameterTypes_____3Ljava_lang_Class_2 (env, objRef); + return getGenericParameterTypes(env, objRef, getMethodInfo(env, objRef)); } @MJI public int getGenericReturnType____Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){ - return getReturnType____Ljava_lang_Class_2(env, objRef); + MethodInfo mi = getMethodInfo(env, objRef); + ThreadInfo ti = env.getThreadInfo(); + + String genRetType = mi.getGenericReturnTypeName(); + String classGenericSig = mi.getClassInfo().getGenericSignature(); + String methodGenericSig = mi.getGenericSignature(); + int retRef; + + if (Types.isGenericSignature(genRetType)) { + if (Types.isArraySignature(genRetType)) { + // Generic array + retRef = getGenericArrayTypeImplObj(genRetType, env, objRef, mi); + } else { + retRef = getParameterizedTypeImplObj(genRetType, env, objRef, mi); + } + } else if (Types.isTypeParameter(genRetType, methodGenericSig) || + Types.isTypeParameter(genRetType, classGenericSig)) { + if (Types.isArraySignature(genRetType)) { + // Generic array + retRef = getGenericArrayTypeImplObj(genRetType, env, objRef, mi); + } else { + retRef = getTypeVariableImplObject(env, objRef, genRetType); + } + } else { + ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName()); + if (!ci.isRegistered()) { + ci.registerClass(ti); + } + retRef = ci.getClassObjectRef(); + } + + return retRef; } // TODO: Fix for Groovy's model-checking - + int getExceptionTypes(MJIEnv env, MethodInfo mi) { ThreadInfo ti = env.getThreadInfo(); String[] exceptionNames = mi.getThrownExceptionClassNames();