changeset 14:1f748158f7ed

updated demo code
author jrose
date Thu, 04 Jun 2009 20:51:51 -0700
parents 083732b6300a
children 800a2c2ff01d
files netbeans/indy-demo/build.xml netbeans/indy-demo/nbproject/project.properties netbeans/indy-demo/src/Main.java netbeans/indy-demo/src/recipes/Curry.java netbeans/indy-demo/src/recipes/FastAndSlow.java netbeans/indy-demo/src/recipes/PlainOldJava.java netbeans/indy-demo/src/recipes/Utensil.java netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java netbeans/meth/test/sun/dyn/util/ValueConversionsTest.java
diffstat 9 files changed, 619 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/netbeans/indy-demo/build.xml	Thu May 28 02:51:05 2009 -0700
+++ b/netbeans/indy-demo/build.xml	Thu Jun 04 20:51:51 2009 -0700
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project name="InvokeDynamicDemo" default="default" basedir=".">
-    <description>Builds, tests, and runs the project InvokeDynamicDemo.</description>
+<project name="indy-demo" default="default" basedir=".">
+    <description>Builds, tests, and runs the project indy-demo.</description>
     <import file="nbproject/build-impl.xml"/>
     <target name="-post-jar">
         <delete file="dist/README.TXT"/>
--- a/netbeans/indy-demo/nbproject/project.properties	Thu May 28 02:51:05 2009 -0700
+++ b/netbeans/indy-demo/nbproject/project.properties	Thu Jun 04 20:51:51 2009 -0700
@@ -49,7 +49,8 @@
 manifest.file=manifest.mf
 meta.inf.dir=${src.dir}/META-INF
 platform.active=JDK_7X
-file.reference.projects=${user.home}/Projects
+#file.reference.projects=${user.home}/Projects
+file.reference.projects=${project.davinci}/patches/netbeans
 project.meth=${file.reference.projects}/meth
 reference.meth.jar=${project.meth}/dist/meth.jar
 run.classpath=\
