changeset 3505:f18dc3fd0496

Enhancement: add M3 generic pool entries harness Fix: build script is not building jshell correctly Fix: alt generic method translation fails to rewrite all typevars Fix: limit generation of redundant generic pool entries in M3 translation
author mcimadamore
date Fri, 15 Apr 2016 17:24:24 +0100
parents 3197e9b4d80a
children 961eb443422f
files make/build.properties make/build.xml src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java test/tools/javac/valhalla/typespec/items/m3/Opcodes.java test/tools/javac/valhalla/typespec/items/m3/PoolMapping.java test/tools/javac/valhalla/typespec/items/m3/PoolMappingHarness.java test/tools/javac/valhalla/typespec/items/m3/TemplateMethod.java test/tools/javac/valhalla/typespec/items/m3/tests/TestAnyMembers.java test/tools/javac/valhalla/typespec/items/m3/tests/TestArrayLoadAndStore.java test/tools/javac/valhalla/typespec/items/m3/tests/TestBinary.java test/tools/javac/valhalla/typespec/items/m3/tests/TestCapture.java test/tools/javac/valhalla/typespec/items/m3/tests/TestCast.java test/tools/javac/valhalla/typespec/items/m3/tests/TestClassLit.java test/tools/javac/valhalla/typespec/items/m3/tests/TestCmp.java test/tools/javac/valhalla/typespec/items/m3/tests/TestDefault.java test/tools/javac/valhalla/typespec/items/m3/tests/TestDup.java test/tools/javac/valhalla/typespec/items/m3/tests/TestForeach.java test/tools/javac/valhalla/typespec/items/m3/tests/TestGeneric2GenericCall.java test/tools/javac/valhalla/typespec/items/m3/tests/TestGenericSpecializedConstructor.java test/tools/javac/valhalla/typespec/items/m3/tests/TestIndy.java test/tools/javac/valhalla/typespec/items/m3/tests/TestIndyErasure.java test/tools/javac/valhalla/typespec/items/m3/tests/TestIndyFactory.java test/tools/javac/valhalla/typespec/items/m3/tests/TestInheritedAnyMembers.java test/tools/javac/valhalla/typespec/items/m3/tests/TestInner.java test/tools/javac/valhalla/typespec/items/m3/tests/TestInstanceof.java test/tools/javac/valhalla/typespec/items/m3/tests/TestLambda.java test/tools/javac/valhalla/typespec/items/m3/tests/TestLoadAndStore.java test/tools/javac/valhalla/typespec/items/m3/tests/TestNestedGenerics.java test/tools/javac/valhalla/typespec/items/m3/tests/TestNew.java test/tools/javac/valhalla/typespec/items/m3/tests/TestNewArray.java test/tools/javac/valhalla/typespec/items/m3/tests/TestNonSpecializedGenericCall.java test/tools/javac/valhalla/typespec/items/m3/tests/TestNonSpecializedMethod.java test/tools/javac/valhalla/typespec/items/m3/tests/TestPop.java test/tools/javac/valhalla/typespec/items/m3/tests/TestRefOnly.java test/tools/javac/valhalla/typespec/items/m3/tests/TestRespecialization.java test/tools/javac/valhalla/typespec/items/m3/tests/TestSuper.java test/tools/javac/valhalla/typespec/items/m3/tests/TestSyntheticCast.java test/tools/javac/valhalla/typespec/items/m3/tests/TestValOnly.java
diffstat 41 files changed, 3364 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/make/build.properties	Mon Apr 11 15:08:12 2016 +0100
+++ b/make/build.properties	Fri Apr 15 17:24:24 2016 +0100
@@ -54,7 +54,7 @@
 jdk.jdeps.dependencies=java.compiler:jdk.compiler
 jdk.internal.le.dependencies=
 jdk.jdi.dependencies=
-jdk.jshell.dependencies=java.compiler:jdk.compiler
+jdk.jshell.dependencies=java.compiler:jdk.compiler:jdk.jdi:jdk.internal.le
 
 tool.javac.main.class=com.sun.tools.javac.Main
 tool.javadoc.main.class=com.sun.tools.javadoc.Main
--- a/make/build.xml	Mon Apr 11 15:08:12 2016 +0100
+++ b/make/build.xml	Fri Apr 15 17:24:24 2016 +0100
@@ -536,6 +536,10 @@
                                       compilation.kind="@{compilation.kind}" />
                 <build-module-classes module.name="jdk.jdeps"
                                       compilation.kind="@{compilation.kind}" />
+                <copy-module-classes  module.name="jdk.internal.le"
+                                      compilation.kind="@{compilation.kind}" />
+                <copy-module-classes  module.name="jdk.jdi"
+                                      compilation.kind="@{compilation.kind}" />
                 <build-module-classes module.name="jdk.jshell"
                                       compilation.kind="@{compilation.kind}"
                                       java.home="${target.java.home}"/>
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Mon Apr 11 15:08:12 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Fri Apr 15 17:24:24 2016 +0100
@@ -1027,6 +1027,7 @@
                     tree.sym = tree.type.tsym;
                     result = tree;
                 } else {
+                    tree.type = patchTypeVars(tree.type);
                     tree.sym = patchParam(tree.sym);
                     result = tree;
                 }
@@ -1038,24 +1039,32 @@
                 JCVariableDecl newTree = (JCVariableDecl)result;
                 if (newTree.sym.owner == oldMeth) {
                     newTree.sym.owner = newMeth;
-                    newTree.type = newTree.sym.type = patchTypeVars(newTree.type);
                 }
+                newTree.type = newTree.sym.type = patchTypeVars(newTree.type);
             }
 
             @Override
+            public void visitMethodDef(JCMethodDecl tree) {
+                super.visitMethodDef(tree);
+                JCMethodDecl newTree = (JCMethodDecl)result;
+                newTree.type = newTree.sym.type = patchTypeVars(newTree.type);
+            }
+
+        @Override
             public void visitClassDef(JCClassDecl tree) {
                 super.visitClassDef(tree);
                 JCClassDecl newTree = (JCClassDecl)result;
                 if (newTree.sym.owner == oldMeth) {
                     newTree.sym.owner = newMeth;
-                    newTree.sym.flatname = chk.localClassName(newTree.sym);
                 }
+                newTree.sym.flatname = chk.localClassName(newTree.sym);
             }
 
             @Override
             public void visitSelect(JCFieldAccess tree) {
                 super.visitSelect(tree);
                 JCFieldAccess newTree = (JCFieldAccess)result;
+                newTree.type = patchTypeVars(newTree.type);
                 newTree.sym = patchParam(newTree.sym);
             }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Apr 11 15:08:12 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Apr 15 17:24:24 2016 +0100
@@ -647,9 +647,9 @@
                     case TYPE_0:
                         break;
                     case TYPE_1:
