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=0fcc83077183e0db0cbeaf21215274a5a5d60ae7;hb=44ae66df31d1ad4f0d390e982e5a4b7a5672e8c0;hpb=c9acde01b456c40967ce0b466af8e6847564de7a 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 0fcc830..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,7 +116,30 @@ public class JPF_java_lang_reflect_Method extends NativePeer { } // TODO: Fix for Groovy's model-checking - private static int getParameterizedTypeImplObj(String signature, MJIEnv env) { + 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(); @@ -133,14 +157,26 @@ public class JPF_java_lang_reflect_Method extends NativePeer { ei.setReferenceField("rawType", gci.getClassObjectRef()); // actualTypeArguments - String[] parameterizedTypes = Types.getParameterizedTypesFromArgumentTypeNames(signature); + 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++) { - ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]); - if (!pci.isRegistered()) { - pci.registerClass(ti); + 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(); } - types[j] = pci.getClassObjectRef(); } int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length); // Set references for every array element @@ -164,15 +200,96 @@ public class JPF_java_lang_reflect_Method extends NativePeer { 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])) { - ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env); + 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()) { @@ -185,7 +302,6 @@ public class JPF_java_lang_reflect_Method extends NativePeer { for (int i = 0; i < argTypeNames.length; i++) { env.setReferenceArrayElement(aRef, i, ar[i]); } - return aRef; } @@ -199,12 +315,28 @@ public class JPF_java_lang_reflect_Method extends NativePeer { MethodInfo mi = getMethodInfo(env, objRef); ThreadInfo ti = env.getThreadInfo(); - String returnTypeName = mi.getGenericReturnTypeName(); + String genRetType = mi.getGenericReturnTypeName(); + String classGenericSig = mi.getClassInfo().getGenericSignature(); + String methodGenericSig = mi.getGenericSignature(); int retRef; - if (Types.isGenericSignature(returnTypeName)) { - retRef = getParameterizedTypeImplObj(returnTypeName, env); + + 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(returnTypeName); + ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName()); if (!ci.isRegistered()) { ci.registerClass(ti); } @@ -214,7 +346,6 @@ public class JPF_java_lang_reflect_Method extends NativePeer { return retRef; } // TODO: Fix for Groovy's model-checking - // TODO: We have been able to only register the generic class and not yet the parameterized types int getExceptionTypes(MJIEnv env, MethodInfo mi) { ThreadInfo ti = env.getThreadInfo();