changeset 52:94b518bfe27e

update for latest API changes
author jrose
date Tue, 04 Jan 2011 22:58:40 -0800
parents e6beb9f45c82
children 0b7c3ce7100f
files netbeans/indy-demo/nbproject/project.properties netbeans/indy-demo/src/FidgetDemo.java netbeans/indy-demo/src/GetNameDemo.java netbeans/indy-demo/src/Hello.java netbeans/indy-demo/src/PrintArgsDemo.java netbeans/indy-demo/src/indify/Indify.java netbeans/meth/nbproject/build-impl.xml netbeans/meth/nbproject/genfiles.properties netbeans/meth/nbproject/project.properties
diffstat 9 files changed, 414 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/netbeans/indy-demo/nbproject/project.properties	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/indy-demo/nbproject/project.properties	Tue Jan 04 22:58:40 2011 -0800
@@ -33,9 +33,9 @@
 # choices: yes, no
 allowTransitionalJSR292=no
 # assuming full JDK_7X:
-#javac.standalone.bcp =
+javac.standalone.bcp =
 # pulling from a standalone langtools build:
-javac.standalone.bcp = -J-Xbootclasspath/p:${reference.langtools-javac.jar}
+#javac.standalone.bcp = -J-Xbootclasspath/p:${reference.langtools-javac.jar}
 javac.deprecation=false
 javac.source=1.7
 javac.target=1.7
--- a/netbeans/indy-demo/src/FidgetDemo.java	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/indy-demo/src/FidgetDemo.java	Tue Jan 04 22:58:40 2011 -0800
@@ -89,7 +89,7 @@
     }
 
     // Use a local call site subclass.  (These are optional but fun.)
-    private static class CSite extends CallSite {
+    private static class CSite extends MutableCallSite {
         int count;
         public CSite(Class caller, String name, MethodType type) throws NoAccessException {
             super(type);
--- a/netbeans/indy-demo/src/GetNameDemo.java	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/indy-demo/src/GetNameDemo.java	Tue Jan 04 22:58:40 2011 -0800
@@ -117,7 +117,7 @@
             System.out.println("[link]   with conversions "+target);
         }
         System.out.println("[link] site is linked; this is the last time for "+name);
-        return new CallSite(target);
+        return new ConstantCallSite(target);
     }
 }
 
--- a/netbeans/indy-demo/src/Hello.java	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/indy-demo/src/Hello.java	Tue Jan 04 22:58:40 2011 -0800
@@ -52,7 +52,7 @@
     private static CallSite bootstrapDynamic(Lookup caller, String name, MethodType type) {
         assert(type.parameterCount() == 1 && name.equals("hail"));  // in lieu of MOP
         System.out.println("set target to adapt "+greeter);
-        return new CallSite(greeter.asType(type));
+        return new VolatileCallSite(greeter.asType(type));
     }
 
     private static MethodType MT_bsm() {
--- a/netbeans/indy-demo/src/PrintArgsDemo.java	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/indy-demo/src/PrintArgsDemo.java	Tue Jan 04 22:58:40 2011 -0800
@@ -53,7 +53,7 @@
 }
 private static CallSite bootstrapDynamic(Lookup caller, String name, MethodType type) {
   // ignore caller and name, but match the type:
-  return new CallSite(MethodHandles.collectArguments(printArgs, type));
+  return new ConstantCallSite(MethodHandles.collectArguments(printArgs, type));
 }
     //// END JAVADOC EXAMPLE
 
--- a/netbeans/indy-demo/src/indify/Indify.java	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/indy-demo/src/indify/Indify.java	Tue Jan 04 22:58:40 2011 -0800
@@ -34,6 +34,13 @@
  * Transform one or more class files to incorporate JSR 292 features,
  * such as {@code invokedynamic}.
  * <p>
+ * This is a standalone program in a single source file.
+ * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
+ * Copies of this file may show up in multiple locations for standalone usage.
+ * The primary maintained location of this file is as follows:
+ * <a href="http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java">
+ * http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java</a>
+ * <p>
  * Static private methods named MH_x and MT_x (where x is arbitrary)
  * must be stereotyped generators of MethodHandle and MethodType
  * constants.  All calls to them are transformed to {@code CONSTANT_MethodHandle}
@@ -57,7 +64,7 @@
  * Static private methods named INDY_x must be stereotyped generators
  * of {@code invokedynamic} call sites.
  * All calls to them must be immediately followed by
- * {@code invokeExact} calls. 
+ * {@code invokeExact} calls.
  * All such pairs of calls are transformed to {@code invokedynamic}
  * instructions.  Each INDY_x method must begin with a call to a
  * MH_x method, which is taken to be its bootstrap method.
@@ -91,11 +98,10 @@
 (same output as above)
  * </pre></blockquote>
  * <p>
- * Until the format of {@code CONSTANT_InvokeDynamic} entries is finalized,
- * the {@code --transitionalJSR292} switch is recommended (and turned on by default).
+ * Before OpenJDK build b123, the format of {@code CONSTANT_InvokeDynamic} is in transition,
+ * and the switch {@code --transitionalJSR292=yes} is recommended.
+ * It is turned <em>off</em> by default, but users of earlier builds may need to turn it on.
  * <p>
- * Note on packaging and reuse:  This is a standalone single-source program.
- * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
  * A version of this transformation built on top of <a href="http://asm.ow2.org/">http://asm.ow2.org/</a> would be welcome.
  * @author John Rose
  */
@@ -107,22 +113,25 @@
     public File dest;
     public String[] classpath = {"."};
     public boolean keepgoing = false;
+    public boolean expandProperties = false;
     public boolean overwrite = false;
     public boolean quiet = false;
     public boolean verbose = false;
-    public boolean transitionalJSR292 = true;
+    public boolean transitionalJSR292 = false;  // final version is distributed
     public boolean all = false;
