package gov.nasa.jpf.jvm;
-import gov.nasa.jpf.Config;
-import gov.nasa.jpf.util.Misc;
-import gov.nasa.jpf.util.StringSetMatcher;
-import gov.nasa.jpf.vm.*;
-
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.LinkedList;
+
+import gov.nasa.jpf.Config;
+import gov.nasa.jpf.util.Misc;
+import gov.nasa.jpf.util.StringSetMatcher;
+import gov.nasa.jpf.vm.AbstractTypeAnnotationInfo;
+import gov.nasa.jpf.vm.AnnotationInfo;
+import gov.nasa.jpf.vm.BootstrapMethodInfo;
+import gov.nasa.jpf.vm.BytecodeAnnotationInfo;
+import gov.nasa.jpf.vm.BytecodeTypeParameterAnnotationInfo;
+import gov.nasa.jpf.vm.ClassInfo;
+import gov.nasa.jpf.vm.ClassInfoException;
+import gov.nasa.jpf.vm.ClassLoaderInfo;
+import gov.nasa.jpf.vm.ClassParseException;
+import gov.nasa.jpf.vm.DirectCallStackFrame;
+import gov.nasa.jpf.vm.ExceptionHandler;
+import gov.nasa.jpf.vm.ExceptionParameterAnnotationInfo;
+import gov.nasa.jpf.vm.FieldInfo;
+import gov.nasa.jpf.vm.FormalParameterAnnotationInfo;
+import gov.nasa.jpf.vm.GenericSignatureHolder;
+import gov.nasa.jpf.vm.InfoObject;
+import gov.nasa.jpf.vm.LocalVarInfo;
+import gov.nasa.jpf.vm.MethodInfo;
+import gov.nasa.jpf.vm.NativeMethodInfo;
+import gov.nasa.jpf.vm.StackFrame;
+import gov.nasa.jpf.vm.SuperTypeAnnotationInfo;
+import gov.nasa.jpf.vm.ThreadInfo;
+import gov.nasa.jpf.vm.ThrowsAnnotationInfo;
+import gov.nasa.jpf.vm.TypeAnnotationInfo;
+import gov.nasa.jpf.vm.TypeParameterAnnotationInfo;
+import gov.nasa.jpf.vm.TypeParameterBoundAnnotationInfo;
+import gov.nasa.jpf.vm.Types;
+import gov.nasa.jpf.vm.VariableAnnotationInfo;
/**
* a ClassInfo that was created from a Java classfile
//--- annotations
protected AnnotationInfo[] annotations;
protected AnnotationInfo curAi;
+ protected LinkedList<AnnotationInfo> annotationStack;
+ protected LinkedList<Object[]> valuesStack;
protected AnnotationInfo[][] parameterAnnotations;
protected Object[] values;
+ // true if we need to filter null annotations
+ private boolean compactAnnotationArray = false;
//--- declaration annotations
@Override
public void setAnnotation (ClassFile cf, Object tag, int annotationIndex, String annotationType) {
if (tag instanceof InfoObject) {
- curAi = getResolvedAnnotationInfo(Types.getClassNameFromTypeName(annotationType));
- annotations[annotationIndex] = curAi;
+ if(annotationIndex == -1) {
+ if(annotationStack == null) {
+ assert valuesStack == null;
+ valuesStack = new LinkedList<>();
+ annotationStack = new LinkedList<>();
+ }
+ annotationStack.addFirst(curAi);
+ valuesStack.addFirst(values);
+ }
+ try {
+ curAi = getResolvedAnnotationInfo(Types.getClassNameFromTypeName(annotationType));
+ if(annotationIndex != -1) {
+ annotations[annotationIndex] = curAi;
+ }
+ } catch(ClassInfoException cie) {
+ // if we can't parse a field, we're sunk, throw and tank the reflective call
+ if(annotationIndex == -1) {
+ throw cie;
+ }
+ compactAnnotationArray = true;
+ annotations[annotationIndex] = null;
+ // skip this annotation
+ throw new SkipAnnotation();
+ }
}
}
@Override
public void setAnnotationsDone (ClassFile cf, Object tag) {
if (tag instanceof InfoObject) {
- ((InfoObject) tag).addAnnotations(annotations);
+ AnnotationInfo[] toSet;
+ if(compactAnnotationArray) {
+ int nAnnot = 0;
+ for(AnnotationInfo ai : annotations) {
+ if(ai != null) {
+ nAnnot++;
+ }
+ }
+ toSet = new AnnotationInfo[nAnnot];
+ int idx = 0;
+ for(AnnotationInfo ai : annotations) {
+ if(ai != null) {
+ toSet[idx++] = ai;
+ }
+ }
+ } else {
+ toSet = annotations;
+ }
+ ((InfoObject) tag).addAnnotations(toSet);
}
+ compactAnnotationArray = false;
}
@Override
@Override
public void setParameterAnnotation (ClassFile cf, Object tag, int annotationIndex, String annotationType) {
- curAi = getResolvedAnnotationInfo(Types.getClassNameFromTypeName(annotationType));
- annotations[annotationIndex] = curAi;
+ try {
+ curAi = getResolvedAnnotationInfo(Types.getClassNameFromTypeName(annotationType));
+ annotations[annotationIndex] = curAi;
+ } catch(ClassInfoException cie) {
+ compactAnnotationArray = true;
+ annotations[annotationIndex] = null;
+ throw new SkipAnnotation();
+ }
}
@Override
public void setAnnotationValueCount (ClassFile cf, Object tag, int annotationIndex, int nValuePairs) {
// if we have values, we need to clone the defined annotation so that we can overwrite entries
curAi = curAi.cloneForOverriddenValues();
- annotations[annotationIndex] = curAi;
+ if(annotationIndex != -1) {
+ annotations[annotationIndex] = curAi;
+ }
}
@Override
curAi.setClonedEntryValue(elementName, val);
}
}
+
+ @Override
+ public void setAnnotationFieldValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex, String elementName, int arrayIndex) {
+ assert annotationStack.size() > 0;
+ AnnotationInfo ai = curAi;
+ values = valuesStack.pop();
+ curAi = annotationStack.pop();
+ if(arrayIndex >= 0) {
+ values[arrayIndex] = ai;
+ } else {
+ curAi.setClonedEntryValue(elementName, ai);
+ }
+ }
@Override
public void setStringAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,