changeset 428:82c32cef2e5d

Experimental jmh-generator-maven-plugin and ASMv4 bytecode parsers.
author shade
date Fri, 28 Feb 2014 00:11:43 +0400
parents a633786bb7b9
children 29381d15537a
files jmh-core/pom.xml jmh-core/src/main/java/org/openjdk/jmh/generators/annotations/APClassInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMClassInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMFieldInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMGeneratorSource.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMMethodInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMParameterInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/AnnHandler.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ClassInfoRepo.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/SourceElementError.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/SourceError.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/SourceThrowableError.java jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/UnresolvedClassException.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java jmh-core/src/main/java/org/openjdk/jmh/generators/reflective/ReflectiveClassInfo.java jmh-core/src/main/java/org/openjdk/jmh/generators/source/ClassInfo.java jmh-generator-maven-plugin/pom.xml jmh-generator-maven-plugin/src/main/java/org/openjdk/jmh/JmhMojo.java pom.xml
diffstat 19 files changed, 1186 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/jmh-core/pom.xml	Wed Feb 26 17:18:42 2014 +0400
+++ b/jmh-core/pom.xml	Fri Feb 28 00:11:43 2014 +0400
@@ -67,6 +67,11 @@
             <artifactId>commons-math3</artifactId>
             <version>3.2</version>
         </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm</artifactId>
+            <version>4.2</version>
+        </dependency>
     </dependencies>
 
     <prerequisites>
@@ -113,7 +118,7 @@
                         <configuration>
                             <header>file:///${project.basedir}/../src/license/gpl_cpe/header.txt</header>
                             <skipExistingHeaders>false</skipExistingHeaders>
-                            <strictCheck>true</strictCheck>
+                            <strictCheck>${project.bu}</strictCheck>
                             <mapping>
                                 <java>PHP</java>
                             </mapping>
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/annotations/APClassInfo.java	Wed Feb 26 17:18:42 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/annotations/APClassInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -68,11 +68,6 @@
     }
 
     @Override
-    public boolean isNested() {
-        return el.getNestingKind().isNested();
-    }
-
-    @Override
     public String getNestedName() {
         return AnnUtils.getNestedName(el);
     }
@@ -146,11 +141,6 @@
     }
 
     @Override