--- a/netbeans/indy-demo/src/Main.java	Thu May 28 02:51:05 2009 -0700
+++ b/netbeans/indy-demo/src/Main.java	Thu Jun 04 20:51:51 2009 -0700
@@ -37,7 +37,10 @@
     static final Class[] CLASSES = {
         Hello.class,
         GetNameDemo.class,
-        FidgetDemo.class
+        FidgetDemo.class,
+        recipes.PlainOldJava.class,
+        recipes.FastAndSlow.class,
+        recipes.Curry.class
     };
     public static void main(String[] args) {
         for (Class c : CLASSES) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netbeans/indy-demo/src/recipes/Curry.java	Thu Jun 04 20:51:51 2009 -0700
@@ -0,0 +1,118 @@
+/*
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package recipes;
+
+import java.dyn.*;
+import static java.dyn.MethodHandles.*;
+import static java.dyn.MethodType.*;
+import static recipes.Utensil.*;
+
+public class Curry {
+    public static void main(String... av) {
+        // ----
+
+        MethodHandle list2 = Utensil.list(2);
+        println(list2);  // list2 = {(x,y) => Arrays.asList(x,y)}
+        println(invoke(list2, "chicken", "rice"));  // [chicken, rice]
+
+        // curry with chicken or rice:
+        MethodHandle partialApp = insertArguments(list2, 0, "curry");
+        println(partialApp); // partialApp = {x => list2("curry", x)}
+        println(invoke(partialApp, "chicken"));  // [curry, chicken]
+        println(invoke(partialApp, "rice"));     // [curry, rice]
+
+        // ----
+
+        // curry with everything:
+        MethodHandle list3 = Utensil.list(3);
+        println(list3);  // list3 = {(x,y,z) => Arrays.asList(x,y,z)}
+        MethodHandle partialApp2 = insertArguments(list3, 0, "curry");
+        // partialApp2 = {(x, y) => list3("curry", x, y)}
+        println(partialApp2);
+        println(invoke(partialApp2, "chicken", "rice"));
+                                            // [curry, chicken, rice]
+
+        // ----
+
+        // double curry:
+        MethodHandle pa3 = insertArguments(list3, 0, "curry", "chutney");
+        // pa3 = {x => list3("curry", "chutney", x)}
+        println(pa3);
+        println(invoke(pa3, "tofu")); //[curry, chutney, tofu]
+
+        // triple curry:
+        MethodHandle pa4 = insertArguments(pa3, 0, "yak");
+        // pa4 = { => list3("curry", "chutney", "yak")}
+        println(pa4);
+        println(invoke(pa4));  // [curry, chutney, yak]
+    }
+
+    static void stronglyTyped() {
+        MethodHandle list2 = Utensil.list(2);
+        println(list2);  // list2 = {(x,y) => Arrays.asList(x,y)}
+        MethodType s2t = make(Object.class, String.class, String.class);
+        //list2 = convertArguments(list2, s2t);
+        println(list2.invoke("chicken", "rice"));
+
+        // curry with chicken or rice:
+        MethodHandle partialApp
+                = MethodHandles.insertArguments(list2, 0, "curry");
+        println(partialApp); // partialApp = {x => list2("curry", x)}
+        println(partialApp.invoke("chicken"));  // [curry, chicken]
+        println(partialApp.invoke("rice"));     // [curry, rice]
+
+        // curry with everything:
+        MethodHandle list3 = Utensil.list(3);
+        println(list3);  // list3 = {(x,y,z) => Arrays.asList(x,y,z)}
+        MethodType s3t = make(Object.class, String.class, String.class, String.class);
+        list3 = convertArguments(list3, s3t);
+        MethodHandle partialApp2
+                = MethodHandles.insertArguments(list3, 0, "curry");
+        // partialApp2 = {(x, y) => list3("curry", x, y)}
+        println(partialApp2);
+        println(partialApp2.invoke("chicken", "rice"));  // [curry, chicken, rice]
+
+        // double curry:
+        MethodHandle partialApp3
+                = MethodHandles.insertArguments(list3, 0, "curry", "chutney");
+        // partialApp3 = {x => list3("curry", "chutney", x)}
+        println(partialApp3);
+        println(partialApp3.invoke("tofu"));  // [curry, chutney, tofu]
+
+        // triple curry:
+        MethodHandle partialApp4
+                = MethodHandles.insertArguments(partialApp3, 0, "yak");
+        // partialApp4 = { => list3("curry", "chutney", "yak")}
+        println(partialApp4);
+        println(partialApp4.invoke());  // [curry, chutney, yak]
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netbeans/indy-demo/src/recipes/FastAndSlow.java	Thu Jun 04 20:51:51 2009 -0700
@@ -0,0 +1,85 @@
+/*
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package recipes;
+
+import java.dyn.*;
+import static java.dyn.MethodHandles.*;
+import static java.dyn.MethodType.*;
+import static recipes.Utensil.*;
+
+public class FastAndSlow {
+    private static final Lookup LOOKUP = lookup();
+
+    // ----
+
+    static Object fastAdd(int x, int y) {
+        int z = x+y;
+        if ((x ^ y) >= 0 && (x ^ z) < 0) {
+            println("oops, it's overflowing");
+            return slowAdd(x, y);
+        }
+        return z;
+    }
+
+    // ----
+
+    static Object slowAdd(Object x, Object y) {
+        double xd = ((Number)x).doubleValue();
+        double yd = ((Number)y).doubleValue();
+        println("I'm hungry; is it done yet?");
+        return xd + yd;
+    }
+
+    // ----
+
+    static boolean bothInts(Object x, Object y) {
+        return x instanceof Integer && y instanceof Integer;
+    }
+
+    public static void main(String... av) {
+        MethodHandle fastAdd =
+            LOOKUP.findStatic(FastAndSlow.class, "fastAdd",
+                make(Object.class, int.class, int.class));
+        MethodHandle slowAdd =
+            LOOKUP.findStatic(FastAndSlow.class, "slowAdd",
+                make(Object.class, Object.class, Object.class));
+        MethodHandle bothInts =
+            LOOKUP.findStatic(FastAndSlow.class, "bothInts",
+                make(boolean.class, Object.class, Object.class));
+        fastAdd = convertArguments(fastAdd, slowAdd.type());
+        MethodHandle combo = guardWithTest(bothInts, fastAdd, slowAdd);
+        println(invoke(combo, 2, 3));
+        println(invoke(combo, 2.1, 3.1));
+        println(invoke(combo, Integer.MAX_VALUE, -1));
+        println(invoke(combo, Integer.MAX_VALUE, 1));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netbeans/indy-demo/src/recipes/PlainOldJava.java	Thu Jun 04 20:51:51 2009 -0700
@@ -0,0 +1,125 @@
+/*
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package recipes;
+
+import java.dyn.*;
+import static java.dyn.MethodHandles.*;
+import static java.dyn.MethodType.*;
+import static recipes.Utensil.*;
+
+public class PlainOldJava {
+    private static final Lookup LOOKUP = lookup();
+
+    public static void main(String... av) {
+        for (int i = 0; i < 4; i++) {
+            test();
+        }
+    }
+    static void test() {
+        // ---
+
+        java.io.File file = new java.io.File("muffin.txt");
+        println(file.getName());
+        MethodHandle getName =
+                LOOKUP.findVirtual(file.getClass(), "getName",
+                            MethodType.make(String.class));
+        println(getName.<String>invoke(file));
+
+        // ---
+
+        MethodHandle charAt =
+                LOOKUP.findVirtual(String.class, "charAt",
+                            MethodType.make(char.class, int.class));
+        println(charAt.<char>invoke("foam", 3));
+
+        // ---
+        
+        // invokedynamic
+        println(InvokeDynamic.<String>getName(file));
+        println(InvokeDynamic.<String>toString((CharSequence) "soy latte"));
+        println(InvokeDynamic.<String>
+                    #"static:\=java\|lang\|Integer:toHexString"
+                        (0xCAFE));
+    }
+
+    // Linkage logic for all invokedynamic call sites in this class.
+    private static MethodHandle linkDynamic(CallSite site) {
+        println("[link] linkDynamic "+site);
+        MethodHandles.Lookup lookup = MethodHandles.lookup();
+        String       name = site.name();
+        MethodType   type = site.type();  // static type of call
+        MethodHandle target = null;  // result of call linkage
+        Class<?>     recvType = null;  // receiver (1st arg) type if any
+        if (type.parameterCount() >= 1) {
+            recvType = type.parameterType(0);
+            if (recvType.isPrimitive())  recvType = null;
+        }
+        if (target == null && recvType != null) {
+            MethodType dropRecvType = type.dropParameterType(0);
+            target = lookup.findVirtual(recvType, name, dropRecvType);
+        }
+        if (target == null && recvType != null && name.startsWith("special:")) {
+            MethodType dropRecvType = type.dropParameterType(0);
+            target = lookup.findSpecial(recvType, name, dropRecvType, site.callerClass());
+        }
+        if (target == null && name.startsWith("static:\\=")) {
+            int cbeg = name.indexOf('=')+1;
+            int cend = name.indexOf(':', cbeg);
+            String cname = name.substring(cbeg, cend).replaceAll("[\\\\][|]", ".");
+            String mname = name.substring(cend+1);
+            try {
+                Class<?> cls = Class.forName(cname);
+                target = lookup.findStatic(cls, mname, type);
+            } catch (ClassNotFoundException ex) {
+            }
+        }
+        if (target == null) {
+            throw new InvokeDynamicBootstrapError("linkage failed: "+site);
+        }
+        return target;
+    }
+
+    // Set up a class-local bootstrap method.
+    static { Linkage.registerBootstrapMethod("bootstrapDynamic"); }
+    private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
+        CallSite site = new CallSite(caller, name, type);
+        MethodHandle target = linkDynamic(site);
+        println("[link] set site target to "+target);
+        if (target.type() != site.type()) {
+            target = MethodHandles.convertArguments(target, site.type());
+            println("[link]   with conversions "+target);
+        }
+        site.setTarget(target);
+        println("[link] site is linked; this is the last time for "+site.name());
+        return site;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netbeans/indy-demo/src/recipes/Utensil.java	Thu Jun 04 20:51:51 2009 -0700
@@ -0,0 +1,112 @@
+/*
+ Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package recipes;
+
+import java.util.*;
+import java.dyn.*;
+import static java.dyn.MethodHandles.*;
+
+class Utensil {
+    public static void println(Object x) {
+        //if (x instanceof MethodHandle)
+        //    x = withType((MethodHandle)x);
+        System.out.println(x);
+    }
+    public static String withType(MethodHandle x) {
+        return x.toString() + x.type();
+    }
+
+    private static final Lookup LOOKUP = lookup();
+
+    /** Return the identity function from Object to Object. */
+    public static MethodHandle identity() {
+        return LOOKUP.findStatic(Utensil.class, "identity", MethodType.makeGeneric(1));
+    }
+
+    private static Object identity(Object x) { return x; }
+
+    private static final Object[] NO_ARGS_ARRAY = {};
+    private static Object[] array() { return NO_ARGS_ARRAY; }
+    private static Object[] makeArray(Object... args) { return args; }
+    private static Object[] array(Object a0)
+                { return makeArray(a0); }
+    private static Object[] array(Object a0, Object a1)
+                { return makeArray(a0, a1); }
+    private static Object[] array(Object a0, Object a1, Object a2)
+                { return makeArray(a0, a1, a2); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+                { return makeArray(a0, a1, a2, a3); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4)
+                { return makeArray(a0, a1, a2, a3, a4); }
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns an Object array of them, as if for varargs.
+     */
+    public static MethodHandle array(int nargs) {
+        try {
+            MethodType type = MethodType.makeGeneric(nargs).changeReturnType(Object[].class);
+            return LOOKUP.findStatic(Utensil.class, "array", type);
+        } catch (NoAccessException ex) {
+            // kitchen accident; call 911
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
+    private static List<Object> list() { return NO_ARGS_LIST; }
+    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
+    private static List<Object> list(Object a0)
+                { return makeList(a0); }
+    private static List<Object> list(Object a0, Object a1)
+                { return makeList(a0, a1); }
+    private static List<Object> list(Object a0, Object a1, Object a2)
+                { return makeList(a0, a1, a2); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
+                { return makeList(a0, a1, a2, a3); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4)
+                { return makeList(a0, a1, a2, a3, a4); }
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns an Object array of them, as if for varargs.
+     */
+    public static MethodHandle list(int nargs) {
+        try {
+            MethodType type = MethodType.makeGeneric(nargs).changeReturnType(List.class);
+            return LOOKUP.findStatic(Utensil.class, "list", type);
+        } catch (NoAccessException ex) {
+            // kitchen accident; call 911
+            throw new RuntimeException(ex);
+        }
+    }
+}
--- a/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java	Thu May 28 02:51:05 2009 -0700
+++ b/netbeans/meth/test/jdk/java/dyn/MethodHandlesTest.java	Thu Jun 04 20:51:51 2009 -0700
@@ -127,6 +127,12 @@
             args[i] = randomArg(params[i]);
         return args;
     }
+    static Object[] randomArgs(int nargs, Class<?> param) {
+        Object[] args = new Object[nargs];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(param);
+        return args;
+    }
 
     static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
         return Arrays.copyOf(a, a.length, atype);
@@ -641,8 +647,8 @@
         } catch (RuntimeException ex) {
             error = ex;
         }
-        System.out.println("convert "+id+ " to "+newType+" => "+target
-                +(error == null ? "" : " !! "+error));
+        //System.out.println("convert "+id+ " to "+newType+" => "+target
+        //        +(error == null ? "" : " !! "+error));
         if (positive && error != null)  throw error;
         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
         if (!positive)  return; // negative test failed as expected
@@ -651,7 +657,7 @@
         Object result = MethodHandles.invoke(target, args);
         assertCalled(name, convArgs);
         assertEquals(convResult, result);
-        System.out.print(':');
+        //System.out.print(':');
     }
 
     @Test
@@ -714,42 +720,73 @@
         fail("The test case is a prototype.");
     }
 