-                        if (genericClassFile) {
+                        if (genericClassFile && pool.needsGenericEntry(type)) {
                             code.emitop2(typed, pool.putType(type));
-                        } else {
+                        } else if (!genericClassFile) {
                             code.markAny(pc, types.typeSig(type));
                         }
                         break;
@@ -2122,7 +2122,7 @@
             } else if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
                 if (genericClassFile) {
                     Type elem = types.elemtype(sigType);
-                    if (types.isSpecializableTypeVar(elem)) {
+                    if (elem.hasTag(TYPEVAR) && pool.needsGenericEntry(elem)) {
                         //temporary hack: treat this as a type-1 opcode
                         code.emitop2(typed, pool.putType(elem));
                     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Mon Apr 11 15:08:12 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Apr 15 17:24:24 2016 +0100
@@ -579,14 +579,13 @@
                     //do nothing
                     break;
                 case TYPE_1:
-                    if (types.isSpecializableTypeVar(originalType)) {
-                        if (genericClassFile) {
-                            //typed
-                            code.emitop2(typed, pool.putType(originalType));
-                        } else {
-                            //emit legacy bytecode mapping
-                            code.markAny(pc, types.bytecodeMappingSig(originalType));
-                        }
+                    if (genericClassFile && originalType.hasTag(TypeTag.TYPEVAR) &&
+                            pool.needsGenericEntry(originalType)) {
+                        //typed
+                        code.emitop2(typed, pool.putType(originalType));
+                    } else if (types.isSpecializableTypeVar(originalType)) {
+                        //emit legacy bytecode mapping
+                        code.markAny(pc, types.bytecodeMappingSig(originalType));
                     }
                     break;
                 case TYPE_3:
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java	Mon Apr 11 15:08:12 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java	Fri Apr 15 17:24:24 2016 +0100
@@ -65,16 +65,19 @@
 import com.sun.tools.javac.util.Tuple.Tuple2;
 
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
 import static com.sun.tools.javac.code.Kinds.Kind.TYP;
 import static com.sun.tools.javac.code.TypeTag.ANY_BOUND;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
+import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
 
 /**
  * Pool interface towards {@code ClassWriter}. Exposes methods to encode and write javac entities
@@ -551,49 +554,6 @@
             }
         }
 
-        private boolean needsGenericEntry(Type t) {
-            return needsGenericEntry.visit(t, null);
-        }
-
-        private DefaultTypeVisitor<Boolean, Void> needsGenericEntry = new DefaultTypeVisitor<Boolean, Void>() {
-            @Override
-            public Boolean visitType(Type t, Void _unused) {
-                return false;
-            }
-
-            @Override
-            public Boolean visitClassType(ClassType t, Void _unused) {
-                return !types.isVirtualizable(t) &&
-                        t.allparams().stream().anyMatch(types::isTypeArgumentSpecializable);
-            }
-
-            @Override
-            public Boolean visitArrayType(ArrayType t, Void _unused) {
-                return visit(t.elemtype, null);
-            }
-
-            @Override
-            public Boolean visitMethodType(Type.MethodType t, Void _unused) {
-                return t.getParameterTypes().prepend(t.getReturnType()).stream().anyMatch(e -> visit(e, null));
-            }
-
-            @Override
-            public Boolean visitWildcardType(WildcardType t, Void _unused) {
-                return visit(t.type, null);
-            }
-
-            @Override
-            public Boolean visitCapturedType(CapturedType t, Void _unused) {
-                return visitWildcardType(t.wildcard, null);
-            }
-
-            @Override
-            public Boolean visitTypeVar(TypeVar t, Void _unused) {
-                return visit(types.getBounds(t).head, null) ||
-                        (typeVarIndex(t) != -1 && types.isSpecializableTypeVar(t));
-            }
-        };
-
         private Type elemtypeRecursive(Type type) {
             Type arr = type;
             while (types.elemtype(arr) != null) {
@@ -603,6 +563,60 @@
         }
     };
 
+    boolean needsGenericEntry(Type t) {
+        return needsGenericEntry.visit(t, false);
+    }
+
+    private DefaultTypeVisitor<Boolean, Boolean> needsGenericEntry = new DefaultTypeVisitor<Boolean, Boolean>() {
+
+        Set<Type> seen = new HashSet<>();
+
+        @Override
+        public Boolean visitType(Type t, Boolean typeArg) {
+            return typeArg ? types.isPrimitiveOrValue(t) : false;
+        }
+
+        @Override
+        public Boolean visitClassType(ClassType t, Boolean typeArg) {
+            return !typeArg && !types.isVirtualizable(t) &&
+                    t.allparams().stream().anyMatch(ta -> ta.accept(this, true));
+        }
+
+        @Override
+        public Boolean visitArrayType(ArrayType t, Boolean typeArg) {
+            return typeArg ? false : visit(t.elemtype, typeArg);
+        }
+
+        @Override
+        public Boolean visitMethodType(Type.MethodType t, Boolean typeArg) {
+            return t.getParameterTypes().prepend(t.getReturnType()).stream().anyMatch(e -> visit(e, typeArg));
+        }
+
+        @Override
+        public Boolean visitWildcardType(WildcardType t, Boolean typeArg) {
+            return visit(t.type, typeArg);
+        }
+
+        @Override
+        public Boolean visitCapturedType(CapturedType t, Boolean typeArg) {
+            return visitWildcardType(t.wildcard, typeArg);
+        }
+
+        @Override
+        public Boolean visitTypeVar(TypeVar t, Boolean typeArg) {
+            try {
+                if (seen.add(t)) {
+                    return visit(types.getBounds(t).head, false) ||
+                            (typeVarIndex(t) != -1 && types.isSpecializableTypeVar(t));
+                } else {
+                    return false;
+                }
+            } finally {
+                seen.remove(t);
+            }
+        }
+    };
+
     /**
      * Write pool contents into given byte buffer.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/Opcodes.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+enum Opcodes {
+    ACONST_NULL("aconst_null"),
+    ALOAD("aload"),
+    ALOAD_0("aload_0"),
+    ALOAD_1("aload_1"),
+    ALOAD_2("aload_2"),
+    ALOAD_3("aload_3"),
+    ASTORE("astore"),
+    ASTORE_0("astore_0"),
+    ASTORE_1("astore_1"),
+    ASTORE_2("astore_2"),
+    ASTORE_3("astore_3"),
+    AALOAD("aaload"),
+    AASTORE("aastore"),
+    ARETURN("areturn"),
+    DUP("dup"),
+    DUP_X1("dup_x1"),
+    DUP_X2("dup_x2"),
+    POP("pop"),
+    LDC("ldc"),
+    LDC_W("ldc_w"),
+    IF_ACMPEQ("if_acmpeq"),
+    IF_ACMPNE("if_acmpne"),
+    CHECKCAST("checkcast"),
+    INSTANCEOF("instanceof"),
+    ANEWARRAY("anewarray"),
+    MULTIANEWARRAY("multianewarray"),
+    NEW("new"),
+    GETFIELD("getfield"),
+    PUTFIELD("putfield"),
+    INVOKEVIRTUAL("invokevirtual"),
+    INVOKEINTERFACE("invokeinterface"),
+    INVOKESPECIAL("invokespecial"),
+    INVOKEDYNAMIC("invokedynamic");
+
+    String mnemonic;
+
+    Opcodes(String mnemonic) {
+        this.mnemonic = mnemonic;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/PoolMapping.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,38 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+
+@Repeatable(PoolMappings.class)
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@interface PoolMapping {
+    Opcodes opcode();
+    String entry() default "";
+}
+
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@interface PoolMappings {
+    PoolMapping[] value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/PoolMappingHarness.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,681 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.lang.model.element.Element;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.BootstrapMethods_attribute;
+import com.sun.tools.classfile.BootstrapMethods_attribute.BootstrapMethodSpecifier;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_ArrayType_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_InterfaceMethodref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodDescriptor_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodType_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_ParameterizedType_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_TypeVar_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+import com.sun.tools.classfile.ConstantPool.CPRefInfo;
+import com.sun.tools.classfile.ConstantPool.SimpleCPVisitor;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
+import com.sun.tools.classfile.Instruction;
+import com.sun.tools.classfile.Instruction.KindVisitor;
+import com.sun.tools.classfile.Instruction.TypeKind;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.Opcode;
+import com.sun.tools.javac.api.BasicJavacTask;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+
+import static javax.tools.StandardLocation.SOURCE_PATH;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
+
+public class PoolMappingHarness {
+
+    static int nerrors = 0;
+
+    static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+    static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+    static final File outputDir = new File("out");
+
+    /*** Test driver ***/
+
+    public static void main(String[] args) throws Exception {
+        try {
+            if (args.length != 1) {
+                System.err.println("Usage: LocalVariableInferenceTester <sourcefile>");
+                System.exit(1);
+            }
+
+            //init output dir
+            outputDir.mkdir();
+
+            // Make sure classes are written to scratch dir.
+            fm.setLocation(CLASS_OUTPUT, Arrays.asList(new File("out")));
+
+            File path = new File(System.getProperty("test.src"));
+            fm.setLocation(SOURCE_PATH, Arrays.asList(path));
+            File input = new File(path, args[0]);
+            JavaFileObject jfo = fm.getJavaFileObjects(input).iterator().next();
+            System.err.println("file = " + jfo);
+            new PoolMappingHarness(jfo).check();
+            if (nerrors > 0) {
+                throw new AssertionError("Errors were found");
+            }
+        } finally {
+            fm.close();
+        }
+    }
+
+    /*** Test runner ***/
+
+    JavaFileObject jfo;
+    Map<ElementKey, List<PoolMapping>> poolMappings = new HashMap<>();
+    List<ElementKey> seenPoolMappings = new ArrayList<>();
+    Set<ElementKey> genericMethodSkip = new HashSet<>();
+
+    protected PoolMappingHarness(JavaFileObject jfo) {
+        this.jfo = jfo;
+    }
+
+    protected void check() throws Exception {
+        JavacTask ct = (JavacTask) comp.getTask(null, fm, null, Arrays.asList("-XDgenericClassFile"),
+                null, Arrays.asList(jfo));
+        ct.addTaskListener(new PoolMappingFinder(ct));
+        System.err.println("compiling code " + jfo);
+        if (!ct.call()) {
+            throw new AssertionError("Error during compilation");
+        }
+
+
+        for (File f : outputDir.listFiles()) {
+            checkClassFile(f);
+            f.delete();
+        }
+
+        //check all candidates have been used up
+        for (ElementKey key : poolMappings.keySet()) {
+            if (!seenPoolMappings.contains(key)) {
+                error("Redundant @PoolMapping annotation on method: " + key);
+            }
+        }
+    }
+
+    void checkClassFile(File file)
+            throws IOException, ConstantPoolException, InvalidDescriptor {
+        ClassFile classFile = ClassFile.read(file);
+        if (classFile.getName().endsWith("$any")) {
+            return; //skip virtual interface
+        }
+        ConstantPool constantPool = classFile.constant_pool;
+        String name = constantPool.get(classFile.this_class).accept(classNameVisitor, constantPool);
+        //lets get all the methods in the class file.
+        for (Method method : classFile.methods) {
+            checkMethod(method, getMappingsForDescriptor(name, classFile, method), name, classFile);
+        }
+    }
+
+    Optional<ElementKey> findKey(ClassFile classFile, Method method, String className, Set<ElementKey> keys) {
+        ConstantPool constantPool = classFile.constant_pool;
+        String bytecodeDesc = get(constantPool, method.descriptor.index).accept(typeEntryErasure, classFile);
+        String bytecodeParamsDesc = bytecodeDesc.substring(0, bytecodeDesc.indexOf(')') + 1);
+        return keys.stream()
+                .filter(k -> k.match(getString(constantPool, method.name_index), className, bytecodeParamsDesc))
+                .findFirst();
+    }
+
+    LinkedList<PoolMapping> getMappingsForDescriptor(String className, ClassFile classFile, Method method)
+            throws ConstantPoolException, InvalidDescriptor {
+        Optional<ElementKey> optKey = findKey(classFile, method, className, poolMappings.keySet());
+        if (optKey.isPresent()) {
+            ElementKey key = optKey.get();
+            List<PoolMapping> mappings = poolMappings.get(key);
+            seenPoolMappings.add(key);
+            poolMappings.remove(key);
+            return new LinkedList<>(mappings);
+        } else {
+            return new LinkedList<>();
+        }
+    }
+
+    void checkMethod(Method method, LinkedList<PoolMapping> expectedMappings, String className, ClassFile classFile)
+                     throws ConstantPoolException, InvalidDescriptor {
+        ConstantPool cp = classFile.constant_pool;
+        String mname = method.getName(cp);
+        String bytecodeDesc = get(cp, method.descriptor.index).accept(typeEntryErasure, classFile);
+        if (mname.endsWith("$get") || mname.endsWith("$set") || method.access_flags.is(AccessFlags.ACC_SYNTHETIC)) {
+            //skip virtualized accessors
+            return;
+        }
+
+        if (method.access_flags.is(AccessFlags.ACC_ABSTRACT)) {
+            System.err.println("Skipping abstract method: " +
+                    method.getName(cp) + bytecodeDesc);
+            return;
+        }
+
+        if (mname.equals("<init>") && classFile.access_flags.is(AccessFlags.ACC_SYNTHETIC)) {
+            System.err.println("Skipping synthetic init: " +
+                    method.getName(cp) + bytecodeDesc);
+            return;
+        }
+
+        Optional<ElementKey> optSkip = findKey(classFile, method, className, genericMethodSkip);
+        if (optSkip.isPresent()) {
+            genericMethodSkip.remove(optSkip);
+            System.err.println("Skipping generic bridge method: " +
+                    method.getName(cp) + bytecodeDesc);
+            return;
+        }
+
+        Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code);
+        boolean foundTyped = false;
+        String entry = null;
+        for (Instruction instr : code.getInstructions()) {
+            if (foundTyped) {
+                foundTyped = false;
+            } else {
+                entry = instr.accept(instructionScanner, classFile);
+            }
+            if (instr.getOpcode() == Opcode.TYPED) {
+                foundTyped = true;
+                continue;
+            }
+            if (entry != null) {
+                //System.err.println("class = " + className + " entry = " + entry + " ; PC = " + instr.getPC() + " ; opcode = " + instr.getMnemonic());
+                if (expectedMappings.isEmpty()) {
+                    error("Missing PoolMapping annotations in method: " +
+                            className + "." + mname + bytecodeDesc);
+                    break;
+                }
+                String mnemonic = instr.getMnemonic();
+                PoolMapping mapping = expectedMappings.peek();
+                if (!mnemonic.equals(mapping.opcode().mnemonic)) {
+                    error("Bad mnemonic in " + className + "." + mname + bytecodeDesc +
+                            " @ pc " + instr.getPC() + " (" + instr.getOpcode() + "): expected: " +
+                            mapping.opcode().mnemonic +
+                            " - found: " + mnemonic);
+                }
+                String expectedEntry = mapping.entry();
+                if (!expectedEntry.isEmpty() && !entry.equals(expectedEntry)) {
+                    error("Bad pool entry in " + className + "." + mname + bytecodeDesc +
+                            " @ pc " + instr.getPC() + " (" + instr.getOpcode() + "): expected: " +
+                            expectedEntry + " - found: " + entry);
+                }
+                expectedMappings.removeFirst();
+            }
+        }
+
+        if (expectedMappings.size() != 0) {
+            error("Unmatched PoolMapping annotations in method: " +
+                    method.getName(cp) + bytecodeDesc);
+        }
+    }
+
+    protected void error(String msg) {
+        nerrors++;
+        System.err.printf("Error occurred while checking file: %s\nreason: %s\n",
+                jfo.getName(), msg);
+    }
+
+    /*** Annotation extraction logic ***/
+
+    enum AnnotationKind {
+        POOL_MAPPING(PoolMapping.class) {
+            List<PoolMapping> getMappings(Annotation anno) {
+                return Collections.singletonList((PoolMapping)anno);
+            }
+        },
+        POOL_MAPPINGS(PoolMappings.class) {
+            List<PoolMapping> getMappings(Annotation anno) {
+                return Arrays.asList(((PoolMappings)anno).value());
+            }
+        };
+
+        Class<? extends Annotation> annoClass;
+
+        AnnotationKind(Class<? extends Annotation> annoClass) {
+            this.annoClass = annoClass;
+        }
+
+        abstract List<PoolMapping> getMappings(Annotation anno);
+    }
+
+    class PoolMappingFinder implements TaskListener {
+
+        Types types;
+        Trees trees;
+
+        PoolMappingFinder(JavacTask jt) {
+            types = Types.instance(((BasicJavacTask)jt).getContext());
+            trees = Trees.instance(jt);
+        }
+
+        @Override
+        public void started(TaskEvent e) {
+            //do nothing
+        }
+
+        @Override
+        public void finished(TaskEvent e) {
+            if (e.getKind() == Kind.ANALYZE) {
+                Tree tree = trees.getTree(e.getTypeElement());
+                new TreeScanner<>() {
+                    @Override
+                    public Object visitMethod(MethodTree node, Object o) {
+                        Element e = ((JCMethodDecl)node).sym;
+                        boolean isGenericMethod = isGenericMethod(e, types);
+                        if (isGenericMethod) {
+                            genericMethodSkip.add(new ElementKey(e, types, false));
+                        }
+                        for (AnnotationKind ak : AnnotationKind.values()) {
+                            Annotation annotation = e.getAnnotation(ak.annoClass);
+                            if (annotation != null) {
+                                poolMappings.put(new ElementKey(e, types, isGenericMethod), ak.getMappings(annotation));
+                            }
+                        }
+                        return super.visitMethod(node, o);
+                    }
+                }.scan(tree, null);
+            }
+        }
+
+        boolean isGenericMethod(Element elem, Types types) {
+            return ((Type)elem.asType()).getTypeArguments().stream().anyMatch(types::isSpecializableTypeVar);
+        }
+    }
+
+    class ElementKey {
+
+        String erasedSig;
+        String name;
+        String owner;
+
+        public ElementKey(Element elem, Types types, boolean isGenericMethod) {
+            Optional<TemplateMethod> templateMethod = Optional.ofNullable(elem.getAnnotation(TemplateMethod.class));
+            this.name = choose(templateMethod, TemplateMethod::name, () -> elem.getSimpleName().toString());
+            this.erasedSig = choose(templateMethod, TemplateMethod::sig, () -> computeErasedSignature(elem, types));
+            this.owner = choose(templateMethod, TemplateMethod::owner, () -> defaultOwner(elem, isGenericMethod));
+            //System.err.println("Entry = " + toString());
+        }
+
+        private String defaultOwner(Element elem, boolean isGenericMethod) {
+            String owner = ((Symbol)elem.getEnclosingElement()).flatName().toString();
+            if (isGenericMethod) {
+                String hash = sigHash(erasedSig);
+                owner = owner + "$" + name + "$" + hash;
+            }
+            return owner;
+        }
+
+        private String choose(Optional<TemplateMethod> templateMethod, Function<TemplateMethod, String> func, Supplier<String> defaultFunc) {
+            return templateMethod.<String>flatMap(templateMethod1 -> {
+                String val = func.apply(templateMethod.get());
+                return val.isEmpty() ? Optional.empty() : Optional.of(val);
+            }).orElseGet(defaultFunc);
+        }
+
+        private String computeErasedSignature(Element elem, Types types) {
+            return ((Symbol)elem).externalType(types).getParameterTypes().stream()
+                    .map(types::typeSig)
+                    .collect(Collectors.joining("", "(", ")"));
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ElementKey) {
+                ElementKey other = (ElementKey)obj;
+                return other.owner.equals(owner) &&
+                        other.name.equals(name) &&
+                        other.erasedSig.equals(erasedSig);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return owner.hashCode() << 8
+                    + name.hashCode() << 16
+                    + erasedSig.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return String.format("Key{name=%s;owner=%s;desc=%s}", name, owner, erasedSig);
+        }
+
+        boolean match(String otherName, String otherOwner, String otherErasedSig) {
+            return (name.equals(otherName) &&
+                    owner.equals(otherOwner) &&
+                    erasedSig.equals(otherErasedSig));
+        }
+
+        private String sigHash(String sig) {
+            String params = sig.substring(1, sig.lastIndexOf(')'));
+            return String.valueOf(Math.abs(params.hashCode()));
+        }
+    }
+
+    /*** pool helper logic ***/
+
+    CPInfo get(ConstantPool cp, int index) {
+        try {
+            return cp.get(index);
+        } catch (ConstantPoolException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    String getString(ConstantPool cp, int index) {
+        CPInfo info = get(cp, index);
+        if (info.getTag() == ConstantPool.CONSTANT_Utf8) {
+            return ((CONSTANT_Utf8_info)info).value;
+        } else {
+            throw new AssertionError("No Utf8 value found at index: " + index);
+        }
+    }
+
+    SimpleCPVisitor<String, ConstantPool> classNameVisitor = new SimpleCPVisitor<>() {
+        @Override
+        public String visitClass(CONSTANT_Class_info info, ConstantPool cp) {
+            return get(cp, info.name_index).accept(this, cp);
+        }
+
+        @Override
+        public String visitUtf8(CONSTANT_Utf8_info info, ConstantPool cp) {
+            return info.value;
+        }
+
+        @Override
+        public String visitParameterizedType(CONSTANT_ParameterizedType_info info, ConstantPool cp) {
+            return get(cp, info.clazz_idx).accept(this, cp);
+        }
+    };
+
+    Instruction.KindVisitor<String, ClassFile> instructionScanner = new KindVisitor<>() {
+
+        TypeEntryToString typeEntryToString = new TypeEntryToString();
+
+        @Override
+        public String visitNoOperands(Instruction instr, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitArrayType(Instruction instr, TypeKind kind, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitBranch(Instruction instr, int offset, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitConstantPoolRef(Instruction instr, int index, ClassFile classFile) {
+            return getDesc(classFile, index);
+        }
+
+        @Override
+        public String visitConstantPoolRefAndValue(Instruction instr, int index, int value, ClassFile classFile) {
+            return getDesc(classFile, index);
+        }
+
+        @Override
+        public String visitLocal(Instruction instr, int index, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitLocalAndValue(Instruction instr, int index, int value, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitValue(Instruction instr, int value, ClassFile classFile) {
+            return null;
+        }
+
+        @Override
+        public String visitUnknown(Instruction instr, ClassFile classFile) {
+            return null;
+        }
+
+        private String getDesc(ClassFile classFile, int index) {
+            return isTypeEntry(classFile, index) ?
+                    get(classFile.constant_pool, index).accept(typeEntryToString, classFile) : null;
+        }
+
+        private boolean isTypeEntry(ClassFile classFile, int index) {
+            ConstantPool pool = classFile.constant_pool;
+            CPInfo info = get(pool, index);
+            switch (info.getTag()) {
+                case ConstantPool.CONSTANT_ParameterizedType:
+                case ConstantPool.CONSTANT_ArrayType:
+                case ConstantPool.CONSTANT_MethodDescriptor:
+                case ConstantPool.CONSTANT_TypeVar:
+                    return true;
+                case ConstantPool.CONSTANT_Fieldref:
+                case ConstantPool.CONSTANT_InterfaceMethodref:
+                case ConstantPool.CONSTANT_Methodref:
+                    return isTypeEntry(classFile, ((CPRefInfo)info).class_index) ||
+                            isTypeEntry(classFile, ((CPRefInfo)info).name_and_type_index);
+                case ConstantPool.CONSTANT_NameAndType:
+                    return isTypeEntry(classFile, ((CONSTANT_NameAndType_info)info).type_index);
+                case ConstantPool.CONSTANT_Class:
+                    return isTypeEntry(classFile, ((CONSTANT_Class_info)info).name_index);
+                case ConstantPool.CONSTANT_MethodType:
+                    return isTypeEntry(classFile, ((CONSTANT_MethodType_info)info).descriptor_index);
+                case ConstantPool.CONSTANT_MethodHandle:
+                    return isTypeEntry(classFile, ((CONSTANT_MethodHandle_info)info).reference_index);
+                case ConstantPool.CONSTANT_InvokeDynamic: {
+                    CONSTANT_InvokeDynamic_info indyInfo = (CONSTANT_InvokeDynamic_info)info;
+                    if (isTypeEntry(classFile, indyInfo.name_and_type_index)) {
+                        return true;
+                    } else {
+                        BootstrapMethods_attribute bsm =
+                                (BootstrapMethods_attribute)classFile.getAttribute(Attribute.BootstrapMethods);
+                        BootstrapMethodSpecifier bsmEntry = bsm.bootstrap_method_specifiers[indyInfo.bootstrap_method_attr_index];
+                        return IntStream.of(bsmEntry.bootstrap_arguments).anyMatch(i -> isTypeEntry(classFile, i));
+                    }
+                }
+                default:
+                    return false;
+            }
+        }
+    };
+
+    class TypeEntryToString extends SimpleCPVisitor<String, ClassFile> {
+
+        public String visitClass(CONSTANT_Class_info info, ClassFile classFile) {
+            return get(classFile.constant_pool, info.name_index).accept(this, classFile);
+        }
+
+        public String visitFieldref(CONSTANT_Fieldref_info info, ClassFile classFile) {
+            return visitRef(info, classFile);
+        }
+
+        public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassFile classFile) {
+            return visitRef(info, classFile);
+        }
+
+        public String visitNameAndType(CONSTANT_NameAndType_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            return get(cp, info.name_index).accept(this, classFile) + ":" + get(cp, info.type_index).accept(this, classFile);
+        }
+
+        public String visitMethodref(CONSTANT_Methodref_info info, ClassFile classFile) {
+            return visitRef(info, classFile);
+        }
+
+        public String visitUtf8(CONSTANT_Utf8_info info, ClassFile classFile) {
+            return info.value;
+        }
+
+        private String visitRef(CPRefInfo info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            String cn = get(cp, info.class_index).accept(this, classFile);
+            String nat = get(cp, info.name_and_type_index).accept(this, classFile);
+            return cn + "." + nat;
+        }
+
+        @Override
+        public String visitTypeVar(CONSTANT_TypeVar_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            String name = get(cp, info.getNameIndex()).accept(this, classFile);
+            String erasure = get(cp, info.erasure_idx).accept(this, classFile);
+            return String.format("%s/%s", name, erasure);
+        }
+
+        @Override
+        public String visitParameterizedType(CONSTANT_ParameterizedType_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            String encl = info.encl_idx != 0 ?
+                    get(cp, info.encl_idx).accept(this, classFile) + "." : "";
+            String clazz = get(cp, info.clazz_idx).accept(this, classFile);
+            String targs = IntStream.of(info.params_idxs)
+                    .mapToObj(i -> get(cp, i).accept(this, classFile))
+                    .collect(Collectors.joining(",", "<", ">"));
+            return String.format("%s%c%s%s;", encl, info.basicType, clazz, targs);
+        }
+
+        @Override
+        public String visitArrayType(CONSTANT_ArrayType_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            String elemDesc = get(cp, info.componentType_idx).accept(this, classFile);
+            return "[[[[[[[[[[[[[[[[".substring(0, info.dims) + elemDesc;
+        }
+
+        @Override
+        public String visitMethodDescriptor(CONSTANT_MethodDescriptor_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            String retDesc = get(cp, info.returnType_idx).accept(this, classFile);
+            String args = IntStream.of(info.params_idxs)
+                    .mapToObj(idx -> get(cp, idx).accept(this, classFile))
+                    .collect(Collectors.joining("", "(", ")"));
+            return args + retDesc;
+        }
+
+        @Override
+        public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            String desc = get(cp, info.name_and_type_index).accept(this, classFile);
+            BootstrapMethods_attribute bsm =
+                    (BootstrapMethods_attribute)classFile.getAttribute(Attribute.BootstrapMethods);
+            BootstrapMethodSpecifier bsmEntry = bsm.bootstrap_method_specifiers[info.bootstrap_method_attr_index];
+            String bsmArgs = IntStream.of(bsmEntry.bootstrap_arguments)
+                    .mapToObj(i -> get(cp, i).accept(this, classFile))
+                    .collect(Collectors.joining(",", "::{", "}"));
+            return desc + bsmArgs;
+        }
+
+        @Override
+        public String visitString(CONSTANT_String_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            return get(cp, info.string_index).accept(this, classFile);
+        }
+
+        @Override
+        public String visitMethodHandle(CONSTANT_MethodHandle_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            return get(cp, info.reference_index).accept(this, classFile);
+        }
+
+        @Override
+        public String visitMethodType(CONSTANT_MethodType_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            return get(cp, info.descriptor_index).accept(this, classFile);
+        }
+    }
+
+    TypeEntryToString typeEntryErasure = new TypeEntryToString() {
+        @Override
+        public String visitTypeVar(CONSTANT_TypeVar_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            return get(cp, info.erasure_idx).accept(this, classFile);
+        }
+
+        @Override
+        public String visitParameterizedType(CONSTANT_ParameterizedType_info info, ClassFile classFile) {
+            ConstantPool cp = classFile.constant_pool;
+            return String.format("%c%s;", info.basicType, get(cp, info.clazz_idx).accept(this, classFile));
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/TemplateMethod.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@interface TemplateMethod {
+    String name() default "";
+    String sig() default "";
+    String owner() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestAnyMembers.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,127 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestAnyMembers.java
+ */
+
+class TestAnyMembers {
+
+    static class AnyClass<any T> {
+        T t;
+        void test() { }
+    }
+
+    interface AnyInterface<any T> {
+        T test();
+    }
+
+    @PoolMapping(opcode=Opcodes.GETFIELD, entry = "LTestAnyMembers$AnyClass<Z/_>;.t:Z/Ljava/lang/Object;")
+    @PoolMapping(opcode=Opcodes.ASTORE_2, entry = "Z/Ljava/lang/Object;")
+    <any Z> void testField(AnyClass<Z> ac) {
+        Z z = ac.t;
+    }
+
+    @PoolMapping(opcode=Opcodes.INVOKEVIRTUAL, entry = "LTestAnyMembers$AnyClass<Z/_>;.test:()V")
+    <any Z> void testInvokeVirtual(AnyClass<Z> ac) {
+        ac.test();
+    }
+
+    @PoolMapping(opcode=Opcodes.INVOKEINTERFACE, entry = "LTestAnyMembers$AnyInterface<Z/_>;.test:()Z/Ljava/lang/Object;")
+    @PoolMapping(opcode=Opcodes.ASTORE_2, entry = "Z/Ljava/lang/Object;")
+    <any Z> void testInvokeInterface(AnyInterface<Z> ai) {
+        Z z = ai.test();
+    }
+
+    <Z> void testNegField(AnyClass<Z> ac) {
+        Z z = ac.t;
+    }
+
+    <Z> void testNegInvokeVirtual(AnyClass<Z> ac) {
+        ac.test();
+    }
+
+    <Z> void testNegInvokeInterface(AnyInterface<Z> ai) {
+        ai.test();
+    }
+
+    <Z> void testNegInvokeVirtualArrayAnyClass(AnyClass<Z>[] ac_arr) {
+        ac_arr.toString();
+    }
+
+    <Z> void testNegInvokeVirtualArrayAnyVar(Z[] z_arr) {
+        z_arr.toString();
+    }
+
+    @PoolMapping(opcode=Opcodes.GETFIELD, entry = "LTestAnyMembers$AnyClass<Z/_>;.t:Z/Ljava/lang/Object;")
+    @PoolMapping(opcode=Opcodes.ASTORE_2, entry = "Z/Ljava/lang/Object;")
+    <any Z> void testExtField(AnyClass<? extends Z> ac) {
+        Z z = ac.t;
+    }
+
+    @PoolMapping(opcode=Opcodes.INVOKEVIRTUAL, entry = "LTestAnyMembers$AnyClass<Z/_>;.test:()V")
+    <any Z> void testExtInvokeVirtual(AnyClass<? extends Z> ac) {
+        ac.test();
+    }
+
+    @PoolMapping(opcode=Opcodes.INVOKEINTERFACE, entry = "LTestAnyMembers$AnyInterface<Z/_>;.test:()Z/Ljava/lang/Object;")
+    @PoolMapping(opcode=Opcodes.POP, entry = "Z/Ljava/lang/Object;")
+    <any Z> void testExtInvokeInterface(AnyInterface<? extends Z> ai) {
+        ai.test();
+    }
+
+    @PoolMapping(opcode=Opcodes.ALOAD_2, entry = "Z/Ljava/lang/Object;")
+    @PoolMapping(opcode=Opcodes.PUTFIELD, entry = "LTestAnyMembers$AnyClass<Z/_>;.t:Z/Ljava/lang/Object;")
+    <any Z> void testSupField(AnyClass<? super Z> ac, Z z) {
+        ac.t = z;
+    }
+
+    @PoolMapping(opcode=Opcodes.INVOKEVIRTUAL, entry = "LTestAnyMembers$AnyClass<Z/_>;.test:()V")
+    <any Z> void testSupInvokeVirtual(AnyClass<? super Z> ac) {
+        ac.test();
+    }
+
+    @PoolMapping(opcode=Opcodes.INVOKEINTERFACE, entry = "LTestAnyMembers$AnyInterface<Z/_>;.test:()Z/Ljava/lang/Object;")
+    @PoolMapping(opcode=Opcodes.POP, entry = "Z/Ljava/lang/Object;")
+    <any Z> void testSupInvokeInterface(AnyInterface<? super Z> ai) {
+        ai.test();
+    }
+
+    void testUnboundField(AnyClass<?> ac) {
+        Object z = ac.t;
+    }
+
+    void testUnboundInvokeVirtual(AnyClass<?> ac) {
+        ac.test();
+    }
+
+    void testUnboundInvokeInterface(AnyInterface<?> ai) {
+        ai.test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestArrayLoadAndStore.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestArrayLoadAndStore.java
+ */
+
+class TestArrayLoadAndStore {
+
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.AASTORE)
+    @PoolMapping(opcode= Opcodes.AALOAD)
+    @PoolMapping(opcode= Opcodes.ASTORE_2)
+    static <any T> void test(T[] tarr, T t) {
+        tarr[0] = t;
+        t = tarr[0];
+    }
+
+    static <T> void testNeg(T[] tarr, T t) {
+        tarr[0] = t;
+        t = tarr[0];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestBinary.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,83 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestBinary.java
+ */
+
+class TestBinary<any T> {
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPNE, entry = "T/Ljava/lang/Object;")
+    public boolean testAnd01(T t, Object obj) {
+        return obj != null && t == t;
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPNE, entry = "T/Ljava/lang/Object;")
+    public boolean testAnd10(T t, Object obj) {
+        return t == t && obj != null;
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPNE, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPNE, entry = "T/Ljava/lang/Object;")
+    public boolean testAnd11(T t, Object obj) {
+        return t == t && t == t;
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPNE, entry = "T/Ljava/lang/Object;")
+    public boolean testOr01(T t, Object obj) {
+        return obj != null || t == t;
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPEQ, entry = "T/Ljava/lang/Object;")
+    public boolean testOr10(T t, Object obj) {
+        return t == t || obj != null;
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPEQ, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD_1, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.IF_ACMPNE, entry = "T/Ljava/lang/Object;")
+    public boolean testOr11(T t, Object obj) {
+        return t == t || t == t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestCapture.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestCapture.java
+ */
+
+class TestCapture<any X> {
+    static class AnyClass<any X> { }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC, entry = "m:(LTestCapture<X/_>;LTestCapture$AnyClass<X/_>;)V::{TestCapture,(LTestCapture$AnyClass;)V,X/_}")
+    void testInvokeSuper(AnyClass<? super X> a) {
+        m(a);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC, entry = "m:(LTestCapture<X/_>;LTestCapture$AnyClass<X/_>;)V::{TestCapture,(LTestCapture$AnyClass;)V,X/_}")
+    void testInvokeExtends(AnyClass<? extends X> a) {
+        m(a);
+    }
+
+    @PoolMapping(opcode = Opcodes.NEW, entry = "LTestCapture$Wrap<X/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL, entry = "LTestCapture$Wrap<X/_>;.<init>:(LTestCapture$AnyClass<X/_>;)V")
+    void testNewSuper(AnyClass<? super X> a) {
+        new Wrap<>(a);
+    }
+
+    @PoolMapping(opcode = Opcodes.NEW, entry = "LTestCapture$Wrap<X/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL, entry = "LTestCapture$Wrap<X/_>;.<init>:(LTestCapture$AnyClass<X/_>;)V")
+    void testNewExtends(AnyClass<? extends X> a) {
+        new Wrap<>(a);
+    }
+
+    static class Wrap<any X> {
+        Wrap(AnyClass<X> a) { }
+    }
+
+    <any Z> void m(AnyClass<Z> anyClass) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestCast.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestCapture.java
+ */
+
+class TestCast {
+
+    static class AnyClass<any T> { }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    void test1(AnyClass<int> li) {
+        Object o = (AnyClass<int>)li;
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    <any Z> void test2() {
+        Object o = (AnyClass<Z>)null;
+    }
+
+    <Z> void test3() {
+        Object o = (AnyClass<Z>)null;
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    <any Z> void test4() {
+        Object o = (Z[])null;
+        o = (Z[][])null;
+    }
+
+    <Z> void test5() {
+        Object o = (Z[])null;
+        o = (Z[][])null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestClassLit.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,57 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestClassLit.java
+ */
+
+class TestClassLit {
+
+    static class AnyClass<any T> { }
+
+    @PoolMapping(opcode = Opcodes.LDC, entry = "LTestClassLit$AnyClass<Z/_>;")
+    <any Z> void testAny() {
+        Class<?> c = AnyClass<Z>.class;
+    }
+
+    @PoolMapping(opcode = Opcodes.LDC, entry = "[LTestClassLit$AnyClass<Z/_>;")
+    <any Z> void testAnyArray() {
+        Class<?> c = AnyClass<Z>[].class;
+    }
+
+    @PoolMapping(opcode = Opcodes.LDC, entry = "LTestClassLit$AnyClass<I>;")
+    void testSpecialized() {
+        Class<?> c = AnyClass<int>.class;
+    }
+
+    @PoolMapping(opcode = Opcodes.LDC, entry = "[LTestClassLit$AnyClass<I>;")
+    void testSpecializedArray() {
+        Class<?> c = AnyClass<int>[].class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestCmp.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,352 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestCmp.java
+ */
+
+class TestCmp {
+
+    static class AnyClass<any T> {
+        boolean cond;
+        T t;
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNe(T t1, T t2) {
+        boolean b = t1 == t2;
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEq(T t1, T t2) {
+        boolean b = t1 != t2;
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeWhile(T t1, T t2) {
+        while (t1 == t2) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqWhile(T t1, T t2) {
+        while (t1 != t2) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeDo(T t1, T t2) {
+        do { } while (t1 != t2);
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqDo(T t1, T t2) {
+        do { } while (t1 == t2);
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeFor(T t1, T t2) {
+        for (; t1 == t2 ;) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqFor(T t1, T t2) {
+        for (; t1 != t2 ;) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeIf(T t1, T t2) {
+        if (t1 == t2) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqIf(T t1, T t2) {
+        if (t1 != t2) { };
+    }
+
+    <T> void testNegCmpNe(T t1, T t2) {
+        boolean b = t1 == t2;
+    }
+
+    <T> void testNegCmpEq(T t1, T t2) {
+        boolean b = t1 != t2;
+    }
+
+    <T> void testNegCmpNeWhile(T t1, T t2) {
+        while (t1 == t2) { };
+    }
+
+    <T> void testNegCmpEqWhile(T t1, T t2) {
+        while (t1 != t2) { };
+    }
+
+    <T> void testNegCmpNeDo(T t1, T t2) {
+        do { } while (t1 != t2);
+    }
+
+    <T> void testNegCmpEqDo(T t1, T t2) {
+        do { } while (t1 == t2);
+    }
+
+    <T> void testNegCmpNeFor(T t1, T t2) {
+        for (; t1 == t2; ) {
+        }
+        ;
+    }
+
+    <T> void testNegCmpEqFor(T t1, T t2) {
+        for (; t1 != t2 ;) { };
+    }
+
+    <T> void testNegCmpNeIf(T t1, T t2) {
+        if (t1 == t2) { };
+    }
+
+    <T> void testNegCmpEqIf(T t1, T t2) {
+        if (t1 != t2) { };
+    }
+    
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeField(AnyClass<T> t1, AnyClass<T> t2) {
+        boolean b = t1.t == t2.t;
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqField(AnyClass<T> t1, AnyClass<T> t2) {
+        boolean b = t1.t != t2.t;
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeWhileField(AnyClass<T> t1, AnyClass<T> t2) {
+        while (t1.t == t2.t) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqWhileField(AnyClass<T> t1, AnyClass<T> t2) {
+        while (t1.t != t2.t) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeDoField(AnyClass<T> t1, AnyClass<T> t2) {
+        do { } while (t1.t != t2.t);
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqDoField(AnyClass<T> t1, AnyClass<T> t2) {
+        do { } while (t1.t == t2.t);
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeForField(AnyClass<T> t1, AnyClass<T> t2) {
+        for (; t1.t == t2.t ;) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqForField(AnyClass<T> t1, AnyClass<T> t2) {
+        for (; t1.t != t2.t ;) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPNE)
+    <any T> void testCmpNeIfField(AnyClass<T> t1, AnyClass<T> t2) {
+        if (t1.t == t2.t) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    @PoolMapping(opcode= Opcodes.IF_ACMPEQ)
+    <any T> void testCmpEqIfField(AnyClass<T> t1, AnyClass<T> t2) {
+        if (t1.t != t2.t) { };
+    }
+
+    <T> void testNegCmpNeField(AnyClass<T> t1, AnyClass<T> t2) {
+        boolean b = t1.t == t2.t;
+    }
+
+    <T> void testNegCmpEqField(AnyClass<T> t1, AnyClass<T> t2) {
+        boolean b = t1.t != t2.t;
+    }
+
+    <T> void testNegCmpNeWhileField(AnyClass<T> t1, AnyClass<T> t2) {
+        while (t1.t == t2.t) { };
+    }
+
+    <T> void testNegCmpEqWhileField(AnyClass<T> t1, AnyClass<T> t2) {
+        while (t1.t != t2.t) { };
+    }
+
+    <T> void testNegCmpNeDoField(AnyClass<T> t1, AnyClass<T> t2) {
+        do { } while (t1.t != t2.t);
+    }
+
+    <T> void testNegCmpEqDoField(AnyClass<T> t1, AnyClass<T> t2) {
+        do { } while (t1.t == t2.t);
+    }
+
+    <T> void testNegCmpNeForField(AnyClass<T> t1, AnyClass<T> t2) {
+        for (; t1.t == t2.t ;) { };
+    }
+
+    <T> void testNegCmpEqForField(AnyClass<T> t1, AnyClass<T> t2) {
+        for (; t1.t != t2.t ;) { };
+    }
+
+    <T> void testNegCmpNeIfField(AnyClass<T> t1, AnyClass<T> t2) {
+        if (t1.t == t2.t) { };
+    }
+
+    <T> void testNegCmpEqIfField(AnyClass<T> t1, AnyClass<T> t2) {
+        if (t1.t != t2.t) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpNeFieldUnary(AnyClass<T> t1) {
+        boolean b = !t1.cond;
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpEqFieldUnary(AnyClass<T> t1) {
+        boolean b = t1.cond;
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpNeWhileFieldUnary(AnyClass<T> t1) {
+        while (!t1.cond) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpEqWhileFieldUnary(AnyClass<T> t1) {
+        while (t1.cond) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpNeDoFieldUnary(AnyClass<T> t1) {
+        do { } while (!t1.cond);
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpEqDoFieldUnary(AnyClass<T> t1) {
+        do { } while (t1.cond);
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpNeForFieldUnary(AnyClass<T> t1) {
+        for (; !t1.cond ;) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpEqForFieldUnary(AnyClass<T> t1) {
+        for (; t1.cond ;) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpNeIfFieldUnary(AnyClass<T> t1) {
+        if (!t1.cond) { };
+    }
+
+    @PoolMapping(opcode= Opcodes.GETFIELD)
+    <any T> void testCmpEqIfFieldUnary(AnyClass<T> t1) {
+        if (t1.cond) { };
+    }
+
+    <T> void testNegCmpNeFieldUnary(AnyClass<T> t1) {
+        boolean b = !t1.cond;
+    }
+
+    <T> void testNegCmpEqFieldUnary(AnyClass<T> t1) {
+        boolean b = t1.cond;
+    }
+
+    <T> void testNegCmpNeWhileFieldUnary(AnyClass<T> t1) {
+        while (!t1.cond) { };
+    }
+
+    <T> void testNegCmpEqWhileFieldUnary(AnyClass<T> t1) {
+        while (t1.cond) { };
+    }
+
+    <T> void testNegCmpNeDoFieldUnary(AnyClass<T> t1) {
+        do { } while (!t1.cond);
+    }
+
+    <T> void testNegCmpEqDoFieldUnary(AnyClass<T> t1) {
+        do { } while (t1.cond);
+    }
+
+    <T> void testNegCmpNeForFieldUnary(AnyClass<T> t1) {
+        for (; !t1.cond ;) { };
+    }
+
+    <T> void testNegCmpEqForFieldUnary(AnyClass<T> t1) {
+        for (; t1.cond ;) { };
+    }
+
+    <T> void testNegCmpNeIfFieldUnary(AnyClass<T> t1) {
+        if (!t1.cond) { };
+    }
+
+    <T> void testNegCmpEqIfFieldUnary(AnyClass<T> t1) {
+        if (t1.cond) { };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestDefault.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,56 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestDefault.java
+ */
+
+class TestDefault<any X> {
+
+    <Z> void testNotAny() {
+        Z z = Z.default;
+    }
+
+    @PoolMapping(opcode = Opcodes.ACONST_NULL)
+    @PoolMapping(opcode = Opcodes.ASTORE_1)
+    <any Z> void testAny() {
+        Z z = Z.default;
+    }
+
+    __WhereRef(X) void testRef() {
+        X x = X.default;
+    }
+
+    @PoolMapping(opcode = Opcodes.ACONST_NULL)
+    @PoolMapping(opcode = Opcodes.ASTORE_1)
+    @TemplateMethod(name = "template$testVal")
+    __WhereVal(X) void testVal() {
+        X x = X.default;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestDup.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestDup.java
+ */
+
+class TestDup {
+
+    static class AnyClass<any T> {
+
+        T t;
+
+        @PoolMapping(opcode= Opcodes.ALOAD_3)
+        @PoolMapping(opcode= Opcodes.DUP)
+        @PoolMapping(opcode= Opcodes.ASTORE_2)
+        @PoolMapping(opcode= Opcodes.ASTORE_1)
+        static <any T> void test_dup(T t1, T t2, T t3) {
+            t1 = (t2 = t3);
+        }
+
+        @PoolMapping(opcode= Opcodes.ALOAD_2)
+        @PoolMapping(opcode= Opcodes.DUP_X1)
+        @PoolMapping(opcode= Opcodes.PUTFIELD)
+        @PoolMapping(opcode= Opcodes.ASTORE_1)
+        void test_dup_x1(T t1, T t2) {
+            t1 = (t = t2);
+        }
+    }
+
+    static class NonAnyClass<T> {
+
+        T t;
+
+        static <T> void testNeg_dup(T t1, T t2, T t3) {
+            t1 = (t2 = t3);
+        }
+
+        void testNeg_dup_x1(T t1, T t2) {
+            t1 = (t = t2);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestForeach.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestForeach.java
+ */
+
+class TestForeach<any T> {
+
+    static class Box<any T> {
+	    void g(T t) { }
+    }
+
+    @PoolMapping(opcode = Opcodes.AALOAD, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ASTORE, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ALOAD, entry = "T/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+    public <any T> void testAnyForEach(T[] t_arr, Box<? super T> b) {
+        for (T t : t_arr) {
+            b.g(t);
+        }
+    }
+
+    public <T> void testPlainForEach(T[] t_arr, Box<? super T> b) {
+        for (T t : t_arr) {
+            b.g(t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestGeneric2GenericCall.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestGeneric2GenericCall.java
+ */
+
+class TestGeneric2GenericCall {
+
+    static class List<any Z> { }
+
+    @PoolMapping(opcode= Opcodes.NEW)
+    @PoolMapping(opcode= Opcodes.INVOKESPECIAL)
+    @PoolMapping(opcode= Opcodes.CHECKCAST, entry = "LTestGeneric2GenericCall$List<Z/_>;")
+    static <any Z> List<Z> list(Z z) { return id(new List<Z>()); }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    static <any Z> Z id(Z z) { return z; }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC,
+                 entry = "id:(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;::{TestGeneric2GenericCall,(Ljava/lang/Object;)Ljava/lang/Object;,Z/_,Z/_}")
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC,
+                 entry = "id:(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;::{TestGeneric2GenericCall,(Ljava/lang/Object;)Ljava/lang/Object;,Z/_,Z/_}")
+    @PoolMapping(opcode= Opcodes.POP)
+    static <any Z> void testNestedIdAny(Z z) {
+        id(id(z));
+    }
+
+    static void testNestedIdPrimitive() {
+        id(id(1));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestGenericSpecializedConstructor.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestGenericSpecializedConstructor.java
+ */
+
+class TestGenericSpecializedConstructor {
+
+    static class Foo<any X> {
+        <any Z> Foo(Z z) { }
+        <Z> Foo(Z z1, Z z2) { }
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "<init>:(I)LTestGenericSpecializedConstructor$Foo<I>;::{TestGenericSpecializedConstructor$Foo,(Ljava/lang/Object;)V,I}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "<init>:(I)LTestGenericSpecializedConstructor$Foo<Z/_>;::{TestGenericSpecializedConstructor$Foo,(Ljava/lang/Object;)V,I}")
+    <any Z, V> void testAny() {
+        Foo<String> foo1 = new Foo<String>(1);
+        Foo<int> foo2 = new Foo<int>(1);
+        Foo<Z> foo3 = new Foo<Z>(1);
+        Foo<V> foo4 = new Foo<V>(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.NEW,
+                 entry = "LTestGenericSpecializedConstructor$Foo<I>;")
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL,
+                 entry = "LTestGenericSpecializedConstructor$Foo<I>;.<init>:(Ljava/lang/Object;Ljava/lang/Object;)V")
+    @PoolMapping(opcode = Opcodes.NEW,
+                 entry = "LTestGenericSpecializedConstructor$Foo<Z/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL,
+                 entry = "LTestGenericSpecializedConstructor$Foo<Z/_>;.<init>:(Ljava/lang/Object;Ljava/lang/Object;)V")
+    <any Z, V> void testNonAny() {
+        Foo<String> foo1 = new Foo<String>(1, 2);
+        Foo<int> foo2 = new Foo<int>(1, 2);
+        Foo<Z> foo3 = new Foo<Z>(1, 2);
+        Foo<V> foo4 = new Foo<V>(1, 2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestIndy.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,107 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestIndy.java
+ */
+
+class TestIndy {
+    static class Box<any T> {
+        <any U> Box<U> dup(U z) { return null; }
+        static <any U> Box<U> dupStatic(U z) { return null; }
+    }
+
+    static class TwoBox<any T, any U> {
+        static <any T, any U> TwoBox<T, U> make(T t, U u) { return null; }
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                     entry = "dup:(LTestIndy$Box<Z/_>;I)LTestIndy$Box<I>;::{TestIndy$Box,(Ljava/lang/Object;)LTestIndy$Box;,I}")
+    <any Z> void testAny(Box<Z> bz) {
+        Box<int> bi = bz.dup(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "dup:(LTestIndy$Box<Z/_>;I)LTestIndy$Box<I>;::{TestIndy$Box,(Ljava/lang/Object;)LTestIndy$Box;,I}")
+    <any Z> void testAnyExplicit(Box<Z> bz) {
+        Box<int> bi = bz.<int>dup(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "dupStatic:(I)LTestIndy$Box<I>;::{TestIndy$Box,(Ljava/lang/Object;)LTestIndy$Box;,I}")
+    <any Z> void testAnyStatic() {
+        Box<int> bi = Box.dupStatic(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "dupStatic:(I)LTestIndy$Box<I>;::{TestIndy$Box,(Ljava/lang/Object;)LTestIndy$Box;,I}")
+    <any Z> void testAnyStaticExplicit() {
+        Box<int> bi = Box.<int>dupStatic(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "dup:(LTestIndy$Box<J>;I)LTestIndy$Box<I>;::{TestIndy$Box,(Ljava/lang/Object;)LTestIndy$Box;,I}")
+    void testSpecialized() {
+        Box<long> bl = null;
+        Box<int> bi = bl.dup(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "dup:(LTestIndy$Box<J>;I)LTestIndy$Box<I>;::{TestIndy$Box,(Ljava/lang/Object;)LTestIndy$Box;,I}")
+    void testSpecializedExplicit() {
+        Box<long> bl = null;
+        Box<int> bi = bl.<int>dup(1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "make:(ILjava/lang/Object;)LTestIndy$TwoBox<I,_>;::{TestIndy$TwoBox,(Ljava/lang/Object;Ljava/lang/Object;)LTestIndy$TwoBox;,I,_}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "make:(Ljava/lang/Object;I)LTestIndy$TwoBox<_,I>;::{TestIndy$TwoBox,(Ljava/lang/Object;Ljava/lang/Object;)LTestIndy$TwoBox;,_,I}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "make:(II)LTestIndy$TwoBox<I,I>;::{TestIndy$TwoBox,(Ljava/lang/Object;Ljava/lang/Object;)LTestIndy$TwoBox;,I,I}")
+    void testMultipleArgs() {
+        TwoBox.make(1, "");
+        TwoBox.make("", 1);
+        TwoBox.make("", "");
+        TwoBox.make(1, 1);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "make:(ILjava/lang/Object;)LTestIndy$TwoBox<I,_>;::{TestIndy$TwoBox,(Ljava/lang/Object;Ljava/lang/Object;)LTestIndy$TwoBox;,I,_}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "make:(Ljava/lang/Object;I)LTestIndy$TwoBox<_,I>;::{TestIndy$TwoBox,(Ljava/lang/Object;Ljava/lang/Object;)LTestIndy$TwoBox;,_,I}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+            entry = "make:(II)LTestIndy$TwoBox<I,I>;::{TestIndy$TwoBox,(Ljava/lang/Object;Ljava/lang/Object;)LTestIndy$TwoBox;,I,I}")
+    void testMultipleArgsExplicit() {
+        TwoBox.<int, String>make(1, "");
+        TwoBox.<String, int>make("", 1);
+        TwoBox.<String, String>make("", "");
+        TwoBox.<int, int>make(1, 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestIndyErasure.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestIndyErasure.java
+ */
+
+class TestIndyErasure {
+    static class Sup<any X> {
+        @PoolMapping(opcode = Opcodes.ALOAD_1)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        <any Z> X m(X x, Z z) { return x; }
+    }
+
+    static class Sub<Y extends Runnable> extends Sup<Y> {
+
+        @PoolMapping(opcode = Opcodes.GETFIELD, entry = "LTestIndyErasure$Sub$test$1633840230<U/_>;.this$0:LTestIndyErasure$Sub;")
+        @PoolMapping(opcode = Opcodes.ALOAD_2)
+        @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                     entry = "m:(LTestIndyErasure$Sub;Ljava/lang/Object;U/Ljava/lang/Object;)Ljava/lang/Object;::{TestIndyErasure$Sub,(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;,U/_}")
+        <any U> void test(Y y, U u) {
+            Runnable r = m(y, u);
+        }
+
+        void test2(Y y) {
+            Runnable r = m(y, 1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestIndyFactory.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestIndyFactory.java
+ */
+
+class TestIndyFactory {
+
+    static class Box<any T> {
+        T t;
+
+        static <any U> Box<U> make(U u) { return null; }
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_1)
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                     entry = "make:(Z/Ljava/lang/Object;)LTestIndyFactory$Box<Z/_>;::{TestIndyFactory$Box,(Ljava/lang/Object;)LTestIndyFactory$Box;,Z/_}")
+    @PoolMapping(opcode = Opcodes.GETFIELD,
+                     entry = "LTestIndyFactory$Box<Z/_>;.t:Z/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any Z> void testAny(Z z) {
+        Z z2 = Box.make(z).t;
+    }
+
+    <Z> void testNonAny(Z z) {
+        Z z2 = Box.make(z).t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestInheritedAnyMembers.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,87 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestInheritedAnyMembers.java
+ */
+
+class TestInheritedAnyMembers {
+    static abstract class Function<any A, any R> {
+	    A a;
+        abstract R apply(A t);
+    }
+
+    static abstract class UnaryOperator<any T> extends Function<T, T> {
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+        UnaryOperator() { }
+    }
+
+    static abstract class IntFunction<any A> extends Function<A, int> {
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+        IntFunction() { }
+    }
+
+    static abstract class IntIntFunction extends IntFunction<int> {
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL, entry = "LTestInheritedAnyMembers$IntFunction<I>;.<init>:()V")
+        IntIntFunction() { }
+    }
+
+    @PoolMapping(opcode = Opcodes.GETFIELD, entry = "LTestInheritedAnyMembers$UnaryOperator<E/_>;.a:E/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any E> void var_any(UnaryOperator<E> operator) {
+        E e = operator.a;
+    }
+
+    @PoolMapping(opcode = Opcodes.GETFIELD, entry = "LTestInheritedAnyMembers$IntFunction<E/_>;.a:E/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any E> void var_partial(IntFunction<E> function) {
+        E e = function.a;
+    }
+
+    void var_specialized(IntIntFunction function) {
+        int i = function.a;
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_2)
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL, entry = "LTestInheritedAnyMembers$UnaryOperator<E/_>;.apply:(E/Ljava/lang/Object;)E/Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.POP)
+    <any E> void inv_any(UnaryOperator<E> operator, E e) {
+        operator.apply( e );
+    }
+
+    @PoolMapping(opcode = Opcodes.ALOAD_2)
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL, entry = "LTestInheritedAnyMembers$IntFunction<E/_>;.apply:(E/Ljava/lang/Object;)I")
+    <any E> void inv_partial(IntFunction<E> function, E e) {
+        function.apply( e );
+    }
+
+    void inv_specialized(IntIntFunction function, int i) {
+        function.apply( i );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestInner.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestInner.java
+ */
+
+class TestInner {
+
+    static class Box<any T> {
+
+        T t;
+
+        class Inner<any U> {
+
+            U u;
+
+            @PoolMapping(opcode = Opcodes.PUTFIELD,
+                         entry = "LTestInner$Box<T/_>;.LTestInner$Box$Inner<U/_>;.this$0:LTestInner$Box<T/_>;")
+            Inner() { }
+
+            @PoolMapping(opcode = Opcodes.GETFIELD,
+                         entry = "LTestInner$Box<T/_>;.LTestInner$Box$Inner<U/_>;.this$0:LTestInner$Box<T/_>;")
+            @PoolMapping(opcode = Opcodes.GETFIELD,
+                         entry = "LTestInner$Box<T/_>;.t:T/Ljava/lang/Object;")
+            @PoolMapping(opcode = Opcodes.ARETURN,
+                         entry = "T/Ljava/lang/Object;")
+            T getT() { return t; }
+
+            @PoolMapping(opcode = Opcodes.GETFIELD,
+                         entry = "LTestInner$Box<T/_>;.LTestInner$Box$Inner<U/_>;.u:U/Ljava/lang/Object;")
+            @PoolMapping(opcode = Opcodes.ARETURN,
+                         entry = "U/Ljava/lang/Object;")
+            U getU() { return u; }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestInstanceof.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,58 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestInstanceof.java
+ */
+
+class TestInstanceof {
+
+    static class AnyClass<any T> { }
+
+    @PoolMapping(opcode = Opcodes.INSTANCEOF, entry = "Z/java/lang/Object")
+    @PoolMapping(opcode = Opcodes.INSTANCEOF, entry = "[Z/Ljava/lang/Object;")
+    <any Z> void testAny(Object o) {
+        boolean b1 = o instanceof Z;
+        boolean b2 = o instanceof Z[];
+    }
+
+    @PoolMapping(opcode = Opcodes.INSTANCEOF, entry = "LTestInstanceof$AnyClass<Z/_>;")
+    @PoolMapping(opcode = Opcodes.INSTANCEOF, entry = "[LTestInstanceof$AnyClass<Z/_>;")
+    <any Z> void testAnyClass(Object o) {
+        boolean b1 = o instanceof AnyClass<Z>;
+        boolean b2 = o instanceof AnyClass<Z>[];
+    }
+
+    @PoolMapping(opcode = Opcodes.INSTANCEOF, entry = "LTestInstanceof$AnyClass<I>;")
+    @PoolMapping(opcode = Opcodes.INSTANCEOF, entry = "[LTestInstanceof$AnyClass<I>;")
+    <any Z> void testSpecialized(Object o) {
+        boolean b1 = o instanceof AnyClass<int>;
+        boolean b2 = o instanceof AnyClass<int>[];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestLambda.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,78 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestLambda.java
+ */
+
+abstract class TestLambda {
+    interface Function<any A, any R> {
+	    R apply(A a);
+    }
+
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC, entry = "apply:()LTestLambda$Function<Z/_,Z/_>;::{(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,LTestLambda$test$90<Z/_>;.lambda$test$0:(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;}")
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC, entry = "apply:(Z)LTestLambda$Function<Z/_,Z/_>;::{(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,LTestLambda$test$90<Z/_>;.lambda$test$1:(ZZ/Ljava/lang/Object;)Z/Ljava/lang/Object;,(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;}")
+    <any Z> void test(boolean cond) {
+		Function<Z, Z> fzz1 = x -> x;
+		Function<Z, Z> fzz2 = (x) -> { if (cond) { return x; } else { return x; } };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC, entry = "apply:(Z/Ljava/lang/Object;)LTestLambda$Function<Z/_,Z/_>;::{(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,LTestLambda$testCapture$1386255498<Z/_>;.lambda$testCapture$0:(Z/Ljava/lang/Object;Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;}")
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC, entry = "apply:(ZZ/Ljava/lang/Object;)LTestLambda$Function<Z/_,Z/_>;::{(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,LTestLambda$testCapture$1386255498<Z/_>;.lambda$testCapture$1:(ZZ/Ljava/lang/Object;Z/Ljava/lang/Object;)Z/Ljava/lang/Object;,(Z/Ljava/lang/Object;)Z/Ljava/lang/Object;}")
+    <any Z> void testCapture(boolean cond, Z z) {
+		Function<Z, Z> fzz1 = x -> z;
+		Function<Z, Z> fzz2 = (x) -> { if (cond) { return z; } else { return z; } };
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_0)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @TemplateMethod(owner = "TestLambda$test$90", name = "lambda$test$0")
+    Object lambda1(Object o) { return null; }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @TemplateMethod(owner = "TestLambda$test$90", name = "lambda$test$1")
+    Object lambda2(boolean b, Object o) { return null; }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_0)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @TemplateMethod(owner = "TestLambda$testCapture$1386255498", name = "lambda$testCapture$0")
+    Object lambda3(Object z, Object o) { return null; }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @TemplateMethod(owner = "TestLambda$testCapture$1386255498", name = "lambda$testCapture$1")
+    Object lambda4(boolean b, Object z, Object o) { return null; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestLoadAndStore.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,61 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestLoadAndStore.java
+ */
+
+class TestLoadAndStore {
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ASTORE_1)
+    @PoolMapping(opcode= Opcodes.ALOAD_2)
+    @PoolMapping(opcode= Opcodes.ASTORE_2)
+    @PoolMapping(opcode= Opcodes.ALOAD_3)
+    @PoolMapping(opcode= Opcodes.ASTORE_3)
+    @PoolMapping(opcode= Opcodes.ALOAD)
+    @PoolMapping(opcode= Opcodes.ASTORE)
+    @PoolMapping(opcode= Opcodes.ALOAD)
+    @PoolMapping(opcode= Opcodes.ASTORE)
+    static <any T> void test(T t0, T t1, T t2, T t3, T t4) {
+        t0 = t0;
+        t1 = t1;
+        t2 = t2;
+        t3 = t3;
+        t4 = t4;
+    }
+
+    static <T> void testNeg(T t0, T t1, T t2, T t3, T t4) {
+        t0 = t0;
+        t1 = t1;
+        t2 = t2;
+        t3 = t3;
+        t4 = t4;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestNestedGenerics.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,86 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestNestedGenerics.java
+ */
+
+class TestNestedGenerics {
+
+    static class AnyClass<any T> {
+        T t;
+
+        @PoolMapping(opcode = Opcodes.GETFIELD)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        T get() { return t; };
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.GETFIELD)
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any Z> void testFieldAny(AnyClass<AnyClass<Z>> z) {
+        Z z2 = z.t.t;
+    }
+
+    <Z> void testFieldNonAny(AnyClass<AnyClass<Z>> z) {
+        Z z2 = z.t.t;
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any Z> void testMethodAny(AnyClass<AnyClass<Z>> z) {
+        Z z2 = z.get().get();
+    }
+
+    <Z> void testMethodNonAny(AnyClass<AnyClass<Z>> z) {
+        Z z2 = z.get().get();
+    }
+
+    <any Z> void testNewAny() {
+        new AnyClass<AnyClass<Z>>();
+    }
+
+    <Z> void testNewNonAny() {
+        new AnyClass<AnyClass<Z>>();
+    }
+
+    static <any T> void testLocal() {
+         class Local {
+            private T state;
+
+            @PoolMapping(opcode = Opcodes.GETFIELD)
+            @PoolMapping(opcode = Opcodes.ARETURN)
+            @TemplateMethod(owner = "TestNestedGenerics$testLocal$0$1Local")
+            public T get() {
+                return state; // <-- needs a mapping
+            }
+         }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestNew.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,75 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestNew.java
+ */
+
+class TestNew {
+
+    static class AnyClass<any T> {
+        T value;
+
+        @PoolMapping(opcode = Opcodes.GETFIELD)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        T get() { return value; }
+
+        @PoolMapping(opcode = Opcodes.NEW)
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+        @PoolMapping(opcode = Opcodes.GETFIELD)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        T testField() {
+            return new AnyClass<T>().value;
+        }
+
+        @PoolMapping(opcode = Opcodes.NEW)
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+        @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        T testMethod() {
+            return new AnyClass<T>().get();
+        }
+    }
+
+    @PoolMapping(opcode = Opcodes.NEW)
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+    void test1() {
+        new AnyClass<int>();
+    }
+
+    @PoolMapping(opcode = Opcodes.NEW)
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+    <any Z> void test2() {
+        new AnyClass<Z>();
+    }
+
+    <Z> void test3() {
+        new AnyClass<Z>();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestNewArray.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,58 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestNewArray.java
+ */
+
+class TestNewArray {
+
+    static class AnyClass<any T> { }
+
+    @PoolMapping(opcode = Opcodes.ANEWARRAY)
+    @PoolMapping(opcode = Opcodes.MULTIANEWARRAY)
+    <any Z> void testAnyArray() {
+        Z[] z_arr1 = new Z[2];
+        Z[][] z_arr2 = new Z[2][4];
+    }
+
+    @PoolMapping(opcode = Opcodes.ANEWARRAY)
+    @PoolMapping(opcode = Opcodes.MULTIANEWARRAY)
+    <any Z> void testAnyClassArray() {
+        AnyClass<Z>[] z_arr1 = new AnyClass<Z>[2];
+        AnyClass<Z>[][] z_arr2 = new AnyClass<Z>[2][4];
+    }
+
+    @PoolMapping(opcode = Opcodes.ANEWARRAY)
+    @PoolMapping(opcode = Opcodes.MULTIANEWARRAY)
+    <any Z> void testSpecializedArray() {
+        AnyClass<int>[] z_arr1 = new AnyClass<int>[2];
+        AnyClass<int>[][] z_arr2 = new AnyClass<int>[2][4];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestNonSpecializedGenericCall.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestNonSpecializedGenericCall.java
+ */
+
+class TestNonSpecializedGenericCall {
+
+    static class Box<any T> {
+        T t;
+
+        @PoolMapping(opcode = Opcodes.ALOAD_1)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        static <any Z> Z id(Z z) { return z; }
+
+        @PoolMapping(opcode = Opcodes.NEW)
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+        static <any Z> Box<Z> wrap(Z z) { return new Box<>(); }
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.GETFIELD)
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any U> void testAnyId(Box<U> z) {
+        U z2 = Box.id(z).t;
+    }
+
+    <U> void testNonAnyId(Box<U> z) {
+        U z2 = Box.id(z).t;
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.GETFIELD)
+    @PoolMapping(opcode = Opcodes.ASTORE_2)
+    <any U> void testAnyWrap(Box<U> z) {
+        U z2 = Box.wrap(z).t.t;
+    }
+
+    <U> void testNonAnyWrap(Box<U> z) {
+        U z2 = Box.wrap(z).t.t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestNonSpecializedMethod.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,47 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestNonSpecializedMethod.java
+ */
+
+class TestNonSpecializedMethod<any X> {
+
+    @PoolMapping(opcode = Opcodes.ACONST_NULL)
+    @PoolMapping(opcode = Opcodes.ARETURN)
+    <any R> R foo(TestNonSpecializedMethod<R> tr) { return R.default; }
+
+    @PoolMapping(opcode = Opcodes.GETFIELD,
+                 entry = "LTestNonSpecializedMethod<X/_>;.LTestNonSpecializedMethod$test$2036000448<Z/_>;.this$0:LTestNonSpecializedMethod<X/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL,
+                 entry = "LTestNonSpecializedMethod<X/_>;.foo:(LTestNonSpecializedMethod;)Ljava/lang/Object;")
+    <any Z> void test(TestNonSpecializedMethod<Object> t) {
+       foo(t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestPop.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestPop.java
+ */
+
+class TestPop<any T> {
+    T t;
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    T m(T t) { return t; };
+
+    String g(T t) { return ""; };
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.INVOKEVIRTUAL)
+    @PoolMapping(opcode= Opcodes.POP)
+    void test(T t) {
+        m(t);
+    }
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.INVOKEVIRTUAL)
+    void testNeg(T t) {
+        g(t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestRefOnly.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,48 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestRefOnly.java
+ */
+
+class TestRefOnly<any T> {
+    T t;
+
+    //no bytecode mappings here!
+    __WhereRef(T) T m1(
+    T t) { return t; };
+
+    //no bytecode mappings here!
+    __WhereRef(T) void m2(T t) { Foo.g(t); };
+
+
+    static class Foo {
+        static <Z> void g(Z z) { }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestRespecialization.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestRespecialization.java
+ */
+
+class TestRespecialization {
+
+    static class MultiBox<any A, any B, any C, any D, any E> {
+        <any Z> MultiBox<Z, B, C, D, E> withA(Z z) { return null; }
+        <any Z> MultiBox<A, Z, C, D, E> withB(Z z) { return null; }
+        <any Z> MultiBox<A, B, Z, D, E> withC(Z z) { return null; }
+        <any Z> MultiBox<A, B, C, Z, E> withD(Z z) { return null; }
+        <any Z> MultiBox<A, B, C, D, Z> withE(Z z) { return null; }
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withA:(LTestRespecialization$MultiBox<A/_,B/_,C/_,D/_,E/_>;I)LTestRespecialization$MultiBox<I,B/_,C/_,D/_,E/_>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,I}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withB:(LTestRespecialization$MultiBox<I,B/_,C/_,D/_,E/_>;J)LTestRespecialization$MultiBox<I,J,C/_,D/_,E/_>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,J}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withC:(LTestRespecialization$MultiBox<I,J,C/_,D/_,E/_>;F)LTestRespecialization$MultiBox<I,J,F,D/_,E/_>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,F}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withD:(LTestRespecialization$MultiBox<I,J,F,D/_,E/_>;D)LTestRespecialization$MultiBox<I,J,F,D,E/_>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,D}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withE:(LTestRespecialization$MultiBox<I,J,F,D,E/_>;Z)LTestRespecialization$MultiBox<I,J,F,D,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,Z}")
+    <any A, any B, any C, any D, any E> void testForward(MultiBox<A, B, C, D, E> mb_abcde) {
+        MultiBox<int, long, float, double, boolean> mb_ilfdb =
+                mb_abcde.withA(0)
+                        .withB(0L)
+                        .withC(0f)
+                        .withD(0d)
+                        .withE(false);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withE:(LTestRespecialization$MultiBox<A/_,B/_,C/_,D/_,E/_>;Z)LTestRespecialization$MultiBox<A/_,B/_,C/_,D/_,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,Z}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withD:(LTestRespecialization$MultiBox<A/_,B/_,C/_,D/_,Z>;D)LTestRespecialization$MultiBox<A/_,B/_,C/_,D,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,D}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withC:(LTestRespecialization$MultiBox<A/_,B/_,C/_,D,Z>;F)LTestRespecialization$MultiBox<A/_,B/_,F,D,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,F}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withB:(LTestRespecialization$MultiBox<A/_,B/_,F,D,Z>;J)LTestRespecialization$MultiBox<A/_,J,F,D,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,J}")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withA:(LTestRespecialization$MultiBox<A/_,J,F,D,Z>;I)LTestRespecialization$MultiBox<I,J,F,D,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,I}")
+    <any A, any B, any C, any D, any E> void testBackwards(MultiBox<A, B, C, D, E> mb_abcde) {
+        MultiBox<int, long, float, double, boolean> mb_ilfdb =
+                mb_abcde.withE(false)
+                        .withD(0d)
+                        .withC(0f)
+                        .withB(0L)
+                        .withA(0);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withA:(LTestRespecialization$MultiBox<A/_,B/_,C/_,D/_,E/_>;I)LTestRespecialization$MultiBox<I,B/_,C/_,D/_,E/_>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,I}")
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL,
+                 entry = "LTestRespecialization$MultiBox<I,B/_,C/_,D/_,E/_>;.withB:(Ljava/lang/Object;)LTestRespecialization$MultiBox<I,_,C/_,D/_,E/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withC:(LTestRespecialization$MultiBox<I,_,C/_,D/_,E/_>;F)LTestRespecialization$MultiBox<I,_,F,D/_,E/_>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,F}")
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL,
+                 entry = "LTestRespecialization$MultiBox<I,_,F,D/_,E/_>;.withD:(Ljava/lang/Object;)LTestRespecialization$MultiBox<I,_,F,_,E/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKEDYNAMIC,
+                 entry = "withE:(LTestRespecialization$MultiBox<I,_,F,_,E/_>;Z)LTestRespecialization$MultiBox<I,_,F,_,Z>;::{TestRespecialization$MultiBox,(Ljava/lang/Object;)LTestRespecialization$MultiBox;,Z}")
+    <any A, any B, any C, any D, any E> void testHoles(MultiBox<A, B, C, D, E> mb_abcde) {
+        MultiBox<int, Long, float, Double, boolean> mb_iLfDb =
+                mb_abcde.withA(0)
+                        .withB(new Long(0))
+                        .withC(0f)
+                        .withD(new Double(0))
+                        .withE(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestSuper.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,75 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestSuper.java
+ */
+
+class TestSuper {
+    static class Sup<any T> {
+        void test(T t) { }
+    }
+
+    static class SubInt extends Sup<int> {
+
+        @PoolMapping(opcode= Opcodes.INVOKESPECIAL, entry = "LTestSuper$Sup<I>;.<init>:()V")
+        SubInt() { }
+
+        @PoolMapping(opcode= Opcodes.INVOKESPECIAL, entry = "LTestSuper$Sup<I>;.test:(I)V")
+        void test() {
+            super.test(1);
+        }
+    }
+
+    static class SubAny<any Z> extends Sup<Z> {
+
+        @PoolMapping(opcode= Opcodes.INVOKESPECIAL)
+        SubAny() {
+            super();
+        }
+
+        @PoolMapping(opcode= Opcodes.ALOAD_1)
+        @PoolMapping(opcode= Opcodes.INVOKESPECIAL)
+        void test(Z z) {
+            super.test(z);
+        }
+    }
+
+    static class SubNonAny<Z> extends Sup<Z> {
+        void test(Z z) {
+            super.test(z);
+        }
+    }
+
+    static class NestedSub<any Z> extends Sup<NestedSub<Z>> {
+        void test() {
+            super.test(null);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestSyntheticCast.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,121 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestSyntheticCast.java
+ */
+
+class TestSyntheticCast<any X> {
+    static class Box<any T> {
+        T t;
+
+        @PoolMapping(opcode = Opcodes.GETFIELD)
+        @PoolMapping(opcode = Opcodes.ARETURN)
+        T get() { return t; }
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    <any Z> void testAnyField(Box<Box<Z>> bbz) {
+        Box<Z> bz = bbz.t;
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    <any Z> void testAnyCall(Box<Box<Z>> bbz) {
+        Box<Z> bz = bbz.get();
+    }
+
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    <any Z> void testAnyAssign(Box<Box<Z>> bbz, Box<Z> bz) {
+        Box<Z> z = (bbz.t = bz);
+    }
+
+    <Z> void testNonAnyField(Box<Box<Z>> bbz) {
+        Box<Z> bz = bbz.t;
+    }
+
+    <Z> void testNonAnyCall(Box<Box<Z>> bbz) {
+        Box<Z> bz = bbz.get();
+    }
+
+    <Z> void testNonAnyAssign(Box<Box<Z>> bbz, Box<Z> bz) {
+        Box<Z> z = (bbz.t = bz);
+    }
+
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+    @PoolMapping(opcode = Opcodes.NEW)
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL)
+    @PoolMapping(opcode = Opcodes.CHECKCAST)
+    @PoolMapping(opcode = Opcodes.INVOKESPECIAL)
+    void testMethodContext(X[] zarr) {
+		X[] arr = id(zarr);
+		g(id(zarr));
+		new ArrayHolder<X>(id(zarr));
+    }
+
+	void g(X[] arr) { }
+
+    <Z> Z id(Z z) { return z; }
+
+    static class ArrayHolder<any X> {
+		ArrayHolder(X[] x) { }
+    }
+
+    interface I1<any X> { }
+    interface I2<any X> { }
+
+    static class Sup<any X, K extends I1<X>, Z extends Sup<X, K, Z>> {
+        K m(Z t) { return null; }
+    }
+
+    static class Sub<any Y, K extends I2<Y> & I1<Y>> extends Sup<Y, K, Sub<Y, K>> {
+
+        @PoolMapping(opcode = Opcodes.INVOKESPECIAL,
+                     entry = "LTestSyntheticCast$Sup<Y/_,_,_>;.<init>:()V")
+        Sub() { }
+
+        @PoolMapping(opcode = Opcodes.CHECKCAST) //arg
+        @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL,
+                     entry = "LTestSyntheticCast$Sub<TY;TK;>;::(LTestSyntheticCast$Sub<TY;TK;>;)LTestSyntheticCast$I2<TY;>;") //bridge call
+        @PoolMapping(opcode = Opcodes.CHECKCAST) //ret
+        @TemplateMethod(name = "m", sig = "(LTestSyntheticCast$Sup;)") //this is the bridge method
+        K m(Sub<Y, K> s) { return null; }
+    }
+
+    @PoolMapping(opcode = Opcodes.GETFIELD, entry = "LTestSyntheticCast<X/_>;.LTestSyntheticCast$testDoubleCast$2042508302<X/_,Y/_>;.this$0:LTestSyntheticCast<X/_>;")
+    @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL, entry = "LTestSyntheticCast<X/_>;.id:(Ljava/lang/Object;)Ljava/lang/Object;")
+    @PoolMapping(opcode = Opcodes.CHECKCAST, entry = "LTestSyntheticCast$Box<Y/_>;")
+    @PoolMapping(opcode = Opcodes.CHECKCAST, entry = "LTestSyntheticCast$Box<Y/_>;")
+    <any X, any Y> void testDoubleCast(Box<X> b) {
+       Box<Y> by = (Box<Y>)id(b);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestValOnly.java	Fri Apr 15 17:24:24 2016 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check that generic pool entries are emitted for certain type-dependent opcodes
+ * @library ../
+ * @build PoolMappingHarness
+ * @run main PoolMappingHarness TestValOnly.java
+ */
+
+class TestValOnly<any T> {
+    T t;
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.ARETURN)
+    @TemplateMethod(name = "template$m1")
+    __WhereVal(T) T m1(
+    T t) { return t; };
+
+    @PoolMapping(opcode= Opcodes.ALOAD_1)
+    @PoolMapping(opcode= Opcodes.INVOKEDYNAMIC)
+    @TemplateMethod(name = "template$m2")
+    __WhereVal(T) void m2(T t) { Foo.g(t); };
+
+    @TemplateMethod(name = "template$m3")
+    @PoolMapping(opcode= Opcodes.INVOKEVIRTUAL, entry = "LTestValOnly$Box<T/_>;.get:()T/Ljava/lang/Object;")
+    @PoolMapping(opcode= Opcodes.ASTORE_2)
+    __WhereVal(T) void m3(Box<T> bt) {
+        T t = bt.get();
+    }
+
+    static class Foo {
+        static <any Z> void g(Z z) { }
+    }
+
+    static class Box<any X> {
+        X x;
+
+        @PoolMapping(opcode= Opcodes.GETFIELD)
+        @PoolMapping(opcode= Opcodes.ARETURN)
+        X get() { return x; }
+    }
+}