changeset 6008:5e95936891d2

Update DefaultMethodAdd/RemoveTests, add shapes, and simplify (Sue Wei w/ RF). combo-test output now to build dir. Metafactory: make bridge et. al. detection and logging available to all MFs. Comment out outdated serialization code. MHI output like javap. More doc.
author Robert Field <Robert.Field@oracle.com>
date Thu, 13 Sep 2012 19:27:22 -0700
parents cd4e5bc1ccb1
children 1ebaa3f08ed1
files combo-tests/build.xml combo-tests/tests/tools/javac/lambda/DefaultMethodAddTest.java combo-tests/tests/tools/javac/lambda/DefaultMethodRemoveTest.java src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java src/share/classes/java/lang/invoke/LambdaMetafactory.java src/share/classes/java/lang/invoke/MethodHandleInfo.java src/share/classes/java/lang/invoke/MethodHandleProxyLambdaMetafactory.java src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
diffstat 9 files changed, 232 insertions(+), 155 deletions(-) [+]
line wrap: on
line diff
--- a/combo-tests/build.xml	Thu Sep 13 19:20:08 2012 -0400
+++ b/combo-tests/build.xml	Thu Sep 13 19:27:22 2012 -0700
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project name="jdk" default="test">
 
-    <property name="build.dir" value="build" />
-    <property name="gen.dir" value="gen" />
+    <property name="build.dir" value="../../build/combo-tests" />
+    <property name="gen.dir" value="${build.dir}/gen" />
     <property name="test.classes.dir" value="${build.dir}/test-classes"/>
     <property name="test.reports.dir" value="${build.dir}/test-reports"/>
     <property name="test.src.dir" value="tests"/>
--- a/combo-tests/tests/tools/javac/lambda/DefaultMethodAddTest.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/combo-tests/tests/tools/javac/lambda/DefaultMethodAddTest.java	Thu Sep 13 19:27:22 2012 -0700
@@ -33,19 +33,16 @@
     @DimensionVar("ADD") AddType addType;
         
     @SourceFile(value="B.java", group="A")
-    String interfaceBModified = "interface B #{SHAPE.EXTEND} { #{ADD} }";
+    String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{ADD} }";
     
     @SourceFile(value="B.java", group="B")
-    String interfaceB = "interface B #{SHAPE.EXTEND} {}";
+    String interfaceB =         "interface B #{SHAPE.B_DECL} {}";
     
     @SourceFile(value="A.java", group="B")
-    String interfaceA = "interface A { String m() default { return \"A\"; } }";
-    
-    @SourceFile(value="AB.java", group="B")
-    String interfaceAB = "#{SHAPE.COMMENT}interface AB extends A, B {}";
+    String interfaceA =         "interface A { String m() default { return \"A\"; } }";
     
     @SourceFile(value="C.java", group="B")
-    String classC = "class C implements #{SHAPE.IMPLEMENT} {}";
+    String classC = "#{SHAPE.C}";
     
     @SourceFile(value="Main.java", group="B")
     String classMain = "public class Main {\n" +
@@ -67,42 +64,59 @@
         } catch (InvocationTargetException ex) {
             output = ex.getCause().getMessage();          
         }        
