changeset 14064:0f7a9b8602e5

Initial push for RuntimeMirror API * add support for any type-variables in signature attributes * add initial API, reference implementation and tests * comment some debugging statements in URLClassLoader
author mcimadamore
date Wed, 15 Jun 2016 18:07:49 +0100
parents 00da8e787d47
children 7e5201fad2a2 9d95ccabcf78
files src/java.base/share/classes/java/lang/reflect/TypeVariable.java src/java.base/share/classes/java/net/URLClassLoader.java src/java.base/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java src/java.base/share/classes/sun/reflect/generics/factory/GenericsFactory.java src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java src/java.base/share/classes/sun/reflect/generics/tree/BaseType.java src/java.base/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java src/java.base/share/classes/sun/reflect/generics/visitor/Reifier.java src/java.base/share/classes/valhalla/classdyn/ClassDynHelper.java src/java.base/share/classes/valhalla/reflect/runtime/ArrayMirror.java src/java.base/share/classes/valhalla/reflect/runtime/ClassLookup.java src/java.base/share/classes/valhalla/reflect/runtime/ClassMirror.java src/java.base/share/classes/valhalla/reflect/runtime/ConstructorLookup.java src/java.base/share/classes/valhalla/reflect/runtime/ConstructorMirror.java src/java.base/share/classes/valhalla/reflect/runtime/FieldLookup.java src/java.base/share/classes/valhalla/reflect/runtime/FieldMirror.java src/java.base/share/classes/valhalla/reflect/runtime/GenericMirror.java src/java.base/share/classes/valhalla/reflect/runtime/MemberLookup.java src/java.base/share/classes/valhalla/reflect/runtime/MemberMirror.java src/java.base/share/classes/valhalla/reflect/runtime/MethodLookup.java src/java.base/share/classes/valhalla/reflect/runtime/MethodMirror.java src/java.base/share/classes/valhalla/reflect/runtime/MirrorFactory.java src/java.base/share/classes/valhalla/reflect/runtime/ReflectableMirror.java src/java.base/share/classes/valhalla/reflect/runtime/RuntimeMirror.java src/java.base/share/classes/valhalla/reflect/runtime/ScopeMirror.java src/java.base/share/classes/valhalla/reflect/runtime/TypeVariableMirror.java src/java.base/share/classes/valhalla/reflect/runtime/impl/AbstractLookupImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/AbstractMemberMirrorImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/ArrayMirrorImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/ClassMirrorImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/DelegatedMirrorImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/MirrorFactoryImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/MirrorUtils.java src/java.base/share/classes/valhalla/reflect/runtime/impl/TypeArgumentMirrorImpl.java src/java.base/share/classes/valhalla/reflect/runtime/impl/TypeVariableMirrorImpl.java src/java.base/share/classes/valhalla/reflect/runtime/package-info.java test/valhalla/test/valhalla/reflect/runtime/MirrorBuilder.java test/valhalla/test/valhalla/reflect/runtime/SimpleReflectionTest.java test/valhalla/test/valhalla/reflect/runtime/TestBase.java test/valhalla/test/valhalla/reflect/runtime/TestFactory.java test/valhalla/test/valhalla/reflect/runtime/TestLookup.java test/valhalla/test/valhalla/reflect/runtime/TestSubtypeOf.java test/valhalla/test/valhalla/reflect/runtime/TestTypeEquals.java
diffstat 44 files changed, 3293 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/reflect/TypeVariable.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/TypeVariable.java	Wed Jun 15 18:07:49 2016 +0100
@@ -99,4 +99,9 @@
      * @since 1.8
      */
      AnnotatedType[] getAnnotatedBounds();
+
+    /**
+     * Returns true if this is an 'any' type-variable.
+     */
+     default boolean isAny() { return false; }
 }
