changeset 452:58550230addb

rebase to current hsx/hotspot-comp; temporarily import tl fixes
author jrose
date Fri, 13 Sep 2013 22:49:37 -0700
parents 1a78d97d1283
children 383cbcabff6f
files meth-7177472.patch meth-aclone-8001105.patch meth-arity-8019417.patch meth-doc-8014634.patch meth-info-8008688.patch meth.patch old/meth-7177472.patch series tl-fixes.1.patch tl-fixes.2.patch tl-fixes.3.patch
diffstat 11 files changed, 2589 insertions(+), 3379 deletions(-) [+]
line wrap: on
line diff
--- a/meth-7177472.patch	Tue Aug 13 12:54:34 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,319 +0,0 @@
-7177472: JSR292: MethodType interning penalizes scalability
-Summary: Use ConcurrentHashMap instead of regular HashMap.
-Reviewed-by: ?
-Contributed-by: aleksey.shipilev@oracle.com
-
-diff --git a/src/share/classes/java/lang/invoke/MethodType.java b/src/share/classes/java/lang/invoke/MethodType.java
---- a/src/share/classes/java/lang/invoke/MethodType.java
-+++ b/src/share/classes/java/lang/invoke/MethodType.java
-@@ -28,11 +28,13 @@
- import sun.invoke.util.Wrapper;
- import java.lang.ref.WeakReference;
- import java.lang.ref.ReferenceQueue;
-+import java.util.concurrent.ConcurrentHashMap;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.List;
- import sun.invoke.util.BytecodeDescriptor;
- import static java.lang.invoke.MethodHandleStatics.*;
-+import java.lang.ref.Reference;
- import sun.invoke.util.VerifyType;
- 
- /**
-@@ -990,84 +992,17 @@
-      * @see         java.util.HashSet
-      * @see         java.util.WeakHashMap
-      * @see         java.lang.ref.WeakReference
-+     * @see         concurrent.ConcurrentHashMap
-      */
-     private static class WeakInternSet {
--        // The default initial capacity -- MUST be a power of two.
--        private static final int DEFAULT_INITIAL_CAPACITY = 16;
--
--        // The maximum capacity, used if a higher value is implicitly specified
--        // by either of the constructors with arguments.
--        // MUST be a power of two <= 1<<30.
--        private static final int MAXIMUM_CAPACITY = 1 << 30;
--
--        // The load factor used when none specified in constructor.
--        private static final float DEFAULT_LOAD_FACTOR = 0.75f;
--
--        // The table, resized as necessary. Length MUST Always be a power of two.
--        private Entry[] table;
--
--        // The number of entries contained in this set.
--        private int size;
--
--        // The next size value at which to resize (capacity * load factor).
--        private int threshold;
--
--        // The load factor for the hash table.
--        private final float loadFactor;
--
--        // Reference queue for cleared WeakEntries
-+        private final ConcurrentHashMap<Entry, Entry> map = new ConcurrentHashMap<Entry, Entry>();
-         private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
- 
--        private Entry[] newTable(int n) {
--            return new Entry[n];
--        }
--
-         /**
-          * Constructs a new, empty <tt>WeakInternSet</tt> with the default initial
--         * capacity (16) and load factor (0.75).
-+         * capacity and load factor, inherited from {@link ConcurrentHashMap}.
-          */
-         WeakInternSet() {
--            this.loadFactor = DEFAULT_LOAD_FACTOR;
--            threshold = DEFAULT_INITIAL_CAPACITY;
--            table = newTable(DEFAULT_INITIAL_CAPACITY);
--        }
--
--        /**
--         * Applies a supplemental hash function to a given hashCode, which
--         * defends against poor quality hash functions.  This is critical
--         * because hashing uses power-of-two length hash tables, that
--         * otherwise encounter collisions for hashCodes that do not differ
--         * in lower bits.
--         * @param h preliminary hash code value
--         * @return supplemental hash code value
--         */
--        private static int hash(int h) {
--            // This function ensures that hashCodes that differ only by
--            // constant multiples at each bit position have a bounded
--            // number of collisions (approximately 8 at default load factor).
--            h ^= (h >>> 20) ^ (h >>> 12);
--            return h ^ (h >>> 7) ^ (h >>> 4);
--        }
--
--        /**
--         * Checks for equality of non-null reference x and possibly-null y.  By
--         * default uses Object.equals.
--         * @param x first object to compare
--         * @param y second object to compare
--         * @return <tt>true</tt> if objects are equal
--         */
--        private static boolean eq(Object x, Object y) {
--            return x == y || x.equals(y);
--        }
--
--        /**
--         * Returns index for hash code h.
--         * @param h      raw hash code
--         * @param length length of table (power of 2)
--         * @return index in table
--         */
--        private static int indexFor(int h, int length) {
--            return h & (length-1);
-         }
- 
-         /**
-@@ -1075,39 +1010,11 @@
-          */
-         private void expungeStaleEntries() {
-             for (Object x; (x = queue.poll()) != null; ) {
--                synchronized (queue) {
--                    Entry entry = (Entry) x;
--                    int i = indexFor(entry.hash, table.length);
--                    Entry prev = table[i];
--                    Entry p = prev;
--                    while (p != null) {
--                        Entry next = p.next;
--                        if (p == entry) {
--                            if (prev == entry)
--                                table[i] = next;
--                            else
--                                prev.next = next;
--                            entry.next = null;
--                            size--;
--                            break;
--                        }
--                        prev = p;
--                        p = next;
--                    }
--                }
-+                map.remove((Entry) x);
-             }
-         }
- 
-         /**
--         * Returns the table after first expunging stale entries.
--         * @return an expunged hash table
--         */
--        private Entry[] getTable() {
--            expungeStaleEntries();
--            return table;
--        }
--
--        /**
-          * Returns the entry to which the specified value is mapped,
-          * or {@code null} if this set contains no entry for the value.
-          *
-@@ -1119,16 +1026,15 @@
-          * @param value value to search for in set
-          * @return interned value if in set, otherwise <tt>null</tt>
-          */
--        synchronized MethodType get(MethodType value) {
--            int h = hash(value.hashCode());
--            Entry[] tab = getTable();
--            int index = indexFor(h, tab.length);
--            Entry e = tab[index];
--            MethodType g;
--            while (e != null) {
--                if (e.hash == h && eq(value, g = e.get()))
--                    return g;
--                e = e.next;
-+        MethodType get(MethodType elem) {
-+            expungeStaleEntries();
-+
-+            Entry value = map.get(new Entry(elem));
-+            if (value != null) {
-+                MethodType res = value.get();
-+                if (res != null) {
-+                    return res;
-+                }
-             }
-             return null;
-         }
-@@ -1142,86 +1048,20 @@
-          * @return the previous entry associated with <tt>value</tt>, or
-          *         <tt>value</tt> if there was no previous entry found
-          */
--        synchronized MethodType add(MethodType value) {
--            int h = hash(value.hashCode());
--            Entry[] tab = getTable();
--            int i = indexFor(h, tab.length);
--            MethodType g;
--            for (Entry e = tab[i]; e != null; e = e.next) {
--                if (h == e.hash && eq(value, g = e.get())) {
--                    return g;
--                }
--            }
--            Entry e = tab[i];
--            tab[i] = new Entry(value, queue, h, e);
--            if (++size >= threshold)
--                resize(tab.length * 2);
--            return value;
--        }
--
--        /**
--         * Rehashes the contents of this set into a new array with a
--         * larger capacity.  This method is called automatically when the
--         * number of keys in this set reaches its threshold.
--         *
--         * If current capacity is MAXIMUM_CAPACITY, this method does not
--         * resize the set, but sets threshold to Integer.MAX_VALUE.
--         * This has the effect of preventing future calls.
--         *
--         * @param newCapacity the new capacity, MUST be a power of two;
--         *        must be greater than current capacity unless current
--         *        capacity is MAXIMUM_CAPACITY (in which case value
--         *        is irrelevant)
--         */
--        private void resize(int newCapacity) {
--            Entry[] oldTable = getTable();
--            int oldCapacity = oldTable.length;
--            if (oldCapacity == MAXIMUM_CAPACITY) {
--                threshold = Integer.MAX_VALUE;
--                return;
--            }
--
--            Entry[] newTable = newTable(newCapacity);
--            transfer(oldTable, newTable);
--            table = newTable;
--
--            /*
--             * If ignoring null elements and processing ref queue caused massive
--             * shrinkage, then restore old table.  This should be rare, but avoids
--             * unbounded expansion of garbage-filled tables.
--             */
--            if (size >= threshold / 2) {
--                threshold = (int)(newCapacity * loadFactor);
--            } else {
-+        MethodType add(MethodType elem) {
-+            // Playing double race here, and so spinloop is required.
-+            // First race is with two concurrent updaters.
-+            // Second race is with GC purging weak ref under our feet.
-+            // Hopefully, we always end up with single spin.
-+            MethodType interned;
-+            do {
-                 expungeStaleEntries();
--                transfer(newTable, oldTable);
--                table = oldTable;
--            }
--        }
--
--        /**
--         * Transfers all entries from src to dest tables
--         * @param src  original table
--         * @param dest new table
--         */
--        private void transfer(Entry[] src, Entry[] dest) {
--            for (int j = 0; j < src.length; ++j) {
--                Entry e = src[j];
--                src[j] = null;
--                while (e != null) {
--                    Entry next = e.next;
--                    MethodType key = e.get();
--                    if (key == null) {
--                        e.next = null;  // Help GC
--                        size--;
--                    } else {
--                        int i = indexFor(e.hash, dest.length);
--                        e.next = dest[i];
--                        dest[i] = e;
--                    }
--                    e = next;
--                }
--            }
-+                Entry e = new Entry(elem, queue);
-+                Entry exist = map.putIfAbsent(e, e);
-+                Entry winner = (exist != null ? exist : e);
-+                interned = winner.get();
-+            } while (interned == null);
-+            return interned;
-         }
- 
-         /**
-@@ -1230,18 +1070,36 @@
-          */
-         private static class Entry extends WeakReference<MethodType> {
-             final int hash;
--            Entry next;
- 
-             /**
-              * Creates new entry.
-              */
-+            Entry(MethodType key) {
-+                super(key);
-+                hash = key.hashCode();
-+            }
-+
-             Entry(MethodType key,
--                  ReferenceQueue<Object> queue,
--                  int hash, Entry next) {
-+                  ReferenceQueue<Object> queue) {
-                 super(key, queue);
--                this.hash  = hash;
--                this.next  = next;
-+                hash = key.hashCode();
-             }
-+
-+            @Override
-+            public boolean equals(Object obj) {
-+                if ((obj != null) && (obj instanceof Entry)) {
-+                    Object that = ((Entry) obj).get();
-+                    Object mine = get();
-+                    return (that == null || mine == null) ? (this == obj) : mine.equals(that);
-+                }
-+                return false;
-+            }
-+
-+            @Override
-+            public int hashCode() {
-+                return hash;
-+            }
-+
-         }
-     }
- }
--- a/meth-aclone-8001105.patch	Tue Aug 13 12:54:34 2013 -0700
+++ b/meth-aclone-8001105.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -4,7 +4,7 @@
 diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
 --- a/src/share/classes/java/lang/invoke/MethodHandles.java
 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java
-@@ -1126,6 +1126,13 @@
+@@ -1206,6 +1206,13 @@
              int allowedModes = this.allowedModes;
              if (allowedModes == TRUSTED)  return;
              int mods = m.getModifiers();
@@ -70,7 +70,7 @@
          if (param.isInterface() && param.isAssignableFrom(List.class))
              return Arrays.asList("#"+nextArg());
          if (param.isInterface() || param.isAssignableFrom(String.class))
-@@ -582,6 +606,13 @@
+@@ -590,6 +614,13 @@
          testFindVirtual(SubExample.class,         Example.class, void.class, "Sub/pkg_v0");
          testFindVirtual(Example.class,         IntExample.class, void.class, "v0");
          testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0");
@@ -84,7 +84,7 @@
      }
  
      void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
-@@ -596,6 +627,9 @@
+@@ -604,6 +635,9 @@
      void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
          testFindVirtual(true, lookup, rcvc, defc, ret, name, params);
      }
@@ -94,7 +94,7 @@
      void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
          countTest(positive);
          String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
-@@ -635,8 +669,21 @@
+@@ -643,8 +677,21 @@
          Object[] argsWithSelf = randomArgs(paramsWithSelf);
          if (selfc.isAssignableFrom(rcvc) && rcvc != selfc)  argsWithSelf[0] = randomArg(rcvc);
          printCalled(target, name, argsWithSelf);
--- a/meth-arity-8019417.patch	Tue Aug 13 12:54:34 2013 -0700
+++ b/meth-arity-8019417.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -2,38 +2,10 @@
 Summary: clarification of erroneous reading of spec. that led to 7194534
 Reviewed-by: ?
 
-The specification for MethodHandle guarantees that each method handle has a method called invokeExact (and also invoke):
- * A method handle contains a pair of special invoker methods
- * called {@link #invokeExact invokeExact} and {@link #invoke invoke}.
-
-Because of JVM limits on the arity of methods, any non-static method can take at most 254 arguments, for total argument count (including receiver) of 255. The limit is lower if there are doubles or longs.
-
-Therefore, a method handle's invokeExact method, and hence its type, cannot have an arity larger than 254.
-
-It is therefore impossible to:
-
-* lookup (reify as a method handle) a static method with arity 255
-* lookup (reify as a method handle) a non-static method or constructor with arity 254
-* create a dropArguments or permuteArguments transform which increases the resulting arity to 255 or more
-* create a collector transform which collects zero arguments and increases the resulting arity to 255 or more
-* request an asType or explicitCastArguments conversion of a method handle to a type of arity 255
-* create an exactInvoker or generic invoker for method handles with arity 254
-* create a spreadInvoker for method handles with arity 254 which spreads less than two arguments
-
-All of these attempts throw (or should throw) IllegalArgumentException.
-
-The mentioned limits decrease if longs or doubles are present, because longs or doubles count (relative to the JVM limit of 255) as two argument slots.
-
-For example, since MethodHandles.exactInvoker produces a method handle which invokes its first argument, it follows that the exact invoker's argument can have an arity of no more than 253. I.e., you cannot make an exactInvoker (or generic invoker) for a method handle type with a maximal arity of 254.
-
-It is theoretically possible to delay the throw by creating a "dummy" MH that refuses its inputs, but the 292 API generally has a fail-fast design in such corner cases. For example, an asType that requests an impossible conversion will throw WrongMethodTypeException, rather than deferring to a later invocation of the broken method handle.
-
-The preceding points are not changes to the original JSR 292 specification, but rather necessary implications of that specification, when combined with the basic limitation of JVM methods to receive at most 255 arguments.  Therefore, this bug calls for an editorial change to the javadoc, rather than a change to the specification.  It may suggest additional compliance tests, but does not require or allow behavior inconsistent with the original specification.
-
 diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java
 --- a/src/share/classes/java/lang/invoke/MethodHandle.java
 +++ b/src/share/classes/java/lang/invoke/MethodHandle.java
-@@ -392,16 +392,32 @@
+@@ -392,7 +392,7 @@
   * Java types.
   * <ul>
   * <li>Method types range over all possible arities,
@@ -42,10 +14,7 @@
   * Generics are not variadic, and so cannot represent this.</li>
   * <li>Method types can specify arguments of primitive types,
   * which Java generic types cannot range over.</li>
-  * <li>Higher order functions over method handles (combinators) are
-- * often generic across a wide range of function types, including
-+ * often generic across a wide range of function types, includingf
-  * those of multiple arities.  It is impossible to represent such
+@@ -402,6 +402,22 @@
   * genericity with a Java type parameter.</li>
   * </ul>
   *
@@ -55,10 +24,10 @@
 + * in certain cases:
 + * <ul>
 + * <li>A {@code long} or {@code double} argument counts (for purposes of arity limits) as two argument slots.
-+ * <li>A non-static method consumes an extra argument for the &ldquo;receiver&rldquo; object on which the method is called.
++ * <li>A non-static method consumes an extra argument for the object on which the method is called.
 + * <li>A constructor consumes an extra argument for the object which is being constructed.
 + * <li>Since a method handle&rsquo;s {@code invoke} method (or other signature-polymorphic method) is non-virtual,
-+ *     it consumes an extra argument for the method handle itself, in addition to any &ldquo;receiver&rldquo; object.
++ *     it consumes an extra argument for the method handle itself, in addition to any non-virtual receiver object.
 + * </ul>
 + * These limits imply that certain method handles cannot be created, solely because of the JVM limit on stacked arguments.
 + * For example, if a static JVM method accepts exactly 255 arguments, a method handle cannot be created for it.
@@ -68,10 +37,37 @@
   * @see MethodType
   * @see MethodHandles
   * @author John Rose, JSR 292 EG
+@@ -815,10 +831,12 @@
+      * @return a new method handle which spreads its final array argument,
+      *         before calling the original method handle
+      * @throws NullPointerException if {@code arrayType} is a null reference
+-     * @throws IllegalArgumentException if {@code arrayType} is not an array type
+-     * @throws IllegalArgumentException if target does not have at least
++     * @throws IllegalArgumentException if {@code arrayType} is not an array type,
++     *         or if target does not have at least
+      *         {@code arrayLength} parameter types,
+-     *         or if {@code arrayLength} is negative
++     *         or if {@code arrayLength} is negative,
++     *         or if the resulting method handle's type would have
++     *         <a href="MethodHandle.html#maxarity">too many parameters</a>
+      * @throws WrongMethodTypeException if the implied {@code asType} call fails
+      * @see #asCollector
+      */
+@@ -931,7 +949,9 @@
+      * @throws NullPointerException if {@code arrayType} is a null reference
+      * @throws IllegalArgumentException if {@code arrayType} is not an array type
+      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
+-     *         or {@code arrayLength} is not a legal array size
++     *         or {@code arrayLength} is not a legal array size,
++     *         or the resulting method handle's type would have
++     *         <a href="MethodHandle.html#maxarity">too many parameters</a>
+      * @throws WrongMethodTypeException if the implied {@code asType} call fails
+      * @see #asSpreader
+      * @see #asVarargsCollector
 diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
 --- a/src/share/classes/java/lang/invoke/MethodHandles.java
 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java
-@@ -242,6 +242,10 @@
+@@ -244,6 +244,10 @@
       * on various grounds (<a href="#secmgr">see below</a>).
       * By contrast, the {@code ldc} instruction is not subject to
       * security manager checks.
@@ -82,6 +78,56 @@
       * </ul>
       *
       * <h1><a name="access"></a>Access checking</h1>
+@@ -1445,7 +1449,9 @@
+      * @return a method handle suitable for invoking any method handle of the given type
+      * @throws NullPointerException if {@code type} is null
+      * @throws IllegalArgumentException if {@code leadingArgCount} is not in
+-     *                  the range from 0 to {@code type.parameterCount()} inclusive
++     *                  the range from 0 to {@code type.parameterCount()} inclusive,
++     *                  or if the resulting method handle's type would have
++     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+      */
+     static public
+     MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
+@@ -1488,6 +1494,8 @@
+      * This method throws no reflective or security exceptions.
+      * @param type the desired target type
+      * @return a method handle suitable for invoking any method handle of the given type
++     * @throws IllegalArgumentException if the resulting method handle's type would have
++     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+      */
+     static public
+     MethodHandle exactInvoker(MethodType type) {
+@@ -1521,6 +1529,8 @@
+      * This method throws no reflective or security exceptions.
+      * @param type the desired target type
+      * @return a method handle suitable for invoking any method handle convertible to the given type
++     * @throws IllegalArgumentException if the resulting method handle's type would have
++     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+      */
+     static public
+     MethodHandle invoker(MethodType type) {
+@@ -1889,7 +1899,8 @@
+      *                              or if the {@code valueTypes} array or any of its elements is null
+      * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
+      *                  or if {@code pos} is negative or greater than the arity of the target,
+-     *                  or if the new method handle's type would have too many parameters
++     *                  or if the new method handle's type would have
++     *                  <a href="MethodHandle.html#maxarity">too many parameters</a>
+      */
+     public static
+     MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
+@@ -1957,7 +1968,9 @@
+      *                              or if the {@code filters} array is null
+      * @throws IllegalArgumentException if a non-null element of {@code filters}
+      *          does not match a corresponding argument type of target as described above,
+-     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()}
++     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
++     *          or if the resulting method handle's type would have
++     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
+      */
+     public static
+     MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
 diff --git a/test/java/lang/invoke/BigArityTest.java b/test/java/lang/invoke/BigArityTest.java
 --- a/test/java/lang/invoke/BigArityTest.java
 +++ b/test/java/lang/invoke/BigArityTest.java
@@ -198,7 +244,55 @@
              else
                  r = smh.invoke(tail);
              assertEquals(r0, r);
-@@ -292,7 +382,7 @@
+@@ -235,21 +325,41 @@
+             MethodHandle mh_VA = mh.asSpreader(cls, arity);
+             assert(mh_VA.type().parameterType(0) == cls);
+             testArities(cls, arity, iterations, verbose, mh, mh_VA);
++            // mh_CA will collect arguments of a particular type and pass them to mh_VA
++            MethodHandle mh_CA = mh_VA.asCollector(cls, arity);
++            MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity);
++            assert(mh_CA.type().equals(mh.type()));
++            assert(mh_VA2.type().equals(mh_VA.type()));
+             if (cls != Object[].class) {
+-                // mh_CA will collect arguments of a particular type and pass them to mh_VA
+-                MethodHandle mh_CA = mh_VA.asCollector(cls, arity);
+-                MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity);
+                 try {
+                     mh_VA2.invokeWithArguments(new Object[arity]);
+                     throw new AssertionError("should not reach");
+                 } catch (ClassCastException | WrongMethodTypeException ex) {
+                 }
+-                assert(mh_CA.type().equals(mh.type()));
+-                assert(mh_VA2.type().equals(mh_VA.type()));
+-                testArities(cls, arity, iterations, false, mh_CA, mh_VA2);
+             }
++            int iterations_VA = iterations / 100;
++            testArities(cls, arity, iterations_VA, false, mh_CA, mh_VA2);
+         }
+     }
++ 
++   /**
++     * Tests calls to {@link BigArityTest#hashArguments hashArguments} as related to a single given arity N.
++     * Applies the given {@code mh} to a set of N integer arguments, checking the answer.
++     * Also applies the varargs variation {@code mh_VA} to an array of type C[] (given by {@code cls}).
++     * Test steps:
++     * <ul>
++     * <li>mh_VA.invokeExact(new C[]{ arg, ... })</li>
++     * <li>mh.invokeWithArguments((Object[]) new C[]{ arg, ... })</li>
++     * <li>exactInvoker(mh.type()).invokeWithArguments(new Object[]{ mh, arg, ... })</li>
++     * <li>invoker(mh.type()).invokeWithArguments(new Object[]{ mh, arg, ... })</li>
++     * </ul>
++     * @param cls     array type for varargs call (one of Object[], Number[], Integer[], Comparable[])
++     * @param arity   N, the number of arguments to {@code mh} and length of its varargs array, in [0..255]
++     * @param iterations  number of times to repeat each test step (at least 4)
++     * @param verbose are we printing extra output?
++     * @param mh      a fixed-arity version of {@code hashArguments}
++     * @param mh_VA   a variable-arity version of {@code hashArguments}, accepting the given array type {@code cls}
++     */
+     private void testArities(Class<? extends Object[]> cls,
+                              int arity,
+                              int iterations,
+@@ -292,7 +402,7 @@
              if (cls == Object[].class)
                  r = mh_VA.invokeExact(args);
              else if (cls == Integer[].class)
@@ -207,7 +301,43 @@
              else
                  r = mh_VA.invoke(args);
              assertEquals(r0, r);
-@@ -648,7 +738,6 @@
+@@ -392,10 +502,16 @@
+     a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
+     a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
+     // </editor-fold>
+-    a[0xF8], a[0xF9], a[0xFA], a[0xFB]);
++    a[0xF8], a[0xF9], a[0xFA], a[0xFB]); // hashArguments_252
+         assertEquals(r0, r);
+         MethodType mt = MethodType.genericMethodType(ARITY);
+         MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
++        test252(mh, a, r0);
++        MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
++        test252(mh_CA, a, r0);
++    }
++    public void test252(MethodHandle mh, Object[] a, Object r0) throws Throwable {
++        Object r;
+         r = mh.invokeExact(
+     // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
+     a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
+@@ -599,10 +715,16 @@
+     a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
+     a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
+     // </editor-fold>
+-    a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
++    a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); // hashArguments_253
+         assertEquals(r0, r);
+         MethodType mt = MethodType.genericMethodType(ARITY);
+         MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
++        test253(mh, a, r0);
++        MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
++        test253(mh_CA, a, r0);
++    }
++    public void test253(MethodHandle mh, Object[] a, Object r0) throws Throwable {
++        Object r;
+         r = mh.invokeExact(
+     // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
+     a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
+@@ -648,7 +770,6 @@
      // </editor-fold>
      a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
          assertEquals(r0, r);
@@ -215,7 +345,7 @@
          r = ximh.invokeWithArguments(cat(mh,a));
          assertEquals(r0, r);
          MethodHandle gimh = MethodHandles.invoker(mh.type());
-@@ -674,7 +763,6 @@
+@@ -674,7 +795,6 @@
      // </editor-fold>
      a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
          assertEquals(r0, r);
@@ -223,7 +353,25 @@
          r = gimh.invokeWithArguments(cat(mh,a));
          assertEquals(r0, r);
          mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class));
-@@ -833,7 +921,6 @@
+@@ -808,10 +928,16 @@
+     a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
+     a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
+     // </editor-fold>
+-    a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]);
++    a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); // hashArguments_254
+         assertEquals(r0, r);
+         MethodType mt = MethodType.genericMethodType(ARITY);
+         MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
++        test254(mh, a, r0);
++        MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
++        test254(mh_CA, a, r0);
++    }
++    public void test254(MethodHandle mh, Object[] a, Object r0) throws Throwable {
++        Object r;
+         r = mh.invokeExact(
+     // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
+     a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
+@@ -833,7 +959,6 @@
      // </editor-fold>
      a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]);
          assertEquals(r0, r);
@@ -231,3 +379,12 @@
          r = mh.invokeWithArguments(a);
          assertEquals(r0, r);
          try {
+@@ -998,7 +1123,7 @@
+     a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF],
+     a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7],
+     // </editor-fold>
+-    a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]);
++    a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); // hashArguments_255
+         assertEquals(r0, r);
+         MethodType mt = MethodType.genericMethodType(ARITY);
+         MethodHandle mh;
--- a/meth-doc-8014634.patch	Tue Aug 13 12:54:34 2013 -0700
+++ b/meth-doc-8014634.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -1,522 +1,2 @@
 8014634: JSR 292 javadoc needs cleanups and clarifications
 