-    @Test @Ignore("unimplemented")
-    public void testInsertArgument_MethodHandle_Object() {
-        System.out.println("insertArgument");
-        MethodHandle target = null;
-        Object value = null;
-        MethodHandle expResult = null;
-        MethodHandle result = MethodHandles.insertArgument(target, 0, value);
-        assertEquals(expResult, result);
-        fail("The test case is a prototype.");
+    @Test
+    public void testInsertArguments() {
+        if (CAN_SKIP_WORKING)  return;
+        System.out.println("insertArguments");
+        for (int nargs = 0; nargs <= 4; nargs++) {
+            for (int ins = 0; ins <= 4; ins++) {
+                for (int pos = 0; pos <= nargs; pos++) {
+                    testInsertArguments(nargs, pos, ins);
+                }
+            }
+        }
     }
 
-    @Test @Ignore("unimplemented")
-    public void testAppendArgument() {
-        System.out.println("appendArgument");
-        MethodHandle target = null;
-        Object value = null;
-        MethodHandle expResult = null;
-        MethodHandle result = MethodHandles.insertArgument(target, target.type().parameterCount(), value);
-        assertEquals(expResult, result);
-        fail("The test case is a prototype.");
+    void testInsertArguments(int nargs, int pos, int ins) {
+        MethodHandle target = ValueConversions.varargsArray(nargs + ins);
+        Object[] args = randomArgs(target.type().parameterArray());
+        List<Object> resList = Arrays.asList(args);
+        List<Object> argsToPass = new ArrayList<Object>(resList);
+        List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
+        MethodHandle target2 = MethodHandles.insertArguments(target, pos,
+                (Object[]) argsToInsert.toArray());
+        //System.out.println("insert: "+argsToInsert+" into "+target2);
+        argsToInsert.clear();  // remove from argsToInsert
+        Object res2 = MethodHandles.invoke(target2, argsToPass.toArray());
+        Object res2List = Arrays.asList((Object[])res2);
+        //System.out.println("result: "+res2List);
+        //if (!resList.equals(res2List))
+        //    System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
+        assertEquals(resList, res2List);
     }
 
-    @Test @Ignore("unimplemented")
-    public void testInsertArgument_3args() {
-        System.out.println("insertArgument");
-        MethodHandle target = null;
-        Object value = null;
-        int pos = 0;
-        MethodHandle expResult = null;
-        MethodHandle result = MethodHandles.insertArgument(target, pos, value);
-        assertEquals(expResult, result);
-        fail("The test case is a prototype.");
+    @Test @Ignore("in progress")
+    public void testFoldArguments() {
+        //if (CAN_SKIP_WORKING)  return;
+        System.out.println("foldArguments");
+        for (int nargs = 0; nargs <= 4; nargs++) {
+            for (int fold = 0; fold <= 4; fold++) {
+                for (int pos = 0; pos <= nargs; pos++) {
+                    testFoldArguments(nargs, pos, fold);
+                }
+            }
+        }
+    }
+
+    void testFoldArguments(int nargs, int pos, int fold) {
+        if (pos != 0)  return;  // can fold only at pos=0 for now
+        MethodHandle target = ValueConversions.varargsList(1 + nargs);
+        MethodHandle combine = ValueConversions.varargsList(fold);
+        List<Object> argsToPass = Arrays.asList(randomArgs(fold + nargs, Object.class));
+        System.out.println("fold "+target+" with "+combine);
+        MethodHandle target2 = MethodHandles.foldArguments(target, combine, fold);
+        // Simulate expected effect of combiner on arglist:
+        List<Object> expected = new ArrayList<Object>(argsToPass);
+        List<Object> argsToFold = expected.subList(pos, pos + fold);
+        System.out.println("fold: "+argsToFold+" into "+target2);
+        Object foldedArgs = MethodHandles.invoke(combine, argsToFold.toArray());
+        argsToFold.clear(); argsToFold.add(foldedArgs);
+        Object result = MethodHandles.invoke(target2, argsToPass.toArray());
+        System.out.println("result: "+result);
+        if (!expected.equals(result))
+            System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result);
+        assertEquals(expected, result);
     }
 
     @Test
     public void testDropArguments() {
+        if (CAN_SKIP_WORKING)  return;
         System.out.println("dropArguments");
         for (int nargs = 0; nargs <= 4; nargs++) {
             for (int drop = 1; drop <= 4; drop++) {
@@ -763,8 +800,6 @@
     void testDropArguments(int nargs, int pos, int drop) {
         MethodHandle target = ValueConversions.varargsArray(nargs);
         Object[] args = randomArgs(target.type().parameterArray());
-        Object res = MethodHandles.invoke(target, args);
-        assertArrayEquals(args, (Object[])res);
         MethodHandle target2 = MethodHandles.dropArguments(target, pos,
                 Collections.nCopies(drop, Object.class).toArray(new Class[0]));
         List<Object> resList = Arrays.asList(args);
@@ -774,8 +809,8 @@
         }
         Object res2 = MethodHandles.invoke(target2, argsToDrop.toArray());
         Object res2List = Arrays.asList((Object[])res2);
-//        if (!resList.equals(res2List))
-//            System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
+        //if (!resList.equals(res2List))
+        //    System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
         assertEquals(resList, res2List);
     }
 
@@ -828,7 +863,7 @@
         while (test.type().parameterCount() < nargs)
             test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
         while (test.type().parameterCount() > nargs)
-            test = MethodHandles.insertArgument(test, 0, MISSING_ARG);
+            test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
         if (argClass != Object.class) {
             test = changeArgTypes(test, argClass);
             target = changeArgTypes(target, argClass);
@@ -857,16 +892,78 @@
         }
     }
 
-    @Test @Ignore("unimplemented")
-    public void testCombineArguments() {
-        System.out.println("checkArguments");
-        MethodHandle target = null;
-        MethodHandle checker = null;
-        int pos = 0;
-        MethodHandle expResult = null;
-        MethodHandle result = MethodHandles.combineArguments(target, pos, checker);
-        assertEquals(expResult, result);
-        fail("The test case is a prototype.");
+    @Test
+    public void testCatchException() {
+        if (CAN_SKIP_WORKING)  return;
+        System.out.println("catchException");
+        for (int nargs = 2; nargs <= 6; nargs++) {
+            for (int ti = 0; ti <= 1; ti++) {
+                boolean throwIt = (ti != 0);
+                testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs);
+                testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs);
+                testCatchException(String.class, new LinkageError("testing"), throwIt, nargs);
+            }
+        }
+    }
+
+    private static <T extends Throwable>
+    Object throwOrReturn(Object normal, T exception) throws T {
+        if (exception != null)  throw exception;
+        return normal;
+    }
+
+    void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) {
+        Class<? extends Throwable> exType = thrown.getClass();
+        MethodHandle throwOrReturn
+                = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
+                    MethodType.make(Object.class, Object.class, Throwable.class));
+        MethodHandle thrower = throwOrReturn;
+        while (thrower.type().parameterCount() < nargs)
+            thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
+        MethodHandle target = MethodHandles.catchException(thrower,
+                thrown.getClass(), ValueConversions.varargsList(1+nargs));
+        assertEquals(thrower.type(), target.type());
+        //System.out.println("catching with "+target+" : "+throwOrReturn);
+        Object[] args = randomArgs(nargs, Object.class);
+        args[1] = (throwIt ? thrown : null);
+        Object returned = MethodHandles.invoke(target, args);
+        //System.out.println("return from "+target+" : "+returned);
+        if (!throwIt) {
+            assertSame(args[0], returned);
+        } else {
+            List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
+            catchArgs.add(0, thrown);
+            assertEquals(catchArgs, returned);
+        }
+    }
+
+    @Test
+    public void testThrowException() {
+        if (CAN_SKIP_WORKING)  return;
+        System.out.println("throwException");
+        testThrowException(int.class, new ClassCastException("testing"));
+        testThrowException(void.class, new java.io.IOException("testing"));
+        testThrowException(String.class, new LinkageError("testing"));
+    }
+
+    void testThrowException(Class<?> returnType, Throwable thrown) {
+        Class<? extends Throwable> exType = thrown.getClass();
+        MethodHandle target = MethodHandles.throwException(returnType, exType);
+        //System.out.println("throwing with "+target+" : "+thrown);
+        MethodType expectedType = MethodType.make(returnType, exType);
+        assertEquals(expectedType, target.type());
+        Throwable caught = null;
+        try {
+            Object res = MethodHandles.invoke_1(target, thrown);
+            fail("got "+res+" instead of throwing "+thrown);
+        } catch (Throwable ex) {
+            if (ex != thrown) {
+                if (ex instanceof Error)  throw (Error)ex;
+                if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
+            }
+            caught = ex;
+        }
+        assertSame(thrown, caught);
     }
 
 }