+    public int verifySpecifierCount = -1;
 
     public void run(String... av) throws IOException {
         List<String> avl = new ArrayList<>(Arrays.asList(av));
         parseOptions(avl);
         if (avl.isEmpty())
-            throw new RuntimeException("Usage: indify [--dest dir] [option...] file...");
+            throw new IllegalArgumentException("Usage: indify [--dest dir] [option...] file...");
         if ("--java".equals(avl.get(0))) {
             avl.remove(0);
             try {
                 runApplication(avl.toArray(new String[0]));
             } catch (Exception ex) {
+                if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
                 throw new RuntimeException(ex);
             }
             return;
@@ -150,6 +159,7 @@
         av = avl.toArray(new String[0]);
         Class<?> mainClass = Class.forName(mainClassName, true, makeClassLoader());
         java.lang.reflect.Method main = mainClass.getMethod("main", String[].class);
+        try { main.setAccessible(true); } catch (SecurityException ex) { }
         main.invoke(null, (Object) av);
     }
 
@@ -157,32 +167,48 @@
         for (; !av.isEmpty(); av.remove(0)) {
             String a = av.get(0);
             if (a.startsWith("-")) {
-                String a2 = a.substring(a.indexOf('=')+1);
-                if (a.equals("--java"))
-                    return;
-                else if (a.startsWith("--dest=") || a.startsWith("-d="))
-                    dest = new File(a2);
-                else if (a.equals("--dest") || a.equals("-d"))
-                    dest = new File(av.remove(1));
-                else if (a.equals("--classpath") || a.equals("-cp"))
-                    classpath = av.remove(1).split("["+File.pathSeparatorChar+"]");
-                else if (a.equals("-k") || a.equals("--keepgoing"))
-                    keepgoing = true;  // print errors but keep going
-                else if (a.equals("--overwrite"))
-                    overwrite = true;  // overwrite output files
-                else if (a.equals("--all"))
-                    all = true;  // copy all classes, even if no patterns
-                else if (a.equals("--quiet") || a.equals("-q"))
-                    quiet = true;  // less output
-                else if (a.equals("--verbose"))
-                    verbose = true;  // more output
-                else if (a.equals("--transitionalJSR292") ||
-                         a.equals("--transitionalJSR292=yes"))
-                    transitionalJSR292 = true;  // use older invokedynamic format
-                else if (a.equals("--transitionalJSR292=no"))
-                    transitionalJSR292 = false;  // do not use older invokedynamic format
-                else
-                    throw new RuntimeException("unrecognized flag: "+a);
+                String a2 = null;
+                int eq = a.indexOf('=');
+                if (eq > 0) {
+                    a2 = maybeExpandProperties(a.substring(eq+1));
+                    a = a.substring(0, eq+1);
+                }
+                switch (a) {
+                case "--java":
+                    return;  // keep this argument
+                case "-d": case "--dest": case "-d=": case "--dest=":
+                    dest = new File(a2 != null ? a2 : maybeExpandProperties(av.remove(1)));
+                    break;
+                case "-cp": case "--classpath":
+                    classpath = maybeExpandProperties(av.remove(1)).split("["+File.pathSeparatorChar+"]");
+                    break;
+                case "-k": case "--keepgoing": case "--keepgoing=":
+                    keepgoing = booleanOption(a2);  // print errors but keep going
+                    break;
+                case "--expand-properties": case "--expand-properties=":
+                    expandProperties = booleanOption(a2);  // expand property references in subsequent arguments
+                    break;
+                case "--verify-specifier-count": case "--verify-specifier-count=":
+                    verifySpecifierCount = Integer.valueOf(a2);
+                    break;
+                case "--overwrite": case "--overwrite=":
+                    overwrite = booleanOption(a2);  // overwrite output files
+                    break;
+                case "--all": case "--all=":
+                    all = booleanOption(a2);  // copy all classes, even if no patterns
+                    break;
+                case "-q": case "--quiet": case "--quiet=":
+                    quiet = booleanOption(a2);  // less output
+                    break;
+                case "-v": case "--verbose": case "--verbose=":
+                    verbose = booleanOption(a2);  // more output
+                    break;
+                case "--transitionalJSR292": case "--transitionalJSR292=":
+                    transitionalJSR292 = booleanOption(a2);  // use older invokedynamic format
+                    break;
+                default:
+                    throw new IllegalArgumentException("unrecognized flag: "+a);
+                }
                 continue;
             } else {
                 break;
@@ -190,6 +216,36 @@
         }
         if (dest == null && !overwrite)
             throw new RuntimeException("no output specified; need --dest d or --overwrite");
+        if (expandProperties) {
+            for (int i = 0; i < av.size(); i++)
+                av.set(i, maybeExpandProperties(av.get(i)));
+        }
+    }
+
+    private boolean booleanOption(String s) {
+        if (s == null)  return true;
+        switch (s) {
+        case "true":  case "yes": case "on":  case "1": return true;
+        case "false": case "no":  case "off": case "0": return false;
+        }
+        throw new IllegalArgumentException("unrecognized boolean flag="+s);
+    }
+
+    private String maybeExpandProperties(String s) {
+        if (!expandProperties)  return s;
+        Set<String> propsDone = new HashSet<>();
+        while (s.contains("${")) {
+            int lbrk = s.indexOf("${");
+            int rbrk = s.indexOf('}', lbrk);
+            if (rbrk < 0)  break;
+            String prop = s.substring(lbrk+2, rbrk);
+            if (!propsDone.add(prop))  break;
+            String value = System.getProperty(prop);
+            if (verbose)  System.err.println("expanding ${"+prop+"} => "+value);
+            if (value == null)  break;
+            s = s.substring(0, lbrk) + value + s.substring(rbrk+1);
+        }
+        return s;
     }
 
     public void indify(String a) throws IOException {
@@ -204,7 +260,7 @@
         else if (!keepgoing)
             throw new RuntimeException("unrecognized file: "+a);
     }
-    
+
     private void ensureDirectory(File dir) {
         if (dir.mkdirs() && !quiet)
             System.err.println("created "+dir);
@@ -215,12 +271,12 @@
         ClassFile cf = new ClassFile(f);
         Logic logic = new Logic(cf);
         boolean changed = logic.transform();
-        if (!quiet)  logic.reportPatternMethods();
+        logic.reportPatternMethods(quiet, keepgoing);
         if (changed || all) {
             File outfile;
             if (dest != null) {
                 ensureDirectory(dest);
-                outfile = classPathFile(dest, cf.classname());
+                outfile = classPathFile(dest, cf.nameString());
             } else {
                 outfile = f;  // overwrite input file, no matter where it is
             }
@@ -230,7 +286,7 @@
     }
 
     File classPathFile(File pathDir, String className) {
-        String qualname = className+".class";
+        String qualname = className.replace('.','/')+".class";
         qualname = qualname.replace('/', File.separatorChar);
         return new File(pathDir, qualname);
     }
@@ -275,6 +331,9 @@
                         return c;
                     }
                 } catch (Exception ex) {
+                    if (ex instanceof IllegalArgumentException)
+                        // pass error from reportPatternMethods
+                        throw (IllegalArgumentException) ex;
                 }
             }
             return super.loadClass(name, resolve);