--- a/src/java.base/share/classes/java/net/URLClassLoader.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/java/net/URLClassLoader.java	Wed Jun 15 18:07:49 2016 +0100
@@ -401,7 +401,7 @@
                             try {
                                 byte[] bytes = res.getBytes();
                                 if (converter.isModel3Class(bytes)) {
-                                    System.err.printf("%s: M3.register(%s)%n", URLClassLoader.this, name);
+                                    //System.err.printf("%s: M3.register(%s)%n", URLClassLoader.this, name);
                                     Model3Converter.TemplateClass key = converter.register(bytes);
                                     res = new ByteResource(res, key.getErasedBytes());
                                     if (dumper != null) {
@@ -428,7 +428,7 @@
                             }
                             byte[] bytes = template.getBytes(pt);
                             if (bytes != null) {
-                                System.err.printf("%s: M3.specialize(%s)%n", URLClassLoader.this, name);
+                                //System.err.printf("%s: M3.specialize(%s)%n", URLClassLoader.this, name);
                                 if (dumper != null)
                                     dumper.dumpClass(name, bytes);
                                 try {
--- a/src/java.base/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java	Wed Jun 15 18:07:49 2016 +0100
@@ -89,9 +89,9 @@
         return new CoreReflectionFactory(d, s);
     }
 
-    public TypeVariable<?> makeTypeVariable(String name,
+    public TypeVariable<?> makeTypeVariable(boolean isAny, String name,
                                             FieldTypeSignature[] bounds){
-        return TypeVariableImpl.make(getDecl(), name, bounds, this);
+        return TypeVariableImpl.make(isAny, getDecl(), name, bounds, this);
     }
 
     public WildcardType makeWildcard(FieldTypeSignature[] ubs,
--- a/src/java.base/share/classes/sun/reflect/generics/factory/GenericsFactory.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/factory/GenericsFactory.java	Wed Jun 15 18:07:49 2016 +0100
@@ -57,7 +57,7 @@
      * @throws NullPointerException if any of the actual parameters
      * or any of the elements of {@code bounds} are {@code null}.
      */
-    TypeVariable<?> makeTypeVariable(String name,
+    TypeVariable<?> makeTypeVariable(boolean isAny, String name,
                                      FieldTypeSignature[] bounds);
     /**
      * Returns an instance of the {@code ParameterizedType} interface
--- a/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java	Wed Jun 15 18:07:49 2016 +0100
@@ -246,9 +246,15 @@
      *     Identifier ClassBound InterfaceBound*
      */
     private FormalTypeParameter parseFormalTypeParameter(){
+        char c = current();
+        boolean isAny = false;
+        if (c == '^') {
+            isAny = true;
+            advance();
+        }
         String id = parseIdentifier();
         FieldTypeSignature[] bs = parseBounds();
-        return FormalTypeParameter.make(id, bs);
+        return FormalTypeParameter.make(isAny, id, bs);
     }
 
     private String parseIdentifier(){
@@ -433,7 +439,7 @@
             return Wildcard.make(ub, lb);
         }
         default:
-            return parseFieldTypeSignature();
+            return (TypeArgument)parseTypeSignature(); //type signatures are also legal type arguments... pssst
         }
     }
 
--- a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -51,6 +51,7 @@
  */
 public class TypeVariableImpl<D extends GenericDeclaration>
     extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
+    private final boolean isAny;
     private final D genericDeclaration;
     private final String name;
 
@@ -63,9 +64,10 @@
     private volatile Object[] bounds;
 
     // constructor is private to enforce access through static factory
-    private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
+    private TypeVariableImpl(boolean isAny, D decl, String n, FieldTypeSignature[] bs,
                              GenericsFactory f) {
         super(f);
+        this.isAny = isAny;
         genericDeclaration = decl;
         name = n;
         bounds = bs;
@@ -84,7 +86,7 @@
      * specified
      */
     public static <T extends GenericDeclaration>
-                             TypeVariableImpl<T> make(T decl, String name,
+                             TypeVariableImpl<T> make(boolean isAny, T decl, String name,
                                                       FieldTypeSignature[] bs,
                                                       GenericsFactory f) {
 
@@ -94,7 +96,7 @@
             throw new AssertionError("Unexpected kind of GenericDeclaration" +
                     decl.getClass().toString());
         }
-        return new TypeVariableImpl<T>(decl, name, bs, f);
+        return new TypeVariableImpl<T>(isAny, decl, name, bs, f);
     }
 
 
@@ -246,4 +248,9 @@
         }
         return result;
     }
+
+    @Override
+    public boolean isAny() {
+        return isAny;
+    }
 }
--- a/src/java.base/share/classes/sun/reflect/generics/tree/BaseType.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/tree/BaseType.java	Wed Jun 15 18:07:49 2016 +0100
@@ -31,4 +31,4 @@
  * section on signatures.
  */
 public interface BaseType
-    extends TypeSignature{}
+    extends TypeArgument, TypeSignature{}
--- a/src/java.base/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java	Wed Jun 15 18:07:49 2016 +0100
@@ -29,10 +29,12 @@
 
 /** AST that represents a formal type parameter. */
 public class FormalTypeParameter implements TypeTree {
+    private final boolean isAny;
     private final String name;
     private final FieldTypeSignature[] bounds;
 
-    private FormalTypeParameter(String n, FieldTypeSignature[] bs) {
+    private FormalTypeParameter(boolean isAny, String n, FieldTypeSignature[] bs) {
+        this.isAny = isAny;
         name = n;
         bounds = bs;
     }
@@ -44,12 +46,13 @@
      * @param bs - the bounds of the type variable to be created by this method.
      * @return a formal type parameter with the requested name and bounds
      */
-    public static FormalTypeParameter make(String n, FieldTypeSignature[] bs){
-        return new FormalTypeParameter(n,bs);
+    public static FormalTypeParameter make(boolean isAny, String n, FieldTypeSignature[] bs){
+        return new FormalTypeParameter(isAny, n,bs);
     }
 
     public FieldTypeSignature[] getBounds(){return bounds;}
     public String getName(){return name;}
+    public boolean isAny() {return isAny;}
 
     public void accept(TypeTreeVisitor<?> v){v.visitFormalTypeParameter(this);}
 }
--- a/src/java.base/share/classes/sun/reflect/generics/visitor/Reifier.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/sun/reflect/generics/visitor/Reifier.java	Wed Jun 15 18:07:49 2016 +0100
@@ -80,7 +80,7 @@
     public Type getResult() { assert resultType != null;return resultType;}
 
     public void visitFormalTypeParameter(FormalTypeParameter ftp){
-        resultType = getFactory().makeTypeVariable(ftp.getName(),
+        resultType = getFactory().makeTypeVariable(ftp.isAny(), ftp.getName(),
                                                    ftp.getBounds());
     }
 
--- a/src/java.base/share/classes/valhalla/classdyn/ClassDynHelper.java	Mon Jun 13 17:51:37 2016 -0400
+++ b/src/java.base/share/classes/valhalla/classdyn/ClassDynHelper.java	Wed Jun 15 18:07:49 2016 +0100
@@ -70,7 +70,7 @@
     public static Class<?> bootstrapLoaderHelper(final String name)
             throws ClassNotFoundException {
         final Class<?> result;
-        System.out.printf("boot: M3.probe(%s)", name);
+        //System.out.printf("boot: M3.probe(%s)", name);
         try {
             return AccessController.doPrivileged(
                     new PrivilegedExceptionAction<Class<?>>() {
@@ -93,7 +93,7 @@
                                 }
                                 byte[] bytes = template.getBytes(pt);
                                 if (bytes != null) {
-                                    System.err.printf("boot: M3.specialize(%s)%n", name);
+                                    //System.err.printf("boot: M3.specialize(%s)%n", name);
                                     if (dumper != null)
                                         dumper.dumpClass(name, bytes);
                                     return Unsafe.getUnsafe().defineClass(name, bytes, 0, bytes.length, null, null);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ArrayMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,12 @@
+package valhalla.reflect.runtime;
+
+/**
+ * {@code ArrayMirror} represents an array type with a given component type.
+ */
+public interface ArrayMirror extends RuntimeMirror {
+    /**
+     * Retrieves the array component type.
+     * @return the array component type
+     */
+    RuntimeMirror getComponentType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ClassLookup.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,26 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandles.Lookup;
+
+public interface ClassLookup extends MemberLookup<ClassMirror> {
+
+    @Override
+    ClassLookup withFlags(int mods);
+
+    @Override
+    ClassLookup withAccessContext(Lookup lookup);
+
+    /**
+     * Forces a given inheritance mode on this class lookup.
+     * @param kind inheritance mode
+     * @return this class lookup
+     */
+    ClassLookup withInheritanceKind(InheritanceMode kind);
+
+    /**
+     * Restrict lookup to fields with given name.
+     * @param name field name
+     * @return this field lookup
+     */
+    ClassLookup withName(String name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ClassMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,16 @@
+package valhalla.reflect.runtime;
+
+import java.util.List;
+
+/**
+ * {@code ClassMirror} represents a (possibly parameterized) class type.
+ */
+public interface ClassMirror extends RuntimeMirror, GenericMirror<ClassMirror>,
+                                     MemberMirror, ReflectableMirror<Class<?>>, ScopeMirror {
+
+    /**
+     * Retrieves the list of direct supertypes of this class mirror.
+     * @return The list of supertypes of this mirror.
+     */
+    List<? extends ClassMirror> getSupertypes();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ConstructorLookup.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,19 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandles.Lookup;
+
+public interface ConstructorLookup extends MemberLookup<ConstructorMirror> {
+
+    @Override
+    ConstructorLookup withFlags(int mods);
+
+    @Override
+    ConstructorLookup withAccessContext(Lookup lookup);
+
+    /**
+     * Restrict lookup to constructors with given parameter types.
+     * @param paramTypes constructors's parameter types
+     * @return this constructor lookup
+     */
+    ConstructorLookup withParameterTypes(RuntimeMirror... paramTypes);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ConstructorMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,25 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+/**
+ * {@code ConstructorMirror} represents a constructor member mirror.
+ */
+public interface ConstructorMirror extends MemberMirror, ReflectableMirror<Constructor<?>> {
+
+    /**
+     * Retrieve the constructor's parameter type list.
+     * @return the constructor's parameter type list
+     */
+    List<? extends RuntimeMirror> getParameterTypes();
+
+    /**
+     * Returns a {@link MethodHandle} object which can be used to call the constructor programmatically.
+     * @return a {@link MethodHandle} object for this constructor member
+     * @throws IllegalAccessException
+     * @throws IllegalStateException if this mirror contains one or more type-variables
+     */
+    MethodHandle asHandle() throws IllegalAccessException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/FieldLookup.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,36 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandles.Lookup;
+
+/**
+ * {@code MemberLookup} is a specialized lookup helper targeting fields.
+ */
+public interface FieldLookup extends MemberLookup<FieldMirror> {
+
+    @Override
+    FieldLookup withFlags(int mods);
+
+    @Override
+    FieldLookup withAccessContext(Lookup lookup);
+
+    /**
+     * Forces a given inheritance mode on this field lookup.
+     * @param kind inheritance mode
+     * @return this field lookup
+     */
+    FieldLookup withInheritanceMode(InheritanceMode kind);
+
+    /**
+     * Restrict lookup to fields with given name.
+     * @param name field name
+     * @return this field lookup
+     */
+    FieldLookup withName(String name);
+
+    /**
+     * Restrict lookup to fields with given type.
+     * @param type field type
+     * @return this field lookup
+     */
+    FieldLookup withType(RuntimeMirror type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/FieldMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,41 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Field;
+
+/**
+ * {@code FieldMirror} represents a method member mirror.
+ */
+public interface FieldMirror extends MemberMirror, ReflectableMirror<Field> {
+
+    /**
+     * Retrieve the field's type.
+     * @return the field's return type
+     */
+    RuntimeMirror getType();
+
+    /**
+     * Returns a {@link MethodHandle} object which can be used to get the field programmatically.
+     * @return a {@link MethodHandle} object for this field member' getter
+     * @throws IllegalAccessException
+     * @throws IllegalStateException if this mirror contains one or more type-variables
+     */
+    MethodHandle asGetterHandle() throws IllegalAccessException;
+
+    /**
+     * Returns a {@link MethodHandle} object which can be used to set the field programmatically.
+     * @return a {@link MethodHandle} object for this field member' setter
+     * @throws IllegalAccessException
+     * @throws IllegalStateException if this mirror contains one or more type-variables
+     */
+    MethodHandle asSetterHandle() throws IllegalAccessException;
+
+    /**
+     * Returns a {@link VarHandle} object which can be used to access the field programmatically.
+     * @return a {@link VarHandle} object for this field member
+     * @throws IllegalAccessException
+     * @throws IllegalStateException if this mirror contains one or more type-variables
+     */
+    VarHandle asHandle() throws IllegalAccessException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/GenericMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,29 @@
+package valhalla.reflect.runtime;
+
+import java.util.List;
+
+/**
+ * {@code GenericMirror} is the common superinterface for all mirrors that can be specialized.
+ * @param <S> the type of the unspecialized mirror associated with this specializable mirror
+ */
+public interface GenericMirror<S extends GenericMirror<S>> {
+    /**
+     * Is this mirror specializable?
+     * @return true if this mirror can be instantiated.
+     */
+    boolean isSpecializable();
+
+    /**
+     * Retrieves the type-argument list associated with this mirror.
+     * @return the type-argument list; if the mirror is non-specializable, an empty list is returned
+     */
+    List<? extends RuntimeMirror> getTypeArguments();
+
+    /**
+     * Returns a specialized mirror given an type-argument array.
+     * @param typeArgs an array of type-argument mirrors
+     * @return a new specialization of this specializable mirror
+     */
+    S asSpecializedMirror(RuntimeMirror... typeArgs);
+    S asGenericMirror();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/MemberLookup.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,49 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * {@code MemberLookup} is the common superinterface for all lookup helpers..
+ * @param <M> the member mirror targeted by this lookup
+ */
+public interface MemberLookup<M extends MemberMirror> {
+
+    /**
+     * The inheritance mode tells as to whether the lookup should propagate recursively to supertypes.
+     */
+    enum InheritanceMode {
+        /** recursive lookup including all inherited members */
+        INHERITED,
+        /** only declared members are returned the lookup */
+        DECLARED
+    }
+
+    /**
+     * Restrict lookup to members with given flags.
+     * @param mods flag mask
+     * @return this member lookup
+     */
+    MemberLookup<M> withFlags(int mods);
+
+    /**
+     * Restrict lookup to members that are accessible within a given {@link MethodLookup}.
+     * @param lookup the lookup object to be used for access checking
+     * @return this member lookup
+     */
+    MemberLookup<M> withAccessContext(Lookup lookup);
+
+    /**
+     * Retrieves all the members matched by this lookup.
+     * @return members matched by this lookup
+     */
+    List<? extends M> findAll();
+
+    /**
+     * Retrieves the single member matched by this lookup (provided an unambiguous match exists).
+     * @return member matched by this lookup
+     * @throws NoSuchElementException if the lookup returns either no member or more than one members.
+     */
+    M findOrFail() throws NoSuchElementException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/MemberMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,20 @@
+package valhalla.reflect.runtime;
+
+/**
+ * {@code MemberMirror} is the common superinterface for all mirrors that can appear as members of other mirrors
+ * {@link ScopeMirror}.
+ */
+public interface MemberMirror {
+
+    /**
+     * Retrieves the name of the member.
+     * @return the name of the member.
+     */
+     String getName();
+
+     /**
+      * Retrieves the enclosing type of this class type.
+      * @return the enclosing type or {@code null} if no such type exists
+      */
+     ScopeMirror getEnclosingType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/MethodLookup.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,61 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+public interface MethodLookup extends MemberLookup<MethodMirror> {
+
+    @Override
+    MethodLookup withFlags(int mods);
+
+    @Override
+    MethodLookup withAccessContext(Lookup lookup);
+
+    /**
+     * Forces a given inheritance mode on this method lookup.
+     * @param kind inheritance mode
+     * @return this method lookup
+     */
+    MethodLookup withInheritanceKind(InheritanceMode kind);
+
+    /**
+     * Restrict lookup to methods with given name.
+     * @param name method name
+     * @return this method lookup
+     */
+    MethodLookup withName(String name);
+
+    /**
+     * Restrict lookup to methods with given parameter types.
+     * @param paramTypes method's parameter types
+     * @return this method lookup
+     */
+    MethodLookup withParameterTypes(RuntimeMirror... paramTypes);
+
+    /**
+     * Restrict lookup to methods with given parameter types.
+     * @param paramsFactory a function that takes the (possibly empty) list of method type-parameters and (optionally) constructs
+     *                      the list of parameter types to be used in the lookup; if the list of type-variables does not
+     *                      satisfy the lookup, the factory should return an empty {@link Optional}
+     * @return this method lookup
+     */
+    MethodLookup withParameterTypes(Function<List<? extends TypeVariableMirror<?>>, Optional<List<? extends RuntimeMirror>>> paramsFactory);
+
+    /**
+     * Restrict lookup to methods with given return type.
+     * @param type method's return type
+     * @return this method lookup
+     */
+    MethodLookup withReturnType(RuntimeMirror type);
+
+    /**
+     * Restrict lookup to methods with given return type.
+     * @param returnFactory a function that takes the (possibly empty) list of method type-parameters and (optionally)
+     *                      constructs the return type to be used in the lookup; if the list of type-variables does not
+     *                      satisfy the lookup, the factory should return an empty {@link Optional}
+     * @return this method lookup
+     */
+    MethodLookup withReturnType(Function<List<? extends TypeVariableMirror<?>>, Optional<RuntimeMirror>> returnFactory);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/MethodMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,31 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * {@code MethodMirror} represents a method member mirror.
+ */
+public interface MethodMirror extends GenericMirror<MethodMirror>, MemberMirror, ReflectableMirror<Method> {
+
+    /**
+     * Retrieve the method's return type.
+     * @return the method's return type
+     */
+    RuntimeMirror getReturnType();
+
+    /**
+     * Retrieve the method's parameter type list.
+     * @return the method's parameter type list
+     */
+    List<? extends RuntimeMirror> getParameterTypes();
+
+    /**
+     * Returns a {@link MethodHandle} object which can be used to call the method programmatically.
+     * @return a {@link MethodHandle} object for this method member
+     * @throws IllegalAccessException
+     * @throws IllegalStateException if this mirror contains one or more type-variables
+     */
+    MethodHandle asHandle() throws IllegalAccessException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/MirrorFactory.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,71 @@
+package valhalla.reflect.runtime;
+
+import valhalla.reflect.runtime.impl.MirrorFactoryImpl;
+
+import java.lang.reflect.TypeVariable;
+
+/**
+ * A factory for creating runtime mirrors.
+ */
+public interface MirrorFactory {
+
+    /**
+     * Creates a class mirror from an existing {@link Class}.
+     * @param clazz {@link Class} object for which the mirror has to be created
+     * @return a new class mirror
+     * @throws IllegalArgumentException if {@code clazz} is either primitive ({@link Class#isPrimitive()} returns {@code true}),
+     * or an array ({@link Class#isArray()} returns {@code true}).
+     */
+    ClassMirror classMirror(Class<?> clazz) throws IllegalArgumentException;
+
+    /**
+     * Creates an array mirror with given component type.
+     * @param componentType the component type of the array mirror
+     * @return a new array mirror
+     */
+    ArrayMirror arrayMirror(RuntimeMirror componentType);
+
+    /**
+     * Creates an array mirror from an existing {@link Class}.
+     * @param clazz {@link Class} object for which the mirror has to be created
+     * @return a new array mirror
+     * @throws IllegalArgumentException if {@code clazz} is not an array ({@link Class#isArray()} returns {@code false})
+     */
+    ArrayMirror arrayMirror(Class<?> clazz) throws IllegalArgumentException;
+
+    /**
+     * Creates a new type-variable mirror from an existing {@link TypeVariable}.
+     * @param typeVariable {@link TypeVariable} object for which the mirror has to be created
+     * @param <Z> the generic mirror the type-variable mirror belongs to
+     * @return
+     */
+    <Z extends GenericMirror<Z>> TypeVariableMirror<Z> typeVarMirror(TypeVariable<?> typeVariable);
+
+    /**
+     * Creates a primitive mirror from an existing {@link Class}.
+     * @param clazz {@link Class} object for which the mirror has to be created
+     * @return a new primitive mirror
+     * @throws IllegalArgumentException if {@code clazz} is not a primitive ({@link Class#isPrimitive()} returns {@code false})
+     */
+    RuntimeMirror primitiveMirror(Class<?> clazz) throws IllegalArgumentException;
+
+    /**
+     * Creates a special {@code erased} type-argument mirror.
+     * @return special {@code erased} type-argument mirror
+     */
+    RuntimeMirror erasedMirror();
+
+    /**
+     * Creates a special {@code any} type-argument mirror.
+     * @return special {@code any} type-argument mirror
+     */
+    RuntimeMirror anyMirror();
+
+    /**
+     * Returns an instance of this mirror factory interface.
+     * @return a mirror factory
+     */
+    static MirrorFactory instance() {
+        return MirrorFactoryImpl.instance();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ReflectableMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,17 @@
+package valhalla.reflect.runtime;
+
+import java.lang.reflect.Method;
+
+/**
+ * {@code ReflectiveMirror} is the common superinterface for all mirrors that can be mapped back to legacy reflective objects.
+ * @param <X> the reflective object this mirror can be mapped to (e.g. {@link Class}, {@link Method}, etc.)
+ */
+public interface ReflectableMirror<X> {
+
+    /**
+     * Map this mirror into a legacy reflective object.
+     * @return the legacy reflective object for this mirror.
+     * @throws IllegalStateException if this mirror contains one or more type-variables
+     */
+    X reflect() throws IllegalStateException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/RuntimeMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,251 @@
+package valhalla.reflect.runtime;
+
+import java.lang.invoke.MethodHandles;
+
+import java.lang.reflect.TypeVariable;
+import java.util.function.Function;
+
+/**
+ * {@code RuntimeMirror} is the common superinterface for all types representable in a Java programming language classfile.
+ * These include parameterized types, array types, type variables, primitive types and special type-arguments (such as
+ * {@code erased} or {@code any}).
+ *
+ * <h1>Overview</h1>
+ * The root of the reflection type hierarchy is {@code RuntimeMirror}. There are six kinds of mirrors; each mirror has a
+ * unique kind (see {@link Kind} and can be created using the corresponding factory method in {@link MirrorFactory},
+ * as summarized in the table below:
+ *
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ *   <caption>Summary of mirror kinds</caption>
+ *   <tr>
+ *     <th>Kind</th>
+ *     <th>Class</th>
+ *     <th>Factory</th>
+ *     <th>{@link Kind}</th>
+ *   </tr>
+ *   <tr>
+ *     <td>class mirror</td>
+ *     <td>{@link ClassMirror}</td>
+ *     <td>{@link MirrorFactory#classMirror(Class)}</td>
+ *     <td>{@link Kind#CLASS}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>array mirror</td>
+ *     <td>{@link ArrayMirror}</td>
+ *     <td>{@link MirrorFactory#arrayMirror(Class)} <br>
+ *         {@link MirrorFactory#arrayMirror(RuntimeMirror)}
+ *     </td>
+ *     <td>{@link Kind#ARRAY}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>type-variable mirror</td>
+ *     <td>{@link TypeVariableMirror}</td>
+ *     <td>{@link MirrorFactory#typeVarMirror(TypeVariable)}</td>
+ *     <td>{@link Kind#TYPEVAR}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>primitive mirror</td>
+ *     <td>{@link RuntimeMirror}</td>
+ *     <td>{@link MirrorFactory#primitiveMirror(Class)}</td>
+ *     <td>{@link Kind#VALUE}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>{@code erased}</td>
+ *     <td>{@link RuntimeMirror}</td>
+ *     <td>{@link MirrorFactory#erasedMirror()}</td>
+ *     <td>{@link Kind#ERASED}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>{@code any}</td>
+ *     <td>{@link RuntimeMirror}</td>
+ *     <td>{@link MirrorFactory#anyMirror()}</td>
+ *     <td>{@link Kind#ANY}</td>
+ *   </tr>
+ * </table>
+ *
+ * <p>Every runtime mirror support basic operations such as kind query (see {@link RuntimeMirror#getKind()} as well as
+ * basic type-related operations (e.g. {@link RuntimeMirror#isSubtypeOf(RuntimeMirror)}.
+ *
+ * <p>Additionally, each mirror class provide some specific structural access to the mirror's contents; for instance,
+ * array mirrors provide access to the component type (see {@link ArrayMirror#getComponentType()}), class mirrors give
+ * access to supertypes (see {@link ClassMirror#getSupertypes()}, etc.
+ *
+ * <h1>Specialization support</h1>
+ *
+ * Some mirrors are specializable (see {@link GenericMirror}); when a mirror is specializable, it contains one or more type-variables,
+ * which are accessible using {@link GenericMirror#getTypeArguments()}. If a mirror is specializable, it can be specialized using
+ * the method {@link GenericMirror#asSpecializedMirror(RuntimeMirror...)} - as follows:
+ * <p>
+ * <blockquote><pre>{@code
+ * RuntimeMirror typeArgs = { ... };
+ * if (mirror.isSpecializable()) {
+ *     ClassMirror s_mirror = mirror.asSpecializedMirror(typeArgs);
+ * }
+ * }</pre></blockquote>
+ * <p>The resulting mirror will be obtained by replacing the type-variable in the specializable mirror with the provided
+ * actual type-arguments. Once a specialized mirror is obtained, one can always go back to the unspecialized version - using
+ * {@link GenericMirror#asGenericMirror()}:
+ *
+ * <p>
+ * {@code assertEquals(s_mirror.asGenericMirror(), mirror);}
+ *
+ * <p>There are two kinds of generic mirrors: class mirrors and method mirrors (since both classes and methods can be specialized).
+ *
+ * <h1>Member lookup</h1>
+ * Some mirrors support lookup operations (see {@link ScopeMirror}). Such mirrors can be asked the list of classes, methods,
+ * fields and constructors defined within themselves (either directly or indirectly, through inheritance). The lookup operations
+ * are supported through lookup objects (see {@link MemberLookup}. The table below groups the available lookup objects
+ * by mirror kind.
+ *
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ *   <caption>Summary of member lookup</caption>
+ *   <tr>
+ *     <th>Member kind</th>
+ *     <th>Class</th>
+ *     <th>{@link MemberLookup}</th>
+ *   </tr>
+ *   <tr>
+ *     <td>class</td>
+ *     <td>{@link ClassMirror}</td>
+ *     <td>{@link ClassLookup}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>field</td>
+ *     <td>{@link FieldMirror}</td>
+ *     <td>{@link FieldLookup}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>method</td>
+ *     <td>{@link MethodMirror}</td>
+ *     <td>{@link MethodLookup}</td>
+ *   </tr>
+ *   <tr>
+ *     <td>constructor</td>
+ *     <td>{@link ConstructorMirror}</td>
+ *     <td>{@link ConstructorLookup}</td>
+ *   </tr>
+ * </table>
+ *
+ * <p>Lookups can be either loose or strict, depending on whether the method {@link MemberLookup#findAll()} or
+ * {@link MemberLookup#findOrFail()} is used to perform the lookup. A loose lookup looks like the following:
+ *
+ * <p>
+ * {@code mirror.methodLookup().findAll();}
+ *
+ * <p>Which returns all methods in {@code mirror} (either declared or inherited).
+ *
+ * <p>If the user knows more about the method to be looked up, a more precise lookup can be attempted:
+ * <blockquote><pre>{@code
+ * RuntimeMirror[] paramTypes = { ... }
+ * mirror.findMethod("foo", paramTypes);
+ * }</pre></blockquote>
+ *
+ * <p>Since a method can be generic, sometimes a strict lookup cannot be defined using the above method (because a generic
+ * method signature could depend on type-parameters declared by the method itself, which are normally not known ahead of lookup).
+ * To address this, a lookup method specifically targeting generic method is provided (see {@link MethodLookup#withParameterTypes(Function)},
+ * which can be used as follows:
+ *
+ * <p>
+ * {@code mirror.findGenericMethod("gfoo", tvars -> Arrays.asList(tvars.get(1)));}
+ *
+ * <p>The above lookup searches for a generic method whose name is 'gfoo' and whose parameter list is the generic method's
+ * second type-variable.
+ *
+ * <p>Fields, constructors and member inner classes can be looked up in a similar fashion.
+ *
+ * <h1>Reflective features</h1>
+ * Some mirrors (see {@link ReflectableMirror}) can be projected back into a legacy reflective object using {@link ReflectableMirror#reflect()}.
+ * In order to perform this projection, a mirror should not contain any open type-variables, <b>or an exception will occur</b>:
+ * <p>
+ * <blockquote><pre>{@code
+ * Class<?> c_m = mirror.reflect(); //throws!
+ * Class<?> c_sm = smirror.reflect(); //ok
+ * }</pre></blockquote>
+ *
+ * <p>This compatibility layers allow new new mirror API to interoperate with existing {@link Class}-based API,
+ * such as {@link MethodHandles.Lookup}.
+ *
+ * <p>In addition to the basic legacy reflective mapping, some mirrors (like method, field and constructor mirrors) provide
+ * extra reflective capabilities to, for example, map a method mirror into a method handle (see {@link MethodMirror#asHandle()}).
+ */
+public interface RuntimeMirror extends ReflectableMirror<Class<?>> {
+
+    /**
+     * The kind of the runtime mirror.
+     */
+    enum Kind {
+        /**
+         * Primitive or value mirror.
+         */
+        VALUE,
+        /**
+         * Array mirror.
+         */
+        ARRAY,
+        /**
+         * Class mirror.
+         */
+        CLASS,
+        /**
+         * Type-variable mirror.
+         */
+        TYPEVAR,
+        /**
+         * Special {@code erased} type-argument mirror.
+         */
+        ERASED,
+        /**
+         * Special {@code any} type-argument mirror.
+         */
+        ANY
+    }
+
+    /**
+     * Retrieves this mirror's kind.
+     * @return the mirror kind
+     */
+    Kind getKind();
+
+    /**
+     * This method implements the type equality relationship {@code T == S}. Equality is determined as follows:
+     * <ul>
+     *     <li>Given two array mirrors {@code S[]} and {@code T[]}, {@code S[] == T[]} if {@code S == T}</li>
+     *     <li>Given two class mirrors {@code G<X1, X2, ... Xn>} and {@code D<Y1, X2, ... Xm>}, {@code G<X1, X2, ... Xn> == D<Y1, Y2, ... Ym>} iff:
+     *     <ul>
+     *         <li>
+     *             G and D represent the same class declaration
+     *             n == m
+     *             for each i in 1..n {@code Xi == Yi}
+     *         </li>
+     *     </ul></li>
+     *     <li>Otherwise given two mirrors {@code S} and {@code T}, {@code S == T} if the two mirrors represent the same underlying entity
+     *     (primitive type, type-variable or special type-argument).</li>
+     * </ul>
+     * @param that the other operand of the equality test
+     * @return true if this type is the same type as {@code that}
+     */
+    boolean equals(Object that);
+
+    /**
+     * This method implements the type equality relationship {@code T <: S}. Equality is determined as follows:
+     * <ul>
+     *     <li>Given two array mirrors {@code S[]} and {@code T[]}, {@code S[] <: T[]} if {@code S <: T}</li>
+     *     <li>Given two class mirrors {@code G<X1, X2, ... Xn>} and {@code D<Y1, X2, ... Xm>}, {@code G<X1, X2, ... Xn> == D<Y1, Y2, ... Yn>} iff:
+     *     <ul>
+     *         <li>{@code G<X1, X2, ... Xn>} has a supertype of the kind {@code D<U1, U2 ... Un>}</li>
+     *         <li>for each i in 1..n either {@code Ui == Yi} or {@code Yi == any}</li>
+     *     </ul></li>
+     *     <li>Given a type-variable mirror X and a mirror T, {@code X <: T} iff there exist a bound B of X such that {@code B <: T}</li>
+     *     <li>Otherwise given two mirrors {@code S} and {@code T}, {@code S <: T} iff {@code S == T}.</li>
+     * </ul>
+     * @param that the other operand of the subtyping test
+     * @return true if this type is a subtype of {@code that}
+     */
+    boolean isSubtypeOf(RuntimeMirror that);
+
+    /**
+     * Retrieve a string-based representation of this mirror.
+     * @return string representation of this mirror
+     */
+    String getTypeString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/ScopeMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,31 @@
+package valhalla.reflect.runtime;
+
+/**
+ * {@code ScopedMirror} is the common superinterface for all mirrors that can contain members.
+ */
+public interface ScopeMirror {
+
+    /**
+     * Retrieves a lookup helper for member classes of this scoped mirror.
+     * @return lookup helper for member classes
+     */
+    ClassLookup classLookup();
+
+    /**
+     * Retrieves a lookup helper for member fields of this scoped mirror.
+     * @return lookup helper for member fields
+     */
+    FieldLookup fieldLookup();
+
+    /**
+     * Retrieves a lookup helper for member methods of this scoped mirror.
+     * @return lookup helper for member methods
+     */
+    MethodLookup methodLookup();
+
+    /**
+     * Retrieves a lookup helper for member constructors of this scoped mirror.
+     * @return lookup helper for member constructors
+     */
+    ConstructorLookup constructorLookup();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/TypeVariableMirror.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,21 @@
+package valhalla.reflect.runtime;
+
+import java.util.List;
+
+/**
+ * {@code TypeVariableMirror} represents a type-variable.
+ */
+public interface TypeVariableMirror<S extends GenericMirror<S>> extends RuntimeMirror {
+
+    /**
+     * Retrieves the type-variable bounds.
+     * @return a list containing type-variable bounds
+     */
+    List<RuntimeMirror> getBounds();
+
+    /**
+     * Retrieves the type-variable owner.
+     * @return the type-variable owner
+     */
+    S getOwner();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/AbstractLookupImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,260 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.ClassLookup;
+import valhalla.reflect.runtime.ClassMirror;
+import valhalla.reflect.runtime.ConstructorLookup;
+import valhalla.reflect.runtime.ConstructorMirror;
+import valhalla.reflect.runtime.FieldLookup;
+import valhalla.reflect.runtime.FieldMirror;
+import valhalla.reflect.runtime.MemberLookup;
+import valhalla.reflect.runtime.MemberMirror;
+import valhalla.reflect.runtime.MethodLookup;
+import valhalla.reflect.runtime.MethodMirror;
+import valhalla.reflect.runtime.RuntimeMirror;
+import valhalla.reflect.runtime.TypeVariableMirror;
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.ConstructorMirrorImpl;
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.FieldMirrorImpl;
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.MethodMirrorImpl;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+abstract class AbstractLookupImpl<M extends MemberMirror, I extends M, R> implements MemberLookup<M> {
+
+    protected final Function<Class<?>, R[]> membersFunc;
+    protected Predicate<I> membersFilter;
+    protected final Function<R, I> memberMapper;
+    protected final ClassMirrorImpl site;
+    protected InheritanceMode inheritanceMode;
+
+    protected AbstractLookupImpl(Function<Class<?>, R[]> membersFunc, Function<R, I> memberMapper,
+                              ClassMirrorImpl site, InheritanceMode inheritanceMode) {
+        this.membersFunc = membersFunc;
+        this.memberMapper = memberMapper;
+        this.membersFilter = x -> true;
+        this.site = site;
+        this.inheritanceMode = inheritanceMode;
+    }
+
+    @Override
+    public List<? extends M> findAll() {
+        return membersClosure(site.clazz).stream()
+                .map(memberMapper)
+                .filter(membersFilter)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public M findOrFail() {
+        List<? extends M> members = findAll();
+        if (findAll().size() == 1) {
+            return members.get(0);
+        } else {
+            throw new NoSuchElementException("No results found");
+        }
+    }
+
+    private static final int ALL_ACCESS_MODES = Modifier.PUBLIC |
+            Modifier.PRIVATE |
+            Modifier.PROTECTED |
+            java.lang.invoke.MethodHandles.Lookup.PACKAGE;
+
+    protected boolean isMemberAccessible(Object... args) {
+        try {
+            Class<?> c = MirrorUtils.factory.forName("sun.invoke.util.VerifyAccess", getClass());
+            return (Boolean) c.getMethod("isMemberAccessible", new Class<?>[] { Class.class, Class.class, int.class, Class.class, int.class }).invoke(null, args);
+        } catch (ReflectiveOperationException ex) {
+            ex.printStackTrace();
+            return false;
+        }
+    }
+
+    private List<R> membersClosure(Class<?> site) {
+        List<R> members = new ArrayList<>();
+        while (site != null) {
+            members.addAll(Arrays.asList(membersFunc.apply(site)));
+            site = site.getSuperclass();
+            if (inheritanceMode == InheritanceMode.DECLARED) break;
+        }
+        return members;
+    }
+
+    static class FieldLookupImpl extends AbstractLookupImpl<FieldMirror, FieldMirrorImpl, Field> implements FieldLookup {
+
+        FieldLookupImpl(ClassMirrorImpl site) {
+            super(Class::getDeclaredFields,
+                    f -> (FieldMirrorImpl)MirrorUtils.factory.field(MirrorUtils.asSuper(site, f.getDeclaringClass()), f),
+                    site, InheritanceMode.INHERITED);
+        }
+
+        @Override
+        public FieldLookupImpl withFlags(int flags) {
+            membersFilter = membersFilter.and(f -> (f.member.getModifiers() & flags) != 0);
+            return this;
+        }
+
+        @Override
+        public FieldLookup withAccessContext(Lookup lookup) {
+            membersFilter = membersFilter.and(f -> isMemberAccessible(f.member.getDeclaringClass(),
+                    f.member.getDeclaringClass(), f.member.getModifiers(), lookup.lookupClass(), ALL_ACCESS_MODES));
+            return this;
+        }
+
+        @Override
+        public FieldLookup withInheritanceMode(InheritanceMode kind) {
+            inheritanceMode = kind;
+            return this;
+        }
+
+        @Override
+        public FieldLookup withName(String name) {
+            membersFilter = membersFilter.and(f -> f.getName().equals(name));
+            return this;
+        }
+
+        @Override
+        public FieldLookup withType(RuntimeMirror type) {
+            membersFilter = membersFilter.and(f -> f.getType().equals(type));
+            return this;
+        }
+    }
+    
+    static class ConstructorLookupImpl extends AbstractLookupImpl<ConstructorMirror, ConstructorMirrorImpl, Constructor<?>> implements ConstructorLookup {
+
+        ConstructorLookupImpl(ClassMirrorImpl site) {
+            super(Class::getDeclaredConstructors,
+                    c -> (ConstructorMirrorImpl)MirrorUtils.factory.constructor(site, c),
+                    site, InheritanceMode.DECLARED);
+        }
+
+        @Override
+        public ConstructorLookup withFlags(int flags) {
+            membersFilter = membersFilter.and(c -> (c.member.getModifiers() & flags) != 0);
+            return this;
+        }
+
+        @Override
+        public ConstructorLookup withAccessContext(Lookup lookup) {
+            membersFilter = membersFilter.and(f -> isMemberAccessible(f.member.getDeclaringClass(),
+                    f.member.getDeclaringClass(), f.member.getModifiers(), lookup.lookupClass(), ALL_ACCESS_MODES));
+            return this;
+        }
+
+        @Override
+        public ConstructorLookup withParameterTypes(RuntimeMirror... paramTypes) {
+            membersFilter = membersFilter.and(f -> f.getParameterTypes().equals(Arrays.asList(paramTypes)));
+            return this;
+        }
+    }
+    
+    static class MethodLookupImpl extends AbstractLookupImpl<MethodMirror, MethodMirrorImpl, Method> implements MethodLookup {
+
+        MethodLookupImpl(ClassMirrorImpl site) {
+            super(Class::getDeclaredMethods,
+                    f -> (MethodMirrorImpl)MirrorUtils.factory.method(MirrorUtils.asSuper(site, f.getDeclaringClass()), f),
+                    site, InheritanceMode.INHERITED);
+        }
+
+        @Override
+        public MethodLookupImpl withFlags(int flags) {
+            membersFilter = membersFilter.and(f -> (f.member.getModifiers() & flags) != 0);
+            return this;
+        }
+
+        @Override
+        public MethodLookup withAccessContext(Lookup lookup) {
+            membersFilter = membersFilter.and(f -> isMemberAccessible(f.member.getDeclaringClass(),
+                    f.member.getDeclaringClass(), f.member.getModifiers(), lookup.lookupClass(), ALL_ACCESS_MODES));
+            return this;
+        }
+
+        @Override
+        public MethodLookup withInheritanceKind(InheritanceMode kind) {
+            inheritanceMode = kind;
+            return this;
+        }
+
+        @Override
+        public MethodLookup withName(String name) {
+            membersFilter = membersFilter.and(f -> f.getName().equals(name));
+            return this;
+        }
+
+        @Override
+        public MethodLookup withReturnType(RuntimeMirror type) {
+            membersFilter = membersFilter.and(f -> f.getReturnType().equals(type));
+            return this;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public MethodLookup withReturnType(Function<List<? extends TypeVariableMirror<?>>, Optional<RuntimeMirror>> returnFactory) {
+            membersFilter = membersFilter.and(m -> {
+                Optional<RuntimeMirror> ret = returnFactory.apply((List<TypeVariableMirror<?>>)m.getTypeArguments());
+                return ret.isPresent() && m.getReturnType().equals(ret.get());
+            });
+            return this;
+        }
+        
+        @Override
+        public MethodLookup withParameterTypes(RuntimeMirror... paramTypes) {
+            membersFilter = membersFilter.and(f -> f.getParameterTypes().equals(Arrays.asList(paramTypes)));
+            return this;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public MethodLookup withParameterTypes(Function<List<? extends TypeVariableMirror<?>>, Optional<List<? extends RuntimeMirror>>> paramsFactory) {
+            membersFilter = membersFilter.and(m -> {
+                Optional<List<? extends RuntimeMirror>> params = paramsFactory.apply((List<TypeVariableMirror<?>>)m.getTypeArguments());
+                return params.isPresent() && m.getParameterTypes().equals(params.get());
+            });
+            return this;
+        }
+    }
+    
+    static class ClassLookupImpl extends AbstractLookupImpl<ClassMirror, ClassMirrorImpl, Class<?>> implements ClassLookup {
+
+        ClassLookupImpl(ClassMirrorImpl site) {
+            super(Class::getDeclaredClasses,
+                    f -> (ClassMirrorImpl)MirrorUtils.factory.memberClass(MirrorUtils.asSuper(site, f.getDeclaringClass()), f),
+                    site, InheritanceMode.INHERITED);
+        }
+
+        @Override
+        public ClassLookupImpl withFlags(int flags) {
+            membersFilter = membersFilter.and(f -> (f.clazz.getModifiers() & flags) != 0);
+            return this;
+        }
+
+        @Override
+        public ClassLookup withAccessContext(Lookup lookup) {
+            membersFilter = membersFilter.and(f -> isMemberAccessible(f.clazz.getDeclaringClass(),
+                    f.clazz.getDeclaringClass(), f.clazz.getModifiers(), lookup.lookupClass(), ALL_ACCESS_MODES));
+            return this;
+        }
+
+        @Override
+        public ClassLookup withInheritanceKind(InheritanceMode kind) {
+            inheritanceMode = kind;
+            return this;
+        }
+
+        @Override
+        public ClassLookup withName(String name) {
+            membersFilter = membersFilter.and(f -> f.clazz.getName().equals(name));
+            return this;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/AbstractMemberMirrorImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,312 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.ClassMirror;
+import valhalla.reflect.runtime.ConstructorMirror;
+import valhalla.reflect.runtime.FieldMirror;
+import valhalla.reflect.runtime.MemberLookup.InheritanceMode;
+import valhalla.reflect.runtime.MemberMirror;
+import valhalla.reflect.runtime.MethodMirror;
+import valhalla.reflect.runtime.RuntimeMirror;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class AbstractMemberMirrorImpl<M extends Member> implements MemberMirror {
+
+    protected final ClassMirrorImpl owner;
+    protected final M member;
+
+    @SuppressWarnings("unchecked")
+    protected <Z extends RuntimeMirror> Z map(Type t) {
+        return (Z)owner.map(t);
+    }
+
+    protected AbstractMemberMirrorImpl(ClassMirrorImpl owner, M member) {
+        this.owner = owner;
+        this.member = member;
+    }
+
+    @Override
+    public String getName() {
+        return member.getName();
+    }
+
+    @Override
+    public ClassMirror getEnclosingType() {
+        return owner;
+    }
+
+    static class FieldMirrorImpl extends AbstractMemberMirrorImpl<Field> implements FieldMirror {
+
+        FieldMirrorImpl(ClassMirrorImpl owner, Field field) {
+            super(owner, field);
+        }
+
+        @Override
+        public RuntimeMirror getType() {
+            return owner.map(member.getGenericType());
+        }
+
+        @Override
+        public VarHandle asHandle() throws IllegalAccessException {
+            throw new UnsupportedOperationException(); //how to unreflect a field?
+        }
+
+        @Override
+        public MethodHandle asGetterHandle() throws IllegalAccessException {
+            return MethodHandles.lookup().unreflectGetter(reflect());
+        }
+
+        @Override
+        public MethodHandle asSetterHandle() throws IllegalAccessException {
+            return MethodHandles.lookup().unreflectSetter(reflect());
+        }
+
+        @Override
+        public Field reflect() {
+            if (owner.isSpecializable()) {
+                throw new IllegalStateException("Open type variables in owner!");
+            }
+            try {
+                return owner.reflect().getDeclaredField(member.getName());
+            } catch (ReflectiveOperationException ex) {
+                throw new IllegalStateException();
+            }
+        }
+    }
+
+    static class MethodMirrorImpl extends AbstractMemberMirrorImpl<Method> implements MethodMirror {
+
+        MethodMirrorImpl(ClassMirrorImpl owner, Method method) {
+            super(owner, method);
+        }
+
+        @Override
+        public RuntimeMirror getReturnType() {
+            return map(member.getGenericReturnType());
+        }
+
+        @Override
+        public List<? extends RuntimeMirror> getParameterTypes() {
+            return Stream.of(member.getGenericParameterTypes())
+                    .map(this::<RuntimeMirror>map)
+                    .collect(Collectors.toList());
+        }
+
+        @Override
+        public MethodHandle asHandle() throws IllegalAccessException {
+            return MethodHandles.lookup().unreflect(reflect());
+        }
+
+        @Override
+        public Method reflect() {
+            if (owner.isSpecializable()) {
+                throw new IllegalStateException("Open type variables in owner!");
+            }
+            try {
+                return owner.reflect().getDeclaredMethod(member.getName(),
+                        getParameterTypes().stream().map(RuntimeMirror::reflect).toArray(Class<?>[]::new));
+            } catch (ReflectiveOperationException ex) {
+                throw new IllegalStateException();
+            }
+        }
+
+        @Override
+        public boolean isSpecializable() {
+            return false;
+        }
+
+        @Override
+        public List<? extends RuntimeMirror> getTypeArguments() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public MethodMirror asSpecializedMirror(RuntimeMirror... typeArgs) {
+            throw new IllegalStateException();
+        }
+
+        @Override
+        public MethodMirror asGenericMirror() {
+            throw new IllegalStateException();
+        }
+    }
+
+    static class ConstructorMirrorImpl extends AbstractMemberMirrorImpl<Constructor<?>> implements ConstructorMirror {
+
+        ConstructorMirrorImpl(ClassMirrorImpl owner, Constructor<?> member) {
+            super(owner, member);
+        }
+
+        @Override
+        public List<? extends RuntimeMirror> getParameterTypes() {
+            return Stream.of(member.getGenericParameterTypes())
+                    .map(owner::<RuntimeMirror>map)
+                    .collect(Collectors.toList());
+        }
+
+        @Override
+        public ClassMirror getEnclosingType() {
+            return owner;
+        }
+
+        @Override
+        public MethodHandle asHandle() throws IllegalAccessException {
+            return MethodHandles.lookup().unreflectConstructor(reflect());
+        }
+
+        @Override
+        public Constructor<?> reflect() {
+            if (owner.isSpecializable()) {
+                throw new IllegalStateException("Open type variables in owner!");
+            }
+            try {
+                return owner.reflect().getDeclaredConstructor(
+                        getParameterTypes().stream().map(RuntimeMirror::reflect).toArray(Class<?>[]::new));
+            } catch (ReflectiveOperationException ex) {
+                throw new IllegalStateException();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "<init>";
+        }
+    }
+
+    static class GenericMethodMirrorImpl extends MethodMirrorImpl {
+
+        final ClassMirrorImpl genericClassMirror;
+        final List<RuntimeMirror> typeArgs;
+
+        GenericMethodMirrorImpl(ClassMirrorImpl owner, Method method, List<RuntimeMirror> typeArgs) {
+            super(owner, method);
+            this.genericClassMirror = (ClassMirrorImpl) owner.classLookup()
+                    .withInheritanceKind(InheritanceMode.DECLARED)
+                    .withName(innerName(method)).findOrFail();
+            this.typeArgs = typeArgs;
+        }
+
+        static String innerName(Method m) {
+            MethodType targetMethod = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
+            String desc = targetMethod.toMethodDescriptorString();
+            String params = desc.substring(1, desc.lastIndexOf(')'));
+            return m.getDeclaringClass().getName() + "$" + m.getName() + "$" + Math.abs(params.hashCode());
+        }
+
+        @Override
+        public List<? extends RuntimeMirror> getTypeArguments() {
+            return typeArgs;
+        }
+
+        @Override
+        public boolean isSpecializable() {
+            return true;
+        }
+
+        @Override
+        public Method reflect() {
+            throw new IllegalStateException("open type variables!");
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public MethodMirror asSpecializedMirror(RuntimeMirror... typeArgs) {
+            if (owner.isSpecializable()) {
+                throw new IllegalStateException("Open type variables in owner!");
+            }
+            List<RuntimeMirror> actualTypeArgs = Arrays.asList(typeArgs);
+            if (actualTypeArgs.size() != getTypeArguments().size()) {
+                new FooImpl(null, null);
+                throw new IllegalStateException();
+            }
+            return new SpecializedMethodMirrorImpl(this, actualTypeArgs);
+        }
+
+        @Override
+        public MethodMirror asGenericMirror() {
+            return this;
+        }
+    }
+
+    static class FooImpl extends MethodMirrorImpl {
+        public FooImpl(ClassMirrorImpl owner, Method method) {
+            super(owner, method);
+        }
+    }
+
+    static class SpecializedMethodMirrorImpl extends MethodMirrorImpl {
+
+        final GenericMethodMirrorImpl genericMethod;
+        final List<RuntimeMirror> actualTypeArgs;
+
+        SpecializedMethodMirrorImpl(GenericMethodMirrorImpl genericMethod, List<RuntimeMirror> actualTypeArgs) {
+            super(genericMethod.owner,
+                    ((MethodMirrorImpl)genericMethod.genericClassMirror.methodLookup()
+                        .withName(genericMethod.getName()).findOrFail()).member);
+            this.genericMethod = genericMethod;
+            this.actualTypeArgs = actualTypeArgs;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        protected RuntimeMirror map(Type t) {
+            return MirrorUtils.subst(super.map(t), (List<RuntimeMirror>)genericMethod.genericClassMirror.getTypeArguments(), actualTypeArgs);
+        }
+
+        @Override
+        public List<? extends RuntimeMirror> getTypeArguments() {
+            return actualTypeArgs;
+        }
+
+        @Override
+        public MethodMirror asGenericMirror() {
+            return genericMethod;
+        }
+
+        @Override
+        public Method reflect() {
+            return genericMethod.genericClassMirror.asSpecializedMirror(actualTypeArgs.stream().toArray(RuntimeMirror[]::new))
+                    .methodLookup()
+                        .withName(member.getName())
+                        .withParameterTypes(getParameterTypes().stream().toArray(RuntimeMirror[]::new)).findOrFail().reflect();
+        }
+
+        @Override
+        public MethodHandle asHandle() throws IllegalAccessException {
+            MethodHandle mh = super.asHandle();
+            if (!Modifier.isStatic(member.getModifiers())) {
+                try {
+                    MethodHandle wrap = MethodHandles.lookup().findVirtual(getClass(), "wrap", MethodType.methodType(Object.class, Object[].class));
+                    MethodHandle boundWrap = wrap.bindTo(this);
+                    return boundWrap.asVarargsCollector(Object[].class);
+                } catch (Throwable ex) {
+                    throw new IllegalStateException(ex);
+                }
+            } else {
+                return mh;
+            }
+        }
+
+        public Object wrap(Object... args) throws ReflectiveOperationException {
+            Method ref = reflect();
+            Object rec = ref.getDeclaringClass().getConstructors()[0].newInstance(args[0]);
+            Object[] args2 = new Object[args.length - 1];
+            System.arraycopy(args, 1, args2, 0, args2.length);
+            return ref.invoke(rec, args2);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/ArrayMirrorImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,59 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.ArrayMirror;
+import valhalla.reflect.runtime.RuntimeMirror;
+
+class ArrayMirrorImpl implements ArrayMirror {
+
+    private final RuntimeMirror elemtype;
+
+    ArrayMirrorImpl(RuntimeMirror elemtype) {
+        this.elemtype = elemtype;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.ARRAY;
+    }
+
+    @Override
+    public boolean isSubtypeOf(RuntimeMirror that) {
+        return equals(that) ||
+                (that.getKind() == Kind.ARRAY && elemtype.isSubtypeOf(((ArrayMirror) that).getComponentType()));
+    }
+
+    @Override
+    public String getTypeString() {
+        return elemtype.getTypeString() + "[]";
+    }
+
+    @Override
+    public Class<?> reflect() {
+        try {
+            Class<?> elemClazz = elemtype.reflect();
+            return MirrorUtils.factory.forName("[" + elemClazz.getCanonicalName(), elemClazz);
+        } catch (ReflectiveOperationException ex) {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ArrayMirrorImpl) {
+            ArrayMirrorImpl that = (ArrayMirrorImpl)obj;
+            return getComponentType().equals(that.getComponentType());
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return getComponentType().hashCode() << 1;
+    }
+
+    @Override
+    public RuntimeMirror getComponentType() {
+        return elemtype;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/ClassMirrorImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,334 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.ClassLookup;
+import valhalla.reflect.runtime.ClassMirror;
+import valhalla.reflect.runtime.ConstructorLookup;
+import valhalla.reflect.runtime.FieldLookup;
+import valhalla.reflect.runtime.MethodLookup;
+import valhalla.reflect.runtime.RuntimeMirror;
+import valhalla.reflect.runtime.impl.AbstractLookupImpl.ClassLookupImpl;
+import valhalla.reflect.runtime.impl.AbstractLookupImpl.ConstructorLookupImpl;
+import valhalla.reflect.runtime.impl.AbstractLookupImpl.FieldLookupImpl;
+import valhalla.reflect.runtime.impl.AbstractLookupImpl.MethodLookupImpl;
+
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class ClassMirrorImpl extends DelegatedMirrorImpl implements ClassMirror {
+
+    protected List<RuntimeMirror> typeArgs;
+
+    ClassMirrorImpl(Class<?> clazz) {
+        super(clazz);
+    }
+
+    @SuppressWarnings("unchecked")
+    <Z extends RuntimeMirror> Z map(Type t) {
+        return (Z)MirrorUtils.typeToMirror(t);
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        return super.equals(that) &&
+                ((ClassMirrorImpl)that).getTypeArguments().equals(getTypeArguments());
+
+    }
+
+    @Override
+    public boolean isSubtypeOf(RuntimeMirror that) {
+        if (equals(that)) {
+            //short-circuit
+            return true;
+        } else if (that.getKind() == Kind.CLASS) {
+            ClassMirrorImpl thatClazz = (ClassMirrorImpl)that;
+            ClassMirror sup = MirrorUtils.asSuper(this, thatClazz.clazz);
+            if (sup == null) {
+                return false;
+            }
+            List<? extends RuntimeMirror> thisArgs = sup.getTypeArguments();
+            List<? extends RuntimeMirror> thatArgs = thatClazz.getTypeArguments();
+            for (int i = 0 ; i < thisArgs.size() ; i++) {
+                if (!thisArgs.get(i).equals(thatArgs.get(i)) && thatArgs.get(i).getKind() != Kind.ANY) {
+                    return false;
+                }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() | getTypeArguments().hashCode();
+    }
+
+    //structural queries
+
+    @Override
+    public List<? extends RuntimeMirror> getTypeArguments() {
+        if (typeArgs == null) {
+            //delay computation to prevent factory deadlocks
+            typeArgs = Stream.of(clazz.getTypeParameters())
+                    .filter(TypeVariable::isAny)
+                    .map(MirrorUtils.factory::typeVarMirror)
+                    .collect(Collectors.toList());
+        }
+        return typeArgs;
+    }
+
+    @Override
+    public ClassMirror getEnclosingType() {
+        return null;
+    }
+
+    @Override
+    public List<? extends ClassMirror> getSupertypes() {
+        List<ClassMirror> sups = new ArrayList<>();
+        if (clazz.getGenericSuperclass() != null) {
+            sups.add(map(clazz.getGenericSuperclass()));
+        }
+        Stream.of(clazz.getGenericInterfaces())
+                .map(this::<ClassMirror>map)
+                .collect(Collectors.toCollection(() -> sups));
+        return sups;
+    }
+
+    @Override
+    public ClassLookup classLookup() {
+        return new ClassLookupImpl(this);
+    }
+
+    @Override
+    public FieldLookup fieldLookup() {
+        return new FieldLookupImpl(this);
+    }
+
+    @Override
+    public MethodLookup methodLookup() {
+        return new MethodLookupImpl(this);
+    }
+
+    @Override
+    public ConstructorLookup constructorLookup() {
+        return new ConstructorLookupImpl(this);
+    }
+
+    @Override
+    public boolean isSpecializable() {
+        ClassMirror curr = this;
+        while (curr != null) {
+            if (!curr.getTypeArguments().isEmpty()) {
+                return true;
+            }
+            curr = (ClassMirrorImpl)curr.getEnclosingType();
+        }
+        return false;
+    }
+
+    @Override
+    public ClassMirror asSpecializedMirror(RuntimeMirror... typeArgs) {
+        List<RuntimeMirror> actualTypeArgs = Arrays.asList(typeArgs);
+        if (actualTypeArgs.size() != getTypeArguments().size()) {
+            throw new IllegalStateException();
+        }
+        ClassMirror encl = getEnclosingType();
+        if (encl != null && encl.isSpecializable()) {
+            throw new IllegalStateException("Open type variables in owner!");
+        }
+        return new SpecializedClassMirrorImpl(this, actualTypeArgs);
+    }
+
+    @Override
+    public ClassMirror asGenericMirror() {
+        return this;
+    }
+
+    @Override
+    public String getTypeString() {
+        String res = getEnclosingType() == null ?
+                super.getTypeString() :
+                getEnclosingType().getTypeString() + "." + clazz.getSimpleName();
+        if (getTypeArguments().size() > 0) {
+            res += getTypeArguments().stream()
+                    .map(RuntimeMirror::getTypeString)
+                    .collect(Collectors.joining(",", "<", ">"));
+        }
+        return res;
+    }
+
+    @Override
+    public String getName() {
+        return clazz.getSimpleName();
+    }
+
+    @Override
+    public Class<?> reflect() {
+        if (isSpecializable()) {
+            throw new IllegalStateException("Open variables!");
+        } else {
+            String encl = null;
+            if (getEnclosingType() != null) {
+                encl = getEnclosingType().reflect().getName();
+            }
+            String args = "";
+            if (getTypeArguments().size() > 0 &&
+                    getTypeArguments().stream().anyMatch(ta -> ta.getKind() != Kind.ERASED)) {
+                args = getTypeArguments().stream()
+                        .map(this::toDesc)
+                        .collect(Collectors.joining("", "$${", "}"));
+            }
+            try {
+                String prefix;
+                if (encl != null) {
+                    String innerName = clazz.getName();
+                    if (innerName.contains(".")) { //skip packages here!
+                        innerName = innerName.substring(innerName.lastIndexOf('.') + 1);
+                    }
+                    prefix = encl + "$$$" + innerName;
+                } else {
+                    prefix = clazz.getName();
+                }
+                return MirrorUtils.factory.forName(prefix + args, clazz);
+            } catch (ReflectiveOperationException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+    }
+
+    private String toDesc(RuntimeMirror r) {
+        if (r instanceof DelegatedMirrorImpl) {
+            Class<?> c = ((DelegatedMirrorImpl)r).clazz;
+            if (c.isPrimitive()) {
+                if (c.equals(Byte.TYPE)) {
+                    return "B";
+                } else if (c.equals(Short.TYPE)) {
+                    return "S";
+                } else if (c.equals(Integer.TYPE)) {
+                    return "I";
+                } else if (c.equals(Float.TYPE)) {
+                    return "F";
+                } else if (c.equals(Long.TYPE)) {
+                    return "J";
+                } else if (c.equals(Double.TYPE)) {
+                    return "D";
+                } else if (c.equals(Character.TYPE)) {
+                    return "C";
+                } else if (c.equals(Boolean.TYPE)) {
+                    return "Z";
+                } else {
+                    throw new IllegalStateException();
+                }
+            } else {
+                return "_";
+            }
+        } else if (r.getKind() == Kind.ERASED) {
+            return "_";
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
+    private static class SpecializedClassMirrorImpl extends ClassMirrorImpl {
+
+        final ClassMirrorImpl genericMirror;
+        final List<RuntimeMirror> actualTypeArgs;
+
+        private SpecializedClassMirrorImpl(ClassMirrorImpl genericMirror, List<RuntimeMirror> actualTypeArgs) {
+            super(genericMirror.clazz);
+            this.genericMirror = genericMirror;
+            this.actualTypeArgs = actualTypeArgs;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        <Z extends RuntimeMirror> Z map(Type t) {
+            return (Z)MirrorUtils.subst(genericMirror.map(t), (List<RuntimeMirror>)genericMirror.getTypeArguments(), actualTypeArgs);
+        }
+
+        @Override
+        public boolean equals(Object that) {
+            return super.equals(that) &&
+                    genericMirror.equals(((SpecializedClassMirrorImpl)that).genericMirror);
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode() | genericMirror.hashCode();
+        }
+
+        @Override
+        public boolean isSpecializable() {
+            return false;
+        }
+
+        @Override
+        public ClassMirror asSpecializedMirror(RuntimeMirror... typeArgs) {
+            throw new IllegalStateException("already specialized");
+        }
+
+        @Override
+        public List<? extends RuntimeMirror> getTypeArguments() {
+            return actualTypeArgs;
+        }
+
+        @Override
+        public ClassMirror asGenericMirror() {
+            return genericMirror;
+        }
+
+        @Override
+        public ClassMirror getEnclosingType() {
+            return genericMirror.getEnclosingType();
+        }
+    }
+
+    static class InnerClassMirrorImpl extends ClassMirrorImpl {
+
+        final ClassMirrorImpl encl;
+
+        InnerClassMirrorImpl(Class<?> clazz, ClassMirrorImpl encl) {
+            super(clazz);
+            this.encl = encl;
+        }
+
+        @Override
+        <Z extends RuntimeMirror> Z map(Type t) {
+            return encl.map(t);
+        }
+
+        @Override
+        public ClassMirror getEnclosingType() {
+            return encl;
+        }
+
+        @Override
+        public boolean equals(Object that) {
+            return super.equals(that) &&
+                    encl.equals(((ClassMirror)that).getEnclosingType());
+
+        }
+
+        @Override
+        public ClassMirror asSpecializedMirror(RuntimeMirror... typeArgs) {
+            ClassMirror encl1 = encl;
+            while (encl1 != null) {
+                if (encl1.isSpecializable()) {
+                    throw new IllegalStateException("Open type variables in enclosing type!");
+                }
+                encl1 = (ClassMirrorImpl)encl1.getEnclosingType();
+            }
+            return super.asSpecializedMirror(typeArgs);
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode() | getEnclosingType().hashCode();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/DelegatedMirrorImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,50 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.RuntimeMirror;
+
+class DelegatedMirrorImpl implements RuntimeMirror {
+
+    final Class<?> clazz;
+
+    DelegatedMirrorImpl(Class<?> clazz) {
+        this.clazz = clazz;
+    }
+
+    @Override
+    public Kind getKind() {
+        if (clazz.isPrimitive()) {
+            return Kind.VALUE;
+        } else if (clazz.isArray()) {
+            return Kind.ARRAY;
+        } else {
+            return Kind.CLASS;
+        }
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        return that instanceof DelegatedMirrorImpl &&
+                clazz.equals(((DelegatedMirrorImpl) that).clazz);
+    }
+
+    @Override
+    public int hashCode() {
+        return clazz.hashCode();
+    }
+
+    @Override
+    public boolean isSubtypeOf(RuntimeMirror that) {
+        return that instanceof DelegatedMirrorImpl &&
+                ((DelegatedMirrorImpl) that).clazz.isAssignableFrom(clazz);
+    }
+
+    @Override
+    public String getTypeString() {
+        return clazz.getName();
+    }
+
+    @Override
+    public Class<?> reflect() {
+        return clazz;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/MirrorFactoryImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,152 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.ArrayMirror;
+import valhalla.reflect.runtime.ClassMirror;
+import valhalla.reflect.runtime.ConstructorMirror;
+import valhalla.reflect.runtime.FieldMirror;
+import valhalla.reflect.runtime.GenericMirror;
+import valhalla.reflect.runtime.MemberMirror;
+import valhalla.reflect.runtime.MethodMirror;
+import valhalla.reflect.runtime.MirrorFactory;
+import valhalla.reflect.runtime.RuntimeMirror;
+import valhalla.reflect.runtime.RuntimeMirror.Kind;
+import valhalla.reflect.runtime.TypeVariableMirror;
+import valhalla.reflect.runtime.impl.ClassMirrorImpl.InnerClassMirrorImpl;
+
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.ConstructorMirrorImpl;
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.FieldMirrorImpl;
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.GenericMethodMirrorImpl;
+import valhalla.reflect.runtime.impl.AbstractMemberMirrorImpl.MethodMirrorImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class MirrorFactoryImpl implements MirrorFactory {
+
+    private final Map<Object, RuntimeMirror> type_cache = new ConcurrentHashMap<>();
+    private final Map<Object, Map<RuntimeMirror, MemberMirror>> members_cache = new ConcurrentHashMap<>();
+
+    private final RuntimeMirror erasedMirror = new TypeArgumentMirrorImpl(Kind.ERASED);
+    private final RuntimeMirror anyMirror = new TypeArgumentMirrorImpl(Kind.ANY);
+
+    private static MirrorFactoryImpl singleton;
+
+    private MirrorFactoryImpl() { }
+
+    public static MirrorFactoryImpl instance() {
+        if (singleton == null) {
+            singleton = new MirrorFactoryImpl();
+        }
+        return singleton;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <Z extends GenericMirror<Z>> TypeVariableMirror<Z> typeVarMirror(TypeVariable<?> typeVariable) {
+        return (TypeVariableMirror<Z>)type_cache.computeIfAbsent(typeVariable, tv -> new TypeVariableMirrorImpl<Z>(typeVariable));
+    }
+
+    @Override
+    public ClassMirror classMirror(Class<?> clazz) {
+        if (clazz.isArray() || clazz.isPrimitive()) {
+            throw new IllegalStateException();
+        }
+        return from(clazz);
+    }
+
+    @Override
+    public RuntimeMirror primitiveMirror(Class<?> clazz) {
+        if (!clazz.isPrimitive()) {
+            throw new IllegalStateException();
+        }
+        return from(clazz);
+    }
+
+    @Override
+    public ArrayMirror arrayMirror(RuntimeMirror componentType) {
+        return (ArrayMirror)type_cache.computeIfAbsent(componentType, tv -> new ArrayMirrorImpl(componentType));
+    }
+
+    @Override
+    public ArrayMirror arrayMirror(Class<?> clazz) {
+        if (!clazz.isArray()) {
+            throw new IllegalStateException();
+        }
+        return from(clazz);
+    }
+
+    @Override
+    public RuntimeMirror erasedMirror() {
+        return erasedMirror;
+    }
+
+    @Override
+    public RuntimeMirror anyMirror() {
+        return anyMirror;
+    }
+
+    @SuppressWarnings("unchecked")
+    <Z extends RuntimeMirror> Z from(Class<?> clazz) {
+        if (clazz.isPrimitive()) {
+            return (Z)type_cache.computeIfAbsent(clazz, tv -> new DelegatedMirrorImpl(clazz));
+        } else if (clazz.isArray()) {
+            RuntimeMirror componentType = from(clazz.getComponentType());
+            return (Z)arrayMirror(componentType);
+        } else {
+            return (Z)memberClass(MirrorUtils.needsEnclosingType(clazz) ?
+                from(clazz.getEnclosingClass()) : null, clazz);
+        }
+    }
+
+    FieldMirror field(RuntimeMirror encl, Field field) {
+        Map<RuntimeMirror, MemberMirror> fields =
+                members_cache.computeIfAbsent(field, _unused -> new ConcurrentHashMap<>());
+        return (FieldMirror)fields.computeIfAbsent(encl, _unused -> new FieldMirrorImpl((ClassMirrorImpl)encl, field));
+    }
+
+    MethodMirror method(RuntimeMirror encl, Method method) {
+        Map<RuntimeMirror, MemberMirror> methods =
+                members_cache.computeIfAbsent(method, _unused -> new ConcurrentHashMap<>());
+        return (MethodMirror)methods.computeIfAbsent(encl, _unused -> {
+            List<RuntimeMirror> avars = Stream.of(method.getTypeParameters())
+                    .filter(TypeVariable::isAny)
+                    .map(this::typeVarMirror)
+                    .collect(Collectors.toList());
+            return !avars.isEmpty() ?
+                    new GenericMethodMirrorImpl((ClassMirrorImpl)encl, method, avars) :
+                    new MethodMirrorImpl((ClassMirrorImpl)encl, method);
+        });
+    }
+
+    ConstructorMirror constructor(RuntimeMirror encl, Constructor<?> constr) {
+        Map<RuntimeMirror, MemberMirror> constructors =
+                members_cache.computeIfAbsent(constr, _unused -> new ConcurrentHashMap<>());
+        return (ConstructorMirror)constructors.computeIfAbsent(encl, _unused -> new ConstructorMirrorImpl((ClassMirrorImpl)encl, constr));
+    }
+
+    ClassMirror memberClass(RuntimeMirror encl, Class<?> memberClazz) {
+        if (MirrorUtils.needsEnclosingType(memberClazz)) {
+            Map<RuntimeMirror, MemberMirror> memberClasses =
+                    members_cache.computeIfAbsent(memberClazz, _unused -> new ConcurrentHashMap<>());
+            return (ClassMirror)memberClasses.computeIfAbsent(encl, _unused -> new InnerClassMirrorImpl(memberClazz, (ClassMirrorImpl)encl));
+        } else {
+            return (ClassMirror)type_cache.computeIfAbsent(memberClazz, tv -> new ClassMirrorImpl(memberClazz));
+        }
+    }
+
+    Class<?> forName(String name, Class<?> contextClass) throws ClassNotFoundException {
+        ClassLoader cl = contextClass.getClassLoader();
+        if (cl == null) {
+            //use boot loader
+            cl = getClass().getClassLoader();
+        }
+        return Class.forName(name, false, cl);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/MirrorUtils.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,145 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.ArrayMirror;
+import valhalla.reflect.runtime.ClassMirror;
+import valhalla.reflect.runtime.RuntimeMirror;
+import valhalla.reflect.runtime.RuntimeMirror.Kind;
+import valhalla.reflect.runtime.TypeVariableMirror;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class MirrorUtils {
+
+    static MirrorFactoryImpl factory = MirrorFactoryImpl.instance();
+
+    public static RuntimeMirror typeToMirror(Type type) {
+        if (type instanceof TypeVariable<?>) {
+            TypeVariable<?> tv = (TypeVariable<?>)type;
+            return tv.isAny() ? factory.typeVarMirror(tv) : typeToMirror(tv.getBounds()[0]);
+        } else if (type instanceof GenericArrayType) {
+            GenericArrayType array = (GenericArrayType)type;
+            RuntimeMirror elem = typeToMirror(array.getGenericComponentType());
+            return factory.arrayMirror(elem);
+        } else if (type instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType)type;
+            RuntimeMirror encl = null;
+            if (pt.getOwnerType() != null) {
+                encl = typeToMirror(pt.getOwnerType());
+            }
+            TypeVariable<?>[] formals = ((Class<?>)pt.getRawType()).getTypeParameters();
+            List<RuntimeMirror> typeargs = new ArrayList<>();
+            for (int i = 0; i < formals.length ; i++) {
+                if (formals[i].isAny()) {
+                    typeargs.add(MirrorUtils.typeArgToMirror(pt.getActualTypeArguments()[i]));
+                }
+            }
+            ClassMirror mirror = encl == null ?
+                    factory.classMirror((Class<?>)pt.getRawType()) :
+                    factory.memberClass(encl, (Class<?>)pt.getRawType());
+            return typeargs.isEmpty() ?
+                    mirror :
+                    mirror.asSpecializedMirror(typeargs.stream().toArray(RuntimeMirror[]::new));
+        } else {
+            if (!(type instanceof Class<?>)) {
+                throw new IllegalStateException("Unexpected type: " + type.getTypeName());
+            }
+            Class<?> clazz = (Class<?>)type;
+            return factory.from(clazz);
+        }
+    }
+
+    private static RuntimeMirror typeArgToMirror(Type type) {
+        if (type instanceof TypeVariable<?>) {
+            TypeVariable<?> tv = (TypeVariable<?>)type;
+            return tv.isAny() ? typeToMirror(tv) : factory.erasedMirror();
+        } else if (type instanceof WildcardType) {
+            WildcardType wild = (WildcardType)type;
+            return wild.getLowerBounds().length != 0 ?
+                    typeArgToMirror(wild.getLowerBounds()[0]) : typeArgToMirror(wild.getUpperBounds()[0]);
+        } else if (type instanceof Class<?>) {
+            Class<?> clazz = (Class<?>)type;
+            return clazz.isPrimitive() ?
+                    typeToMirror(type) : factory.erasedMirror();
+        } else {
+            return factory.erasedMirror();
+        }
+    }
+
+    static RuntimeMirror subst(RuntimeMirror type, List<RuntimeMirror> from, List<RuntimeMirror> to) {
+        if (from.size() != to.size()) {
+            throw new IllegalStateException();
+        }
+        Map<RuntimeMirror, RuntimeMirror> substMap = new HashMap<>(from.size());
+        for (int i = 0 ; i < from.size() ; i++) {
+            substMap.put(from.get(i), to.get(i));
+        }
+        return subst(type, substMap, false);
+    }
+
+    private static RuntimeMirror subst(RuntimeMirror type, Map<RuntimeMirror, RuntimeMirror> substMap, boolean typeArgPos) {
+        switch (type.getKind()) {
+            case TYPEVAR: {
+                RuntimeMirror to = substMap.get(type);
+                if (to == null) {
+                    return type;
+                } else if (to.getKind() == Kind.ERASED) { //TODO: any should propagate outwards
+                    if (typeArgPos) {
+                        return to;
+                    } else {
+                        List<? extends RuntimeMirror> bounds = ((TypeVariableMirror<?>) type).getBounds();
+                        return bounds.isEmpty() ?
+                                factory.from(Object.class) : //any type-vars should erase to Object
+                                bounds.get(0);
+                    }
+                } else {
+                    return to;
+                }
+            }
+            case ARRAY: {
+                ArrayMirror arr = (ArrayMirror) type;
+                return factory.arrayMirror(subst(arr.getComponentType(), substMap, false));
+            }
+            case CLASS: {
+                ClassMirrorImpl templateClass = (ClassMirrorImpl) type;
+                List<? extends RuntimeMirror> typeArgs = templateClass.getTypeArguments();
+                if (typeArgs.size() != 0) {
+                    List<RuntimeMirror> newTypeArgs = typeArgs.stream()
+                            .map(ta -> subst(ta, substMap, true))
+                            .collect(Collectors.toList());
+                    if (!newTypeArgs.equals(typeArgs)) {
+                        return templateClass.asGenericMirror().asSpecializedMirror(newTypeArgs.toArray(new RuntimeMirror[typeArgs.size()]));
+                    }
+                }
+                return type;
+            }
+            default:
+                return type;
+        }
+    }
+
+    static ClassMirrorImpl asSuper(ClassMirrorImpl site, Class<?> sym) {
+        if (site.clazz.equals(sym)) {
+            return site;
+        } else {
+            return site.getSupertypes().stream()
+                    .map(rtm -> asSuper((ClassMirrorImpl)rtm, sym))
+                    .filter(rtm -> rtm != null)
+                    .findFirst().orElse(null);
+        }
+    }
+
+    static boolean needsEnclosingType(Class<?> clazz) {
+        return clazz.getEnclosingClass() != null && !Modifier.isStatic(clazz.getModifiers());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/TypeArgumentMirrorImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,52 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.RuntimeMirror;
+
+class TypeArgumentMirrorImpl implements RuntimeMirror {
+
+    private final Kind kind;
+
+    TypeArgumentMirrorImpl(Kind kind) {
+        this.kind = kind;
+    }
+
+    @Override
+    public Kind getKind() {
+        return kind;
+    }
+
+    @Override
+    public boolean isSubtypeOf(RuntimeMirror that) {
+        return false;
+    }
+
+    @Override
+    public String getTypeString() {
+        switch (kind) {
+            case ANY: return "?";
+            case ERASED: return "_";
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public Class<?> reflect() {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof TypeArgumentMirrorImpl) {
+            TypeArgumentMirrorImpl that = (TypeArgumentMirrorImpl)obj;
+            return kind.equals(that.kind);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return kind.hashCode();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/impl/TypeVariableMirrorImpl.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,77 @@
+package valhalla.reflect.runtime.impl;
+
+import valhalla.reflect.runtime.GenericMirror;
+import valhalla.reflect.runtime.RuntimeMirror;
+import valhalla.reflect.runtime.TypeVariableMirror;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class TypeVariableMirrorImpl<S extends GenericMirror<S>> implements TypeVariableMirror<S> {
+
+    private final TypeVariable<?> typeVar;
+
+    @Override
+    public Kind getKind() {
+        return Kind.TYPEVAR;
+    }
+
+    @Override
+    public boolean isSubtypeOf(RuntimeMirror that) {
+        return equals(that) ||
+                getBounds().stream().anyMatch(b -> b.isSubtypeOf(that));
+    }
+
+    @Override
+    public Class<?> reflect() {
+        throw new IllegalStateException("Cannot reflect type-variable: " + typeVar.getName());
+    }
+
+    TypeVariableMirrorImpl(TypeVariable<?> typeVar) {
+        this.typeVar = typeVar;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof TypeVariableMirrorImpl<?>) {
+            TypeVariableMirrorImpl<?> that = (TypeVariableMirrorImpl<?>)obj;
+            return that.typeVar.equals(typeVar);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return typeVar.hashCode();
+    }
+
+    @Override
+    public List<RuntimeMirror> getBounds() {
+        return Stream.of(typeVar.getBounds())
+                .map(MirrorUtils::typeToMirror)
+                .filter(b -> !MirrorUtils.factory.from(Object.class).equals(b))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public String getTypeString() {
+        return typeVar.getName();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public S getOwner() {
+        if (typeVar.getGenericDeclaration() instanceof Method) {
+            Method method = (Method)typeVar.getGenericDeclaration();
+            return (S)MirrorUtils.factory.method(MirrorUtils.factory.classMirror(method.getDeclaringClass()), method);
+        } else if (typeVar.getGenericDeclaration() instanceof Class<?>) {
+            return (S) MirrorUtils.factory.classMirror((Class<?>) typeVar.getGenericDeclaration());
+        } else {
+            throw new IllegalStateException(); //constructor avars not supported
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/valhalla/reflect/runtime/package-info.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,4 @@
+/**
+ * Provides classes and interfaces for obtaining reflective information about reifiable types.
+ */
+package valhalla.reflect.runtime;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/MirrorBuilder.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,300 @@
+package valhalla.reflect.runtime;
+
+/*
+* Copyright (c) 2016, 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.
+*
+* 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.
+*/
+
+import valhalla.reflect.runtime.impl.MirrorUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.charset.Charset;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+public class MirrorBuilder {
+
+    Map<String, RuntimeMirror> mirror_cache = new ConcurrentHashMap<>();
+
+    static final int MAX_RETRY_COUNT = 10;
+
+    JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+
+    ThreadLocal<JavaFileManager> jfm = new ThreadLocal<>() {
+        @Override
+        protected JavaFileManager initialValue() {
+            return comp.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset());
+        }
+    };
+
+    ThreadLocal<URLClassLoader> loaders = new ThreadLocal<>() {
+        @Override
+        protected URLClassLoader initialValue() {
+            try {
+                return new URLClassLoader(new URL[]{new File(tmpDirName()).toURI().toURL()}, this.getClass().getClassLoader());
+            } catch (Throwable ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+    };
+
+    AtomicInteger id = new AtomicInteger();
+
+    String pkg;
+    List<String> imports;
+    List<String> typeVarDecls;
+    List<Type> typeVariables;
+
+    public MirrorBuilder(String pkg, List<String> imports, List<String> typeVarDecls) {
+        this.pkg = pkg;
+        this.imports = imports;
+        this.typeVarDecls = typeVarDecls;
+        this.typeVariables = typeVarDecls.stream()
+                .map(this::typeVarName)
+                .map(this::getType)
+                .collect(Collectors.toList());
+    }
+
+    String tmpDirName() {
+        return "tmp" + Thread.currentThread().getId();
+    }
+
+    String typeVarName(String typeVarDecl) {
+        String[] ss = typeVarDecl.split(" ");
+        return ss[0].equals("any") ?
+                ss[1] : ss[0];
+    }
+
+    /**
+     * Returns a runtime mirror for a given string representing a valid Java type.
+     * An optional list of type-variable declarations can be provided; such variables can be used freely
+     * in the given type string.
+     */
+    @SuppressWarnings("unchecked")
+    public final <R extends RuntimeMirror> R getMirror(String type) {
+        return (R)mirror_cache.computeIfAbsent(type, _unused -> MirrorUtils.typeToMirror(getType(type)));
+    }
+
+    private final Type getType(String type) {
+        File tmp = new File(tmpDirName());
+        tmp.mkdir();
+        try {
+            JavaSource source = new JavaSource(type);
+            List<JavaFileObject> inputs = List.of(source);
+            boolean res = comp.getTask(null, jfm.get(), null, Arrays.asList("-d", tmp.getAbsolutePath()), null, inputs).call();
+            if (!res) {
+                throw new IllegalStateException("Compilation error: " + source.getCharContent(false));
+            }
+            try {
+                URLClassLoader cl = new URLClassLoader(new URL[] {new File(tmpDirName()).toURI().toURL() },
+                        this.getClass().getClassLoader());
+                Class<?> c = cl.loadClass((pkg != null ? pkg + "." : "") + "G" + source.id);
+                for (int retryCount = 0 ; ; retryCount++) {
+                    try {
+                        Type t = c.getDeclaredField("var").getGenericType();
+                        if (typeVariables != null) {
+                            t = subst(List.of(t), List.of(c.getTypeParameters()), typeVariables).get(0);
+                        }
+                        return t;
+                    } catch (ReflectiveOperationException ex) {
+                        throw new IllegalStateException(ex);
+                    } catch (Throwable ex) {
+                        //try again (workaround thread-safety issues in Model3Converter)
+                        if (retryCount == MAX_RETRY_COUNT) {
+                            throw new IllegalStateException(ex);
+                        }
+                    }
+                }
+            } catch (Throwable ex) {
+                throw new IllegalStateException(ex);
+            }
+        } finally {
+            try {
+                removeDir(tmp);
+            } catch (IOException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+    }
+
+    class JavaSource extends SimpleJavaFileObject {
+
+        String id;
+        String type;
+        String template = "#Package;\n" +
+                "#Imports\n" +
+                "class G#Id#TypeVars {\n" +
+                "   #FieldType var;" +
+                "}";
+
+        JavaSource(String type) {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            this.id = String.valueOf(MirrorBuilder.this.id.incrementAndGet());
+            this.type = type;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            String impStmts = imports.size() > 0 ?
+                    imports.stream().map(i -> "import " + i + ";").collect(Collectors.joining("\n")) : "";
+            String tvars = typeVarDecls.size() > 0 ?
+                    typeVarDecls.stream().collect(Collectors.joining(",", "<", ">")) : "";
+            return template
+                    .replace("#Package", (pkg == null) ? "" : "package " + pkg + ";")
+                    .replace("#Imports", impStmts)
+                    .replace("#Id", id)
+                    .replace("#TypeVars", tvars)
+                    .replace("#FieldType", type);
+        }
+    }
+
+    private static void removeDir(File f) throws IOException {
+        Files.walkFileTree(f.toPath(), new SimpleFileVisitor<>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                Files.delete(dir);
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    List<Type> subst(List<Type> ts, List<Type> from, List<Type> to) {
+        return substInternal(ts, IntStream.range(0, from.size())
+            .mapToObj(i -> i) //box
+            .collect(Collectors.toMap(i -> from.get(i), i -> to.get(i))));
+    }
+
+    List<Type> substInternal(List<Type> ts, Map<Type, Type> substMap) {
+        return ts.stream()
+                .map(t -> substInternal(t, substMap))
+                .collect(Collectors.toList());
+    }
+
+    Type substInternal(Type t, Map<Type, Type> substMap) {
+        Type subst = substMap.get(t);
+        if (subst != null) {
+            return subst;
+        } else if (t instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) t;
+            List<Type> prevArgs = List.of(pt.getActualTypeArguments());
+            List<Type> substArgs = substInternal(prevArgs, substMap);
+            if (prevArgs.equals(substArgs)) {
+                return pt;
+            } else {
+                Type owner = pt.getOwnerType();
+                Type raw = pt.getRawType();
+                return new ParameterizedType() {
+                    @Override
+                    public Type[] getActualTypeArguments() {
+                        return substArgs.stream().toArray(Type[]::new);
+                    }
+
+                    @Override
+                    public Type getRawType() {
+                        return raw;
+                    }
+
+                    @Override
+                    public Type getOwnerType() {
+                        return owner;
+                    }
+                };
+            }
+        } else if (t instanceof WildcardType) {
+            WildcardType wt = (WildcardType) t;
+            List<Type> prevLower = List.of(wt.getLowerBounds());
+            List<Type> prevUpper = List.of(wt.getUpperBounds());
+            List<Type> substLower = substInternal(prevLower, substMap);
+            List<Type> substUpper = substInternal(prevUpper, substMap);
+            if (prevLower.equals(substLower) && prevUpper.equals(substUpper)) {
+                return wt;
+            } else {
+                return new WildcardType() {
+                    @Override
+                    public Type[] getUpperBounds() {
+                        return substUpper.stream().toArray(Type[]::new);
+                    }
+
+                    @Override
+                    public Type[] getLowerBounds() {
+                        return substLower.stream().toArray(Type[]::new);
+                    }
+                };
+            }
+        } else if (t instanceof GenericArrayType) {
+            GenericArrayType gt = (GenericArrayType) t;
+            Type prevElem = gt.getGenericComponentType();
+            Type substElem = substInternal(prevElem, substMap);
+            if (prevElem.equals(substElem)) {
+                return gt;
+            } else {
+                return new GenericArrayType() {
+                    @Override
+                    public Type getGenericComponentType() {
+                        return substElem;
+                    }
+                };
+            }
+        } else {
+            return t;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        MirrorBuilder tb = new MirrorBuilder(null, List.of("valhalla.reflect.runtime.MirrorBuilder.*"), List.of("any A", "R"));
+        RuntimeMirror m1 = tb.getMirror("Foo2<A, ? super A>[]");
+        RuntimeMirror m2 = tb.getMirror("Foo2<? super A, A>[]");
+        System.err.println(m1.equals(m2));
+    }
+
+    public static class Foo2<any X, any Y> { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/SimpleReflectionTest.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,107 @@
+package valhalla.reflect.runtime;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Test
+public class SimpleReflectionTest extends TestBase {
+
+    public static class Sup<any X, any Y> { }
+
+    public static class Foo<any X> extends Sup<X, int> {
+        public X[] doSomething(X x) {
+            System.out.println("Hello!");
+            return null;
+        }
+
+        <any Z> Z[] doGeneric(Z z, X x) {
+            System.out.println("Hello generic!");
+            return null;
+        }
+    }
+
+    final MirrorFactory factory = MirrorFactory.instance();
+    final RuntimeMirror Object_mirror = factory.classMirror(Object.class);
+    final RuntimeMirror int_mirror = factory.primitiveMirror(int.class);
+    final RuntimeMirror float_mirror = factory.primitiveMirror(float.class);
+
+    public void test() throws Throwable {
+        Class.forName("valhalla.reflect.runtime.SimpleReflectionTest$Foo");
+        ClassMirror foo_x = factory.classMirror(Foo.class);
+        Assert.assertEquals(foo_x.getTypeString(), "valhalla.reflect.runtime.SimpleReflectionTest$Foo<X>");
+        ClassMirror sup_int_X = foo_x.getSupertypes().get(0);
+        Assert.assertEquals(sup_int_X.getTypeString(), "valhalla.reflect.runtime.SimpleReflectionTest$Sup<X,int>");
+        Assert.assertNotEquals(foo_x, sup_int_X);
+        Assert.assertTrue(foo_x.isSubtypeOf(sup_int_X));
+        Assert.assertTrue(((TypeVariableMirror<?>)foo_x.getTypeArguments().get(0)).getOwner() == foo_x);
+        assertThrown(IllegalStateException.class, foo_x::reflect);
+        ClassMirror foo_erased = foo_x.asSpecializedMirror(factory.erasedMirror());
+        Assert.assertEquals(foo_erased.getTypeString(), "valhalla.reflect.runtime.SimpleReflectionTest$Foo<_>");
+        ClassMirror sup_erased_int = foo_erased.getSupertypes().get(0);
+        Assert.assertEquals(sup_erased_int.getTypeString(), "valhalla.reflect.runtime.SimpleReflectionTest$Sup<_,int>");
+        Assert.assertNotEquals(foo_erased, sup_erased_int);
+        Assert.assertTrue(foo_erased.isSubtypeOf(sup_erased_int));
+        Assert.assertNotEquals(foo_erased, equals(sup_int_X));
+        Assert.assertFalse(foo_erased.isSubtypeOf(sup_int_X));
+        foo_erased.reflect();
+        ClassMirror foo_int = foo_x.asSpecializedMirror(int_mirror);
+        Assert.assertEquals(foo_int.getTypeString(), "valhalla.reflect.runtime.SimpleReflectionTest$Foo<int>");
+        ClassMirror sup_int_int = foo_int.getSupertypes().get(0);
+        Assert.assertEquals(sup_int_int.getTypeString(), "valhalla.reflect.runtime.SimpleReflectionTest$Sup<int,int>");
+        Assert.assertNotEquals(foo_int, equals(sup_int_int));
+        Assert.assertTrue(foo_int.isSubtypeOf(sup_int_int));
+        Assert.assertNotEquals(foo_int, equals(sup_int_X));
+        Assert.assertFalse(foo_int.isSubtypeOf(sup_int_X));
+        foo_int.reflect();
+        MethodMirror foo_x_doSomething = foo_x.methodLookup()
+                .withName("doSomething")
+                .withParameterTypes(foo_x.getTypeArguments().get(0)).findOrFail();
+        Assert.assertEquals(sig(foo_x_doSomething), "(X)X[]");
+        assertThrown(IllegalStateException.class, foo_x_doSomething::reflect);
+        assertThrown(IllegalStateException.class, foo_x_doSomething::asHandle);
+        Foo<String> f_string = new Foo<String>();
+        MethodMirror foo_erased_doSomething = foo_erased.methodLookup()
+                .withName("doSomething")
+                .withParameterTypes(Object_mirror).findOrFail();
+        Assert.assertEquals(sig(foo_erased_doSomething), "(java.lang.Object)java.lang.Object[]");
+        foo_erased_doSomething.reflect().invoke(f_string, "Hello!"); //classic reflective call
+        foo_erased_doSomething.asHandle().invoke(f_string, "Hello!"); //method handle-backed reflective call
+        Foo<int> fi = new Foo<int>();
+        MethodMirror foo_int_doSomething = foo_int.methodLookup()
+                .withName("doSomething")
+                .withParameterTypes(int_mirror).findOrFail();
+        Assert.assertEquals(sig(foo_int_doSomething), "(int)int[]");
+        foo_int_doSomething.reflect().invoke(fi, 42); //classic reflective call
+        foo_int_doSomething.asHandle().invoke(fi, 42); //method handle-backed reflective call
+        MethodMirror foo_x_doGeneric_z = foo_x.methodLookup()
+                .withName("doGeneric")
+                .withParameterTypes(tvs -> Optional.of(Arrays.asList(tvs.get(0), foo_x.getTypeArguments().get(0)))).findOrFail();
+        Assert.assertTrue(((TypeVariableMirror<?>)foo_x_doGeneric_z.getTypeArguments().get(0)).getOwner() == foo_x_doGeneric_z);
+        MethodMirror foo_int_doGeneric_z = foo_int.methodLookup()
+                .withName("doGeneric")
+                .withParameterTypes(tvs -> Optional.of(Arrays.asList(tvs.get(0), int_mirror))).findOrFail();
+        Assert.assertEquals(sig(foo_int_doGeneric_z), "<Z>(Z,int)Z[]");
+        assertThrown(IllegalStateException.class, foo_int_doGeneric_z::reflect);
+        assertThrown(IllegalStateException.class, foo_int_doGeneric_z::asHandle);
+        MethodMirror foo_int_doGeneric_float = foo_int_doGeneric_z.asSpecializedMirror(float_mirror);
+        Assert.assertEquals(sig(foo_int_doGeneric_float), "<float>(float,int)float[]");
+        //m_g_int_float.reflect().invoke(fi, 1f, 42); //classic reflective call - blows up!
+        foo_int_doGeneric_float.asHandle().invoke(fi, 1f, 42); //method handle-backed reflective call
+    }
+
+    static String sig(MethodMirror mm) {
+        String sig = mm.getParameterTypes().stream()
+                .map(RuntimeMirror::getTypeString)
+                .collect(Collectors.joining(",", "(", ")")) + mm.getReturnType().getTypeString();
+        if (mm.getTypeArguments().size() > 0) {
+            sig = mm.getTypeArguments().stream()
+                    .map(RuntimeMirror::getTypeString)
+                    .collect(Collectors.joining(",", "<", ">")) + sig;
+        }
+        return sig;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/TestBase.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,215 @@
+package valhalla.reflect.runtime;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class TestBase {
+
+    MirrorBuilder B = new MirrorBuilder("valhalla.reflect.runtime",
+            List.of("valhalla.reflect.runtime." + getClass().getSimpleName() + ".*"),
+            List.of("any A", "R"));
+
+    static <X extends Throwable> void assertThrown(Class<X> ex, ThrowableAction action) {
+        try {
+            action.doSomething();
+        } catch (Throwable ex2) {
+            Assert.assertEquals(ex2.getClass(), ex);
+        }
+    }
+
+    interface ThrowableAction {
+        void doSomething() throws Throwable;
+    }
+
+    @DataProvider(name = "typeArgs", parallel = true)
+    public static Object[][] typeArgs(Method m) {
+        int arity = m.getParameterCount();
+        return typeArgsCache.computeIfAbsent(arity, _unused -> {
+            List<Object[]> res = new ArrayList<>();
+            TypeArgument[] typeargs = typeArgs();
+            Object[][] universe = new Object[arity][typeargs.length];
+            Arrays.fill(universe, typeargs);
+            initCombos(0, new Stack<>(), res, universe);
+            return res.stream().toArray(Object[][]::new);
+        });
+    }
+
+    static TypeArgument[] typeArgs() {
+        List<TypeArgument> res = new ArrayList<>();
+        for (WildcardKind wk : WildcardKind.values()) {
+            for (TypeArgumentKind tak : TypeArgumentKind.values()) {
+                if ((tak.primitive && wk != WildcardKind.NONE)) continue;
+                for (ArrayKind ak : ArrayKind.values()) {
+                    if (!tak.isSingleSlot() && ak == ArrayKind.NONE) continue;
+                    res.add(new TypeArgument(wk, tak, ak));
+                }
+            }
+        }
+        return res.stream().toArray(TypeArgument[]::new);
+    }
+
+    @DataProvider(name = "basicTypes", parallel = true)
+    public static Object[][] basicTypes(Method m) {
+        int arity = m.getParameterCount();
+        return basicTypesCache.computeIfAbsent(arity, _unused -> {
+            List<Object[]> res = new ArrayList<>();
+            BasicType[] btypes = basicTypes();
+            Object[][] universe = new Object[arity][btypes.length];
+            Arrays.fill(universe, btypes);
+            initCombos(0, new Stack<>(), res, universe);
+            return res.stream().toArray(Object[][]::new);
+        });
+    }
+
+    static BasicType[] basicTypes() {
+        BasicType[] res = new BasicType[TypeArgumentKind.values().length * ArrayKind.values().length];
+        int i = 0;
+        for (TypeArgumentKind tak : TypeArgumentKind.values()) {
+            for (ArrayKind ak : ArrayKind.values()) {
+                res[i++] = new BasicType(tak, ak);
+            }
+        }
+        return res;
+    }
+
+    protected static void initCombos(int index, Stack<Object> bindings, List<Object[]> acc, Object[]... universe) {
+        if (index == universe.length) {
+            acc.add(bindings.stream().toArray());
+        } else {
+            for (Object z : universe[index]) {
+                bindings.push(z);
+                initCombos(index + 1, bindings, acc, universe);
+                bindings.pop();
+            }
+        }
+    }
+
+    static Map<Integer, Object[][]> basicTypesCache = new ConcurrentHashMap<>();
+    static Map<Integer, Object[][]> typeArgsCache = new ConcurrentHashMap<>();
+
+    enum TypeArgumentKind {
+        STRING("java.lang.String", false, false),
+        BYTE("byte", true, true),
+        SHORT("short", true, true),
+        INT("int", true, true),
+        FLOAT("float", true, true),
+        LONG("long", true, true),
+        DOUBLE("double", true, true),
+        CHAR("char", true, true),
+        BOOL("boolean", true, true),
+        REF_VAR("R", false, false),
+        ANY_VAR("A", true, false);
+
+        String typeArg;
+        boolean reified;
+        boolean primitive;
+
+        TypeArgumentKind(String typeArg, boolean reified, boolean primitive) {
+            this.typeArg = typeArg;
+            this.reified = reified;
+            this.primitive = primitive;
+        }
+
+        boolean isSingleSlot() {
+            return this != LONG && this != DOUBLE;
+        }
+    }
+
+    enum WildcardKind {
+        NONE(""),
+        EXTENDS("? extends "),
+        SUPER("? super ");
+
+        String wildStr;
+
+        WildcardKind(String wildStr) {
+            this.wildStr = wildStr;
+        }
+    }
+
+    enum ArrayKind {
+        NONE(""),
+        SINGLE("[]"),
+        DOUBLE("[][]");
+
+        String arrStr;
+
+        ArrayKind(String arrStr) {
+            this.arrStr = arrStr;
+        }
+    }
+
+    static class TypeArgument {
+        WildcardKind wk;
+        TypeArgumentKind tak;
+        ArrayKind ak;
+
+        private final static String typeArgTemplate = "#W#T#A";
+
+        TypeArgument(WildcardKind wk, TypeArgumentKind tak, ArrayKind ak) {
+            this.wk = wk;
+            this.tak = tak;
+            this.ak = ak;
+        }
+
+        String typeArgString() {
+            return typeArgTemplate
+                    .replace("#W", wk.wildStr)
+                    .replace("#T", tak.typeArg)
+                    .replace("#A", ak.arrStr);
+        }
+
+        String erasure() {
+            return (tak.reified && ak == ArrayKind.NONE) ?
+                tak.typeArg : "_";
+        }
+
+        @Override
+        public String toString() {
+            return typeArgString();
+        }
+    }
+
+    static class BasicType {
+
+        TypeArgumentKind tak;
+        ArrayKind ak;
+
+        private final static String basicTypeTemplate = "#T#A";
+
+        BasicType(TypeArgumentKind tak, ArrayKind ak) {
+            this.tak = tak;
+            this.ak = ak;
+        }
+
+        String typeString() {
+            return basicTypeTemplate
+                    .replace("#T", tak.typeArg)
+                    .replace("#A", ak.arrStr);
+        }
+
+        String erasure() {
+            return tak == TypeArgumentKind.REF_VAR ?
+                    "java.lang.Object" + ak.arrStr :
+                    typeString();
+        }
+
+        @Override
+        public String toString() {
+            return typeString();
+        }
+
+        boolean isSingleSlot() {
+            return ak != ArrayKind.NONE ||
+                    tak.isSingleSlot();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/TestFactory.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,66 @@
+package valhalla.reflect.runtime;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class TestFactory extends TestBase {
+
+    static class Foo<any X> {
+        class Inner<any Y> { }
+    }
+
+    static class Foo2<any X, any Y> {
+        class Inner2<any U, any W> { }
+    }
+
+    public void testTemplate() {
+        assertTypeEquals("Foo", "valhalla.reflect.runtime.TestFactory$Foo<X>");
+        assertTypeEquals("Foo.Inner", "valhalla.reflect.runtime.TestFactory$Foo<X>.Inner<Y>");
+        assertTypeEquals("Foo[]", "valhalla.reflect.runtime.TestFactory$Foo<X>[]");
+        assertTypeEquals("Foo.Inner[]", "valhalla.reflect.runtime.TestFactory$Foo<X>.Inner<Y>[]");
+        assertTypeEquals("Foo2", "valhalla.reflect.runtime.TestFactory$Foo2<X,Y>");
+        assertTypeEquals("Foo2.Inner2", "valhalla.reflect.runtime.TestFactory$Foo2<X,Y>.Inner2<U,W>");
+        assertTypeEquals("Foo2[]", "valhalla.reflect.runtime.TestFactory$Foo2<X,Y>[]");
+        assertTypeEquals("Foo2.Inner2[]", "valhalla.reflect.runtime.TestFactory$Foo2<X,Y>.Inner2<U,W>[]");
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterized(TypeArgument ta) {
+        assertTypeEquals(String.format("Foo<%s>", ta.typeArgString()),
+                         String.format("valhalla.reflect.runtime.TestFactory$Foo<%s>", ta.erasure()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedInner(TypeArgument ta1, TypeArgument ta2) {
+        assertTypeEquals(String.format("Foo<%s>.Inner<%s>", ta1.typeArgString(), ta2.typeArgString()),
+                         String.format("valhalla.reflect.runtime.TestFactory$Foo<%s>.Inner<%s>", ta1.erasure(), ta2.erasure()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedArray(TypeArgument ta) {
+        assertTypeEquals(String.format("Foo<%s>[]", ta.typeArgString()),
+                         String.format("valhalla.reflect.runtime.TestFactory$Foo<%s>[]", ta.erasure()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedInnerArray(TypeArgument ta1, TypeArgument ta2) {
+        assertTypeEquals(String.format("Foo<%s>.Inner<%s>[]", ta1.typeArgString(), ta2.typeArgString()),
+                         String.format("valhalla.reflect.runtime.TestFactory$Foo<%s>.Inner<%s>[]", ta1.erasure(), ta2.erasure()));
+    }
+
+    @Test(dataProvider = "basicTypes")
+    public void testBasic(BasicType t) {
+        assertTypeEquals(t.typeString(), t.erasure());
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterized2(TypeArgument ta1, TypeArgument ta2) {
+        assertTypeEquals(String.format("Foo2<%s,%s>", ta1.typeArgString(), ta2.typeArgString()),
+                         String.format("valhalla.reflect.runtime.TestFactory$Foo2<%s,%s>", ta1.erasure(), ta2.erasure()));
+    }
+
+    void assertTypeEquals(String typeStr, String expected) {
+        Assert.assertEquals(B.getMirror(typeStr).getTypeString(), expected);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/TestLookup.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,210 @@
+package valhalla.reflect.runtime;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import valhalla.reflect.runtime.MemberLookup.InheritanceMode;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Stack;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+@Test
+public class TestLookup extends TestBase {
+
+    static class Sup<any X> {
+        X m;
+        X m(X x) { return x; }
+        <any Z> Z m(Z z, X x) { return z; }
+    }
+
+    static class Foo<any X> extends Sup<X> {
+        Foo(X x) { }
+    }
+
+    @Test(dataProvider = "namedLookup")
+    public void testFieldLookup(StaticKind staticKind, AccessKind accessKind, NameKind nameKind,
+                                InheritanceMode inheritanceMode, BasicType typeArg, BasicType fieldType) {
+        lookupHelper(staticKind, accessKind, nameKind, inheritanceMode, typeArg, fieldType,
+                ClassMirror::fieldLookup,
+                (l, fieldTypeMirror) -> l.withName(nameKind.name)
+                        .withInheritanceMode(inheritanceMode)
+                        .withType(fieldTypeMirror),
+                (f, fieldTypeMirror) -> {
+                    Assert.assertEquals(f.getType(), fieldTypeMirror);
+                    Assert.assertEquals(f.getName(), nameKind.name);
+                });
+    }
+
+    @Test(dataProvider = "namedLookup")
+    public void testMethodLookupByParam(StaticKind staticKind, AccessKind accessKind, NameKind nameKind,
+                                        InheritanceMode inheritanceMode, BasicType typeArg, BasicType paramType) {
+        lookupHelper(staticKind, accessKind, nameKind, inheritanceMode, typeArg, paramType,
+                ClassMirror::methodLookup,
+                (l, paramTypeMirror) -> l.withName(nameKind.name)
+                        .withInheritanceKind(inheritanceMode)
+                        .withParameterTypes(paramTypeMirror),
+                (m, paramTypeMirror) -> {
+                    Assert.assertEquals(m.getReturnType(), paramTypeMirror);
+                    Assert.assertEquals(m.getParameterTypes().size(), 1);
+                    Assert.assertEquals(m.getParameterTypes().get(0), paramTypeMirror);
+                    Assert.assertEquals(m.getName(), nameKind.name);
+                });
+    }
+
+    @Test(dataProvider = "namedLookup")
+    public void testMethodLookupByReturn(StaticKind staticKind, AccessKind accessKind, NameKind nameKind,
+                                         InheritanceMode inheritanceMode, BasicType typeArg, BasicType paramType) {
+        lookupHelper(staticKind, accessKind, nameKind, inheritanceMode, typeArg, paramType,
+                ClassMirror::methodLookup,
+                (l, retTypeMirror) -> l.withName(nameKind.name)
+                        .withInheritanceKind(inheritanceMode)
+                        .withReturnType(retTypeMirror),
+                (m, retTypeMirror) -> {
+                    Assert.assertEquals(m.getReturnType(), retTypeMirror);
+                    Assert.assertEquals(m.getParameterTypes().size(), 1);
+                    Assert.assertEquals(m.getParameterTypes().get(0), retTypeMirror);
+                    Assert.assertEquals(m.getName(), nameKind.name);
+                });
+    }
+
+    @Test(dataProvider = "unnamedLookup")
+    public void testConstructorLookup(StaticKind staticKind, AccessKind accessKind, BasicType typeArg, BasicType paramType) {
+        lookupHelper(staticKind, accessKind, null, null, typeArg, paramType,
+                ClassMirror::constructorLookup,
+                (l, paramTypeMirror) -> l.withParameterTypes(paramTypeMirror),
+                (c, paramTypeMirror) -> {
+                    Assert.assertEquals(c.getParameterTypes().size(), 1);
+                    Assert.assertEquals(c.getParameterTypes().get(0), paramTypeMirror);
+                    Assert.assertEquals(c.getName(), "<init>");
+                });
+    }
+
+    @Test(dataProvider = "namedLookup")
+    public void testGenericMethodLookupByParam(StaticKind staticKind, AccessKind accessKind, NameKind nameKind,
+                                        InheritanceMode inheritanceMode, BasicType typeArg, BasicType paramType) {
+        lookupHelper(staticKind, accessKind, nameKind, inheritanceMode, typeArg, paramType,
+                ClassMirror::methodLookup,
+                (l, paramTypeMirror) -> l.withName(nameKind.name)
+                        .withInheritanceKind(inheritanceMode)
+                        .withParameterTypes(tvars -> (tvars.size() == 1) ?
+                                Optional.of(List.of(tvars.get(0), paramTypeMirror)) : Optional.empty()),
+                (m, paramTypeMirror) -> {
+                    Assert.assertEquals(m.getReturnType(), m.getTypeArguments().get(0));
+                    Assert.assertEquals(m.getParameterTypes().size(), 2);
+                    Assert.assertEquals(m.getParameterTypes(), List.of(m.getTypeArguments().get(0), paramTypeMirror));
+                    Assert.assertEquals(m.getName(), nameKind.name);
+                });
+    }
+
+    @Test(dataProvider = "namedLookup")
+    public void testGenericMethodLookupByReturn(StaticKind staticKind, AccessKind accessKind, NameKind nameKind,
+                                         InheritanceMode inheritanceMode, BasicType typeArg, BasicType paramType) {
+        lookupHelper(staticKind, accessKind, nameKind, inheritanceMode, typeArg, paramType,
+                ClassMirror::methodLookup,
+                (l, retTypeMirror) -> l.withName(nameKind.name)
+                        .withInheritanceKind(inheritanceMode)
+                        .withReturnType(tvars -> (tvars.size() == 1) ?
+                                Optional.of(tvars.get(0)) : Optional.empty()),
+                (m, retTypeMirror) -> {
+                    Assert.assertEquals(m.getReturnType(), m.getTypeArguments().get(0));
+                    Assert.assertEquals(m.getParameterTypes().size(), 2);
+                    Assert.assertEquals(m.getParameterTypes(), List.of(m.getTypeArguments().get(0), retTypeMirror));
+                    Assert.assertEquals(m.getName(), nameKind.name);
+                });
+    }
+
+    @SuppressWarnings("unchecked")
+    private <M extends MemberMirror,
+             L extends MemberLookup<M>> void lookupHelper(StaticKind staticKind, AccessKind accessKind, NameKind nameKindOpt,
+                                                          InheritanceMode inheritanceModeOpt, BasicType typeArg, BasicType lookupType,
+                                                          Function<ClassMirror, L> lookupFunc, BiConsumer<L, RuntimeMirror> lookupInit,
+                                                          BiConsumer<M, RuntimeMirror> lookupValidation) {
+        ClassMirror mirror = B.getMirror("Foo<" + typeArg.typeString() + ">");
+        RuntimeMirror lookupTypeMirror = B.getMirror(lookupType.typeString());
+        L lookup = lookupFunc.apply(mirror);
+        lookupInit.accept(lookup, lookupTypeMirror);
+        if (staticKind != StaticKind.NON_STATIC) {
+            lookup = (L)lookup.withFlags(staticKind.mods);
+        }
+        if (accessKind != AccessKind.PACKAGE) {
+            lookup = (L)lookup.withFlags(accessKind.mods);
+        }
+        L lookup2 = lookup;
+        if (staticKind == StaticKind.NON_STATIC && accessKind == AccessKind.PACKAGE &&
+                (nameKindOpt == null || nameKindOpt == NameKind.M) &&
+                (inheritanceModeOpt == null || inheritanceModeOpt == InheritanceMode.INHERITED) &&
+                mirror.getTypeArguments().get(0).equals(lookupTypeMirror)) {
+            M mmirror = lookup.findOrFail();
+            lookupValidation.accept(mmirror, lookupTypeMirror);
+        } else {
+            assertThrown(NoSuchElementException.class, () -> lookup2.findOrFail());
+        }
+    }
+
+    enum StaticKind {
+        STATIC(Modifier.STATIC),
+        NON_STATIC(0);
+
+        int mods;
+
+        StaticKind(int mods) {
+            this.mods = mods;
+        }
+    }
+
+    enum AccessKind {
+        PUBLIC(Modifier.PUBLIC),
+        PACKAGE(0);
+
+        int mods;
+
+        AccessKind(int mods) {
+            this.mods = mods;
+        }
+    }
+
+    enum NameKind {
+        M("m"),
+        G("g");
+
+        String name;
+
+        NameKind(String name) {
+            this.name = name;
+        }
+    }
+
+    @DataProvider(name = "namedLookup", parallel = true)
+    public static Object[][] namedLookup() {
+        if (namedLookup == null) {
+            List<Object[]> res = new ArrayList<>();
+            //we need to filter out double slot specializations which are not supported
+            initCombos(0, new Stack<>(), res, StaticKind.values(), AccessKind.values(), NameKind.values(),
+                    InheritanceMode.values(), Stream.of(basicTypes()).filter(BasicType::isSingleSlot).toArray(), basicTypes());
+            namedLookup = res.stream().toArray(Object[][]::new);
+        }
+        return namedLookup;
+    }
+
+    @DataProvider(name = "unnamedLookup", parallel = true)
+    public static Object[][] unnamedLookup() {
+        if (unnamedLookup == null) {
+            List<Object[]> res = new ArrayList<>();
+            //we need to filter out double slot specializations which are not supported
+            initCombos(0, new Stack<>(), res, StaticKind.values(), AccessKind.values(),
+                    Stream.of(basicTypes()).filter(BasicType::isSingleSlot).toArray(), basicTypes());
+            unnamedLookup = res.stream().toArray(Object[][]::new);
+        }
+        return unnamedLookup;
+    }
+
+    private static Object[][] namedLookup;
+    private static Object[][] unnamedLookup;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/TestSubtypeOf.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,103 @@
+package valhalla.reflect.runtime;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import valhalla.reflect.runtime.RuntimeMirror.Kind;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Test
+public class TestSubtypeOf extends TestBase {
+
+    static class Sup<any X> { }
+    static class Sup2<any X, any Y> { }
+
+    static class Foo<any X> extends Sup<X> { }
+    static class Foo2<any X, any Y> { }
+
+    public void testTemplate() {
+        assertSubtypeOf("Foo", "Foo");
+        assertSubtypeOf("Foo[]", "Foo[]");
+        assertSubtypeOf("Foo2", "Foo2");
+        assertSubtypeOf("Foo2[]", "Foo2[]");
+    }
+
+    @Test(dataProvider = "basicTypes")
+    public void testBasic(BasicType t1, BasicType t2) {
+        assertSubtypeOf(t1.typeString(), t2.typeString());
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterized(TypeArgument ta1, TypeArgument ta2) {
+        assertSubtypeOf(String.format("Foo<%s>", ta1.typeArgString()),
+                         String.format("Foo<%s>", ta2.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedArray(TypeArgument ta1, TypeArgument ta2) {
+        assertSubtypeOf(String.format("Foo<%s>[]", ta1.typeArgString()),
+                         String.format("Foo<%s>[]", ta2.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedSup(TypeArgument ta1, TypeArgument ta2) {
+        assertSubtypeOf(String.format("Foo<%s>", ta1.typeArgString()),
+                         String.format("Sup<%s>", ta2.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedSupArray(TypeArgument ta1, TypeArgument ta2) {
+        assertSubtypeOf(String.format("Foo<%s>[]", ta1.typeArgString()),
+                         String.format("Sup<%s>[]", ta2.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterized2(TypeArgument ta1, TypeArgument ta2) {
+        assertSubtypeOf(String.format("Foo2<%s,%s>[]", ta1.typeArgString(), ta2.typeArgString()),
+                         String.format("Foo2<%s,%s>[]", ta2.typeArgString(), ta1.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedSup2(TypeArgument ta1, TypeArgument ta2) {
+        assertSubtypeOf(String.format("Foo2<%s,%s>[]", ta1.typeArgString(), ta2.typeArgString()),
+                         String.format("Sup2<%s,%s>[]", ta2.typeArgString(), ta1.typeArgString()));
+    }
+
+    void assertSubtypeOf(String S, String T) {
+        RuntimeMirror Sm = B.getMirror(S);
+        RuntimeMirror Tm = B.getMirror(T);
+        Assert.assertEquals(Sm.isSubtypeOf(Tm),
+                supertypeClosure(Sm).contains(Tm));
+    }
+
+    private Map<RuntimeMirror, Set<RuntimeMirror>> invClosureMap = new ConcurrentHashMap<>();
+
+    Set<RuntimeMirror> supertypeClosure(RuntimeMirror mirror) {
+        return invClosureMap.computeIfAbsent(mirror, this::doClosure);
+    }
+
+    Set<RuntimeMirror> doClosure(RuntimeMirror mirror) {
+        Set<RuntimeMirror> cl = new HashSet<>();
+        doClosure(mirror, cl);
+        return cl;
+    }
+
+    void doClosure(RuntimeMirror mirror, Set<RuntimeMirror> cl) {
+        if (cl.add(mirror)) {
+            if (mirror.getKind() == Kind.CLASS) {
+                ((ClassMirror)mirror).getSupertypes().forEach(sup -> doClosure(sup, cl));
+            } else if (mirror.getKind() == Kind.ARRAY) {
+                ArrayMirror arr = (ArrayMirror)mirror;
+                //avoid recurring on the concurrent map!
+                Set<RuntimeMirror> elemClosure = doClosure(arr.getComponentType());
+                elemClosure.stream()
+                        .map(m -> MirrorFactory.instance().arrayMirror(m))
+                        .forEach(cl::add);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/valhalla/test/valhalla/reflect/runtime/TestTypeEquals.java	Wed Jun 15 18:07:49 2016 +0100
@@ -0,0 +1,53 @@
+package valhalla.reflect.runtime;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+@Test
+public class TestTypeEquals extends TestBase {
+
+    static class Foo<any X> { }
+    static class Foo2<any X, any Y> { }
+
+    public void testTemplate() {
+        assertTypeEquals("Foo", "Foo");
+        assertTypeEquals("Foo[]", "Foo[]");
+        assertTypeEquals("Foo2", "Foo2");
+        assertTypeEquals("Foo2[]", "Foo2[]");
+    }
+
+    @Test(dataProvider = "basicTypes")
+    public void testBasic(BasicType t1, BasicType t2) {
+        assertTypeEquals(t1.typeString(), t2.typeString());
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterized(TypeArgument ta1, TypeArgument ta2) {
+        assertTypeEquals(String.format("Foo<%s>", ta1.typeArgString()),
+                         String.format("Foo<%s>", ta2.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterizedArray(TypeArgument ta1, TypeArgument ta2) {
+        assertTypeEquals(String.format("Foo<%s>[]", ta1.typeArgString()),
+                         String.format("Foo<%s>[]", ta2.typeArgString()));
+    }
+
+    @Test(dataProvider = "typeArgs")
+    public void testParameterized2(TypeArgument ta1, TypeArgument ta2) {
+        assertTypeEquals(String.format("Foo2<%s,%s>[]", ta1.typeArgString(), ta2.typeArgString()),
+                         String.format("Foo2<%s,%s>[]", ta2.typeArgString(), ta1.typeArgString()));
+    }
+
+    void assertTypeEquals(String S, String T) {
+        RuntimeMirror Sm = B.getMirror(S);
+        RuntimeMirror Tm = B.getMirror(T);
+        if (Sm.getTypeString().equals(Tm.getTypeString())) {
+            Assert.assertEquals(Sm, Tm);
+        } else {
+            Assert.assertNotEquals(Sm, Tm);
+        }
+    }
+}