-diff --git a/src/share/classes/java/lang/invoke/LambdaMetafactory.java b/src/share/classes/java/lang/invoke/LambdaMetafactory.java
---- a/src/share/classes/java/lang/invoke/LambdaMetafactory.java
-+++ b/src/share/classes/java/lang/invoke/LambdaMetafactory.java
-@@ -111,7 +111,7 @@
-  * done on return type, while a strict version is applied to arguments.
-  *
-  * <p>A type Q is considered adaptable to S as follows:
-- * <table>
-+ * <table summary="adaptable types">
-  *     <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
-  *     <tr>
-  *         <td>Primitive</td><td>Primitive</td>
-@@ -174,7 +174,7 @@
-      * @param instantiatedMethodType The signature of the primary functional interface method after type variables
-      *                               are substituted with their instantiation from the capture site
-      * @return a CallSite, which, when invoked, will return an instance of the functional interface
--     * @throws ReflectiveOperationException
-+     * @throws ReflectiveOperationException if the caller is not able to reconstruct one of the method handles
-      * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
-      */
-     public static CallSite metaFactory(MethodHandles.Lookup caller,
-@@ -226,7 +226,7 @@
-      *                    the first argument in the invocation signature will correspond to the receiver.
-      * @param  args       argument to pass, flags, marker interface count, and marker interfaces as described above
-      * @return a CallSite, which, when invoked, will return an instance of the functional interface
--     * @throws ReflectiveOperationException
-+     * @throws ReflectiveOperationException if the caller is not able to reconstruct one of the method handles
-      * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
-      */
-     public static CallSite altMetaFactory(MethodHandles.Lookup caller,
-diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java
---- a/src/share/classes/java/lang/invoke/MethodHandle.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandle.java
-@@ -44,7 +44,7 @@
-  * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
-  * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
-  *
-- * <h3>Method handle contents</h3>
-+ * <h1>Method handle contents</h1>
-  * Method handles are dynamically and strongly typed according to their parameter and return types.
-  * They are not distinguished by the name or the defining class of their underlying methods.
-  * A method handle must be invoked using a symbolic type descriptor which matches
-@@ -81,7 +81,7 @@
-  * from its specific class, as the method handle class hierarchy (if any)
-  * may change from time to time or across implementations from different vendors.
-  *
-- * <h3>Method handle compilation</h3>
-+ * <h1>Method handle compilation</h1>
-  * A Java method call expression naming {@code invokeExact} or {@code invoke}
-  * can invoke a method handle from Java source code.
-  * From the viewpoint of source code, these methods can take any arguments
-@@ -111,7 +111,7 @@
-  * The ambiguity with the type {@code Void} is harmless, since there are no references of type
-  * {@code Void} except the null reference.
-  *
-- * <h3>Method handle invocation</h3>
-+ * <h1>Method handle invocation</h1>
-  * The first time a {@code invokevirtual} instruction is executed
-  * it is linked, by symbolically resolving the names in the instruction
-  * and verifying that the method call is statically legal.
-@@ -154,7 +154,7 @@
-  * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
-  * and implementations are therefore not required to materialize it.)
-  *
-- * <h3>Invocation checking</h3>
-+ * <h1>Invocation checking</h1>
-  * In typical programs, method handle type matching will usually succeed.
-  * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
-  * either directly (in the case of {@code invokeExact}) or indirectly as if
-@@ -195,7 +195,7 @@
-  * They should not be passed to untrusted code unless their use from
-  * the untrusted code would be harmless.
-  *
-- * <h3>Method handle creation</h3>
-+ * <h1>Method handle creation</h1>
-  * Java code can create a method handle that directly accesses
-  * any method, constructor, or field that is accessible to that code.
-  * This is done via a reflective, capability-based API called
-@@ -249,7 +249,7 @@
-  * receiver type.  Such a method handle simulates the effect of
-  * an {@code invokespecial} instruction to the same method.
-  *
-- * <h3>Usage examples</h3>
-+ * <h1>Usage examples</h1>
-  * Here are some examples of usage:
-  * <p><blockquote><pre>
- Object x, y; String s; int i;
-@@ -295,7 +295,7 @@
-  * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals }
-  * on its arguments, and asserts that the result is true.
-  *
-- * <h3>Exceptions</h3>
-+ * <h1>Exceptions</h1>
-  * The methods {@code invokeExact} and {@code invoke} are declared
-  * to throw {@link java.lang.Throwable Throwable},
-  * which is to say that there is no static restriction on what a method handle
-@@ -308,7 +308,7 @@
-  * throwables locally, rethrowing only those which are legal in the context,
-  * and wrapping ones which are illegal.
-  *
-- * <h3><a name="sigpoly"></a>Signature polymorphism</h3>
-+ * <h1><a name="sigpoly"></a>Signature polymorphism</h1>
-  * The unusual compilation and linkage behavior of
-  * {@code invokeExact} and plain {@code invoke}
-  * is referenced by the term <em>signature polymorphism</em>.
-@@ -333,7 +333,7 @@
-  * Tools which determine symbolic linkage are required to accept such
-  * untransformed descriptors, without reporting linkage errors.
-  *
-- * <h3>Interoperation between method handles and the Core Reflection API</h3>
-+ * <h1>Interoperation between method handles and the Core Reflection API</h1>
-  * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
-  * any class member represented by a Core Reflection API object
-  * can be converted to a behaviorally equivalent method handle.
-@@ -375,7 +375,7 @@
-  * to call {@code invokeExact} or plain {@code invoke},
-  * for any specified type descriptor .
-  *
-- * <h3>Interoperation between method handles and Java generics</h3>
-+ * <h1>Interoperation between method handles and Java generics</h1>
-  * A method handle can be obtained on a method, constructor, or field
-  * which is declared with Java generic types.
-  * As with the Core Reflection API, the type of the method handle
-@@ -457,6 +457,8 @@
-      * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
-      * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
-      * it will throw an {@code UnsupportedOperationException}.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-      * @throws WrongMethodTypeException if the target's type is not identical with the caller's symbolic type descriptor
-      * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
-      */
-@@ -491,6 +493,8 @@
-      * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
-      * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
-      * it will throw an {@code UnsupportedOperationException}.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-      * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's symbolic type descriptor
-      * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
-      * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
-@@ -511,15 +515,26 @@
-      * operations on outgoing argument values.)
-      * The caller can assume that the incoming result value is part of the range
-      * of the callee's return type.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-      */
-     /*non-public*/ final native @PolymorphicSignature Object invokeBasic(Object... args) throws Throwable;
- 
-+    /**
-+     * Private method for trusted invocation of a MemberName of kind {@code REF_invokeVirtual}.
-+     * The caller signature is restricted to basic types as with {@code invokeBasic}.
-+     * The trailing (not leading) argument must be a MemberName.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-+     */
-     /*non-public*/ static native @PolymorphicSignature Object linkToVirtual(Object... args) throws Throwable;
- 
-     /**
-      * Private method for trusted invocation of a MemberName of kind {@code REF_invokeStatic}.
-      * The caller signature is restricted to basic types as with {@code invokeBasic}.
-      * The trailing (not leading) argument must be a MemberName.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-      */
-     /*non-public*/ static native @PolymorphicSignature Object linkToStatic(Object... args) throws Throwable;
- 
-@@ -527,6 +542,8 @@
-      * Private method for trusted invocation of a MemberName of kind {@code REF_invokeSpecial}.
-      * The caller signature is restricted to basic types as with {@code invokeBasic}.
-      * The trailing (not leading) argument must be a MemberName.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-      */
-     /*non-public*/ static native @PolymorphicSignature Object linkToSpecial(Object... args) throws Throwable;
- 
-@@ -534,6 +551,8 @@
-      * Private method for trusted invocation of a MemberName of kind {@code REF_invokeInterface}.
-      * The caller signature is restricted to basic types as with {@code invokeBasic}.
-      * The trailing (not leading) argument must be a MemberName.
-+     * @param args the signature-polymorphic parameter list, statically represented using varargs
-+     * @return the signature-polymorphic result, statically represented using {@code Object}
-      */
-     /*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable;
- 
-@@ -776,8 +795,8 @@
- assert( (boolean) eq0.invokeExact("me", (Object)"me", new Object[0]));
- assert(!(boolean) eq0.invokeExact("me", (Object)"thee", (Object[])null));
- // asSpreader and asCollector are approximate inverses:
--for (int n = 0; n <= 2; n++) {
--    for (Class<?> a : new Class<?>[]{Object[].class, String[].class, CharSequence[].class}) {
-+for (int n = 0; n &lt;= 2; n++) {
-+    for (Class&lt;?&gt; a : new Class&lt;?&gt;[]{Object[].class, String[].class, CharSequence[].class}) {
-         MethodHandle equals2 = equals.asSpreader(a, n).asCollector(a, n);
-         assert( (boolean) equals2.invokeWithArguments("me", "me"));
-         assert(!(boolean) equals2.invokeWithArguments("me", "thee"));
-diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
---- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
-@@ -108,8 +108,9 @@
-      * Future versions of this API may also equip wrapper instances
-      * with one or more additional public "marker" interfaces.
-      *
-+     * @param <T> the desired type of the wrapper, a single-method interface
-+     * @param intfc a class object representing {@code T}
-      * @param target the method handle to invoke from the wrapper
--     * @param intfc the desired type of the wrapper, a single-method interface
-      * @return a correctly-typed wrapper for the given target
-      * @throws NullPointerException if either argument is null
-      * @throws IllegalArgumentException if the {@code intfc} is not a
-diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
---- a/src/share/classes/java/lang/invoke/MethodHandles.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandles.java
-@@ -68,6 +68,7 @@
-      * including direct method handles to private fields and methods.
-      * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
-      * Do not store it in place where untrusted code can access it.
-+     * @return a lookup object for the caller of this method
-      */
-     @CallerSensitive
-     public static Lookup lookup() {
-@@ -86,6 +87,7 @@
-      * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
-      * Since all classes have equal access to public names,
-      * such a change would confer no new access rights.
-+     * @return a lookup object which is trusted minimally
-      */
-     public static Lookup publicLookup() {
-         return Lookup.PUBLIC_LOOKUP;
-@@ -109,72 +111,73 @@
-      * on the {@code Lookup} object to create method handles for access-checked members.
-      * This includes all methods, constructors, and fields which are allowed to the lookup class,
-      * even private ones.
--     * <p>
-+     *
-+     * <h1><a name="lookups"></a>Lookup Factory Methods</h1>
-      * The factory methods on a {@code Lookup} object correspond to all major
-      * use cases for methods, constructors, and fields.
-      * Here is a summary of the correspondence between these factory methods and
--     * the behavior the resulting method handles:
--     * <code>
-+     * the behavior of the resulting method handles:
-      * <table border=1 cellpadding=5 summary="lookup method behaviors">
-      * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
--     *     <td>FT f;</td><td>(T) this.f;</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
-+     *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
--     *     <td>static<br>FT f;</td><td>(T) C.f;</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
-+     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
--     *     <td>FT f;</td><td>this.f = x;</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
-+     *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
--     *     <td>static<br>FT f;</td><td>C.f = arg;</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
-+     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
--     *     <td>T m(A*);</td><td>(T) this.m(arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
-+     *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
--     *     <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
-+     *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
--     *     <td>T m(A*);</td><td>(T) super.m(arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
-+     *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
--     *     <td>C(A*);</td><td>(T) new C(arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
-+     *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
--     *     <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
-+     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
--     *     <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
-+     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
--     *     <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
-+     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
--     *     <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
-+     *     <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
-      * </tr>
-      * <tr>
--     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
--     *     <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
-+     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
-+     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
-      * </tr>
-      * </table>
--     * </code>
-      * Here, the type {@code C} is the class or interface being searched for a member,
-      * documented as a parameter named {@code refc} in the lookup methods.
--     * The method or constructor type {@code MT} is composed from the return type {@code T}
-+     * The method type {@code MT} is composed from the return type {@code T}
-      * and the sequence of argument types {@code A*}.
-+     * The constructor also has a sequence of argument types {@code A*} and
-+     * is deemed to return the newly-created object of type {@code C}.
-      * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
-      * The formal parameter {@code this} stands for the self-reference of type {@code C};
-      * if it is present, it is always the leading argument to the method handle invocation.
-@@ -208,7 +211,7 @@
-      * security manager checks.
-      * </ul>
-      *
--     * <h3><a name="access"></a>Access checking</h3>
-+     * <h1><a name="access"></a>Access checking</h1>
-      * Access checks are applied in the factory methods of {@code Lookup},
-      * when a method handle is created.
-      * This is a key difference from the Core Reflection API, since
-@@ -295,7 +298,7 @@
-      * with static methods of {@link MethodHandles},
-      * independently of any {@code Lookup} object.
-      *
--     * <h3>Security manager interactions</h3>
-+     * <h1>Security manager interactions</h1>
-      * <a name="secmgr"></a>
-      * If a security manager is present, member lookups are subject to
-      * additional checks.
-@@ -386,6 +389,7 @@
-          *  but the permissions may be additionally limited by the bitmask
-          *  {@link #lookupModes lookupModes}, which controls whether non-public members
-          *  can be accessed.
-+         *  @return the lookup class, on behalf of which this lookup object finds members
-          */
-         public Class<?> lookupClass() {
-             return lookupClass;
-@@ -412,6 +416,7 @@
-          *  The purpose of this is to restrict access via the new lookup object,
-          *  so that it can access only names which can be reached by the original
-          *  lookup object, and also by the new lookup class.
-+         *  @return the lookup modes, which limit the kinds of access performed by this lookup object
-          */
-         public int lookupModes() {
-             return allowedModes & ALL_MODES;
-@@ -1371,6 +1376,7 @@
-      * The type of the method handle will have a void return type.
-      * Its last argument will be the array's element type.
-      * The first and second arguments will be the array type and int.
-+     * @param arrayClass the class of an array
-      * @return a method handle which can store values into the array type
-      * @throws NullPointerException if the argument is null
-      * @throws IllegalArgumentException if arrayClass is not an array type
-@@ -1599,12 +1605,12 @@
- ...
- MethodType intfn1 = methodType(int.class, int.class);
- MethodType intfn2 = methodType(int.class, int.class, int.class);
--MethodHandle sub = ... {int x, int y => x-y} ...;
-+MethodHandle sub = ... (int x, int y) -&gt; (x-y) ...;
- assert(sub.type().equals(intfn2));
- MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
- MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
- assert((int)rsub.invokeExact(1, 100) == 99);
--MethodHandle add = ... {int x, int y => x+y} ...;
-+MethodHandle add = ... (int x, int y) -&gt; (x+y) ...;
- assert(add.type().equals(intfn2));
- MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
- assert(twice.type().equals(intfn1));
-@@ -2280,6 +2286,8 @@
-      * The method type will nominally specify a return of {@code returnType}.
-      * The return type may be anything convenient:  It doesn't matter to the
-      * method handle's behavior, since it will never return normally.
-+     * @param returnType the return type of the desired method handle
-+     * @param exType the parameter type of the desired method handle
-      * @return method handle which can throw the given exceptions
-      * @throws NullPointerException if either argument is null
-      */
-diff --git a/src/share/classes/java/lang/invoke/MethodType.java b/src/share/classes/java/lang/invoke/MethodType.java
---- a/src/share/classes/java/lang/invoke/MethodType.java
-+++ b/src/share/classes/java/lang/invoke/MethodType.java
-@@ -191,6 +191,8 @@
-     /**
-      * Finds or creates a method type with the given components.
-      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-+     * @param rtype  the return type
-+     * @param ptypes the parameter types
-      * @return a method type with the given components
-      * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
-      * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
-@@ -211,6 +213,9 @@
-      * Finds or creates a method type with the given components.
-      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-      * The leading parameter type is prepended to the remaining array.
-+     * @param rtype  the return type
-+     * @param ptype0 the first parameter type
-+     * @param ptypes the remaining parameter types
-      * @return a method type with the given components
-      * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
-      * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
-@@ -227,6 +232,7 @@
-      * Finds or creates a method type with the given components.
-      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-      * The resulting method has no parameter types.
-+     * @param rtype  the return type
-      * @return a method type with the given return value
-      * @throws NullPointerException if {@code rtype} is null
-      */
-@@ -239,6 +245,8 @@
-      * Finds or creates a method type with the given components.
-      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-      * The resulting method has the single given parameter type.
-+     * @param rtype  the return type
-+     * @param ptype0 the parameter type
-      * @return a method type with the given return value and parameter type
-      * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
-      * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
-@@ -253,6 +261,9 @@
-      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-      * The resulting method has the same parameter types as {@code ptypes},
-      * and the specified return type.
-+     * @param rtype  the return type
-+     * @param ptypes the method type which supplies the parameter types
-+     * @return a method type with the given components
-      * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
-      */
-     public static
-@@ -935,7 +946,8 @@
-      * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
-      * For example, null values, or {@code void} parameter types,
-      * will lead to exceptions during deserialization.
--     * @param the stream to write the object to
-+     * @param s the stream to write the object to
-+     * @throws java.io.IOException if there is a problem writing the object
-      */
-     private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-         s.defaultWriteObject();  // requires serialPersistentFields to be an empty array
-@@ -950,7 +962,9 @@
-      * It provides the parameters to the factory method called by
-      * {@link #readResolve readResolve}.
-      * After that call it is discarded.
--     * @param the stream to read the object from
-+     * @param s the stream to read the object from
-+     * @throws java.io.IOException if there is a problem reading the object
-+     * @throws ClassNotFoundException if one of the component classes cannot be resolved
-      * @see #MethodType()
-      * @see #readResolve
-      * @see #writeObject
-diff --git a/src/share/classes/java/lang/invoke/MutableCallSite.java b/src/share/classes/java/lang/invoke/MutableCallSite.java
---- a/src/share/classes/java/lang/invoke/MutableCallSite.java
-+++ b/src/share/classes/java/lang/invoke/MutableCallSite.java
-@@ -195,7 +195,7 @@
-      * processed before the method returns abnormally.
-      * Which elements these are (if any) is implementation-dependent.
-      *
--     * <h3>Java Memory Model details</h3>
-+     * <h1>Java Memory Model details</h1>
-      * In terms of the Java Memory Model, this operation performs a synchronization
-      * action which is comparable in effect to the writing of a volatile variable
-      * by the current thread, and an eventual volatile read by every other thread
-diff --git a/src/share/classes/java/lang/invoke/package-info.java b/src/share/classes/java/lang/invoke/package-info.java
---- a/src/share/classes/java/lang/invoke/package-info.java
-+++ b/src/share/classes/java/lang/invoke/package-info.java
-@@ -43,13 +43,13 @@
-  * </li>
-  * </ul>
-  *
-- * <h2><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h2>
-+ * <h1><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h1>
-  * The following low-level information summarizes relevant parts of the
-  * Java Virtual Machine specification.  For full details, please see the
-  * current version of that specification.
-  *
-  * Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
-- * <h3><a name="indyinsn"></a>{@code invokedynamic} instructions</h3>
-+ * <h2><a name="indyinsn"></a>{@code invokedynamic} instructions</h2>
-  * A dynamic call site is originally in an unlinked state.  In this state, there is
-  * no target method for the call site to invoke.
-  * <p>
-@@ -97,7 +97,7 @@
-  * If this happens, the same error will the thrown for all subsequent
-  * attempts to execute the dynamic call site.
-  *
-- * <h3>timing of linkage</h3>
-+ * <h2>timing of linkage</h2>
-  * A dynamic call site is linked just before its first execution.
-  * The bootstrap method call implementing the linkage occurs within
-  * a thread that is attempting a first execution.
-@@ -131,7 +131,7 @@
-  * just before its first invocation.
-  * There is no way to undo the effect of a completed bootstrap method call.
-  *
-- * <h3>types of bootstrap methods</h3>
-+ * <h2>types of bootstrap methods</h2>
-  * As long as each bootstrap method can be correctly invoked
-  * by {@code MethodHandle.invoke}, its detailed type is arbitrary.
-  * For example, the first argument could be {@code Object}
--- a/meth-info-8008688.patch	Tue Aug 13 12:54:34 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1982 +0,0 @@
-8008688: Make MethodHandleInfo public
-Summary: Polish the proposed MethodHandleInfo API.
-Reviewed-by: vlivanov, twisti
-
-diff --git a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
---- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
-+++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
-@@ -102,12 +102,12 @@
-         this.samBase = invokedType.returnType();
- 
-         this.samMethod = samMethod;
--        this.samInfo = new MethodHandleInfo(samMethod);
-+        this.samInfo = caller.revealDirect(samMethod);
-         this.samClass = samInfo.getDeclaringClass();
-         this.samMethodType  = samInfo.getMethodType();
- 
-         this.implMethod = implMethod;
--        this.implInfo = new MethodHandleInfo(implMethod);
-+        this.implInfo = caller.revealDirect(implMethod);
-         // @@@ Temporary work-around pending resolution of 8005119
-         this.implKind = (implInfo.getReferenceKind() == MethodHandleInfo.REF_invokeSpecial)
-                         ? MethodHandleInfo.REF_invokeVirtual
-diff --git a/src/share/classes/java/lang/invoke/InfoFromMemberName.java b/src/share/classes/java/lang/invoke/InfoFromMemberName.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/java/lang/invoke/InfoFromMemberName.java
-@@ -0,0 +1,145 @@
-+/*
-+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * This code is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 only, as
-+ * published by the Free Software Foundation.  Oracle designates this
-+ * particular file as subject to the "Classpath" exception as provided
-+ * by Oracle in the LICENSE file that accompanied this code.
-+ *
-+ * This code is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-+ * version 2 for more details (a copy is included in the LICENSE file that
-+ * accompanied this code).
-+ *
-+ * You should have received a copy of the GNU General Public License version
-+ * 2 along with this work; if not, write to the Free Software Foundation,
-+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-+ * or visit www.oracle.com if you need additional information or have any
-+ * questions.
-+ */
-+
-+package java.lang.invoke;
-+
-+import java.security.*;
-+import java.lang.reflect.*;
-+import java.lang.invoke.MethodHandleNatives.Constants;
-+import java.lang.invoke.MethodHandles.Lookup;
-+import static java.lang.invoke.MethodHandleStatics.*;
-+
-+/*
-+ * Auxiliary to MethodHandleInfo, wants to nest in MethodHandleInfo but must be non-public.
-+ */
-+/*non-public*/
-+final
-+class InfoFromMemberName implements MethodHandleInfo {
-+    private final MemberName member;
-+    private final int referenceKind;
-+
-+    InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
-+        assert(member.isResolved() || member.isMethodHandleInvoke());
-+        assert(member.referenceKindIsConsistentWith(referenceKind));
-+        this.member = member;
-+        this.referenceKind = referenceKind;
-+    }
-+
-+    @Override
-+    public Class<?> getDeclaringClass() {
-+        return member.getDeclaringClass();
-+    }
-+
-+    @Override
-+    public String getName() {
-+        return member.getName();
-+    }
-+
-+    @Override
-+    public MethodType getMethodType() {
-+        return member.getMethodOrFieldType();
-+    }
-+
-+    @Override
-+    public int getModifiers() {
-+        return member.getModifiers();
-+    }
-+
-+    @Override
-+    public int getReferenceKind() {
-+        return referenceKind;
-+    }
-+
-+    @Override
-+    public String toString() {
-+        return MethodHandleInfo.toString(getReferenceKind(), getDeclaringClass(), getName(), getMethodType());
-+    }
-+
-+    @Override
-+    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
-+        if (member.isMethodHandleInvoke() && !member.isVarargs()) {
-+            // This member is an instance of a signature-polymorphic method, which cannot be reflected
-+            // A method handle invoker can come in either of two forms:
-+            // A generic placeholder (present in the source code, and varargs)
-+            // and a signature-polymorphic instance (synthetic and not varargs).
-+            // For more information see comments on {@link MethodHandleNatives#linkMethod}.
-+            throw new IllegalArgumentException("cannot reflect signature polymorphic method");
-+        }
-+        Member mem = AccessController.doPrivileged(new PrivilegedAction<Member>() {
-+                public Member run() {
-+                    try {
-+                        return reflectUnchecked();
-+                    } catch (ReflectiveOperationException ex) {
-+                        throw new IllegalArgumentException(ex);
-+                    }
-+                }
-+            });
-+        try {
-+            Class<?> defc = getDeclaringClass();
-+            byte refKind = (byte) getReferenceKind();
-+            lookup.checkAccess(refKind, defc, convertToMemberName(refKind, mem));
-+        } catch (IllegalAccessException ex) {
-+            throw new IllegalArgumentException(ex);
-+        }
-+        return expected.cast(mem);
-+    }
-+
-+    private Member reflectUnchecked() throws ReflectiveOperationException {
-+        byte refKind = (byte) getReferenceKind();
-+        Class<?> defc = getDeclaringClass();
-+        boolean isPublic = Modifier.isPublic(getModifiers());
-+        if (MethodHandleNatives.refKindIsMethod(refKind)) {
-+            if (isPublic)
-+                return defc.getMethod(getName(), getMethodType().parameterArray());
-+            else
-+                return defc.getDeclaredMethod(getName(), getMethodType().parameterArray());
-+        } else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
-+            if (isPublic)
-+                return defc.getConstructor(getMethodType().parameterArray());
-+            else
-+                return defc.getDeclaredConstructor(getMethodType().parameterArray());
-+        } else if (MethodHandleNatives.refKindIsField(refKind)) {
-+            if (isPublic)
-+                return defc.getField(getName());
-+            else
-+                return defc.getDeclaredField(getName());
-+        } else {
-+            throw new IllegalArgumentException("referenceKind="+refKind);
-+        }
-+    }
-+
-+    private static MemberName convertToMemberName(byte refKind, Member mem) throws IllegalAccessException {
-+        if (mem instanceof Method) {
-+            boolean wantSpecial = (refKind == REF_invokeSpecial);
-+            return new MemberName((Method) mem, wantSpecial);
-+        } else if (mem instanceof Constructor) {
-+            return new MemberName((Constructor) mem);
-+        } else if (mem instanceof Field) {
-+            boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic);
-+            return new MemberName((Field) mem, isSetter);
-+        }
-+        throw new InternalError(mem.getClass().getName());
-+    }
-+}
-diff --git a/src/share/classes/java/lang/invoke/Invokers.java b/src/share/classes/java/lang/invoke/Invokers.java
---- a/src/share/classes/java/lang/invoke/Invokers.java
-+++ b/src/share/classes/java/lang/invoke/Invokers.java
-@@ -87,6 +87,7 @@
-             lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_INVOKER);
-             invoker = SimpleMethodHandle.make(invokerType, lform);
-         }
-+        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke("invokeExact", mtype));
-         assert(checkInvoker(invoker));
-         exactInvoker = invoker;
-         return invoker;
-@@ -110,6 +111,7 @@
-             lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_INVOKER);
-             invoker = SimpleMethodHandle.make(invokerType, lform);
-         }
-+        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke("invoke", mtype));
-         assert(checkInvoker(invoker));
-         generalInvoker = invoker;
-         return invoker;
-diff --git a/src/share/classes/java/lang/invoke/MemberName.java b/src/share/classes/java/lang/invoke/MemberName.java
---- a/src/share/classes/java/lang/invoke/MemberName.java
-+++ b/src/share/classes/java/lang/invoke/MemberName.java
-@@ -320,14 +320,18 @@
- 
-     /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
-     public boolean isMethodHandleInvoke() {
--        final int bits = Modifier.NATIVE | Modifier.FINAL;
-+        final int bits = MH_INVOKE_MODS;
-         final int negs = Modifier.STATIC;
-         if (testFlags(bits | negs, bits) &&
-             clazz == MethodHandle.class) {
--            return name.equals("invoke") || name.equals("invokeExact");
-+            return isMethodHandleInvokeName(name);
-         }
-         return false;
-     }
-+    public static boolean isMethodHandleInvokeName(String name) {
-+        return name.equals("invoke") || name.equals("invokeExact");
-+    }
-+    private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
- 
-     /** Utility method to query the modifier flags of this member. */
-     public boolean isStatic() {
-@@ -482,12 +486,27 @@
-         m.getClass();  // NPE check
-         // fill in vmtarget, vmindex while we have m in hand:
-         MethodHandleNatives.init(this, m);
-+        if (clazz == null) {  // MHN.init failed
-+            if (m.getDeclaringClass() == MethodHandle.class &&
-+                isMethodHandleInvokeName(m.getName())) {
-+                // The JVM did not reify this signature-polymorphic instance.
-+                // Need a special case here.
-+                // See comments on MethodHandleNatives.linkMethod.
-+                MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
-+                int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
-+                init(MethodHandle.class, m.getName(), type, flags);
-+                if (isMethodHandleInvoke())
-+                    return;
-+            }
-+            throw new LinkageError(m.toString());
-+        }
-         assert(isResolved() && this.clazz != null);
-         this.name = m.getName();
-         if (this.type == null)
-             this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
-         if (wantSpecial) {
--            assert(!isAbstract()) : this;
-+            if (isAbstract())
-+                throw new AbstractMethodError(this.toString());
-             if (getReferenceKind() == REF_invokeVirtual)
-                 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
-             else if (getReferenceKind() == REF_invokeInterface)
-@@ -562,6 +581,22 @@
-         initResolved(true);
-     }
- 
-+    /**
-+     * Create a name for a signature-polymorphic invoker.
-+     * This is a placeholder for a signature-polymorphic instance
-+     * (of MH.invokeExact, etc.) that the JVM does not reify.
-+     * See comments on {@link MethodHandleNatives#linkMethod}.
-+     */
-+    static MemberName makeMethodHandleInvoke(String name, MethodType type) {
-+        return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
-+    }
-+    static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
-+        MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
-+        mem.flags |= mods;  // it's not resolved, but add these modifiers anyway
-+        assert(mem.isMethodHandleInvoke()) : mem;
-+        return mem;
-+    }
-+
-     // bare-bones constructor; the JVM will fill it in
-     MemberName() { }
- 
-diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java
---- a/src/share/classes/java/lang/invoke/MethodHandle.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandle.java
-@@ -1285,6 +1285,11 @@
-     }
- 
-     /*non-public*/
-+    MethodHandle withInternalMemberName(MemberName member) {
-+        return MethodHandleImpl.makeWrappedMember(this, member);
-+    }
-+
-+    /*non-public*/
-     boolean isInvokeSpecial() {
-         return false;  // DMH.Special returns true
-     }
-@@ -1356,7 +1361,7 @@
-     MethodHandle rebind() {
-         // Bind 'this' into a new invoker, of the known class BMH.
-         MethodType type2 = type();
--        LambdaForm form2 = reinvokerForm(type2.basicType());
-+        LambdaForm form2 = reinvokerForm(this);
-         // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
-         return BoundMethodHandle.bindSingle(type2, form2, this);
-     }
-@@ -1369,23 +1374,38 @@
-     /** Create a LF which simply reinvokes a target of the given basic type.
-      *  The target MH must override {@link #reinvokerTarget} to provide the target.
-      */
--    static LambdaForm reinvokerForm(MethodType mtype) {
--        mtype = mtype.basicType();
-+    static LambdaForm reinvokerForm(MethodHandle target) {
-+        MethodType mtype = target.type().basicType();
-         LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
-         if (reinvoker != null)  return reinvoker;
--        MethodHandle MH_invokeBasic = MethodHandles.basicInvoker(mtype);
-+        if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)
-+            return makeReinvokerForm(target.type(), target);  // cannot cache this
-+        reinvoker = makeReinvokerForm(mtype, null);
-+        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker);
-+    }
-+    private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) {
-+        boolean customized = (customTargetOrNull != null);
-+        MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype);
-         final int THIS_BMH    = 0;
-         final int ARG_BASE    = 1;
-         final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
-         int nameCursor = ARG_LIMIT;
--        final int NEXT_MH     = nameCursor++;
-+        final int NEXT_MH     = customized ? -1 : nameCursor++;
-         final int REINVOKE    = nameCursor++;
-         LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
--        names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
--        Object[] targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
--        targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
--        names[REINVOKE] = new LambdaForm.Name(MH_invokeBasic, targetArgs);
--        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, new LambdaForm("BMH.reinvoke", ARG_LIMIT, names));
-+        Object[] targetArgs;
-+        MethodHandle targetMH;
-+        if (customized) {
-+            targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
-+            targetMH = customTargetOrNull;
-+        } else {
-+            names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
-+            targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
-+            targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
-+            targetMH = MethodHandles.basicInvoker(mtype);
-+        }
-+        names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs);
-+        return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names);
-     }
- 
-     private static final LambdaForm.NamedFunction NF_reinvokerTarget;
-diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java
---- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java
-@@ -317,7 +317,7 @@
-         private MethodHandle cache;
- 
-         AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
--            super(type, reinvokerForm(type));
-+            super(type, reinvokerForm(target));
-             this.target = target;
-             this.arrayType = arrayType;
-             this.cache = target.asCollector(arrayType, 0);
-@@ -777,16 +777,27 @@
-     }
-     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
- 
--    static MethodHandle FAKE_METHOD_HANDLE_INVOKE;
--    static
--    MethodHandle fakeMethodHandleInvoke(MemberName method) {
--        MethodType type = method.getInvocationType();
--        assert(type.equals(MethodType.methodType(Object.class, Object[].class)));
--        MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE;
-+    static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
-+    static MethodHandle fakeMethodHandleInvoke(MemberName method) {
-+        int idx;
-+        assert(method.isMethodHandleInvoke());
-+        switch (method.getName()) {
-+        case "invoke":       idx = 0; break;
-+        case "invokeExact":  idx = 1; break;
-+        default:             throw new InternalError(method.getName());
-+        }
-+        MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
-         if (mh != null)  return mh;
--        mh = throwException(type.insertParameterTypes(0, UnsupportedOperationException.class));
-+        MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
-+                                                MethodHandle.class, Object[].class);
-+        mh = throwException(type);
-         mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
--        FAKE_METHOD_HANDLE_INVOKE = mh;
-+        if (!method.getInvocationType().equals(mh.type()))
-+            throw new InternalError(method.toString());
-+        mh = mh.withInternalMemberName(method);
-+        mh = mh.asVarargsCollector(Object[].class);
-+        assert(method.isVarargs());
-+        FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
-         return mh;
-     }
- 
-@@ -820,7 +831,7 @@
-             MethodHandle vamh = prepareForInvoker(mh);
-             // Cache the result of makeInjectedInvoker once per argument class.
-             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
--            return restoreToType(bccInvoker.bindTo(vamh), mh.type());
-+            return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName());
-         }
- 
-         private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
-@@ -875,8 +886,11 @@
-         }
- 
-         // Undo the adapter effect of prepareForInvoker:
--        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type) {
--            return vamh.asCollector(Object[].class, type.parameterCount()).asType(type);
-+        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type, MemberName member) {
-+            MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
-+            mh = mh.asType(type);
-+            mh = mh.withInternalMemberName(member);
-+            return mh;
-         }
- 
-         private static final MethodHandle MH_checkCallerClass;
-@@ -938,4 +952,41 @@
-             }
-         }
-     }
-+
-+
-+    /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
-+    static class WrappedMember extends MethodHandle {
-+        private final MethodHandle target;
-+        private final MemberName member;
-+
-+        private WrappedMember(MethodHandle target, MethodType type, MemberName member) {
-+            super(type, reinvokerForm(target));
-+            this.target = target;
-+            this.member = member;
-+        }
-+
-+        @Override
-+        MethodHandle reinvokerTarget() {
-+            return target;
-+        }
-+        @Override
-+        MemberName internalMemberName() {
-+            return member;
-+        }
-+        @Override
-+        boolean isInvokeSpecial() {
-+            return target.isInvokeSpecial();
-+        }
-+        @Override
-+        MethodHandle viewAsType(MethodType newType) {
-+            return new WrappedMember(target, newType, member);
-+        }
-+    }
-+
-+    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
-+        if (member.equals(target.internalMemberName()))
-+            return target;
-+        return new WrappedMember(target, target.type(), member);
-+    }
-+
- }
-diff --git a/src/share/classes/java/lang/invoke/MethodHandleInfo.java b/src/share/classes/java/lang/invoke/MethodHandleInfo.java
---- a/src/share/classes/java/lang/invoke/MethodHandleInfo.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandleInfo.java
-@@ -24,80 +24,246 @@
-  */
- 
- package java.lang.invoke;
-+
-+import java.lang.reflect.*;
-+import java.util.*;
- import java.lang.invoke.MethodHandleNatives.Constants;
-+import java.lang.invoke.MethodHandles.Lookup;
-+import static java.lang.invoke.MethodHandleStatics.*;
- 
- /**
-- * Cracking (reflecting) method handles back into their constituent symbolic parts.
-+ * A symbolic reference obtained by cracking a method handle into its consitutent symbolic parts.
-+ * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
-+ * <p>
-+ * A <em>direct method handle</em> represents a method, constructor, or field without
-+ * any intervening argument bindings or other transformations.
-+ * The method, constructor, or field referred to by a direct method handle is called
-+ * its <em>underlying member</em>.
-+ * Direct method handles may be obtained in any of these ways:
-+ * <ul>
-+ * <li>By executing an {@code ldc} instruction on a {@code CONSTANT_MethodHandle} constant.
-+ *     (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.)
-+ * <li>By calling one of the <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>,
-+ *     such as {@link Lookup#findVirtual Lookup.findVirtual},
-+ *     to resolve a symbolic reference into a method handle.
-+ *     A symbolic reference consists of a class, name string, and type.
-+ * <li>By calling the factory method {@link Lookup#unreflect Lookup.unreflect}
-+ *     or {@link Lookup#unreflectSpecial Lookup.unreflectSpecial}
-+ *     to convert a {@link Method} into a method handle.
-+ * <li>By calling the factory method {@link Lookup#unreflectConstructor Lookup.unreflectConstructor}
-+ *     to convert a {@link Constructor} into a method handle.
-+ * <li>By calling the factory method {@link Lookup#unreflectGetter Lookup.unreflectGetter}
-+ *     or {@link Lookup#unreflectSetter Lookup.unreflectSetter}
-+ *     to convert a {@link Field} into a method handle.
-+ * </ul>
-+ * In all of these cases, it is possible to crack the resulting direct method handle
-+ * to recover a symbolic reference for the underlying method, constructor, or field.
-+ * Cracking must be done via a {@code Lookup} object equivalent to that which created
-+ * the target method handle, or which has enough access permissions to recreate
-+ * an equivalent method handle.
-  *
-+ * <h1><a name="refkinds"></a>Reference kinds</h1>
-+ * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
-+ * correspond to all major use cases for methods, constructors, and fields.
-+ * These use cases may be distinguished using small integers as follows:
-+ * <table border=1 cellpadding=5 summary="reference kinds">
-+ * <tr><th>reference kind</th><th>descriptive name</th><th>scope</th><th>member</th><th>behavior</th></tr>
-+ * <tr>
-+ *     <td>{@code 1}</td><td>{@code REF_getField}</td><td>{@code class}</td>
-+ *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 2}</td><td>{@code REF_getStatic}</td><td>{@code class} or {@code interface}</td>
-+ *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 3}</td><td>{@code REF_putField}</td><td>{@code class}</td>
-+ *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 4}</td><td>{@code REF_putStatic}</td><td>{@code class}</td>
-+ *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 5}</td><td>{@code REF_invokeVirtual}</td><td>{@code class}</td>
-+ *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 6}</td><td>{@code REF_invokeStatic}</td><td>{@code class} or {@code interface}</td>
-+ *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 7}</td><td>{@code REF_invokeSpecial}</td><td>{@code class} or {@code interface}</td>
-+ *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 8}</td><td>{@code REF_newInvokeSpecial}</td><td>{@code class}</td>
-+ *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
-+ * </tr>
-+ * <tr>
-+ *     <td>{@code 9}</td><td>{@code REF_invokeInterface}</td><td>{@code interface}</td>
-+ *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
-+ * </tr>
-+ * </table>
-+ * @since 1.8
-  */
--final class MethodHandleInfo {
--   public static final int
--       REF_getField                = Constants.REF_getField,
--       REF_getStatic               = Constants.REF_getStatic,
--       REF_putField                = Constants.REF_putField,
--       REF_putStatic               = Constants.REF_putStatic,
--       REF_invokeVirtual           = Constants.REF_invokeVirtual,
--       REF_invokeStatic            = Constants.REF_invokeStatic,
--       REF_invokeSpecial           = Constants.REF_invokeSpecial,
--       REF_newInvokeSpecial        = Constants.REF_newInvokeSpecial,
--       REF_invokeInterface         = Constants.REF_invokeInterface;
-+public
-+interface MethodHandleInfo {
-+    /**
-+     * A direct method handle reference kind,
-+     * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
-+     */
-+    public static final int
-+        REF_getField                = Constants.REF_getField,
-+        REF_getStatic               = Constants.REF_getStatic,
-+        REF_putField                = Constants.REF_putField,
-+        REF_putStatic               = Constants.REF_putStatic,
-+        REF_invokeVirtual           = Constants.REF_invokeVirtual,
-+        REF_invokeStatic            = Constants.REF_invokeStatic,
-+        REF_invokeSpecial           = Constants.REF_invokeSpecial,
-+        REF_newInvokeSpecial        = Constants.REF_newInvokeSpecial,
-+        REF_invokeInterface         = Constants.REF_invokeInterface;
- 
--   private final Class<?> declaringClass;
--   private final String name;
--   private final MethodType methodType;
--   private final int referenceKind;
-+    /**
-+     * Returns the reference kind of the cracked method handle, which in turn
-+     * determines whether the method handle's underlying member was a constructor, method, or field.
-+     * See the <a href="MethodHandleInfo.html#refkinds">table above</a> for definitions.
-+     * @return the integer code for the kind of reference used to access the underlying member
-+     */
-+    public int getReferenceKind();
- 
--   public MethodHandleInfo(MethodHandle mh) {
--       MemberName mn = mh.internalMemberName();
--       if (mn == null)  throw new IllegalArgumentException("not a direct method handle");
--       this.declaringClass = mn.getDeclaringClass();
--       this.name = mn.getName();
--       this.methodType = mn.getMethodOrFieldType();
--       byte refKind = mn.getReferenceKind();
--       if (refKind == REF_invokeSpecial && !mh.isInvokeSpecial())
--           // Devirtualized method invocation is usually formally virtual.
--           refKind = REF_invokeVirtual;
--       this.referenceKind = refKind;
--   }
-+    /**
-+     * Returns the class in which the cracked method handle's underlying member was defined.
-+     * @return the declaring class of the underlying member
-+     */
-+    public Class<?> getDeclaringClass();
- 
--   public Class<?> getDeclaringClass() {
--       return declaringClass;
--   }
-+    /**
-+     * Returns the name of the cracked method handle's underlying member.
-+     * This is {@code "&lt;init&gt;"} if the underlying member was a constructor,
-+     * else it is a simple method name or field name.
-+     * @return the simple name of the underlying member
-+     */
-+    public String getName();
- 
--   public String getName() {
--       return name;
--   }
-+    /**
-+     * Returns the nominal type of the cracked symbolic reference, expressed as a method type.
-+     * If the reference is to a constructor, the return type will be {@code void}.
-+     * If it is to a non-static method, the method type will not mention the {@code this} parameter.
-+     * If it is to a field and the requested access is to read the field,
-+     * the method type will have no parameters and return the field type.
-+     * If it is to a field and the requested access is to write the field,
-+     * the method type will have one parameter of the field type and return {@code void}.
-+     * <p>
-+     * Note that original direct method handle may include a leading {@code this} parameter,
-+     * or (in the case of a constructor) will replace the {@code void} return type
-+     * with the constructed class.
-+     * The nominal type does not include any {@code this} parameter,
-+     * and (in the case of a constructor) will return {@code void}.
-+     * @return the type of the underlying member, expressed as a method type
-+     */
-+    public MethodType getMethodType();
- 
--   public MethodType getMethodType() {
--       return methodType;
--   }
-+    // Utility methods.
-+    // NOTE: class/name/type and reference kind constitute a symbolic reference
-+    // member and modifiers are an add-on, derived from Core Reflection (or the equivalent)
- 
--   public int getModifiers() {
--       return -1; //TODO
--   }
-+    /**
-+     * Reflects the underlying member as a method, constructor, or field object.
-+     * If the underlying member is public, it is reflected as if by
-+     * {@code getMethod}, {@code getConstructor}, or {@code getField}.
-+     * Otherwise, it is reflected as if by
-+     * {@code getDeclaredMethod}, {@code getDeclaredConstructor}, or {@code getDeclaredField}.
-+     * The underlying member must be accessible to the given lookup object.
-+     * @param <T> the desired type of the result, either {@link Member} or a subtype
-+     * @param expected a class object representing the desired result type {@code T}
-+     * @param lookup the lookup object that created this MethodHandleInfo, or one with equivalent access privileges
-+     * @return a reference to the method, constructor, or field object
-+     * @exception ClassCastException if the member is not of the expected type
-+     * @exception NullPointerException if either argument is {@code null}
-+     * @exception IllegalArgumentException if the underlying member is not accessible to the given lookup object
-+     */
-+    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup);
- 
--   public int getReferenceKind() {
--       return referenceKind;
--   }
-+    /**
-+     * Returns the access modifiers of the underlying member.
-+     * @return the Java language modifiers for underlying member,
-+     *         or -1 if the member cannot be accessed
-+     * @see Modifier
-+     * @see reflectAs
-+     */
-+    public int getModifiers();
- 
--   static String getReferenceKindString(int referenceKind) {
--        switch (referenceKind) {
--            case REF_getField: return "getfield";
--            case REF_getStatic: return "getstatic";
--            case REF_putField: return "putfield";
--            case REF_putStatic: return "putstatic";
--            case REF_invokeVirtual: return "invokevirtual";
--            case REF_invokeStatic: return "invokestatic";
--            case REF_invokeSpecial: return "invokespecial";
--            case REF_newInvokeSpecial: return "newinvokespecial";
--            case REF_invokeInterface: return "invokeinterface";
--            default: return "UNKNOWN_REFENCE_KIND" + "[" + referenceKind + "]";
--        }
-+    /**
-+     * Determines if the underlying member was a variable arity method or constructor.
-+     * Such members are represented by method handles that are varargs collectors.
-+     * @implSpec
-+     * This produces a result equivalent to:
-+     * <pre>{@code
-+     *     getReferenceKind() >= REF_invokeVirtual && Modifier.isTransient(getModifiers())
-+     * }</pre>
-+     *
-+     *
-+     * @return {@code true} if and only if the underlying member was declared with variable arity.
-+     */
-+    // spelling derived from java.lang.reflect.Executable, not MethodHandle.isVarargsCollector
-+    public default boolean isVarArgs()  {
-+        // fields are never varargs:
-+        if (MethodHandleNatives.refKindIsField((byte) getReferenceKind()))
-+            return false;
-+        // not in the public API: Modifier.VARARGS
-+        final int ACC_VARARGS = 0x00000080;  // from JVMS 4.6 (Table 4.20)
-+        assert(ACC_VARARGS == Modifier.TRANSIENT);
-+        return Modifier.isTransient(getModifiers());
-     }
- 
--    @Override
--    public String toString() {
--        return String.format("%s %s.%s:%s", getReferenceKindString(referenceKind),
--                             declaringClass.getName(), name, methodType);
-+    /**
-+     * Returns the descriptive name of the given reference kind,
-+     * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
-+     * The conventional prefix "REF_" is omitted.
-+     * @param referenceKind an integer code for a kind of reference used to access a class member
-+     * @return a mixed-case string such as {@code "getField"}
-+     * @exception IllegalArgumentException if the argument is not a valid
-+     *            <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
-+     */
-+    public static String referenceKindToString(int referenceKind) {
-+        if (!MethodHandleNatives.refKindIsValid(referenceKind))
-+            throw newIllegalArgumentException("invalid reference kind", referenceKind);
-+        return MethodHandleNatives.refKindName((byte)referenceKind);
-+    }
-+
-+    /**
-+     * Returns a string representation for a {@code MethodHandleInfo},
-+     * given the four parts of its symbolic reference.
-+     * This is defined to be of the form {@code "RK C.N:MT"}, where {@code RK} is the
-+     * {@linkplain #referenceKindToString reference kind string} for {@code kind},
-+     * {@code C} is the {@linkplain java.lang.Class#getName name} of {@code defc}
-+     * {@code N} is the {@code name}, and
-+     * {@code MT} is the {@code type}.
-+     * These four values may be obtained from the
-+     * {@linkplain #getReferenceKind reference kind},
-+     * {@linkplain #getDeclaringClass declaring class},
-+     * {@linkplain #getName member name},
-+     * and {@linkplain #getMethodType method type}
-+     * of a {@code MethodHandleInfo} object.
-+     *
-+     * @implSpec
-+     * This produces a result equivalent to:
-+     * <pre>{@code
-+     *     String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type)
-+     * }</pre>
-+     *
-+     * @param kind the {@linkplain #getReferenceKind reference kind} part of the symbolic reference
-+     * @param defc the {@linkplain #getDeclaringClass declaring class} part of the symbolic reference
-+     * @param name the {@linkplain #getName member name} part of the symbolic reference
-+     * @param type the {@linkplain #getMethodType method type} part of the symbolic reference
-+     * @return a string of the form {@code "RK C.N:MT"}
-+     * @exception IllegalArgumentException if the first argument is not a valid
-+     *            <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
-+     * @exception NullPointerException if any reference argument is {@code null}
-+     */
-+    public static String toString(int kind, Class<?> defc, String name, MethodType type) {
-+        Objects.requireNonNull(name); Objects.requireNonNull(type);
-+        return String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type);
-     }
- }
-diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
---- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
-@@ -205,6 +205,9 @@
-     static boolean refKindIsMethod(byte refKind) {
-         return !refKindIsField(refKind) && (refKind != REF_newInvokeSpecial);
-     }
-+    static boolean refKindIsConstructor(byte refKind) {
-+        return (refKind == REF_newInvokeSpecial);
-+    }
-     static boolean refKindHasReceiver(byte refKind) {
-         assert(refKindIsValid(refKind));
-         return (refKind & 1) != 0;
-@@ -313,7 +316,65 @@
-      * The method assumes the following arguments on the stack:
-      * 0: the method handle being invoked
-      * 1-N: the arguments to the method handle invocation
--     * N+1: an implicitly added type argument (the given MethodType)
-+     * N+1: an optional, implicitly added argument (typically the given MethodType)
-+     * <p>
-+     * The nominal method at such a call site is an instance of
-+     * a signature-polymorphic method (see @PolymorphicSignature).
-+     * Such method instances are user-visible entities which are
-+     * "split" from the generic placeholder method in {@code MethodHandle}.
-+     * (Note that the placeholder method is not identical with any of
-+     * its instances.  If invoked reflectively, is guaranteed to throw an
-+     * {@code UnsupportedOperationException}.)
-+     * If the signature-polymorphic method instance is ever reified,
-+     * it appears as a "copy" of the original placeholder
-+     * (a native final member of {@code MethodHandle}) except
-+     * that its type descriptor has shape required by the instance,
-+     * and the method instance is <em>not</em> varargs.
-+     * The method instance is also marked synthetic, since the
-+     * method (by definition) does not appear in Java source code.
-+     * <p>
-+     * The JVM is allowed to reify this method as instance metadata.
-+     * For example, {@code invokeBasic} is always reified.
-+     * But the JVM may instead call {@code linkMethod}.
-+     * If the result is an * ordered pair of a {@code (method, appendix)},
-+     * the method gets all the arguments (0..N inclusive)
-+     * plus the appendix (N+1), and uses the appendix to complete the call.
-+     * In this way, one reusable method (called a "linker method")
-+     * can perform the function of any number of polymorphic instance
-+     * methods.
-+     * <p>
-+     * Linker methods are allowed to be weakly typed, with any or
-+     * all references rewritten to {@code Object} and any primitives
-+     * (except {@code long}/{@code float}/{@code double})
-+     * rewritten to {@code int}.
-+     * A linker method is trusted to return a strongly typed result,
-+     * according to the specific method type descriptor of the
-+     * signature-polymorphic instance it is emulating.
-+     * This can involve (as necessary) a dynamic check using
-+     * data extracted from the appendix argument.
-+     * <p>
-+     * The JVM does not inspect the appendix, other than to pass
-+     * it verbatim to the linker method at every call.
-+     * This means that the JDK runtime has wide latitude
-+     * for choosing the shape of each linker method and its
-+     * corresponding appendix.
-+     * Linker methods should be generated from {@code LambdaForm}s
-+     * so that they do not become visible on stack traces.
-+     * <p>
-+     * The {@code linkMethod} call is free to omit the appendix
-+     * (returning null) and instead emulate the required function
-+     * completely in the linker method.
-+     * As a corner case, if N==255, no appendix is possible.
-+     * In this case, the method returned must be custom-generated to
-+     * to perform any needed type checking.
-+     * <p>
-+     * If the JVM does not reify a method at a call site, but instead
-+     * calls {@code linkMethod}, the corresponding call represented
-+     * in the bytecodes may mention a valid method which is not
-+     * representable with a {@code MemberName}.
-+     * Therefore, use cases for {@code linkMethod} tend to correspond to
-+     * special cases in reflective code such as {@code findVirtual}
-+     * or {@code revealDirect}.
-      */
-     static MemberName linkMethod(Class<?> callerClass, int refKind,
-                                  Class<?> defc, String name, Object type,
-diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
---- a/src/share/classes/java/lang/invoke/MethodHandles.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandles.java
-@@ -26,8 +26,6 @@
- package java.lang.invoke;
- 
- import java.lang.reflect.*;
--import java.security.AccessController;
--import java.security.PrivilegedAction;
- import java.util.List;
- import java.util.ArrayList;
- import java.util.Arrays;
-@@ -53,6 +51,7 @@
-  * </ul>
-  * <p>
-  * @author John Rose, JSR 292 EG
-+ * @since 1.7
-  */
- public class MethodHandles {
- 
-@@ -96,6 +95,38 @@
-     }
- 
-     /**
-+     * Performs an unchecked "crack" of a direct method handle.
-+     * The result is as if the user had obtained a lookup object capable enough
-+     * to crack the target method handle, called
-+     * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
-+     * on the target to obtain its symbolic reference, and then called
-+     * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
-+     * to resolve the symbolic reference to a member.
-+     * <p>
-+     * If there is a security manager, its {@code checkPermission} method
-+     * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
-+     * @param <T> the desired type of the result, either {@link Member} or a subtype
-+     * @param target a direct method handle to crack into symbolic reference components
-+     * @param expected a class object representing the desired result type {@code T}
-+     * @return a reference to the method, constructor, or field object
-+     * @exception SecurityException if the caller is not privileged to call {@code setAccessible}
-+     * @exception NullPointerException if either argument is {@code null}
-+     * @exception IllegalArgumentException if the target is not a direct method handle
-+     * @exception ClassCastException if the member is not of the expected type
-+     * @since 1.8
-+     */
-+    public static <T extends Member> T
-+    reflectAs(Class<T> expected, MethodHandle target) {
-+        SecurityManager smgr = System.getSecurityManager();
-+        if (smgr != null)  smgr.checkPermission(ACCESS_PERMISSION);
-+        Lookup lookup = Lookup.IMPL_LOOKUP;  // use maximally privileged lookup
-+        return lookup.revealDirect(target).reflectAs(expected, lookup);
-+    }
-+    // Copied from AccessibleObject, as used by Method.setAccessible, etc.:
-+    static final private java.security.Permission ACCESS_PERMISSION =
-+        new ReflectPermission("suppressAccessChecks");
-+
-+    /**
-      * A <em>lookup object</em> is a factory for creating method handles,
-      * when the creation requires access checking.
-      * Method handles do not perform
-@@ -651,6 +682,7 @@
-                 return invoker(type);
-             if ("invokeExact".equals(name))
-                 return exactInvoker(type);
-+            assert(!MemberName.isMethodHandleInvokeName(name));
-             return null;
-         }
- 
-@@ -896,6 +928,10 @@
-          * @throws NullPointerException if the argument is null
-          */
-         public MethodHandle unreflect(Method m) throws IllegalAccessException {
-+            if (m.getDeclaringClass() == MethodHandle.class) {
-+                MethodHandle mh = unreflectForMH(m);
-+                if (mh != null)  return mh;
-+            }
-             MemberName method = new MemberName(m);
-             byte refKind = method.getReferenceKind();
-             if (refKind == REF_invokeSpecial)
-@@ -904,6 +940,12 @@
-             Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
-             return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method));
-         }
-+        private MethodHandle unreflectForMH(Method m) {
-+            // these names require special lookups because they throw UnsupportedOperationException
-+            if (MemberName.isMethodHandleInvokeName(m.getName()))
-+                return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
-+            return null;
-+        }
- 
-         /**
-          * Produces a method handle for a reflected method.
-@@ -1008,6 +1050,46 @@
-             return unreflectField(f, true);
-         }
- 
-+        /**
-+         * Cracks a direct method handle created by this lookup object or a similar one.
-+         * Security and access checks are performed to ensure that this lookup object
-+         * is capable of reproducing the target method handle.
-+         * This means that the cracking may fail if target is a direct method handle
-+         * but was created by an unrelated lookup object.
-+         * @param target a direct method handle to crack into symbolic reference components
-+         * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object
-+         * @exception SecurityException if a security manager is present and it
-+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-+         * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
-+         * @exception NullPointerException if the target is {@code null}
-+         * @since 1.8
-+         */
-+        public MethodHandleInfo revealDirect(MethodHandle target) {
-+            MemberName member = target.internalMemberName();
-+            if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
-+                throw newIllegalArgumentException("not a direct method handle");
-+            Class<?> defc = member.getDeclaringClass();
-+            byte refKind = member.getReferenceKind();
-+            assert(MethodHandleNatives.refKindIsValid(refKind));
-+            if (refKind == REF_invokeSpecial && !target.isInvokeSpecial())
-+                // Devirtualized method invocation is usually formally virtual.
-+                // To avoid creating extra MemberName objects for this common case,
-+                // we encode this extra degree of freedom using MH.isInvokeSpecial.
-+                refKind = REF_invokeVirtual;
-+            if (refKind == REF_invokeVirtual && defc.isInterface())
-+                // Symbolic reference is through interface but resolves to Object method (toString, etc.)
-+                refKind = REF_invokeInterface;
-+            // Check SM permissions and member access before cracking.
-+            try {
-+                checkSecurityManager(defc, member);
-+                checkAccess(refKind, defc, member);
-+            } catch (IllegalAccessException ex) {
-+                throw new IllegalArgumentException(ex);
-+            }
-+            // Produce the handle to the results.
-+            return new InfoFromMemberName(this, member, refKind);
-+        }
-+
-         /// Helper methods, all package-private.
- 
-         MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
-@@ -1244,12 +1326,12 @@
-         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
-                                                    boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
-             checkMethod(refKind, refc, method);
--            if (method.isMethodHandleInvoke())
--                return fakeMethodHandleInvoke(method);
-+            assert(!method.isMethodHandleInvoke());
- 
-             Class<?> refcAsSuper;
-             if (refKind == REF_invokeSpecial &&
-                 refc != lookupClass() &&
-+                !refc.isInterface() &&
-                 refc != (refcAsSuper = lookupClass().getSuperclass()) &&
-                 refc.isAssignableFrom(lookupClass())) {
-                 assert(!method.getName().equals("<init>"));  // not this code path
-@@ -1277,9 +1359,6 @@
-                 mh = restrictReceiver(method, mh, lookupClass());
-             return mh;
-         }
--        private MethodHandle fakeMethodHandleInvoke(MemberName method) {
--            return throwException(method.getReturnType(), UnsupportedOperationException.class);
--        }
-         private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
-                                              Class<?> callerClass)
-                                              throws IllegalAccessException {
-diff --git a/src/share/classes/java/lang/invoke/SerializedLambda.java b/src/share/classes/java/lang/invoke/SerializedLambda.java
---- a/src/share/classes/java/lang/invoke/SerializedLambda.java
-+++ b/src/share/classes/java/lang/invoke/SerializedLambda.java
-@@ -189,9 +189,9 @@
-     public String toString() {
-         return String.format("SerializedLambda[capturingClass=%s, functionalInterfaceMethod=%s %s.%s:%s, " +
-                              "implementation=%s %s.%s:%s, instantiatedMethodType=%s, numCaptured=%d]",
--                             capturingClass, MethodHandleInfo.getReferenceKindString(functionalInterfaceMethodKind),
-+                             capturingClass, MethodHandleInfo.referenceKindToString(functionalInterfaceMethodKind),
-                              functionalInterfaceClass, functionalInterfaceMethodName, functionalInterfaceMethodSignature,
--                             MethodHandleInfo.getReferenceKindString(implMethodKind), implClass, implMethodName,
-+                             MethodHandleInfo.referenceKindToString(implMethodKind), implClass, implMethodName,
-                              implMethodSignature, instantiatedMethodType, capturedArgs.length);
-     }
- }
-diff --git a/test/java/lang/invoke/7087570/Test7087570.java b/test/java/lang/invoke/7087570/Test7087570.java
---- a/test/java/lang/invoke/7087570/Test7087570.java
-+++ b/test/java/lang/invoke/7087570/Test7087570.java
-@@ -35,20 +35,9 @@
- 
- import static java.lang.invoke.MethodHandles.*;
- import static java.lang.invoke.MethodType.*;
-+import static java.lang.invoke.MethodHandleInfo.*;
- 
- public class Test7087570 {
--    // XXX may remove the following constant declarations when MethodHandleInfo is made public
--    private static final int
--            REF_getField                = 1,
--            REF_getStatic               = 2,
--            REF_putField                = 3,
--            REF_putStatic               = 4,
--            REF_invokeVirtual           = 5,
--            REF_invokeStatic            = 6,
--            REF_invokeSpecial           = 7,
--            REF_newInvokeSpecial        = 8,
--            REF_invokeInterface         = 9,
--            REF_LIMIT                  = 10;
- 
-     private static final TestMethodData[] TESTS = new TestMethodData[] {
-         // field accessors
-@@ -87,17 +76,17 @@
-     }
- 
-     private static void doTest(MethodHandle mh, TestMethodData testMethod) {
--        Object mhi = newMethodHandleInfo(mh);
-+        MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
- 
-         System.out.printf("%s.%s: %s, nominal refKind: %s, actual refKind: %s\n",
-                           testMethod.clazz.getName(), testMethod.name, testMethod.methodType,
--                          REF_KIND_NAMES[testMethod.referenceKind],
--                          REF_KIND_NAMES[getReferenceKind(mhi)]);
--        assertEquals(testMethod.name,           getName(mhi));
--        assertEquals(testMethod.methodType,     getMethodType(mhi));
--        assertEquals(testMethod.declaringClass, getDeclaringClass(mhi));
-+                          referenceKindToString(testMethod.referenceKind),
-+                          referenceKindToString(mhi.getReferenceKind()));
-+        assertEquals(testMethod.name,           mhi.getName());
-+        assertEquals(testMethod.methodType,     mhi.getMethodType());
-+        assertEquals(testMethod.declaringClass, mhi.getDeclaringClass());
-         assertEquals(testMethod.referenceKind == REF_invokeSpecial, isInvokeSpecial(mh));
--        assertRefKindEquals(testMethod.referenceKind,  getReferenceKind(mhi));
-+        assertRefKindEquals(testMethod.referenceKind,  mhi.getReferenceKind());
-     }
- 
-     private static void testWithLookup() throws Throwable {
-@@ -122,50 +111,8 @@
-         return methodType(void.class, clazz);
-     }
- 
--    private static final String[] REF_KIND_NAMES = {
--        "MH::invokeBasic",
--        "REF_getField", "REF_getStatic", "REF_putField", "REF_putStatic",
--        "REF_invokeVirtual", "REF_invokeStatic", "REF_invokeSpecial",
--        "REF_newInvokeSpecial", "REF_invokeInterface"
--    };
--
-     private static final Lookup LOOKUP = lookup();
- 
--    // XXX may remove the following reflective logic when MethodHandleInfo is made public
--    private static final MethodHandle MH_IS_INVOKESPECIAL;
--    private static final MethodHandle MHI_CONSTRUCTOR;
--    private static final MethodHandle MHI_GET_NAME;
--    private static final MethodHandle MHI_GET_METHOD_TYPE;
--    private static final MethodHandle MHI_GET_DECLARING_CLASS;
--    private static final MethodHandle MHI_GET_REFERENCE_KIND;
--
--    static {
--        try {
--            // This is white box testing.  Use reflection to grab private implementation bits.
--            String magicName = "IMPL_LOOKUP";
--            Field magicLookup = MethodHandles.Lookup.class.getDeclaredField(magicName);
--            // This unit test will fail if a security manager is installed.
--            magicLookup.setAccessible(true);
--            // Forbidden fruit...
--            Lookup directInvokeLookup = (Lookup) magicLookup.get(null);
--            Class<?> mhiClass = Class.forName("java.lang.invoke.MethodHandleInfo", false, MethodHandle.class.getClassLoader());
--            MH_IS_INVOKESPECIAL = directInvokeLookup
--                    .findVirtual(MethodHandle.class, "isInvokeSpecial", methodType(boolean.class));
--            MHI_CONSTRUCTOR = directInvokeLookup
--                    .findConstructor(mhiClass, methodType(void.class, MethodHandle.class));
--            MHI_GET_NAME = directInvokeLookup
--                    .findVirtual(mhiClass, "getName", methodType(String.class));
--            MHI_GET_METHOD_TYPE = directInvokeLookup
--                    .findVirtual(mhiClass, "getMethodType", methodType(MethodType.class));
--            MHI_GET_DECLARING_CLASS = directInvokeLookup
--                    .findVirtual(mhiClass, "getDeclaringClass", methodType(Class.class));
--            MHI_GET_REFERENCE_KIND = directInvokeLookup
--                    .findVirtual(mhiClass, "getReferenceKind", methodType(int.class));
--        } catch (ReflectiveOperationException ex) {
--            throw new Error(ex);
--        }
--    }
--
-     private static class TestMethodData {
-         final Class<?> clazz;
-         final String name;
-@@ -208,7 +155,9 @@
-             return LOOKUP.findStatic(testMethod.clazz, testMethod.name, testMethod.methodType);
-         case REF_invokeSpecial:
-             Class<?> thisClass = LOOKUP.lookupClass();
--            return LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass);
-+            MethodHandle smh = LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass);
-+            noteInvokeSpecial(smh);
-+            return smh;
-         case REF_newInvokeSpecial:
-             return LOOKUP.findConstructor(testMethod.clazz, testMethod.methodType);
-         default:
-@@ -238,7 +187,9 @@
-         case REF_invokeSpecial: {
-                 Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray());
-                 Class<?> thisClass = LOOKUP.lookupClass();
--                return LOOKUP.unreflectSpecial(m, thisClass);
-+                MethodHandle smh = LOOKUP.unreflectSpecial(m, thisClass);
-+                noteInvokeSpecial(smh);
-+                return smh;
-             }
-         case REF_newInvokeSpecial: {
-                 Constructor c = testMethod.clazz.getDeclaredConstructor(testMethod.methodType.parameterArray());
-@@ -249,59 +200,20 @@
-         }
-     }
- 
--    private static Object newMethodHandleInfo(MethodHandle mh) {
--        try {
--            return MHI_CONSTRUCTOR.invoke(mh);
--        } catch (Throwable ex) {
--            throw new Error(ex);
--        }
-+    private static List<MethodHandle> specialMethodHandles = new ArrayList<>();
-+    private static void noteInvokeSpecial(MethodHandle mh) {
-+        specialMethodHandles.add(mh);
-+        assert(isInvokeSpecial(mh));
-     }
--
-     private static boolean isInvokeSpecial(MethodHandle mh) {
--        try {
--            return (boolean) MH_IS_INVOKESPECIAL.invokeExact(mh);
--        } catch (Throwable ex) {
--            throw new Error(ex);
--        }
--    }
--
--    private static String getName(Object mhi) {
--        try {
--            return (String) MHI_GET_NAME.invoke(mhi);
--        } catch (Throwable ex) {
--            throw new Error(ex);
--        }
--    }
--
--    private static MethodType getMethodType(Object mhi) {
--        try {
--            return (MethodType) MHI_GET_METHOD_TYPE.invoke(mhi);
--        } catch (Throwable ex) {
--            throw new Error(ex);
--        }
--    }
--
--    private static Class<?> getDeclaringClass(Object mhi) {
--        try {
--            return (Class<?>) MHI_GET_DECLARING_CLASS.invoke(mhi);
--        } catch (Throwable ex) {
--            throw new Error(ex);
--        }
--    }
--
--    private static int getReferenceKind(Object mhi) {
--        try {
--            return (int) MHI_GET_REFERENCE_KIND.invoke(mhi);
--        } catch (Throwable ex) {
--            throw new Error(ex);
--        }
-+        return specialMethodHandles.contains(mh);
-     }
- 
-     private static void assertRefKindEquals(int expect, int observed) {
-         if (expect == observed) return;
- 
--        String msg = "expected " + REF_KIND_NAMES[(int) expect] +
--                     " but observed " + REF_KIND_NAMES[(int) observed];
-+        String msg = "expected " + referenceKindToString(expect) +
-+                     " but observed " + referenceKindToString(observed);
-         System.out.println("FAILED: " + msg);
-         throw new AssertionError(msg);
-     }
-diff --git a/test/java/lang/invoke/RevealDirectTest.java b/test/java/lang/invoke/RevealDirectTest.java
-new file mode 100644
---- /dev/null
-+++ b/test/java/lang/invoke/RevealDirectTest.java
-@@ -0,0 +1,753 @@
-+/*
-+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * This code is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 only, as
-+ * published by the Free Software Foundation.  Oracle designates this
-+ * particular file as subject to the "Classpath" exception as provided
-+ * by Oracle in the LICENSE file that accompanied this code.
-+ *
-+ * This code is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-+ * version 2 for more details (a copy is included in the LICENSE file that
-+ * accompanied this code).
-+ *
-+ * You should have received a copy of the GNU General Public License version
-+ * 2 along with this work; if not, write to the Free Software Foundation,
-+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-+ * or visit www.oracle.com if you need additional information or have any
-+ * questions.
-+ */
-+
-+/*
-+ * @test
-+ * @summary verify Lookup.revealDirect on a variety of input handles
-+ * @compile -XDignore.symbol.file RevealDirectTest.java
-+ * @run junit/othervm -ea -esa test.java.lang.invoke.RevealDirectTest
-+ *
-+ * @test
-+ * @summary verify Lookup.revealDirect on a variety of input handles, with security manager
-+ * @run main/othervm/policy=jtreg.security.policy/secure=java.lang.SecurityManager -ea -esa test.java.lang.invoke.RevealDirectTest
-+ */
-+
-+/* To run manually:
-+ * $ $JAVA8X_HOME/bin/javac -cp $JUNIT4_JAR -d ../../../.. -XDignore.symbol.file RevealDirectTest.java
-+ * $ $JAVA8X_HOME/bin/java  -cp $JUNIT4_JAR:../../../.. -ea -esa org.junit.runner.JUnitCore test.java.lang.invoke.RevealDirectTest
-+ * $ $JAVA8X_HOME/bin/java  -cp $JUNIT4_JAR:../../../.. -ea -esa    -Djava.security.manager test.java.lang.invoke.RevealDirectTest
-+ */
-+
-+package test.java.lang.invoke;
-+
-+import java.lang.reflect.*;
-+import java.lang.invoke.*;
-+import static java.lang.invoke.MethodHandles.*;
-+import static java.lang.invoke.MethodType.*;
-+import static java.lang.invoke.MethodHandleInfo.*;
-+import java.util.*;
-+import static org.junit.Assert.*;
-+import org.junit.*;
-+
-+public class RevealDirectTest {
-+    public static void main(String... av) throws Throwable {
-+        // Run the @Test methods explicitly, in case we don't want to use the JUnitCore driver.
-+        // This appears to be necessary when running with a security manager.
-+        Throwable fail = null;
-+        for (Method test : RevealDirectTest.class.getDeclaredMethods()) {
-+            if (!test.isAnnotationPresent(Test.class))  continue;
-+            try {
-+                test.invoke(new RevealDirectTest());
-+            } catch (Throwable ex) {
-+                if (ex instanceof InvocationTargetException)
-+                    ex = ex.getCause();
-+                if (fail == null)  fail = ex;
-+                System.out.println("Testcase: "+test.getName()
-+                                   +"("+test.getDeclaringClass().getName()
-+                                   +"):\tCaused an ERROR");
-+                System.out.println(ex);
-+                ex.printStackTrace(System.out);
-+            }
-+        }
-+        if (fail != null)  throw fail;
-+    }
-+
-+    public interface SimpleSuperInterface {
-+        public abstract int getInt();
-+        public static void printAll(String... args) {
-+            System.out.println(Arrays.toString(args));
-+        }
-+        public int NICE_CONSTANT = 42;
-+    }
-+    public interface SimpleInterface extends SimpleSuperInterface {
-+        default float getFloat() { return getInt(); }
-+        public static void printAll(String[] args) {
-+            System.out.println(Arrays.toString(args));
-+        }
-+    }
-+    public static class Simple implements SimpleInterface, Cloneable {
-+        public int intField;
-+        public final int finalField;
-+        private static String stringField;
-+        public int getInt() { return NICE_CONSTANT; }
-+        private static Number getNum() { return 804; }
-+        public Simple clone() {
-+            try {
-+                return (Simple) super.clone();
-+            } catch (CloneNotSupportedException ex) {
-+                throw new RuntimeException(ex);
-+            }
-+        }
-+        Simple() { finalField = -NICE_CONSTANT; }
-+        private static Lookup localLookup() { return lookup(); }
-+        private static List<Member> members() { return getMembers(lookup().lookupClass()); };
-+    }
-+
-+    static boolean VERBOSE = false;
-+
-+    @Test public void testSimple() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testSimple");
-+        testOnMembers("testSimple", Simple.members(), Simple.localLookup());
-+    }
-+    @Test public void testPublicLookup() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testPublicLookup");
-+        List<Member> mems = publicOnly(Simple.members());
-+        Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup();
-+        testOnMembers("testPublicLookup/1", mems, pubLookup);
-+        // reveal using publicLookup:
-+        testOnMembers("testPublicLookup/2", mems, privLookup, pubLookup);
-+        // lookup using publicLookup, but reveal using private:
-+        testOnMembers("testPublicLookup/3", mems, pubLookup, privLookup);
-+    }
-+    @Test public void testPublicLookupNegative() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testPublicLookupNegative");
-+        List<Member> mems = nonPublicOnly(Simple.members());
-+        Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup();
-+        testOnMembersNoLookup("testPublicLookupNegative/1", mems, pubLookup);
-+        testOnMembersNoReveal("testPublicLookupNegative/2", mems, privLookup, pubLookup);
-+        testOnMembersNoReflect("testPublicLookupNegative/3", mems, privLookup, pubLookup);
-+    }
-+    @Test public void testJavaLangClass() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testJavaLangClass");
-+        List<Member> mems = callerSensitive(false, publicOnly(getMembers(Class.class)));
-+        mems = limit(20, mems);
-+        testOnMembers("testJavaLangClass", mems, Simple.localLookup());
-+    }
-+    @Test public void testCallerSensitive() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testCallerSensitive");
-+        List<Member> mems = union(getMembers(MethodHandles.class, "lookup"),
-+                                  getMembers(Method.class, "invoke"),
-+                                  getMembers(Field.class, "get", "set", "getLong"),
-+                                  getMembers(Class.class));
-+        mems = callerSensitive(true, publicOnly(mems));
-+        mems = limit(10, mems);
-+        testOnMembers("testCallerSensitive", mems, Simple.localLookup());
-+    }
-+    @Test public void testCallerSensitiveNegative() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testCallerSensitiveNegative");
-+        List<Member> mems = union(getMembers(MethodHandles.class, "lookup"),
-+                                  getMembers(Class.class, "forName"),
-+                                  getMembers(Method.class, "invoke"));
-+        mems = callerSensitive(true, publicOnly(mems));
-+        // CS methods cannot be looked up with publicLookup
-+        testOnMembersNoLookup("testCallerSensitiveNegative", mems, publicLookup());
-+    }
-+    @Test public void testMethodHandleNatives() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testMethodHandleNatives");
-+        List<Member> mems = getMembers(MethodHandle.class, "invoke", "invokeExact");
-+        testOnMembers("testMethodHandleNatives", mems, Simple.localLookup());
-+    }
-+    @Test public void testMethodHandleInvokes() throws Throwable {
-+        if (VERBOSE)  System.out.println("@Test testMethodHandleInvokes");
-+        List<MethodType> types = new ArrayList<>();
-+        Class<?>[] someParamTypes = { void.class, int.class, Object.class, Object[].class };
-+        for (Class<?> rt : someParamTypes) {
-+            for (Class<?> p0 : someParamTypes) {
-+                if (p0 == void.class) { types.add(methodType(rt)); continue; }
-+                for (Class<?> p1 : someParamTypes) {
-+                    if (p1 == void.class) { types.add(methodType(rt, p0)); continue; }
-+                    for (Class<?> p2 : someParamTypes) {
-+                        if (p2 == void.class) { types.add(methodType(rt, p0, p1)); continue; }
-+                        types.add(methodType(rt, p0, p1, p2));
-+                    }
-+                }
-+            }
-+        }
-+        List<Member> mems = union(getPolyMembers(MethodHandle.class, "invoke", types),
-+                                  getPolyMembers(MethodHandle.class, "invokeExact", types));
-+        testOnMembers("testMethodHandleInvokes/1", mems, Simple.localLookup());
-+        testOnMembers("testMethodHandleInvokes/2", mems, publicLookup());
-+    }
-+
-+    static List<Member> getPolyMembers(Class<?> cls, String name, List<MethodType> types) {
-+        assert(cls == MethodHandle.class);
-+        ArrayList<Member> mems = new ArrayList<>();
-+        for (MethodType type : types) {
-+            mems.add(new SignaturePolymorphicMethod(name, type));
-+        }
-+        return mems;
-+    }
-+    static List<Member> getMembers(Class<?> cls) {
-+        return getMembers(cls, (String[]) null);
-+    }
-+    static List<Member> getMembers(Class<?> cls, String... onlyNames) {
-+        List<String> names = (onlyNames == null || onlyNames.length == 0 ? null : Arrays.asList(onlyNames));
-+        ArrayList<Member> res = new ArrayList<>();
-+        for (Class<?> sup : getSupers(cls)) {
-+            res.addAll(getDeclaredMembers(sup, "getDeclaredFields"));
-+            res.addAll(getDeclaredMembers(sup, "getDeclaredMethods"));
-+            res.addAll(getDeclaredMembers(sup, "getDeclaredConstructors"));
-+        }
-+        res = new ArrayList<>(new LinkedHashSet<>(res));
-+        for (int i = 0; i < res.size(); i++) {
-+            Member mem = res.get(i);
-+            if (!canBeReached(mem, cls) ||
-+                res.indexOf(mem) != i ||
-+                mem.isSynthetic() ||
-+                (names != null && !names.contains(mem.getName()))
-+                ) {
-+                res.remove(i--);
-+            }
-+        }
-+        return res;
-+    }
-+    static List<Class<?>> getSupers(Class<?> cls) {
-+        ArrayList<Class<?>> res = new ArrayList<>();
-+        ArrayList<Class<?>> intfs = new ArrayList<>();
-+        for (Class<?> sup = cls; sup != null; sup = sup.getSuperclass()) {
-+            res.add(sup);
-+            for (Class<?> intf : cls.getInterfaces()) {
-+                if (!intfs.contains(intf))
-+                    intfs.add(intf);
-+            }
-+        }
-+        for (int i = 0; i < intfs.size(); i++) {
-+            for (Class<?> intf : intfs.get(i).getInterfaces()) {
-+                if (!intfs.contains(intf))
-+                    intfs.add(intf);
-+            }
-+        }
-+        res.addAll(intfs);
-+        //System.out.println("getSupers => "+res);
-+        return res;
-+    }
-+    static boolean hasSM() {
-+        return (System.getSecurityManager() != null);
-+    }
-+    static List<Member> getDeclaredMembers(Class<?> cls, String accessor) {
-+        Member[] mems = {};
-+        Method getter = getMethod(Class.class, accessor);
-+        if (hasSM()) {
-+            try {
-+                mems = (Member[]) invokeMethod(getter, cls);
-+            } catch (SecurityException ex) {
-+                //if (VERBOSE)  ex.printStackTrace();
-+                accessor = accessor.replace("Declared", "");
-+                getter = getMethod(Class.class, accessor);
-+                if (VERBOSE)  System.out.println("replaced accessor: "+getter);
-+            }
-+        }
-+        if (mems.length == 0) {
-+            try {
-+                mems = (Member[]) invokeMethod(getter, cls);
-+            } catch (SecurityException ex) {
-+                ex.printStackTrace();
-+            }
-+        }
-+        if (VERBOSE)  System.out.println(accessor+" "+cls.getName()+" => "+mems.length+" members");
-+        return Arrays.asList(mems);
-+    }
-+    static Method getMethod(Class<?> cls, String name) {
-+        try {
-+            return cls.getMethod(name);
-+        } catch (ReflectiveOperationException ex) {
-+            throw new AssertionError(ex);
-+        }
-+    }
-+    static Object invokeMethod(Method m, Object recv, Object... args) {
-+        try {
-+            return m.invoke(recv, args);
-+        } catch (InvocationTargetException ex) {
-+            Throwable ex2 = ex.getCause();
-+            if (ex2 instanceof RuntimeException)  throw (RuntimeException) ex2;
-+            if (ex2 instanceof Error)  throw (Error) ex2;
-+            throw new AssertionError(ex);
-+        } catch (ReflectiveOperationException ex) {
-+            throw new AssertionError(ex);
-+        }
-+    }
-+
-+    static List<Member> limit(int len, List<Member> mems) {
-+        if (mems.size() <= len)  return mems;
-+        return mems.subList(0, len);
-+    }
-+    @SafeVarargs
-+    static List<Member> union(List<Member> mems, List<Member>... mem2s) {
-+        for (List<Member> mem2 : mem2s) {
-+            for (Member m : mem2) {
-+                if (!mems.contains(m))
-+                    mems.add(m);
-+            }
-+        }
-+        return mems;
-+    }
-+    static List<Member> callerSensitive(boolean cond, List<Member> members) {
-+        for (Iterator<Member> i = members.iterator(); i.hasNext(); ) {
-+            Member mem = i.next();
-+            if (isCallerSensitive(mem) != cond)
-+                i.remove();
-+        }
-+        if (members.isEmpty())  throw new AssertionError("trivial result");
-+        return members;
-+    }
-+    static boolean isCallerSensitive(Member mem) {
-+        if (!(mem instanceof AnnotatedElement))  return false;
-+        AnnotatedElement ae = (AnnotatedElement) mem;
-+        if (CS_CLASS != null)
-+            return ae.isAnnotationPresent(sun.reflect.CallerSensitive.class);
-+        for (java.lang.annotation.Annotation a : ae.getDeclaredAnnotations()) {
-+            if (a.toString().contains(".CallerSensitive"))
-+                return true;
-+        }
-+        return false;
-+    }
-+    static final Class<?> CS_CLASS;
-+    static {
-+        Class<?> c = null;
-+        try {
-+            c = sun.reflect.CallerSensitive.class;
-+        } catch (SecurityException | LinkageError ex) {
-+        }
-+        CS_CLASS = c;
-+    }
-+    static List<Member> publicOnly(List<Member> members) {
-+        return removeMods(members, Modifier.PUBLIC, 0);
-+    }
-+    static List<Member> nonPublicOnly(List<Member> members) {
-+        return removeMods(members, Modifier.PUBLIC, -1);
-+    }
-+    static List<Member> removeMods(List<Member> members, int mask, int bits) {
-+        int publicMods = (mask & Modifier.PUBLIC);
-+        members = new ArrayList<>(members);
-+        for (Iterator<Member> i = members.iterator(); i.hasNext(); ) {
-+            Member mem = i.next();
-+            int mods = mem.getModifiers();
-+            if ((publicMods & mods) != 0 &&
-+                (publicMods & mem.getDeclaringClass().getModifiers()) == 0)
-+                mods -= publicMods;
-+            if ((mods & mask) == (bits & mask))
-+                i.remove();
-+        }
-+        return members;
-+    }
-+
-+    void testOnMembers(String tname, List<Member> mems, Lookup lookup, Lookup... lookups) throws Throwable {
-+        if (VERBOSE)  System.out.println("testOnMembers "+mems);
-+        Lookup revLookup = (lookups.length > 0) ? lookups[0] : null;
-+        if (revLookup == null)  revLookup = lookup;
-+        Lookup refLookup = (lookups.length > 1) ? lookups[1] : null;
-+        if (refLookup == null)  refLookup = lookup;
-+        assert(lookups.length <= 2);
-+        testOnMembersImpl(tname, mems, lookup, revLookup, refLookup, NO_FAIL);
-+    }
-+    void testOnMembersNoLookup(String tname, List<Member> mems, Lookup lookup) throws Throwable {
-+        if (VERBOSE)  System.out.println("testOnMembersNoLookup "+mems);
-+        testOnMembersImpl(tname, mems, lookup, null, null, FAIL_LOOKUP);
-+    }
-+    void testOnMembersNoReveal(String tname, List<Member> mems,
-+                               Lookup lookup, Lookup negLookup) throws Throwable {
-+        if (VERBOSE)  System.out.println("testOnMembersNoReveal "+mems);
-+        testOnMembersImpl(tname, mems, lookup, negLookup, null, FAIL_REVEAL);
-+    }
-+    void testOnMembersNoReflect(String tname, List<Member> mems,
-+                                Lookup lookup, Lookup negLookup) throws Throwable {
-+        if (VERBOSE)  System.out.println("testOnMembersNoReflect "+mems);
-+        testOnMembersImpl(tname, mems, lookup, lookup, negLookup, FAIL_REFLECT);
-+    }
-+    void testOnMembersImpl(String tname, List<Member> mems,
-+                           Lookup lookup,
-+                           Lookup revLookup,
-+                           Lookup refLookup,
-+                           int failureMode) throws Throwable {
-+        Throwable fail = null;
-+        int failCount = 0;
-+        failureModeCounts = new int[FAIL_MODE_COUNT];
-+        long tm0 = System.currentTimeMillis();
-+        for (Member mem : mems) {
-+            try {
-+                testWithMember(mem, lookup, revLookup, refLookup, failureMode);
-+            } catch (Throwable ex) {
-+                if (fail == null)  fail = ex;
-+                if (++failCount > 10) { System.out.println("*** FAIL: too many failures"); break; }
-+                System.out.println("*** FAIL: "+mem+" => "+ex);
-+                if (VERBOSE)  ex.printStackTrace(System.out);
-+            }
-+        }
-+        long tm1 = System.currentTimeMillis();
-+        System.out.printf("@Test %s executed %s tests in %d ms",
-+                          tname, testKinds(failureModeCounts), (tm1-tm0)).println();
-+        if (fail != null)  throw fail;
-+    }
-+    static String testKinds(int[] modes) {
-+        int pos = modes[0], neg = -pos;
-+        for (int n : modes)  neg += n;
-+        if (neg == 0)  return pos + " positive";
-+        String negs = "";
-+        for (int n : modes)  negs += "/"+n;
-+        negs = negs.replaceFirst("/"+pos+"/", "");
-+        negs += " negative";
-+        if (pos == 0)  return negs;
-+        return pos + " positive, " + negs;
-+    }
-+    static class SignaturePolymorphicMethod implements Member {  // non-reflected instance of MH.invoke*
-+        final String name;
-+        final MethodType type;
-+        SignaturePolymorphicMethod(String name, MethodType type) {
-+            this.name = name;
-+            this.type = type;
-+        }
-+        public String toString() {
-+            String typeStr = type.toString();
-+            if (isVarArgs())  typeStr = typeStr.replaceFirst("\\[\\])$", "...)");
-+            return (Modifier.toString(getModifiers())
-+                    +typeStr.substring(0, typeStr.indexOf('('))+" "
-+                    +getDeclaringClass().getTypeName()+"."
-+                    +getName()+typeStr.substring(typeStr.indexOf('(')));
-+        }
-+        public boolean equals(Object x) {
-+            return (x instanceof SignaturePolymorphicMethod && equals((SignaturePolymorphicMethod)x));
-+        }
-+        public boolean equals(SignaturePolymorphicMethod that) {
-+            return this.name.equals(that.name) && this.type.equals(that.type);
-+        }
-+        public int hashCode() {
-+            return name.hashCode() * 31 + type.hashCode();
-+        }
-+        public Class<?> getDeclaringClass() { return MethodHandle.class; }
-+        public String getName() { return name; }
-+        public MethodType getMethodType() { return type; }
-+        public int getModifiers() { return Modifier.PUBLIC | Modifier.FINAL | Modifier.NATIVE | SYNTHETIC; }
-+        public boolean isVarArgs() { return Modifier.isTransient(getModifiers()); }
-+        public boolean isSynthetic() { return true; }
-+        public Class<?> getReturnType() { return type.returnType(); }
-+        public Class<?>[] getParameterTypes() { return type.parameterArray(); }
-+        static final int SYNTHETIC = 0x00001000;
-+    }
-+    static class UnreflectResult {  // a tuple
-+        final MethodHandle mh;
-+        final Throwable ex;
-+        final byte kind;
-+        final Member mem;
-+        final int var;
-+        UnreflectResult(MethodHandle mh, byte kind, Member mem, int var) {
-+            this.mh = mh;
-+            this.ex = null;
-+            this.kind = kind;
-+            this.mem = mem;
-+            this.var = var;
-+        }
-+        UnreflectResult(Throwable ex, byte kind, Member mem, int var) {
-+            this.mh = null;
-+            this.ex = ex;
-+            this.kind = kind;
-+            this.mem = mem;
-+            this.var = var;
-+        }
-+        public String toString() {
-+            return toInfoString()+"/v"+var;
-+        }
-+        public String toInfoString() {
-+            return String.format("%s %s.%s:%s", MethodHandleInfo.referenceKindToString(kind),
-+                                 mem.getDeclaringClass().getName(), name(mem), type(mem, kind));
-+        }
-+        static String name(Member mem) {
-+            if (mem instanceof Constructor)  return "<init>";
-+            return mem.getName();
-+        }
-+        static MethodType type(Member mem, byte kind) {
-+            if (mem instanceof Field) {
-+                Class<?> type = ((Field)mem).getType();
-+                if (kind == REF_putStatic || kind == REF_putField)
-+                    return methodType(void.class, type);
-+                return methodType(type);
-+            } else if (mem instanceof SignaturePolymorphicMethod) {
-+                return ((SignaturePolymorphicMethod)mem).getMethodType();
-+            }
-+            Class<?>[] params = ((Executable)mem).getParameterTypes();
-+            if (mem instanceof Constructor)
-+                return methodType(void.class, params);
-+            Class<?> type = ((Method)mem).getReturnType();
-+            return methodType(type, params);
-+        }
-+    }
-+    static UnreflectResult unreflectMember(Lookup lookup, Member mem, int variation) {
-+        byte[] refKind = {0};
-+        try {
-+            return unreflectMemberOrThrow(lookup, mem, variation, refKind);
-+        } catch (ReflectiveOperationException|SecurityException ex) {
-+            return new UnreflectResult(ex, refKind[0], mem, variation);
-+        }
-+    }
-+    static UnreflectResult unreflectMemberOrThrow(Lookup lookup, Member mem, int variation,
-+                                                  byte[] refKind) throws ReflectiveOperationException {
-+        Class<?> cls = lookup.lookupClass();
-+        Class<?> defc = mem.getDeclaringClass();
-+        String   name = mem.getName();
-+        int      mods = mem.getModifiers();
-+        boolean isStatic = Modifier.isStatic(mods);
-+        MethodHandle mh = null;
-+        byte kind = 0;
-+        if (mem instanceof Method) {
-+            Method m = (Method) mem;
-+            MethodType type = methodType(m.getReturnType(), m.getParameterTypes());
-+            boolean canBeSpecial = (!isStatic &&
-+                                    (lookup.lookupModes() & Modifier.PRIVATE) != 0 &&
-+                                    defc.isAssignableFrom(cls) &&
-+                                    (!defc.isInterface() || Arrays.asList(cls.getInterfaces()).contains(defc)));
-+            if (variation >= 2)
-+                kind = REF_invokeSpecial;
-+            else if (isStatic)
-+                kind = REF_invokeStatic;
-+            else if (defc.isInterface())
-+                kind = REF_invokeInterface;
-+            else
-+                kind = REF_invokeVirtual;
-+            refKind[0] = kind;
-+            switch (variation) {
-+            case 0:
-+                mh = lookup.unreflect(m);
-+                break;
-+            case 1:
-+                if (defc == MethodHandle.class &&
-+                    !isStatic &&
-+                    m.isVarArgs() &&
-+                    Modifier.isFinal(mods) &&
-+                    Modifier.isNative(mods)) {
-+                    break;
-+                }
-+                if (isStatic)
-+                    mh = lookup.findStatic(defc, name, type);
-+                else
-+                    mh = lookup.findVirtual(defc, name, type);
-+                break;
-+            case 2:
-+                if (!canBeSpecial)
-+                    break;
-+                mh = lookup.unreflectSpecial(m, lookup.lookupClass());
-+                break;
-+            case 3:
-+                if (!canBeSpecial)
-+                    break;
-+                mh = lookup.findSpecial(defc, name, type, lookup.lookupClass());
-+                break;
-+            }
-+        } else if (mem instanceof SignaturePolymorphicMethod) {
-+            SignaturePolymorphicMethod m = (SignaturePolymorphicMethod) mem;
-+            MethodType type = methodType(m.getReturnType(), m.getParameterTypes());
-+            kind = REF_invokeVirtual;
-+            refKind[0] = kind;
-+            switch (variation) {
-+            case 0:
-+                mh = lookup.findVirtual(defc, name, type);
-+                break;
-+            }
-+        } else if (mem instanceof Constructor) {
-+            name = "<init>";  // not used
-+            Constructor<?> m = (Constructor<?>) mem;
-+            MethodType type = methodType(void.class, m.getParameterTypes());
-+            kind = REF_newInvokeSpecial;
-+            refKind[0] = kind;
-+            switch (variation) {
-+            case 0:
-+                mh = lookup.unreflectConstructor(m);
-+                break;
-+            case 1:
-+                mh = lookup.findConstructor(defc, type);
-+                break;
-+            }
-+        } else if (mem instanceof Field) {
-+            Field m = (Field) mem;
-+            Class<?> type = m.getType();
-+            boolean canHaveSetter = !Modifier.isFinal(mods);
-+            if (variation >= 2)
-+                kind = (byte)(isStatic ? REF_putStatic : REF_putField);
-+            else
-+                kind = (byte)(isStatic ? REF_getStatic : REF_getField);
-+            refKind[0] = kind;
-+            switch (variation) {
-+            case 0:
-+                mh = lookup.unreflectGetter(m);
-+                break;
-+            case 1:
-+                if (isStatic)
-+                    mh = lookup.findStaticGetter(defc, name, type);
-+                else
-+                    mh = lookup.findGetter(defc, name, type);
-+                break;
-+            case 3:
-+                if (!canHaveSetter)
-+                    break;
-+                mh = lookup.unreflectSetter(m);
-+                break;
-+            case 2:
-+                if (!canHaveSetter)
-+                    break;
-+                if (isStatic)
-+                    mh = lookup.findStaticSetter(defc, name, type);
-+                else
-+                    mh = lookup.findSetter(defc, name, type);
-+                break;
-+            }
-+        } else {
-+            throw new IllegalArgumentException(String.valueOf(mem));
-+        }
-+        if (mh == null)
-+            // ran out of valid variations; return null to caller
-+            return null;
-+        return new UnreflectResult(mh, kind, mem, variation);
-+    }
-+    static boolean canBeReached(Member mem, Class<?> cls) {
-+        Class<?> defc = mem.getDeclaringClass();
-+        String   name = mem.getName();
-+        int      mods = mem.getModifiers();
-+        if (mem instanceof Constructor) {
-+            name = "<init>";  // according to 292 spec.
-+        }
-+        if (defc == cls)
-+            return true;
-+        if (name.startsWith("<"))
-+            return false;  // only my own constructors
-+        if (Modifier.isPrivate(mods))
-+            return false;  // only my own constructors
-+        if (defc.getPackage() == cls.getPackage())
-+            return true;   // package access or greater OK
-+        if (Modifier.isPublic(mods))
-+            return true;   // publics always OK
-+        if (Modifier.isProtected(mods) && defc.isAssignableFrom(cls))
-+            return true;   // protected OK
-+        return false;
-+    }
-+    static boolean consistent(UnreflectResult res, MethodHandleInfo info) {
-+        assert(res.mh != null);
-+        assertEquals(res.kind, info.getReferenceKind());
-+        assertEquals(res.mem.getModifiers(), info.getModifiers());
-+        assertEquals(res.mem.getDeclaringClass(), info.getDeclaringClass());
-+        String expectName = res.mem.getName();
-+        if (res.kind == REF_newInvokeSpecial)
-+            expectName = "<init>";
-+        assertEquals(expectName, info.getName());
-+        MethodType expectType = res.mh.type();
-+        if ((res.kind & 1) == (REF_getField & 1))
-+            expectType = expectType.dropParameterTypes(0, 1);
-+        if (res.kind == REF_newInvokeSpecial)
-+            expectType = expectType.changeReturnType(void.class);
-+        assertEquals(expectType, info.getMethodType());
-+        assertEquals(res.mh.isVarargsCollector(), isVarArgs(info));
-+        assertEquals(res.toInfoString(), info.toString());
-+        assertEquals(res.toInfoString(), MethodHandleInfo.toString(info.getReferenceKind(), info.getDeclaringClass(), info.getName(), info.getMethodType()));
-+        return true;
-+    }
-+    static boolean isVarArgs(MethodHandleInfo info) {
-+        return info.isVarArgs();
-+    }
-+    static boolean consistent(Member mem, Member mem2) {
-+        assertEquals(mem, mem2);
-+        return true;
-+    }
-+    static boolean consistent(MethodHandleInfo info, MethodHandleInfo info2) {
-+        assertEquals(info.getReferenceKind(), info2.getReferenceKind());
-+        assertEquals(info.getModifiers(), info2.getModifiers());
-+        assertEquals(info.getDeclaringClass(), info2.getDeclaringClass());
-+        assertEquals(info.getName(), info2.getName());
-+        assertEquals(info.getMethodType(), info2.getMethodType());
-+        assertEquals(isVarArgs(info), isVarArgs(info));
-+        return true;
-+    }
-+    static boolean consistent(MethodHandle mh, MethodHandle mh2) {
-+        assertEquals(mh.type(), mh2.type());
-+        assertEquals(mh.isVarargsCollector(), mh2.isVarargsCollector());
-+        return true;
-+    }
-+    int[] failureModeCounts;
-+    static final int NO_FAIL=0, FAIL_LOOKUP=1, FAIL_REVEAL=2, FAIL_REFLECT=3, FAIL_MODE_COUNT=4;
-+    void testWithMember(Member mem,
-+                        Lookup lookup,      // initial lookup of member => MH
-+                        Lookup revLookup,   // reveal MH => info
-+                        Lookup refLookup,   // reflect info => member
-+                        int failureMode) throws Throwable {
-+        boolean expectEx1 = (failureMode == FAIL_LOOKUP);   // testOnMembersNoLookup
-+        boolean expectEx2 = (failureMode == FAIL_REVEAL);   // testOnMembersNoReveal
-+        boolean expectEx3 = (failureMode == FAIL_REFLECT);  // testOnMembersNoReflect
-+        for (int variation = 0; ; variation++) {
-+            UnreflectResult res = unreflectMember(lookup, mem, variation);
-+            failureModeCounts[failureMode] += 1;
-+            if (variation == 0)  assert(res != null);
-+            if (res == null)  break;
-+            if (VERBOSE && variation == 0)
-+                System.out.println("from "+mem.getDeclaringClass().getSimpleName());
-+            MethodHandle mh = res.mh;
-+            Throwable   ex1 = res.ex;
-+            if (VERBOSE)  System.out.println("  "+variation+": "+res+"  << "+(mh != null ? mh : ex1));
-+            if (expectEx1 && ex1 != null)
-+                continue;  // this is OK; we expected that lookup to fail
-+            if (expectEx1)
-+                throw new AssertionError("unexpected lookup for negative test");
-+            if (ex1 != null && !expectEx1) {
-+                if (failureMode != NO_FAIL)
-+                    throw new AssertionError("unexpected lookup failure for negative test", ex1);
-+                throw ex1;
-+            }
-+            MethodHandleInfo info;
-+            try {
-+                info = revLookup.revealDirect(mh);
-+                if (expectEx2)  throw new AssertionError("unexpected revelation for negative test");
-+            } catch (Throwable ex2) {
-+                if (VERBOSE)  System.out.println("  "+variation+": "+res+" => "+mh.getClass().getName()+" => (EX2)"+ex2);
-+                if (expectEx2)
-+                    continue;  // this is OK; we expected the reflect to fail
-+                if (failureMode != NO_FAIL)
-+                    throw new AssertionError("unexpected revelation failure for negative test", ex2);
-+                throw ex2;
-+            }
-+            assert(consistent(res, info));
-+            Member mem2;
-+            try {
-+                mem2 = info.reflectAs(Member.class, refLookup);
-+                if (expectEx3)  throw new AssertionError("unexpected reflection for negative test");
-+                assert(!(mem instanceof SignaturePolymorphicMethod));
-+            } catch (IllegalArgumentException ex3) {
-+                if (VERBOSE)  System.out.println("  "+variation+": "+info+" => (EX3)"+ex3);
-+                if (expectEx3)
-+                    continue;  // this is OK; we expected the reflect to fail
-+                if (mem instanceof SignaturePolymorphicMethod)
-+                    continue;  // this is OK; we cannot reflect MH.invokeExact(a,b,c)
-+                if (failureMode != NO_FAIL)
-+                    throw new AssertionError("unexpected reflection failure for negative test", ex3);
-+                throw ex3;
-+            }
-+            assert(consistent(mem, mem2));
-+            UnreflectResult res2 = unreflectMember(lookup, mem2, variation);
-+            MethodHandle mh2 = res2.mh;
-+            assert(consistent(mh, mh2));
-+            MethodHandleInfo info2 = lookup.revealDirect(mh2);
-+            assert(consistent(info, info2));
-+            assert(consistent(res, info2));
-+            Member mem3;
-+            if (hasSM())
-+                mem3 = info2.reflectAs(Member.class, lookup);
-+            else
-+                mem3 = MethodHandles.reflectAs(Member.class, mh2);
-+            assert(consistent(mem2, mem3));
-+            if (hasSM()) {
-+                try {
-+                    MethodHandles.reflectAs(Member.class, mh2);
-+                    throw new AssertionError("failed to throw on "+mem3);
-+                } catch (SecurityException ex3) {
-+                    // OK...
-+                }
-+            }
-+        }
-+    }
-+}
-diff --git a/test/java/lang/invoke/jtreg.security.policy b/test/java/lang/invoke/jtreg.security.policy
-new file mode 100644
---- /dev/null
-+++ b/test/java/lang/invoke/jtreg.security.policy
-@@ -0,0 +1,9 @@
-+/*
-+ * security policy used by the test process
-+ * must allow file reads so that jtreg itself can run
-+ */
-+
-+grant {
-+  // standard test activation permissions
-+  permission java.io.FilePermission "*", "read";
-+};
--- a/meth.patch	Tue Aug 13 12:54:34 2013 -0700
+++ b/meth.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -1,8 +1,5 @@
 # Unsorted changes to method handles are entrained here.