@@ -282,6 +341,7 @@
         private File findClassInPath(String name) {
             for (String s : classpath) {
                 File f = classPathFile(new File(s), name);
+                //System.out.println("Checking for "+f);
                 if (f.exists() && f.canRead()) {
                     return f;
                 }
@@ -296,12 +356,12 @@
             }
         }
         private Class<?> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
-            if (verbose)  System.out.println("Loading class from "+f);
+            if (verbose)  System.err.println("Loading class from "+f);
             ClassFile cf = new ClassFile(f);
             Logic logic = new Logic(cf);
             boolean changed = logic.transform();
-            if (verbose && !changed)  System.out.println("(no change)");
-            if (verbose)  logic.reportPatternMethods();
+            if (verbose && !changed)  System.err.println("(no change)");
+            logic.reportPatternMethods(!verbose, keepgoing);
             byte[] bytes = cf.toByteArray();
             return defineClass(null, bytes, 0, bytes.length);
         }
@@ -323,6 +383,7 @@
             Pool pool = cf.pool;
             //for (Constant c : cp)  System.out.println("  # "+c);
             for (Method m : cf.methods) {
+                if (constants.containsKey(m))  continue;  // don't bother
                 // Transform references.
                 int blab = 0;
                 for (Instruction i = m.instructions(); i != null; i = i.next()) {
@@ -335,7 +396,7 @@
                     Constant con = constants.get(conm);
                     if (con == null)  continue;
                     if (blab++ == 0 && !quiet)
-                        System.err.println("patching "+cf.classname()+"."+m);
+                        System.err.println("patching "+cf.nameString()+"."+m);
                     //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("  |"+j); }
                     if (con.tag == CONSTANT_InvokeDynamic ||
                         con.tag == CONSTANT_InvokeDynamic_17) {
@@ -379,7 +440,7 @@
             cf.methods.removeAll(constants.keySet());
             return true;
         }
-        
+
         // Scan forward from the instruction to find where the stack p
         // below the current sp at the instruction.
         Instruction findPop(Instruction i) {
@@ -397,9 +458,9 @@
                     String type = simplifyType(pool.getString(CONSTANT_Utf8, ref[2]));
                     switch (i.bc) {
                     case opc_getstatic:
-                    case opc_getfield:          
+                    case opc_getfield:
                     case opc_putstatic:
-                    case opc_putfield:          
+                    case opc_putfield:
                         pops = pops.replace("Q", type);
                         break;
                     default:
@@ -429,7 +490,7 @@
             System.err.println("*** bailout on jvm: "+jvm.stack+" "+i);
             return null;
         }
-        
+
         boolean findPatternMethods() {
             boolean found = false;
             for (char mark : "THI".toCharArray()) {
@@ -447,14 +508,27 @@
             return found;
         }
 
-        void reportPatternMethods() {
-            if (!constants.keySet().isEmpty())
-                System.err.println("pattern methods found: "+constants.keySet());
+        void reportPatternMethods(boolean quietly, boolean allowMatchFailure) {
+            if (!quietly && !constants.keySet().isEmpty())
+                System.err.println("pattern methods removed: "+constants.keySet());
             for (Method m : cf.methods) {
                 if (nameMark(cf.pool.getString(m.name)) != 0 &&
-                    !constants.containsKey(m))
-                    System.err.println("warning: method has special name but fails to match pattern: "+m);
+                    constants.get(m) == null) {
+                    String failure = "method has special name but fails to match pattern: "+m;
+                    if (!allowMatchFailure)
+                        throw new IllegalArgumentException(failure);
+                    else if (!quietly)
+                        System.err.println("warning: "+failure);
+                }
             }
+            if (verifySpecifierCount >= 0) {
+                List<Object[]> specs = bootstrapMethodSpecifiers(false);
+                int specsLen = (specs == null ? 0 : specs.size());
+                if (specsLen != verifySpecifierCount) {
+                    throw new IllegalArgumentException("BootstrapMethods length is "+specsLen+" but should be "+verifySpecifierCount);
+                }
+            }
+            if (!quiet)  System.err.flush();
         }
 
         // mark constant pool entries according to participation in patterns
@@ -491,7 +565,7 @@
                             break;
                         }
                         String cls = cf.pool.getString(CONSTANT_Class, cl);
-                        if (cls.equals(cf.classname())) {
+                        if (cls.equals(cf.nameString())) {
                             switch (poolMarks[(char)nt]) {
                             // it is a private MH/MT/INDY method
                             case 'T': case 'H': case 'I':
@@ -544,6 +618,7 @@
             final List<Object> stack = new ArrayList<>();
             int sp() { return stack.size(); }
             void push(Object x) { stack.add(x); }
+            void push2(Object x) { stack.add(EMPTY_SLOT); stack.add(x); }
             void pushAt(int pos, Object x) { stack.add(stack.size()+pos, x); }
             Object pop() { return stack.remove(sp()-1); }
             Object top() { return stack.get(sp()-1); }
@@ -567,6 +642,17 @@
                 return true;
             }
         }
+        private final String EMPTY_SLOT = "_";
+        private void removeEmptyJVMSlots(List<Object> args) {
+            for (;;) {
+                int i = args.indexOf(EMPTY_SLOT);
+                if (i >= 0 && i+1 < args.size()
+                    && (isConstant(args.get(i+1), CONSTANT_Long) ||
+                        isConstant(args.get(i+1), CONSTANT_Double)))
+                    args.remove(i);
+                else  break;
+            }
+        }
 
         private Constant scanPattern(Method m, char patternMark) {
             if (verbose)  System.err.println("scan "+m+" for pattern="+patternMark);
@@ -589,11 +675,12 @@
                 //System.out.println(jvm.stack+" "+i);
                 int bc = i.bc;
                 switch (bc) {
-                case opc_ldc:           jvm.push(pool.get(i.u1At(1))); break;
-                case opc_ldc_w:         jvm.push(pool.get(i.u2At(1))); break;
-                case opc_aconst_null:   jvm.push(null);              break;
-                case opc_bipush:        jvm.push((byte)  i.u1At(1)); break;
-                case opc_sipush:        jvm.push((short) i.u2At(1)); break;
+                case opc_ldc:           jvm.push(pool.get(i.u1At(1)));   break;
+                case opc_ldc_w:         jvm.push(pool.get(i.u2At(1)));   break;
+                case opc_ldc2_w:        jvm.push2(pool.get(i.u2At(1)));  break;
+                case opc_aconst_null:   jvm.push(null);                  break;
+                case opc_bipush:        jvm.push((int)(byte) i.u1At(1)); break;
+                case opc_sipush:        jvm.push((int)(short)i.u2At(1)); break;
 
                 // these support creation of a restarg array
                 case opc_anewarray:
@@ -613,6 +700,18 @@
                     args.clear();
                     break;
 
+                case opc_new:
+                {
+                    String type = pool.getString(CONSTANT_Class, (short)i.u2At(1));
+                    //System.out.println("new "+type);
+                    switch (type) {
+                    case "java/lang/StringBuilder":
+                        jvm.push("StringBuilder");
+                        continue decode;  // go to next instruction
+                    }
+                    break decode;  // bail out
+                }
+
                 case opc_getstatic:
                 {
                     // int.class compiles to getstatic Integer.TYPE
@@ -649,8 +748,9 @@
 
                 case opc_invokestatic:
                 case opc_invokevirtual:
+                case opc_invokespecial:
                 {
-                    boolean hasRecv = (bc == opc_invokevirtual);
+                    boolean hasRecv = (bc != opc_invokestatic);
                     int methi = i.u2At(1);
                     char mark = poolMarks[methi];
                     Short[] ref = pool.getMemberRef((short)methi);
@@ -659,8 +759,14 @@
                     args = jvm.args(hasRecv, type);
                     String intrinsic = null;
                     Constant con;
-                    if (mark == 'D') {
+                    if (mark == 'D' || mark == 'J') {
                         intrinsic = pool.getString(CONSTANT_Utf8, ref[1]);
+                        if (mark == 'J') {
+                            String cls = pool.getString(CONSTANT_Class, ref[0]);
+                            cls = cls.substring(1+cls.lastIndexOf('/'));
+                            intrinsic = cls+"."+intrinsic;
+                        }
+                        //System.out.println("recognized intrinsic "+intrinsic);
                         byte refKind = -1;
                         switch (intrinsic) {
                         case "findGetter":          refKind = REF_getField;         break;
@@ -681,11 +787,13 @@
                     if (mark == 'T' || mark == 'H' || mark == 'I') {
                         ownMethod = findMember(cf.methods, ref[1], ref[2]);
                     }
-                    if ("fromMethodDescriptorString".equals(intrinsic)) {
+                    //if (intrinsic != null)  System.out.println("intrinsic = "+intrinsic);
+                    switch (intrinsic == null ? "" : intrinsic) {
+                    case "fromMethodDescriptorString":
                         con = makeMethodTypeCon(args.get(0));
                         args.clear(); args.add(con);
                         continue;
-                    } else if ("methodType".equals(intrinsic)) {
+                    case "methodType": {
                         flattenVarargs(args);  // there are several overloadings, some with varargs
                         StringBuilder buf = new StringBuilder();
                         String rtype = null;
@@ -714,7 +822,11 @@
                             } else if (typeArg instanceof Constant) {
                                 Constant argCon = (Constant) typeArg;
                                 if (argCon.tag == CONSTANT_Class) {
-                                    buf.append('L').append(pool.get(argCon.itemIndex()).itemString()).append(';');
+                                    String cn = pool.get(argCon.itemIndex()).itemString();
+                                    if (cn.endsWith(";"))
+                                        buf.append(cn);
+                                    else
+                                        buf.append('L').append(cn).append(';');
                                 } else {
                                     break decode;
                                 }
@@ -732,30 +844,57 @@
                         con = con = makeMethodTypeCon(buf.toString());
                         args.clear(); args.add(con);
                         continue;
-                    } else if ("lookup".equals(intrinsic)) {
+                    }
+                    case "lookup":
+                    case "dynamicInvoker":
                         args.clear(); args.add(intrinsic);
                         continue;
-                    } else if ("lookupClass".equals(intrinsic) && args.equals(Arrays.asList("lookup"))) {
-                        // fold lookup().lookupClass() to the enclosing class
-                        args.clear(); args.add(pool.get(cf.thisc));
-                        continue;
-                    } else if ("dynamicInvoker".equals(intrinsic)) {
-                        args.clear(); args.add(intrinsic);
-                        continue;
-                    } else if ("invokeGeneric".equals(intrinsic) ||
-                               "invokeWithArguments".equals(intrinsic)) {
+                    case "lookupClass":
+                        if (args.equals(Arrays.asList("lookup"))) {
+                            // fold lookup().lookupClass() to the enclosing class
+                            args.clear(); args.add(pool.get(cf.thisc));
+                            continue;
+                        }
+                        break;
+                    case "invokeGeneric":
+                    case "invokeWithArguments":
                         if (patternMark != 'I')  break decode;
                         if ("invokeWithArguments".equals(intrinsic))
                             flattenVarargs(args);
                         bsmArgs = new ArrayList(args);
                         args.clear(); args.add("invokeGeneric");
                         continue;
-                    } else if (!hasRecv && ownMethod != null && patternMark != 0) {
+                    case "Integer.valueOf":
+                    case "Float.valueOf":
+                    case "Long.valueOf":
+                    case "Double.valueOf":
+                        removeEmptyJVMSlots(args);
+                        if (args.size() == 1) {
+                            arg = args.remove(0);
+                            assert(3456 == (CONSTANT_Integer*1000 + CONSTANT_Float*100 + CONSTANT_Long*10 + CONSTANT_Double));
+                            if (isConstant(arg, CONSTANT_Integer + "IFLD".indexOf(intrinsic.charAt(0)))
+                                || arg instanceof Number) {
+                                args.add(arg); continue;
+                            }
+                        }
+                        break decode;
+                    case "StringBuilder.append":
+                        // allow calls like ("value = "+x)
+                        removeEmptyJVMSlots(args);
+                        args.subList(1, args.size()).clear();
+                        continue;
+                    case "StringBuilder.toString":
+                        args.clear();
+                        args.add(intrinsic);
+                        continue;
+                    }
+                    if (!hasRecv && ownMethod != null && patternMark != 0) {
                         con = constants.get(ownMethod);
                         if (con == null)  break decode;
                         args.clear(); args.add(con);
                         continue;
-                    } else if (patternMark == 'I' && type.endsWith(")V")) {
+                    } else if (type.endsWith(")V")) {
+                        // allow calls like println("reached the pattern method")
                         args.clear();
                         continue;
                     }
@@ -765,24 +904,27 @@
                 {
                     ++branchCount;
                     if (bsmArgs != null) {
-                        // parse bsmArgs as (MH, lookup, MT, String, [extra])
+                        // parse bsmArgs as (MH, lookup, String, MT, [extra])
                         Constant indyCon = makeInvokeDynamicCon(bsmArgs);
                         if (indyCon != null) {
                             Constant typeCon = (Constant) bsmArgs.get(3);
                             indySignatures.put(m, pool.getString(typeCon.itemIndex()));
+                            return indyCon;
                         }
-                        return indyCon;
+                        System.err.println(m+": inscrutable bsm arguments: "+bsmArgs);
+                        break decode;  // bail out
                     }
                     arg = jvm.pop();
                     if (branchCount == 2 && UNKNOWN_CON.equals(arg))
                         break;  // merge to next path
-                    if (!isConstant(arg, wantTag))  break decode;
-                    return (Constant) arg;
+                    if (isConstant(arg, wantTag))
+                        return (Constant) arg;
+                    break decode;  // bail out
                 }
                 default:
                     if (jvm.stackMotion(i.bc))  break;
-                    if (bc >= opc_iconst_MIN && bc <= opc_iconst_MAX)
-                        { jvm.push((int)(bc - opc_iconst_0)); break; }
+                    if (bc >= opc_nconst_MIN && bc <= opc_nconst_MAX)
+                        { jvm.push(INSTRUCTION_CONSTANTS[bc - opc_nconst_MIN]); break; }
                     if (patternMark == 'I') {
                         // these support caching paths in INDY_x methods
                         if (bc == opc_aload || bc >= opc_aload_0 && bc <= opc_aload_MAX)
@@ -854,7 +996,7 @@
             ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
                     new Short[]{ nindex, tindex }).index;
             byte reftag = CONSTANT_Method;
-            if (refKind <= REF_putStatic)      
+            if (refKind <= REF_putStatic)
                 reftag = CONSTANT_Field;
             else if (refKind == REF_invokeInterface)
                 reftag = CONSTANT_InterfaceMethod;
@@ -863,47 +1005,101 @@
         }
         private Constant makeInvokeDynamicCon(List<Object> args) {
             // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg")
+            removeEmptyJVMSlots(args);
             if (args.size() != 4 && args.size() != 5)  return null;
             int argi = 0;
-            short nindex, tindex;
-            List<Short> indexes = new ArrayList<>();
+            short nindex, tindex, ntindex, bsmindex;
             Object con;
             if (!isConstant(con = args.get(argi++), CONSTANT_MethodHandle))  return null;
-            indexes.add((short) ((Constant)con).index);
+            bsmindex = (short) ((Constant)con).index;
             if (!"lookup".equals(args.get(argi++)))  return null;
             if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
             nindex = ((Constant)con).itemIndex();
             if (!isConstant(con = args.get(argi++), CONSTANT_MethodType))  return null;
             tindex = ((Constant)con).itemIndex();
-            indexes.add( (short) cf.pool.addConstant(CONSTANT_NameAndType,
-                    new Short[]{ nindex, tindex }).index );
+            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
+                                                  new Short[]{ nindex, tindex }).index;
             if (transitionalJSR292) {
-                if (argi != args.size())  return null;
+                if (argi != args.size()) {
+                    System.err.println("BSM specifier has extra arguments but transitionalJSR292=1");
+                    return null;
+                }
                 return cf.pool.addConstant(CONSTANT_InvokeDynamic_17,
-                        indexes.toArray(new Short[indexes.size()]));
-            } else if (argi == args.size()) {
-                indexes.add((short)0);
-            } else {
-                List<Object> extraArgs;
-                if (args.get(argi) instanceof List)
-                    extraArgs = (List<Object>) args.get(argi);
+                        new Short[]{ bsmindex, ntindex });
+            }
+            List<Object> extraArgs = Collections.emptyList();
+            if (argi < args.size()) {
+                Object arg = args.get(argi);
+                if (arg instanceof List)
+                    extraArgs = (List<Object>) arg;
                 else
-                    extraArgs = Arrays.asList(args.get(argi));
-                indexes.add((short)extraArgs.size());
-                for (Object x : extraArgs) {
-                    if (!(x instanceof Constant))  return null;
-                    indexes.add((short) ((Constant)x).index);
+                    extraArgs = Arrays.asList(arg);
+                removeEmptyJVMSlots(args);
+            }
+            List<Short> extraArgIndexes = new CountedList<>(Short.class);
+            for (Object x : extraArgs) {
+                if (x instanceof Number) {
+                    Object num = null; byte numTag = 0;
+                    if (x instanceof Integer) { num = x; numTag = CONSTANT_Integer; }
+                    if (x instanceof Float)   { num = Float.floatToRawIntBits((Float)x); numTag = CONSTANT_Float; }
+                    if (x instanceof Long)    { num = x; numTag = CONSTANT_Long; }
+                    if (x instanceof Double)  { num = Double.doubleToRawLongBits((Double)x); numTag = CONSTANT_Double; }
+                    if (num != null)  x = cf.pool.addConstant(numTag, x);
+                }
+                if (!(x instanceof Constant))  return null;
+                extraArgIndexes.add((short) ((Constant)x).index);
+            }
+            List<Object[]> specs = bootstrapMethodSpecifiers(true);
+            int specindex = -1;
+            Object[] spec = new Object[]{ bsmindex, extraArgIndexes };
+            for (Object[] spec1 : specs) {
+                if (Arrays.equals(spec1, spec)) {
+                    specindex = specs.indexOf(spec1);
+                    if (verbose)  System.err.println("reusing BSM specifier: "+spec1[0]+spec1[1]);
+                    break;
                 }
             }
+            if (specindex == -1) {
+                specindex = (short) specs.size();
+                specs.add(spec);
+                if (verbose)  System.err.println("adding BSM specifier: "+spec[0]+spec[1]);
+            }
             return cf.pool.addConstant(CONSTANT_InvokeDynamic,
-                    indexes.toArray(new Short[indexes.size()]));
+                        new Short[]{ (short)specindex, ntindex });
+        }
+
+        List<Object[]> bootstrapMethodSpecifiers(boolean createIfNotFound) {
+            Attr bsms = cf.findAttr("BootstrapMethods");
+            if (bsms == null) {
+                if (!createIfNotFound)  return null;
+                bsms = new Attr(cf, "BootstrapMethods", new byte[]{0,0});
+                assert(bsms == cf.findAttr("BootstrapMethods"));
+            }
+            if (bsms.item instanceof byte[]) {
+                // unflatten
+                List<Object[]> specs = new CountedList<>(Object[].class);
+                DataInputStream in = new DataInputStream(new ByteArrayInputStream((byte[]) bsms.item));
+                try {
+                    int len = (char) in.readShort();
+                    for (int i = 0; i < len; i++) {
+                        short bsm = in.readShort();
+                        int argc = (char) in.readShort();
+                        List<Short> argv = new CountedList<>(Short.class);
+                        for (int j = 0; j < argc; j++)
+                            argv.add(in.readShort());
+                        specs.add(new Object[]{ bsm, argv });
+                    }
+                } catch (IOException ex) { throw new InternalError(); }
+                bsms.item = specs;
+            }
+            return (List<Object[]>) bsms.item;
         }
     }
-    
+
     private DataInputStream openInput(File f) throws IOException {
         return new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
     }
-    
+
     private DataOutputStream openOutput(File f) throws IOException {
         if (!overwrite && f.exists())
             throw new IOException("file already exists: "+f);
@@ -918,7 +1114,7 @@
             throw new InternalError("wrong size: "+nr);
         return bytes;
     }
-   
+
     private interface Chunk {
         void readFrom(DataInputStream in) throws IOException;
         void writeTo(DataOutputStream out) throws IOException;
@@ -943,7 +1139,7 @@
                     for (int i = 0; i < rowlen; i++)
                         row[i] = readInput(in, elemClass);
                     add(itemClass.cast(row));
-                }        
+                }
             }
         }
         public void writeTo(DataOutputStream out) throws IOException {
@@ -1017,7 +1213,7 @@
     private static void writeOutputs(DataOutputStream out, Object... data) throws IOException {
         for (Object x : data)  writeOutput(out, x);
     }
-    
+
     public static abstract class Outer {
         public abstract List<? extends Inner> inners();
         protected void linkInners() {
@@ -1034,6 +1230,18 @@
                 //if (!(walk instanceof Inner))  return null;
             }
         }
+
+        public abstract List<Attr> attrs();
+        public Attr findAttr(String name) {
+            return findAttr(outer(ClassFile.class).pool.stringIndex(name, false));
+        }
+        public Attr findAttr(int name) {
+            if (name == 0)  return null;
+            for (Attr a : attrs()) {
+                if (a.name == name)  return a;
+            }
+            return null;
+        }
     }
     public interface Inner { Outer outer(); void linkOuter(Outer o); }
     public static abstract class InnerOuter extends Outer implements Inner {
@@ -1063,12 +1271,36 @@
         public void writeTo(DataOutputStream out) throws IOException {
             writeOutputs(out, tag, item);
         }
+        public boolean equals(Object x) { return (x instanceof Constant && equals((Constant)x)); }
+        public boolean equals(Constant that) {
+            return (this.tag == that.tag && this.itemAsComparable().equals(that.itemAsComparable()));
+        }
+        public int hashCode() { return (tag * 31) + this.itemAsComparable().hashCode(); }
+        public Object itemAsComparable() {
+            switch (tag) {
+            case CONSTANT_Double:   return Double.longBitsToDouble((Long)item);
+            case CONSTANT_Float:    return Float.intBitsToFloat((Integer)item);
+            }
+            return (item instanceof Object[] ? Arrays.asList((Object[])item) : item);
+        }
         public String toString() {
-            return index+":"+tag+"="+(item instanceof Object[] ? Arrays.toString((Object[])item) : item.toString());
+            String itstr = String.valueOf(itemAsComparable());
+            return (index + ":" + tagName(tag) + (itstr.startsWith("[")?"":"=") + itstr);
+        }
+        private static String[] TAG_NAMES;
+        public static String tagName(byte tag) {  // used for error messages
+            if (TAG_NAMES == null)
+                TAG_NAMES = ("None Utf8 Unicode Integer Float Long Double Class String"
+                             +" Fieldref Methodref InterfaceMethodref NameAndType #13 #14"
+                             +" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").split(" ");
+            if ((tag & 0xFF) >= TAG_NAMES.length)  return "#"+(tag & 0xFF);
+            return TAG_NAMES[tag & 0xFF];
         }
     }
 
     public static class Pool extends CountedList<Constant> implements Chunk {
+        private Map<String,Short> strings = new TreeMap<>();
+
         public Pool() {
             super(Constant.class);
         }
@@ -1079,12 +1311,12 @@
                 readConstant(in);
             }
         }
-        public void writeTo(DataOutputStream out) throws IOException {
-            super.writeTo(out);
-        }
         public <T> Constant<T> addConstant(byte tag, T item) {
             Constant<T> con = new Constant<>(size(), tag, item);
+            int idx = indexOf(con);
+            if (idx >= 0)  return get(idx);
             add(con);
+            if (tag == CONSTANT_Utf8)  strings.put((String)item, (short) con.index);
             return con;
         }
         private void readConstant(DataInputStream in) throws IOException {
@@ -1093,7 +1325,9 @@
             Object arg;
             switch (tag) {
             case CONSTANT_Utf8:
-                arg = in.readUTF(); break;
+                arg = in.readUTF();
+                strings.put((String) arg, (short) size());
+                break;
             case CONSTANT_Integer:
             case CONSTANT_Float:
                 arg = in.readInt(); break;
@@ -1109,6 +1343,8 @@
             case CONSTANT_Method:
             case CONSTANT_InterfaceMethod:
             case CONSTANT_NameAndType:
+            case CONSTANT_InvokeDynamic_17:
+            case CONSTANT_InvokeDynamic:
                 // read an ordered pair
                 arg = new Short[] { in.readShort(), in.readShort() };
                 break;
@@ -1118,19 +1354,6 @@
                 break;
             case CONSTANT_MethodType:
                 arg = in.readShort(); break;
-            case CONSTANT_InvokeDynamic_17:
-                arg = in.readInt(); break;
-            case CONSTANT_InvokeDynamic:
-            {
-                ArrayList<Object> indy = new ArrayList<>();
-                indy.add(in.readInt());  // <BSM:N&T>
-                short bsmac = in.readShort();
-                indy.add(bsmac);
-                for (int i = 0; i < bsmac; i++)
-                    indy.add(in.read());
-                add(new Constant(index, tag, indy.toArray()));
-                return;
-            }
             default:
                 throw new InternalError("bad CP tag "+tag);
             }
@@ -1158,6 +1381,12 @@
                 res[i] = getString(indexes[i]);
             return res;
         }
+        int stringIndex(String name, boolean createIfNotFound) {
+            Short x = strings.get(name);
+            if (x != null)  return (char)(int) x;
+            if (!createIfNotFound)  return 0;
+            return addConstant(CONSTANT_Utf8, name).index;
+        }
         Short[] getMemberRef(short index) {
             Short[] cls_nnt = get(index).itemIndexes();
             Short[] name_type = get(cls_nnt[1]).itemIndexes();
@@ -1174,7 +1403,7 @@
                 if (in != null)  in.close();
             }
         }
-        
+
         public int                magic, version;  // <min:maj>
         public final Pool         pool       = new Pool();
         public short              access, thisc, superc;
@@ -1187,13 +1416,13 @@
             magic = in.readInt(); version = in.readInt();
             if (magic != 0xCAFEBABE)  throw new IOException("bad magic number");
             pool.readFrom(in);
+            Code_index = pool.stringIndex("Code", false);
             access = in.readShort(); thisc = in.readShort(); superc = in.readShort();
             readInputs(in, interfaces, fields, methods, attrs);
             if (in.read() >= 0)  throw new IOException("junk after end of file");
-            recordUtf8s();
             linkInners();
         }
-        
+
         void writeTo(File f) throws IOException {
             DataOutputStream out = openOutput(f);
             try {
@@ -1218,47 +1447,17 @@
                 throw new InternalError();
             }
         }
-        
+
         public List<Inner> inners() {
             List<Inner> inns = new ArrayList<>();
             inns.addAll(fields); inns.addAll(methods); inns.addAll(attrs);
             return inns;
         }
+        public List<Attr> attrs() { return attrs; }
 
         // derived stuff:
-        public String classname() { return pool.getString(CONSTANT_Class, thisc); }
+        public String nameString() { return pool.getString(CONSTANT_Class, thisc); }
         int Code_index;
-
-        private Map<String,Short> cpoolUTF8 = new TreeMap<>();
-        private void recordUtf8s() {
-            int cpindex = -1;
-            for (Constant c : pool) {
-                ++cpindex;
-                if (c != null && c.tag == CONSTANT_Utf8) {
-                    cpoolUTF8.put(c.itemString(), (short) cpindex);
-                }
-            }
-            Code_index = cpoolUTF8("Code");
-        }
-
-        //FIXME
-        int cpoolUTF8(String name) {
-            Short x = cpoolUTF8.get(name);
-            return (x == null ? 0 : (char)(int) x);
-        }
-    }
-
-    private static Attr findAttribute(List<Attr> attrs, String name) {
-        if (attrs.isEmpty())  return null;
-        ClassFile cf = attrs.get(0).outer(ClassFile.class);
-        return findAttribute(attrs, cf.cpoolUTF8(name));
-    }
-    private static Attr findAttribute(List<Attr> attrs, int name) {
-        if (name == 0)  return null;
-        for (Attr a : attrs) {
-            if (a.name == name)  return a;
-        }
-        return null;
     }
 
     private static <T extends Member> T findMember(List<T> mems, int name, int type) {
@@ -1280,20 +1479,21 @@
             writeOutputs(out, access, name, type, attrs);
         }
         public List<Attr> inners() { return attrs; }
+        public List<Attr> attrs() { return attrs; }
         public ClassFile outer() { return (ClassFile) outer; }
+        public String nameString() { return outer().pool.getString(CONSTANT_Utf8, name); }
+        public String typeString() { return outer().pool.getString(CONSTANT_Utf8, type); }
         public String toString() {
             if (outer == null)  return super.toString();
-            Pool pool = outer().pool;
-            return (pool.getString(CONSTANT_Utf8, name) +
-                    (this instanceof Method? "" : ":") +
-                    simplifyType(pool.getString(CONSTANT_Utf8, type)));
+            return nameString() + (this instanceof Method ? "" : ":")
+                    + simplifyType(typeString());
         }
     }
     public static class Field extends Member {
     }
     public static class Method extends Member {
         public Code code() {
-            Attr a = findAttribute(attrs, "Code");
+            Attr a = findAttr("Code");
             if (a == null)  return null;
             return (Code) a.item;
         }
@@ -1306,8 +1506,17 @@
 
     public static class Attr extends InnerOuter implements Chunk {
         public short name;
-        public int size;
+        public int size = -1;  // no pre-declared size
         public Object item;
+
+        public Attr() {}
+        public Attr(Outer outer, String name, Object item) {
+            ClassFile cf = outer.outer(ClassFile.class);
+            linkOuter(outer);
+            this.name = (short) cf.pool.stringIndex(name, true);
+            this.item = item;
+            outer.attrs().add(this);
+        }
         public void readFrom(DataInputStream in) throws IOException {
             name = in.readShort();
             size = in.readInt();
@@ -1324,6 +1533,7 @@
                 out.write(bytes);
             } else {
                 trueSize = flatten(out);
+                //if (!(item instanceof Code))  System.err.println("wrote complex attr name="+(int)(char)name+" size="+trueSize+" data="+Arrays.toString(flatten()));
             }
             if (trueSize != size && size >= 0)
                 System.err.println("warning: attribute size changed "+size+" to "+trueSize);
@@ -1341,13 +1551,14 @@
                 return Collections.nCopies(1, (Inner)item);
             return Collections.emptyList();
         }
+        public List<Attr> attrs() { return null; }  // Code overrides this
         public byte[] flatten() {
-            ByteArrayOutputStream buf = new ByteArrayOutputStream(size);
+            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
             flatten(buf);
             return buf.toByteArray();
         }
         public int flatten(DataOutputStream out) throws IOException {
-            ByteArrayOutputStream buf = new ByteArrayOutputStream(size);
+            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
             int trueSize = flatten(buf);
             out.writeInt(trueSize);
             buf.writeTo(out);
@@ -1361,8 +1572,16 @@
                 throw new InternalError();
             }
         }