-        if(shapeType == CShapes.C_B_A){
+        if(shapeType == CShapes.C_B_A) {
             if(addType == AddType.ADD)
                 assertEquals(result, "B");
             else //redeclare
-                assertEquals(result, "A");
-        } else {
-            if(addType == AddType.ADD)
-                assertTrue(output.matches("Conflicting default methods: .+[.]m .+[.]m"));                    
-            else //redeclare
-                assertEquals(result, "A");        
+                assertEquals(output, "Method B.m()Ljava/lang/String; is abstract");
         }
+        else if(shapeType == CShapes.C_I_AB2)
+        	assertEquals(result, "A");
+        else if(shapeType == CShapes.C_CI)
+        	assertEquals(result, "D");
+        else if(shapeType == CShapes.C_I_AB3)
+        	assertEquals(result, "AB");
+        else            
+            assertTrue(output.matches("Conflicting default methods: .+[.]m .+[.]m"));        
     }
     
     enum CShapes implements Template { //shapes of class hirarchy
         //class C implements interface A, B
-        C_AB("", "A, B", "//"), 
+        C_AB("", 
+	       "class C implements A, B {}"), 
         //class C implments interface B, B extends interface A
-        C_B_A("extends A", "B", "//"),         
+        C_B_A("extends A", 
+	       "class C implements B {}"),         
+
         //class C implments interface AB, AB extends interface A, B
-        C_I_AB("", "AB", "");        
+        C_I_AB("", 
+	       "interface AB extends A, B {  }\n" + 
+	       "class C implements AB {}"),
+        //class C implments interface AB, AB extends interface A, B and explicitly inherits the default method in A
+        C_I_AB2("", 
+		"interface AB extends A, B { String m() default { return A.super.m(); } }\n" + 
+		"class C implements AB {}"),
+        //class C implments interface AB, AB extends interface A, B and overrides the default method inherited
+        C_I_AB3("", 
+		"interface AB extends A, B { String m() default { return \"AB\"; } }\n" + 
+		"class C implements AB {}"),
+        //class C extends Class D implements Interface B
+        C_CI("", 
+	        "class D { public String m() { return \"D\"; } }\n" + 
+	        "class C extends D implements B {}");
         
-        private final String extend;
-        private final String implement;
-        private final String commentSign;
+        private final String sB_DECL;
+        private final String sC;
         
-        CShapes(String extend, String implement, String commentSign) {
-            this.extend = extend;
-            this.implement = implement;
-            this.commentSign = commentSign;            
+        CShapes(String sB_DECL, String sC) {
+            this.sB_DECL = sB_DECL;
+            this.sC = sC;
         }
         
         public String expand(String selector) {
             switch(selector) {
-                case "EXTEND": return extend;
-                case "IMPLEMENT": return implement;
-                case "COMMENT": return commentSign;
+                case "B_DECL": return sB_DECL;
+                case "C": return sC;
                 default: return toString();
             }            
         }        
--- a/combo-tests/tests/tools/javac/lambda/DefaultMethodRemoveTest.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/combo-tests/tests/tools/javac/lambda/DefaultMethodRemoveTest.java	Thu Sep 13 19:27:22 2012 -0700
@@ -32,19 +32,16 @@
     @DimensionVar("REMOVE") RemoveType removeType;
     
     @SourceFile(value="B.java", group="A")
-    String interfaceBModified = "interface B #{SHAPE.EXTENDS} { #{REMOVE} }";
+    String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{REMOVE} }";
       
     @SourceFile(value="A.java", group="B")
     String interfaceA = "interface A { String m() default { return \"A\"; } }";
     
     @SourceFile(value="B.java", group="B")
-    String interfaceB = "interface B #{SHAPE.EXTENDS} { String m() default { return \"B\"; } }";
-    
-    @SourceFile(value="D.java", group="B")
-    String interfaceD = "#{SHAPE.COMMENT}interface D { String m() default { return \"D\"; } }";
-    
+    String interfaceB = "interface B #{SHAPE.B_DECL} { String m() default { return \"B\"; } }";
+        
     @SourceFile(value="C.java", group="B")
-    String classC = "class C implements B {}";
+    String classC = "#{SHAPE.C}";
     
     @SourceFile(value="Main.java", group="B")
     String classMain = "public class Main {\n" +
@@ -72,40 +69,56 @@
         } catch (InvocationTargetException ex) {
             output = ex.getCause().getMessage();
         }
