changeset 418:4a0cedf169a2

meth-lazy: remove about 1kLOC more
author jrose
date Sat, 21 Jul 2012 14:10:20 -0700
parents e27e7efee021
children 905bcd21d2bb
files meth-lazy-7023639.rmcode.patch series
diffstat 2 files changed, 2268 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meth-lazy-7023639.rmcode.patch	Sat Jul 21 14:10:20 2012 -0700
@@ -0,0 +1,2267 @@
+# HG changeset patch
+# Parent 6683721e6afb216ff3d42a23cbbb40e6f99f4b21
+
+diff --git a/src/share/classes/java/lang/invoke/BoundMethodHandle.java b/src/share/classes/java/lang/invoke/BoundMethodHandle.java
+--- a/src/share/classes/java/lang/invoke/BoundMethodHandle.java
++++ b/src/share/classes/java/lang/invoke/BoundMethodHandle.java
+@@ -35,8 +35,7 @@
+ import java.lang.invoke.MethodHandles.Lookup;
+ import java.lang.reflect.Field;
+ import java.util.Arrays;
+-import java.util.IdentityHashMap;
+-import java.util.Map;
++import java.util.HashMap;
+ 
+ import sun.invoke.util.ValueConversions;
+ import sun.invoke.util.Wrapper;
+@@ -68,15 +67,15 @@
+             switch (xtype) {
+             case 'L':
+                 if (true)  return bindSingle(type, form, x);  // Use known fast path.
+-                return (BoundMethodHandle) Data.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
++                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
+             case 'I':
+-                return (BoundMethodHandle) Data.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
++                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
+             case 'J':
+-                return (BoundMethodHandle) Data.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
++                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
+             case 'F':
+-                return (BoundMethodHandle) Data.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
++                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
+             case 'D':
+-                return (BoundMethodHandle) Data.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
++                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
+             default : throw new InternalError("unexpected xtype: " + xtype);
+             }
+         } catch (Throwable t) {
+@@ -85,7 +84,7 @@
+     }
+ 
+     static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
+-            return new BMH_L(type, form, x);
++            return new Species_L(type, form, x);
+     }
+ 
+     MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
+@@ -106,7 +105,7 @@
+     @Override
+     MethodHandle bindArgument(int pos, char basicType, Object value) {
+         MethodType type = type().dropParameterTypes(pos, pos+1);
+-        LambdaForm form = internalForm().bind(1+pos, myData());
++        LambdaForm form = internalForm().bind(1+pos, speciesData());
+         return cloneExtend(type, form, basicType, value);
+     }
+ 
+@@ -138,14 +137,14 @@
+     }
+ 
+     /**
+-     * Return the {@link Data} instance representing this BMH species. All subclasses must provide a
++     * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
+      * static field containing this value, and they must accordingly implement this method.
+      */
+-    protected abstract Data myData();
++    protected abstract SpeciesData speciesData();
+ 
+     @Override
+     final Object internalValues() {
+-        Object[] boundValues = new Object[myData().fieldCount()];
++        Object[] boundValues = new Object[speciesData().fieldCount()];
+         for (int i = 0; i < boundValues.length; ++i) {
+             boundValues[i] = arg(i);
+         }
+@@ -154,7 +153,7 @@
+ 
+     public final Object arg(int i) {
+         try {
+-            switch (myData().fieldType(i)) {
++            switch (speciesData().fieldType(i)) {
+             case 'L': return argL(i);
+             case 'I': return argI(i);
+             case 'F': return argF(i);
+@@ -164,13 +163,13 @@
+         } catch (Throwable ex) {
+             throw new InternalError(ex);
+         }
+-        throw new InternalError("unexpected type: " + myData().types+"."+i);
++        throw new InternalError("unexpected type: " + speciesData().types+"."+i);
+     }
+-    public final Object argL(int i) throws Throwable { return          myData().getters[i].invokeBasic(this); }
+-    public final int    argI(int i) throws Throwable { return (int)    myData().getters[i].invokeBasic(this); }
+-    public final float  argF(int i) throws Throwable { return (float)  myData().getters[i].invokeBasic(this); }
+-    public final double argD(int i) throws Throwable { return (double) myData().getters[i].invokeBasic(this); }
+-    public final long   argJ(int i) throws Throwable { return (long)   myData().getters[i].invokeBasic(this); }
++    public final Object argL(int i) throws Throwable { return          speciesData().getters[i].invokeBasic(this); }
++    public final int    argI(int i) throws Throwable { return (int)    speciesData().getters[i].invokeBasic(this); }
++    public final float  argF(int i) throws Throwable { return (float)  speciesData().getters[i].invokeBasic(this); }
++    public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
++    public final long   argJ(int i) throws Throwable { return (long)   speciesData().getters[i].invokeBasic(this); }
+ 
+     //
+     // cloning API
+@@ -197,142 +196,142 @@
+     //
+ 
+     private  // make it private to force users to access the enclosing class first
+-    static final class BMH_L extends BoundMethodHandle {
++    static final class Species_L extends BoundMethodHandle {
+         final Object argL0;
+-        public BMH_L(MethodType mt, LambdaForm lf, Object argL0) {
++        public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
+             super(mt, lf);
+             this.argL0 = argL0;
+         }
+         // The following is a grossly irregular hack:
+         @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
+         @Override
+-        public Data myData() {
+-            return DATA;
++        public SpeciesData speciesData() {
++            return SPECIES_DATA;
+         }
+-        public static final Data DATA = Data.getForClass("L", BMH_L.class);
++        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
+         @Override
+         public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
+-            return new BMH_L(mt, lf, argL0);
++            return new Species_L(mt, lf, argL0);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
+         }
+     }
+ 
+ /*
+-    static final class BMH_LL extends BoundMethodHandle {
++    static final class Species_LL extends BoundMethodHandle {
+         final Object argL0;
+         final Object argL1;
+-        public BMH_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
++        public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
+             super(mt, lf);
+             this.argL0 = argL0;
+             this.argL1 = argL1;
+         }
+         @Override
+-        public Data myData() {
+-            return DATA;
++        public SpeciesData speciesData() {
++            return SPECIES_DATA;
+         }
+-        public static final Data DATA = Data.getForClass("LL", BMH_LL.class);
++        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class);
+         @Override
+         public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
+-            return new BMH_LL(mt, lf, argL0, argL1);
++            return new Species_LL(mt, lf, argL0, argL1);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
+         }
+     }
+ 
+-    static final class BMH_JL extends BoundMethodHandle {
++    static final class Species_JL extends BoundMethodHandle {
+         final long argJ0;
+         final Object argL1;
+-        public BMH_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
++        public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
+             super(mt, lf);
+             this.argJ0 = argJ0;
+             this.argL1 = argL1;
+         }
+         @Override
+-        public Data myData() {
+-            return DATA;
++        public SpeciesData speciesData() {
++            return SPECIES_DATA;
+         }
+-        public static final Data DATA = Data.getForClass("JL", BMH_JL.class);
++        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class);
+         @Override public final long   argJ0() { return argJ0; }
+         @Override public final Object argL1() { return argL1; }
+         @Override
+         public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
+-            return new BMH_JL(mt, lf, argJ0, argL1);
++            return new Species_JL(mt, lf, argJ0, argL1);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
+         }
+         @Override
+         public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
+-            return (BoundMethodHandle) DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
++            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
+         }
+     }
+ */
+ 
+     //
+-    // BMH meta-data
++    // BMH species meta-data
+     //
+ 
+     /**
+      * Meta-data wrapper for concrete BMH classes.
+      */
+-    static class Data {
++    static class SpeciesData {
+         final String                             types;
+         final Class<? extends BoundMethodHandle> clazz;
+-        // Bootstrapping requires circular relations MH -> BMH -> Data -> MH
++        // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
+         // Therefore, we need a non-final link in the chain.  Use array elements.
+         final MethodHandle[]                     constructor;
+         final MethodHandle[]                     getters;
+-        final Data[]                             extensions;
++        final SpeciesData[]                      extensions;
+ 
+         public int fieldCount() {
+             return types.length();
+@@ -342,7 +341,7 @@
+         }
+ 
+         public String toString() {
+-            return "Data["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
++            return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
+         }
+ 
+         /**
+@@ -356,9 +355,9 @@
+             return new Name(mh, mhName);
+         }
+ 
+-        static final Data EMPTY = new Data("", BoundMethodHandle.class);
++        static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
+ 
+-        private Data(String types, Class<? extends BoundMethodHandle> clazz) {
++        private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
+             this.types = types;
+             this.clazz = clazz;
+             if (!INIT_DONE) {
+@@ -368,7 +367,7 @@
+                 this.constructor = Factory.makeCtors(clazz, types, null);
+                 this.getters = Factory.makeGetters(clazz, types, null);
+             }
+-            this.extensions = new Data[EXTENSION_TYPES.length()];
++            this.extensions = new SpeciesData[EXTENSION_TYPES.length()];
+         }
+ 
+         private void initForBootstrap() {
+@@ -379,7 +378,7 @@
+             }
+         }
+ 
+-        private Data(String types) {
++        private SpeciesData(String types) {
+             // Placeholder only.
+             this.types = types;
+             this.clazz = null;
+@@ -389,27 +388,27 @@
+         }
+         private boolean isPlaceholder() { return clazz == null; }
+ 
+-        private static final Map<String, Data> CACHE = new IdentityHashMap<>();
++        private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
+         private static final boolean INIT_DONE;  // set after <clinit> finishes...
+ 
+-        Data extendWithType(char type) {
++        SpeciesData extendWithType(char type) {
+             int i = extensionIndex(type);
+-            Data d = extensions[i];
++            SpeciesData d = extensions[i];
+             if (d != null)  return d;
+-            extensions[i] = d = get((types+type).intern());
++            extensions[i] = d = get(types+type);
+             return d;
+         }
+ 
+-        Data extendWithIndex(byte index) {
+-            Data d = extensions[index];
++        SpeciesData extendWithIndex(byte index) {
++            SpeciesData d = extensions[index];
+             if (d != null)  return d;
+             extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index));
+             return d;
+         }
+ 
+-        private static Data get(String types) {
++        private static SpeciesData get(String types) {
+             // Acquire cache lock for query.
+-            Data d = accessCache(types, null);
++            SpeciesData d = lookupCache(types);
+             if (!d.isPlaceholder())
+                 return d;
+             Class<? extends BoundMethodHandle> cbmh;
+@@ -419,54 +418,51 @@
+                 cbmh = Factory.generateConcreteBMHClass(types);
+             }
+             // Reacquire cache lock.
+-            d = accessCache(types, null);
++            d = lookupCache(types);
+             // Class loading must have upgraded the cache.
+             assert(d != null && !d.isPlaceholder());
+             return d;
+         }
+-        static Data getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
+-            // clazz is a new class which is initializing its DATA field
+-            return accessCache(types, new Data(types, clazz));
++        static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
++            // clazz is a new class which is initializing its SPECIES_DATA field
++            return updateCache(types, new SpeciesData(types, clazz));
+         }
+-        private static synchronized Data accessCache(String types, Data upgrade) {
+-            assert(types == types.intern());  // caller responsibility
+-            Data d;
+-            if (upgrade != null) {
+-                assert((d = CACHE.get(types)) == null || d.isPlaceholder());
+-                d = upgrade;
+-                CACHE.put(types, d);
+-                return d;
+-            }
+-            d = CACHE.get(types);
+-            if (d != null) {
+-                return d;
+-            }
+-            d = new Data(types);
++        private static synchronized SpeciesData lookupCache(String types) {
++            SpeciesData d = CACHE.get(types);
++            if (d != null)  return d;
++            d = new SpeciesData(types);
+             assert(d.isPlaceholder());
+             CACHE.put(types, d);
+             return d;
+         }
++        private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
++            SpeciesData d2;
++            assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
++            assert(!d.isPlaceholder());
++            CACHE.put(types, d);
++            return d;
++        }
+ 
+         static {
+-            // pre-fill the BMH data cache with BMH's inner classes
++            // pre-fill the BMH speciesdata cache with BMH's inner classes
+             final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
+-            Data d0 = BoundMethodHandle.DATA;  // trigger class init
+-            assert(d0 == null || d0 == accessCache("", null)) : d0;
++            SpeciesData d0 = BoundMethodHandle.SPECIES_DATA;  // trigger class init
++            assert(d0 == null || d0 == lookupCache("")) : d0;
+             try {
+                 for (Class<?> c : rootCls.getDeclaredClasses()) {
+                     if (rootCls.isAssignableFrom(c)) {
+                         final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
+-                        Data d = Factory.dataFromConcreteBMHClass(cbmh);
++                        SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
+                         assert(d != null) : cbmh.getName();
+                         assert(d.clazz == cbmh);
+-                        assert(d == accessCache(d.types, null));
++                        assert(d == lookupCache(d.types));
+                     }
+                 }
+             } catch (Throwable e) {
+                 throw new InternalError(e);
+             }
+ 
+-            for (Data d : CACHE.values()) {
++            for (SpeciesData d : CACHE.values()) {
+                 d.initForBootstrap();
+             }
+             // Note:  Do not simplify this, because INIT_DONE must not be
+@@ -475,19 +471,19 @@
+         }
+     }
+ 
+-    static Data getData(String types) {
+-        return Data.get(types);
++    static SpeciesData getSpeciesData(String types) {
++        return SpeciesData.get(types);
+     }
+ 
+     /**
+      * Generation of concrete BMH classes.
+      *
+-     * A concrete BMH is fit for binding a number of values adhering to a
++     * A concrete BMH species is fit for binding a number of values adhering to a
+      * given type pattern. Reference types are erased.
+      *
+-     * BMH classes are cached by type pattern.
++     * BMH species are cached by type pattern.
+      *
+-     * A concrete BMH has a number of fields with the concrete (possibly erased) types of
++     * A BMH species has a number of fields with the concrete (possibly erased) types of
+      * bound values. Setters are provided as an API in BMH. Getters are exposed as MHs,
+      * which can be included as names in lambda forms.
+      */
+@@ -497,15 +493,18 @@
+         static final String JLS_SIG  = "Ljava/lang/String;";
+         static final String JLC_SIG  = "Ljava/lang/Class;";
+         static final String MH       = "java/lang/invoke/MethodHandle";
+-        static final String MH_SIG   = "Ljava/lang/invoke/MethodHandle;";
++        static final String MH_SIG   = "L"+MH+";";
+         static final String BMH      = "java/lang/invoke/BoundMethodHandle";
+-        static final String BMH_SIG  = "Ljava/lang/invoke/BoundMethodHandle;";
+-        static final String DATA     = "java/lang/invoke/BoundMethodHandle$Data";
+-        static final String DATA_SIG = "Ljava/lang/invoke/BoundMethodHandle$Data;";
++        static final String BMH_SIG  = "L"+BMH+";";
++        static final String SPECIES_DATA     = "java/lang/invoke/BoundMethodHandle$SpeciesData";
++        static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
+ 
+-        static final String BMHDATA_EWI_SIG = "(B)" + DATA_SIG;
+-        static final String BMHDATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + DATA_SIG;
+-        static final String MYDATA_SIG = "()" + DATA_SIG;
++        static final String SPECIES_PREFIX_NAME = "Species_";
++        static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
++
++        static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
++        static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG;
++        static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
+         static final String VOID_SIG   = "()V";
+ 
+         static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
+@@ -517,12 +516,12 @@
+         /**
+          * Generate a concrete subclass of BMH for a given combination of bound types.
+          *
+-         * A concrete BMH subclass adheres to the following schema:
++         * A concrete BMH species adheres to the following schema:
+          *
+          * <pre>
+-         * class BMH_<<types>> extends BMH {
++         * class Species_<<types>> extends BoundMethodHandle {
+          *     <<fields>>
+-         *     final String dataValuemyTypes() { return <<types>>; }
++         *     final SpeciesData speciesData() { return SpeciesData.get("<<types>>"); }
+          * }
+          * </pre>
+          *
+@@ -533,41 +532,40 @@
+          * the type signature, adhering to the naming schema described in the definition of
+          * {@link #makeFieldName()}.
+          *
+-         * For example, a concrete BMH class for two reference and one integral bound values
++         * For example, a concrete BMH species for two reference and one integral bound values
+          * would have the following shape:
+          *
+          * <pre>
+-         * final class BMH_LLI extends BMH {
++         * class BoundMethodHandle { ... private static
++         * final class Species_LLI extends BoundMethodHandle {
+          *     final Object argL0;
+          *     final Object argL1;
+          *     final int argI2;
+-         *     public BMH_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
++         *     public Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
+          *         super(mt, lf);
+          *         this.argL0 = argL0;
+          *         this.argL1 = argL1;
+          *         this.argI2 = argI2;
+          *     }
+-         *     public final String myTypes() { return TYPES; }
+-         *     public static final String TYPES = "LLI";
+-         *     public final Data myData() { return DATA; }
+-         *     public static final Data DATA = Data.getForClass(TYPES, BMH_LLI.class);
++         *     public final SpeciesData speciesData() { return SPECIES_DATA; }
++         *     public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
+          *     public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
+-         *         return DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
++         *         return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
+          *     }
+          *     public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
+-         *         return BMHData.get("LLIL").constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
++         *         return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+          *     }
+          *     public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
+-         *         return BMHData.get("LLII").constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
++         *         return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+          *     }
+          *     public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
+-         *         return BMHData.get("LLIJ").constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
++         *         return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+          *     }
+          *     public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
+-         *         return BMHData.get("LLIF").constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
++         *         return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+          *     }
+          *     public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
+-         *         return BMHData.get("LLID").constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
++         *         return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
+          *     }
+          * }
+          * </pre>
+@@ -578,13 +576,13 @@
+         static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
+             final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
+ 
+-            final String className = BMH + "$BMH_" + types;
+-            final String sourceFile = "BMH_" + types;
++            final String className  = SPECIES_PREFIX_PATH + types;
++            final String sourceFile = SPECIES_PREFIX_NAME + types;
+             cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
+             cw.visitSource(sourceFile, null);
+ 
+-            // emit static types and data fields
+-            cw.visitField(ACC_PUBLIC + ACC_STATIC, "DATA", DATA_SIG, null, null).visitEnd();
++            // emit static types and SPECIES_DATA fields
++            cw.visitField(ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
+ 
+             // emit bound argument fields
+             for (int i = 0; i < types.length(); ++i) {
+@@ -630,10 +628,10 @@
+             mv.visitMaxs(0, 0);
+             mv.visitEnd();
+ 
+-            // emit implementation of myData()
+-            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "myData", MYDATA_SIG, null, null);
++            // emit implementation of speciesData()
++            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
+             mv.visitCode();
+-            mv.visitFieldInsn(GETSTATIC, className, "DATA", DATA_SIG);
++            mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
+             mv.visitInsn(ARETURN);
+             mv.visitMaxs(0, 0);
+             mv.visitEnd();
+@@ -641,11 +639,11 @@
+             // emit clone()
+             mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
+             mv.visitCode();
+-            // return myData().constructor[0].invokeBasic(mt, lf, argL0, ...)
++            // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...)
+             // obtain constructor
+             mv.visitVarInsn(ALOAD, 0);
+-            mv.visitFieldInsn(GETSTATIC, className, "DATA", DATA_SIG);
+-            mv.visitFieldInsn(GETFIELD, DATA, "constructor", "[" + MH_SIG);
++            mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
++            mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
+             mv.visitInsn(ICONST_0);
+             mv.visitInsn(AALOAD);
+             // load mt, lf
+@@ -664,14 +662,14 @@
+                 char t = Wrapper.basicTypeChar(c);
+                 mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
+                 mv.visitCode();
+-                // return DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
++                // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
+                 // obtain constructor
+-                mv.visitFieldInsn(GETSTATIC, className, "DATA", DATA_SIG);
++                mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
+                 int iconstInsn = ICONST_0 + extensionIndex(t);
+                 assert(iconstInsn <= ICONST_5);
+                 mv.visitInsn(iconstInsn);
+-                mv.visitMethodInsn(INVOKEVIRTUAL, DATA, "extendWithIndex", BMHDATA_EWI_SIG);
+-                mv.visitFieldInsn(GETFIELD, DATA, "constructor", "[" + MH_SIG);
++                mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWithIndex", BMHSPECIES_DATA_EWI_SIG);
++                mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
+                 mv.visitInsn(ICONST_0);
+                 mv.visitInsn(AALOAD);
+                 // load mt, lf
+@@ -693,8 +691,8 @@
+             mv.visitCode();
+             mv.visitLdcInsn(types);
+             mv.visitLdcInsn(Type.getObjectType(className));
+-            mv.visitMethodInsn(INVOKESTATIC, DATA, "getForClass", BMHDATA_GFC_SIG);
+-            mv.visitFieldInsn(PUTSTATIC, className, "DATA", DATA_SIG);
++            mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG);
++            mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
+             mv.visitInsn(RETURN);
+             mv.visitMaxs(0, 0);
+             mv.visitEnd();
+@@ -768,11 +766,11 @@
+         // Auxiliary methods.
+         //
+ 
+-        static Data dataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
++        static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
+             try {
+-                Field fdata = cbmh.getDeclaredField("DATA");
+-                return (Data) fdata.get(null);
+-            } catch (Throwable ex) {
++                Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
++                return (SpeciesData) F_SPECIES_DATA.get(null);
++            } catch (ReflectiveOperationException ex) {
+                 throw new InternalError(ex);
+             }
+         }
+@@ -850,5 +848,5 @@
+     /**
+      * All subclasses must provide such a value describing their type signature.
+      */
+-    static final Data DATA = Data.EMPTY;
++    static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
+ }
+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
+@@ -241,7 +241,7 @@
+         assert(names.length == nameCursor);
+         if (MTYPE_ARG >= INARG_LIMIT) {
+             assert(names[MTYPE_ARG] == null);
+-            names[MTYPE_ARG] = BoundMethodHandle.getData("L").getterName(names[THIS_MH], 0);
++            names[MTYPE_ARG] = BoundMethodHandle.getSpeciesData("L").getterName(names[THIS_MH], 0);
+             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
+         }
+ 
+diff --git a/src/share/classes/java/lang/invoke/LambdaForm.java b/src/share/classes/java/lang/invoke/LambdaForm.java
+--- a/src/share/classes/java/lang/invoke/LambdaForm.java
++++ b/src/share/classes/java/lang/invoke/LambdaForm.java
+@@ -773,14 +773,14 @@
+         return new LambdaForm(debugName, arity2, names2, result2);
+     }
+ 
+-    LambdaForm bind(int namePos, BoundMethodHandle.Data oldData) {
++    LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) {
+         Name name = names[namePos];
+-        BoundMethodHandle.Data newData = oldData.extendWithType(name.type);
++        BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type);
+         return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData);
+     }
+     LambdaForm bind(Name name, Name binding,
+-                    BoundMethodHandle.Data oldData,
+-                    BoundMethodHandle.Data newData) {
++                    BoundMethodHandle.SpeciesData oldData,
++                    BoundMethodHandle.SpeciesData newData) {
+         int pos = name.index;
+         assert(name.isParam());
+         assert(!binding.isParam());
+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
+@@ -805,7 +805,8 @@
+      */
+     public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
+         asSpreaderChecks(arrayType, arrayLength);
+-        return MethodHandleImpl.spreadArguments(this, arrayType, arrayLength);
++        int spreadArgPos = type.parameterCount() - arrayLength;
++        return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength);
+     }
+ 
+     private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
+@@ -918,8 +919,12 @@
+      */
+     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
+         asCollectorChecks(arrayType, arrayLength);
++        int collectArgPos = type().parameterCount()-1;
++        MethodHandle target = this;
++        if (arrayType != type().parameterType(collectArgPos))
++            target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
+         MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength);
+-        return MethodHandleImpl.collectArguments(this, type.parameterCount()-1, collector);
++        return MethodHandleImpl.makeCollectArguments(target, collector, collectArgPos, false);
+     }
+ 
+     // private API: return true if last param exactly matches arrayType
+@@ -1245,9 +1250,9 @@
+     /*non-public*/
+     MethodHandle viewAsType(MethodType newType) {
+         // No actual conversions, just a new view of the same method.
+-        MethodHandle mh = MethodHandleImpl.convertArguments(this, newType, type(), 0);
+-        if (mh == null)  throw new InternalError();
+-        return mh;
++        if (!type.isViewableAs(newType))
++            throw new InternalError();
++        return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
+     }
+ 
+     // Decoding
+@@ -1273,7 +1278,7 @@
+ 
+     /*non-public*/ MethodHandle convertArguments(MethodType newType) {
+         // Override this if it can be improved.
+-        return MethodHandleImpl.convertArguments(this, newType, 1);
++        return MethodHandleImpl.makePairwiseConvert(this, newType, 1);
+     }
+ 
+     /*non-public*/
+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
+@@ -27,7 +27,6 @@
+ 
+ import sun.invoke.util.VerifyType;
+ 
+-import java.lang.invoke.BoundMethodHandle.Data;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.HashMap;
+@@ -35,7 +34,6 @@
+ import sun.invoke.util.ValueConversions;
+ import sun.invoke.util.Wrapper;
+ import static java.lang.invoke.LambdaForm.*;
+-import static java.lang.invoke.MethodHandleNatives.Constants.*;
+ import static java.lang.invoke.MethodHandleStatics.*;
+ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+ 
+@@ -151,106 +149,6 @@
+         }
+     }
+ 
+-    /*non-public*/ static
+-    MethodHandle convertArguments(MethodHandle target, MethodType srcType, int level) {
+-        MethodType dstType = target.type();
+-        if (dstType.equals(srcType))
+-            return target;
+-        assert(level > 1 || dstType.isConvertibleTo(srcType));
+-        MethodHandle retFilter = null;
+-        Class<?> oldRT = dstType.returnType();
+-        Class<?> newRT = srcType.returnType();
+-        if (!VerifyType.isNullConversion(oldRT, newRT)) {
+-            if (oldRT == void.class) {
+-                Wrapper wrap = newRT.isPrimitive() ? Wrapper.forPrimitiveType(newRT) : Wrapper.OBJECT;
+-                retFilter = ValueConversions.zeroConstantFunction(wrap);
+-            } else {
+-                retFilter = MethodHandles.identity(newRT);
+-                retFilter = convertArguments(retFilter, retFilter.type().changeParameterType(0, oldRT), level);
+-            }
+-            srcType = srcType.changeReturnType(oldRT);
+-        }
+-        MethodHandle res = null;
+-        Exception ex = null;
+-        try {
+-            res = convertArguments(target, srcType, dstType, level);
+-        } catch (IllegalArgumentException ex1) {
+-            ex = ex1;
+-        }
+-        if (res == null) {
+-            WrongMethodTypeException wmt = new WrongMethodTypeException("cannot convert to "+srcType+": "+target);
+-            wmt.initCause(ex);
+-            throw wmt;
+-        }
+-        if (retFilter != null)
+-            res = MethodHandles.filterReturnValue(res, retFilter);
+-        return res;
+-    }
+-
+-    static MethodHandle convertArguments(MethodHandle target,
+-                                         MethodType srcType,
+-                                         MethodType dstType,
+-                                         int level) {
+-        assert(dstType.parameterCount() == target.type().parameterCount());
+-        if (srcType == dstType)
+-            return target;
+-        if (dstType.parameterCount() != srcType.parameterCount())
+-            throw newIllegalArgumentException("mismatched parameter count", dstType, srcType);
+-        return makePairwiseConvert(srcType, target, level);
+-    }
+-
+-    /** Can a JVM-level adapter directly implement the proposed
+-     *  argument conversions, as if by fixed-arity MethodHandle.asType?
+-     */
+-    private static boolean canPairwiseConvert(MethodType srcType, MethodType dstType, int level) {
+-        // same number of args, of course
+-        int len = srcType.parameterCount();
+-        if (len != dstType.parameterCount())
+-            return false;
+-
+-        // Check return type.
+-        Class<?> exp = srcType.returnType();
+-        Class<?> ret = dstType.returnType();
+-        if (!VerifyType.isNullConversion(ret, exp)) {
+-            if (!canConvertArgument(ret, exp, level))
+-                return false;
+-        }
+-
+-        // Check args pairwise.
+-        for (int i = 0; i < len; i++) {
+-            Class<?> src = srcType.parameterType(i); // source type
+-            Class<?> dst = dstType.parameterType(i); // destination type
+-            if (!canConvertArgument(src, dst, level))
+-                return false;
+-        }
+-
+-        return true;
+-    }
+-
+-    /** Can a JVM-level adapter directly implement the proposed
+-     *  argument conversion, as if by fixed-arity MethodHandle.asType?
+-     */
+-    private static boolean canConvertArgument(Class<?> src, Class<?> dst, int level) {
+-        // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
+-        // so we don't need to repeat so much decision making.
+-        if (VerifyType.isNullConversion(src, dst)) {
+-            return true;
+-        // } else if (convOpSupported(OP_COLLECT_ARGS)) {
+-        //     // If we can build filters, we can convert anything to anything.
+-        //     return true;
+-        } else if (src.isPrimitive()) {
+-            if (dst.isPrimitive())
+-                return canPrimCast(src, dst);
+-            else
+-                return canBoxArgument(src, dst);
+-        } else {
+-            if (dst.isPrimitive())
+-                return canUnboxArgument(src, dst, level);
+-            else
+-                return true;  // any two refs can be interconverted
+-        }
+-    }
+-
+     /**
+      * Create a JVM-level adapter method handle to conform the given method
+      * handle to the similar newType, using only pairwise argument conversions.
+@@ -264,13 +162,12 @@
+      *          or the original target if the types are already identical
+      *          or null if the adaptation cannot be made
+      */
+-    private static MethodHandle makePairwiseConvert(MethodType srcType, MethodHandle target, int level) {
++    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
++        assert(level >= 0 && level <= 2);
+         MethodType dstType = target.type();
+-        if (srcType == dstType)  return target;
+-
+-        if (!canPairwiseConvert(srcType, dstType, level))
+-            return null;
+-        // (after this point, it is an assertion error to fail to convert)
++        assert(dstType.parameterCount() == target.type().parameterCount());
++        if (srcType == dstType)
++            return target;
+ 
+         // Calculate extra arguments (temporaries) required in the names array.
+         // FIXME: Use an ArrayList<Name>.  Some arguments require more than one conversion step.
+@@ -278,27 +175,26 @@
+         for (int i = 0; i < srcType.parameterCount(); i++) {
+             Class<?> src = srcType.parameterType(i);
+             Class<?> dst = dstType.parameterType(i);
+-            if (!isTrivialConversion(src, dst, level)) {
++            if (!VerifyType.isNullConversion(src, dst)) {
+                 extra++;
+             }
+         }
+ 
+         Class<?> needReturn = srcType.returnType();
+         Class<?> haveReturn = dstType.returnType();
+-        boolean retConv = !isTrivialConversion(haveReturn, needReturn, level);
++        boolean retConv = !VerifyType.isNullConversion(haveReturn, needReturn);
+ 
+         // Now build a LambdaForm.
+         MethodType lambdaType = srcType.invokerType();
+         Name[] names = arguments(extra + 1, lambdaType);
+         int[] indexes = new int[lambdaType.parameterCount()];
+ 
+-        MethodHandle adapter = target;
+         MethodType midType = dstType;
+         for (int i = 0, argIndex = 1, tmpIndex = lambdaType.parameterCount(); i < srcType.parameterCount(); i++, argIndex++) {
+             Class<?> src = srcType.parameterType(i);
+             Class<?> dst = midType.parameterType(i);
+ 
+-            if (isTrivialConversion(src, dst, level)) {
++            if (VerifyType.isNullConversion(src, dst)) {
+                 // do nothing: difference is trivial
+                 indexes[i] = argIndex;
+                 continue;
+@@ -308,24 +204,46 @@
+             midType = midType.changeParameterType(i, src);
+ 
+             // Tricky case analysis follows.
+-            // It parallels canConvertArgument() above.
+             MethodHandle fn = null;
+             if (src.isPrimitive()) {
+                 if (dst.isPrimitive()) {
+-                    fn = makePrimCast(src, dst);
++                    fn = ValueConversions.convertPrimitive(src, dst);
+                 } else {
+-                    fn = makeBoxArgument(midType, adapter, i, src);
++                    Wrapper w = Wrapper.forPrimitiveType(src);
++                    MethodHandle boxMethod = ValueConversions.box(w);
++                    if (dst == w.wrapperType())
++                        fn = boxMethod;
++                    else
++                        fn = boxMethod.asType(MethodType.methodType(dst, src));
+                 }
+             } else {
+                 if (dst.isPrimitive()) {
+                     // Caller has boxed a primitive.  Unbox it for the target.
+-                    fn = makeUnboxArgument(src, dst, level);
++                    Wrapper w = Wrapper.forPrimitiveType(dst);
++                    if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
++                        fn = ValueConversions.unbox(dst);
++                    } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
++                        // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
++                        // must include additional conversions
++                        // src must be examined at runtime, to detect Byte, Character, etc.
++                        MethodHandle unboxMethod = (level == 1
++                                                    ? ValueConversions.unbox(dst)
++                                                    : ValueConversions.unboxCast(dst));
++                        fn = unboxMethod;
++                    } else {
++                        // Example: Byte->int
++                        // Do this by reformulating the problem to Byte->byte.
++                        Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
++                        MethodHandle unbox = ValueConversions.unbox(srcPrim);
++                        // Compose the two conversions.  FIXME:  should make two Names for this job
++                        fn = unbox.asType(MethodType.methodType(dst, src));
++                    }
+                 } else {
+                     // Simple reference conversion.
+                     // Note:  Do not check for a class hierarchy relation
+                     // between src and dst.  In all cases a 'null' argument
+                     // will pass the cast conversion.
+-                    fn = makeCheckCast(midType, adapter, i, dst);
++                    fn = ValueConversions.cast(dst);
+                 }
+             }
+             names[tmpIndex] = new Name(fn, names[argIndex]);
+@@ -333,9 +251,17 @@
+             tmpIndex++;
+         }
+         if (retConv) {
+-            MethodHandle fn = makeReturnConversion(adapter, haveReturn, needReturn);
+-            assert(fn != null);
+-            target = fn;
++            MethodHandle adjustReturn;
++            if (haveReturn == void.class) {
++                // synthesize a zero value for the given void
++                Object zero = Wrapper.forBasicType(needReturn).zero();
++                adjustReturn = MethodHandles.constant(needReturn, zero);
++            } else {
++                MethodHandle identity = MethodHandles.identity(needReturn);
++                MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
++                adjustReturn = makePairwiseConvert(identity, needConversion, level);
++            }
++            target = makeCollectArguments(adjustReturn, target, 0, false);
+         }
+ 
+         // Build argument array for the call.
+@@ -349,133 +275,12 @@
+         return new SimpleMethodHandle(srcType, form);
+     }
+ 
+-    private static boolean isTrivialConversion(Class<?> src, Class<?> dst, int level) {
+-        if (src == dst || dst == void.class)  return true;
+-        if (!VerifyType.isNullConversion(src, dst))  return false;
+-        if (level > 1)  return true;  // explicitCastArguments
+-        boolean sp = src.isPrimitive();
+-        boolean dp = dst.isPrimitive();
+-        if (sp != dp)  return false;
+-        if (sp) {
+-            // in addition to being a null conversion, forbid boolean->int etc.
+-            return Wrapper.forPrimitiveType(dst)
+-                    .isConvertibleFrom(Wrapper.forPrimitiveType(src));
+-        } else {
+-            return dst.isAssignableFrom(src);
+-        }
+-    }
+-
+-    private static MethodHandle makeReturnConversion(MethodHandle target, Class<?> haveReturn, Class<?> needReturn) {
+-        MethodHandle adjustReturn;
+-        if (haveReturn == void.class) {
+-            // synthesize a zero value for the given void
+-            Object zero = Wrapper.forBasicType(needReturn).zero();
+-            adjustReturn = MethodHandles.constant(needReturn, zero);
+-        } else {
+-            MethodType needConversion = MethodType.methodType(needReturn, haveReturn);
+-            adjustReturn = MethodHandles.identity(needReturn).asType(needConversion);
+-        }
+-        return makeCollectArguments(adjustReturn, target, 0, false);
+-    }
+-
+-    /* Return one plus the position of the first non-trivial difference
+-     * between the given types.  This is not a symmetric operation;
+-     * we are considering adapting the targetType to adapterType.
+-     * Trivial differences are those which could be ignored by the JVM
+-     * without subverting the verifier.  Otherwise, adaptable differences
+-     * are ones for which we could create an adapter to make the type change.
+-     * Return zero if there are no differences (other than trivial ones).
+-     * Return 1+N if N is the only adaptable argument difference.
+-     * Return the -2-N where N is the first of several adaptable
+-     * argument differences.
+-     * Return -1 if there there are differences which are not adaptable.
+-     */
+-    private static int diffTypes(MethodType adapterType,
+-                                 MethodType targetType,
+-                                 boolean raw) {
+-        int diff;
+-        diff = diffReturnTypes(adapterType, targetType, raw);
+-        if (diff != 0)  return diff;
+-        int nargs = adapterType.parameterCount();
+-        if (nargs != targetType.parameterCount())
+-            return -1;
+-        return diffParamTypes(adapterType, 0, targetType, 0, nargs, raw);
+-    }
+-    private static int diffReturnTypes(MethodType adapterType,
+-                                       MethodType targetType,
+-                                       boolean raw) {
+-        Class<?> src = targetType.returnType();
+-        Class<?> dst = adapterType.returnType();
+-        if ((!raw
+-             ? VerifyType.canPassUnchecked(src, dst)
+-             : VerifyType.canPassRaw(src, dst)
+-             ) > 0)
+-            return 0;  // no significant difference
+-        if (raw && !src.isPrimitive() && !dst.isPrimitive())
+-            return 0;  // can force a reference return (very carefully!)
+-        //if (false)  return 1;  // never adaptable!
+-        return -1;  // some significant difference
+-    }
+-    private static int diffParamTypes(MethodType adapterType, int astart,
+-                                      MethodType targetType, int tstart,
+-                                      int nargs, boolean raw) {
+-        assert(nargs >= 0);
+-        int res = 0;
+-        for (int i = 0; i < nargs; i++) {
+-            Class<?> src  = adapterType.parameterType(astart+i);
+-            Class<?> dest = targetType.parameterType(tstart+i);
+-            if ((!raw
+-                 ? VerifyType.canPassUnchecked(src, dest)
+-                 : VerifyType.canPassRaw(src, dest)
+-                ) <= 0) {
+-                // found a difference; is it the only one so far?
+-                if (res != 0)
+-                    return -1-res; // return -2-i for prev. i
+-                res = 1+i;
+-            }
+-        }
+-        return res;
+-    }
+-
+-    /** Can a retyping adapter (alone) validly convert the target to newType? */
+-    // private static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
+-    //     return canRetype(newType, targetType, false);
+-    // }
+-    /** Can a retyping adapter (alone) convert the target to newType?
+-     *  It is allowed to widen subword types and void to int, to make bitwise
+-     *  conversions between float/int and double/long, and to perform unchecked
+-     *  reference conversions on return.  This last feature requires that the
+-     *  caller be trusted, and perform explicit cast conversions on return values.
+-     */
+-    // private static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
+-    //     return canRetype(newType, targetType, true);
+-    // }
+-    // private static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) {
+-    //     int diff = diffTypes(newType, targetType, raw);
+-    //     // %%% This assert is too strong.  Factor diff into VerifyType and reconcile.
+-    //     assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
+-    //     return diff == 0;
+-    // }
+-
+-    /** Factory method:  Performs no conversions; simply retypes the adapter.
+-     *  Allows unchecked argument conversions pairwise, if they are safe.
+-     *  Returns null if not possible.
+-     */
+-    static MethodHandle makeRetype(MethodType srcType, MethodHandle target) {
+-        MethodType dstType = target.type();
+-        if (dstType == srcType)  return target;
+-        // if (!canRetype(srcType, dstType, raw))
+-        //     return null;
+-        // TO DO:  clone the target guy, whatever he is, with new type.
+-        //return AdapterMethodHandle.makeRetype(srcType, target, raw);
+-        MethodType lambdaType = srcType.invokerType();
++    static MethodHandle makeReferenceIdentity(Class<?> refType) {
++        MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
+         Name[] names = arguments(1, lambdaType);
+-
+-        Object[] targetArgs = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount(), Object[].class);
+-        names[names.length - 1] = new Name(target, targetArgs);
+-
+-        LambdaForm form = new LambdaForm("asType", lambdaType.parameterCount(), names);
+-        return new SimpleMethodHandle(srcType, form);
++        names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
++        LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
++        return new SimpleMethodHandle(MethodType.methodType(refType, refType), form);
+     }
+ 
+     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
+@@ -578,251 +383,20 @@
+         }
+     }
+ 
+-    /** Can a checkcast adapter validly convert the target to srcType?
+-     *  The JVM supports all kind of reference casts, even silly ones.
+-     */
+-    private static boolean canCheckCast(MethodType srcType, MethodType targetType,
+-                                        int arg, Class<?> castType) {
+-        Class<?> src = srcType.parameterType(arg);
+-        Class<?> dst = targetType.parameterType(arg);
+-        if (!canCheckCast(src, castType)
+-                || !VerifyType.isNullConversion(castType, dst))
+-            return false;
+-        // int diff = diffTypes(srcType, targetType, false);
+-        // return (diff == arg+1) || (diff == 0);  // arg is sole non-trivial diff
+-        return true;
+-    }
+-    /** Can an primitive conversion adapter validly convert src to dst? */
+-    private static boolean canCheckCast(Class<?> src, Class<?> dst) {
+-        return (!src.isPrimitive() && !dst.isPrimitive());
+-    }
++    /** Factory method:  Spread selected argument. */
++    static MethodHandle makeSpreadArguments(MethodHandle target,
++                                            Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
++        MethodType targetType = target.type();
+ 
+-    /** Factory method:  Forces a cast at the given argument.
+-     *  The castType is the target of the cast, and can be any type
+-     *  with a null conversion to the corresponding target parameter.
+-     *  Return null if this cannot be done.
+-     */
+-    private static MethodHandle makeCheckCast(MethodType srcType, MethodHandle target,
+-                                              int arg, Class<?> castType) {
+-        if (!canCheckCast(srcType, target.type(), arg, castType))
+-            return null;
+-        return ValueConversions.cast(castType);
+-    }
+-
+-    /** Can an primitive conversion adapter validly convert the target to newType?
+-     *  The JVM currently supports all conversions except those between
+-     *  floating and integral types.
+-     */
+-    private static boolean canPrimCast(MethodType newType, MethodType targetType,
+-                                       int arg, Class<?> convType) {
+-        Class<?> src = newType.parameterType(arg);
+-        Class<?> dst = targetType.parameterType(arg);
+-        if (!canPrimCast(src, convType)
+-                || !VerifyType.isNullConversion(convType, dst))
+-            return false;
+-        // int diff = diffTypes(newType, targetType, false);
+-        // return (diff == arg+1);  // arg is sole non-trivial diff
+-        return true;
+-    }
+-    /** Can an primitive conversion adapter validly convert src to dst? */
+-    static boolean canPrimCast(Class<?> src, Class<?> dst) {
+-        if (!src.isPrimitive() || !dst.isPrimitive()) {
+-            return false;
+-        }
+-        return true;
+-    }
+-
+-    /** Factory method:  Truncate the given argument with zero or sign extension,
+-     *  and/or convert between single and doubleword versions of integer or float.
+-     */
+-    private static MethodHandle makePrimCast(Class<?> src, Class<?> dst) {
+-        if (VerifyType.isNullConversion(src, dst))
+-            return ValueConversions.identity(dst);
+-        else
+-            return ValueConversions.convertPrimitive(src, dst);
+-    }
+-
+-    /** Can an unboxing conversion validly convert src to dst?
+-     *  The JVM currently supports all kinds of casting and unboxing.
+-     *  The convType is the unboxed type; it can be either a primitive or wrapper.
+-     */
+-    private static boolean canUnboxArgument(MethodType srcType, MethodType targetType,
+-                                            int arg, Class<?> convType, int level) {
+-        Class<?> src = srcType.parameterType(arg);
+-        Class<?> dst = targetType.parameterType(arg);
+-        Class<?> boxType = Wrapper.asWrapperType(convType);
+-        convType = Wrapper.asPrimitiveType(convType);
+-        if (!canCheckCast(src, boxType)
+-                || boxType == convType
+-                || !VerifyType.isNullConversion(convType, dst))
+-            return false;
+-        // int diff = diffTypes(srcType, targetType, false);
+-        // return (diff == arg+1);  // arg is sole non-trivial diff
+-        return true;
+-    }
+-    /** Can an primitive unboxing adapter validly convert src to dst? */
+-    private static boolean canUnboxArgument(Class<?> src, Class<?> dst, int level) {
+-        assert(dst.isPrimitive());
+-        // if we have JVM support for boxing, we can also do complex unboxing
+-        return true;
+-    }
+-
+-    /** Factory method:  Unbox the given argument.
+-     */
+-    private static MethodHandle makeUnboxArgument(Class<?> src, Class<?> dst, int level) {
+-        Class<?> convType = dst;
+-        Class<?> boxType = Wrapper.asWrapperType(convType);
+-        Class<?> primType = Wrapper.asPrimitiveType(convType);
+-        Class<?> castDone = src;
+-        if (!VerifyType.isNullConversion(src, boxType)) {
+-            // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
+-            if (level != 0) {
+-                // must include additional conversions
+-                if (src == Object.class || !Wrapper.isWrapperType(src)) {
+-                    // src must be examined at runtime, to detect Byte, Character, etc.
+-                    MethodHandle unboxMethod = (level == 1
+-                                                ? ValueConversions.unbox(dst)
+-                                                : ValueConversions.unboxCast(dst));
+-                    // long conv = makeConv(OP_COLLECT_ARGS, arg, basicType(src), basicType(dst));
+-                    // return new AdapterMethodHandle(target, srcType, conv, unboxMethod);
+-                    return unboxMethod;
+-                }
+-                // Example: Byte->int
+-                // Do this by reformulating the problem to Byte->byte.
+-                Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
+-                MethodHandle unbox = makeUnboxArgument(src, srcPrim, 0);
+-                // Compose the two conversions.  FIXME:  caller should make two Names for this job
+-                return unbox.asType(MethodType.methodType(dst, src));
+-            }
+-            castDone = boxType;
+-        }
+-        // long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
+-        // MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
+-        MethodHandle unboxMethod = ValueConversions.unbox(dst);
+-        if (castDone == src)
+-            return unboxMethod;
+-        return unboxMethod.asType(MethodType.methodType(src, dst));
+-    }
+-
+-    /** Can a boxing conversion validly convert src to dst? */
+-    private static boolean canBoxArgument(MethodType srcType, MethodType targetType,
+-                                          int arg, Class<?> convType) {
+-        Class<?> src = srcType.parameterType(arg);
+-        Class<?> dst = targetType.parameterType(arg);
+-        Class<?> boxType = Wrapper.asWrapperType(convType);
+-        convType = Wrapper.asPrimitiveType(convType);
+-        if (!canCheckCast(boxType, dst)
+-                || boxType == convType
+-                || !VerifyType.isNullConversion(src, convType))
+-            return false;
+-        // int diff = diffTypes(srcType, targetType, false);
+-        // return (diff == arg+1);  // arg is sole non-trivial diff
+-        return true;
+-    }
+-
+-    /** Can an primitive boxing adapter validly convert src to dst? */
+-    private static boolean canBoxArgument(Class<?> src, Class<?> dst) {
+-        return (src.isPrimitive() && !dst.isPrimitive());
+-    }
+-
+-    /** Factory method:  Box the given argument.
+-     *  Return null if this cannot be done.
+-     */
+-    private static MethodHandle makeBoxArgument(MethodType srcType, MethodHandle target,
+-                                                int arg, Class<?> convType) {
+-        MethodType dstType = target.type();
+-        Class<?> src = srcType.parameterType(arg);
+-        Class<?> dst = dstType.parameterType(arg);
+-        Class<?> boxType = Wrapper.asWrapperType(convType);
+-        Class<?> primType = Wrapper.asPrimitiveType(convType);
+-        if (!canBoxArgument(srcType, dstType, arg, convType)) {
+-            return null;
+-        }
+-        if (!VerifyType.isNullConversion(boxType, dst))
+-            target = makeCheckCast(dstType.changeParameterType(arg, boxType), target, arg, dst);
+-        return ValueConversions.box(Wrapper.forPrimitiveType(primType));
+-    }
+-
+-    static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) {
+-        MethodType oldType = target.type();
+-        int nargs = oldType.parameterCount();
+-        int keepPosArgs = nargs - arrayLength;
+-        MethodType srcType = oldType
+-                .dropParameterTypes(keepPosArgs, nargs)
+-                .insertParameterTypes(keepPosArgs, arrayType);
+-        return spreadArguments(target, srcType, keepPosArgs, arrayType, arrayLength);
+-    }
+-    // called internally only
+-    private static MethodHandle spreadArgumentsFromPos(MethodHandle target, MethodType srcType, int spreadArgPos) {
+-        int arrayLength = target.type().parameterCount() - spreadArgPos;
+-        return spreadArguments(target, srcType, spreadArgPos, Object[].class, arrayLength);
+-    }
+-    private static MethodHandle spreadArguments(MethodHandle target,
+-                                                MethodType srcType,
+-                                                int spreadArgPos,
+-                                                Class<?> arrayType,
+-                                                int arrayLength) {
+-        // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
+-        MethodType dstType = target.type();
+-        // spread the last argument of srcType to dstType
+-        assert(arrayLength == dstType.parameterCount() - spreadArgPos);
+-        assert(srcType.parameterType(spreadArgPos) == arrayType);
+-        return makeSpreadArguments(srcType, target, arrayType, spreadArgPos, arrayLength);
+-    }
+-
+-    /** Can an adapter spread an argument to convert the target to srcType? */
+-    private static boolean canSpreadArguments(MethodType srcType, MethodType targetType,
+-                                              Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
+-        if (diffReturnTypes(srcType, targetType, false) != 0)
+-            return false;
+-        int nptypes = srcType.parameterCount();
+-        // parameter types must be the same up to the spread point
+-        if (spreadArgPos != 0 && diffParamTypes(srcType, 0, targetType, 0, spreadArgPos, false) != 0)
+-            return false;
+-        int afterPos = spreadArgPos + spreadArgCount;
+-        int afterCount = nptypes - (spreadArgPos + 1);
+-        if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
+-            spreadArgCount < 0 ||
+-            targetType.parameterCount() != afterPos + afterCount)
+-            return false;
+-        // parameter types after the spread point must also be the same
+-        if (afterCount != 0 && diffParamTypes(srcType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0)
+-            return false;
+-        // match the array element type to the spread arg types
+-        Class<?> rawSpreadArgType = srcType.parameterType(spreadArgPos);
+-        if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType))
+-            return false;
+-        for (int i = 0; i < spreadArgCount; i++) {
+-            Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i);
+-            Class<?> dst = targetType.parameterType(spreadArgPos + i);
+-            if (src == null || !canConvertArgument(src, dst, 1))
+-                return false;
+-        }
+-        return true;
+-    }
+-
+-
+-    /** Factory method:  Spread selected argument. */
+-    private static MethodHandle makeSpreadArguments(MethodType srcType, MethodHandle target,
+-                                                    Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
+-        // FIXME: Get rid of srcType; derive new arguments from structure of spreadArgType
+-        MethodType targetType = target.type();
+-        assert(canSpreadArguments(srcType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
+-            : "[srcType, targetType, spreadArgType, spreadArgPos, spreadArgCount] = "
+-              + Arrays.asList(srcType, targetType, spreadArgType, spreadArgPos, spreadArgCount);
+-        // dest is not significant; remove?
+-        int dest = T_VOID;
+         for (int i = 0; i < spreadArgCount; i++) {
+             Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
+             if (arg == null)  arg = Object.class;
+-            int dest2 = basicType(arg);
+-            if      (dest == T_VOID)  dest = dest2;
+-            else if (dest != dest2)   dest = T_VOID;
+-            if (dest == T_VOID)  break;
+             targetType = targetType.changeParameterType(spreadArgPos + i, arg);
+         }
+         target = target.asType(targetType);
+ 
++        MethodType srcType = targetType
++                .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
+         // Now build a LambdaForm.
+         MethodType lambdaType = srcType.invokerType();
+         Name[] names = arguments(spreadArgCount + 2, lambdaType);
+@@ -883,61 +457,18 @@
+         }
+     }
+ 
+-    static MethodHandle collectArguments(MethodHandle target,
+-                                                int collectArg,
+-                                                MethodHandle collector) {
+-        MethodType type = target.type();
+-        Class<?> collectType = collector.type().returnType();
+-        assert(collectType != void.class);  // else use foldArguments
+-        if (collectType != type.parameterType(collectArg))
+-            target = target.asType(type.changeParameterType(collectArg, collectType));
+-        MethodType srcType = type
+-                .dropParameterTypes(collectArg, collectArg+1)
+-                .insertParameterTypes(collectArg, collector.type().parameterArray());
+-        return collectArguments(target, srcType, collectArg, collector);
+-    }
+-    static MethodHandle collectArguments(MethodHandle target,
+-                                                MethodType srcType,
+-                                                int collectArg,
+-                                                MethodHandle collector) {
+-        MethodType dstType = target.type();     // (a...,c)=>r
+-        //         srcType                      // (a..., b...)=>r
+-        MethodType colType = collector.type();  // (b...)=>c
+-        //         dstType                      // (a..., b...)=>r
+-        assert(srcType.parameterCount() == collectArg + colType.parameterCount());
+-        assert(dstType.parameterCount() == collectArg + 1);
+-        assert(canCollectArguments(dstType, colType, collectArg, false));
+-        return makeCollectArguments(target, collector, collectArg, false);
+-    }
+-
+-    /** Can an adapter collect a series of arguments, replacing them by zero or one results? */
+-    static boolean canCollectArguments(MethodType targetType,
+-                MethodType collectorType, int collectArgPos, boolean retainOriginalArgs) {
+-        int collectArgCount = collectorType.parameterCount();
+-        Class<?> rtype = collectorType.returnType();
+-        assert(rtype == void.class || targetType.parameterType(collectArgPos) == rtype)
+-                // [(Object)Object[], (Object[])Object[], 0, 1]
+-                : Arrays.asList(targetType, collectorType, collectArgPos, collectArgCount)
+-                ;
+-        return true;
+-    }
+-
+     /** Factory method:  Collect or filter selected argument(s). */
+     static MethodHandle makeCollectArguments(MethodHandle target,
+                 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
+-        assert(canCollectArguments(target.type(), collector.type(), collectArgPos, retainOriginalArgs));
+-        MethodType targetType = target.type();
+-        MethodType collectorType = collector.type();
++        MethodType targetType = target.type();          // (a..., c, [b...])=>r
++        MethodType collectorType = collector.type();    // (b...)=>c
+         int collectArgCount = collectorType.parameterCount();
+         Class<?> collectValType = collectorType.returnType();
+         int collectValCount = (collectValType == void.class ? 0 : 1);
+-        MethodType srcType = targetType.dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
+-        if (!retainOriginalArgs) {
++        MethodType srcType = targetType                 // (a..., [b...])=>r
++                .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
++        if (!retainOriginalArgs) {                      // (a..., b...)=>r
+             srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
+-        } else {
+-            // parameter types at the fold point must be the same
+-            assert(diffParamTypes(srcType, collectArgPos, targetType, collectValCount, collectArgCount, false) == 0)
+-                : Arrays.asList(target, collector, collectArgPos, retainOriginalArgs);
+         }
+         // in  arglist: [0: ...keep1 | cpos: collect...  | cpos+cacount: keep2... ]
+         // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
+@@ -980,26 +511,6 @@
+         return new SimpleMethodHandle(srcType, form);
+     }
+ 
+-    static MethodHandle filterArgument(MethodHandle target,
+-                                       int pos,
+-                                       MethodHandle filter) {
+-        MethodType ftype = filter.type();
+-        assert(ftype.parameterCount() == 1);
+-        // return AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
+-        return makeCollectArguments(target, filter, pos, false);
+-    }
+-
+-    static MethodHandle foldArguments(MethodHandle target,
+-                                      MethodType newType,
+-                                      int foldPos,
+-                                      MethodHandle combiner) {
+-        MethodType oldType = target.type();
+-        MethodType ctype = combiner.type();
+-        assert(canCollectArguments(oldType, ctype, foldPos, true));
+-        // return AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true);
+-        return makeCollectArguments(target, combiner, foldPos, true);
+-    }
+-
+     static
+     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
+         return testResult ? target : fallback;
+@@ -1189,22 +700,20 @@
+             MethodType gtype = type.generic();
+             MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+             // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
+-            MethodHandle gtarget = convertArguments(target, gtype, type, 2);
+-            MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, 2);
++            MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
++            MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
+             GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
+-            if (gtarget == null || gcatcher == null || gguard == null)  return null;
++            if (gtarget == null || gcatcher == null)  throw new InternalError();
+             MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
+-            return convertArguments(ginvoker, type, gtype, 2);
++            return makePairwiseConvert(ginvoker, type, 2);
+         } else {
+-            MethodType gtype = MethodType.genericMethodType(0, true);
+-            MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+-            MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
++            MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
+             catcher = catcher.asType(ctype.changeParameterType(0, Throwable.class));
+-            MethodHandle gcatcher = spreadArgumentsFromPos(catcher, gcatchType, 1);
++            MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
+             GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
+-            if (gtarget == null || gcatcher == null || gguard == null)  return null;
++            if (gtarget == null || gcatcher == null)  throw new InternalError();
+             MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
+-            return collectArguments(ginvoker, type, 0, ValueConversions.varargsArray(nargs)).asType(type);
++            return makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
+         }
+     }
+ 
+@@ -1215,7 +724,7 @@
+         if (arity > 1) {
+             return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
+         }
+-        return makeRetype(type, throwException());
++        return makePairwiseConvert(throwException(), type, 2);
+     }
+ 
+     static MethodHandle THROW_EXCEPTION;
+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
+@@ -1467,7 +1467,10 @@
+      */
+     public static
+     MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
+-        return MethodHandleImpl.convertArguments(target, newType, 2);
++        if (!target.type().isCastableTo(newType)) {
++            throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType);
++        }
++        return MethodHandleImpl.makePairwiseConvert(target, newType, 2);
+     }
+ 
+     /**
+@@ -1601,8 +1604,7 @@
+         else if (type.isPrimitive())
+             return ValueConversions.identity(Wrapper.forPrimitiveType(type));
+         else
+-            return MethodHandleImpl.makeRetype(
+-                     MethodType.methodType(type, type), ValueConversions.identity());
++            return MethodHandleImpl.makeReferenceIdentity(type);
+     }
+ 
+     /**
+@@ -1871,7 +1873,7 @@
+         if (filterType.parameterCount() != 1
+             || filterType.returnType() != targetType.parameterType(pos))
+             throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
+-        return MethodHandleImpl.filterArgument(target, pos, filter);
++        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
+     }
+ 
+     /**
+@@ -1943,7 +1945,6 @@
+             throw newIllegalArgumentException("target and filter types do not match", target, filter);
+         // result = fold( lambda(retval, arg...) { filter(retval) },
+         //                lambda(        arg...) { target(arg...) } )
+-        assert(MethodHandleImpl.canCollectArguments(filterType, targetType, 0, false));
+         return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
+     }
+ 
+@@ -2042,9 +2043,7 @@
+         if (!ok)
+             throw misMatchedTypes("target and combiner types", targetType, combinerType);
+         MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
+-        MethodHandle res = MethodHandleImpl.foldArguments(target, newType, foldPos, combiner);
+-        if (res == null)  throw newIllegalArgumentException("cannot fold from "+newType+" to " +targetType);
+-        return res;
++        return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
+     }
+ 
+     /**
+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
+@@ -33,6 +33,7 @@
+ import java.util.List;
+ import sun.invoke.util.BytecodeDescriptor;
+ import static java.lang.invoke.MethodHandleStatics.*;
++import sun.invoke.util.VerifyType;
+ 
+ /**
+  * A method type represents the arguments and return type accepted and
+@@ -240,8 +241,7 @@
+             ptypes = NO_PTYPES; trusted = true;
+         }
+         MethodType mt1 = new MethodType(rtype, ptypes);
+-        MethodType mt0;
+-        mt0 = internTable.get(mt1);
++        MethodType mt0 = internTable.get(mt1);
+         if (mt0 != null)
+             return mt0;
+         if (!trusted)
+@@ -383,6 +383,32 @@
+         return insertParameterTypes(parameterCount(), ptypesToInsert);
+     }
+ 
++     /**
++     * Finds or creates a method type with modified parameter types.
++     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
++     * @param start  the position (zero-based) of the first replaced parameter type(s)
++     * @param end    the position (zero-based) after the last replaced parameter type(s)
++     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
++     * @return the same type, except with the selected parameter(s) replaced
++     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
++     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
++     *                                  or if {@code start} is greater than {@code end}
++     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
++     *                                  or if the resulting method type would have more than 255 parameter slots
++     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
++     */
++    /*non-public*/ MethodType replaceParameterTypes(int start, int end, Class<?>... ptypesToInsert) {
++        if (start == end)
++            return insertParameterTypes(start, ptypesToInsert);
++        int len = ptypes.length;
++        if (!(0 <= start && start <= end && end <= len))
++            throw newIndexOutOfBoundsException("start="+start+" end="+end);
++        int ilen = ptypesToInsert.length;
++        if (ilen == 0)
++            return dropParameterTypes(start, end);
++        return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
++    }
++
+     /**
+      * Finds or creates a method type with some parameter types omitted.
+      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+@@ -573,6 +599,11 @@
+         return Collections.unmodifiableList(Arrays.asList(ptypes));
+     }
+ 
++    /*non-public*/ Class<?> lastParameterType() {
++        int len = ptypes.length;
++        return len == 0 ? void.class : ptypes[len-1];
++    }
++
+     /**
+      * Presents the parameter types as an array (a convenience method).
+      * Changes to the array will not result in changes to the type.
+@@ -642,6 +673,26 @@
+ 
+ 
+     /*non-public*/
++    boolean isViewableAs(MethodType newType) {
++        if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
++            return false;
++        int argc = parameterCount();
++        if (argc != newType.parameterCount())
++            return false;
++        for (int i = 0; i < argc; i++) {
++            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
++                return false;
++        }
++        return true;
++    }
++    /*non-public*/
++    boolean isCastableTo(MethodType newType) {
++        int argc = parameterCount();
++        if (argc != newType.parameterCount())
++            return false;
++        return true;
++    }
++    /*non-public*/
+     boolean isConvertibleTo(MethodType newType) {
+         if (!canConvert(returnType(), newType.returnType()))
+             return false;
+diff --git a/src/share/classes/java/lang/invoke/SimpleMethodHandle.java b/src/share/classes/java/lang/invoke/SimpleMethodHandle.java
+--- a/src/share/classes/java/lang/invoke/SimpleMethodHandle.java
++++ b/src/share/classes/java/lang/invoke/SimpleMethodHandle.java
+@@ -42,7 +42,7 @@
+     @Override
+     MethodHandle bindArgument(int pos, char basicType, Object value) {
+         MethodType type2 = type().dropParameterTypes(pos, pos+1);
+-        LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.Data.EMPTY);
++        LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY);
+         return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
+     }
+ 
+diff --git a/src/share/classes/sun/invoke/util/ValueConversions.java b/src/share/classes/sun/invoke/util/ValueConversions.java
+--- a/src/share/classes/sun/invoke/util/ValueConversions.java
++++ b/src/share/classes/sun/invoke/util/ValueConversions.java
+@@ -118,43 +118,15 @@
+         return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue();
+     }
+ 
+-    /// Converting references to "raw" values.
+-    /// A raw primitive value is always an int or long.
+-    /// FIXME: Get rid of the raw kind of conversions.
+-
+-    static int unboxByteRaw(Object x, boolean cast) {
+-        return unboxByte(x, cast);
+-    }
+-
+-    static int unboxShortRaw(Object x, boolean cast) {
+-        return unboxShort(x, cast);
+-    }
+-
+-    static int unboxBooleanRaw(Object x, boolean cast) {
+-        return unboxBoolean(x, cast) ? 1 : 0;
+-    }
+-
+-    static int unboxCharacterRaw(Object x, boolean cast) {
+-        return unboxCharacter(x, cast);
+-    }
+-
+-    static int unboxFloatRaw(Object x, boolean cast) {
+-        return Float.floatToIntBits(unboxFloat(x, cast));
+-    }
+-
+-    static long unboxDoubleRaw(Object x, boolean cast) {
+-        return Double.doubleToRawLongBits(unboxDouble(x, cast));
+-    }
+-
+-    private static MethodType unboxType(Wrapper wrap, boolean raw) {
+-        return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), Object.class, boolean.class);
++    private static MethodType unboxType(Wrapper wrap) {
++        return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
+     }
+ 
+     private static final EnumMap<Wrapper, MethodHandle>[]
+-            UNBOX_CONVERSIONS = newWrapperCaches(4);
++            UNBOX_CONVERSIONS = newWrapperCaches(2);
+ 
+-    private static MethodHandle unbox(Wrapper wrap, boolean raw, boolean cast) {
+-        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast?1:0)+(raw?2:0)];
++    private static MethodHandle unbox(Wrapper wrap, boolean cast) {
++        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast?1:0)];
+         MethodHandle mh = cache.get(wrap);
+         if (mh != null) {
+             return mh;
+@@ -164,19 +136,15 @@
+             case OBJECT:
+                 mh = IDENTITY; break;
+             case VOID:
+-                mh = raw ? ALWAYS_ZERO : IGNORE; break;
+-            case INT: case LONG:
+-                // these guys don't need separate raw channels
+-                if (raw)  mh = unbox(wrap, false, cast);
+-                break;
++                mh = IGNORE; break;
+         }
+         if (mh != null) {
+             cache.put(wrap, mh);
+             return mh;
+         }
+         // look up the method
+-        String name = "unbox" + wrap.wrapperSimpleName() + (raw ? "Raw" : "");
+-        MethodType type = unboxType(wrap, raw);
++        String name = "unbox" + wrap.wrapperSimpleName();
++        MethodType type = unboxType(wrap);
+         try {
+             mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
+         } catch (ReflectiveOperationException ex) {
+@@ -188,27 +156,19 @@
+             return mh;
+         }
+         throw new IllegalArgumentException("cannot find unbox adapter for " + wrap
+-                + (cast ? " (cast)" : "") + (raw ? " (raw)" : ""));
++                + (cast ? " (cast)" : ""));
+     }
+ 
+     public static MethodHandle unboxCast(Wrapper type) {
+-        return unbox(type, false, true);
+-    }
+-
+-    public static MethodHandle unboxRaw(Wrapper type) {
+-        return unbox(type, true, false);
++        return unbox(type, true);
+     }
+ 
+     public static MethodHandle unbox(Class<?> type) {
+-        return unbox(Wrapper.forPrimitiveType(type), false, false);
++        return unbox(Wrapper.forPrimitiveType(type), false);
+     }
+ 
+     public static MethodHandle unboxCast(Class<?> type) {
+-        return unbox(Wrapper.forPrimitiveType(type), false, true);
+-    }
+-
+-    public static MethodHandle unboxRaw(Class<?> type) {
+-        return unbox(Wrapper.forPrimitiveType(type), true, false);
++        return unbox(Wrapper.forPrimitiveType(type), true);
+     }
+ 
+     static private final Integer ZERO_INT = 0, ONE_INT = 1;
+@@ -299,53 +259,17 @@
+         return x;
+     }
+ 
+-    /// Converting raw primitives to references
+-
+-    static Byte boxByteRaw(int x) {
+-        return boxByte((byte)x);
+-    }
+-
+-    static Short boxShortRaw(int x) {
+-        return boxShort((short)x);
+-    }
+-
+-    static Boolean boxBooleanRaw(int x) {
+-        return boxBoolean(x != 0);
+-    }
+-
+-    static Character boxCharacterRaw(int x) {
+-        return boxCharacter((char)x);
+-    }
+-
+-    static Float boxFloatRaw(int x) {
+-        return boxFloat(Float.intBitsToFloat(x));
+-    }
+-
+-    static Double boxDoubleRaw(long x) {
+-        return boxDouble(Double.longBitsToDouble(x));
+-    }
+-
+-    // a raw void value is (arbitrarily) a garbage int
+-    static Void boxVoidRaw(int x) {
+-        return null;
+-    }
+-
+-    private static MethodType boxType(Wrapper wrap, boolean raw) {
++    private static MethodType boxType(Wrapper wrap) {
+         // be exact, since return casts are hard to compose
+         Class<?> boxType = wrap.wrapperType();
+-        return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
+-    }
+-
+-    private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
+-        if (raw)  return wrap.isDoubleWord() ? Wrapper.LONG : Wrapper.INT;
+-        return wrap;
++        return MethodType.methodType(boxType, wrap.primitiveType());
+     }
+ 
+     private static final EnumMap<Wrapper, MethodHandle>[]
+-            BOX_CONVERSIONS = newWrapperCaches(4);
++            BOX_CONVERSIONS = newWrapperCaches(2);
+ 
+-    private static MethodHandle box(Wrapper wrap, boolean exact, boolean raw) {
+-        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
++    private static MethodHandle box(Wrapper wrap, boolean exact) {
++        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)];
+         MethodHandle mh = cache.get(wrap);
+         if (mh != null) {
+             return mh;
+@@ -355,11 +279,7 @@
+             case OBJECT:
+                 mh = IDENTITY; break;
+             case VOID:
+-                if (!raw)  mh = ZERO_OBJECT;
+-                break;
+-            case INT: case LONG:
+-                // these guys don't need separate raw channels
+-                if (raw)  mh = box(wrap, exact, false);
++                mh = ZERO_OBJECT;
+                 break;
+         }
+         if (mh != null) {
+@@ -367,8 +287,8 @@
+             return mh;
+         }
+         // look up the method
+-        String name = "box" + wrap.wrapperSimpleName() + (raw ? "Raw" : "");
+-        MethodType type = boxType(wrap, raw);
++        String name = "box" + wrap.wrapperSimpleName();
++        MethodType type = boxType(wrap);
+         if (exact) {
+             try {
+                 mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
+@@ -376,143 +296,26 @@
+                 mh = null;
+             }
+         } else {
+-            mh = box(wrap, !exact, raw).asType(type.erase());
++            mh = box(wrap, !exact).asType(type.erase());
+         }
+         if (mh != null) {
+             cache.put(wrap, mh);
+             return mh;
+         }
+         throw new IllegalArgumentException("cannot find box adapter for "
+-                + wrap + (exact ? " (exact)" : "") + (raw ? " (raw)" : ""));
++                + wrap + (exact ? " (exact)" : ""));
+     }
+ 
+     public static MethodHandle box(Class<?> type) {
+         boolean exact = false;
+         // e.g., boxShort(short)Short if exact,
+         // e.g., boxShort(short)Object if !exact
+-        return box(Wrapper.forPrimitiveType(type), exact, false);
+-    }
+-
+-    public static MethodHandle boxRaw(Class<?> type) {
+-        boolean exact = false;
+-        // e.g., boxShortRaw(int)Short if exact
+-        // e.g., boxShortRaw(int)Object if !exact
+-        return box(Wrapper.forPrimitiveType(type), exact, true);
++        return box(Wrapper.forPrimitiveType(type), exact);
+     }
+ 
+     public static MethodHandle box(Wrapper type) {
+         boolean exact = false;
+-        return box(type, exact, false);
+-    }
+-
+-    public static MethodHandle boxRaw(Wrapper type) {
+-        boolean exact = false;
+-        return box(type, exact, true);
+-    }
+-
+-    /// Kludges for when raw values get accidentally boxed.
+-    /// FIXME: Get rid of the raw kind of conversions.
+-
+-    static int unboxRawInteger(Object x) {
+-        if (x instanceof Integer)
+-            return (int) x;
+-        else
+-            return (int) unboxLong(x, false);
+-    }
+-
+-    static Integer reboxRawInteger(Object x) {
+-        if (x instanceof Integer)
+-            return (Integer) x;
+-        else
+-            return (int) unboxLong(x, false);
+-    }
+-
+-    static Byte reboxRawByte(Object x) {
+-        if (x instanceof Byte)  return (Byte) x;
+-        return boxByteRaw(unboxRawInteger(x));
+-    }
+-
+-    static Short reboxRawShort(Object x) {
+-        if (x instanceof Short)  return (Short) x;
+-        return boxShortRaw(unboxRawInteger(x));
+-    }
+-
+-    static Boolean reboxRawBoolean(Object x) {
+-        if (x instanceof Boolean)  return (Boolean) x;
+-        return boxBooleanRaw(unboxRawInteger(x));
+-    }
+-
+-    static Character reboxRawCharacter(Object x) {
+-        if (x instanceof Character)  return (Character) x;
+-        return boxCharacterRaw(unboxRawInteger(x));
+-    }
+-
+-    static Float reboxRawFloat(Object x) {
+-        if (x instanceof Float)  return (Float) x;
+-        return boxFloatRaw(unboxRawInteger(x));
+-    }
+-
+-    static Long reboxRawLong(Object x) {
+-        return (Long) x;  //never a rebox
+-    }
+-
+-    static Double reboxRawDouble(Object x) {
+-        if (x instanceof Double)  return (Double) x;
+-        return boxDoubleRaw(unboxLong(x, true));
+-    }
+-
+-    private static MethodType reboxType(Wrapper wrap) {
+-        Class<?> boxType = wrap.wrapperType();
+-        return MethodType.methodType(boxType, Object.class);
+-    }
+-
+-    private static final EnumMap<Wrapper, MethodHandle>[]
+-            REBOX_CONVERSIONS = newWrapperCaches(1);
+-
+-    /**
+-     * Because we normalize primitive types to reduce the number of signatures,
+-     * primitives are sometimes manipulated under an "erased" type,
+-     * either int (for types other than long/double) or long (for all types).
+-     * When the erased primitive value is then boxed into an Integer or Long,
+-     * the final boxed primitive is sometimes required.  This transformation
+-     * is called a "rebox".  It takes an Integer or Long and produces some
+-     * other boxed value, typed (inexactly) as an Object
+-     */
+-    public static MethodHandle rebox(Wrapper wrap) {
+-        EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[0];
+-        MethodHandle mh = cache.get(wrap);
+-        if (mh != null) {
+-            return mh;
+-        }
+-        // slow path
+-        switch (wrap) {
+-            case OBJECT:
+-                mh = IDENTITY; break;
+-            case VOID:
+-                throw new IllegalArgumentException("cannot rebox a void");
+-        }
+-        if (mh != null) {
+-            cache.put(wrap, mh);
+-            return mh;
+-        }
+-        // look up the method
+-        String name = "reboxRaw" + wrap.wrapperSimpleName();
+-        MethodType type = reboxType(wrap);
+-        try {
+-            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
+-            mh = mh.asType(IDENTITY.type());
+-        } catch (ReflectiveOperationException ex) {
+-            mh = null;
+-        }
+-        if (mh != null) {
+-            cache.put(wrap, mh);
+-            return mh;
+-        }
+-        throw new IllegalArgumentException("cannot find rebox adapter for " + wrap);
+-    }
+-
+-    public static MethodHandle rebox(Class<?> type) {
+-        return rebox(Wrapper.forPrimitiveType(type));
++        return box(type, exact);
+     }
+ 
+     /// Constant functions
+@@ -575,12 +378,9 @@
+             return mh;
+         }
+ 
+-        // use the raw method
+-        Wrapper rawWrap = wrap.rawPrimitive();
+-        if (mh == null && rawWrap != wrap) {
+-            mh = MethodHandles.explicitCastArguments(zeroConstantFunction(rawWrap), type);
+-        }
+-        if (mh != null) {
++        // use zeroInt and cast the result
++        if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
++            mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
+             cache.put(wrap, mh);
+             return mh;
+         }
+@@ -732,7 +532,6 @@
+         if (exact) {
+             MethodType xmt = MethodType.methodType(type, Object.class);
+             mh = MethodHandles.explicitCastArguments(mh, xmt);
+-            //mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
+         }
+         if (cache != null)
+             cache.put(wrap, mh);
+diff --git a/src/share/classes/sun/invoke/util/VerifyType.java b/src/share/classes/sun/invoke/util/VerifyType.java
+--- a/src/share/classes/sun/invoke/util/VerifyType.java
++++ b/src/share/classes/sun/invoke/util/VerifyType.java
+@@ -122,8 +122,6 @@
+         return isNullConversion(recv.returnType(), call.returnType());
+     }
+ 
+-    //TO DO: isRawConversion
+-
+     /**
+      * Determine if the JVM verifier allows a value of type call to be
+      * passed to a formal parameter (or return variable) of type recv.
+@@ -188,40 +186,6 @@
+         return -1;
+     }
+ 
+-    public static int canPassRaw(Class<?> src, Class<?> dst) {
+-        if (dst.isPrimitive()) {
+-            if (dst == void.class)
+-                // As above, return anything to a caller expecting void.
+-                return 1;
+-            if (src == void.class)
+-                // Special permission for raw conversions: allow a void
+-                // to be captured as a garbage int.
+-                // Caller promises that the actual value will be disregarded.
+-                return dst == int.class ? 1 : 0;
+-            if (isNullType(src))
+-                // Special permission for raw conversions: allow a null
+-                // to be reinterpreted as anything.  For objects, it is safe,
+-                // and for primitives you get a garbage value (probably zero).
+-                return 1;
+-            if (!src.isPrimitive())
+-                return 0;
+-            Wrapper sw = Wrapper.forPrimitiveType(src);
+-            Wrapper dw = Wrapper.forPrimitiveType(dst);
+-            if (sw.stackSlots() == dw.stackSlots())
+-                return 1;  // can do a reinterpret-cast on a stacked primitive
+-            if (sw.isSubwordOrInt() && dw == Wrapper.VOID)
+-                return 1;  // can drop an outgoing int value
+-            return 0;
+-        } else if (src.isPrimitive()) {
+-            return 0;
+-        }
+-
+-        // Both references.
+-        if (isNullReferenceConversion(src, dst))
+-            return 1;
+-        return -1;
+-    }
+-
+     public static boolean isSpreadArgType(Class<?> spreadArg) {
+         return spreadArg.isArray();
+     }
+diff --git a/src/share/classes/sun/invoke/util/Wrapper.java b/src/share/classes/sun/invoke/util/Wrapper.java
+--- a/src/share/classes/sun/invoke/util/Wrapper.java
++++ b/src/share/classes/sun/invoke/util/Wrapper.java
+@@ -562,67 +562,6 @@
+         throw new InternalError("bad wrapper");
+     }
+ 
+-    /** Wrap a value (a long or smaller value) in this wrapper's type.
+-     * Does not perform floating point conversion.
+-     * Produces a {@code Long} for {@code OBJECT}, although the exact type
+-     * of the operand is not known.
+-     * Returns null for {@code VOID}.
+-     */
+-    public Object wrapRaw(long x) {
+-        switch (basicTypeChar) {
+-            case 'F':  return Float.valueOf(Float.intBitsToFloat((int)x));
+-            case 'D':  return Double.valueOf(Double.longBitsToDouble(x));
+-            case 'L':  // same as 'J':
+-            case 'J':  return (Long) x;
+-        }
+-        // Other wrapping operations are just the same, given that the
+-        // operand is already promoted to an int.
+-        return wrap((int)x);
+-    }
+-
+-    /** Produce bitwise value which encodes the given wrapped value.
+-     * Does not perform floating point conversion.
+-     * Returns zero for {@code VOID}.
+-     */
+-    public long unwrapRaw(Object x) {
+-        switch (basicTypeChar) {
+-            case 'F':  return Float.floatToRawIntBits((Float) x);
+-            case 'D':  return Double.doubleToRawLongBits((Double) x);
+-
+-            case 'L': throw newIllegalArgumentException("cannot unwrap from sobject type");
+-            case 'V': return 0;
+-            case 'I': return (int)(Integer) x;
+-            case 'J': return (long)(Long) x;
+-            case 'S': return (short)(Short) x;
+-            case 'B': return (byte)(Byte) x;
+-            case 'C': return (char)(Character) x;
+-            case 'Z': return (boolean)(Boolean) x ? 1 : 0;
+-        }
+-        throw new InternalError("bad wrapper");
+-    }
+-
+-    /** Report what primitive type holds this guy's raw value. */
+-    public Class<?> rawPrimitiveType() {
+-        return rawPrimitive().primitiveType();
+-    }
+-
+-    /** Report, as a wrapper, what primitive type holds this guy's raw value.
+-     *  Returns self for INT, LONG, OBJECT; returns LONG for DOUBLE,
+-     *  else returns INT.
+-     */
+-    public Wrapper rawPrimitive() {
+-        switch (basicTypeChar) {
+-            case 'S': case 'B':
+-            case 'C': case 'Z':
+-            case 'V':
+-            case 'F':
+-                return INT;
+-            case 'D':
+-                return LONG;
+-        }
+-        return this;
+-    }
+-
+     private static Number numberValue(Object x) {
+         if (x instanceof Number)     return (Number)x;
+         if (x instanceof Character)  return (int)(Character)x;
+diff --git a/test/sun/invoke/util/ValueConversionsTest.java b/test/sun/invoke/util/ValueConversionsTest.java
+--- a/test/sun/invoke/util/ValueConversionsTest.java
++++ b/test/sun/invoke/util/ValueConversionsTest.java
+@@ -122,36 +122,6 @@
+     }
+ 
+     @Test
+-    public void testUnboxRaw() throws Throwable {
+-        //System.out.println("unboxRaw");
+-        for (Wrapper w : Wrapper.values()) {
+-            if (w == Wrapper.OBJECT)  continue;  // skip this; no raw form
+-            //System.out.println(w);
+-            for (int n = -5; n < 10; n++) {
+-                Object box = w.wrap(n);
+-                long expResult = w.unwrapRaw(box);
+-                Object box2 = w.wrapRaw(expResult);
+-                assertEquals(box, box2);
+-                MethodHandle unboxer = ValueConversions.unboxRaw(w.primitiveType());
+-                long result = -1;
+-                switch (w) {
+-                    case INT:     result = (int)  unboxer.invokeExact(box); break;
+-                    case LONG:    result = (long) unboxer.invokeExact(box); break;
+-                    case FLOAT:   result = (int)  unboxer.invokeExact(box); break;
+-                    case DOUBLE:  result = (long) unboxer.invokeExact(box); break;
+-                    case CHAR:    result = (int)  unboxer.invokeExact(box); break;
+-                    case BYTE:    result = (int)  unboxer.invokeExact(box); break;
+-                    case SHORT:   result = (int)  unboxer.invokeExact(box); break;
+-                    case BOOLEAN: result = (int)  unboxer.invokeExact(box); break;
+-                    case VOID:    result = (int)  unboxer.invokeExact(box); break;
+-                }
+-                assertEquals("(w,n,box)="+Arrays.asList(w,n,box),
+-                             expResult, result);
+-            }
+-        }
+-    }
+-
+-    @Test
+     public void testBox() throws Throwable {
+         //System.out.println("box");
+         for (Wrapper w : Wrapper.values()) {
+@@ -180,65 +150,6 @@
+     }
+ 
+     @Test
+-    public void testBoxRaw() throws Throwable {
+-        //System.out.println("boxRaw");
+-        for (Wrapper w : Wrapper.values()) {
+-            if (w == Wrapper.VOID)  continue;  // skip this; no unboxed form
+-            if (w == Wrapper.OBJECT)  continue;  // skip this; no raw form
+-            //System.out.println(w);
+-            for (int n = -5; n < 10; n++) {
+-                Object box = w.wrap(n);
+-                long   raw = w.unwrapRaw(box);
+-                Object expResult = box;
+-                MethodHandle boxer = ValueConversions.boxRaw(w.primitiveType());
+-                Object result = null;
+-                switch (w) {
+-                case INT:     result = boxer.invokeExact((int)raw); break;
+-                case LONG:    result = boxer.invokeExact(raw); break;
+-                case FLOAT:   result = boxer.invokeExact((int)raw); break;
+-                case DOUBLE:  result = boxer.invokeExact(raw); break;
+-                case CHAR:    result = boxer.invokeExact((int)raw); break;
+-                case BYTE:    result = boxer.invokeExact((int)raw); break;
+-                case SHORT:   result = boxer.invokeExact((int)raw); break;
+-                case BOOLEAN: result = boxer.invokeExact((int)raw); break;
+-                }
+-                assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
+-                             expResult, result);
+-            }
+-        }
+-    }
+-
+-    @Test
+-    public void testReboxRaw() throws Throwable {
+-        //System.out.println("reboxRaw");
+-        for (Wrapper w : Wrapper.values()) {
+-            Wrapper pw = Wrapper.forPrimitiveType(w.rawPrimitiveType());
+-            if (w == Wrapper.VOID)  continue;  // skip this; no unboxed form
+-            if (w == Wrapper.OBJECT)  continue;  // skip this; no raw form
+-            //System.out.println(w);
+-            for (int n = -5; n < 10; n++) {
+-                Object box = w.wrap(n);
+-                Object raw = pw.wrap(w.unwrapRaw(box));
+-                Object expResult = box;
+-                MethodHandle boxer = ValueConversions.rebox(w.primitiveType());
+-                Object result = null;
+-                switch (w) {
+-                case INT:     result = boxer.invokeExact(raw); break;
+-                case LONG:    result = boxer.invokeExact(raw); break;
+-                case FLOAT:   result = boxer.invokeExact(raw); break;
+-                case DOUBLE:  result = boxer.invokeExact(raw); break;
+-                case CHAR:    result = boxer.invokeExact(raw); break;
+-                case BYTE:    result = boxer.invokeExact(raw); break;
+-                case SHORT:   result = boxer.invokeExact(raw); break;
+-                case BOOLEAN: result = boxer.invokeExact(raw); break;
+-                }
+-                assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
+-                             expResult, result);
+-            }
+-        }
+-    }
+-
+-    @Test
+     public void testCast() throws Throwable {
+         //System.out.println("cast");
+         Class<?>[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class };
--- a/series	Fri Jul 20 01:46:55 2012 -0700
+++ b/series	Sat Jul 21 14:10:20 2012 -0700
@@ -7,6 +7,7 @@
 meth-lazy-7023639.patch         #-/meth #+78f1f4e4e9c7
 meth-lazy-7023639.init.patch    #-/meth #+78f1f4e4e9c7
 meth-lazy-7023639.bmh.patch     #-/meth #+78f1f4e4e9c7
+meth-lazy-7023639.rmcode.patch  #-/meth #+78f1f4e4e9c7
 
 # non-pushed files are under review or development, or merely experimental:
 meth-7177472.patch              #-/meth #+78f1f4e4e9c7