+        public String nameString() {
+            ClassFile cf = outer(ClassFile.class);
+            if (cf == null)  return "#"+name;
+            return cf.pool.getString(name);
+        }
+        public String toString() {
+            return nameString()+(size < 0 ? "=" : "["+size+"]=")+item;
+        }
     }
-    
+
     public static class Code extends InnerOuter implements Chunk {
         public short stacks, locals;
         public byte[] bytes;
@@ -1378,6 +1597,7 @@
             writeOutputs(out, stacks, locals, bytes.length, bytes, etable, attrs);
         }
         public List<Attr> inners() { return attrs; }
+        public List<Attr> attrs() { return attrs; }
         public Instruction instructions() {
             return new Instruction(bytes, 0);
         }
@@ -1414,9 +1634,8 @@
     private static final int
         opc_nop                    = 0,
         opc_aconst_null            = 1,
-        opc_iconst_MIN             = 2,
-        opc_iconst_0               = 3,
-        opc_iconst_MAX             = 8,
+        opc_nconst_MIN             = 2,  // iconst_m1
+        opc_nconst_MAX             = 15, // dconst_1
         opc_bipush                 = 16,
         opc_sipush                 = 17,
         opc_ldc                    = 18,
@@ -1451,12 +1670,17 @@
         opc_invokestatic           = 184,
         opc_invokeinterface        = 185,
         opc_invokedynamic          = 186,