-        if(shapeType == CShapes.C_B_A)
-            assertEquals(result, "A");
-        else if(shapeType == CShapes.C_B)
-            assertEquals(output, "C.m()Ljava/lang/String;");
-        else if (shapeType == CShapes.C_B_AD)                        
-            assertTrue(output.matches("Conflicting default methods: .+[.]m .+[.]m"));
+        if(shapeType == CShapes.C_B_A) {
+            if(removeType == RemoveType.REMOVE)
+                assertEquals(result, "A");
+            else
+                assertEquals(output, "Method B.m()Ljava/lang/String; is abstract");
+        }
+        else if(shapeType == CShapes.C_CI)
+            assertEquals(result, "D");
+        else {
+            if(shapeType == CShapes.C_B_AD && removeType == RemoveType.REDECLARE)
+                assertEquals(output, "Method B.m()Ljava/lang/String; is abstract");
+            else
+                assertEquals(output, "C.m()Ljava/lang/String;");
+        }
     }
     
     enum CShapes implements Template { //shapes of class hirarchy
         //class C implements interface B
-        C_B("", "//"), 
+        C_B("", 
+            "class C implements B {}"), 
         //class C implments interface B, B extends interface A
-        C_B_A("extends A", "//"),
+        C_B_A("extends A", 
+              "class C implements B {}"),
         //class C implments interface B, B extends interface A, D
-        C_B_AD("extends A, D", ""); 
+        C_B_AD("extends A, D", 
+               "interface D { String m() default { return \"D\"; } }\n" + 
+               "class C implements B {}"),
+        //class C extends Class D implements Interface B
+        C_CI("", 
+             "class D { public String m() { return \"D\"; } }\n" + 
+              "class C extends D implements B {}");
         
-        private final String extend;
-        private final String commentSign;
+        private final String sB_DECL;
+        private final String sC;
         
-        CShapes(String extend, String commentSign) {
-            this.extend = extend;
-            this.commentSign = commentSign;
+        CShapes(String sB_DECL, String sC) {
+            this.sB_DECL = sB_DECL;
+            this.sC = sC;            
         }
         
         public String expand(String selector) {
             switch(selector) {
-                case "EXTENDS": return extend;
-                case "COMMENT": return commentSign;                
+                case "B_DECL": return sB_DECL;
+                case "C": return sC;                
                 default: return toString();
             }
         }        
     }
     
-    enum RemoveType implements Template { // remove by removing default method code or redeclaring the interface method
+    enum RemoveType implements Template { //remove by removing default method code or redeclaring the interface method
         REMOVE(""),
         REDECLARE("String m();");
         
--- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Thu Sep 13 19:27:22 2012 -0700
@@ -25,11 +25,17 @@
 package java.lang.invoke;
 
 import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 /**
  * Abstract implementation of a meta-factory which provides parameter unrolling and input validation.
@@ -63,6 +69,9 @@
     final MethodType implMethodType;          // Type of the implementation method "(int)String"
     final MethodType instantiatedMethodType;  // Instantiated erased functional interface method type "(Integer)Object"
 
+    static final Executor logPool = Executors.newSingleThreadExecutor(); // @@@ For debugging only
+
+
     /**
      * Meta-factory constructor.
      *
@@ -304,4 +313,101 @@
                || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
     }
 
+    // @@@ Logging support -- for debugging only -- delete before shipping
+    protected static void log(final String s) {
+        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(s);
+            }
+        });
+    }
+
+    protected static void log(final String s, final Throwable e) {
+        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(s);
+                e.printStackTrace(System.out);
+            }
+        });
+    }
+
+    /**
+     * Find the SAM method and corresponding methods which should be bridged. SAM method and those to be bridged
+     * will have the same name and number of parameters. Check for matching default methods (non-abstract), they
+     * should not be bridged-over and indicate a complex bridging situation.
+     */
+    class MethodAnalyzer {
+        private final Method[] methods = samBase.getMethods();
+        private final List<Method> methodsFound = new ArrayList<>(methods.length);
+
+        private Method samMethod = null;
+        private final List<Method> methodsToBridge = new ArrayList<>(methods.length);
+        private boolean defaultMethodFound = false;
+
+        MethodAnalyzer() {
+            String samMethodName = samInfo.getName();
+            Class<?>[] samParamTypes = samMethodType.parameterArray();
+            int samParamLength = samParamTypes.length;
+            Class<?> samReturnType = samMethodType.returnType();
+            Class<?> objectClass = Object.class;
+
+            for (Method m : methods) {
+                if (m.getName().equals(samMethodName) && m.getDeclaringClass() != objectClass) {
+                    Class<?>[] mParamTypes = m.getParameterTypes();
+                    if (mParamTypes.length == samParamLength) {
+                        if (Modifier.isAbstract(m.getModifiers())) {
+                            // Exclude methods with duplicate signatures
+                            if (methodUnique(m)) {
+                                if (m.getReturnType().equals(samReturnType) && Arrays.equals(mParamTypes, samParamTypes)) {
+                                    // Exact match, this is the SAM method signature
+                                    samMethod = m;
+                                } else {
+                                    methodsToBridge.add(m);
+                                }
+                            }
+                        } else {
+                            // This is a default method, flag for special processing
+                            defaultMethodFound = true;
+                            // Ignore future matching abstracts.
+                            // Note, due to reabstraction, this is really a punt, hence pass-off to VM
+                            methodUnique(m);
+                        }
+                    }
+                }
+            }
+        }
+
+        Method getSamMethod() {
+            return samMethod;
+        }
+
+        List<Method> getMethodsToBridge() {
+            return methodsToBridge;
+        }
+
+        boolean wasDefaultMethodFound() {
+            return defaultMethodFound;
+        }
+
+        /**
+         * Search the list of previously found methods to determine if there is a method with the same signature
+         * (return and parameter types) as the specified method. If it wasn't found before, add to the found list.
+         *
+         * @param m The method to match
+         * @return False if the method was found, True otherwise
+         */
+        private boolean methodUnique(Method m) {
+            Class<?>[] ptypes = m.getParameterTypes();
+            Class<?> rtype = m.getReturnType();
+            for (Method md : methodsFound) {
+                if (md.getReturnType().equals(rtype) && Arrays.equals(ptypes, md.getParameterTypes())) {
+                    return false;
+                }
+            }
+            methodsFound.add(m);
+            return true;
+        }
+    }
 }
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Sep 13 19:27:22 2012 -0700
@@ -147,7 +147,6 @@
     private <T> Class<? extends T> spinInnerClass() {
         String samMethodName = samInfo.getName();
 
-        Method[] methods = samBase.getMethods();
         String samName = samBase.getName().replace('.', '/');
         Type samType = Type.getType(samBase);
 
@@ -162,65 +161,28 @@
         
         generateConstructor();
 
-        // Generate methods
-        Class<?>[] samParamTypes = samMethodType.parameterArray();
-        int samParamLength = samParamTypes.length;
-        Class<?> samReturnType = samMethodType.returnType();
-        boolean defaultMethodFound = false;
-        Method samMethod = null;
-        List<Method> methodsFound = new ArrayList<>(methods.length);
-        List<Method> methodsToBridge = new ArrayList<>(methods.length);
-        Class<?> objectClass = Object.class;
-
-        // Find the SAM method and corresponding methods which should be bridged.
-        // SAM method and those to be bridged will have the same name and number of parameters.
-        // Check for default methods (non-abstract), they should not be bridged-over and indicate a complex bridging situation.
-        for (Method m : methods) {
-            if (m.getName().equals(samMethodName) && m.getDeclaringClass() != objectClass) {
-                Class<?>[] mParamTypes = m.getParameterTypes();
-                if (mParamTypes.length == samParamLength) {
-                    if (Modifier.isAbstract(m.getModifiers())) {
-                        // Exclude methods with duplicate signatures
-                        if (!matchesAnyMethod(m, methodsFound)) {
-                            methodsFound.add(m);
-                            if (m.getReturnType().equals(samReturnType) && Arrays.equals(mParamTypes, samParamTypes)) {
-                                // Exact match, this is the SAM method signature
-                                samMethod = m;
-                            } else {
-                                methodsToBridge.add(m);
-                            }
-                        }
-                    } else {
-                        // This is a default method, flag for special processing
-                        defaultMethodFound = true;
-                        // Ignore future matching abstracts.
-                        // Note, due to reabstraction, this is really a punt, hence pass-off to VM
-                        if (!matchesAnyMethod(m, methodsFound)) {
-                            methodsFound.add(m);
-                        }
-                    }
-                }
-            }
-        }
+        MethodAnalyzer ma = new MethodAnalyzer();
 
         // Forward the SAM method
-        if (samMethod == null) {
+        if (ma.getSamMethod() == null) {
             throw new LambdaConversionException(String.format("SAM method not found: %s", samMethodType));
         } else {
-            generateForwardingMethod(samMethod, false);
+            generateForwardingMethod(ma.getSamMethod(), false);
         }
 
         // Forward the bridges
         // @@@ Once the VM can do fail-over, uncomment the default method test
-        if (!methodsToBridge.isEmpty() /* && !defaultMethodFound*/) {
-            for (Method m : methodsToBridge) {
+        if (!ma.getMethodsToBridge().isEmpty() /* && !ma.wasDefaultMethodFound() */) {
+            for (Method m : ma.getMethodsToBridge()) {
                 generateForwardingMethod(m, true);
             }
         }
 
+        /***** Serialization not yet supported
         if (isSerializable) {
             generateSerializationMethod(samType, samMethodName);
         }
+        ******/
 
         cw.visitEnd();
 
@@ -243,23 +205,6 @@
     }
 
     /**
-     * Search the specified list of methods to determine if there is a method with the same signature (return and parameter types) as the specified method.
-     * @param m The method to match
-     * @param methods The list of methods to search
-     * @return True if a method was found in 'methods' which the same signature as 'm', False otherwise
-     */
-    private static boolean matchesAnyMethod(Method m, List<Method> methods) {
-        Class<?>[] ptypes = m.getParameterTypes();
-        Class<?> rtype = m.getReturnType();
-        for (Method md : methods) {
-            if (md.getReturnType().equals(rtype) && Arrays.equals(ptypes, md.getParameterTypes())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
      * Generate the constructor for the class
      */
     private void generateConstructor() {
@@ -283,6 +228,7 @@
     /**
      * Generate the serialization method (if needed)
      */
+    /****** This code is out of date -- known to be wrong -- and not currently used ******
     private void generateSerializationMethod(Type samType, String samMethodName) {
         String samMethodDesc = samMethodType.toMethodDescriptorString();
         TypeConvertingMethodAdapter mv = new TypeConvertingMethodAdapter(cw.visitMethod(ACC_PRIVATE + ACC_FINAL, NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE, null, null));
@@ -313,6 +259,7 @@
         mv.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
         mv.visitEnd();
     }
+    ********/
 
     /**
      * Generate a method which calls the lambda implementation method,
--- a/src/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/src/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Sep 13 19:27:22 2012 -0700
@@ -69,8 +69,9 @@
  * as well as a method signature describing the number and static types (but not the values) of the dynamic
  * arguments, and the static return type of the invokedynamic site.
  *
- * <p>The implementation method can, in theory, be anything representable with a method handle. Currently supported
- * are method handles representing invocation of virtual, interface, constructor and static methods.
+ * <p>The implementation method is described with a method handle. In theory, any method handle could be used.
+ * Currently supported are method handles representing invocation of virtual, interface, constructor and static
+ * methods.
  *
  * <p>Assume:
  * <ul>
@@ -86,7 +87,8 @@
  * <ul>
  *     <li>Rd is a subtype of F</li>
  *     <li>For i=1..N, Ti is a subtype of Ui</li>
- *     <li>Rt is a subtype of Ru</li>
+ *     <li>Either Rt and Ru are primitive and are the same type, or both are reference types and
+ *         Rt is a subtype of Ru</li>
  *     <li>If the implementation method is a static method:
  *     <ul>
  *         <li>K + N = M</li>
@@ -106,8 +108,8 @@
  * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
  * the completely known instantiated return type is adapted to the implementation arguments. Because the
  * instantiated type of the implementation method is not available, the adaptability of return types cannot be
- * checked as precisely at link-time as arguments. Thus a loose version of link-time checking is done on return
- * type, while a strict version is applied to arguments.
+ * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
+ * done on return type, while a strict version is applied to arguments.
  *
  * <p>A type Q is considered adaptable to S as follows:
  * <table>
--- a/src/share/classes/java/lang/invoke/MethodHandleInfo.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/src/share/classes/java/lang/invoke/MethodHandleInfo.java	Thu Sep 13 19:27:22 2012 -0700
@@ -79,21 +79,21 @@
     private String getReferenceKindString() {
         switch (referenceKind) {
             case REF_NONE: return "REF_NONE";
-            case REF_getField: return "getField";
-            case REF_getStatic: return "getStatic";
-            case REF_putField: return "putField";
-            case REF_putStatic: return "putStatic";
-            case REF_invokeVirtual: return "invokeVirtual";
-            case REF_invokeStatic: return "invokeStatic";
-            case REF_invokeSpecial: return "invokeSpecial";
-            case REF_newInvokeSpecial: return "newInvokeSpecial";
-            case REF_invokeInterface: return "invokeInterface";
+            case REF_getField: return "getfield";
+            case REF_getStatic: return "getstatic";
+            case REF_putField: return "putfield";
+            case REF_putStatic: return "putstatic";
+            case REF_invokeVirtual: return "invokevirtual";
+            case REF_invokeStatic: return "invokestatic";
+            case REF_invokeSpecial: return "invokespecial";
+            case REF_newInvokeSpecial: return "newinvokespecial";
+            case REF_invokeInterface: return "invokeinterface";
             default: return "UNKNOWN_REFENCE_KIND";
         }
     }
 
     @Override
     public String toString() {
-        return String.format("MethodHandleInfo[%s %s.%s%s]", getReferenceKindString(), declaringClass.getName(), name, methodType);
+        return String.format("%s %s.%s:%s", getReferenceKindString(), declaringClass.getName(), name, methodType);
     }
 }
--- a/src/share/classes/java/lang/invoke/MethodHandleProxyLambdaMetafactory.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/src/share/classes/java/lang/invoke/MethodHandleProxyLambdaMetafactory.java	Thu Sep 13 19:27:22 2012 -0700
@@ -25,8 +25,6 @@
 package java.lang.invoke;
 
 import java.lang.reflect.InvocationTargetException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
 
 /**
  * MethodHandleProxyLambdaMetafactory
@@ -37,27 +35,6 @@
 
     private final MethodHandle implMethod;
 
-    // @@@ For debugging only -- delete before shipping
-    static Executor logPool = Executors.newSingleThreadExecutor();
-    private static void log(final String s) {
-        logPool.execute(new Runnable() {
-            @Override
-            public void run() {
-                System.out.println(s);
-            }
-        });
-    }
-    private static void log(final String s, final Throwable e) {
-        logPool.execute(new Runnable() {
-            @Override
-            public void run() {
-                System.out.println(s);
-                e.printStackTrace(System.out);
-            }
-        });
-    }
-    // -- dev-only --
-
     /**
      * Meta-factory constructor.
      *
--- a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java	Thu Sep 13 19:20:08 2012 -0400
+++ b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java	Thu Sep 13 19:27:22 2012 -0700
@@ -180,8 +180,13 @@
                 boxingDescriptor(sort));
     }
 
-    void unbox(Type sType, Type tType) {
-        int sSort = sType.getSort();
+    /**
+     * Convert types by unboxing. The source type is known to be a primitive wrapper.
+     * @param spType A primitive type corresponding to wrapped reference source type
+     * @param tType A primitive type being converted to
+     */
+    void unbox(Type spType, Type tType) {
+        int sSort = spType.getSort();
         int tSort = tType.getSort();
         visitMethodInsn(INVOKEVIRTUAL,
                 NAME_PRIMITIVE_WRAPPER[sSort],
@@ -189,6 +194,12 @@
                 unboxingDescriptor(tSort));
     }
 
+    /**
+     * Convert types by unboxing.  Use the base wrapper (for example, Number for int, short, etc) to go directly
+     * to the desired type.
+     * @param sType A reference type being converted from
+     * @param tType A primitive type being converted to
+     */
     void looseUnbox(Type sType, Type tType) {
         int tSort = tType.getSort();
         String baseWrapper = NAME_PRIMITIVE_BASE_WRAPPER[tSort];
@@ -230,6 +241,13 @@
         return NAME_PRIMITIVE_WRAPPER[type.getSort()];
     }
 
+    /**
+     * Convert an argument of type 'argType' to be passed to 'targetType' assuring that it is 'functionalType'.
+     * Insert the needed conversion instructions in the method code.
+     * @param argType
+     * @param targetType
+     * @param functionalType
+     */
     void convertType(Type argType, Type targetType, Type functionalType) {
         if (argType.equals(targetType) || argType.equals(VOID_TYPE)) {
             return;