--- a/netbeans/meth/test/sun/dyn/util/ValueConversionsTest.java	Thu May 28 02:51:05 2009 -0700
+++ b/netbeans/meth/test/sun/dyn/util/ValueConversionsTest.java	Thu Jun 04 20:51:51 2009 -0700
@@ -26,7 +26,10 @@
 package sun.dyn.util;
 
 import java.dyn.MethodHandle;
+import java.dyn.MethodHandles;
 import java.io.Serializable;
+import java.util.Arrays;
+import org.junit.Ignore;
 import org.junit.Test;
 import static org.junit.Assert.*;
 
@@ -232,4 +235,29 @@
         assertEquals(expResult, result);
     }
 
+    @Test
+    public void testVarargsArray() {
+        System.out.println("varargsArray");
+        for (int nargs = 0; nargs <= 5; nargs++) {
+            MethodHandle target = ValueConversions.varargsArray(nargs);
+            Object[] args = new Object[nargs];
+            for (int i = 0; i < nargs; i++)
+                args[i] = "#"+i;
+            Object res = MethodHandles.invoke(target, args);
+            assertArrayEquals(args, (Object[])res);
+        }
+    }
+
+    @Test
+    public void testVarargsList() {
+        System.out.println("varargsList");
+        for (int nargs = 0; nargs <= 5; nargs++) {
+            MethodHandle target = ValueConversions.varargsList(nargs);
+            Object[] args = new Object[nargs];
+            for (int i = 0; i < nargs; i++)
+                args[i] = "#"+i;
+            Object res = MethodHandles.invoke(target, args);
+            assertEquals(Arrays.asList(args), res);
+        }
+    }
 }
\ No newline at end of file