+        opc_new                    = 187,
         opc_anewarray              = 189,
         opc_checkcast              = 192,
         opc_ifnull                 = 198,
         opc_ifnonnull              = 199,
         opc_wide                   = 196;
 
+    private static final Object[] INSTRUCTION_CONSTANTS = {
+        -1, 0, 1, 2, 3, 4, 5, 0L, 1L, 0.0F, 1.0F, 2.0F, 0.0D, 1.0D
+    };
+
     private static final String INSTRUCTION_FORMATS =
         "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
         "iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
@@ -1548,7 +1772,7 @@
         INSTRUCTION_NAMES = names;
         INSTRUCTION_POPS = pops;
     }
-    
+
     public static class Instruction implements Cloneable {
         byte[] codeBase;
         int pc;
--- a/netbeans/meth/nbproject/build-impl.xml	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/meth/nbproject/build-impl.xml	Tue Jan 04 22:58:40 2011 -0800
@@ -219,6 +219,7 @@
             <length length="0" string="${endorsed.classpath}" when="greater"/>
         </condition>
         <property name="jar.index" value="false"/>
+        <property name="jar.index.metainf" value="${jar.index}"/>
         <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
     </target>
     <target name="-post-init">
@@ -377,6 +378,7 @@
                     <formatter type="brief" usefile="false"/>
                     <formatter type="xml"/>
                     <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <jvmarg value="-ea"/>
                     <jvmarg line="${run.jvmargs}"/>
                 </junit>
             </sequential>
@@ -525,6 +527,7 @@
     </target>
     <target name="-init-macrodef-copylibs">
         <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${manifest.file}" name="manifest"/>
             <element name="customize" optional="true"/>
             <sequential>
                 <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
@@ -540,7 +543,7 @@
                     </chainedmapper>
                 </pathconvert>
                 <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
-                <copylibs compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+                <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
                     <fileset dir="${build.classes.dir}"/>
                     <manifest>
                         <attribute name="Class-Path" value="${jar.classpath}"/>
--- a/netbeans/meth/nbproject/genfiles.properties	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/meth/nbproject/genfiles.properties	Tue Jan 04 22:58:40 2011 -0800
@@ -1,5 +1,5 @@
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
 nbproject/build-impl.xml.data.CRC32=a09bc78f
-nbproject/build-impl.xml.script.CRC32=27e568d3
-nbproject/build-impl.xml.stylesheet.CRC32=fce8b508@1.40.0.45
+nbproject/build-impl.xml.script.CRC32=158bc400
+nbproject/build-impl.xml.stylesheet.CRC32=f35869c8@1.41.0.45
--- a/netbeans/meth/nbproject/project.properties	Mon Nov 22 14:07:44 2010 -0800
+++ b/netbeans/meth/nbproject/project.properties	Tue Jan 04 22:58:40 2011 -0800
@@ -1,3 +1,6 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.run.all.processors=true
 #
 # Some of these probably need to be pre-defined, in ../build.properties:
 #
@@ -7,6 +10,8 @@
 
 # e.g., ln -s ...davinci/sources/build/bsd-i586/j2sdk-image ~/env/JAVA7X_HOME
 file.reference.env-folder=${user.home}/env
+javac.processorpath=\
+    ${javac.classpath}
   libs.junit_4.classpath=${file.reference.env-folder}/JUNIT4_JAR
   platforms.JDK_7X.home=${file.reference.env-folder}/JAVA7X_HOME
 
@@ -47,7 +52,7 @@
 #file.reference.bsd-i586-classes=../davinci/sources/build/bsd-i586/classes
 file.reference.test-classes=build/test/classes
 file.reference.jdk-tests=${file.reference.davinci-project-folder.sources.jdk}/test
-includes=java/dyn/**,jdk/java/dyn/**,sun/dyn/**,test/java/dyn/**
+includes=java/dyn/**,jdk/java/dyn/**,sun/dyn/**,test/java/dyn/**/*.java
 #includes=**
 jar.compress=true
 javac.classpath=
@@ -99,7 +104,7 @@
 # Space-separated list of JVM arguments used when running the project
 # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
 # or test-sys-prop.name=value to set system properties for unit tests):
-run.jvmargs=-ea -esa ${config.run.jvmargs} -Xbootclasspath/p:"${run.classpath}:${libs.junit_4.classpath}"
+run.jvmargs=-XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -ea -esa ${config.run.jvmargs} -Xbootclasspath/p:"${run.classpath}:${libs.junit_4.classpath}" -Dbuild.test.classes.dir=${build.test.classes.dir}
 #manual hack: override ${config.run.jvmargs} in ${config}.properties
 config.run.jvmargs=-XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles
 run.test.classpath=\