-8001108: an attempt to use "<init>" as a method name should elicit NoSuchMethodException
-8001109: arity mismatch on a call to spreader method handle should elicit WrongMethodTypeException
-8001110: method handles should have a collectArguments transform, generalizing asCollector
-add comments where MR1 changes are likely
+- more use of factored exception builds
 
 diff --git a/src/share/classes/java/lang/invoke/CallSite.java b/src/share/classes/java/lang/invoke/CallSite.java
 --- a/src/share/classes/java/lang/invoke/CallSite.java
@@ -19,7 +16,7 @@
 diff --git a/src/share/classes/java/lang/invoke/MemberName.java b/src/share/classes/java/lang/invoke/MemberName.java
 --- a/src/share/classes/java/lang/invoke/MemberName.java
 +++ b/src/share/classes/java/lang/invoke/MemberName.java
-@@ -302,10 +302,6 @@
+@@ -301,10 +301,6 @@
          assert(getReferenceKind() == oldKind);
          assert(MethodHandleNatives.refKindIsValid(refKind));
          flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
@@ -30,118 +27,10 @@
          return this;
      }
  
-@@ -493,14 +489,14 @@
-         case REF_invokeInterface:   return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
-         case REF_newInvokeSpecial:  return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
-         }
--        throw new IllegalArgumentException(this.toString());
-+        throw newIllegalArgumentException("cannot be made special", this);
-     }
-     public MemberName asConstructor() {
-         switch (getReferenceKind()) {
-         case REF_invokeSpecial:     return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
-         case REF_newInvokeSpecial:  return this;
-         }
--        throw new IllegalArgumentException(this.toString());
-+        throw newIllegalArgumentException("cannot be made constructor", this);
-     }
-     /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
-     @SuppressWarnings("LeakingThisInConstructor")
-@@ -569,7 +565,7 @@
-      *  This may be in a super-class of the declaring class of this member.
-      */
-     public MemberName getDefinition() {
--        if (!isResolved())  throw new IllegalStateException("must be resolved: "+this);
-+        if (!isResolved())  throw newIllegalStateException("must be resolved", this);
-         if (isType())  return this;
-         MemberName res = this.clone();
-         res.clazz = null;
-@@ -613,15 +609,6 @@
-         init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
-         initResolved(false);
-     }
--    /** Create a field or type name from the given components:  Declaring class, name, type.
--     *  The declaring class may be supplied as null if this is to be a bare name and type.
--     *  The modifier flags default to zero.
--     *  The resulting name will in an unresolved state.
--     */
--    public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
--        this(defClass, name, type, REF_NONE);
--        initResolved(false);
--    }
-     /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
-      *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
-      *  The declaring class may be supplied as null if this is to be a bare name and type.
-@@ -634,15 +621,6 @@
-         init(defClass, name, type, flagsMods(flags, 0, refKind));
-         initResolved(false);
-     }
--//    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
--//     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
--//     *  The declaring class may be supplied as null if this is to be a bare name and type.
--//     *  The modifier flags default to zero.
--//     *  The resulting name will in an unresolved state.
--//     */
--//    public MemberName(Class<?> defClass, String name, MethodType type, Void unused) {
--//        this(defClass, name, type, REF_NONE);
--//    }
- 
-     /** Query whether this member name is resolved to a non-static, non-final method.
-      */
-diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java
---- a/src/share/classes/java/lang/invoke/MethodHandle.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandle.java
-@@ -31,8 +31,6 @@
- import sun.misc.Unsafe;
- 
- import static java.lang.invoke.MethodHandleStatics.*;
--import java.util.logging.Level;
--import java.util.logging.Logger;
- 
- /**
-  * A method handle is a typed, directly executable reference to an underlying method,
-@@ -804,6 +802,7 @@
-      * @throws WrongMethodTypeException if the implied {@code asType} call fails
-      * @see #asCollector
-      */
-+    //FIXME in MR1: clarify that after spreading, if there is an arity mismatch, WMTE is raised
-     public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
-         asSpreaderChecks(arrayType, arrayLength);
-         int spreadArgPos = type.parameterCount() - arrayLength;
-diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java
---- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java
-+++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java
-@@ -107,7 +107,7 @@
-         }
-         static String name(Class<?> arrayClass, boolean isSetter) {
-             Class<?> elemClass = arrayClass.getComponentType();
--            if (elemClass == null)  throw new IllegalArgumentException();
-+            if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
-             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
-         }
-         static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false;  // FIXME: decide
-@@ -460,7 +460,7 @@
-     static void checkSpreadArgument(Object av, int n) {
-         // FIXME: regression test for bug 7141637 erroneously expects an NPE, and other tests may expect IAE
-         // but the actual exception raised by an arity mismatch should be WMTE
--        final boolean RAISE_RANDOM_EXCEPTIONS = true;  // FIXME: delete in JSR 292 M1
-+        final boolean RAISE_RANDOM_EXCEPTIONS = false;  // FIXME in MR1: set this to false and remove
-         if (av == null) {
-             if (n == 0)  return;
-             int len;
-@@ -476,7 +476,7 @@
-         // fall through to error:
-         if (RAISE_RANDOM_EXCEPTIONS)
-             throw newIllegalArgumentException("Array is not of length "+n);
--        throw new WrongMethodTypeException("Array is not of length "+n);
-+        throw new WrongMethodTypeException("array is not of length "+n);
-     }
- 
-     private static final NamedFunction NF_checkSpreadArgument;
 diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
 --- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java
 +++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
-@@ -28,6 +28,7 @@
+@@ -33,6 +33,7 @@
  import sun.reflect.CallerSensitive;
  import sun.reflect.Reflection;
  import sun.reflect.misc.ReflectUtil;
@@ -149,7 +38,7 @@
  
  /**
   * This class consists exclusively of static methods that help adapt
-@@ -136,7 +137,7 @@
+@@ -143,7 +144,7 @@
      public static
      <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
          if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
@@ -158,7 +47,7 @@
          final MethodHandle mh;
          if (System.getSecurityManager() != null) {
              final Class<?> caller = Reflection.getCallerClass();
-@@ -143,7 +144,7 @@
+@@ -160,7 +161,7 @@
          }
          final Method[] methods = getSingleNameMethods(intfc);
          if (methods == null)
@@ -167,7 +56,7 @@
          final MethodHandle[] vaTargets = new MethodHandle[methods.length];
          for (int i = 0; i < methods.length; i++) {
              Method sm = methods[i];
-@@ -187,7 +188,7 @@
+@@ -235,7 +236,7 @@
                  return (WrapperInstance) x;
          } catch (ClassCastException ex) {
          }
@@ -179,73 +68,7 @@
 diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
 --- a/src/share/classes/java/lang/invoke/MethodHandles.java
 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java
-@@ -330,6 +330,7 @@
-      * </ul>
-      */
-     // FIXME in MR1: clarify that the bytecode behavior of a caller-ID method (like Class.forName) is relative to the lookupClass used to create the method handle, not the dynamic caller of the method handle
-+    // FIXME in MR1: clarify that the name "<init>" never works as a method name, even if the corresponding constructor happens to exist
-     public static final
-     class Lookup {
-         /** The class on behalf of whom the lookup is being performed. */
-@@ -644,6 +645,7 @@
-          * @throws NullPointerException if any argument is null
-          */
-         @CallerSensitive
-+        // FIXME in MR1: clarify that name="<init>" elicits a NoSuchMethodException always (ctor != method)
-         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
-             if (refc == MethodHandle.class) {
-                 MethodHandle mh = findVirtualForMH(name, type);
-@@ -729,6 +731,8 @@
-          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-          * @throws NullPointerException if any argument is null
-          */
-+        // FIXME in MR1: clarify that specialCaller access check happens first
-+        // FIXME in MR1: clarify that name="<init>" elicits a NoSuchMethodException always (ctor != method)
-         @CallerSensitive
-         public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
-                                         Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
-@@ -964,7 +968,7 @@
-          *                                is set and {@code asVarargsCollector} fails
-          * @throws NullPointerException if the argument is null
-          */
--        @SuppressWarnings("rawtypes")  // Will be Constructor<?> after JSR 292 MR
-+        @SuppressWarnings("rawtypes")  // FIXME in MR1: add wildcard to be Constructor<?>
-         public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
-             MemberName ctor = new MemberName(c);
-             assert(ctor.isConstructor());
-@@ -1019,15 +1023,16 @@
-         /// Helper methods, all package-private.
- 
-         MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
-+            name.getClass(); type.getClass();  // NPE
-             checkSymbolicClass(refc);  // do this before attempting to resolve
--            name.getClass(); type.getClass();  // NPE
-             return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
-                                             NoSuchFieldException.class);
-         }
- 
-         MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
-+            type.getClass();  // NPE
-             checkSymbolicClass(refc);  // do this before attempting to resolve
--            name.getClass(); type.getClass();  // NPE
-+            checkMethodName(refKind, name);
-             return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
-                                             NoSuchMethodException.class);
-         }
-@@ -1038,6 +1043,12 @@
-                 throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
-         }
- 
-+        void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
-+            if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
-+                throw new NoSuchMethodException("illegal method name: "+name);
-+        }
-+
-+
-         /**
-          * Find my trustable caller class if m is a caller sensitive method.
-          * If this lookup object has private access, then the caller class is the lookupClass.
-@@ -1344,7 +1355,7 @@
+@@ -1484,7 +1484,7 @@
      static public
      MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
          if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
@@ -254,19 +77,10 @@
          return type.invokers().spreadInvoker(leadingArgCount);
      }
  
-@@ -1883,7 +1894,7 @@
-         return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
-     }
- 
--    // FIXME: Make this public in M1.
-+    // FIXME in MR1: Make this a public API
-     /*non-public*/ static
-     MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle collector) {
-         MethodType targetType = target.type();
 diff --git a/src/share/classes/java/lang/invoke/MethodType.java b/src/share/classes/java/lang/invoke/MethodType.java
 --- a/src/share/classes/java/lang/invoke/MethodType.java
 +++ b/src/share/classes/java/lang/invoke/MethodType.java
-@@ -883,7 +883,7 @@
+@@ -896,7 +896,7 @@
          if (!descriptor.startsWith("(") ||  // also generates NPE if needed
              descriptor.indexOf(')') < 0 ||
              descriptor.indexOf('.') >= 0)
@@ -287,308 +101,3 @@
  
  /**
   * A method handle whose behavior is determined only by its LambdaForm.
-diff --git a/test/java/lang/invoke/MethodHandlesTest.java b/test/java/lang/invoke/MethodHandlesTest.java
---- a/test/java/lang/invoke/MethodHandlesTest.java
-+++ b/test/java/lang/invoke/MethodHandlesTest.java
-@@ -387,6 +387,7 @@
-         protected Example(String name) { this.name = name; }
-         @SuppressWarnings("LeakingThisInConstructor")
-         protected Example(int x) { this(); called("protected <init>", this, x); }
-+        //Example(Void x) { does not exist; lookup elicts NoSuchMethodException }
-         @Override public String toString() { return name; }
- 
-         public void            v0()     { called("v0", this); }
-@@ -487,6 +488,9 @@
-         return lookup.in(defc);
-     }
- 
-+    /** Is findVirtual (etc.) of "<init>" supposed to elicit a NoSuchMethodException? */
-+    final static boolean INIT_REF_CAUSES_NSME = true;
-+
-     @Test
-     public void testFindStatic() throws Throwable {
-         if (CAN_SKIP_WORKING)  return;
-@@ -507,6 +511,8 @@
-         testFindStatic(Example.class, Object.class, "s7", float.class, double.class);
- 
-         testFindStatic(false, PRIVATE, Example.class, void.class, "bogus");
-+        testFindStatic(false, PRIVATE, Example.class, void.class, "<init>", int.class);
-+        testFindStatic(false, PRIVATE, Example.class, void.class, "<init>", Void.class);
-         testFindStatic(false, PRIVATE, Example.class, void.class, "v0");
-     }
- 
-@@ -529,11 +535,12 @@
-             target = maybeMoveIn(lookup, defc).findStatic(defc, methodName, type);
-         } catch (ReflectiveOperationException ex) {
-             noAccess = ex;
-+            assertExceptionClass(
-+                (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("<init>"))
-+                ?   NoSuchMethodException.class
-+                :   IllegalAccessException.class,
-+                noAccess);
-             if (verbosity >= 5)  ex.printStackTrace(System.out);
--            if (name.contains("bogus"))
--                assertTrue(noAccess instanceof NoSuchMethodException);
--            else
--                assertTrue(noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
-@@ -551,6 +558,13 @@
-             System.out.print(':');
-     }
- 
-+    static void assertExceptionClass(Class<? extends Throwable> expected,
-+                                     Throwable actual) {
-+        if (expected.isInstance(actual))  return;
-+        actual.printStackTrace();
-+        assertEquals(expected, actual.getClass());
-+    }
-+
-     static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
- 
-     // rough check of name string
-@@ -580,6 +594,8 @@
-         testFindVirtual(PubExample.class, void.class, "Pub/pro_v0");
- 
-         testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus");
-+        testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "<init>", int.class);
-+        testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "<init>", Void.class);
-         testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "s0");
- 
-         // test dispatch
-@@ -625,11 +641,12 @@
-             target = maybeMoveIn(lookup, defc).findVirtual(defc, methodName, type);
-         } catch (ReflectiveOperationException ex) {
-             noAccess = ex;
-+            assertExceptionClass(
-+                (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("<init>"))
-+                ?   NoSuchMethodException.class
-+                :   IllegalAccessException.class,
-+                noAccess);
-             if (verbosity >= 5)  ex.printStackTrace(System.out);
--            if (name.contains("bogus"))
--                assertTrue(noAccess instanceof NoSuchMethodException);
--            else
--                assertTrue(noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
-@@ -679,11 +696,11 @@
-         testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
-         testFindSpecial(RemoteExample.class, PubExample.class, void.class, "Pub/pro_v0");
-         // Do some negative testing:
--        testFindSpecial(false, EXAMPLE, SubExample.class, Example.class, void.class, "bogus");
--        testFindSpecial(false, PRIVATE, SubExample.class, Example.class, void.class, "bogus");
-         for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
-             testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
-+            testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus");
-             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
-+            testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", Void.class);
-             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
-         }
-     }
-@@ -709,19 +726,25 @@
-         countTest(positive);
-         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
-         MethodType type = MethodType.methodType(ret, params);
-+        Lookup specialLookup = maybeMoveIn(lookup, specialCaller);
-+        boolean specialAccessOK = (specialLookup.lookupClass() == specialCaller &&
-+                                   (specialLookup.lookupModes() & Lookup.PRIVATE) != 0);
-         MethodHandle target = null;
-         Exception noAccess = null;
-         try {
-             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
--            if (verbosity >= 5)  System.out.println("  lookup => "+maybeMoveIn(lookup, specialCaller));
--            target = maybeMoveIn(lookup, specialCaller).findSpecial(defc, methodName, type, specialCaller);
-+            if (verbosity >= 5)  System.out.println("  lookup => "+specialLookup);
-+            target = specialLookup.findSpecial(defc, methodName, type, specialCaller);
-         } catch (ReflectiveOperationException ex) {
-             noAccess = ex;
-+            assertExceptionClass(
-+                (!specialAccessOK)  // this check should happen first
-+                ?   IllegalAccessException.class
-+                : (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("<init>"))
-+                ?   NoSuchMethodException.class
-+                : IllegalAccessException.class,
-+                noAccess);
-             if (verbosity >= 5)  ex.printStackTrace(System.out);
--            if (name.contains("bogus"))
--                assertTrue(noAccess instanceof NoSuchMethodException);
--            else
--                assertTrue(noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
-@@ -766,7 +789,7 @@
-             target = lookup.findConstructor(defc, type);
-         } catch (ReflectiveOperationException ex) {
-             noAccess = ex;
--            assertTrue(noAccess instanceof IllegalAccessException);
-+            assertTrue(noAccess.getClass().getName(), noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("findConstructor "+defc.getName()+".<init>/"+type+" => "+target
-@@ -797,6 +820,8 @@
-         testBind(Example.class, Object.class, "v2", int.class, Object.class);
-         testBind(Example.class, Object.class, "v2", int.class, int.class);
-         testBind(false, PRIVATE, Example.class, void.class, "bogus");
-+        testBind(false, PRIVATE, Example.class, void.class, "<init>", int.class);
-+        testBind(false, PRIVATE, Example.class, void.class, "<init>", Void.class);
-         testBind(SubExample.class, void.class, "Sub/v0");
-         testBind(SubExample.class, void.class, "Sub/pkg_v0");
-         testBind(IntExample.Impl.class, void.class, "Int/v0");
-@@ -820,11 +845,12 @@
-             target = maybeMoveIn(lookup, defc).bind(receiver, methodName, type);
-         } catch (ReflectiveOperationException ex) {
-             noAccess = ex;
-+            assertExceptionClass(
-+                (name.contains("bogus") || INIT_REF_CAUSES_NSME && name.contains("<init>"))
-+                ?   NoSuchMethodException.class
-+                :   IllegalAccessException.class,
-+                noAccess);
-             if (verbosity >= 5)  ex.printStackTrace(System.out);
--            if (name.contains("bogus"))
--                assertTrue(noAccess instanceof NoSuchMethodException);
--            else
--                assertTrue(noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
-@@ -887,6 +913,10 @@
-         countTest(positive);
-         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
-         MethodType type = MethodType.methodType(ret, params);
-+        Lookup specialLookup = (specialCaller != null ? maybeMoveIn(lookup, specialCaller) : null);
-+        boolean specialAccessOK = (specialCaller != null &&
-+                                   specialLookup.lookupClass() == specialCaller &&
-+                                   (specialLookup.lookupModes() & Lookup.PRIVATE) != 0);
-         Method rmethod = defc.getDeclaredMethod(methodName, params);
-         MethodHandle target = null;
-         Exception noAccess = null;
-@@ -895,16 +925,15 @@
-         try {
-             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
-             if (isSpecial)
--                target = maybeMoveIn(lookup, specialCaller).unreflectSpecial(rmethod, specialCaller);
-+                target = specialLookup.unreflectSpecial(rmethod, specialCaller);
-             else
-                 target = maybeMoveIn(lookup, defc).unreflect(rmethod);
-         } catch (ReflectiveOperationException ex) {
-             noAccess = ex;
-+            assertExceptionClass(
-+                IllegalAccessException.class,  // NSME is impossible, since it was already reflected
-+                noAccess);
-             if (verbosity >= 5)  ex.printStackTrace(System.out);
--            if (name.contains("bogus"))
--                assertTrue(noAccess instanceof NoSuchMethodException);
--            else
--                assertTrue(noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type
-@@ -1138,11 +1167,12 @@
-         } catch (ReflectiveOperationException ex) {
-             mh = null;
-             noAccess = ex;
-+            assertExceptionClass(
-+                (fname.contains("bogus"))
-+                ?   NoSuchFieldException.class
-+                :   IllegalAccessException.class,
-+                noAccess);
-             if (verbosity >= 5)  ex.printStackTrace(System.out);
--            if (fname.contains("bogus"))
--                assertTrue(noAccess instanceof NoSuchFieldException);
--            else
--                assertTrue(noAccess instanceof IllegalAccessException);
-         }
-         if (verbosity >= 3)
-             System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
-diff --git a/test/java/lang/invoke/BigArityTest.java b/test/java/lang/invoke/BigArityTest.java
---- a/test/java/lang/invoke/BigArityTest.java
-+++ b/test/java/lang/invoke/BigArityTest.java
-@@ -235,21 +235,41 @@
-             MethodHandle mh_VA = mh.asSpreader(cls, arity);
-             assert(mh_VA.type().parameterType(0) == cls);
-             testArities(cls, arity, iterations, verbose, mh, mh_VA);
-+            // mh_CA will collect arguments of a particular type and pass them to mh_VA
-+            MethodHandle mh_CA = mh_VA.asCollector(cls, arity);
-+            MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity);
-+            assert(mh_CA.type().equals(mh.type()));
-+            assert(mh_VA2.type().equals(mh_VA.type()));
-             if (cls != Object[].class) {
--                // mh_CA will collect arguments of a particular type and pass them to mh_VA
--                MethodHandle mh_CA = mh_VA.asCollector(cls, arity);
--                MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity);
-                 try {
-                     mh_VA2.invokeWithArguments(new Object[arity]);
-                     throw new AssertionError("should not reach");
-                 } catch (ClassCastException | WrongMethodTypeException ex) {
-                 }
--                assert(mh_CA.type().equals(mh.type()));
--                assert(mh_VA2.type().equals(mh_VA.type()));
--                testArities(cls, arity, iterations, false, mh_CA, mh_VA2);
-             }
-+            int iterations_VA = iterations / 100;
-+            testArities(cls, arity, iterations_VA, false, mh_CA, mh_VA2);
-         }
-     }
-+ 
-+   /**
-+     * Tests calls to {@link BigArityTest#hashArguments hashArguments} as related to a single given arity N.
-+     * Applies the given {@code mh} to a set of N integer arguments, checking the answer.
-+     * Also applies the varargs variation {@code mh_VA} to an array of type C[] (given by {@code cls}).
-+     * Test steps:
-+     * <ul>
-+     * <li>mh_VA.invokeExact(new C[]{ arg, ... })</li>
-+     * <li>mh.invokeWithArguments((Object[]) new C[]{ arg, ... })</li>
-+     * <li>exactInvoker(mh.type()).invokeWithArguments(new Object[]{ mh, arg, ... })</li>
-+     * <li>invoker(mh.type()).invokeWithArguments(new Object[]{ mh, arg, ... })</li>
-+     * </ul>
-+     * @param cls     array type for varargs call (one of Object[], Number[], Integer[], Comparable[])
-+     * @param arity   N, the number of arguments to {@code mh} and length of its varargs array, in [0..255]
-+     * @param iterations  number of times to repeat each test step (at least 4)
-+     * @param verbose are we printing extra output?
-+     * @param mh      a fixed-arity version of {@code hashArguments}
-+     * @param mh_VA   a variable-arity version of {@code hashArguments}, accepting the given array type {@code cls}
-+     */
-     private void testArities(Class<? extends Object[]> cls,
-                              int arity,
-                              int iterations,
-@@ -648,7 +668,6 @@
-     // </editor-fold>
-     a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
-         assertEquals(r0, r);
--        // FIXME: This next one fails, because it uses an internal invoker of arity 255.
-         r = ximh.invokeWithArguments(cat(mh,a));
-         assertEquals(r0, r);
-         MethodHandle gimh = MethodHandles.invoker(mh.type());
-@@ -674,7 +693,6 @@
-     // </editor-fold>
-     a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]);
-         assertEquals(r0, r);
--        // FIXME: This next one fails, because it uses an internal invoker of arity 255.
-         r = gimh.invokeWithArguments(cat(mh,a));
-         assertEquals(r0, r);
-         mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class));
-@@ -812,6 +830,12 @@
-         assertEquals(r0, r);
-         MethodType mt = MethodType.genericMethodType(ARITY);
-         MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt);
-+        test254(mh, a, r0);
-+        MethodHandle mh_CA = MH_hashArguments_VA.asFixedArity().asCollector(Object[].class, ARITY);
-+        test254(mh_CA, a, r0);
-+    }
-+    public void test254(MethodHandle mh, Object[] a, Object r0) throws Throwable {
-+        Object r;
-         r = mh.invokeExact(
-     // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ...">
-     a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F],
-@@ -833,7 +857,6 @@
-     // </editor-fold>
-     a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]);
-         assertEquals(r0, r);
--        // FIXME: This next one fails, because it uses an internal invoker of arity 255.
-         r = mh.invokeWithArguments(a);
-         assertEquals(r0, r);
-         try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/meth-7177472.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -0,0 +1,319 @@
+7177472: JSR292: MethodType interning penalizes scalability
+Summary: Use ConcurrentHashMap instead of regular HashMap.
+Reviewed-by: ?
+Contributed-by: aleksey.shipilev@oracle.com
+
+diff --git a/src/share/classes/java/lang/invoke/MethodType.java b/src/share/classes/java/lang/invoke/MethodType.java
+--- a/src/share/classes/java/lang/invoke/MethodType.java
++++ b/src/share/classes/java/lang/invoke/MethodType.java
+@@ -28,11 +28,13 @@
+ import sun.invoke.util.Wrapper;
+ import java.lang.ref.WeakReference;
+ import java.lang.ref.ReferenceQueue;
++import java.util.concurrent.ConcurrentHashMap;
+ import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.List;
+ import sun.invoke.util.BytecodeDescriptor;
+ import static java.lang.invoke.MethodHandleStatics.*;
++import java.lang.ref.Reference;
+ import sun.invoke.util.VerifyType;
+ 
+ /**
+@@ -990,84 +992,17 @@
+      * @see         java.util.HashSet
+      * @see         java.util.WeakHashMap
+      * @see         java.lang.ref.WeakReference
++     * @see         concurrent.ConcurrentHashMap
+      */
+     private static class WeakInternSet {
+-        // The default initial capacity -- MUST be a power of two.
+-        private static final int DEFAULT_INITIAL_CAPACITY = 16;
+-
+-        // The maximum capacity, used if a higher value is implicitly specified
+-        // by either of the constructors with arguments.
+-        // MUST be a power of two <= 1<<30.
+-        private static final int MAXIMUM_CAPACITY = 1 << 30;
+-
+-        // The load factor used when none specified in constructor.
+-        private static final float DEFAULT_LOAD_FACTOR = 0.75f;
+-
+-        // The table, resized as necessary. Length MUST Always be a power of two.
+-        private Entry[] table;
+-
+-        // The number of entries contained in this set.
+-        private int size;
+-
+-        // The next size value at which to resize (capacity * load factor).
+-        private int threshold;
+-
+-        // The load factor for the hash table.
+-        private final float loadFactor;
+-
+-        // Reference queue for cleared WeakEntries
++        private final ConcurrentHashMap<Entry, Entry> map = new ConcurrentHashMap<Entry, Entry>();
+         private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
+ 
+-        private Entry[] newTable(int n) {
+-            return new Entry[n];
+-        }
+-
+         /**
+          * Constructs a new, empty <tt>WeakInternSet</tt> with the default initial
+-         * capacity (16) and load factor (0.75).
++         * capacity and load factor, inherited from {@link ConcurrentHashMap}.
+          */
+         WeakInternSet() {
+-            this.loadFactor = DEFAULT_LOAD_FACTOR;
+-            threshold = DEFAULT_INITIAL_CAPACITY;
+-            table = newTable(DEFAULT_INITIAL_CAPACITY);
+-        }
+-
+-        /**
+-         * Applies a supplemental hash function to a given hashCode, which
+-         * defends against poor quality hash functions.  This is critical
+-         * because hashing uses power-of-two length hash tables, that
+-         * otherwise encounter collisions for hashCodes that do not differ
+-         * in lower bits.
+-         * @param h preliminary hash code value
+-         * @return supplemental hash code value
+-         */
+-        private static int hash(int h) {
+-            // This function ensures that hashCodes that differ only by
+-            // constant multiples at each bit position have a bounded
+-            // number of collisions (approximately 8 at default load factor).
+-            h ^= (h >>> 20) ^ (h >>> 12);
+-            return h ^ (h >>> 7) ^ (h >>> 4);
+-        }
+-
+-        /**
+-         * Checks for equality of non-null reference x and possibly-null y.  By
+-         * default uses Object.equals.
+-         * @param x first object to compare
+-         * @param y second object to compare
+-         * @return <tt>true</tt> if objects are equal
+-         */
+-        private static boolean eq(Object x, Object y) {
+-            return x == y || x.equals(y);
+-        }
+-
+-        /**
+-         * Returns index for hash code h.
+-         * @param h      raw hash code
+-         * @param length length of table (power of 2)
+-         * @return index in table
+-         */
+-        private static int indexFor(int h, int length) {
+-            return h & (length-1);
+         }
+ 
+         /**
+@@ -1075,39 +1010,11 @@
+          */
+         private void expungeStaleEntries() {
+             for (Object x; (x = queue.poll()) != null; ) {
+-                synchronized (queue) {
+-                    Entry entry = (Entry) x;
+-                    int i = indexFor(entry.hash, table.length);
+-                    Entry prev = table[i];
+-                    Entry p = prev;
+-                    while (p != null) {
+-                        Entry next = p.next;
+-                        if (p == entry) {
+-                            if (prev == entry)
+-                                table[i] = next;
+-                            else
+-                                prev.next = next;
+-                            entry.next = null;
+-                            size--;
+-                            break;
+-                        }
+-                        prev = p;
+-                        p = next;
+-                    }
+-                }
++                map.remove((Entry) x);
+             }
+         }
+ 
+         /**
+-         * Returns the table after first expunging stale entries.
+-         * @return an expunged hash table
+-         */
+-        private Entry[] getTable() {
+-            expungeStaleEntries();
+-            return table;
+-        }
+-
+-        /**
+          * Returns the entry to which the specified value is mapped,
+          * or {@code null} if this set contains no entry for the value.
+          *
+@@ -1119,16 +1026,15 @@
+          * @param value value to search for in set
+          * @return interned value if in set, otherwise <tt>null</tt>
+          */
+-        synchronized MethodType get(MethodType value) {
+-            int h = hash(value.hashCode());
+-            Entry[] tab = getTable();
+-            int index = indexFor(h, tab.length);
+-            Entry e = tab[index];
+-            MethodType g;
+-            while (e != null) {
+-                if (e.hash == h && eq(value, g = e.get()))
+-                    return g;
+-                e = e.next;
++        MethodType get(MethodType elem) {
++            expungeStaleEntries();
++
++            Entry value = map.get(new Entry(elem));
++            if (value != null) {
++                MethodType res = value.get();
++                if (res != null) {
++                    return res;
++                }
+             }
+             return null;
+         }
+@@ -1142,86 +1048,20 @@
+          * @return the previous entry associated with <tt>value</tt>, or
+          *         <tt>value</tt> if there was no previous entry found
+          */
+-        synchronized MethodType add(MethodType value) {
+-            int h = hash(value.hashCode());
+-            Entry[] tab = getTable();
+-            int i = indexFor(h, tab.length);
+-            MethodType g;
+-            for (Entry e = tab[i]; e != null; e = e.next) {
+-                if (h == e.hash && eq(value, g = e.get())) {
+-                    return g;
+-                }
+-            }
+-            Entry e = tab[i];
+-            tab[i] = new Entry(value, queue, h, e);
+-            if (++size >= threshold)
+-                resize(tab.length * 2);
+-            return value;
+-        }
+-
+-        /**
+-         * Rehashes the contents of this set into a new array with a
+-         * larger capacity.  This method is called automatically when the
+-         * number of keys in this set reaches its threshold.
+-         *
+-         * If current capacity is MAXIMUM_CAPACITY, this method does not
+-         * resize the set, but sets threshold to Integer.MAX_VALUE.
+-         * This has the effect of preventing future calls.
+-         *
+-         * @param newCapacity the new capacity, MUST be a power of two;
+-         *        must be greater than current capacity unless current
+-         *        capacity is MAXIMUM_CAPACITY (in which case value
+-         *        is irrelevant)
+-         */
+-        private void resize(int newCapacity) {
+-            Entry[] oldTable = getTable();
+-            int oldCapacity = oldTable.length;
+-            if (oldCapacity == MAXIMUM_CAPACITY) {
+-                threshold = Integer.MAX_VALUE;
+-                return;
+-            }
+-
+-            Entry[] newTable = newTable(newCapacity);
+-            transfer(oldTable, newTable);
+-            table = newTable;
+-
+-            /*
+-             * If ignoring null elements and processing ref queue caused massive
+-             * shrinkage, then restore old table.  This should be rare, but avoids
+-             * unbounded expansion of garbage-filled tables.
+-             */
+-            if (size >= threshold / 2) {
+-                threshold = (int)(newCapacity * loadFactor);
+-            } else {
++        MethodType add(MethodType elem) {
++            // Playing double race here, and so spinloop is required.
++            // First race is with two concurrent updaters.
++            // Second race is with GC purging weak ref under our feet.
++            // Hopefully, we always end up with single spin.
++            MethodType interned;
++            do {
+                 expungeStaleEntries();
+-                transfer(newTable, oldTable);
+-                table = oldTable;
+-            }
+-        }
+-
+-        /**
+-         * Transfers all entries from src to dest tables
+-         * @param src  original table
+-         * @param dest new table
+-         */
+-        private void transfer(Entry[] src, Entry[] dest) {
+-            for (int j = 0; j < src.length; ++j) {
+-                Entry e = src[j];
+-                src[j] = null;
+-                while (e != null) {
+-                    Entry next = e.next;
+-                    MethodType key = e.get();
+-                    if (key == null) {
+-                        e.next = null;  // Help GC
+-                        size--;
+-                    } else {
+-                        int i = indexFor(e.hash, dest.length);
+-                        e.next = dest[i];
+-                        dest[i] = e;
+-                    }
+-                    e = next;
+-                }
+-            }
++                Entry e = new Entry(elem, queue);
++                Entry exist = map.putIfAbsent(e, e);
++                Entry winner = (exist != null ? exist : e);
++                interned = winner.get();
++            } while (interned == null);
++            return interned;
+         }
+ 
+         /**
+@@ -1230,18 +1070,36 @@
+          */
+         private static class Entry extends WeakReference<MethodType> {
+             final int hash;
+-            Entry next;
+ 
+             /**
+              * Creates new entry.
+              */
++            Entry(MethodType key) {
++                super(key);
++                hash = key.hashCode();
++            }
++
+             Entry(MethodType key,
+-                  ReferenceQueue<Object> queue,
+-                  int hash, Entry next) {
++                  ReferenceQueue<Object> queue) {
+                 super(key, queue);
+-                this.hash  = hash;
+-                this.next  = next;
++                hash = key.hashCode();
+             }
++
++            @Override
++            public boolean equals(Object obj) {
++                if ((obj != null) && (obj instanceof Entry)) {
++                    Object that = ((Entry) obj).get();
++                    Object mine = get();
++                    return (that == null || mine == null) ? (this == obj) : mine.equals(that);
++                }
++                return false;
++            }
++
++            @Override
++            public int hashCode() {
++                return hash;
++            }
++
+         }
+     }
+ }
--- a/series	Tue Aug 13 12:54:34 2013 -0700
+++ b/series	Fri Sep 13 22:49:37 2013 -0700
@@ -1,32 +1,42 @@
-# base = 53be90fb39d6 in http://hg.openjdk.java.net/hsx/hotspot-comp/jdk [2013-04-25]
+# base = b67c8099ba28 in http://hg.openjdk.java.net/hsx/hotspot-comp/jdk [2013-09-12]
+
+# relevant fixes pulled from http://hg.openjdk.java.net/jdk8/tl/jdk
+tl-fixes.1.patch
+tl-fixes.2.patch
+tl-fixes.3.patch
 
 # review complete for hotspot-comp:
-# (none)
 
 # review pending before push to hotspot-comp (or tl):
-meth-doc-8014634.patch          #-/meth #+53be90fb39d6
-meth-info-8008688.patch         #-/meth #+53be90fb39d6
-meth-arity-8019417.patch        #-/meth #+53be90fb39d6
+indy-bsm-8024761.patch          #-/meth #+b67c8099ba28
+
+# spec maintenance
+meth-arity-8019417.patch        #-/meth #+b67c8099ba28
+meth-spr-8001109.patch          #-/meth #+b67c8099ba28
+meth-nsme-8001108.patch         #-/meth #+b67c8099ba28
+meth-clinit-8024599.patch       #-/meth #+b67c8099ba28
+meth-coll-8001110.patch         #-/meth #+b67c8099ba28
+meth-mr-8024438.patch           #-/meth #+b67c8099ba28
+
+meth-aclone-8001105.patch       #-/meth #+b67c8099ba28
+meth-catch-8005625.patch        #-/meth #+b67c8099ba28
+meth.patch                      #-/meth #+b67c8099ba28
 
 # non-pushed files are under review or development, or merely experimental:
-anno-stable-8001107.patch       #-/meth #+53be90fb39d6 #-testable
-meth-lfi-8001106.patch          #-/meth #+53be90fb39d6 #-testable
-meth-aclone-8001105.patch       #-/meth #+53be90fb39d6
-meth-catch-8005625.patch        #-/meth #+53be90fb39d6
-indy-bsm-8005626.patch          #-/meth #+53be90fb39d6
-meth.patch                      #-/meth #+53be90fb39d6
-meth-7177472.patch              #-/meth #+53be90fb39d6 #-buildable
+anno-stable-8001107.patch       #-/meth #+b67c8099ba28 #-testable
+meth-lfi-8001106.patch          #-/meth #+b67c8099ba28 #-testable
+indy-bsm-8005626.patch          #-/meth #+b67c8099ba28 #-testable
 
 # Keep these separate, for debugging and review:
 dyncast.patch   #+dyncast       #-/dyncast
 inti.patch      #+inti          #-/inti #-buildable
 callcc_old.patch #+callcc_old   #-/callcc_old
-continuation.patch #+continuation #-/continuation #(53be90fb39d6)
+continuation.patch #+continuation #-/continuation #(b67c8099ba28)
 tailc.patch     #+tailc         #-/tailc
 anonk.patch                     #-/anonk #+anonk
 
 # Coroutine patches: full version and simple version (no thread migration, no serialization, no stack sharing) 
-coro.patch                      #+coro          #(53be90fb39d6)
-coro-simple.patch               #+coro-simple   #(53be90fb39d6)
+coro.patch                      #+coro          #(b67c8099ba28)
+coro-simple.patch               #+coro-simple   #(b67c8099ba28)
 
 tuple-tsig.patch                #-/tuple #-testable
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tl-fixes.1.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -0,0 +1,1979 @@
+# HG changeset patch
+# User rfield
+# Date 1378269776 25200
+# Node ID 4bdbd1fabea41960b73dbb01f23defe887bfde97
+# Parent  2cdd1078f45bf670cecaef8bc621261d36301825
+8008688: Make MethodHandleInfo public
+Summary: A major overhaul to MethodHandleInfo and method handles in general.
+Reviewed-by: vlivanov, twisti
+Contributed-by: john.r.rose@oracle.com
+
+diff --git a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+--- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
++++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+@@ -124,7 +124,7 @@
+         this.samMethodType  = samMethodType;
+ 
+         this.implMethod = implMethod;
+-        this.implInfo = new MethodHandleInfo(implMethod);
++        this.implInfo = caller.revealDirect(implMethod);
+         // @@@ Temporary work-around pending resolution of 8005119
+         this.implKind = (implInfo.getReferenceKind() == MethodHandleInfo.REF_invokeSpecial)
+                         ? MethodHandleInfo.REF_invokeVirtual
+diff --git a/src/share/classes/java/lang/invoke/InfoFromMemberName.java b/src/share/classes/java/lang/invoke/InfoFromMemberName.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/java/lang/invoke/InfoFromMemberName.java
+@@ -0,0 +1,145 @@
++/*
++ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.  Oracle designates this
++ * particular file as subject to the "Classpath" exception as provided
++ * by Oracle in the LICENSE file that accompanied this code.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++package java.lang.invoke;
++
++import java.security.*;
++import java.lang.reflect.*;
++import java.lang.invoke.MethodHandleNatives.Constants;
++import java.lang.invoke.MethodHandles.Lookup;
++import static java.lang.invoke.MethodHandleStatics.*;
++
++/*
++ * Auxiliary to MethodHandleInfo, wants to nest in MethodHandleInfo but must be non-public.
++ */
++/*non-public*/
++final
++class InfoFromMemberName implements MethodHandleInfo {
++    private final MemberName member;
++    private final int referenceKind;
++
++    InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
++        assert(member.isResolved() || member.isMethodHandleInvoke());
++        assert(member.referenceKindIsConsistentWith(referenceKind));
++        this.member = member;
++        this.referenceKind = referenceKind;
++    }
++
++    @Override
++    public Class<?> getDeclaringClass() {
++        return member.getDeclaringClass();
++    }
++
++    @Override
++    public String getName() {
++        return member.getName();
++    }
++
++    @Override
++    public MethodType getMethodType() {
++        return member.getMethodOrFieldType();
++    }
++
++    @Override
++    public int getModifiers() {
++        return member.getModifiers();
++    }
++
++    @Override
++    public int getReferenceKind() {
++        return referenceKind;
++    }
++
++    @Override
++    public String toString() {
++        return MethodHandleInfo.toString(getReferenceKind(), getDeclaringClass(), getName(), getMethodType());
++    }
++
++    @Override
++    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
++        if (member.isMethodHandleInvoke() && !member.isVarargs()) {
++            // This member is an instance of a signature-polymorphic method, which cannot be reflected
++            // A method handle invoker can come in either of two forms:
++            // A generic placeholder (present in the source code, and varargs)
++            // and a signature-polymorphic instance (synthetic and not varargs).
++            // For more information see comments on {@link MethodHandleNatives#linkMethod}.
++            throw new IllegalArgumentException("cannot reflect signature polymorphic method");
++        }
++        Member mem = AccessController.doPrivileged(new PrivilegedAction<Member>() {
++                public Member run() {
++                    try {
++                        return reflectUnchecked();
++                    } catch (ReflectiveOperationException ex) {
++                        throw new IllegalArgumentException(ex);
++                    }
++                }
++            });
++        try {
++            Class<?> defc = getDeclaringClass();
++            byte refKind = (byte) getReferenceKind();
++            lookup.checkAccess(refKind, defc, convertToMemberName(refKind, mem));
++        } catch (IllegalAccessException ex) {
++            throw new IllegalArgumentException(ex);
++        }
++        return expected.cast(mem);
++    }
++
++    private Member reflectUnchecked() throws ReflectiveOperationException {
++        byte refKind = (byte) getReferenceKind();
++        Class<?> defc = getDeclaringClass();
++        boolean isPublic = Modifier.isPublic(getModifiers());
++        if (MethodHandleNatives.refKindIsMethod(refKind)) {
++            if (isPublic)
++                return defc.getMethod(getName(), getMethodType().parameterArray());
++            else
++                return defc.getDeclaredMethod(getName(), getMethodType().parameterArray());
++        } else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
++            if (isPublic)
++                return defc.getConstructor(getMethodType().parameterArray());
++            else
++                return defc.getDeclaredConstructor(getMethodType().parameterArray());
++        } else if (MethodHandleNatives.refKindIsField(refKind)) {
++            if (isPublic)
++                return defc.getField(getName());
++            else
++                return defc.getDeclaredField(getName());
++        } else {
++            throw new IllegalArgumentException("referenceKind="+refKind);
++        }
++    }
++
++    private static MemberName convertToMemberName(byte refKind, Member mem) throws IllegalAccessException {
++        if (mem instanceof Method) {
++            boolean wantSpecial = (refKind == REF_invokeSpecial);
++            return new MemberName((Method) mem, wantSpecial);
++        } else if (mem instanceof Constructor) {
++            return new MemberName((Constructor) mem);
++        } else if (mem instanceof Field) {
++            boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic);
++            return new MemberName((Field) mem, isSetter);
++        }
++        throw new InternalError(mem.getClass().getName());
++    }
++}
+diff --git a/src/share/classes/java/lang/invoke/Invokers.java b/src/share/classes/java/lang/invoke/Invokers.java
+--- a/src/share/classes/java/lang/invoke/Invokers.java
++++ b/src/share/classes/java/lang/invoke/Invokers.java
+@@ -87,6 +87,7 @@
+             lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_INVOKER);
+             invoker = SimpleMethodHandle.make(invokerType, lform);
+         }
++        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke("invokeExact", mtype));
+         assert(checkInvoker(invoker));
+         exactInvoker = invoker;
+         return invoker;
+@@ -110,6 +111,7 @@
+             lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_INVOKER);
+             invoker = SimpleMethodHandle.make(invokerType, lform);
+         }
++        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke("invoke", mtype));
+         assert(checkInvoker(invoker));
+         generalInvoker = invoker;
+         return invoker;
+diff --git a/src/share/classes/java/lang/invoke/MemberName.java b/src/share/classes/java/lang/invoke/MemberName.java
+--- a/src/share/classes/java/lang/invoke/MemberName.java
++++ b/src/share/classes/java/lang/invoke/MemberName.java
+@@ -320,14 +320,18 @@
+ 
+     /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
+     public boolean isMethodHandleInvoke() {
+-        final int bits = Modifier.NATIVE | Modifier.FINAL;
++        final int bits = MH_INVOKE_MODS;
+         final int negs = Modifier.STATIC;
+         if (testFlags(bits | negs, bits) &&
+             clazz == MethodHandle.class) {
+-            return name.equals("invoke") || name.equals("invokeExact");
++            return isMethodHandleInvokeName(name);
+         }
+         return false;
+     }
++    public static boolean isMethodHandleInvokeName(String name) {
++        return name.equals("invoke") || name.equals("invokeExact");
++    }
++    private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
+ 
+     /** Utility method to query the modifier flags of this member. */
+     public boolean isStatic() {
+@@ -482,12 +486,27 @@
+         m.getClass();  // NPE check
+         // fill in vmtarget, vmindex while we have m in hand:
+         MethodHandleNatives.init(this, m);
++        if (clazz == null) {  // MHN.init failed
++            if (m.getDeclaringClass() == MethodHandle.class &&
++                isMethodHandleInvokeName(m.getName())) {
++                // The JVM did not reify this signature-polymorphic instance.
++                // Need a special case here.
++                // See comments on MethodHandleNatives.linkMethod.
++                MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
++                int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
++                init(MethodHandle.class, m.getName(), type, flags);
++                if (isMethodHandleInvoke())
++                    return;
++            }
++            throw new LinkageError(m.toString());
++        }
+         assert(isResolved() && this.clazz != null);
+         this.name = m.getName();
+         if (this.type == null)
+             this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
+         if (wantSpecial) {
+-            assert(!isAbstract()) : this;
++            if (isAbstract())
++                throw new AbstractMethodError(this.toString());
+             if (getReferenceKind() == REF_invokeVirtual)
+                 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
+             else if (getReferenceKind() == REF_invokeInterface)
+@@ -562,6 +581,22 @@
+         initResolved(true);
+     }
+ 
++    /**
++     * Create a name for a signature-polymorphic invoker.
++     * This is a placeholder for a signature-polymorphic instance
++     * (of MH.invokeExact, etc.) that the JVM does not reify.
++     * See comments on {@link MethodHandleNatives#linkMethod}.
++     */
++    static MemberName makeMethodHandleInvoke(String name, MethodType type) {
++        return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
++    }
++    static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
++        MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
++        mem.flags |= mods;  // it's not resolved, but add these modifiers anyway
++        assert(mem.isMethodHandleInvoke()) : mem;
++        return mem;
++    }
++
+     // bare-bones constructor; the JVM will fill it in
+     MemberName() { }
+ 
+diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java
+--- a/src/share/classes/java/lang/invoke/MethodHandle.java
++++ b/src/share/classes/java/lang/invoke/MethodHandle.java
+@@ -1285,6 +1285,11 @@
+     }
+ 
+     /*non-public*/
++    MethodHandle withInternalMemberName(MemberName member) {
++        return MethodHandleImpl.makeWrappedMember(this, member);
++    }
++
++    /*non-public*/
+     boolean isInvokeSpecial() {
+         return false;  // DMH.Special returns true
+     }
+@@ -1356,7 +1361,7 @@
+     MethodHandle rebind() {
+         // Bind 'this' into a new invoker, of the known class BMH.
+         MethodType type2 = type();
+-        LambdaForm form2 = reinvokerForm(type2.basicType());
++        LambdaForm form2 = reinvokerForm(this);
+         // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
+         return BoundMethodHandle.bindSingle(type2, form2, this);
+     }
+@@ -1369,23 +1374,38 @@
+     /** Create a LF which simply reinvokes a target of the given basic type.
+      *  The target MH must override {@link #reinvokerTarget} to provide the target.
+      */
+-    static LambdaForm reinvokerForm(MethodType mtype) {
+-        mtype = mtype.basicType();
++    static LambdaForm reinvokerForm(MethodHandle target) {
++        MethodType mtype = target.type().basicType();
+         LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
+         if (reinvoker != null)  return reinvoker;
+-        MethodHandle MH_invokeBasic = MethodHandles.basicInvoker(mtype);
++        if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)
++            return makeReinvokerForm(target.type(), target);  // cannot cache this
++        reinvoker = makeReinvokerForm(mtype, null);
++        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker);
++    }
++    private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) {
++        boolean customized = (customTargetOrNull != null);
++        MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype);
+         final int THIS_BMH    = 0;
+         final int ARG_BASE    = 1;
+         final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
+         int nameCursor = ARG_LIMIT;
+-        final int NEXT_MH     = nameCursor++;
++        final int NEXT_MH     = customized ? -1 : nameCursor++;
+         final int REINVOKE    = nameCursor++;
+         LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
+-        names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
+-        Object[] targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
+-        targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
+-        names[REINVOKE] = new LambdaForm.Name(MH_invokeBasic, targetArgs);
+-        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, new LambdaForm("BMH.reinvoke", ARG_LIMIT, names));
++        Object[] targetArgs;
++        MethodHandle targetMH;
++        if (customized) {
++            targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
++            targetMH = customTargetOrNull;
++        } else {
++            names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
++            targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
++            targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
++            targetMH = MethodHandles.basicInvoker(mtype);
++        }
++        names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs);
++        return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names);
+     }
+ 
+     private static final LambdaForm.NamedFunction NF_reinvokerTarget;
+diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java
+--- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java
++++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java
+@@ -317,7 +317,7 @@
+         private MethodHandle cache;
+ 
+         AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
+-            super(type, reinvokerForm(type));
++            super(type, reinvokerForm(target));
+             this.target = target;
+             this.arrayType = arrayType;
+             this.cache = target.asCollector(arrayType, 0);
+@@ -778,16 +778,27 @@
+     }
+     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
+ 
+-    static MethodHandle FAKE_METHOD_HANDLE_INVOKE;
+-    static
+-    MethodHandle fakeMethodHandleInvoke(MemberName method) {
+-        MethodType type = method.getInvocationType();
+-        assert(type.equals(MethodType.methodType(Object.class, Object[].class)));
+-        MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE;
++    static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
++    static MethodHandle fakeMethodHandleInvoke(MemberName method) {
++        int idx;
++        assert(method.isMethodHandleInvoke());
++        switch (method.getName()) {
++        case "invoke":       idx = 0; break;
++        case "invokeExact":  idx = 1; break;
++        default:             throw new InternalError(method.getName());
++        }
++        MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
+         if (mh != null)  return mh;
+-        mh = throwException(type.insertParameterTypes(0, UnsupportedOperationException.class));
++        MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
++                                                MethodHandle.class, Object[].class);
++        mh = throwException(type);
+         mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
+-        FAKE_METHOD_HANDLE_INVOKE = mh;
++        if (!method.getInvocationType().equals(mh.type()))
++            throw new InternalError(method.toString());
++        mh = mh.withInternalMemberName(method);
++        mh = mh.asVarargsCollector(Object[].class);
++        assert(method.isVarargs());
++        FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
+         return mh;
+     }
+ 
+@@ -821,7 +832,7 @@
+             MethodHandle vamh = prepareForInvoker(mh);
+             // Cache the result of makeInjectedInvoker once per argument class.
+             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
+-            return restoreToType(bccInvoker.bindTo(vamh), mh.type());
++            return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName());
+         }
+ 
+         private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
+@@ -876,8 +887,11 @@
+         }
+ 
+         // Undo the adapter effect of prepareForInvoker:
+-        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type) {
+-            return vamh.asCollector(Object[].class, type.parameterCount()).asType(type);
++        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type, MemberName member) {
++            MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
++            mh = mh.asType(type);
++            mh = mh.withInternalMemberName(member);
++            return mh;
+         }
+ 
+         private static final MethodHandle MH_checkCallerClass;
+@@ -939,4 +953,41 @@
+             }
+         }
+     }
++
++
++    /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
++    static class WrappedMember extends MethodHandle {
++        private final MethodHandle target;
++        private final MemberName member;
++
++        private WrappedMember(MethodHandle target, MethodType type, MemberName member) {
++            super(type, reinvokerForm(target));
++            this.target = target;
++            this.member = member;
++        }
++
++        @Override
++        MethodHandle reinvokerTarget() {
++            return target;
++        }
++        @Override
++        MemberName internalMemberName() {
++            return member;
++        }
++        @Override
++        boolean isInvokeSpecial() {
++            return target.isInvokeSpecial();
++        }
++        @Override
++        MethodHandle viewAsType(MethodType newType) {
++            return new WrappedMember(target, newType, member);
++        }
++    }
++
++    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
++        if (member.equals(target.internalMemberName()))
++            return target;
++        return new WrappedMember(target, target.type(), member);
++    }
++
+ }
+diff --git a/src/share/classes/java/lang/invoke/MethodHandleInfo.java b/src/share/classes/java/lang/invoke/MethodHandleInfo.java
+--- a/src/share/classes/java/lang/invoke/MethodHandleInfo.java
++++ b/src/share/classes/java/lang/invoke/MethodHandleInfo.java
+@@ -24,80 +24,246 @@
+  */
+ 
+ package java.lang.invoke;
++
++import java.lang.reflect.*;
++import java.util.*;
+ import java.lang.invoke.MethodHandleNatives.Constants;
++import java.lang.invoke.MethodHandles.Lookup;
++import static java.lang.invoke.MethodHandleStatics.*;
+ 
+ /**
+- * Cracking (reflecting) method handles back into their constituent symbolic parts.
++ * A symbolic reference obtained by cracking a method handle into its consitutent symbolic parts.
++ * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
++ * <p>
++ * A <em>direct method handle</em> represents a method, constructor, or field without
++ * any intervening argument bindings or other transformations.
++ * The method, constructor, or field referred to by a direct method handle is called
++ * its <em>underlying member</em>.
++ * Direct method handles may be obtained in any of these ways:
++ * <ul>
++ * <li>By executing an {@code ldc} instruction on a {@code CONSTANT_MethodHandle} constant.
++ *     (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.)
++ * <li>By calling one of the <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>,
++ *     such as {@link Lookup#findVirtual Lookup.findVirtual},
++ *     to resolve a symbolic reference into a method handle.
++ *     A symbolic reference consists of a class, name string, and type.
++ * <li>By calling the factory method {@link Lookup#unreflect Lookup.unreflect}
++ *     or {@link Lookup#unreflectSpecial Lookup.unreflectSpecial}
++ *     to convert a {@link Method} into a method handle.
++ * <li>By calling the factory method {@link Lookup#unreflectConstructor Lookup.unreflectConstructor}
++ *     to convert a {@link Constructor} into a method handle.
++ * <li>By calling the factory method {@link Lookup#unreflectGetter Lookup.unreflectGetter}
++ *     or {@link Lookup#unreflectSetter Lookup.unreflectSetter}
++ *     to convert a {@link Field} into a method handle.
++ * </ul>
++ * In all of these cases, it is possible to crack the resulting direct method handle
++ * to recover a symbolic reference for the underlying method, constructor, or field.
++ * Cracking must be done via a {@code Lookup} object equivalent to that which created
++ * the target method handle, or which has enough access permissions to recreate
++ * an equivalent method handle.
+  *
++ * <h1><a name="refkinds"></a>Reference kinds</h1>
++ * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
++ * correspond to all major use cases for methods, constructors, and fields.
++ * These use cases may be distinguished using small integers as follows:
++ * <table border=1 cellpadding=5 summary="reference kinds">
++ * <tr><th>reference kind</th><th>descriptive name</th><th>scope</th><th>member</th><th>behavior</th></tr>
++ * <tr>
++ *     <td>{@code 1}</td><td>{@code REF_getField}</td><td>{@code class}</td>
++ *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 2}</td><td>{@code REF_getStatic}</td><td>{@code class} or {@code interface}</td>
++ *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 3}</td><td>{@code REF_putField}</td><td>{@code class}</td>
++ *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 4}</td><td>{@code REF_putStatic}</td><td>{@code class}</td>
++ *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 5}</td><td>{@code REF_invokeVirtual}</td><td>{@code class}</td>
++ *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 6}</td><td>{@code REF_invokeStatic}</td><td>{@code class} or {@code interface}</td>
++ *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 7}</td><td>{@code REF_invokeSpecial}</td><td>{@code class} or {@code interface}</td>
++ *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 8}</td><td>{@code REF_newInvokeSpecial}</td><td>{@code class}</td>
++ *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
++ * </tr>
++ * <tr>
++ *     <td>{@code 9}</td><td>{@code REF_invokeInterface}</td><td>{@code interface}</td>
++ *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
++ * </tr>
++ * </table>
++ * @since 1.8
+  */
+-final class MethodHandleInfo {
+-   public static final int
+-       REF_getField                = Constants.REF_getField,
+-       REF_getStatic               = Constants.REF_getStatic,
+-       REF_putField                = Constants.REF_putField,
+-       REF_putStatic               = Constants.REF_putStatic,
+-       REF_invokeVirtual           = Constants.REF_invokeVirtual,
+-       REF_invokeStatic            = Constants.REF_invokeStatic,
+-       REF_invokeSpecial           = Constants.REF_invokeSpecial,
+-       REF_newInvokeSpecial        = Constants.REF_newInvokeSpecial,
+-       REF_invokeInterface         = Constants.REF_invokeInterface;
++public
++interface MethodHandleInfo {
++    /**
++     * A direct method handle reference kind,
++     * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
++     */
++    public static final int
++        REF_getField                = Constants.REF_getField,
++        REF_getStatic               = Constants.REF_getStatic,
++        REF_putField                = Constants.REF_putField,
++        REF_putStatic               = Constants.REF_putStatic,
++        REF_invokeVirtual           = Constants.REF_invokeVirtual,
++        REF_invokeStatic            = Constants.REF_invokeStatic,
++        REF_invokeSpecial           = Constants.REF_invokeSpecial,
++        REF_newInvokeSpecial        = Constants.REF_newInvokeSpecial,
++        REF_invokeInterface         = Constants.REF_invokeInterface;
+ 
+-   private final Class<?> declaringClass;
+-   private final String name;
+-   private final MethodType methodType;
+-   private final int referenceKind;
++    /**
++     * Returns the reference kind of the cracked method handle, which in turn
++     * determines whether the method handle's underlying member was a constructor, method, or field.
++     * See the <a href="MethodHandleInfo.html#refkinds">table above</a> for definitions.
++     * @return the integer code for the kind of reference used to access the underlying member
++     */
++    public int getReferenceKind();
+ 
+-   public MethodHandleInfo(MethodHandle mh) {
+-       MemberName mn = mh.internalMemberName();
+-       if (mn == null)  throw new IllegalArgumentException("not a direct method handle");
+-       this.declaringClass = mn.getDeclaringClass();
+-       this.name = mn.getName();
+-       this.methodType = mn.getMethodOrFieldType();
+-       byte refKind = mn.getReferenceKind();
+-       if (refKind == REF_invokeSpecial && !mh.isInvokeSpecial())
+-           // Devirtualized method invocation is usually formally virtual.
+-           refKind = REF_invokeVirtual;
+-       this.referenceKind = refKind;
+-   }
++    /**
++     * Returns the class in which the cracked method handle's underlying member was defined.
++     * @return the declaring class of the underlying member
++     */
++    public Class<?> getDeclaringClass();
+ 
+-   public Class<?> getDeclaringClass() {
+-       return declaringClass;
+-   }
++    /**
++     * Returns the name of the cracked method handle's underlying member.
++     * This is {@code "&lt;init&gt;"} if the underlying member was a constructor,
++     * else it is a simple method name or field name.
++     * @return the simple name of the underlying member
++     */
++    public String getName();
+ 
+-   public String getName() {
+-       return name;
+-   }
++    /**
++     * Returns the nominal type of the cracked symbolic reference, expressed as a method type.
++     * If the reference is to a constructor, the return type will be {@code void}.
++     * If it is to a non-static method, the method type will not mention the {@code this} parameter.
++     * If it is to a field and the requested access is to read the field,
++     * the method type will have no parameters and return the field type.
++     * If it is to a field and the requested access is to write the field,
++     * the method type will have one parameter of the field type and return {@code void}.
++     * <p>
++     * Note that original direct method handle may include a leading {@code this} parameter,
++     * or (in the case of a constructor) will replace the {@code void} return type
++     * with the constructed class.
++     * The nominal type does not include any {@code this} parameter,
++     * and (in the case of a constructor) will return {@code void}.
++     * @return the type of the underlying member, expressed as a method type
++     */
++    public MethodType getMethodType();
+ 
+-   public MethodType getMethodType() {
+-       return methodType;
+-   }
++    // Utility methods.
++    // NOTE: class/name/type and reference kind constitute a symbolic reference
++    // member and modifiers are an add-on, derived from Core Reflection (or the equivalent)
+ 
+-   public int getModifiers() {
+-       return -1; //TODO
+-   }
++    /**
++     * Reflects the underlying member as a method, constructor, or field object.
++     * If the underlying member is public, it is reflected as if by
++     * {@code getMethod}, {@code getConstructor}, or {@code getField}.
++     * Otherwise, it is reflected as if by
++     * {@code getDeclaredMethod}, {@code getDeclaredConstructor}, or {@code getDeclaredField}.
++     * The underlying member must be accessible to the given lookup object.
++     * @param <T> the desired type of the result, either {@link Member} or a subtype
++     * @param expected a class object representing the desired result type {@code T}
++     * @param lookup the lookup object that created this MethodHandleInfo, or one with equivalent access privileges
++     * @return a reference to the method, constructor, or field object
++     * @exception ClassCastException if the member is not of the expected type
++     * @exception NullPointerException if either argument is {@code null}
++     * @exception IllegalArgumentException if the underlying member is not accessible to the given lookup object
++     */
++    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup);
+ 
+-   public int getReferenceKind() {
+-       return referenceKind;
+-   }
++    /**
++     * Returns the access modifiers of the underlying member.
++     * @return the Java language modifiers for underlying member,
++     *         or -1 if the member cannot be accessed
++     * @see Modifier
++     * @see reflectAs
++     */
++    public int getModifiers();
+ 
+-   static String getReferenceKindString(int referenceKind) {
+-        switch (referenceKind) {
+-            case REF_getField: return "getfield";
+-            case REF_getStatic: return "getstatic";
+-            case REF_putField: return "putfield";
+-            case REF_putStatic: return "putstatic";
+-            case REF_invokeVirtual: return "invokevirtual";
+-            case REF_invokeStatic: return "invokestatic";
+-            case REF_invokeSpecial: return "invokespecial";
+-            case REF_newInvokeSpecial: return "newinvokespecial";
+-            case REF_invokeInterface: return "invokeinterface";
+-            default: return "UNKNOWN_REFENCE_KIND" + "[" + referenceKind + "]";
+-        }
++    /**
++     * Determines if the underlying member was a variable arity method or constructor.
++     * Such members are represented by method handles that are varargs collectors.
++     * @implSpec
++     * This produces a result equivalent to:
++     * <pre>{@code
++     *     getReferenceKind() >= REF_invokeVirtual && Modifier.isTransient(getModifiers())
++     * }</pre>
++     *
++     *
++     * @return {@code true} if and only if the underlying member was declared with variable arity.
++     */
++    // spelling derived from java.lang.reflect.Executable, not MethodHandle.isVarargsCollector
++    public default boolean isVarArgs()  {
++        // fields are never varargs:
++        if (MethodHandleNatives.refKindIsField((byte) getReferenceKind()))
++            return false;
++        // not in the public API: Modifier.VARARGS
++        final int ACC_VARARGS = 0x00000080;  // from JVMS 4.6 (Table 4.20)
++        assert(ACC_VARARGS == Modifier.TRANSIENT);
++        return Modifier.isTransient(getModifiers());
+     }
+ 
+-    @Override
+-    public String toString() {
+-        return String.format("%s %s.%s:%s", getReferenceKindString(referenceKind),
+-                             declaringClass.getName(), name, methodType);
++    /**
++     * Returns the descriptive name of the given reference kind,
++     * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
++     * The conventional prefix "REF_" is omitted.
++     * @param referenceKind an integer code for a kind of reference used to access a class member
++     * @return a mixed-case string such as {@code "getField"}
++     * @exception IllegalArgumentException if the argument is not a valid
++     *            <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
++     */
++    public static String referenceKindToString(int referenceKind) {
++        if (!MethodHandleNatives.refKindIsValid(referenceKind))
++            throw newIllegalArgumentException("invalid reference kind", referenceKind);
++        return MethodHandleNatives.refKindName((byte)referenceKind);
++    }
++
++    /**
++     * Returns a string representation for a {@code MethodHandleInfo},
++     * given the four parts of its symbolic reference.
++     * This is defined to be of the form {@code "RK C.N:MT"}, where {@code RK} is the
++     * {@linkplain #referenceKindToString reference kind string} for {@code kind},
++     * {@code C} is the {@linkplain java.lang.Class#getName name} of {@code defc}
++     * {@code N} is the {@code name}, and
++     * {@code MT} is the {@code type}.
++     * These four values may be obtained from the
++     * {@linkplain #getReferenceKind reference kind},
++     * {@linkplain #getDeclaringClass declaring class},
++     * {@linkplain #getName member name},
++     * and {@linkplain #getMethodType method type}
++     * of a {@code MethodHandleInfo} object.
++     *
++     * @implSpec
++     * This produces a result equivalent to:
++     * <pre>{@code
++     *     String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type)
++     * }</pre>
++     *
++     * @param kind the {@linkplain #getReferenceKind reference kind} part of the symbolic reference
++     * @param defc the {@linkplain #getDeclaringClass declaring class} part of the symbolic reference
++     * @param name the {@linkplain #getName member name} part of the symbolic reference
++     * @param type the {@linkplain #getMethodType method type} part of the symbolic reference
++     * @return a string of the form {@code "RK C.N:MT"}
++     * @exception IllegalArgumentException if the first argument is not a valid
++     *            <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
++     * @exception NullPointerException if any reference argument is {@code null}
++     */
++    public static String toString(int kind, Class<?> defc, String name, MethodType type) {
++        Objects.requireNonNull(name); Objects.requireNonNull(type);
++        return String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type);
+     }
+ }
+diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
+--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java
++++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
+@@ -205,6 +205,9 @@
+     static boolean refKindIsMethod(byte refKind) {
+         return !refKindIsField(refKind) && (refKind != REF_newInvokeSpecial);
+     }
++    static boolean refKindIsConstructor(byte refKind) {
++        return (refKind == REF_newInvokeSpecial);
++    }
+     static boolean refKindHasReceiver(byte refKind) {
+         assert(refKindIsValid(refKind));
+         return (refKind & 1) != 0;
+@@ -313,7 +316,65 @@
+      * The method assumes the following arguments on the stack:
+      * 0: the method handle being invoked
+      * 1-N: the arguments to the method handle invocation
+-     * N+1: an implicitly added type argument (the given MethodType)
++     * N+1: an optional, implicitly added argument (typically the given MethodType)
++     * <p>
++     * The nominal method at such a call site is an instance of
++     * a signature-polymorphic method (see @PolymorphicSignature).
++     * Such method instances are user-visible entities which are
++     * "split" from the generic placeholder method in {@code MethodHandle}.
++     * (Note that the placeholder method is not identical with any of
++     * its instances.  If invoked reflectively, is guaranteed to throw an
++     * {@code UnsupportedOperationException}.)
++     * If the signature-polymorphic method instance is ever reified,
++     * it appears as a "copy" of the original placeholder
++     * (a native final member of {@code MethodHandle}) except
++     * that its type descriptor has shape required by the instance,
++     * and the method instance is <em>not</em> varargs.
++     * The method instance is also marked synthetic, since the
++     * method (by definition) does not appear in Java source code.
++     * <p>
++     * The JVM is allowed to reify this method as instance metadata.
++     * For example, {@code invokeBasic} is always reified.
++     * But the JVM may instead call {@code linkMethod}.
++     * If the result is an * ordered pair of a {@code (method, appendix)},
++     * the method gets all the arguments (0..N inclusive)
++     * plus the appendix (N+1), and uses the appendix to complete the call.
++     * In this way, one reusable method (called a "linker method")
++     * can perform the function of any number of polymorphic instance
++     * methods.
++     * <p>
++     * Linker methods are allowed to be weakly typed, with any or
++     * all references rewritten to {@code Object} and any primitives
++     * (except {@code long}/{@code float}/{@code double})
++     * rewritten to {@code int}.
++     * A linker method is trusted to return a strongly typed result,
++     * according to the specific method type descriptor of the
++     * signature-polymorphic instance it is emulating.
++     * This can involve (as necessary) a dynamic check using
++     * data extracted from the appendix argument.
++     * <p>
++     * The JVM does not inspect the appendix, other than to pass
++     * it verbatim to the linker method at every call.
++     * This means that the JDK runtime has wide latitude
++     * for choosing the shape of each linker method and its
++     * corresponding appendix.
++     * Linker methods should be generated from {@code LambdaForm}s
++     * so that they do not become visible on stack traces.
++     * <p>
++     * The {@code linkMethod} call is free to omit the appendix
++     * (returning null) and instead emulate the required function
++     * completely in the linker method.
++     * As a corner case, if N==255, no appendix is possible.
++     * In this case, the method returned must be custom-generated to
++     * to perform any needed type checking.
++     * <p>
++     * If the JVM does not reify a method at a call site, but instead
++     * calls {@code linkMethod}, the corresponding call represented
++     * in the bytecodes may mention a valid method which is not
++     * representable with a {@code MemberName}.
++     * Therefore, use cases for {@code linkMethod} tend to correspond to
++     * special cases in reflective code such as {@code findVirtual}
++     * or {@code revealDirect}.
+      */
+     static MemberName linkMethod(Class<?> callerClass, int refKind,
+                                  Class<?> defc, String name, Object type,
+diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
+--- a/src/share/classes/java/lang/invoke/MethodHandles.java
++++ b/src/share/classes/java/lang/invoke/MethodHandles.java
+@@ -26,8 +26,6 @@
+ package java.lang.invoke;
+ 
+ import java.lang.reflect.*;
+-import java.security.AccessController;
+-import java.security.PrivilegedAction;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+@@ -54,6 +52,7 @@
+  * </ul>
+  * <p>
+  * @author John Rose, JSR 292 EG
++ * @since 1.7
+  */
+ public class MethodHandles {
+ 
+@@ -97,6 +96,38 @@
+     }
+ 
+     /**
++     * Performs an unchecked "crack" of a direct method handle.
++     * The result is as if the user had obtained a lookup object capable enough
++     * to crack the target method handle, called
++     * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
++     * on the target to obtain its symbolic reference, and then called
++     * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
++     * to resolve the symbolic reference to a member.
++     * <p>
++     * If there is a security manager, its {@code checkPermission} method
++     * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
++     * @param <T> the desired type of the result, either {@link Member} or a subtype
++     * @param target a direct method handle to crack into symbolic reference components
++     * @param expected a class object representing the desired result type {@code T}
++     * @return a reference to the method, constructor, or field object
++     * @exception SecurityException if the caller is not privileged to call {@code setAccessible}
++     * @exception NullPointerException if either argument is {@code null}
++     * @exception IllegalArgumentException if the target is not a direct method handle
++     * @exception ClassCastException if the member is not of the expected type
++     * @since 1.8
++     */
++    public static <T extends Member> T
++    reflectAs(Class<T> expected, MethodHandle target) {
++        SecurityManager smgr = System.getSecurityManager();
++        if (smgr != null)  smgr.checkPermission(ACCESS_PERMISSION);
++        Lookup lookup = Lookup.IMPL_LOOKUP;  // use maximally privileged lookup
++        return lookup.revealDirect(target).reflectAs(expected, lookup);
++    }
++    // Copied from AccessibleObject, as used by Method.setAccessible, etc.:
++    static final private java.security.Permission ACCESS_PERMISSION =
++        new ReflectPermission("suppressAccessChecks");
++
++    /**
+      * A <em>lookup object</em> is a factory for creating method handles,
+      * when the creation requires access checking.
+      * Method handles do not perform
+@@ -647,6 +678,7 @@
+                 return invoker(type);
+             if ("invokeExact".equals(name))
+                 return exactInvoker(type);
++            assert(!MemberName.isMethodHandleInvokeName(name));
+             return null;
+         }
+ 
+@@ -892,6 +924,10 @@
+          * @throws NullPointerException if the argument is null
+          */
+         public MethodHandle unreflect(Method m) throws IllegalAccessException {
++            if (m.getDeclaringClass() == MethodHandle.class) {
++                MethodHandle mh = unreflectForMH(m);
++                if (mh != null)  return mh;
++            }
+             MemberName method = new MemberName(m);
+             byte refKind = method.getReferenceKind();
+             if (refKind == REF_invokeSpecial)
+@@ -900,6 +936,12 @@
+             Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
+             return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method));
+         }
++        private MethodHandle unreflectForMH(Method m) {
++            // these names require special lookups because they throw UnsupportedOperationException
++            if (MemberName.isMethodHandleInvokeName(m.getName()))
++                return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
++            return null;
++        }
+ 
+         /**
+          * Produces a method handle for a reflected method.
+@@ -1004,6 +1046,46 @@
+             return unreflectField(f, true);
+         }
+ 
++        /**
++         * Cracks a direct method handle created by this lookup object or a similar one.
++         * Security and access checks are performed to ensure that this lookup object
++         * is capable of reproducing the target method handle.
++         * This means that the cracking may fail if target is a direct method handle
++         * but was created by an unrelated lookup object.
++         * @param target a direct method handle to crack into symbolic reference components
++         * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object
++         * @exception SecurityException if a security manager is present and it
++         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
++         * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
++         * @exception NullPointerException if the target is {@code null}
++         * @since 1.8
++         */
++        public MethodHandleInfo revealDirect(MethodHandle target) {
++            MemberName member = target.internalMemberName();
++            if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
++                throw newIllegalArgumentException("not a direct method handle");
++            Class<?> defc = member.getDeclaringClass();
++            byte refKind = member.getReferenceKind();
++            assert(MethodHandleNatives.refKindIsValid(refKind));
++            if (refKind == REF_invokeSpecial && !target.isInvokeSpecial())
++                // Devirtualized method invocation is usually formally virtual.
++                // To avoid creating extra MemberName objects for this common case,
++                // we encode this extra degree of freedom using MH.isInvokeSpecial.
++                refKind = REF_invokeVirtual;
++            if (refKind == REF_invokeVirtual && defc.isInterface())
++                // Symbolic reference is through interface but resolves to Object method (toString, etc.)
++                refKind = REF_invokeInterface;
++            // Check SM permissions and member access before cracking.
++            try {
++                checkSecurityManager(defc, member);
++                checkAccess(refKind, defc, member);
++            } catch (IllegalAccessException ex) {
++                throw new IllegalArgumentException(ex);
++            }
++            // Produce the handle to the results.
++            return new InfoFromMemberName(this, member, refKind);
++        }
++
+         /// Helper methods, all package-private.
+ 
+         MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+@@ -1201,12 +1283,12 @@
+         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
+                                                    boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
+             checkMethod(refKind, refc, method);
+-            if (method.isMethodHandleInvoke())
+-                return fakeMethodHandleInvoke(method);
++            assert(!method.isMethodHandleInvoke());
+ 
+             Class<?> refcAsSuper;
+             if (refKind == REF_invokeSpecial &&
+                 refc != lookupClass() &&
++                !refc.isInterface() &&
+                 refc != (refcAsSuper = lookupClass().getSuperclass()) &&
+                 refc.isAssignableFrom(lookupClass())) {
+                 assert(!method.getName().equals("<init>"));  // not this code path
+@@ -1234,9 +1316,6 @@
+                 mh = restrictReceiver(method, mh, lookupClass());
+             return mh;
+         }
+-        private MethodHandle fakeMethodHandleInvoke(MemberName method) {
+-            return throwException(method.getReturnType(), UnsupportedOperationException.class);
+-        }
+         private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
+                                              Class<?> callerClass)
+                                              throws IllegalAccessException {
+diff --git a/src/share/classes/java/lang/invoke/SerializedLambda.java b/src/share/classes/java/lang/invoke/SerializedLambda.java
+--- a/src/share/classes/java/lang/invoke/SerializedLambda.java
++++ b/src/share/classes/java/lang/invoke/SerializedLambda.java
+@@ -225,7 +225,7 @@
+ 
+     @Override
+     public String toString() {
+-        String implKind=MethodHandleInfo.getReferenceKindString(implMethodKind);
++        String implKind=MethodHandleInfo.referenceKindToString(implMethodKind);
+         return String.format("SerializedLambda[%s=%s, %s=%s.%s:%s, " +
+                              "%s=%s %s.%s:%s, %s=%s, %s=%d]",
+                              "capturingClass", capturingClass,
+diff --git a/test/java/lang/invoke/7087570/Test7087570.java b/test/java/lang/invoke/7087570/Test7087570.java
+--- a/test/java/lang/invoke/7087570/Test7087570.java
++++ b/test/java/lang/invoke/7087570/Test7087570.java
+@@ -35,20 +35,9 @@
+ 
+ import static java.lang.invoke.MethodHandles.*;
+ import static java.lang.invoke.MethodType.*;
++import static java.lang.invoke.MethodHandleInfo.*;
+ 
+ public class Test7087570 {
+-    // XXX may remove the following constant declarations when MethodHandleInfo is made public
+-    private static final int
+-            REF_getField                = 1,
+-            REF_getStatic               = 2,
+-            REF_putField                = 3,
+-            REF_putStatic               = 4,
+-            REF_invokeVirtual           = 5,
+-            REF_invokeStatic            = 6,
+-            REF_invokeSpecial           = 7,
+-            REF_newInvokeSpecial        = 8,
+-            REF_invokeInterface         = 9,
+-            REF_LIMIT                  = 10;
+ 
+     private static final TestMethodData[] TESTS = new TestMethodData[] {
+         // field accessors
+@@ -87,17 +76,17 @@
+     }
+ 
+     private static void doTest(MethodHandle mh, TestMethodData testMethod) {
+-        Object mhi = newMethodHandleInfo(mh);
++        MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
+ 
+         System.out.printf("%s.%s: %s, nominal refKind: %s, actual refKind: %s\n",
+                           testMethod.clazz.getName(), testMethod.name, testMethod.methodType,
+-                          REF_KIND_NAMES[testMethod.referenceKind],
+-                          REF_KIND_NAMES[getReferenceKind(mhi)]);
+-        assertEquals(testMethod.name,           getName(mhi));
+-        assertEquals(testMethod.methodType,     getMethodType(mhi));
+-        assertEquals(testMethod.declaringClass, getDeclaringClass(mhi));
++                          referenceKindToString(testMethod.referenceKind),
++                          referenceKindToString(mhi.getReferenceKind()));
++        assertEquals(testMethod.name,           mhi.getName());
++        assertEquals(testMethod.methodType,     mhi.getMethodType());
++        assertEquals(testMethod.declaringClass, mhi.getDeclaringClass());
+         assertEquals(testMethod.referenceKind == REF_invokeSpecial, isInvokeSpecial(mh));
+-        assertRefKindEquals(testMethod.referenceKind,  getReferenceKind(mhi));
++        assertRefKindEquals(testMethod.referenceKind,  mhi.getReferenceKind());
+     }
+ 
+     private static void testWithLookup() throws Throwable {
+@@ -122,50 +111,8 @@
+         return methodType(void.class, clazz);
+     }
+ 
+-    private static final String[] REF_KIND_NAMES = {
+-        "MH::invokeBasic",
+-        "REF_getField", "REF_getStatic", "REF_putField", "REF_putStatic",
+-        "REF_invokeVirtual", "REF_invokeStatic", "REF_invokeSpecial",
+-        "REF_newInvokeSpecial", "REF_invokeInterface"
+-    };
+-
+     private static final Lookup LOOKUP = lookup();
+ 
+-    // XXX may remove the following reflective logic when MethodHandleInfo is made public
+-    private static final MethodHandle MH_IS_INVOKESPECIAL;
+-    private static final MethodHandle MHI_CONSTRUCTOR;
+-    private static final MethodHandle MHI_GET_NAME;
+-    private static final MethodHandle MHI_GET_METHOD_TYPE;
+-    private static final MethodHandle MHI_GET_DECLARING_CLASS;
+-    private static final MethodHandle MHI_GET_REFERENCE_KIND;
+-
+-    static {
+-        try {
+-            // This is white box testing.  Use reflection to grab private implementation bits.
+-            String magicName = "IMPL_LOOKUP";
+-            Field magicLookup = MethodHandles.Lookup.class.getDeclaredField(magicName);
+-            // This unit test will fail if a security manager is installed.
+-            magicLookup.setAccessible(true);
+-            // Forbidden fruit...
+-            Lookup directInvokeLookup = (Lookup) magicLookup.get(null);
+-            Class<?> mhiClass = Class.forName("java.lang.invoke.MethodHandleInfo", false, MethodHandle.class.getClassLoader());
+-            MH_IS_INVOKESPECIAL = directInvokeLookup
+-                    .findVirtual(MethodHandle.class, "isInvokeSpecial", methodType(boolean.class));
+-            MHI_CONSTRUCTOR = directInvokeLookup
+-                    .findConstructor(mhiClass, methodType(void.class, MethodHandle.class));
+-            MHI_GET_NAME = directInvokeLookup
+-                    .findVirtual(mhiClass, "getName", methodType(String.class));
+-            MHI_GET_METHOD_TYPE = directInvokeLookup
+-                    .findVirtual(mhiClass, "getMethodType", methodType(MethodType.class));
+-            MHI_GET_DECLARING_CLASS = directInvokeLookup
+-                    .findVirtual(mhiClass, "getDeclaringClass", methodType(Class.class));
+-            MHI_GET_REFERENCE_KIND = directInvokeLookup
+-                    .findVirtual(mhiClass, "getReferenceKind", methodType(int.class));
+-        } catch (ReflectiveOperationException ex) {
+-            throw new Error(ex);
+-        }
+-    }
+-
+     private static class TestMethodData {
+         final Class<?> clazz;
+         final String name;
+@@ -208,7 +155,9 @@
+             return LOOKUP.findStatic(testMethod.clazz, testMethod.name, testMethod.methodType);
+         case REF_invokeSpecial:
+             Class<?> thisClass = LOOKUP.lookupClass();
+-            return LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass);
++            MethodHandle smh = LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass);
++            noteInvokeSpecial(smh);
++            return smh;
+         case REF_newInvokeSpecial:
+             return LOOKUP.findConstructor(testMethod.clazz, testMethod.methodType);
+         default:
+@@ -238,7 +187,9 @@
+         case REF_invokeSpecial: {
+                 Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray());
+                 Class<?> thisClass = LOOKUP.lookupClass();
+-                return LOOKUP.unreflectSpecial(m, thisClass);
++                MethodHandle smh = LOOKUP.unreflectSpecial(m, thisClass);
++                noteInvokeSpecial(smh);
++                return smh;
+             }
+         case REF_newInvokeSpecial: {
+                 Constructor c = testMethod.clazz.getDeclaredConstructor(testMethod.methodType.parameterArray());
+@@ -249,59 +200,20 @@
+         }
+     }
+ 
+-    private static Object newMethodHandleInfo(MethodHandle mh) {
+-        try {
+-            return MHI_CONSTRUCTOR.invoke(mh);
+-        } catch (Throwable ex) {
+-            throw new Error(ex);
+-        }
++    private static List<MethodHandle> specialMethodHandles = new ArrayList<>();
++    private static void noteInvokeSpecial(MethodHandle mh) {
++        specialMethodHandles.add(mh);
++        assert(isInvokeSpecial(mh));
+     }
+-
+     private static boolean isInvokeSpecial(MethodHandle mh) {
+-        try {
+-            return (boolean) MH_IS_INVOKESPECIAL.invokeExact(mh);
+-        } catch (Throwable ex) {
+-            throw new Error(ex);
+-        }
+-    }
+-
+-    private static String getName(Object mhi) {
+-        try {
+-            return (String) MHI_GET_NAME.invoke(mhi);
+-        } catch (Throwable ex) {
+-            throw new Error(ex);
+-        }
+-    }
+-
+-    private static MethodType getMethodType(Object mhi) {
+-        try {
+-            return (MethodType) MHI_GET_METHOD_TYPE.invoke(mhi);
+-        } catch (Throwable ex) {
+-            throw new Error(ex);
+-        }
+-    }
+-
+-    private static Class<?> getDeclaringClass(Object mhi) {
+-        try {
+-            return (Class<?>) MHI_GET_DECLARING_CLASS.invoke(mhi);
+-        } catch (Throwable ex) {
+-            throw new Error(ex);
+-        }
+-    }
+-
+-    private static int getReferenceKind(Object mhi) {
+-        try {
+-            return (int) MHI_GET_REFERENCE_KIND.invoke(mhi);
+-        } catch (Throwable ex) {
+-            throw new Error(ex);
+-        }
++        return specialMethodHandles.contains(mh);
+     }
+ 
+     private static void assertRefKindEquals(int expect, int observed) {
+         if (expect == observed) return;
+ 
+-        String msg = "expected " + REF_KIND_NAMES[(int) expect] +
+-                     " but observed " + REF_KIND_NAMES[(int) observed];
++        String msg = "expected " + referenceKindToString(expect) +
++                     " but observed " + referenceKindToString(observed);
+         System.out.println("FAILED: " + msg);
+         throw new AssertionError(msg);
+     }
+diff --git a/test/java/lang/invoke/RevealDirectTest.java b/test/java/lang/invoke/RevealDirectTest.java
+new file mode 100644
+--- /dev/null
++++ b/test/java/lang/invoke/RevealDirectTest.java
+@@ -0,0 +1,753 @@
++/*
++ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.  Oracle designates this
++ * particular file as subject to the "Classpath" exception as provided
++ * by Oracle in the LICENSE file that accompanied this code.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++/*
++ * @test
++ * @summary verify Lookup.revealDirect on a variety of input handles
++ * @compile -XDignore.symbol.file RevealDirectTest.java
++ * @run junit/othervm -ea -esa test.java.lang.invoke.RevealDirectTest
++ *
++ * @test
++ * @summary verify Lookup.revealDirect on a variety of input handles, with security manager
++ * @run main/othervm/policy=jtreg.security.policy/secure=java.lang.SecurityManager -ea -esa test.java.lang.invoke.RevealDirectTest
++ */
++
++/* To run manually:
++ * $ $JAVA8X_HOME/bin/javac -cp $JUNIT4_JAR -d ../../../.. -XDignore.symbol.file RevealDirectTest.java
++ * $ $JAVA8X_HOME/bin/java  -cp $JUNIT4_JAR:../../../.. -ea -esa org.junit.runner.JUnitCore test.java.lang.invoke.RevealDirectTest
++ * $ $JAVA8X_HOME/bin/java  -cp $JUNIT4_JAR:../../../.. -ea -esa    -Djava.security.manager test.java.lang.invoke.RevealDirectTest
++ */
++
++package test.java.lang.invoke;
++
++import java.lang.reflect.*;
++import java.lang.invoke.*;
++import static java.lang.invoke.MethodHandles.*;
++import static java.lang.invoke.MethodType.*;
++import static java.lang.invoke.MethodHandleInfo.*;
++import java.util.*;
++import static org.junit.Assert.*;
++import org.junit.*;
++
++public class RevealDirectTest {
++    public static void main(String... av) throws Throwable {
++        // Run the @Test methods explicitly, in case we don't want to use the JUnitCore driver.
++        // This appears to be necessary when running with a security manager.
++        Throwable fail = null;
++        for (Method test : RevealDirectTest.class.getDeclaredMethods()) {
++            if (!test.isAnnotationPresent(Test.class))  continue;
++            try {
++                test.invoke(new RevealDirectTest());
++            } catch (Throwable ex) {
++                if (ex instanceof InvocationTargetException)
++                    ex = ex.getCause();
++                if (fail == null)  fail = ex;
++                System.out.println("Testcase: "+test.getName()
++                                   +"("+test.getDeclaringClass().getName()
++                                   +"):\tCaused an ERROR");
++                System.out.println(ex);
++                ex.printStackTrace(System.out);
++            }
++        }
++        if (fail != null)  throw fail;
++    }
++
++    public interface SimpleSuperInterface {
++        public abstract int getInt();
++        public static void printAll(String... args) {
++            System.out.println(Arrays.toString(args));
++        }
++        public int NICE_CONSTANT = 42;
++    }
++    public interface SimpleInterface extends SimpleSuperInterface {
++        default float getFloat() { return getInt(); }
++        public static void printAll(String[] args) {
++            System.out.println(Arrays.toString(args));
++        }
++    }
++    public static class Simple implements SimpleInterface, Cloneable {
++        public int intField;
++        public final int finalField;
++        private static String stringField;
++        public int getInt() { return NICE_CONSTANT; }
++        private static Number getNum() { return 804; }
++        public Simple clone() {
++            try {
++                return (Simple) super.clone();
++            } catch (CloneNotSupportedException ex) {
++                throw new RuntimeException(ex);
++            }
++        }
++        Simple() { finalField = -NICE_CONSTANT; }
++        private static Lookup localLookup() { return lookup(); }
++        private static List<Member> members() { return getMembers(lookup().lookupClass()); };
++    }
++
++    static boolean VERBOSE = false;
++
++    @Test public void testSimple() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testSimple");
++        testOnMembers("testSimple", Simple.members(), Simple.localLookup());
++    }
++    @Test public void testPublicLookup() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testPublicLookup");
++        List<Member> mems = publicOnly(Simple.members());
++        Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup();
++        testOnMembers("testPublicLookup/1", mems, pubLookup);
++        // reveal using publicLookup:
++        testOnMembers("testPublicLookup/2", mems, privLookup, pubLookup);
++        // lookup using publicLookup, but reveal using private:
++        testOnMembers("testPublicLookup/3", mems, pubLookup, privLookup);
++    }
++    @Test public void testPublicLookupNegative() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testPublicLookupNegative");
++        List<Member> mems = nonPublicOnly(Simple.members());
++        Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup();
++        testOnMembersNoLookup("testPublicLookupNegative/1", mems, pubLookup);
++        testOnMembersNoReveal("testPublicLookupNegative/2", mems, privLookup, pubLookup);
++        testOnMembersNoReflect("testPublicLookupNegative/3", mems, privLookup, pubLookup);
++    }
++    @Test public void testJavaLangClass() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testJavaLangClass");
++        List<Member> mems = callerSensitive(false, publicOnly(getMembers(Class.class)));
++        mems = limit(20, mems);
++        testOnMembers("testJavaLangClass", mems, Simple.localLookup());
++    }
++    @Test public void testCallerSensitive() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testCallerSensitive");
++        List<Member> mems = union(getMembers(MethodHandles.class, "lookup"),
++                                  getMembers(Method.class, "invoke"),
++                                  getMembers(Field.class, "get", "set", "getLong"),
++                                  getMembers(Class.class));
++        mems = callerSensitive(true, publicOnly(mems));
++        mems = limit(10, mems);
++        testOnMembers("testCallerSensitive", mems, Simple.localLookup());
++    }
++    @Test public void testCallerSensitiveNegative() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testCallerSensitiveNegative");
++        List<Member> mems = union(getMembers(MethodHandles.class, "lookup"),
++                                  getMembers(Class.class, "forName"),
++                                  getMembers(Method.class, "invoke"));
++        mems = callerSensitive(true, publicOnly(mems));
++        // CS methods cannot be looked up with publicLookup
++        testOnMembersNoLookup("testCallerSensitiveNegative", mems, publicLookup());
++    }
++    @Test public void testMethodHandleNatives() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testMethodHandleNatives");
++        List<Member> mems = getMembers(MethodHandle.class, "invoke", "invokeExact");
++        testOnMembers("testMethodHandleNatives", mems, Simple.localLookup());
++    }
++    @Test public void testMethodHandleInvokes() throws Throwable {
++        if (VERBOSE)  System.out.println("@Test testMethodHandleInvokes");
++        List<MethodType> types = new ArrayList<>();
++        Class<?>[] someParamTypes = { void.class, int.class, Object.class, Object[].class };
++        for (Class<?> rt : someParamTypes) {
++            for (Class<?> p0 : someParamTypes) {
++                if (p0 == void.class) { types.add(methodType(rt)); continue; }
++                for (Class<?> p1 : someParamTypes) {
++                    if (p1 == void.class) { types.add(methodType(rt, p0)); continue; }
++                    for (Class<?> p2 : someParamTypes) {
++                        if (p2 == void.class) { types.add(methodType(rt, p0, p1)); continue; }
++                        types.add(methodType(rt, p0, p1, p2));
++                    }
++                }
++            }
++        }
++        List<Member> mems = union(getPolyMembers(MethodHandle.class, "invoke", types),
++                                  getPolyMembers(MethodHandle.class, "invokeExact", types));
++        testOnMembers("testMethodHandleInvokes/1", mems, Simple.localLookup());
++        testOnMembers("testMethodHandleInvokes/2", mems, publicLookup());
++    }
++
++    static List<Member> getPolyMembers(Class<?> cls, String name, List<MethodType> types) {
++        assert(cls == MethodHandle.class);
++        ArrayList<Member> mems = new ArrayList<>();
++        for (MethodType type : types) {
++            mems.add(new SignaturePolymorphicMethod(name, type));
++        }
++        return mems;
++    }
++    static List<Member> getMembers(Class<?> cls) {
++        return getMembers(cls, (String[]) null);
++    }
++    static List<Member> getMembers(Class<?> cls, String... onlyNames) {
++        List<String> names = (onlyNames == null || onlyNames.length == 0 ? null : Arrays.asList(onlyNames));
++        ArrayList<Member> res = new ArrayList<>();
++        for (Class<?> sup : getSupers(cls)) {
++            res.addAll(getDeclaredMembers(sup, "getDeclaredFields"));
++            res.addAll(getDeclaredMembers(sup, "getDeclaredMethods"));
++            res.addAll(getDeclaredMembers(sup, "getDeclaredConstructors"));
++        }
++        res = new ArrayList<>(new LinkedHashSet<>(res));
++        for (int i = 0; i < res.size(); i++) {
++            Member mem = res.get(i);
++            if (!canBeReached(mem, cls) ||
++                res.indexOf(mem) != i ||
++                mem.isSynthetic() ||
++                (names != null && !names.contains(mem.getName()))
++                ) {
++                res.remove(i--);
++            }
++        }
++        return res;
++    }
++    static List<Class<?>> getSupers(Class<?> cls) {
++        ArrayList<Class<?>> res = new ArrayList<>();
++        ArrayList<Class<?>> intfs = new ArrayList<>();
++        for (Class<?> sup = cls; sup != null; sup = sup.getSuperclass()) {
++            res.add(sup);
++            for (Class<?> intf : cls.getInterfaces()) {
++                if (!intfs.contains(intf))
++                    intfs.add(intf);
++            }
++        }
++        for (int i = 0; i < intfs.size(); i++) {
++            for (Class<?> intf : intfs.get(i).getInterfaces()) {
++                if (!intfs.contains(intf))
++                    intfs.add(intf);
++            }
++        }
++        res.addAll(intfs);
++        //System.out.println("getSupers => "+res);
++        return res;
++    }
++    static boolean hasSM() {
++        return (System.getSecurityManager() != null);
++    }
++    static List<Member> getDeclaredMembers(Class<?> cls, String accessor) {
++        Member[] mems = {};
++        Method getter = getMethod(Class.class, accessor);
++        if (hasSM()) {
++            try {
++                mems = (Member[]) invokeMethod(getter, cls);
++            } catch (SecurityException ex) {
++                //if (VERBOSE)  ex.printStackTrace();
++                accessor = accessor.replace("Declared", "");
++                getter = getMethod(Class.class, accessor);
++                if (VERBOSE)  System.out.println("replaced accessor: "+getter);
++            }
++        }
++        if (mems.length == 0) {
++            try {
++                mems = (Member[]) invokeMethod(getter, cls);
++            } catch (SecurityException ex) {
++                ex.printStackTrace();
++            }
++        }
++        if (VERBOSE)  System.out.println(accessor+" "+cls.getName()+" => "+mems.length+" members");
++        return Arrays.asList(mems);
++    }
++    static Method getMethod(Class<?> cls, String name) {
++        try {
++            return cls.getMethod(name);
++        } catch (ReflectiveOperationException ex) {
++            throw new AssertionError(ex);
++        }
++    }
++    static Object invokeMethod(Method m, Object recv, Object... args) {
++        try {
++            return m.invoke(recv, args);
++        } catch (InvocationTargetException ex) {
++            Throwable ex2 = ex.getCause();
++            if (ex2 instanceof RuntimeException)  throw (RuntimeException) ex2;
++            if (ex2 instanceof Error)  throw (Error) ex2;
++            throw new AssertionError(ex);
++        } catch (ReflectiveOperationException ex) {
++            throw new AssertionError(ex);
++        }
++    }
++
++    static List<Member> limit(int len, List<Member> mems) {
++        if (mems.size() <= len)  return mems;
++        return mems.subList(0, len);
++    }
++    @SafeVarargs
++    static List<Member> union(List<Member> mems, List<Member>... mem2s) {
++        for (List<Member> mem2 : mem2s) {
++            for (Member m : mem2) {
++                if (!mems.contains(m))
++                    mems.add(m);
++            }
++        }
++        return mems;
++    }
++    static List<Member> callerSensitive(boolean cond, List<Member> members) {
++        for (Iterator<Member> i = members.iterator(); i.hasNext(); ) {
++            Member mem = i.next();
++            if (isCallerSensitive(mem) != cond)
++                i.remove();
++        }
++        if (members.isEmpty())  throw new AssertionError("trivial result");
++        return members;
++    }
++    static boolean isCallerSensitive(Member mem) {
++        if (!(mem instanceof AnnotatedElement))  return false;
++        AnnotatedElement ae = (AnnotatedElement) mem;
++        if (CS_CLASS != null)
++            return ae.isAnnotationPresent(sun.reflect.CallerSensitive.class);
++        for (java.lang.annotation.Annotation a : ae.getDeclaredAnnotations()) {
++            if (a.toString().contains(".CallerSensitive"))
++                return true;
++        }
++        return false;
++    }
++    static final Class<?> CS_CLASS;
++    static {
++        Class<?> c = null;
++        try {
++            c = sun.reflect.CallerSensitive.class;
++        } catch (SecurityException | LinkageError ex) {
++        }
++        CS_CLASS = c;
++    }
++    static List<Member> publicOnly(List<Member> members) {
++        return removeMods(members, Modifier.PUBLIC, 0);
++    }
++    static List<Member> nonPublicOnly(List<Member> members) {
++        return removeMods(members, Modifier.PUBLIC, -1);
++    }
++    static List<Member> removeMods(List<Member> members, int mask, int bits) {
++        int publicMods = (mask & Modifier.PUBLIC);
++        members = new ArrayList<>(members);
++        for (Iterator<Member> i = members.iterator(); i.hasNext(); ) {
++            Member mem = i.next();
++            int mods = mem.getModifiers();
++            if ((publicMods & mods) != 0 &&
++                (publicMods & mem.getDeclaringClass().getModifiers()) == 0)
++                mods -= publicMods;
++            if ((mods & mask) == (bits & mask))
++                i.remove();
++        }
++        return members;
++    }
++
++    void testOnMembers(String tname, List<Member> mems, Lookup lookup, Lookup... lookups) throws Throwable {
++        if (VERBOSE)  System.out.println("testOnMembers "+mems);
++        Lookup revLookup = (lookups.length > 0) ? lookups[0] : null;
++        if (revLookup == null)  revLookup = lookup;
++        Lookup refLookup = (lookups.length > 1) ? lookups[1] : null;
++        if (refLookup == null)  refLookup = lookup;
++        assert(lookups.length <= 2);
++        testOnMembersImpl(tname, mems, lookup, revLookup, refLookup, NO_FAIL);
++    }
++    void testOnMembersNoLookup(String tname, List<Member> mems, Lookup lookup) throws Throwable {
++        if (VERBOSE)  System.out.println("testOnMembersNoLookup "+mems);
++        testOnMembersImpl(tname, mems, lookup, null, null, FAIL_LOOKUP);
++    }
++    void testOnMembersNoReveal(String tname, List<Member> mems,
++                               Lookup lookup, Lookup negLookup) throws Throwable {
++        if (VERBOSE)  System.out.println("testOnMembersNoReveal "+mems);
++        testOnMembersImpl(tname, mems, lookup, negLookup, null, FAIL_REVEAL);
++    }
++    void testOnMembersNoReflect(String tname, List<Member> mems,
++                                Lookup lookup, Lookup negLookup) throws Throwable {
++        if (VERBOSE)  System.out.println("testOnMembersNoReflect "+mems);
++        testOnMembersImpl(tname, mems, lookup, lookup, negLookup, FAIL_REFLECT);
++    }
++    void testOnMembersImpl(String tname, List<Member> mems,
++                           Lookup lookup,
++                           Lookup revLookup,
++                           Lookup refLookup,
++                           int failureMode) throws Throwable {
++        Throwable fail = null;
++        int failCount = 0;
++        failureModeCounts = new int[FAIL_MODE_COUNT];
++        long tm0 = System.currentTimeMillis();
++        for (Member mem : mems) {
++            try {
++                testWithMember(mem, lookup, revLookup, refLookup, failureMode);
++            } catch (Throwable ex) {
++                if (fail == null)  fail = ex;
++                if (++failCount > 10) { System.out.println("*** FAIL: too many failures"); break; }
++                System.out.println("*** FAIL: "+mem+" => "+ex);
++                if (VERBOSE)  ex.printStackTrace(System.out);
++            }
++        }
++        long tm1 = System.currentTimeMillis();
++        System.out.printf("@Test %s executed %s tests in %d ms",
++                          tname, testKinds(failureModeCounts), (tm1-tm0)).println();
++        if (fail != null)  throw fail;
++    }
++    static String testKinds(int[] modes) {
++        int pos = modes[0], neg = -pos;
++        for (int n : modes)  neg += n;
++        if (neg == 0)  return pos + " positive";
++        String negs = "";
++        for (int n : modes)  negs += "/"+n;
++        negs = negs.replaceFirst("/"+pos+"/", "");
++        negs += " negative";
++        if (pos == 0)  return negs;
++        return pos + " positive, " + negs;
++    }
++    static class SignaturePolymorphicMethod implements Member {  // non-reflected instance of MH.invoke*
++        final String name;
++        final MethodType type;
++        SignaturePolymorphicMethod(String name, MethodType type) {
++            this.name = name;
++            this.type = type;
++        }
++        public String toString() {
++            String typeStr = type.toString();
++            if (isVarArgs())  typeStr = typeStr.replaceFirst("\\[\\])$", "...)");
++            return (Modifier.toString(getModifiers())
++                    +typeStr.substring(0, typeStr.indexOf('('))+" "
++                    +getDeclaringClass().getTypeName()+"."
++                    +getName()+typeStr.substring(typeStr.indexOf('(')));
++        }
++        public boolean equals(Object x) {
++            return (x instanceof SignaturePolymorphicMethod && equals((SignaturePolymorphicMethod)x));
++        }
++        public boolean equals(SignaturePolymorphicMethod that) {
++            return this.name.equals(that.name) && this.type.equals(that.type);
++        }
++        public int hashCode() {
++            return name.hashCode() * 31 + type.hashCode();
++        }
++        public Class<?> getDeclaringClass() { return MethodHandle.class; }
++        public String getName() { return name; }
++        public MethodType getMethodType() { return type; }
++        public int getModifiers() { return Modifier.PUBLIC | Modifier.FINAL | Modifier.NATIVE | SYNTHETIC; }
++        public boolean isVarArgs() { return Modifier.isTransient(getModifiers()); }
++        public boolean isSynthetic() { return true; }
++        public Class<?> getReturnType() { return type.returnType(); }
++        public Class<?>[] getParameterTypes() { return type.parameterArray(); }
++        static final int SYNTHETIC = 0x00001000;
++    }
++    static class UnreflectResult {  // a tuple
++        final MethodHandle mh;
++        final Throwable ex;
++        final byte kind;
++        final Member mem;
++        final int var;
++        UnreflectResult(MethodHandle mh, byte kind, Member mem, int var) {
++            this.mh = mh;
++            this.ex = null;
++            this.kind = kind;
++            this.mem = mem;
++            this.var = var;
++        }
++        UnreflectResult(Throwable ex, byte kind, Member mem, int var) {
++            this.mh = null;
++            this.ex = ex;
++            this.kind = kind;
++            this.mem = mem;
++            this.var = var;
++        }
++        public String toString() {
++            return toInfoString()+"/v"+var;
++        }
++        public String toInfoString() {
++            return String.format("%s %s.%s:%s", MethodHandleInfo.referenceKindToString(kind),
++                                 mem.getDeclaringClass().getName(), name(mem), type(mem, kind));
++        }
++        static String name(Member mem) {
++            if (mem instanceof Constructor)  return "<init>";
++            return mem.getName();
++        }
++        static MethodType type(Member mem, byte kind) {
++            if (mem instanceof Field) {
++                Class<?> type = ((Field)mem).getType();
++                if (kind == REF_putStatic || kind == REF_putField)
++                    return methodType(void.class, type);
++                return methodType(type);
++            } else if (mem instanceof SignaturePolymorphicMethod) {
++                return ((SignaturePolymorphicMethod)mem).getMethodType();
++            }
++            Class<?>[] params = ((Executable)mem).getParameterTypes();
++            if (mem instanceof Constructor)
++                return methodType(void.class, params);
++            Class<?> type = ((Method)mem).getReturnType();
++            return methodType(type, params);
++        }
++    }
++    static UnreflectResult unreflectMember(Lookup lookup, Member mem, int variation) {
++        byte[] refKind = {0};
++        try {
++            return unreflectMemberOrThrow(lookup, mem, variation, refKind);
++        } catch (ReflectiveOperationException|SecurityException ex) {
++            return new UnreflectResult(ex, refKind[0], mem, variation);
++        }
++    }
++    static UnreflectResult unreflectMemberOrThrow(Lookup lookup, Member mem, int variation,
++                                                  byte[] refKind) throws ReflectiveOperationException {
++        Class<?> cls = lookup.lookupClass();
++        Class<?> defc = mem.getDeclaringClass();
++        String   name = mem.getName();
++        int      mods = mem.getModifiers();
++        boolean isStatic = Modifier.isStatic(mods);
++        MethodHandle mh = null;
++        byte kind = 0;
++        if (mem instanceof Method) {
++            Method m = (Method) mem;
++            MethodType type = methodType(m.getReturnType(), m.getParameterTypes());
++            boolean canBeSpecial = (!isStatic &&
++                                    (lookup.lookupModes() & Modifier.PRIVATE) != 0 &&
++                                    defc.isAssignableFrom(cls) &&
++                                    (!defc.isInterface() || Arrays.asList(cls.getInterfaces()).contains(defc)));
++            if (variation >= 2)
++                kind = REF_invokeSpecial;
++            else if (isStatic)
++                kind = REF_invokeStatic;
++            else if (defc.isInterface())
++                kind = REF_invokeInterface;
++            else
++                kind = REF_invokeVirtual;
++            refKind[0] = kind;
++            switch (variation) {
++            case 0:
++                mh = lookup.unreflect(m);
++                break;
++            case 1:
++                if (defc == MethodHandle.class &&
++                    !isStatic &&
++                    m.isVarArgs() &&
++                    Modifier.isFinal(mods) &&
++                    Modifier.isNative(mods)) {
++                    break;
++                }
++                if (isStatic)
++                    mh = lookup.findStatic(defc, name, type);
++                else
++                    mh = lookup.findVirtual(defc, name, type);
++                break;
++            case 2:
++                if (!canBeSpecial)
++                    break;
++                mh = lookup.unreflectSpecial(m, lookup.lookupClass());
++                break;
++            case 3:
++                if (!canBeSpecial)
++                    break;
++                mh = lookup.findSpecial(defc, name, type, lookup.lookupClass());
++                break;
++            }
++        } else if (mem instanceof SignaturePolymorphicMethod) {
++            SignaturePolymorphicMethod m = (SignaturePolymorphicMethod) mem;
++            MethodType type = methodType(m.getReturnType(), m.getParameterTypes());
++            kind = REF_invokeVirtual;
++            refKind[0] = kind;
++            switch (variation) {
++            case 0:
++                mh = lookup.findVirtual(defc, name, type);
++                break;
++            }
++        } else if (mem instanceof Constructor) {
++            name = "<init>";  // not used
++            Constructor<?> m = (Constructor<?>) mem;
++            MethodType type = methodType(void.class, m.getParameterTypes());
++            kind = REF_newInvokeSpecial;
++            refKind[0] = kind;
++            switch (variation) {
++            case 0:
++                mh = lookup.unreflectConstructor(m);
++                break;
++            case 1:
++                mh = lookup.findConstructor(defc, type);
++                break;
++            }
++        } else if (mem instanceof Field) {
++            Field m = (Field) mem;
++            Class<?> type = m.getType();
++            boolean canHaveSetter = !Modifier.isFinal(mods);
++            if (variation >= 2)
++                kind = (byte)(isStatic ? REF_putStatic : REF_putField);
++            else
++                kind = (byte)(isStatic ? REF_getStatic : REF_getField);
++            refKind[0] = kind;
++            switch (variation) {
++            case 0:
++                mh = lookup.unreflectGetter(m);
++                break;
++            case 1:
++                if (isStatic)
++                    mh = lookup.findStaticGetter(defc, name, type);
++                else
++                    mh = lookup.findGetter(defc, name, type);
++                break;
++            case 3:
++                if (!canHaveSetter)
++                    break;
++                mh = lookup.unreflectSetter(m);
++                break;
++            case 2:
++                if (!canHaveSetter)
++                    break;
++                if (isStatic)
++                    mh = lookup.findStaticSetter(defc, name, type);
++                else
++                    mh = lookup.findSetter(defc, name, type);
++                break;
++            }
++        } else {
++            throw new IllegalArgumentException(String.valueOf(mem));
++        }
++        if (mh == null)
++            // ran out of valid variations; return null to caller
++            return null;
++        return new UnreflectResult(mh, kind, mem, variation);
++    }
++    static boolean canBeReached(Member mem, Class<?> cls) {
++        Class<?> defc = mem.getDeclaringClass();
++        String   name = mem.getName();
++        int      mods = mem.getModifiers();
++        if (mem instanceof Constructor) {
++            name = "<init>";  // according to 292 spec.
++        }
++        if (defc == cls)
++            return true;
++        if (name.startsWith("<"))
++            return false;  // only my own constructors
++        if (Modifier.isPrivate(mods))
++            return false;  // only my own constructors
++        if (defc.getPackage() == cls.getPackage())
++            return true;   // package access or greater OK
++        if (Modifier.isPublic(mods))
++            return true;   // publics always OK
++        if (Modifier.isProtected(mods) && defc.isAssignableFrom(cls))
++            return true;   // protected OK
++        return false;
++    }
++    static boolean consistent(UnreflectResult res, MethodHandleInfo info) {
++        assert(res.mh != null);
++        assertEquals(res.kind, info.getReferenceKind());
++        assertEquals(res.mem.getModifiers(), info.getModifiers());
++        assertEquals(res.mem.getDeclaringClass(), info.getDeclaringClass());
++        String expectName = res.mem.getName();
++        if (res.kind == REF_newInvokeSpecial)
++            expectName = "<init>";
++        assertEquals(expectName, info.getName());
++        MethodType expectType = res.mh.type();
++        if ((res.kind & 1) == (REF_getField & 1))
++            expectType = expectType.dropParameterTypes(0, 1);
++        if (res.kind == REF_newInvokeSpecial)
++            expectType = expectType.changeReturnType(void.class);
++        assertEquals(expectType, info.getMethodType());
++        assertEquals(res.mh.isVarargsCollector(), isVarArgs(info));
++        assertEquals(res.toInfoString(), info.toString());
++        assertEquals(res.toInfoString(), MethodHandleInfo.toString(info.getReferenceKind(), info.getDeclaringClass(), info.getName(), info.getMethodType()));
++        return true;
++    }
++    static boolean isVarArgs(MethodHandleInfo info) {
++        return info.isVarArgs();
++    }
++    static boolean consistent(Member mem, Member mem2) {
++        assertEquals(mem, mem2);
++        return true;
++    }
++    static boolean consistent(MethodHandleInfo info, MethodHandleInfo info2) {
++        assertEquals(info.getReferenceKind(), info2.getReferenceKind());
++        assertEquals(info.getModifiers(), info2.getModifiers());
++        assertEquals(info.getDeclaringClass(), info2.getDeclaringClass());
++        assertEquals(info.getName(), info2.getName());
++        assertEquals(info.getMethodType(), info2.getMethodType());
++        assertEquals(isVarArgs(info), isVarArgs(info));
++        return true;
++    }
++    static boolean consistent(MethodHandle mh, MethodHandle mh2) {
++        assertEquals(mh.type(), mh2.type());
++        assertEquals(mh.isVarargsCollector(), mh2.isVarargsCollector());
++        return true;
++    }
++    int[] failureModeCounts;
++    static final int NO_FAIL=0, FAIL_LOOKUP=1, FAIL_REVEAL=2, FAIL_REFLECT=3, FAIL_MODE_COUNT=4;
++    void testWithMember(Member mem,
++                        Lookup lookup,      // initial lookup of member => MH
++                        Lookup revLookup,   // reveal MH => info
++                        Lookup refLookup,   // reflect info => member
++                        int failureMode) throws Throwable {
++        boolean expectEx1 = (failureMode == FAIL_LOOKUP);   // testOnMembersNoLookup
++        boolean expectEx2 = (failureMode == FAIL_REVEAL);   // testOnMembersNoReveal
++        boolean expectEx3 = (failureMode == FAIL_REFLECT);  // testOnMembersNoReflect
++        for (int variation = 0; ; variation++) {
++            UnreflectResult res = unreflectMember(lookup, mem, variation);
++            failureModeCounts[failureMode] += 1;
++            if (variation == 0)  assert(res != null);
++            if (res == null)  break;
++            if (VERBOSE && variation == 0)
++                System.out.println("from "+mem.getDeclaringClass().getSimpleName());
++            MethodHandle mh = res.mh;
++            Throwable   ex1 = res.ex;
++            if (VERBOSE)  System.out.println("  "+variation+": "+res+"  << "+(mh != null ? mh : ex1));
++            if (expectEx1 && ex1 != null)
++                continue;  // this is OK; we expected that lookup to fail
++            if (expectEx1)
++                throw new AssertionError("unexpected lookup for negative test");
++            if (ex1 != null && !expectEx1) {
++                if (failureMode != NO_FAIL)
++                    throw new AssertionError("unexpected lookup failure for negative test", ex1);
++                throw ex1;
++            }
++            MethodHandleInfo info;
++            try {
++                info = revLookup.revealDirect(mh);
++                if (expectEx2)  throw new AssertionError("unexpected revelation for negative test");
++            } catch (Throwable ex2) {
++                if (VERBOSE)  System.out.println("  "+variation+": "+res+" => "+mh.getClass().getName()+" => (EX2)"+ex2);
++                if (expectEx2)
++                    continue;  // this is OK; we expected the reflect to fail
++                if (failureMode != NO_FAIL)
++                    throw new AssertionError("unexpected revelation failure for negative test", ex2);
++                throw ex2;
++            }
++            assert(consistent(res, info));
++            Member mem2;
++            try {
++                mem2 = info.reflectAs(Member.class, refLookup);
++                if (expectEx3)  throw new AssertionError("unexpected reflection for negative test");
++                assert(!(mem instanceof SignaturePolymorphicMethod));
++            } catch (IllegalArgumentException ex3) {
++                if (VERBOSE)  System.out.println("  "+variation+": "+info+" => (EX3)"+ex3);
++                if (expectEx3)
++                    continue;  // this is OK; we expected the reflect to fail
++                if (mem instanceof SignaturePolymorphicMethod)
++                    continue;  // this is OK; we cannot reflect MH.invokeExact(a,b,c)
++                if (failureMode != NO_FAIL)
++                    throw new AssertionError("unexpected reflection failure for negative test", ex3);
++                throw ex3;
++            }
++            assert(consistent(mem, mem2));
++            UnreflectResult res2 = unreflectMember(lookup, mem2, variation);
++            MethodHandle mh2 = res2.mh;
++            assert(consistent(mh, mh2));
++            MethodHandleInfo info2 = lookup.revealDirect(mh2);
++            assert(consistent(info, info2));
++            assert(consistent(res, info2));
++            Member mem3;
++            if (hasSM())
++                mem3 = info2.reflectAs(Member.class, lookup);
++            else
++                mem3 = MethodHandles.reflectAs(Member.class, mh2);
++            assert(consistent(mem2, mem3));
++            if (hasSM()) {
++                try {
++                    MethodHandles.reflectAs(Member.class, mh2);
++                    throw new AssertionError("failed to throw on "+mem3);
++                } catch (SecurityException ex3) {
++                    // OK...
++                }
++            }
++        }
++    }
++}
+diff --git a/test/java/lang/invoke/jtreg.security.policy b/test/java/lang/invoke/jtreg.security.policy
+new file mode 100644
+--- /dev/null
++++ b/test/java/lang/invoke/jtreg.security.policy
+@@ -0,0 +1,9 @@
++/*
++ * security policy used by the test process
++ * must allow file reads so that jtreg itself can run
++ */
++
++grant {
++  // standard test activation permissions
++  permission java.io.FilePermission "*", "read";
++};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tl-fixes.2.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -0,0 +1,26 @@
+# HG changeset patch
+# User rfield
+# Date 1378418329 25200
+# Node ID 9cc74675a8548c6bbbda66d919953f65ea2813e3
+# Parent  4c711ef41bfa6fb3f2bc0d3021658c8b3e8a2093
+8024283: 10 nashorn tests fail with similar stack trace InternalError with cause being NoClassDefFoundError
+Summary: Fix pre-existing 292 bug tickled by combo of nashorn code and MethodHandleInfo changes
+Reviewed-by: jrose
+Contributed-by: vladimir.x.ivanov@oracle.com
+
+diff --git a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+--- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
++++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+@@ -612,6 +612,12 @@
+             return false;  // inner class of some sort
+         if (cls.getClassLoader() != MethodHandle.class.getClassLoader())
+             return false;  // not on BCP
++        MethodType mtype = member.getMethodOrFieldType();
++        if (!isStaticallyNameable(mtype.returnType()))
++            return false;
++        for (Class<?> ptype : mtype.parameterArray())
++            if (!isStaticallyNameable(ptype))
++                return false;
+         if (!member.isPrivate() && VerifyAccess.isSamePackage(MethodHandle.class, cls))
+             return true;   // in java.lang.invoke package
+         if (member.isPublic() && isStaticallyNameable(cls))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tl-fixes.3.patch	Fri Sep 13 22:49:37 2013 -0700
@@ -0,0 +1,31 @@
+# HG changeset patch
+# User rfield
+# Date 1378453380 25200
+# Node ID f2487bb0c0d2ed8e1e610c62a7e7726673cfcffc
+# Parent  9cc74675a8548c6bbbda66d919953f65ea2813e3
+8024260: 10 closed/java/lang/invoke/* tests failing after overhaul to MethodHandleInfo
+Reviewed-by: vlivanov, briangoetz
+Contributed-by: john.r.rose@oracle.com
+
+diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java
+--- a/src/share/classes/java/lang/invoke/MethodHandle.java
++++ b/src/share/classes/java/lang/invoke/MethodHandle.java
+@@ -1286,7 +1286,17 @@
+ 
+     /*non-public*/
+     MethodHandle withInternalMemberName(MemberName member) {
+-        return MethodHandleImpl.makeWrappedMember(this, member);
++        if (member != null) {
++            return MethodHandleImpl.makeWrappedMember(this, member);
++        } else if (internalMemberName() == null) {
++            // The required internaMemberName is null, and this MH (like most) doesn't have one.
++            return this;
++        } else {
++            // The following case is rare. Mask the internalMemberName by wrapping the MH in a BMH.
++            MethodHandle result = rebind();
++            assert (result.internalMemberName() == null);
++            return result;
++        }
+     }
+ 
+     /*non-public*/