changeset 442:0b204ee93eaf

@States should be acceptable down the hierarchy: accept any subclass of @State-marked class as the parameter.
author shade
date Fri, 28 Feb 2014 16:24:44 +0400
parents e285f2d94773
children e574a5c575bb
files jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMClassInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ClassInfoRepo.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGeneratorUtils.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/HelperMethodValidationPlugin.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/StateObjectHandler.java
diffstat 6 files changed, 31 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMClassInfo.java	Fri Feb 28 15:44:40 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMClassInfo.java	Fri Feb 28 16:24:44 2014 +0400
@@ -56,6 +56,7 @@
     private final List<FieldInfo> fields;
     private final Map<String, AnnHandler> annotations = new HashMap<String, AnnHandler>();
     private final ClassInfoRepo classInfos;
+    private String superName;
 
     public ASMClassInfo(ClassInfoRepo classInfos) {
         super(Opcodes.ASM4);
@@ -72,6 +73,7 @@
     @Override
     public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
         super.visit(version, access, name, signature, superName, interfaces);
+        this.superName = superName;
         this.idName = name;
         this.access = access;
         qualifiedName = name.replaceAll("/", ".");
@@ -150,8 +152,7 @@
 
     @Override
     public ClassInfo getSuperclass() {
-        // TODO: FIXME
-        return null;
+        return classInfos.get(superName);
     }
 
     @Override
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ClassInfoRepo.java	Fri Feb 28 15:44:40 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ClassInfoRepo.java	Fri Feb 28 16:24:44 2014 +0400
@@ -37,10 +37,6 @@
 
     public ClassInfo get(String desc) {
         Type type = Type.getType(desc);
-        return get(type);
-    }
-
-    public ClassInfo get(Type type) {
         return map.get(type);
     }
 
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Fri Feb 28 15:44:40 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Fri Feb 28 16:24:44 2014 +0400
@@ -214,12 +214,17 @@
         // validate all arguments are @State-s
         for (MethodInfo e : methods) {
             for (ParameterInfo var : e.getParameters()) {
+                if (BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(var.getType(), State.class) == null) {
+                    throw new GenerationException(
+                            "Method parameters should be @" + State.class.getSimpleName() + " classes.",
+                            e);
+                }
                 states.add(var.getType());
             }
         }
 
         // validate if enclosing class is implicit @State
-        if (clazz.getAnnotation(State.class) != null) {
+        if (BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(clazz, State.class) != null) {
             states.add(clazz);
         }
 
@@ -229,7 +234,7 @@
             // we need to preemptively check the annotation value, and
             // the API can only allow that by catching the exception, argh.
             try {
-                state.getAnnotation(State.class).value();
+                BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(state, State.class).value();
             } catch (IncompleteAnnotationException iae) {
                 throw new GenerationException("The " + State.class.getSimpleName() +
                         " annotation should have the explicit " + Scope.class.getSimpleName() + " argument",
@@ -255,7 +260,7 @@
         }
 
         // validate against rogue fields
-        if (clazz.getAnnotation(State.class) == null || clazz.isAbstract()) {
+        if (BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(clazz, State.class) == null || clazz.isAbstract()) {
             for (FieldInfo fi : BenchmarkGeneratorUtils.getAllFields(clazz)) {
                 // allow static fields
                 if (fi.isStatic()) continue;
@@ -278,7 +283,7 @@
                         + " method can not be abstract.", m);
             }
             if (m.isSynchronized()) {
-                if (clazz.getAnnotation(State.class) == null) {
+                if (BenchmarkGeneratorUtils.getAnnotationRecursive(m, State.class) == null) {
                     throw new GenerationException("@" + GenerateMicroBenchmark.class.getSimpleName()
                             + " method can only be synchronized if the enclosing class is annotated with "
                             + "@" + State.class.getSimpleName() + ".", m);
@@ -309,7 +314,7 @@
                 MethodInfo meth = group.methods().iterator().next();
                 if (meth.getAnnotation(Group.class) == null) {
                     for (ParameterInfo param : meth.getParameters()) {
-                        State stateAnn = param.getType().getAnnotation(State.class);
+                        State stateAnn = BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(param.getType(), State.class);
                         if (stateAnn != null && stateAnn.value() == Scope.Group) {
                             throw new GenerationException(
                                     "Only @" + Group.class.getSimpleName() + " methods can reference @" + State.class.getSimpleName()
@@ -318,7 +323,7 @@
                         }
                     }
 
-                    State stateAnn = meth.getOwner().getAnnotation(State.class);
+                    State stateAnn = BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(meth.getOwner(), State.class);
                     if (stateAnn != null && stateAnn.value() == Scope.Group) {
                         throw new GenerationException(
                                 "Only @" + Group.class.getSimpleName() + " methods can implicitly reference @" + State.class.getSimpleName()
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGeneratorUtils.java	Fri Feb 28 15:44:40 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGeneratorUtils.java	Fri Feb 28 16:24:44 2014 +0400
@@ -86,6 +86,19 @@
         return ls;
     }
 
+    public static <T extends Annotation> T getAnnotationRecursiveSuper(ClassInfo ci, Class<T> annClass) {
+        T ann = ci.getAnnotation(annClass);
+        if (ann != null) {
+            return ann;
+        } else {
+            ClassInfo eci = ci.getSuperclass();
+            if (eci != null) {
+                return getAnnotationRecursive(eci, annClass);
+            }
+        }
+        return null;
+    }
+
     public static <T extends Annotation> T getAnnotationRecursive(ClassInfo ci, Class<T> annClass) {
         T ann = ci.getAnnotation(annClass);
         if (ann != null) {
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/HelperMethodValidationPlugin.java	Fri Feb 28 15:44:40 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/HelperMethodValidationPlugin.java	Fri Feb 28 16:24:44 2014 +0400
@@ -37,7 +37,7 @@
         try {
             for (MethodInfo element : BenchmarkGeneratorUtils.getMethodsAnnotatedWith(source, Setup.class)) {
                 // OK to have these annotation for @State objects
-                if (element.getOwner().getAnnotation(State.class) != null) continue;
+                if (BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(element.getOwner(), State.class) != null) continue;
 
                 // Abstract classes are not instantiated, assume OK
                 if (element.getOwner().isAbstract()) continue;
@@ -51,7 +51,7 @@
 
             for (MethodInfo element : BenchmarkGeneratorUtils.getMethodsAnnotatedWith(source, TearDown.class)) {
                 // OK to have these annotation for @State objects
-                if (element.getOwner().getAnnotation(State.class) != null) continue;
+                if (BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(element.getOwner(), State.class) != null) continue;
 
                 // Abstract classes are not instantiated, assume OK
                 if (element.getOwner().isAbstract()) continue;
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/StateObjectHandler.java	Fri Feb 28 15:44:40 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/StateObjectHandler.java	Fri Feb 28 16:24:44 2014 +0400
@@ -99,7 +99,7 @@
     }
 
     public void bindArg(MethodInfo mi, ParameterInfo pi) {
-        State ann = pi.getType().getAnnotation(State.class);
+        State ann = BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(pi.getType(), State.class);
         if (ann != null) {
             bindState(mi, pi.getType(), ann.value(), null);
         } else {
@@ -112,7 +112,7 @@
     }
 
     public void bindImplicit(ClassInfo ci, String label, Scope scope) {
-        State ann = ci.getAnnotation(State.class);
+        State ann = BenchmarkGeneratorUtils.getAnnotationRecursiveSuper(ci, State.class);
         bindState(null, ci, (ann != null) ? ann.value() : scope, label);
     }