-    public boolean isStatic() {
-        return el.getModifiers().contains(Modifier.STATIC);
-    }
-
-    @Override
     public boolean isStrictFP() {
         return el.getModifiers().contains(Modifier.STRICTFP);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMClassInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.openjdk.jmh.generators.source.ClassInfo;
+import org.openjdk.jmh.generators.source.FieldInfo;
+import org.openjdk.jmh.generators.source.MethodInfo;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ASMClassInfo extends ClassVisitor implements ClassInfo {
+
+    private String idName;
+    private String packageName;
+    private String qualifiedName;
+    private String name;
+    private int access;
+
+    private final List<MethodInfo> methods;
+    private final List<MethodInfo> constructors;
+    private final List<FieldInfo> fields;
+    private final Map<String, AnnHandler> annotations = new HashMap<String, AnnHandler>();
+    private final ClassInfoRepo classInfos;
+
+    public ASMClassInfo(ClassInfoRepo classInfos) {
+        super(Opcodes.ASM4);
+        this.classInfos = classInfos;
+        methods = new ArrayList<MethodInfo>();
+        constructors = new ArrayList<MethodInfo>();
+        fields = new ArrayList<FieldInfo>();
+    }
+
+    public String getIdName() {
+        return idName;
+    }
+
+    @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.idName = name;
+        this.access = access;
+        qualifiedName = name.replaceAll("/", ".");
+        packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
+        this.name = qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1);
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annClass) {
+        AnnHandler handler = annotations.get(annClass.getCanonicalName());
+        if (handler == null) {
+            return null;
+        } else {
+            return (T) Proxy.newProxyInstance(
+                    this.getClass().getClassLoader(),
+                    new Class[]{annClass},
+                    handler);
+        }
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
+        AnnHandler annHandler = new AnnHandler(super.visitAnnotation(desc, visible));
+        annotations.put(Type.getType(desc).getClassName(), annHandler);
+        return annHandler;
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+        ASMFieldInfo fi = new ASMFieldInfo(super.visitField(access, name, desc, signature, value),
+                this, access, name, desc, signature);
+        fields.add(fi);
+        return fi;
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, final String methodName, String methodDesc, String signature, String[] exceptions) {
+        ASMMethodInfo mi = new ASMMethodInfo(super.visitMethod(access, methodName, methodDesc, signature, exceptions),
+                classInfos, this, access, methodName, methodDesc, signature);
+        methods.add(mi);
+        if (methodName.equals("<init>")) {
+            constructors.add(mi);
+        }
+        return mi;
+    }
+
+    @Override
+    public String getPackageName() {
+        return packageName;
+    }
+
+    @Override
+    public String getNestedName() {
+        return name;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return qualifiedName;
+    }
+
+    @Override
+    public Collection<FieldInfo> getDeclaredFields() {
+        return fields;
+    }
+
+    @Override
+    public Collection<FieldInfo> getFields() {
+        List<FieldInfo> ls = new ArrayList<FieldInfo>();
+        ls.addAll(getDeclaredFields());
+        for (ClassInfo cl : getSuperclasses()) {
+            ls.addAll(cl.getDeclaredFields());
+        }
+        return ls;
+    }
+
+    @Override
+    public Collection<MethodInfo> getConstructors() {
+        return constructors;
+    }
+
+    @Override
+    public Collection<MethodInfo> getDeclaredMethods() {
+        return methods;
+    }
+
+    @Override
+    public Collection<MethodInfo> getMethods() {
+        List<MethodInfo> ls = new ArrayList<MethodInfo>();
+        ls.addAll(getDeclaredMethods());
+        for (ClassInfo cl : getSuperclasses()) {
+            ls.addAll(cl.getDeclaredMethods());
+        }
+        return ls;
+    }
+
+    @Override
+    public Collection<ClassInfo> getSuperclasses() {
+        // TODO: FIXME
+        return Collections.emptyList();
+    }
+
+
+    @Override
+    public <T extends Annotation> T getAnnotationRecursive(Class<T> annClass) {
+        return getAnnotation(annClass); // TODO: FIXME
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return (access & Opcodes.ACC_ABSTRACT) > 0;
+    }
+
+    @Override
+    public boolean isPublic() {
+        return (access & Opcodes.ACC_PUBLIC) > 0;
+    }
+
+    @Override
+    public boolean isStrictFP() {
+        return (access & Opcodes.ACC_STRICT) > 0;
+    }
+
+    @Override
+    public String toString() {
+        return qualifiedName;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMFieldInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.openjdk.jmh.generators.source.ClassInfo;
+import org.openjdk.jmh.generators.source.FieldInfo;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ASMFieldInfo extends FieldVisitor implements FieldInfo {
+
+    private final String type;
+    private final ASMClassInfo owner;
+    private final int access;
+    private final String name;
+    private final Map<String, AnnHandler> annotations;
+
+    public ASMFieldInfo(FieldVisitor fieldVisitor, ASMClassInfo owner, int access, String name, String desc, String signature) {
+        super(Opcodes.ASM4, fieldVisitor);
+        this.owner = owner;
+        this.access = access;
+        this.name = name;
+        this.type = Type.getReturnType(desc).getClassName();
+        this.annotations = new HashMap<String, AnnHandler>();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    @Override
+    public boolean isPublic() {
+        return (access & Opcodes.ACC_PUBLIC) > 0;
+    }
+
+    @Override
+    public boolean isStatic() {
+        return (access & Opcodes.ACC_STATIC) > 0;
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annClass) {
+        AnnHandler handler = annotations.get(annClass.getCanonicalName());
+        if (handler == null) {
+            return null;
+        } else {
+            return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{annClass}, handler);
+        }
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
+        AnnHandler annHandler = new AnnHandler(super.visitAnnotation(desc, visible));
+        annotations.put(Type.getType(desc).getClassName(), annHandler);
+        return annHandler;
+    }
+
+    @Override
+    public ClassInfo getOwner() {
+        return owner;
+    }
+
+    @Override
+    public String toString() {
+        return owner.getQualifiedName() + "." + name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMGeneratorSource.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.objectweb.asm.ClassReader;
+import org.openjdk.jmh.generators.reflective.ReflectiveClassInfo;
+import org.openjdk.jmh.generators.source.ClassInfo;
+import org.openjdk.jmh.generators.source.GeneratorSource;
+import org.openjdk.jmh.generators.source.MetadataInfo;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ASMGeneratorSource implements GeneratorSource {
+
+    private final ClassInfoRepo classInfos;
+    private final File targetDir;
+    private final File targetSourceDir;
+    private final List<SourceError> sourceErrors;
+
+    public ASMGeneratorSource(File targetDir, File targetSourceDir) {
+        this.targetDir = targetDir;
+        this.targetSourceDir = targetSourceDir;
+        this.sourceErrors = new ArrayList<SourceError>();
+        this.classInfos = new ClassInfoRepo();
+    }
+
+    public void processClasses(Collection<File> classFiles)  throws IOException {
+        for (File f : classFiles) {
+            try {
+                processClass(f);
+            } catch (UnresolvedClassException e) {
+
+            }
+        }
+    }
+
+    public void processClass(File classFile) throws IOException {
+        final ASMClassInfo ci = new ASMClassInfo(classInfos);
+        FileInputStream fos = null;
+        try {
+            fos = new FileInputStream(classFile);
+            ClassReader reader = new ClassReader(fos);
+            reader.accept(ci, 0);
+            classInfos.put(ci.getIdName(), ci);
+        } finally {
+            if (fos != null) {
+                fos.close();
+            }
+        }
+    }
+
+    @Override
+    public Collection<ClassInfo> getClasses() {
+        return classInfos.getInfos();
+    }
+
+    @Override
+    public ClassInfo resolveClass(String className) {
+        try {
+            return new ReflectiveClassInfo(Class.forName(className));
+        } catch (ClassNotFoundException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public Writer newResource(String path) throws IOException {
+        String pathName = targetDir.getAbsolutePath() + "/" + path;
+        new File(pathName.substring(0, pathName.lastIndexOf("/"))).mkdirs();
+        return new FileWriter(new File(pathName));
+    }
+
+    @Override
+    public Writer newFile(String objectName) throws IOException {
+        String pathName = targetSourceDir.getAbsolutePath() + "/" + objectName.replaceAll("\\.", "/");
+        new File(pathName.substring(0, pathName.lastIndexOf("/"))).mkdirs();
+        return new FileWriter(new File(pathName + ".java"));
+    }
+
+    @Override
+    public void printError(String message) {
+        sourceErrors.add(new SourceError(message));
+    }
+
+    @Override
+    public void printError(String message, MetadataInfo element) {
+        sourceErrors.add(new SourceElementError(message, element));
+    }
+
+    @Override
+    public void printError(String message, Throwable throwable) {
+        sourceErrors.add(new SourceThrowableError(message, throwable));
+    }
+
+    public boolean hasErrors() {
+        return !sourceErrors.isEmpty();
+    }
+
+    public Collection<SourceError> getErrors() {
+        return sourceErrors;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMMethodInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.openjdk.jmh.generators.source.ClassInfo;
+import org.openjdk.jmh.generators.source.MethodInfo;
+import org.openjdk.jmh.generators.source.ParameterInfo;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ASMMethodInfo extends MethodVisitor implements MethodInfo  {
+
+    private final ASMClassInfo classInfo;
+    private final Map<String, AnnHandler> annotations;
+    private final int access;
+    private final String name;
+    private final String returnType;
+    private final Type[] argumentTypes;
+    private final ClassInfoRepo repo;
+
+    public ASMMethodInfo(MethodVisitor methodVisitor, ClassInfoRepo repo, ASMClassInfo classInfo, int access, String name, String desc, String signature) {
+        super(Opcodes.ASM4, methodVisitor);
+        this.classInfo = classInfo;
+        this.repo = repo;
+        this.access = access;
+        this.name = name;
+        this.returnType = Type.getReturnType(desc).getClassName();
+        this.annotations = new HashMap<String, AnnHandler>();
+        this.argumentTypes = Type.getArgumentTypes(desc);
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annClass) {
+        AnnHandler handler = annotations.get(annClass.getCanonicalName());
+        if (handler == null) {
+            return null;
+        } else {
+            return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{annClass}, handler);
+        }
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotationRecursive(Class<T> annClass) {
+        T ann = getAnnotation(annClass);
+        if (ann != null) {
+            return ann;
+        } else {
+            return classInfo.getAnnotation(annClass);
+        }
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
+        AnnHandler annHandler = new AnnHandler(super.visitAnnotation(desc, visible));
+        annotations.put(Type.getType(desc).getClassName(), annHandler);
+        return annHandler;
+    }
+
+    @Override
+    public ClassInfo getOwner() {
+        return classInfo;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return classInfo.getQualifiedName() + "." + name;
+    }
+
+    @Override
+    public String getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public Collection<ParameterInfo> getParameters() {
+        Collection<ParameterInfo> result = new ArrayList<ParameterInfo>();
+        for (Type t : argumentTypes) {
+            ClassInfo ci = repo.get(t.getClassName().replaceAll("\\.", "/"));
+            if (ci == null) {
+                System.err.println("Unresolved class: " + this + " " + t);
+            }
+            result.add(new ASMParameterInfo(ci));
+        }
+        return result;
+    }
+
+    @Override
+    public boolean isPublic() {
+        return (access & Opcodes.ACC_PUBLIC) > 0;
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return (access & Opcodes.ACC_ABSTRACT) > 0;
+    }
+
+    @Override
+    public boolean isSynchronized() {
+        return (access & Opcodes.ACC_SYNCHRONIZED) > 0;
+    }
+
+    @Override
+    public boolean isStrictFP() {
+        return (access & Opcodes.ACC_STRICT) > 0;
+    }
+
+    @Override
+    public int compareTo(MethodInfo o) {
+        return getQualifiedName().compareTo(o.getQualifiedName());
+    }
+
+    @Override
+    public String toString() {
+        return getQualifiedName() + "()";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ASMParameterInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.openjdk.jmh.generators.source.ClassInfo;
+import org.openjdk.jmh.generators.source.ParameterInfo;
+
+public class ASMParameterInfo implements ParameterInfo {
+
+    private final ClassInfo ci;
+
+    public ASMParameterInfo(ClassInfo ci) {
+        this.ci = ci;
+    }
+
+    @Override
+    public ClassInfo getType() {
+        return ci;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/AnnHandler.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AnnHandler extends AnnotationVisitor implements InvocationHandler {
+    private final Map<String, Object> values;
+
+    public AnnHandler(AnnotationVisitor annotationVisitor) {
+        super(Opcodes.ASM4, annotationVisitor);
+        this.values = new HashMap<String, Object>();
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        String key = method.getName();
+        Class<?> returnType = method.getReturnType();
+
+        Object value = values.get(key);
+        if (value == null) {
+            value = method.getDefaultValue();
+        }
+
+        // FIXME: Types
+        if (returnType.isEnum() && (value instanceof String)) {
+            Method m = returnType.getMethod("valueOf", String.class);
+            return m.invoke(null, value);
+        }
+        return value;
+    }
+
+    @Override
+    public void visit(String name, Object value) {
+        values.put(name, value);
+        super.visit(name, value);
+    }
+
+    @Override
+    public void visitEnum(String name, String desc, String value) {
+        values.put(name, value);
+        super.visitEnum(name, desc, value);
+    }
+
+    @Override
+    public AnnotationVisitor visitArray(final String name) {
+        throw new UnsupportedOperationException("This processor does not support annotations with array arguments yet.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/ClassInfoRepo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.objectweb.asm.Type;
+import org.openjdk.jmh.generators.source.ClassInfo;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ClassInfoRepo {
+
+    private final Map<Type, ClassInfo> map = new HashMap<Type, ClassInfo>();
+
+    public ClassInfo get(String desc) {
+        Type type = Type.getType(desc);
+        return get(type);
+    }
+
+    public ClassInfo get(Type type) {
+        return map.get(type);
+    }
+
+    public void put(String desc, ClassInfo info) {
+        Type type = Type.getType(desc);
+        map.put(type, info);
+    }
+
+    public Collection<ClassInfo> getInfos() {
+        return map.values();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/SourceElementError.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import org.openjdk.jmh.generators.source.MetadataInfo;
+
+public class SourceElementError extends SourceError {
+
+    private final MetadataInfo element;
+
+    public SourceElementError(String message, MetadataInfo element) {
+        super(message);
+        this.element = element;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "\n   [" + element.toString() + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/SourceError.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+public class SourceError {
+
+    private final String message;
+
+    public SourceError(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public String toString() {
+        return message;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/SourceThrowableError.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class SourceThrowableError extends SourceError {
+
+    private final Throwable element;
+
+    public SourceThrowableError(String message, Throwable element) {
+        super(message);
+        this.element = element;
+    }
+
+    @Override
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        element.printStackTrace(pw);
+        pw.close();
+        return super.toString() + "\n" + sw.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/bytecode/UnresolvedClassException.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.bytecode;
+
+public class UnresolvedClassException extends RuntimeException {
+}
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Wed Feb 26 17:18:42 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGenerator.java	Fri Feb 28 00:11:43 2014 +0400
@@ -248,12 +248,6 @@
                         " annotation only supports public classes.", state);
             }
 
-            if (state.isNested() && !state.isStatic()) {
-                throw new GenerationException("The " + State.class.getSimpleName() +
-                        " annotation does not support inner classes, make sure the class is nested (static).",
-                        state);
-            }
-
             boolean hasDefaultConstructor = false;
             for (MethodInfo constructor : state.getConstructors()) {
                 hasDefaultConstructor |= (constructor.getParameters().isEmpty() && constructor.isPublic());
@@ -261,7 +255,8 @@
 
             if (!hasDefaultConstructor) {
                 throw new GenerationException("The " + State.class.getSimpleName() +
-                        " annotation can only be applied to the classes having the default public constructor.",
+                        " annotation can only be applied to the classes having the default public constructor." +
+                        " Make sure the class is nested (static).",
                         state);
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/reflective/ReflectiveClassInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.generators.reflective;
+
+import org.openjdk.jmh.generators.source.ClassInfo;
+import org.openjdk.jmh.generators.source.FieldInfo;
+import org.openjdk.jmh.generators.source.MethodInfo;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class ReflectiveClassInfo implements ClassInfo {
+    private final Class<?> klass;
+
+    public ReflectiveClassInfo(Class<?> klass) {
+        this.klass = klass;
+    }
+
+    @Override
+    public String getPackageName() {
+        return klass.getPackage().getName();
+    }
+
+    @Override
+    public String getNestedName() {
+        // FIXME
+        return getQualifiedName();
+    }
+
+    @Override
+    public String getQualifiedName() {
+        return klass.getCanonicalName();
+    }
+
+    @Override
+    public Collection<FieldInfo> getDeclaredFields() {
+        // FIXME
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<FieldInfo> getFields() {
+        List<FieldInfo> ls = new ArrayList<FieldInfo>();
+        ls.addAll(getDeclaredFields());
+        for (ClassInfo cl : getSuperclasses()) {
+            ls.addAll(cl.getDeclaredFields());
+        }
+        return ls;
+    }
+
+    @Override
+    public Collection<MethodInfo> getConstructors() {
+        // FIXME
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<MethodInfo> getDeclaredMethods() {
+        // FIXME
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Collection<MethodInfo> getMethods() {
+        List<MethodInfo> ls = new ArrayList<MethodInfo>();
+        ls.addAll(getDeclaredMethods());
+        for (ClassInfo cl : getSuperclasses()) {
+            ls.addAll(cl.getDeclaredMethods());
+        }
+        return ls;
+    }
+
+    @Override
+    public Collection<ClassInfo> getSuperclasses() {
+        // FIXME
+        return Collections.emptyList();
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annClass) {
+        return klass.getAnnotation(annClass);
+    }
+
+    @Override
+    public <T extends Annotation> T getAnnotationRecursive(Class<T> annClass) {
+        // TODO: FIXME
+        return getAnnotation(annClass);
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return Modifier.isAbstract(klass.getModifiers());
+    }
+
+    @Override
+    public boolean isPublic() {
+        return Modifier.isPublic(klass.getModifiers());
+    }
+
+    @Override
+    public boolean isStrictFP() {
+        return Modifier.isStrict(klass.getModifiers());
+    }
+}
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/source/ClassInfo.java	Wed Feb 26 17:18:42 2014 +0400
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/source/ClassInfo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -54,14 +54,10 @@
 
     <T extends Annotation> T getAnnotationRecursive(Class<T> annClass);
 
-    boolean isNested();
-
     boolean isAbstract();
 
     boolean isPublic();
 
-    boolean isStatic();
-
     boolean isStrictFP();
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-generator-maven-plugin/pom.xml	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,40 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.openjdk.jmh</groupId>
+        <artifactId>jmh-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.openjdk.jmh</groupId>
+    <artifactId>jmh-generator-maven-plugin</artifactId>
+    <packaging>maven-plugin</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>JMH Generator Maven Plugin</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>2.0.9</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openjdk.jmh</groupId>
+            <artifactId>jmh-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-generator-maven-plugin/src/main/java/org/openjdk/jmh/JmhMojo.java	Fri Feb 28 00:11:43 2014 +0400
@@ -0,0 +1,84 @@
+package org.openjdk.jmh;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.openjdk.jmh.generators.bytecode.ASMGeneratorSource;
+import org.openjdk.jmh.generators.bytecode.SourceError;
+import org.openjdk.jmh.generators.core.BenchmarkGenerator;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @goal "generate"
+ * @phase "process-sources"
+ */
+public class JmhMojo extends AbstractMojo {
+
+    /**
+     * Classes dir
+     *
+     * @parameter expression="${project.build.outputDirectory}"
+     * @required
+     */
+    private File classesDirectory;
+
+    /**
+     * Classes dir
+     *
+     * @parameter expression="${project.build.directory}/generated-sources/jmh/"
+     * @required
+     */
+    private File generatedSourcesDir;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        ASMGeneratorSource source = new ASMGeneratorSource(classesDirectory, generatedSourcesDir);
+
+        try {
+            source.processClasses(getClasses(classesDirectory));
+        } catch (IOException ioe) {
+            throw new MojoExecutionException("IOException", ioe);
+        }
+
+        BenchmarkGenerator gen = new BenchmarkGenerator();
+        gen.generate(source);
+        gen.complete(source);
+
+        if (source.hasErrors()) {
+            for (SourceError e : source.getErrors()) {
+                getLog().error(e.toString() + "\n");
+            }
+            throw new MojoFailureException("Errors detected.");
+        }
+    }
+
+    public Collection<File> getClasses(File root) {
+        Collection<File> result = new ArrayList<File>();
+
+        List<File> newDirs = new ArrayList<File>();
+        newDirs.add(root);
+        while (!newDirs.isEmpty()) {
+            List<File> add = new ArrayList<File>();
+            for (File dir : newDirs) {
+                for (File f : dir.listFiles()) {
+                    if (f.isDirectory()) {
+                        add.add(f);
+                    } else {
+                        if (f.getName().endsWith(".class")) {
+                            result.add(f);
+                        }
+                    }
+                }
+            }
+            newDirs.clear();
+            newDirs = add;
+        }
+
+        return result;
+    }
+
+}
--- a/pom.xml	Wed Feb 26 17:18:42 2014 +0400
+++ b/pom.xml	Fri Feb 28 00:11:43 2014 +0400
@@ -163,6 +163,7 @@
         <module>jmh-core-benchmarks</module>
         <module>jmh-samples</module>
         <module>jmh-simple-benchmark-archetype</module>
+        <module>jmh-generator-maven-plugin</module>
     </modules>
 
 </project>