changeset 9536:e233d4d68878

Merge
author mduigou
date Wed, 14 Aug 2013 15:53:13 -0700
parents e0f6039c0290 0abc86164e40
children 068c47d1d7d2
files .hgtags .jcheck/conf makefiles/CompileNativeLibraries.gmk src/share/classes/java/beans/EventHandler.java src/share/classes/java/lang/invoke/LambdaConversionException.java src/share/classes/java/nio/file/Files.java src/share/classes/java/util/Collections.java src/share/classes/java/util/Comparator.java src/share/classes/java/util/Comparators.java src/share/classes/java/util/DoubleSummaryStatistics.java src/share/classes/java/util/HashMap.java src/share/classes/java/util/Hashtable.java src/share/classes/java/util/IdentityHashMap.java src/share/classes/java/util/IntSummaryStatistics.java src/share/classes/java/util/List.java src/share/classes/java/util/LongSummaryStatistics.java src/share/classes/java/util/Map.java src/share/classes/java/util/Optional.java src/share/classes/java/util/PriorityQueue.java src/share/classes/java/util/Queue.java src/share/classes/java/util/Random.java src/share/classes/java/util/StringJoiner.java src/share/classes/java/util/TreeMap.java src/share/classes/java/util/Vector.java src/share/classes/java/util/WeakHashMap.java src/share/classes/java/util/concurrent/AbstractExecutorService.java src/share/classes/java/util/concurrent/CompletableFuture.java src/share/classes/java/util/concurrent/CompletionStage.java src/share/classes/java/util/concurrent/ConcurrentHashMap.java src/share/classes/java/util/concurrent/ExecutorService.java src/share/classes/java/util/concurrent/Executors.java src/share/classes/java/util/concurrent/ForkJoinPool.java src/share/classes/java/util/concurrent/ForkJoinTask.java src/share/classes/java/util/concurrent/ScheduledExecutorService.java src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java src/share/classes/java/util/concurrent/TimeUnit.java src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java src/share/classes/java/util/function/BiConsumer.java src/share/classes/java/util/function/BiFunction.java src/share/classes/java/util/function/BiPredicate.java src/share/classes/java/util/function/BinaryOperator.java src/share/classes/java/util/function/BooleanSupplier.java src/share/classes/java/util/function/Consumer.java src/share/classes/java/util/function/DoubleBinaryOperator.java src/share/classes/java/util/function/DoubleConsumer.java src/share/classes/java/util/function/DoubleFunction.java src/share/classes/java/util/function/DoublePredicate.java src/share/classes/java/util/function/DoubleSupplier.java src/share/classes/java/util/function/DoubleToIntFunction.java src/share/classes/java/util/function/DoubleToLongFunction.java src/share/classes/java/util/function/DoubleUnaryOperator.java src/share/classes/java/util/function/Function.java src/share/classes/java/util/function/IntBinaryOperator.java src/share/classes/java/util/function/IntConsumer.java src/share/classes/java/util/function/IntFunction.java src/share/classes/java/util/function/IntPredicate.java src/share/classes/java/util/function/IntSupplier.java src/share/classes/java/util/function/IntToDoubleFunction.java src/share/classes/java/util/function/IntToLongFunction.java src/share/classes/java/util/function/IntUnaryOperator.java src/share/classes/java/util/function/LongBinaryOperator.java src/share/classes/java/util/function/LongConsumer.java src/share/classes/java/util/function/LongFunction.java src/share/classes/java/util/function/LongPredicate.java src/share/classes/java/util/function/LongSupplier.java src/share/classes/java/util/function/LongToDoubleFunction.java src/share/classes/java/util/function/LongToIntFunction.java src/share/classes/java/util/function/LongUnaryOperator.java src/share/classes/java/util/function/ObjDoubleConsumer.java src/share/classes/java/util/function/ObjIntConsumer.java src/share/classes/java/util/function/ObjLongConsumer.java src/share/classes/java/util/function/Predicate.java src/share/classes/java/util/function/Supplier.java src/share/classes/java/util/function/ToDoubleBiFunction.java src/share/classes/java/util/function/ToDoubleFunction.java src/share/classes/java/util/function/ToIntBiFunction.java src/share/classes/java/util/function/ToIntFunction.java src/share/classes/java/util/function/ToLongBiFunction.java src/share/classes/java/util/function/ToLongFunction.java src/share/classes/java/util/function/UnaryOperator.java src/share/classes/java/util/function/package-info.java src/share/classes/java/util/jar/JarFile.java src/share/classes/java/util/stream/AbstractPipeline.java src/share/classes/java/util/stream/AbstractShortCircuitTask.java src/share/classes/java/util/stream/AbstractTask.java src/share/classes/java/util/stream/CloseableStream.java src/share/classes/java/util/stream/Collector.java src/share/classes/java/util/stream/Collectors.java src/share/classes/java/util/stream/DelegatingStream.java src/share/classes/java/util/stream/DoublePipeline.java src/share/classes/java/util/stream/DoubleStream.java src/share/classes/java/util/stream/FindOps.java src/share/classes/java/util/stream/ForEachOps.java src/share/classes/java/util/stream/IntPipeline.java src/share/classes/java/util/stream/IntStream.java src/share/classes/java/util/stream/LongPipeline.java src/share/classes/java/util/stream/LongStream.java src/share/classes/java/util/stream/MatchOps.java src/share/classes/java/util/stream/Nodes.java src/share/classes/java/util/stream/ReduceOps.java src/share/classes/java/util/stream/ReferencePipeline.java src/share/classes/java/util/stream/Sink.java src/share/classes/java/util/stream/SliceOps.java src/share/classes/java/util/stream/SortedOps.java src/share/classes/java/util/stream/SpinedBuffer.java src/share/classes/java/util/stream/Stream.java src/share/classes/java/util/stream/StreamSpliterators.java src/share/classes/java/util/stream/StreamSupport.java src/share/classes/java/util/stream/Streams.java src/share/classes/java/util/stream/package-info.java src/solaris/native/java/lang/java_props_md.c test/Makefile test/ProblemList.txt test/java/util/Random/RandomStreamTest.java test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java test/java/util/StringJoiner/MergeTest.java test/java/util/concurrent/CompletableFuture/Basic.java test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java test/java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java test/java/util/stream/test/org/openjdk/tests/java/util/stream/TabulatorsTest.java
diffstat 205 files changed, 24992 insertions(+), 2140 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Aug 13 10:42:37 2013 -0700
+++ b/.hgignore	Wed Aug 14 15:53:13 2013 -0700
@@ -5,3 +5,19 @@
 ^make/netbeans/.*/dist/
 ^.hgtip
 .DS_Store
+^test-ng/gen-separate/
+^test-ng/lib/
+^.idea/
+^combo-tests/gen/
+^combo-tests/build/
+^out/
+.*\.rej$
+.*\.orig$
+.*\.iml$
+.*~$
+^webrev/
+webrev.zip$
+^.classpath
+^.project
+JTreport
+JTwork
--- a/.hgtags	Tue Aug 13 10:42:37 2013 -0700
+++ b/.hgtags	Wed Aug 14 15:53:13 2013 -0700
@@ -167,16 +167,20 @@
 b3246687c3695dff6f461bb407f9db88f7d072e7 jdk8-b43
 db471a7af03168e4441c245b1d9976f720a7cb77 jdk8-b44
 b92353a01aa049bc508fc56f0347d5934b7c4390 jdk8-b45
+077225955d5722f0fbd780650178c5931693c07e lambda-b45
 8d2ed9d58453c8049715a72a6d26b6b66b37a94c jdk8-b46
 00b22b23269a57d0bb46c57753be2fe9a9d2c1a3 jdk8-b47
 3e4ab821f46166fcf63e8fe5c8046216003c941f jdk8-b48
+b3b65a3d441e7f39cb68140d2db547704ea0a670 lambda-b48
 51707c3b75c0f521794d9ab425f4e5b2351c70c1 jdk8-b49
 e4bae5c53fca8fcb9393d47fd36a34b9e2e8d4ec jdk8-b50
+958eaa191b79bf79be82979240903199791ed9f7 lambda-b50
 e865efbc71059a414b3b2dd2e0adfcb3d2ab6ff9 jdk8-b51
 e8569a473cee7f4955bd9e76a9bdf6c6a07ced27 jdk8-b52
 2c6933c5106b81a8578b70996fe5b735fb3adb60 jdk8-b53
 70ad0ed1d6cef0e7712690d1bab21e4769708aad jdk8-b54
 1f3f4b333341873f00da3dee85e4879f0e89c9bb jdk8-b55
+2e6170973d921fe4b8d2dfd6032f5aaf4150a542 lambda-b56
 2e9eeef2909b33c9224a024afddb61ccb0b77f14 jdk8-b56
 51594d095a4bcffac4a314bf6e148214501399e0 jdk8-b57
 d94613ac03d8de375ef60493e2bb76dbd30d875d jdk8-b58
--- a/.jcheck/conf	Tue Aug 13 10:42:37 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-project=jdk8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/build.xml	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="jdk" default="test">
+
+    <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"/>
+    <property name="lib.dir" location="lib" />
+    <property name="test.pattern" value="*Test" />
+    <property name="lambda.metafactory" value="" />
+    <property name="combo.debug" value="" />
+    <property name="heap.size" value="4G" />
+
+    <property name="lib.testng.jar" value="${lib.dir}/testng-6.7.jar"/>
+    <property name="lib.tools.jar" value="${java.home}/../lib/tools.jar"/>
+
+    <path id="test.class.path">
+        <pathelement path="${sun.boot.class.path}" />
+        <pathelement location="${test.classes.dir}" />
+        <pathelement location="${lib.testng.jar}"/>
+        <pathelement location="${lib.tools.jar}"/>
+    </path>
+
+    <taskdef name="testng" classpathref="test.class.path" classname="org.testng.TestNGAntTask" />
+
+    <target name="prepare">
+        <mkdir dir="${build.dir}"/>
+        <mkdir dir="${lib.dir}"/>
+        <mkdir dir="${test.classes.dir}"/>
+        <mkdir dir="${test.reports.dir}"/>
+    </target>
+
+    <target name="test-compile" depends="prepare">
+        <javac destdir="${test.classes.dir}" debug="on" srcdir="${test.src.dir}" fork="true"
+               classpathref="test.class.path">
+            <compilerarg value="-XDlambdaToMethod"/>
+        </javac>
+    </target>
+
+    <target name="test" depends="test-compile" >
+        <delete dir="${gen.dir}" />
+        <testng outputdir="${test.reports.dir}" usedefaultlisteners="false"
+                listeners="org.testng.reporters.FailedReporter,org.testng.reporters.XMLReporter">
+            <classpath refid="test.class.path" />
+            <classfileset dir="${test.classes.dir}" includes="**/${test.pattern}.class"/>
+            <jvmarg value="-Xms1G" />
+            <jvmarg value="-Xmx${heap.size}" />
+            <jvmarg value="-XX:+UseNUMA" />
+            <jvmarg value="-XX:+UseG1GC" />
+            <jvmarg value="-ea" />
+            <jvmarg value="-esa" />
+            <jvmarg value="-Xverify:all" />
+            <sysproperty key="lambda.metafactory" value="${lambda.metafactory}" />
+            <sysproperty key="combo.debug" value="${combo.debug}" />
+        </testng>
+    </target>
+   
+    <!-- New target added that uses a different set of listeners to show results in Aurora --> 
+    <target name="aurora-test" depends="test-compile" >
+        <testng outputdir="${test.reports.dir}" usedefaultlisteners="false"
+                listeners="org.testng.reporters.JUnitXMLReporter,org.testng.reporters.JUnitReportReporter,
+                           org.testng.reporters.XMLReporter">
+            <classpath refid="test.class.path" />
+            <classfileset dir="${test.classes.dir}" includes="**/${test.pattern}.class"/>
+            <jvmarg value="-Xms1G" />
+            <jvmarg value="-Xmx2G" />
+            <jvmarg value="-XX:+UseNUMA" />
+            <jvmarg value="-XX:+UseG1GC" />
+            <jvmarg value="-ea" />
+            <jvmarg value="-esa" />
+            <jvmarg value="-Xverify:all" />
+            <sysproperty key="lambda.metafactory" value="${lambda.metafactory}" />
+            <sysproperty key="combo.debug" value="${combo.debug}" />
+        </testng>
+    </target>
+
+    <target name="clean">
+        <delete dir="${build.dir}" />
+        <delete dir="${gen.dir}" />
+    </target>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/BridgeMethodTestCase.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.fail;
+
+/**
+ * BridgeMethodTestCase -- used for asserting linkage to bridges under separate compilation.
+ *
+ * Example test case:
+ *     public void test1() throws IOException, ReflectiveOperationException {
+ *         compileSpec("C(Bc1(A))");
+ *         assertLinkage("C", LINKAGE_ERROR, "B1");
+ *         recompileSpec("C(Bc1(Ac0))", "A");
+ *          assertLinkage("C", "A0", "B1");
+ *     }
+ *
+ * This compiles A, B, and C, asserts that C.m()Object does not exist, asserts
+ * that C.m()Number eventually invokes B.m()Number, recompiles B, and then asserts
+ * that the result of calling C.m()Object now arrives at A.
+ *
+ * @author Brian Goetz
+ */
+
+@Test
+public abstract class BridgeMethodTestCase extends JavacTemplateTestBase {
+
+    private static final String TYPE_LETTERS = "ABCDIJK";
+
+    private static final String BASE_INDEX_CLASS = "class C0 {\n" +
+                                                   "    int val;\n" +
+                                                   "    C0(int val) { this.val = val; }\n" +
+                                                   "    public int getVal() { return val; }\n" +
+                                                   "}\n";
+    
+    private static final String INDEX_CLASS_TEMPLATE = "class C#ID extends C#PREV {\n" +
+                                                       "    C#ID(int val) { super(val); }\n" +
+                                                       "}\n";
+
+
+
+    protected static String LINKAGE_ERROR = "-1";
+
+    private List<File> compileDirs = new ArrayList<>();
+
+    /**
+     * Compile all the classes in a class spec, and put them on the classpath.
+     *
+     * The spec is the specification for a nest of classes, using the following notation
+     * A, B represent abstract classes
+     * C represents a concrete class
+     * I, J, K represent interfaces
+     * Lowercase 'c' following a class means that the method m() is concrete
+     * Lowercase 'a' following a class or interface means that the method m() is abstract
+     * Lowercase 'd' following an interface means that the method m() is default
+     * A number 0, 1, or 2 following the lowercase letter indicates the return type of that method
+     * 0 = Object, 1 = Number, 2 = Integer (these form an inheritance chain so bridges are generated)
+     * A classes supertypes follow its method spec, in parentheses
+     * Examples:
+     *   C(Ia0, Jd0) -- C extends I and J, I has abstract m()Object, J has default m()Object
+     *   Cc1(Ia0) -- C has concrete m()Number, extends I with abstract m()Object
+     * If a type must appear multiple times, its full spec must be in the first occurrence
+     * Example:
+     *   C(I(Kd0), J(K))
+     */
+    protected void compileSpec(String spec) throws IOException {
+        compileSpec(spec, false);
+    }
+
+    protected void compileSpec(String spec, boolean debug) throws IOException {
+        ClassModel cm = new Parser(spec).parseClassModel();
+        for (int i = 0; i <= cm.maxIndex() ; i++) {
+            if (debug) System.out.println(indexClass(i));
+            addSourceFile(String.format("C%d.java", i), new StringTemplate(indexClass(i)));
+        }  
+        for (Map.Entry<String, ClassModel> e : classes(cm).entrySet()) {
+            if (debug) System.out.println(e.getValue().toSource());
+            addSourceFile(e.getKey() + ".java", new StringTemplate(e.getValue().toSource()));
+        }
+        compileDirs.add(compile(true));
+        resetSourceFiles();
+        assertCompileSucceeded();
+    }
+
+    /**
+     * Recompile only a subset of classes in the class spec, as named by names,
+     * and put them on the classpath such that they shadow earlier versions of that class.
+     */
+    protected void recompileSpec(String spec, String... names) throws IOException {
+        List<String> nameList = Arrays.asList(names);
+        ClassModel cm = new Parser(spec).parseClassModel();
+        for (int i = 0; i <= cm.maxIndex() ; i++) {
+            addSourceFile(String.format("C%d.java", i), new StringTemplate(indexClass(i)));
+        }
+        for (Map.Entry<String, ClassModel> e : classes(cm).entrySet())
+            if (nameList.contains(e.getKey()))
+                addSourceFile(e.getKey() + ".java", new StringTemplate(e.getValue().toSource()));
+        compileDirs.add(compile(Arrays.asList(classPaths()), true));
+        resetSourceFiles();
+        assertCompileSucceeded();
+    }
+
+    protected void assertLinkage(String name, String... expected) throws ReflectiveOperationException {
+        for (int i=0; i<expected.length; i++) {
+            String e = expected[i];
+            if (e.equals(LINKAGE_ERROR)) {
+                try {
+                    int actual = invoke(name, i);
+                    fail("Expected linkage error, got" + fromNum(actual));
+                }
+                catch (LinkageError x) {
+                    // success
+                }
+            }
+            else {
+                if (e.length() == 1)
+                    e += "0";
+                int expectedInt = toNum(e);
+                int actual = invoke(name, i);
+                if (expectedInt != actual)
+                    fail(String.format("Expected %s but found %s for %s.m()%d", fromNum(expectedInt), fromNum(actual), name, i));
+            }
+        }
+    }
+
+    private Map<String, ClassModel> classes(ClassModel cm) {
+        HashMap<String, ClassModel> m = new HashMap<>();
+        classesHelper(cm, m);
+        return m;
+    }
+
+    private String indexClass(int index) {
+        if (index == 0) {
+            return BASE_INDEX_CLASS;
+        } else {
+            return INDEX_CLASS_TEMPLATE
+                    .replace("#ID", String.valueOf(index))
+                    .replace("#PREV", String.valueOf(index - 1));
+        }
+    }
+
+    private static String overrideName(int index) {
+        return "C" + index;
+    }
+
+    private void classesHelper(ClassModel cm, Map<String, ClassModel> m) {
+        if (!m.containsKey(cm.name))
+            m.put(cm.name, cm);
+        for (ClassModel s : cm.supertypes)
+            classesHelper(s, m);
+    }
+
+    private static String fromNum(int num) {
+        return String.format("%c%d", TYPE_LETTERS.charAt(num / 10), num % 10);
+    }
+
+    private static int toNum(String name, int index) {
+        return 10*(TYPE_LETTERS.indexOf(name.charAt(0))) + index;
+    }
+
+    private static int toNum(String string) {
+        return 10*(TYPE_LETTERS.indexOf(string.charAt(0))) + Integer.parseInt(string.substring(1, 2));
+    }
+
+    private int invoke(String name, int index) throws ReflectiveOperationException {
+        File[] files = classPaths();
+        Class clazz = loadClass(name, files);
+        Method[] ms = clazz.getMethods();
+        for (Method m : ms) {
+            if (m.getName().equals("m") && m.getReturnType().getName().equals(overrideName(index))) {
+                m.setAccessible(true);
+                Object instance = clazz.newInstance();
+                Object c0 = m.invoke(instance);
+                Method getVal = c0.getClass().getMethod("getVal");
+                getVal.setAccessible(true);
+                return (int)getVal.invoke(c0);
+            }
+        }
+        throw new NoSuchMethodError("cannot find method m()" + index + " in class " + name);
+    }
+
+    private File[] classPaths() {
+        File[] files = new File[compileDirs.size()];
+        for (int i=0; i<files.length; i++)
+            files[files.length - i - 1] = compileDirs.get(i);
+        return files;
+    }
+
+    @BeforeMethod
+    @Override
+    public void reset() {
+        compileDirs.clear();
+        super.reset();
+    }
+
+    private static class ClassModel {
+
+        enum MethodType {
+            ABSTRACT('a'), CONCRETE('c'), DEFAULT('d');
+
+            public final char designator;
+
+            MethodType(char designator) {
+                this.designator = designator;
+            }
+
+            public static MethodType find(char c) {
+                for (MethodType m : values())
+                    if (m.designator == c)
+                        return m;
+                throw new IllegalArgumentException();
+            }
+        }
+
+        private final String name;
+        private final boolean isInterface;
+        private final List<ClassModel> supertypes;
+        private final MethodType methodType;
+        private final int methodIndex;
+
+        private ClassModel(String name,
+                           boolean anInterface,
+                           List<ClassModel> supertypes,
+                           MethodType methodType,
+                           int methodIndex) {
+            this.name = name;
+            isInterface = anInterface;
+            this.supertypes = supertypes;
+            this.methodType = methodType;
+            this.methodIndex = methodIndex;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(name);
+            if (methodType != null) {
+                sb.append(methodType.designator);
+                sb.append(methodIndex);
+            }
+            if (!supertypes.isEmpty()) {
+                sb.append("(");
+                for (int i=0; i<supertypes.size(); i++) {
+                    if (i > 0)
+                        sb.append(",");
+                    sb.append(supertypes.get(i).toString());
+                }
+                sb.append(")");
+            }
+            return sb.toString();
+        }
+
+        int maxIndex() {
+            int maxSoFar = methodIndex;
+            for (ClassModel cm : supertypes) {
+                maxSoFar = Math.max(cm.maxIndex(), maxSoFar);
+            }
+            return maxSoFar;
+        }
+
+        public String toSource() {
+            String extendsClause = "";
+            String implementsClause = "";
+            String methodBody = "";
+            boolean isAbstract = "AB".contains(name);
+
+            for (ClassModel s : supertypes) {
+                if (!s.isInterface) {
+                    extendsClause = String.format("extends %s", s.name);
+                    break;
+                }
+            }
+
+            StringJoiner sj = new StringJoiner(", ");
+            for (ClassModel s : supertypes)
+                if (s.isInterface)
+                    sj.add(s.name);
+            if (sj.length() > 0) {
+                if (isInterface)
+                    implementsClause = "extends " + sj.toString();
+                else
+                implementsClause = "implements " + sj.toString();
+            }
+            if (methodType != null) {
+                switch (methodType) {
+                    case ABSTRACT:
+                        methodBody = String.format("public abstract %s m();", overrideName(methodIndex));
+                        break;
+                    case CONCRETE:
+                        methodBody = String.format("public %s m() { return new %s(%d); };",
+                                overrideName(methodIndex), overrideName(methodIndex), toNum(name, methodIndex));
+                        break;
+                    case DEFAULT:
+                        methodBody = String.format("public default %s m() { return new %s(%d); };",
+                                overrideName(methodIndex), overrideName(methodIndex), toNum(name, methodIndex));
+                        break;
+
+                }
+            }
+
+            return String.format("public %s %s %s %s %s {  %s }", isAbstract ? "abstract" : "",
+                                 isInterface ? "interface" : "class",
+                                 name, extendsClause, implementsClause, methodBody);
+        }
+    }
+
+    private static class Parser {
+        private final String input;
+        private final char[] chars;
+        private int index;
+
+        private Parser(String s) {
+            input = s;
+            chars = s.toCharArray();
+        }
+
+        private char peek() {
+            return index < chars.length ? chars[index] : 0;
+        }
+
+        private boolean peek(String validChars) {
+            return validChars.indexOf(peek()) >= 0;
+        }
+
+        private char advanceIf(String validChars) {
+            if (peek(validChars))
+                return chars[index++];
+            else
+                return 0;
+        }
+
+        private char advanceIfDigit() {
+            return advanceIf("0123456789");
+        }
+
+        private int index() {
+            StringBuilder buf = new StringBuilder();
+            char c = advanceIfDigit();
+            while (c != 0) {
+                buf.append(c);
+                c = advanceIfDigit();
+            }
+            return Integer.valueOf(buf.toString());
+        }
+
+        private char advance() {
+            return chars[index++];
+        }
+
+        private char expect(String validChars) {
+            char c = advanceIf(validChars);
+            if (c == 0)
+                throw new IllegalArgumentException(String.format("Expecting %s at position %d of %s", validChars, index, input));
+            return c;
+        }
+
+        public ClassModel parseClassModel() {
+            List<ClassModel> supers = new ArrayList<>();
+            char name = expect(TYPE_LETTERS);
+            boolean isInterface = "IJK".indexOf(name) >= 0;
+            ClassModel.MethodType methodType = peek(isInterface ? "ad" : "ac") ? ClassModel.MethodType.find(advance()) : null;
+            int methodIndex = 0;
+            if (methodType != null) {
+                methodIndex = index();
+            }
+            if (peek() == '(') {
+                advance();
+                supers.add(parseClassModel());
+                while (peek() == ',') {
+                    advance();
+                    supers.add(parseClassModel());
+                }
+                expect(")");
+            }
+            return new ClassModel(new String(new char[]{ name }), isInterface, supers, methodType, methodIndex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/BridgeMethodsLinearTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.io.IOException;
+
+import org.testng.annotations.Test;
+
+/**
+ * BridgeMethodsLinearTest
+ *
+ * @author Brian Goetz
+ */
+@Test
+public class BridgeMethodsLinearTest extends BridgeMethodTestCase {
+
+    /*
+     * Cc1(A) -> Cc1(Ac0)
+     *
+     * 0*: Inherited from A
+     * 1: Declared in C
+     */
+    public void test1() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc1(A)");
+        assertLinkage("C", LINKAGE_ERROR, "C1");
+        recompileSpec("Cc1(Ac0)", "A");
+        assertLinkage("C", "A0", "C1");
+    }
+
+    /*
+     * Cc1(I) -> Cc1(Id0)
+     *
+     * 0*: Inherited default from I
+     * 1: Declared in C
+     */
+    public void test2() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc1(I)");
+        assertLinkage("C", LINKAGE_ERROR, "C1");
+        recompileSpec("Cc1(Id0)", "I");
+        assertLinkage("C", "I0", "C1");
+    }
+
+    /*
+     * C(Bc1(A)) -> C(Bc1(Ac0))
+     *
+     * 0*: Inherited from A
+     * 1: Inherited from B
+     */
+    public void test3() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Bc1(A))");
+        assertLinkage("C", LINKAGE_ERROR, "B1");
+        recompileSpec("C(Bc1(Ac0))", "A");
+        assertLinkage("C", "A0", "B1");
+    }
+
+    /*
+     * C(B(Ac0)) -> C(Bc1(Ac0))
+     *
+     * 0: Inherited from B (through bridge)
+     * 1: Inherited from B
+     */
+    public void test4() throws IOException, ReflectiveOperationException {
+        compileSpec("C(B(Ac0))");
+        assertLinkage("C", "A0", LINKAGE_ERROR);
+        recompileSpec("C(Bc1(Ac0))", "B");
+        assertLinkage("C", "B1", "B1");
+    }
+
+    /*
+     * C(B(A)) -> C(Bc1(Ac0))
+     *
+     * 0: Inherited from B (through bridge)
+     * 1: Inherited from B
+     */
+    public void test5() throws IOException, ReflectiveOperationException {
+        compileSpec("C(B(A))");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR);
+        recompileSpec("C(Bc1(Ac0))", "A", "B");
+        assertLinkage("C", "B1", "B1");
+    }
+
+    /*
+     * C(Ac1(I)) -> C(Ac1(Id0))
+     *
+     * 0*: Inherited default from I
+     * 1: Inherited from A
+     */
+    public void test6() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac1(I))");
+        assertLinkage("C", LINKAGE_ERROR, "A1");
+        recompileSpec("C(Ac1(Id0))", "I");
+        assertLinkage("C", "I0", "A1");
+    }
+
+    /*
+     * C(A(Id0)) -> C(Ac1(Id0))
+     *
+     * 0: Inherited from A (through bridge)
+     * 1: Inherited from A
+     */
+    public void test7() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0))");
+        assertLinkage("C", "I0", LINKAGE_ERROR);
+        recompileSpec("C(Ac1(Id0))", "A");
+        assertLinkage("C", "A1", "A1");
+    }
+
+    /*
+     * C(A(I)) -> C(Ac1(Id0))
+     *
+     * 0*: Inherited from A (through bridge)
+     * 1*: Inherited from A
+     */
+    public void test8() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(I))");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR);
+        recompileSpec("C(Ac1(Id0))", "A", "I");
+        assertLinkage("C", "A1", "A1");
+    }
+
+    /*
+     * C(Id1(J)) -> C(Id1(Jd0))
+     *
+     * 0*: Inherited default from J
+     * 1: Inherited default from I
+     */
+    public void test9() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Id1(J))");
+        assertLinkage("C", LINKAGE_ERROR, "I1");
+        recompileSpec("C(Id1(Jd0))", "J");
+        assertLinkage("C", "J0", "I1");
+    }
+
+    /*
+     * C(I(Jd0)) -> C(Id1(Jd0))
+     *
+     * 0: Inherited default from I (through bridge)
+     * 1: Inherited default from I
+     */
+    public void test10() throws IOException, ReflectiveOperationException {
+        compileSpec("C(I(Jd0))");
+        assertLinkage("C", "J0", LINKAGE_ERROR);
+        recompileSpec("C(Id1(Jd0))", "I");
+        assertLinkage("C", "I1", "I1");
+    }
+
+    /*
+     * C(I(J)) -> C(Id1(Jd0))
+     *
+     * 0: Inherited default from I (through bridge)
+     * 1: Inherited default from I
+     */
+    public void test11() throws IOException, ReflectiveOperationException {
+        compileSpec("C(I(J))");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR);
+        recompileSpec("C(Id1(Jd0))", "I", "J");
+        assertLinkage("C", "I1", "I1");
+    }
+
+    /*
+     * Cc2(B(Ac0)) -> Cc2(Bc1(Ac0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from B
+     * 2: Declared in C
+     */
+    public void test12() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(B(Ac0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Bc1(Ac0))", "B");
+        assertLinkage("C", "C2", "B1", "C2");
+    }
+
+    /*
+     * Cc2(B(Aa0)) -> Cc2(Bc1(Aa0))
+     *
+     * 0: Bridge in C (through bridge)
+     * 1*: Inherited from B
+     * 2: Declared in C
+     */
+    public void test13() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(B(Aa0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Bc1(Aa0))", "B");
+        assertLinkage("C", "C2", "B1", "C2");
+    }
+
+    /*
+     * Cc2(Bc1(A)) -> Cc2(Bc1(Ac0))
+     *
+     * 0*: Inherited from A
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test14() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Bc1(A))");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Bc1(Ac0))", "A");
+        assertLinkage("C", "A0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(Ba1(A)) -> Cc2(Ba1(Ac0))
+     *
+     * 0*: Inherited from A
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test15() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Ba1(A))");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Ba1(Ac0))", "A");
+        assertLinkage("C", "A0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(B(A)) -> Cc2(Bc1(Ac0))
+     *
+     * 0*: Inherited from B (through bridge)
+     * 1*: Inherited from B
+     * 2: Declared in C
+     */
+    public void test16() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(B(A))");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Bc1(Ac0))", "B", "A");
+        assertLinkage("C", "B1", "B1", "C2");
+    }
+
+    /*
+     * Cc2(A(Id0)) -> Cc2(Ac1(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test17() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(Id0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1(Id0))", "A");
+        assertLinkage("C", "C2", "A1", "C2");
+    }
+
+    /*
+     * Cc2(A(Ia0)) -> Cc2(Ac1(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test18() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(Ia0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1(Ia0))", "A");
+        assertLinkage("C", "C2", "A1", "C2");
+    }
+
+    /*
+     * Cc2(Ac1(I)) -> Cc2(Ac1(Id0))
+     *
+     * 0*: Inherited from I
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test19() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Ac1(I))");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Ac1(Id0))", "I");
+        assertLinkage("C", "I0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(Aa1(I)) -> Cc2(Aa1(Id0))
+     *
+     * 0*: Inherited from I
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test20() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Aa1(I))");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Aa1(Id0))", "I");
+        assertLinkage("C", "I0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(A(I)) -> Cc2(Ac1(Id0))
+     *
+     * 0*: Inherited from A (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test21() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(I))");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1(Id0))", "A", "I");
+        assertLinkage("C", "A1", "A1", "C2");
+    }
+
+    /*
+     * Cc2(J(Id0)) -> Cc2(Jd1(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test22() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(J(Id0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Jd1(Id0))", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc2(J(Ia0)) -> Cc2(Jd1(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test23() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(J(Ia0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Jd1(Ia0))", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc2(Jd1(I)) -> Cc2(Jd1(Id0))
+     *
+     * 0*: Inherited default from I
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test24() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Jd1(I))");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Jd1(Id0))", "I");
+        assertLinkage("C", "I0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(Ja1(I)) -> Cc2(Ja1(Id0))
+     *
+     * 0*: Inherited default from I
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test25() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Ja1(I))");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Ja1(Id0))", "I");
+        assertLinkage("C", "I0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(J(I)) -> Cc2(Jd1(Id0))
+     *
+     * 0*: Inherited default from J (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test26() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(J(I))");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Jd1(Id0))", "J", "I");
+        assertLinkage("C", "J1", "J1", "C2");
+    }
+
+    /*
+     * C(Ac1, I) -> C(Ac1, Id0)
+     *
+     * 0*: Inherited default from I
+     * 1: Inherited from A
+     */
+    public void test27() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac1,I)");
+        assertLinkage("C", LINKAGE_ERROR, "A1");
+        recompileSpec("C(Ac1,Id0)", "I");
+        assertLinkage("C", "I0", "A1");
+    }
+
+    /*
+     * C(A, Id0) -> C(Ac1, Id0)
+     *
+     * 0*: Inherited default from I
+     * 1: Inherited from A
+     */
+    public void test28() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A,Id0)");
+        assertLinkage("C", "I0", LINKAGE_ERROR);
+        recompileSpec("C(Ac1,Id0)", "A");
+        assertLinkage("C", "I0", "A1");
+    }
+
+    /*
+     * C(A, I) -> C(Ac1, Id0)
+     *
+     * 0*: Inherited default from I
+     * 1: Inherited from A
+     */
+    public void test29() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A,I)");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR);
+        recompileSpec("C(Ac1,Id0)", "A", "I");
+        assertLinkage("C", "I0", "A1");
+    }
+
+    /*
+     * Cc2(Ac1, I) -> Cc2(Ac1, Id0)
+     *
+     * 0*: Inherited default from I
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test30() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Ac1,I)");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Ac1,Id0)", "I");
+        assertLinkage("C", "I0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(Aa1, I) -> Cc2(Aa1, Id0)
+     *
+     * 0*: Inherited default from I
+     * 1: Declared in C (through bridge)
+     * 2: Declared in C
+     */
+    public void test31() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Aa1,I)");
+        assertLinkage("C", LINKAGE_ERROR, "C2", "C2");
+        recompileSpec("Cc2(Aa1,Id0)", "I");
+        assertLinkage("C", "I0", "C2", "C2");
+    }
+
+    /*
+     * Cc2(A, Id0) -> Cc2(Ac1, Id0)
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test32() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A,Id0)");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1,Id0)", "A");
+        assertLinkage("C", "C2", "A1", "C2");
+    }
+
+    /*
+     * Cc2(A, Ia0) -> Cc2(Ac1, Ia0)
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test33() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A,Ia0)");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1,Ia0)", "A");
+        assertLinkage("C", "C2", "A1", "C2");
+    }
+
+    /*
+     * Cc2(A, I) -> Cc2(Ac1, Id0)
+     *
+     * 0*: Inherited from A
+     * 1*: Inherited default from I
+     * 2: Declared in C
+     */
+    public void test34() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A,I)");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1,Id0)", "A", "I");
+        assertLinkage("C", "I0", "A1", "C2");
+    }
+
+    /*
+     * Cc2(Id0, J) -> Cc2(Id0, Jd1)
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test35() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Id0,J)");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Id0,Jd1)", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc2(Ia0, J) -> Cc2(Ia0, Jd1)
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test36() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(Ia0,J)");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ia0,Jd1)", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc2(I, J) -> Cc2(Id0, Jd1)
+     *
+     * 0*: Inherited default from I
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test37() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(I,J)");
+        assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Id0,Jd1)", "I", "J");
+        assertLinkage("C", "I0", "J1", "C2");
+    }
+
+    /*
+     * C(A(Id0), J(Id0)) -> C(Ac1(Id0), J(Id0))
+     *
+     * 0: Inherited default from I
+     * 0*: Inherited from A (through bridge)
+     * 1*: Inherited from A
+     */
+    public void test38() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0),J(Id0))");
+        assertLinkage("C", "I0", LINKAGE_ERROR);
+        recompileSpec("C(Ac1(Id0),J(Id0))", "A");
+        assertLinkage("C", "A1", "A1");
+    }
+
+    /*
+     * C(A(Id0), J(Id0)) -> C(A(Id0), Jd1(Id0))
+     *
+     * 0: Inherited default from I
+     * 0: Inherited default from J (through bridge)
+     * 1*: Inherited default from J
+     */
+    public void test39() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0),J(Id0))");
+        assertLinkage("C", "I0", LINKAGE_ERROR);
+        recompileSpec("C(A(Id0),Jd1(Id0))", "J");
+        assertLinkage("C", "J1", "J1");
+    }
+
+    /*
+     * C(A(Id0), J(Id0)) -> C(Ac2(Id0), Jd1(Id0))
+     *
+     * 0: Inherited default from I
+     * 0*: Inherited from A (new bridge in A beats new bridge in J)
+     * 1*: Inherited default from J
+     * 2: Inherited from A
+     */
+    public void test40() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0),J(Id0))");
+        assertLinkage("C", "I0", LINKAGE_ERROR);
+        recompileSpec("C(Ac2(Id0),Jd1(Id0))", "A", "J");
+        assertLinkage("C", "A2", "J1", "A2");
+    }
+
+    /*
+     * C(J(Id0), K(Id0)) -> C(Jd1(Id0), K(Id0))
+     *
+     * 0: Inherited from I
+     * 0*: Inherited default from J (through bridge)
+     * 1: Inherited default from J
+     */
+    public void test41() throws IOException, ReflectiveOperationException {
+        compileSpec("C(J(Id0),K(Id0))");
+        assertLinkage("C", "I0", LINKAGE_ERROR);
+        recompileSpec("C(Jd1(Id0),K(Id0))", "J");
+        assertLinkage("C", "J1", "J1");
+    }
+
+    /*
+     * C(Ac2(Id0), J(Id0)) -> C(Ac2(Id0), Jd1(Id0))
+     *
+     * 0: Inherited from A (bridge in A beats new bridge in J)
+     * 1*: Inherited default from J
+     * 2: Inherited from A
+     */
+    public void test42() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac2(Id0),J(Id0))");
+        assertLinkage("C", "A2", LINKAGE_ERROR, "A2");
+        recompileSpec("C(Ac2(Id0),Jd1(Id0))", "J");
+        assertLinkage("C", "A2", "J1", "A2");
+    }
+
+    /*
+     * C(Ac2(Ia0), J(Ia0)) -> C(Ac2(Ia0), Jd1(Ia0))
+     *
+     * 0: Inherited from A (bridge in A beats new bridge in J)
+     * 1*: Inherited default from J
+     * 2: Inherited from A
+     */
+    public void test43() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac2(Ia0),J(Ia0))");
+        assertLinkage("C", "A2", LINKAGE_ERROR, "A2");
+        recompileSpec("C(Ac2(Ia0),Jd1(Ia0))", "J");
+        assertLinkage("C", "A2", "J1", "A2");
+    }
+
+    /*
+     * C(A(Id0), Jd1(Id0)) -> C(Ac2(Id0), Jd1(Id0))
+     *
+     * 0: Inherited from J
+     * 0*: Inherited from A (new bridge in A beats bridge in J)
+     * 1: Inherited default from J
+     * 2*: Inherited from A
+     */
+    public void test44() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0),Jd1(Id0))");
+        assertLinkage("C", "J1", "J1", LINKAGE_ERROR);
+        recompileSpec("C(Ac2(Id0),Jd1(Id0))", "A");
+        assertLinkage("C", "A2", "J1", "A2");
+    }
+
+    /*
+     * C(A(Ia0), Jd1(Ia0)) -> C(Ac2(Ia0), Jd1(Ia0))
+     *
+     * 0: Inherited from J
+     * 0*: Inherited from A (new bridge in A beats bridge in J)
+     * 1: Inherited default from J
+     * 2*: Inherited from A
+     */
+    public void test45() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Ia0),Jd1(Ia0))");
+        assertLinkage("C", "J1", "J1", LINKAGE_ERROR);
+        recompileSpec("C(Ac2(Ia0),Jd1(Ia0))", "A");
+        assertLinkage("C", "A2", "J1", "A2");
+    }
+
+    /*
+     * Cc2(A(Id0), J(Id0)) -> Cc2(Ac1(Id0), J(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test46() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(Id0),J(Id0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1(Id0),J(Id0))", "A");
+        assertLinkage("C", "C2", "A1", "C2");
+    }
+
+    /*
+     * Cc2(A(Ia0), J(Ia0)) -> Cc2(Ac1(Ia0), J(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C
+     */
+    public void test47() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(Ia0),J(Ia0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Ac1(Ia0),J(Ia0))", "A");
+        assertLinkage("C", "C2", "A1", "C2");
+    }
+
+    /*
+     * Cc2(A(Id0), J(Id0)) -> Cc2(A(Id0), Jd1(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test48() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(Id0),J(Id0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(A(Id0),Jd1(Id0))", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc2(A(Ia0), J(Ia0)) -> Cc2(A(Ia0), Jd1(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test49() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(A(Ia0),J(Ia0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(A(Ia0),Jd1(Ia0))", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+
+    /*
+     * Cc3(A(Id0), J(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0))
+     *
+     * 0: Bridge in C
+     * 1*: Inherited from A
+     * 2*: Inherited default from J
+     * 3: Declared in C
+     */
+    public void test50() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(A(Id0),J(Id0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "A", "J");
+        assertLinkage("C", "C3", "A1", "J2", "C3");
+    }
+
+    /*
+     * Cc3(A(Ia0), J(Ia0)) -> Cc3(Ac1(Ia0), Jd2(Ia0))
+     *
+     * 0: Bridge in C
+     * 1*: Inherited from A
+     * 2*: Inherited default from J
+     * 3: Declared in C
+     */
+    public void test51() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(A(Ia0),J(Ia0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "A", "J");
+        assertLinkage("C", "C3", "A1", "J2", "C3");
+    }
+
+    /*
+     * Cc2(J(Id0), K(Id0)) -> Cc2(Jd1(Id0), K(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test52() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(J(Id0),K(Id0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Jd1(Id0),K(Id0))", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc2(J(Ia0), K(Ia0)) -> Cc2(Jd1(Ia0), K(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2: Declared in C
+     */
+    public void test53() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc2(J(Ia0),K(Ia0))");
+        assertLinkage("C", "C2", LINKAGE_ERROR, "C2");
+        recompileSpec("Cc2(Jd1(Ia0),K(Ia0))", "J");
+        assertLinkage("C", "C2", "J1", "C2");
+    }
+
+    /*
+     * Cc3(J(Id0), K(Id0)) -> Cc3(Jd1(Id0), Kd2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2*: Inherited default from K
+     * 3: Declared in C
+     */
+    public void test54() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(J(Id0),K(Id0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "J", "K");
+        assertLinkage("C", "C3", "J1", "K2", "C3");
+    }
+
+    /*
+     * Cc3(J(Ia0), K(Ia0)) -> Cc3(Jd1(Ia0), Kd2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited default from J
+     * 2*: Inherited default from K
+     * 3: Declared in C
+     */
+    public void test55() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(J(Ia0),K(Ia0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "J", "K");
+        assertLinkage("C", "C3", "J1", "K2", "C3");
+    }
+
+    /*
+     * Cc3(Ac1(Id0), J(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from J
+     * 3: Declared in C
+     */
+    public void test56() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Ac1(Id0),J(Id0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "J");
+        assertLinkage("C", "C3", "C3", "J2", "C3");
+    }
+
+    /*
+     * Cc3(Ac1(Ia0), J(Ia0)) -> Cc3(Ac1(Ia0), Jd2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from J
+     * 3: Declared in C
+     */
+    public void test57() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Ac1(Ia0),J(Ia0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "J");
+        assertLinkage("C", "C3", "C3", "J2", "C3");
+    }
+
+    /*
+     * Cc3(Aa1(Id0), J(Id0)) -> Cc3(Aa1(Id0), Jd2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from J
+     * 3: Declared in C
+     */
+    public void test58() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Aa1(Id0),J(Id0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Aa1(Id0),Jd2(Id0))", "J");
+        assertLinkage("C", "C3", "C3", "J2", "C3");
+    }
+
+    /*
+     * Cc3(Aa1(Ia0), J(Ia0)) -> Cc3(Aa1(Ia0), Jd2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from J
+     * 3: Declared in C
+     */
+    public void test59() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Aa1(Ia0),J(Ia0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Aa1(Ia0),Jd2(Ia0))", "J");
+        assertLinkage("C", "C3", "C3", "J2", "C3");
+    }
+
+    /*
+     * Cc3(A(Id0), Jd2(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C (through bridge)
+     * 3: Declared in C
+     */
+    public void test60() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(A(Id0),Jd2(Id0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3");
+        recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "A");
+        assertLinkage("C", "C3", "A1", "C3", "C3");
+    }
+
+    /*
+     * Cc3(A(Im0), Jd2(Ia0)) -> Cc3(Ac1(Im0), Jd2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C (through bridge)
+     * 3: Declared in C
+     */
+    public void test61() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(A(Ia0),Jd2(Ia0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3");
+        recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "A");
+        assertLinkage("C", "C3", "A1", "C3", "C3");
+    }
+
+    /*
+     * Cc3(A(Im0), Ja2(Id0)) -> Cc3(Ac1(Id0), Ja2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C (through bridge)
+     * 3: Declared in C
+     */
+    public void test62() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(A(Id0),Ja2(Id0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3");
+        recompileSpec("Cc3(Ac1(Id0),Ja2(Id0))", "A");
+        assertLinkage("C", "C3", "A1", "C3", "C3");
+    }
+
+    /*
+     * Cc3(A(Im0), Ja2(Ia0)) -> Cc3(Ac1(Ia0), Ja2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1*: Inherited from A
+     * 2: Declared in C (through bridge)
+     * 3: Declared in C
+     */
+    public void test63() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(A(Ia0),Ja2(Ia0))");
+        assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3");
+        recompileSpec("Cc3(Ac1(Ia0),Ja2(Ia0))", "A");
+        assertLinkage("C", "C3", "A1", "C3", "C3");
+    }
+
+    /*
+     * Cc3(Jd1(Id0), K(Id0)) -> Cc3(Jd1(Id0), Kd2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from K
+     * 3: Declared in C
+     */
+    public void test64() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Jd1(Id0),K(Id0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "K");
+        assertLinkage("C", "C3", "C3", "K2", "C3");
+    }
+
+    /*
+     * Cc3(Jd1(Ia0), K(Ia0)) -> Cc3(Jd1(Ia0), Kd2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from K
+     * 3: Declared in C
+     */
+    public void test65() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Jd1(Ia0),K(Ia0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "K");
+        assertLinkage("C", "C3", "C3", "K2", "C3");
+    }
+
+    /*
+     * Cc3(Ja1(Id0), K(Id0)) -> Cc3(Ja1(Id0), Kd2(Id0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from K
+     * 3: Declared in C
+     */
+    public void test66() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Jd1(Id0),K(Id0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "K");
+        assertLinkage("C", "C3", "C3", "K2", "C3");
+    }
+
+    /*
+     * Cc3(Ja1(Ia0), K(Ia0)) -> Cc3(Ja1(Ia0), Kd2(Ia0))
+     *
+     * 0: Declared in C (through bridge)
+     * 1: Declared in C (through bridge)
+     * 2*: Inherited default from K
+     * 3: Declared in C
+     */
+    public void test67() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc3(Jd1(Ia0),K(Ia0))");
+        assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3");
+        recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "K");
+        assertLinkage("C", "C3", "C3", "K2", "C3");
+    }
+
+    // Dan's set A
+    public void testA1() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Id0)");
+        assertLinkage("C", "I0");
+    }
+
+    public void testA2() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0))");
+        assertLinkage("C", "I0");
+    }
+
+    public void testA3() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0),J)");
+        assertLinkage("C", "I0");
+    }
+
+    public void testA4() throws IOException, ReflectiveOperationException {
+        compileSpec("D(C(Id0),Jd0(Id0))");
+        assertLinkage("D", "J0");
+        assertLinkage("C", "I0");
+    }
+    /* Doesn't compile
+    public void testA5() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0),Jd0)");
+        assertLinkage("C", "J0");
+        assertLinkage("A", "I0");
+    }
+    */
+    /* Doesn't compile
+    public void testA6() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(Id0,Jd0))");
+        assertLinkage("C", "J0");
+        assertLinkage("A", "I0");
+    }
+    */
+    /* Doesn't compile
+    public void testA7() throws IOException, ReflectiveOperationException {
+        compileSpec("C(A(I0,Jd0))");
+        assertLinkage("C", "J0");
+        assertLinkage("A", "I0");
+    }
+    */
+    public void testA8() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac0(Id0))");
+        assertLinkage("C", "A0");
+    }
+
+    /* Doesn't compile
+    public void testA9() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac0,Id0)");
+        assertLinkage("C", "A0");
+    }
+    */
+
+    // Dan's set B
+
+    /* B1 can't be done, needs a second concrete class D
+    public void testB1() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc1(Dc0)");
+        assertLinkage("C", "C1", "C1");
+        assertLinkage("D", "A0", LINKAGE_ERROR);
+    }
+    */
+
+    public void testB2() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc1(Ac0)");
+        assertLinkage("C", "C1", "C1");
+    }
+
+    //??? B3 seems to suggest that we should create an abstract class
+    //public void testB3() throws IOException, ReflectiveOperationException {
+    //    compileSpec("Ba1(Cc0)");
+    //    assertLinkage("B", "C0", "A1");
+    //}
+
+    // B4 needs too many classes
+
+    public void testB5() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc1(Aa1(Id0))");
+        assertLinkage("C", "C1", "C1");
+    }
+
+    public void testB6() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Ac1(Id0))");
+        assertLinkage("C", "A1", "A1");
+    }
+
+    public void testB7() throws IOException, ReflectiveOperationException {
+        compileSpec("Cc1(Id0)");
+        assertLinkage("C", "C1", "C1");
+    }
+
+    public void testB8() throws IOException, ReflectiveOperationException {
+        compileSpec("C(Jd1(Id0))");
+        assertLinkage("C", "J1", "J1");
+    }
+
+    // B9 needs too many classes
+
+    // The rest of Dan's tests need generics
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/ComboTestBase.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import com.sun.tools.javac.util.Pair;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.Test;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.*;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * ComboTestBase
+ *
+ * @author Brian Goetz
+ */
+public abstract class ComboTestBase<T extends ComboTestBase<T>> extends JavacTemplateTestBase {
+    private final static Map<Class, ComboTestMetadata> metadataMap = new HashMap<>();
+    private final static boolean DEBUG_PROPERTY_SET = !System.getProperty("combo.debug", "").equals("");
+    private final static long timestamp = System.currentTimeMillis();
+    private final static Map</* filename */ String,
+                             Map</* combo vars */ Map<String, String>, /* data */ Map<String, String>>> debugInfo
+            = new HashMap<>();
+
+    protected final ComboTestMetadata<T> metadata;
+    protected final Object[] comboArgs;
+    private boolean debugOnly = false;
+
+    // This class cannot have a constructor; it interferes with testng's ability to find the factory method
+    //in subclasses.  Anything that would be done by a constructor should insteady be done by init blocks
+    //or the pseudoConstructor() method.
+
+    /* init */ {
+        metadata = getMetadata((Class<T>) getClass());
+        comboArgs = new Object[metadata.dimensions.length];
+    }
+
+    /**
+     * This method is meant to be called from an @Factory method in the subclass, passing its own class literal
+     * as the clazz argument.  It will introspect over the provided class, find the dimension variables, and
+     * generate the combinatorial explosion of test cases.  (It consults shouldSkip() to determine if a particular
+     * combination should be skipped.)
+     */
+    public static<T extends ComboTestBase> Object[] factory(Class<T> clazz) throws ReflectiveOperationException {
+        int index = 0;
+        try {
+            ComboTestMetadata<T> md = getMetadata(clazz);
+            List<T> list = new ArrayList<>();
+            for (Object[] args : md.makeLoop()) {
+                T instance = md.makeInstance(args);
+                if (!instance.shouldSkip()) {
+                    instance.pseudoConstructor(args);
+                    list.add(instance);
+                    instance.templates.put("__INDEX__", instance.new StringTemplate(Integer.toString(index++)));
+                    if (DEBUG_PROPERTY_SET)
+                        ((ComboTestBase) instance).debugOnly = true;
+                }
+            }
+
+            return list.toArray();
+        } catch (Throwable t) {
+            // This is a needed annoyance; TestNG swallows exception data from exceptions thrown from @Factory methods
+            t.printStackTrace(System.err);
+            t.printStackTrace(System.out);
+            throw t;
+        }
+    }
+
+    /** For debugging of test cases -- sets tests into debug-only mode, where we print out the instantiations of
+     * the dimension variables and the templates.
+     */
+    public static<T extends ComboTestBase> Object[] debugFactory(Class<T> clazz) throws ReflectiveOperationException {
+        Object[] results = factory(clazz);
+        for (Object o : results)
+            ((ComboTestBase) o).debugOnly = true;
+        return results;
+    }
+
+    private static<T extends ComboTestBase<T>> ComboTestMetadata<T> getMetadata(Class<T> clazz) {
+        try {
+            ComboTestMetadata<T> md = metadataMap.get(clazz);
+            if (md == null) {
+                md = new ComboTestMetadata<T>(clazz);
+                metadataMap.put(clazz, md);
+            }
+            return md;
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // Should be private, but can't be
+    void pseudoConstructor(Object[] args) throws ReflectiveOperationException {
+        System.arraycopy(args, 0, comboArgs, 0, args.length);
+    }
+
+    private void addTemplates() throws ReflectiveOperationException {
+        for (int i=0; i<comboArgs.length; i++)
+            addTemplate(metadata.dimensions[i].name, asTemplate(comboArgs[i]));
+
+        for (ComboTestMetadata.TemplateMember<TemplateVar, Field> m : metadata.templateFields)
+            addTemplate(m.name, asTemplate(m.member.get(this)));
+
+        for (ComboTestMetadata.TemplateMember<TemplateVar, Method> m : metadata.templateMethods)
+            addTemplate(m.name, asTemplate(m.member.invoke(this)));
+    }
+
+    private void addAllSourceFiles() throws ReflectiveOperationException {
+        for (ComboTestMetadata.TemplateMember<SourceFile, Field> m : metadata.sourceFields)
+            addSourceFile(m.name, asTemplate(m.member.get(this)));
+
+        for (ComboTestMetadata.TemplateMember<SourceFile, Method> m : metadata.sourceMethods)
+            addSourceFile(m.name, asTemplate(m.member.invoke(this)));
+    }
+
+    private void addSourceFiles(String group) throws ReflectiveOperationException {
+        for (ComboTestMetadata.TemplateMember<SourceFile, Field> m : metadata.sourceFields)
+            if (group.equals(m.annotation.group()))
+                addSourceFile(m.name, asTemplate(m.member.get(this)));
+
+        for (ComboTestMetadata.TemplateMember<SourceFile, Method> m : metadata.sourceMethods)
+            if (group.equals(m.annotation.group()))
+                addSourceFile(m.name, asTemplate(m.member.invoke(this)));
+    }
+
+    /**
+     * Should the current combination of inputs be skipped?  Default implementation returns false for
+     * all combinations (indicating all combinations are valid.)
+     */
+    protected boolean shouldSkip() {
+        return false;
+    }
+
+    protected boolean shouldRun() {
+        return false;
+    }
+
+    /**
+     * Called after test() compiles, allowing subclass an opportunity to examine diagonstics and assert
+     * their properties.  Default implementation calls assertCompileSucceeded().
+     * @param group
+     */
+    protected void postCompile(String group) {
+        assertCompileSucceeded();
+    }
+
+    protected String[] getCompileOptions(String group) {
+        return new String[0];
+    }
+
+    /**
+     * Called before test() compiles, allowing subclass an opportunity to set compilation options.
+     */
+    protected void preCompile(String group) {
+    }
+
+    @Test
+    public void test() throws Exception {
+        if (debugOnly) {
+            addTemplates();
+            addAllSourceFiles();
+            System.out.println("Test case : " + getTestCaseDescription());
+            for (Pair<String, Template> e : sourceFiles)
+                System.out.println("Source file " + e.fst + ": " + e.snd);
+
+            String testFile = getClass().getName();
+            Map<Map<String, String>, Map<String, String>> testCaseMap = debugInfo.get(testFile);
+            if (testCaseMap == null) {
+                testCaseMap = new HashMap<>();
+                debugInfo.put(testFile, testCaseMap);
+            }
+
+            Map<String, String> comboKeys = new HashMap<>();
+            for (int i=0; i<metadata.dimensions.length; i++)
+                comboKeys.put(metadata.dimensions[i].name, comboArgs[i].toString());
+            String compileOptions = Arrays.asList(getCompileOptions("")).toString();
+            Map<String, String> data = new HashMap<>();
+            int count = 0;
+            for (Pair<String, Template> e : sourceFiles) {
+                count++;
+                data.put("File." + count + ".FileName", e.fst);
+                data.put("File." + count + ".Source", e.snd.toString());
+                data.put("File." + count + ".Group", "");
+                data.put("File." + count + ".CompileOptions", compileOptions);
+            }
+            Object prev = testCaseMap.put(comboKeys, data);
+            if (prev != null)
+                fail(String.format("Duplicate key for file %s, keys %s", testFile, comboKeys.toString()));
+        }
+        else {
+            boolean generate = shouldRun();
+            boolean errors = false;
+            List<File> files = new ArrayList<>();
+            List<String> groupsReversed = new ArrayList<>(metadata.groups);
+            Collections.reverse(groupsReversed);
+            for (String g : groupsReversed) {
+                addTemplates();
+                addSourceFiles(g);
+                preCompile(g);
+                addCompileOptions(getCompileOptions(g));
+                for (File f : files)
+                    addClassPath(f);
+                files.add(0, compile(generate));
+                errors |= diags.errorsFound();
+                postCompile(g);
+                reset();
+            }
+
+            if (generate && !errors) {
+                run(loadClass("Main", files.toArray(new File[files.size()])));
+            }
+        }
+    }
+
+    @AfterSuite
+    public void dumpDebug() throws IOException {
+        if (DEBUG_PROPERTY_SET) {
+            for (Map.Entry<String, Map<Map<String, String>, Map<String, String>>> f : debugInfo.entrySet()) {
+                File out = new File(String.format("ComboLog-%s-%d.ser", f.getKey(), timestamp));
+                try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(out))) {
+                    os.writeObject(f.getValue());
+                }
+            }
+        }
+    }
+
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        assertTrue(clazz != null);
+    }
+
+    protected String getTestCaseDescription() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("ComboTest[").append(getClass().getName()).append(": ");
+        for (int i=0; i<metadata.dimensions.length; i++)
+            sb.append(metadata.dimensions[i].name).append(" = ").append(comboArgs[i]).append(", ");
+        sb.append("]");
+        return sb.toString();
+    }
+
+    protected boolean skipConstrained(int arity, Enum... enums) {
+        for (int i=arity; i<enums.length; i++)
+            if (enums[i].ordinal() != 0)
+                return true;
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/ComboTestDebug.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * ComboTestDebug -- utility program for dumping or comparing combo test debug logs.  Debug logs can be
+ * used for debugging combo tests, as they contain all the generated source files and options (but are
+ * primarily used for testing for regressions in the combo test framework when changes are made to the
+ * framework.)
+ *
+ * @author Brian Goetz
+ */
+public class ComboTestDebug {
+    public static List<String> files = new ArrayList<>();
+    public static boolean compare;
+
+    private static void compareFiles(String s1, String s2) throws IOException, ClassNotFoundException {
+        Map</* combo vars */ Map<String, String>,
+                /* data */ Map<String, String>> f1, f2;
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s1))) {
+            f1 = (Map<Map<String, String>, Map<String, String>>) ois.readObject();
+        }
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s2))) {
+            f2 = (Map<Map<String, String>, Map<String, String>>) ois.readObject();
+        }
+
+        if (f1.size() != f2.size())
+            System.out.printf("Number of test cases differ: %d, %d%n", f1.size(), f2.size());
+
+        if (!f1.keySet().equals(f2.keySet())) {
+            System.out.printf("Test cases differ%n");
+            for (Map<String, String> k : f1.keySet()) {
+                if (!f2.containsKey(k))
+                    System.out.printf("Only in file 1: test case %s%n", k);
+            }
+            for (Map<String, String> k : f2.keySet()) {
+                if (!f1.containsKey(k))
+                    System.out.printf("Only in file 2: test case %s%n", k);
+            }
+        }
+
+        for (Map<String, String> k : f1.keySet()) {
+            if (!f2.keySet().contains(k))
+                continue;
+            Map<String, String> d1 = f1.get(k);
+            Map<String, String> d2 = f2.get(k);
+            if (!d1.equals(d2)) {
+                System.out.printf("Test case %s%n", k);
+                for (String s : d1.keySet())
+                    if (!d2.containsKey(s))
+                        System.out.printf("  Only in file 1: key %s%n", s);
+                    else {
+                        if (!d1.get(s).equals(d2.get(s))) {
+                            System.out.printf("  Key values differ for key %s: [%s] [%s]%n", s, d1.get(s), d2.get(s));
+                        }
+                    }
+                for (String s : d2.keySet())
+                    if (!d1.containsKey(s))
+                        System.out.printf("  Only in file 2: key %s%n", s);
+                System.out.println();
+            }
+        }
+    }
+
+    private static void dumpFile(String s) throws IOException, ClassNotFoundException {
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s))) {
+            Map</* combo vars */ Map<String, String>,
+                /* data */ Map<String, String>> debugInfo;
+
+            debugInfo = (Map<Map<String, String>, Map<String, String>>) ois.readObject();
+            System.out.printf("%d test cases%n%n", debugInfo.size());
+            for (Map.Entry<Map<String, String>, Map<String, String>> e : debugInfo.entrySet()) {
+                System.out.println("Test case: " + e.getKey());
+                for (Map.Entry<String, String> de : new TreeMap<>(e.getValue()).entrySet())
+                    System.out.printf("  %s = %s%n", de.getKey(), de.getValue());
+                System.out.println();
+            }
+        }
+
+    }
+
+    public static void main(String[] args) throws IOException, ClassNotFoundException {
+        for (String a : args) {
+            if (a.equals("-c"))
+                compare = true;
+            else if (a.startsWith("-"))
+                usage();
+            else
+                files.add(a);
+        }
+
+        if (compare) {
+            if (files.size() != 2)
+                usage();
+            compareFiles(files.get(0), files.get(1));
+        }
+        else {
+            for (String f : files)
+                dumpFile(f);
+        }
+    }
+
+    public static void usage() {
+        System.out.println("Usage: ComboTestDebug [ -c ] files...");
+        System.exit(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/ComboTestMetadata.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.*;
+
+/**
+ * ComboTestMetadata
+ *
+ * @author Brian Goetz*/
+class ComboTestMetadata<T> {
+    public final Class<T> clazz;
+    public final Constructor<T> ctor;
+    public final List<TemplateMember<TemplateVar, Field>> templateFields = new ArrayList<>();
+    public final List<TemplateMember<TemplateVar, Method>> templateMethods = new ArrayList<>();
+    public final List<TemplateMember<SourceFile, Field>> sourceFields = new ArrayList<>();
+    public final List<TemplateMember<SourceFile, Method>> sourceMethods = new ArrayList<>();
+    public final Set<String> groups = new TreeSet<>();
+    public final Dimension[] dimensions;
+
+    public ComboTestMetadata(Class<T> clazz) throws ReflectiveOperationException {
+        this.clazz = clazz;
+        Constructor[] constructors = clazz.getConstructors();
+        ctor = (constructors.length == 1 && constructors[0].getParameterTypes().length > 0) ? constructors[0] : null;
+
+        Map<DimensionVar, Field> tmpDimFields = new LinkedHashMap<>();
+        for (Field f : clazz.getDeclaredFields()) {
+            TemplateVar template = f.getAnnotation(TemplateVar.class);
+            if (template != null) {
+                if (!Template.class.isAssignableFrom(f.getType()) && !String.class.isAssignableFrom(f.getType()))
+                    throw new AssertionError(String.format("Found @TemplateVar on field %s whose type is not Template or String", f));
+                f.setAccessible(true);
+                templateFields.add(new TemplateMember<>(template.value(), template, f));
+            }
+
+            SourceFile source = f.getAnnotation(SourceFile.class);
+            if (source != null) {
+                if (!Template.class.isAssignableFrom(f.getType()) && !String.class.isAssignableFrom(f.getType()))
+                    throw new AssertionError(String.format("Found @SourceFile on field %s whose type is not Template or String", f));
+                f.setAccessible(true);
+                sourceFields.add(new TemplateMember<>(source.value(), source, f));
+                groups.add(source.group());
+            }
+            
+            DimensionVar dim = f.getAnnotation(DimensionVar.class);
+            if (dim != null) 
+                tmpDimFields.put(dim, f);
+        }
+
+        for (Method m : clazz.getDeclaredMethods()) {
+            TemplateVar template = m.getAnnotation(TemplateVar.class);
+            if (template != null) {
+                if (!Template.class.isAssignableFrom(m.getReturnType()) && !String.class.isAssignableFrom(m.getReturnType()))
+                    throw new AssertionError(String.format("Found @TemplateVar on method %s whose return type is not Template or String", m));
+                m.setAccessible(true);
+                templateMethods.add(new TemplateMember<>(template.value(), template, m));
+            }
+
+            SourceFile source = m.getAnnotation(SourceFile.class);
+            if (source != null) {
+                if (!Template.class.isAssignableFrom(m.getReturnType()) && !String.class.isAssignableFrom(m.getReturnType()))
+                    throw new AssertionError(String.format("Found @SourceFile on method %s whose return type is not Template or String ", m));
+                sourceMethods.add(new TemplateMember<>(source.value(), source, m));
+                groups.add(source.group());
+            }
+        }
+
+        if (constructors.length > 1)
+            throw new AssertionError(String.format("Multiple constructors for class %s", clazz));
+        else if (ctor != null && !tmpDimFields.isEmpty())
+            throw new AssertionError(String.format("Class %s has both constructors and fields with @DimensionVar", clazz));
+        else if (constructors.length == 0 && tmpDimFields.isEmpty())
+            throw new AssertionError(String.format("Class %s has neither constructors nor fields with @DimensionVar", clazz));
+        else if (ctor != null) {
+            Class<?>[] argTypes = ctor.getParameterTypes();
+            Annotation[][] paramAnnotations = ctor.getParameterAnnotations();
+            dimensions = new Dimension[argTypes.length];
+            for (int i = 0, argTypesLength = argTypes.length; i < argTypesLength; i++) {
+                DimensionVar cd = null;
+                for (Annotation a : paramAnnotations[i])
+                    if (a instanceof DimensionVar) {
+                        cd = (DimensionVar) a;
+                        break;
+                    }
+                if (cd == null)
+                    throw new AssertionError(String.format("Parameter %d of constructor %s does not have @DimensionVar annotation", i, ctor));
+                dimensions[i] = new Dimension(cd, argTypes[i], String.format("Parameter %d of constructor %s", i, ctor));
+            }
+        }
+        else {
+            dimensions = new Dimension[tmpDimFields.size()];
+            int i = 0;
+            for (Map.Entry<DimensionVar, Field> e : tmpDimFields.entrySet())
+                dimensions[i++] = new Dimension(e.getKey(), e.getValue());
+        }
+    }
+
+    public T makeInstance(Object[] args) throws ReflectiveOperationException {
+        if (ctor != null)
+            return ctor.newInstance(args);
+        else {
+            T t = clazz.newInstance();
+            for (int i=0; i< dimensions.length; i++)
+                dimensions[i].field.set(t, args[i]);
+            return t;
+        }
+    }
+
+    public SyntheticLoop makeLoop() {
+        int n = dimensions.length;
+        Object[][] dimValues = new Object[n][];
+        for (int i=0; i<n; i++)
+            dimValues[i] = dimensions[i].values;
+        return new SyntheticLoop(dimValues);
+    }
+
+    static class Dimension {
+        public final Object[] values;
+        public final String name;
+        public final Field field;
+
+        public Dimension(DimensionVar dv, Field f) throws ReflectiveOperationException {
+            field = f;
+            field.setAccessible(true);
+            name = dv.value();
+            values = getValues(dv, f.getType(), String.format("Field %s", f.getName()));
+        }
+
+        public Dimension(DimensionVar dv, Class<?> paramType, String descr) throws ReflectiveOperationException {
+            field = null;
+            name = dv.value();
+            values = getValues(dv, paramType, descr);
+        }
+
+        private Object[] getValues(DimensionVar dv, Class<?> clazz, String descr) throws ReflectiveOperationException {
+            if (Enum.class.isAssignableFrom(clazz) && Template.class.isAssignableFrom(clazz)) {
+                Method m = clazz.getDeclaredMethod("values");
+                m.setAccessible(true);
+                return (Template[]) m.invoke(null);
+            }
+            else if (int.class.isAssignableFrom(clazz)) {
+                Object[] ts = new Object[dv.rangeUpper() - dv.rangeLower() + 1];
+                for (int i=dv.rangeLower(); i <= dv.rangeUpper(); i++)
+                    ts[i-dv.rangeLower()] = i;
+                return ts;
+            }
+            else
+                throw new AssertionError(String.format("Invalid type %s for %s", clazz.getName(), descr));
+        }
+    }
+
+    static class TemplateMember<A extends Annotation, M extends Member> {
+        public final String name;
+        public final A annotation;
+        public final M member;
+
+        TemplateMember(String name, A annotation, M member) {
+            this.name = name;
+            this.annotation = annotation;
+            this.member = member;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/Diagnostics.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* A container for compiler diagnostics, separated into errors and warnings,
+ * used by JavacTemplateTestBase.
+ *
+ * @author Brian Goetz
+*/
+public class Diagnostics implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+    protected List<String> errors = new ArrayList<>();
+    protected List<String> warnings = new ArrayList<>();
+
+    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+        switch (diagnostic.getKind()) {
+            case ERROR:
+                errors.add(diagnostic.getCode());
+                break;
+
+            case WARNING:
+            case MANDATORY_WARNING:
+                warnings.add(diagnostic.getCode());
+                break;
+        }
+    }
+
+    /** Were there any errors found? */
+    public boolean errorsFound() {
+        return !errors.isEmpty();
+    }
+
+    /** How many errors were found? */
+    public int getErrorCount() {
+        return errors.size();
+    }
+
+    /** Get the error keys */
+    public List<String> errors() {
+        return errors;
+    }
+
+    public String toString() { return errors.toString(); }
+
+    /** Clear all diagnostic state */
+    public void reset() {
+        errors.clear();
+        warnings.clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/DimensionVar.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+* DimensionVar
+*/
+@Retention(RetentionPolicy.RUNTIME)
+@java.lang.annotation.Target({ElementType.PARAMETER, ElementType.FIELD})
+public @interface DimensionVar {
+    String value();
+    int rangeLower() default 0;
+    int rangeUpper() default 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/JavacTemplateTestBase.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.util.Pair;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.fail;
+
+/**
+ * Base class for template-driven TestNG javac tests that support on-the-fly
+ * source file generation, compilation, classloading, execution, and separate
+ * compilation.
+ *
+ * <p>Manages a set of templates (which have embedded tags of the form
+ * {@code #\{NAME\}}), source files (which are also templates), and compile
+ * options.  Test cases can register templates and source files, cause them to
+ * be compiled, validate whether the set of diagnostic messages output by the
+ * compiler is correct, and optionally load and run the compiled classes.
+ *
+ * @author Brian Goetz
+ */
+@Test
+public abstract class JavacTemplateTestBase {
+    private static final Set<String> suiteErrors = Collections.synchronizedSet(new HashSet<>());
+    private static final AtomicInteger counter = new AtomicInteger();
+    private static final File root = new File(System.getProperty("user.dir"), "gen");
+    private static final File nullDir = new File(System.getProperty("user.dir"), "empty");
+
+    protected final Map<String, Template> templates = new HashMap<>();
+    protected final Diagnostics diags = new Diagnostics();
+    protected final List<Pair<String, Template>> sourceFiles = new ArrayList<>();
+    protected final List<String> compileOptions = new ArrayList<>();
+    protected final List<File> classpaths = new ArrayList<>();
+    protected final Template.Resolver defaultResolver = new MapResolver(templates);
+
+    private Template.Resolver currentResolver = defaultResolver;
+
+    /** Add a template with a specified name */
+    protected void addTemplate(String name, Template t) {
+        templates.put(name, t);
+    }
+
+    /** Add a template with a specified name */
+    protected void addTemplate(String name, String s) {
+        templates.put(name, new StringTemplate(s));
+    }
+
+    /** Add a source file */
+    protected void addSourceFile(String name, Template t) {
+        sourceFiles.add(new Pair<>(name, t));
+    }
+
+    /** Add a File to the class path to be used when loading classes; File values
+     * will generally be the result of a previous call to {@link #compile()}.
+     * This enables testing of separate compilation scenarios if the class path
+     * is set up properly.
+     */
+    protected void addClassPath(File path) {
+        classpaths.add(path);
+    }
+
+    /**
+     * Add a set of compilation command-line options
+     */
+    protected void addCompileOptions(String... opts) {
+        Collections.addAll(compileOptions, opts);
+    }
+
+    /** Reset the compile options to the default (empty) value */
+    protected void resetCompileOptions() { compileOptions.clear(); }
+
+    /** Remove all templates */
+    protected void resetTemplates() { templates.clear(); }
+
+    /** Remove accumulated diagnostics */
+    protected void resetDiagnostics() { diags.reset(); }
+
+    /** Remove all source files */
+    protected void resetSourceFiles() { sourceFiles.clear(); }
+
+    /** Remove registered class paths */
+    protected void resetClassPaths() { classpaths.clear(); }
+
+    // Before each test method, reset everything
+    @BeforeMethod
+    public void reset() {
+        resetCompileOptions();
+        resetDiagnostics();
+        resetSourceFiles();
+        resetTemplates();
+        resetClassPaths();
+    }
+
+    // After each test method, if the test failed, capture source files and diagnostics and put them in the log
+    @AfterMethod
+    public void copyErrors(ITestResult result) {
+        if (!result.isSuccess()) {
+            suiteErrors.addAll(diags.errors());
+
+            List<Object> list = new ArrayList<>();
+            Collections.addAll(list, result.getParameters());
+            list.add("Test case: " + getTestCaseDescription());
+            for (Pair<String, Template> e : sourceFiles)
+                list.add("Source file " + e.fst + ": " + e.snd);
+            if (diags.getErrorCount() != 0)
+                list.add("Compile diagnostics: " + diags.toString());
+            result.setParameters(list.toArray(new Object[list.size()]));
+        }
+    }
+
+    @AfterSuite
+    // After the suite is done, dump any errors to output
+    public void dumpErrors() {
+        if (!suiteErrors.isEmpty())
+            System.err.println("Errors found in test suite: " + suiteErrors);
+    }
+
+    /**
+     * Get a description of this test case; since test cases may be combinatorially
+     * generated, this should include all information needed to describe the test case
+     */
+    protected String getTestCaseDescription() {
+        return this.toString();
+    }
+
+    /** Assert that all previous calls to compile() succeeded */
+    protected void assertCompileSucceeded() {
+        if (diags.errorsFound())
+            fail("Expected successful compilation");
+    }
+
+    /**
+     * If the provided boolean is true, assert all previous compiles succeeded,
+     * otherwise assert that a compile failed.
+     * */
+    protected void assertCompileSucceededIff(boolean b) {
+        if (b)
+            assertCompileSucceeded();
+        else
+            assertCompileFailed();
+    }
+
+    /** Assert that a previous call to compile() failed */
+    protected void assertCompileFailed() {
+        if (!diags.errorsFound())
+            fail("Expected failed compilation");
+    }
+
+    /** Assert that a previous call to compile() failed with a specific error key */
+    protected void assertCompileFailed(String message) {
+        if (!diags.errorsFound())
+            fail("Expected failed compilation: " + message);
+    }
+
+    /** Assert that a previous call to compile() failed with all of the specified error keys */
+    protected void assertCompileErrors(String... keys) {
+        if (!diags.errorsFound())
+            fail("Expected failed compilation");
+        for (String k : keys)
+            if (!diags.errors().contains(k))
+                fail("Expected compilation error " + k);
+    }
+
+    /** Convert an object, which may be a Template or a String, into a Template */
+    protected Template asTemplate(Object o) {
+        if (o instanceof Template)
+            return (Template) o;
+        else if (o instanceof String)
+            return new StringTemplate((String) o);
+        else
+            return new StringTemplate(o.toString());
+    }
+
+    /** Compile all registered source files */
+    protected void compile() throws IOException {
+        compile(false);
+    }
+
+    /** Compile all registered source files, optionally generating class files
+     * and returning a File describing the directory to which they were written */
+    protected File compile(boolean generate) throws IOException {
+        List<JavaFileObject> files = new ArrayList<>();
+        for (Pair<String, Template> e : sourceFiles)
+            files.add(new FileAdapter(e.fst, asTemplate(e.snd)));
+        return compile(classpaths, files, generate);
+    }
+
+    /** Compile all registered source files, using the provided list of class paths
+     * for finding required classfiles, optionally generating class files
+     * and returning a File describing the directory to which they were written */
+    protected File compile(List<File> classpaths, boolean generate) throws IOException {
+        List<JavaFileObject> files = new ArrayList<>();
+        for (Pair<String, Template> e : sourceFiles)
+            files.add(new FileAdapter(e.fst, asTemplate(e.snd)));
+        return compile(classpaths, files, generate);
+    }
+
+    private File compile(List<File> classpaths, List<JavaFileObject> files, boolean generate) throws IOException {
+        JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fm = systemJavaCompiler.getStandardFileManager(null, null, null);
+        if (classpaths.size() > 0)
+            fm.setLocation(StandardLocation.CLASS_PATH, classpaths);
+        JavacTask ct = (JavacTask) systemJavaCompiler.getTask(null, fm, diags, compileOptions, null, files);
+        if (generate) {
+            File destDir = new File(root, Integer.toString(counter.incrementAndGet()));
+            // @@@ Assert that this directory didn't exist, or start counter at max+1
+            destDir.mkdirs();
+            fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir));
+            ct.generate();
+            return destDir;
+        }
+        else {
+            ct.analyze();
+            return nullDir;
+        }
+    }
+
+    /** Load the given class using the provided list of class paths */
+    protected Class<?> loadClass(String className, File... destDirs) {
+        try {
+            List<URL> list = new ArrayList<>();
+            for (File f : destDirs)
+                list.add(new URL("file:" + f.toString().replace("\\", "/") + "/"));
+            return Class.forName(className, true, new URLClassLoader(list.toArray(new URL[list.size()])));
+        } catch (ClassNotFoundException | MalformedURLException e) {
+            throw new RuntimeException("Error loading class " + className, e);
+        }
+    }
+
+    /** An implementation of Template which is backed by a String */
+    protected class StringTemplate implements Template {
+        protected final String template;
+
+        public StringTemplate(String template) {
+            this.template = template;
+        }
+
+        public String expand(String selector) {
+            return Behavior.expandTemplate(template, currentResolver);
+        }
+
+        public String toString() {
+            return expand("");
+        }
+
+        public StringTemplate with(final String key, final String value) {
+            return new StringTemplateWithResolver(template, new KeyResolver(key, value));
+        }
+
+    }
+
+    /** An implementation of Template which is backed by a String and which
+     * encapsulates a Resolver for resolving embedded tags. */
+    protected class StringTemplateWithResolver extends StringTemplate {
+        private final Resolver localResolver;
+
+        public StringTemplateWithResolver(String template, Resolver localResolver) {
+            super(template);
+            this.localResolver = localResolver;
+        }
+
+        @Override
+        public String expand(String selector) {
+            Resolver saved = currentResolver;
+            currentResolver = new ChainedResolver(currentResolver, localResolver);
+            try {
+                return super.expand(selector);
+            }
+            finally {
+                currentResolver = saved;
+            }
+        }
+
+        @Override
+        public StringTemplate with(String key, String value) {
+            return new StringTemplateWithResolver(template, new ChainedResolver(localResolver, new KeyResolver(key, value)));
+        }
+    }
+
+    /** A Resolver which uses a Map to resolve tags */
+    private class KeyResolver implements Template.Resolver {
+        private final String key;
+        private final String value;
+
+        public KeyResolver(String key, String value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        @Override
+        public Template lookup(String k) {
+            return key.equals(k) ? new StringTemplate(value) : null;
+        }
+    }
+
+    private class FileAdapter extends SimpleJavaFileObject {
+        private final String filename;
+        private final Template template;
+
+        public FileAdapter(String filename, Template template) {
+            super(URI.create("myfo:/" + filename), Kind.SOURCE);
+            this.template = template;
+            this.filename = filename;
+        }
+
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return toString();
+        }
+
+        public String toString() {
+            return Template.Behavior.expandTemplate(template.expand(filename), defaultResolver);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/SeparateCompilationComboTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import org.testng.annotations.Factory;
+
+import java.lang.reflect.Method;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * SeparateCompilationComboTest
+ */
+public class SeparateCompilationComboTest extends ComboTestBase<SeparateCompilationComboTest> {
+    @Factory
+    public static Object[] testCombo() throws Exception {
+        return factory(SeparateCompilationComboTest.class);
+    }
+
+    @DimensionVar("FOO") Dummy dummy;
+
+    @SourceFile(value="Main.java", group="B") String a2 = "public class Main { public String main() { return Other.b(); } }";
+    @SourceFile(value="Other.java", group="B") String b2 = "public class Other { public static String b() { return \"1\"; } }";
+    @SourceFile(value="Other.java", group="A") String b1 = "public class Other { public static String b() { return \"2\"; } }";
+
+    @Override
+    protected boolean shouldRun() {
+        return true;
+    }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Object obj = clazz.newInstance();
+        Method m = clazz.getMethod("main");
+        String result = (String) m.invoke(obj);
+        assertEquals("2", result);
+    }
+
+    static enum Dummy implements Template {
+        A();
+
+        public String expand(String selector) { return toString(); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/SeparateCompilationComboTest2.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import org.testng.annotations.Factory;
+
+import java.lang.reflect.Method;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * SeparateCompilationComboTest2
+ */
+public class SeparateCompilationComboTest2 extends ComboTestBase<SeparateCompilationComboTest2> {
+    @Factory
+    public static Object[] testCombo() throws Exception {
+        return factory(SeparateCompilationComboTest2.class);
+    }
+
+    @DimensionVar("FOO") Dummy dummy;
+
+    @SourceFile(value="Main.java", group="A" )
+    String main = "public class Main { public String main() { return new B().x(); } }";
+    @SourceFile(value="B.java", group="B" )
+    String b = "public class B extends C { public String x() { return \"2\"; } }";
+    @SourceFile(value="C.java", group="C" )
+    String c = "public class C { public String x() { return \"1\"; } }";
+
+    @Override
+    protected boolean shouldRun() {
+        return true;
+    }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Object obj = clazz.newInstance();
+        Method m = clazz.getMethod("main");
+        String result = (String) m.invoke(obj);
+        assertEquals("2", result);
+    }
+
+    static enum Dummy implements Template {
+        A();
+
+        public String expand(String selector) { return toString(); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/SeparateCompilationTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * SeparateCompilationTest -- test of test framework to do separate compilation
+ */
+@Test
+public class SeparateCompilationTest extends JavacTemplateTestBase {
+
+    public void testCompletelySeparate() throws ReflectiveOperationException, IOException {
+        addSourceFile("A.java", new StringTemplate("public class A { public String a() throws Throwable { return Class.forName(\"B\").getName(); } }"));
+        File aFile = compile(true);
+        assertCompileSucceeded();
+        reset();
+
+        addSourceFile("B.java", new StringTemplate("public class B {  }"));
+        File bFile = compile(true);
+        assertCompileSucceeded();
+
+        Class clazz = loadClass("A", aFile, bFile);
+        Method m = clazz.getMethod("a");
+        Object instance = clazz.newInstance();
+        String x = (String) m.invoke(instance);
+        assertEquals("B", x);
+    }
+
+    public void testIdenticalRecompile() throws ReflectiveOperationException, IOException {
+        addSourceFile("A.java", new StringTemplate("public class A { public String a() { return B.b(); } }"));
+        addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"1\"; } }"));
+        File aFile = compile(true);
+        assertCompileSucceeded();
+        // Deleting B.class is not generally needed for test cases that simply replace B, but here we're testing the framework's ability to find B elsewhere
+        File bClass = new File(aFile, "B.class");
+        assertTrue(bClass.exists());
+        boolean deleted = bClass.delete();
+        assertTrue(deleted);
+        reset();
+
+        addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"1\"; } }"));
+        File bFile = compile(true);
+        assertCompileSucceeded();
+
+        Class clazz = loadClass("A", bFile, aFile);
+        Method m = clazz.getMethod("a");
+        Object instance = clazz.newInstance();
+        String x = (String) m.invoke(instance);
+        assertEquals("1", x);
+    }
+
+    public void testConsistentRecompile() throws ReflectiveOperationException, IOException {
+        addSourceFile("A.java", new StringTemplate("public class A { public String a() { return B.b(); } }"));
+        addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"1\"; } }"));
+        File aFile = compile(true);
+        assertCompileSucceeded();
+        reset();
+
+        addSourceFile("B.java", new StringTemplate("public class B { public static String b() { return \"2\"; } }"));
+        File bFile = compile(true);
+        assertCompileSucceeded();
+
+        Class clazz = loadClass("A", bFile, aFile);
+        Method m = clazz.getMethod("a");
+        Object instance = clazz.newInstance();
+        String x = (String) m.invoke(instance);
+        assertEquals("2", x);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/SourceFile.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * SourceFile
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@java.lang.annotation.Target({ElementType.METHOD, ElementType.FIELD})
+public @interface SourceFile {
+    String value();
+    String group() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/StackProcessingUtils.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package tools.javac.combo;
+
+/**
+ * Utility class for defining stack processing-like operations
+ *
+ * @author Maurizio Cimadamore
+ */
+public class StackProcessingUtils {
+
+    /**
+     * interface representing a stack item - each item has an arity ---
+     * if arity is > 0 - then the item is an operator
+     */
+    public interface StackItem<T extends StackItem<T>> {
+        int arity();
+    }
+
+    /**
+     * A reducer takes an element of the stack and produces a result of a given
+     * type by applying the stack item to zero or more operands
+     */
+    public interface StackReducer<I extends StackItem<I>, T, O> {
+        T reduce(I item, T[] operands, O o);
+        Class<T> resultToken();
+        O reducerArg(I item, int i);
+    }
+
+    static class StackResult<T> {
+        T result;
+        int nextPos;
+
+        StackResult(T result, int nextPos) {
+            this.result = result;
+            this.nextPos = nextPos;
+        }
+    }
+
+    public static <I extends StackItem<I>, T, O> T process(I[] elems, StackReducer<I, T, O> reducer, O o) {
+        StackResult<T> result = processInternal(0, elems, reducer, o);
+        assert result.nextPos == elems.length;
+        return result.result;
+    }
+
+    private static <I extends StackItem<I>, T, O> StackResult<T> processInternal(int start, I[] elems, StackReducer<I, T, O> reducer, O o) {
+        @SuppressWarnings("unchecked")
+        I head = elems[start];
+        T[] operands = (T[])java.lang.reflect.Array.newInstance(reducer.resultToken(), head.arity());
+        int nextPos = start + 1;
+        for (int i = 0 ; i < head.arity() ; i++) {
+            StackResult<T> partialResult = processInternal(nextPos, elems, reducer, reducer.reducerArg(head, i));
+            nextPos = partialResult.nextPos;
+            operands[i] = partialResult.result;
+        }
+        return new StackResult<T>(reducer.reduce(head, operands, o), nextPos);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/StringTemplateTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * StringTemplateTest
+ */
+@Test
+public class StringTemplateTest extends JavacTemplateTestBase {
+    private void assertTemplate(String expected, Template template) {
+        String result = template.expand("");
+        assertEquals(result, expected, "for " + template);
+    }
+
+    public void testStringTemplate() {
+        assertTemplate("XYZ", new StringTemplate("XYZ"));
+        addTemplate("NONE", "SOME");
+        assertTemplate("SOME", new StringTemplate("#{NONE}"));
+
+        addTemplate("A", "#{B}");
+        addTemplate("B", "C");
+        assertTemplate("C", new StringTemplate("#{A}"));
+    }
+
+    public void testChainedTemplate() {
+        assertTemplate("A", new StringTemplate("#{A}").with("A", "A"));
+        assertTemplate("AB", new StringTemplate("#{A}#{B}").with("A", "A").with("B", "B"));
+        assertTemplate("TWO", new StringTemplate("#{A}").with("A", "ONE").with("A", "TWO"));
+        addTemplate("A", "BASE_A");
+        addTemplate("AA", "#{A}");
+        assertTemplate("FAKE_A", new StringTemplate("#{A}").with("A", "FAKE_A"));
+        assertTemplate("BASE_A", new StringTemplate("#{AA}"));
+        assertTemplate("FAKE_A", new StringTemplate("#{AA}").with("A", "FAKE_A"));
+
+        addTemplate("X", new StringTemplate("#{A}").with("A", "intercepted"));
+        assertTemplate("intercepted", new StringTemplate("#{B}").with("B", "#{X}"));
+        addTemplate("Y", new StringTemplate("#{A}"));
+        assertTemplate("again", new StringTemplate("#{B}").with("B", "#{Y}").with("A", "again"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/SyntheticLoop.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.util.Iterator;
+
+/**
+ * SyntheticLoop -- exhaustively generate a set of combinations of variables
+ *
+ * @author Brian Goetz
+ */
+public class SyntheticLoop implements Iterable<Object[]> {
+    final int dimensions;
+    final int[] maxs;
+    final Object[][] values;
+
+    /** Simple version -- generate the cartesian product of the provided sets of axis values */
+    public SyntheticLoop(Object[][] dimValues) {
+        dimensions = dimValues.length;
+        maxs = new int[dimensions];
+        values = new Object[dimensions][];
+        for (int i=0; i<dimensions; i++) {
+            values[i] = dimValues[i];
+            maxs[i] = values[i].length;
+        }
+    }
+
+//    /** Complex version -- allow the contents of some dimensions to depend on previous dimensions, such
+//     * as generating tuples (a,b) where foo(b) <= foo(a).  Of the two arrays provided, for each index i,
+//     * exactly one of dimValues[i], dimGenerators[i] must be non-null.
+//     */
+//    public SyntheticLoop(Object[][] dimValues, DimensionFactory[] dimGenerators) {
+//        @@@NYI
+//    }
+
+    public Iterator<Object[]> iterator() {
+        return new Iterator<Object[]>() {
+            final int[] idxs = new int[dimensions];
+            boolean hasNext = (dimensions > 0);
+
+            public boolean hasNext() {
+                return hasNext;
+            }
+
+            public Object[] next() {
+                Object[] ret = new Object[dimensions];
+                for (int i=0; i<dimensions; i++)
+                    ret[i] = values[i][idxs[i]];
+                hasNext = !advance(dimensions-1);
+                return ret;
+            }
+
+            public void remove() { throw new UnsupportedOperationException(); }
+
+            private boolean advance(int i) {
+                if (i < 0)
+                    return true;
+                if (++idxs[i] == maxs[i]) {
+                    idxs[i] = 0;
+                    return advance(i - 1);
+                }
+                return false;
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/SyntheticLoopTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import org.testng.annotations.Test;
+
+import java.util.Iterator;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * SyntheticLoopTest
+ */
+@Test
+public class SyntheticLoopTest {
+    public void testEmpty() {
+        SyntheticLoop sl = new SyntheticLoop(new Object[0][]);
+        Iterator<Object[]> it = sl.iterator();
+        assertTrue(!it.hasNext());
+    }
+
+    private void assertSL(String expected, SyntheticLoop sl) {
+        StringBuilder sb = new StringBuilder();
+        for (Object[] row : sl) {
+            for (Object o : row) {
+                sb.append(o);
+            }
+            sb.append(" ");
+        }
+        assertEquals(sb.toString(), expected);
+    }
+
+    private void assertSL(int size, SyntheticLoop sl) {
+        int count = 0;
+        for (Object row : sl) {
+            ++count;
+        }
+        assertEquals(count, size);
+    }
+
+    public void testSimple() {
+        Object[] abc = {"A", "B", "C"};
+        assertSL("A B C ", new SyntheticLoop(new Object[][] {abc}));
+        assertSL("AA AB AC BA BB BC CA CB CC ", new SyntheticLoop(new Object[][] {abc, abc}));
+        assertSL(9, new SyntheticLoop(new Object[][] {abc, abc}));
+        assertSL(9, new SyntheticLoop(new Object[][] {abc, abc, new Object[] { "X" }}));
+        assertSL(27, new SyntheticLoop(new Object[][] {abc, abc, abc}));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/Template.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A template into which tags of the form {@code #\{KEY\}} or
+ * {@code #\{KEY.SUBKEY\}} can be expanded.
+ */
+public interface Template {
+    String expand(String selector);
+
+    interface Resolver {
+        public Template lookup(String key);
+    }
+
+    public static class Behavior {
+        private static final Pattern pattern = Pattern.compile("#\\{([A-Z_][A-Z0-9_]*(?:\\[\\d+\\])?)(?:\\.([A-Z0-9_]*))?\\}");
+
+        public static String expandTemplate(String template, final Map<String, Template> vars) {
+            return expandTemplate(template, new MapResolver(vars));
+        }
+
+        public static String expandTemplate(String template, Resolver res) {
+            CharSequence in = template;
+            StringBuffer out = new StringBuffer();
+            while (true) {
+                boolean more = false;
+                Matcher m = pattern.matcher(in);
+                while (m.find()) {
+                    String major = m.group(1);
+                    String minor = m.group(2);
+                    Template key = res.lookup(major);
+                    if (key == null)
+                        throw new IllegalStateException("Unknown major key " + major);
+
+                    String replacement = key.expand(minor == null ? "" : minor);
+                    more |= pattern.matcher(replacement).find();
+                    m.appendReplacement(out, replacement);
+                }
+                m.appendTail(out);
+                if (!more)
+                    return out.toString();
+                else {
+                    in = out;
+                    out = new StringBuffer();
+                }
+            }
+        }
+
+    }
+}
+
+class MapResolver implements Template.Resolver {
+    private final Map<String, Template> vars;
+
+    public MapResolver(Map<String, Template> vars) {this.vars = vars;}
+
+    public Template lookup(String key) {
+        return vars.get(key);
+    }
+}
+
+class ChainedResolver implements Template.Resolver {
+    private final Template.Resolver upstreamResolver, thisResolver;
+
+    public ChainedResolver(Template.Resolver upstreamResolver, Template.Resolver thisResolver) {
+        this.upstreamResolver = upstreamResolver;
+        this.thisResolver = thisResolver;
+    }
+
+    public Template.Resolver getUpstreamResolver() {
+        return upstreamResolver;
+    }
+
+    @Override
+    public Template lookup(String key) {
+        Template result = thisResolver.lookup(key);
+        if (result == null)
+            result = upstreamResolver.lookup(key);
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/TemplateTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * TemplateTest
+ */
+@Test
+public class TemplateTest {
+    Map<String, Template> vars = new HashMap<>();
+
+    @BeforeTest
+    void before() { vars.clear(); }
+
+    private void assertTemplate(String expected, String template) {
+        String result = Template.Behavior.expandTemplate(template, vars);
+        assertEquals(result, expected, "for " + template);
+    }
+
+    private String dotIf(String s) {
+        return s == null || s.isEmpty() ? "" : "." + s;
+    }
+
+    public void testTemplateExpansion() {
+        vars.put("A", s -> "a" + dotIf(s));
+        vars.put("B", s -> "b" + dotIf(s));
+        vars.put("C", s -> "#{A}#{B}");
+        vars.put("D", s -> "#{A" + dotIf(s) + "}#{B" + dotIf(s) + "}");
+        vars.put("_D", s -> "d");
+
+        assertTemplate("", "");
+        assertTemplate("foo", "foo");
+        assertTemplate("a", "#{A}");
+        assertTemplate("a", "#{A.}");
+        assertTemplate("a.FOO", "#{A.FOO}");
+        assertTemplate("aa", "#{A}#{A}");
+        assertTemplate("ab", "#{C}");
+        assertTemplate("ab", "#{C.FOO}");
+        assertTemplate("ab", "#{C.}");
+        assertTemplate("a.FOOb.FOO", "#{D.FOO}");
+        assertTemplate("ab", "#{D}");
+        assertTemplate("d", "#{_D}");
+        assertTemplate("#{A", "#{A");
+    }
+
+    public void testIndexedTemplate() {
+        vars.put("A[0]", s -> "a" );
+        vars.put("A[1]", s -> "b" );
+        vars.put("A[2]", s -> "c" );
+        vars.put("X", s -> "0");
+        assertTemplate("a", "#{A[0]}");
+        assertTemplate("b", "#{A[1]}");
+        assertTemplate("c", "#{A[2]}");
+    }
+
+    public void testAngleBrackets() {
+        vars.put("X", s -> "xyz");
+        assertTemplate("List<String> ls = xyz;", "List<String> ls = #{X};");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class )
+    public void testUnknownKey() {
+        assertTemplate("#{Q}", "#{Q}");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/combo/TemplateVar.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.combo;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * ComboTemplate
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@java.lang.annotation.Target({ElementType.METHOD, ElementType.FIELD})
+public @interface TemplateVar {
+    String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/ConditionalExpressionTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import tools.javac.combo.ComboTestBase;
+import tools.javac.combo.DimensionVar;
+import tools.javac.combo.SourceFile;
+import tools.javac.combo.Template;
+import tools.javac.combo.TemplateVar;
+
+/**
+ * ConditionalExpressionTest
+ */
+public class ConditionalExpressionTest extends ComboTestBase<ConditionalExpressionTest> {
+    @Factory
+    public static Object[] testConditionalExpression() throws Exception {
+        return factory(ConditionalExpressionTest.class);
+    }
+
+    @DimensionVar("TYPE1") Type type1;
+    @DimensionVar("TYPE2") Type type2;
+    @DimensionVar("TARGET") Type target;
+    @DimensionVar("STMT") Statement stmt;
+
+    @SourceFile("Main.java")
+    String clientFile = "public class Main {\n"
+            + " #{STMT_DECL};\n"
+            + " #{DECL.1};\n"
+            + " #{DECL.2};\n"  
+            + " void test(boolean cond) { \n"
+            + "   #{STMT};"
+            + " }\n"
+            +"}";
+
+    @Override
+    protected void postCompile(String grp) {
+        CondResult res = Type.condType(type1, type2);
+        if (!res.check(type1, type2, target)) {
+            assertCompileFailed();
+        } else {
+            assertCompileSucceeded();
+        }
+    }
+
+    @Override
+    protected boolean shouldSkip() {
+        return target == Type.INT_CONST;
+    }
+
+    interface CondResult {
+        boolean check(Type op1, Type op2, Type target);
+    }
+
+    static CondResult ERR = new CondResult() {
+        public boolean check(Type op1, Type op2, Type target) { return false; }
+    };
+
+    static CondResult TARGET = new CondResult() {
+        public boolean check(Type op1, Type op2, Type target) {
+           return op1.compatibleWith(target) && op2.compatibleWith(target);
+        }
+    };
+
+    enum TypeKind {
+        NUMERIC,
+        BOOLEAN,
+        OTHER;
+    }
+
+    enum Type implements Template, CondResult {
+        BYTE("byte", "0", TypeKind.NUMERIC),
+        SHORT("short", "0", TypeKind.NUMERIC),
+        INT("int", "0", TypeKind.NUMERIC),
+        INT_CONST("int", "0", TypeKind.NUMERIC),
+        LONG("long", "0", TypeKind.NUMERIC),
+        FLOAT("float", "0", TypeKind.NUMERIC),
+        DOUBLE("double", "0", TypeKind.NUMERIC),
+        CHAR("char", "'0'", TypeKind.NUMERIC),
+        BOOLEAN("boolean", "false", TypeKind.BOOLEAN),
+        J_L_BYTE("Byte", "null", TypeKind.NUMERIC),
+        J_L_SHORT("Short", "null", TypeKind.NUMERIC),
+        J_L_INT("Integer", "null", TypeKind.NUMERIC),
+        J_L_LONG("Long", "null", TypeKind.NUMERIC),
+        J_L_FLOAT("Float", "null", TypeKind.NUMERIC),
+        J_L_DOUBLE("Double", "null", TypeKind.NUMERIC),
+        J_L_CHAR("Character", "null", TypeKind.NUMERIC),
+        J_L_BOOLEAN("Boolean", "null", TypeKind.BOOLEAN),
+        NUMBER("Number", "null", TypeKind.OTHER),
+        SERIAL("java.io.Serializable", "null", TypeKind.OTHER);
+
+        public boolean check(Type op1, Type op2, Type target) {
+            return compatibleWith(target);
+        }
+
+        public boolean isErroneous() {
+            return false;
+        }
+
+        public String expand(String qualifier) {
+            return typeStr;
+        }
+
+        boolean compatibleWith(Type that) {
+            return that.anyOf(compatibleWith[this.ordinal()]);
+        }
+
+        boolean anyOf(Type... ts) {
+            for (Type t : ts) {
+                if (t == this) return true;
+            }
+            return false;
+        }
+
+        Type unbox() {
+            switch (this) {
+                case BYTE:
+                case J_L_BYTE: return BYTE;
+                case SHORT:
+                case J_L_SHORT: return SHORT;
+                case INT:
+                case INT_CONST:
+                case J_L_INT: return INT;
+                case LONG:
+                case J_L_LONG: return LONG;
+                case FLOAT:
+                case J_L_FLOAT: return FLOAT;
+                case DOUBLE:
+                case J_L_DOUBLE: return DOUBLE;
+                case BOOLEAN:
+                case J_L_BOOLEAN: return BOOLEAN;
+                case CHAR:
+                case J_L_CHAR: return CHAR;                
+                default:
+                    return null;
+            }
+        }
+
+        String typeStr;
+        String defaultVal;
+        TypeKind kind;
+
+        Type(String typeStr, String defaultVal, TypeKind kind) {
+            this.typeStr = typeStr;
+            this.defaultVal = defaultVal;
+            this.kind = kind;
+        }
+
+        static CondResult condType(Type type1, Type type2) {
+            if (type1.kind == TypeKind.BOOLEAN && type2.kind == TypeKind.BOOLEAN) {
+                //boolean conditional
+                return BOOLEAN;
+            } else if (type1.kind == TypeKind.NUMERIC && type2.kind == TypeKind.NUMERIC) {                    
+                //numeric conditional
+                Type unbox1 = type1.unbox();
+                Type unbox2 = type2.unbox();
+                if (type1 == INT_CONST &&     
+                        unbox2.anyOf(CHAR, BYTE, SHORT)) {
+                    return unbox2;
+                }
+                if (type2 == INT_CONST &&     
+                        unbox1.anyOf(CHAR, BYTE, SHORT)) {
+                    return unbox1;
+                }
+                if (unbox1 == unbox2) {
+                    return unbox1;
+                }
+                if (unbox1 == CHAR) {
+                    return condType(INT, unbox2);
+                }
+                if (unbox2 == CHAR) {
+                    return condType(unbox1, INT);
+                }
+                if (unbox1.compatibleWith(unbox2)) {
+                    return unbox2;
+                } else if (unbox2.compatibleWith(unbox1)) {
+                    return unbox1;
+                } else {
+                    return ERR;
+                }
+            } else {
+                //reference conditional
+                return TARGET;
+            }
+        }
+
+        static Type[][] compatibleWith = new Type[][] {
+        /* BYTE */        { BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, J_L_BYTE, NUMBER, SERIAL },
+        /* SHORT */       { SHORT, INT, LONG, FLOAT, DOUBLE, J_L_SHORT, NUMBER, SERIAL },
+        /* INT */         { INT, LONG, FLOAT, DOUBLE, J_L_INT, NUMBER, SERIAL },
+        /* INT_CONST */   { INT, LONG, FLOAT, DOUBLE, J_L_INT, NUMBER, SERIAL },
+        /* LONG */        { LONG, FLOAT, DOUBLE, J_L_LONG, NUMBER, SERIAL },
+        /* FLOAT */       { FLOAT, DOUBLE, J_L_FLOAT, NUMBER, SERIAL },
+        /* DOUBLE */      { DOUBLE, J_L_DOUBLE, NUMBER, SERIAL },
+        /* CHAR */        { CHAR, INT, LONG, FLOAT, DOUBLE, J_L_CHAR, SERIAL },
+        /* BOOLEAN */     { BOOLEAN, J_L_BOOLEAN, SERIAL },
+        /* J_L_BYTE */    { J_L_BYTE, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, NUMBER, SERIAL },
+        /* J_L_SHORT */   { J_L_SHORT, SHORT, INT, LONG, FLOAT, DOUBLE, NUMBER, SERIAL },
+        /* J_L_INT */     { J_L_INT, INT, LONG, FLOAT, DOUBLE, NUMBER, SERIAL },
+        /* J_L_LONG */    { J_L_LONG, LONG, FLOAT, DOUBLE, NUMBER, SERIAL },
+        /* J_L_FLOAT */   { J_L_FLOAT, FLOAT, DOUBLE, NUMBER, SERIAL },
+        /* J_L_DOUBLE */  { J_L_DOUBLE, DOUBLE, NUMBER, SERIAL },
+        /* J_L_CHAR */    { J_L_CHAR, CHAR, INT, LONG, FLOAT, DOUBLE, SERIAL },
+        /* J_L_BOOLEAN */ { J_L_BOOLEAN, BOOLEAN, SERIAL },
+        /* NUMBER */      { NUMBER, SERIAL },
+        /* SERIAL */      { SERIAL } };
+    }
+
+    enum Statement implements Template {
+        ASSIGN("#{TARGET} t = cond ? #{EXPR.1} : #{EXPR.2}"),
+        METHOD("m(cond ? #{EXPR.1} : #{EXPR.2})");
+
+        String stmtStr;
+
+        Statement(String stmtStr) {
+            this.stmtStr = stmtStr;
+        }
+
+        public String expand(String qual) {
+            return stmtStr;
+        }
+    }
+
+    @TemplateVar("STMT_DECL")
+    Template stmt_decl = new Template() {
+        public String expand(String selector) {            
+            return stmt == Statement.ASSIGN ? "" : "void m(#{TARGET} arg) { }";
+        }
+    };
+
+    @TemplateVar("DECL")
+    Template decl = new Template() {
+        public String expand(String selector) {
+            int sel = Integer.valueOf(selector);
+            Type t = sel == 1 ? type1 : type2;
+            return t == Type.INT_CONST ? "" : String.format("#{TYPE%d} m%d() { return %s; }", sel, sel, t.defaultVal);
+        }
+    };
+
+    @TemplateVar("EXPR")
+    Template expr = new Template() {
+        public String expand(String selector) {
+            int sel = Integer.valueOf(selector);
+            Type t = sel == 1 ? type1 : type2;
+            return t == Type.INT_CONST ? t.defaultVal : String.format("m%d()", sel);
+        }
+    };
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/DefaultMethodAddTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.testng.annotations.Factory;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import tools.javac.combo.*;
+
+/**
+ * DefaultMethodAddTest: Test default method by running bytecode compiled at different times
+ *                       where conflicting default methods are added or declared
+ */
+public class DefaultMethodAddTest extends ComboTestBase<DefaultMethodAddTest> {
+    @Factory
+    public static Object[] testDefaultMethodAdd() throws Exception {
+        return factory(DefaultMethodAddTest.class);
+    }
+    
+    @DimensionVar("SHAPE") CShapes shapeType;
+    
+    /**
+     * The separate-compilation operation to be performed, such as adding a default method, 
+     * adding an abstract itnerface method, redeclaring an inherited default method as 
+     * abstract interface method, etc
+     */     
+    @DimensionVar("ADD") AddType addType;
+        
+    @SourceFile(value="B.java", group="A")
+    String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{ADD} }";
+    
+    @SourceFile(value="B.java", group="B")
+    String interfaceB =         "interface B #{SHAPE.B_DECL} {}";
+    
+    @SourceFile(value="A.java", group="B")
+    String interfaceA =         "interface A { default String m() { return \"A\"; } }";
+    
+    @SourceFile(value="C.java", group="B")
+    String classC = "#{SHAPE.C}";
+    
+    @SourceFile(value="Main.java", group="B")
+    String classMain = "public class Main {\n" +
+                       "    public String main() {\n" +
+                       "        return new C().m();\n" +                       
+                       "    }\n" +
+                       "}";    
+
+    @Override
+    protected boolean shouldRun() { return true; }
+    
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Method m = clazz.getMethod("main");
+        Object obj = clazz.newInstance();
+        String result = null, output = null;
+        try {
+            result = (String) m.invoke(obj);
+        } catch (InvocationTargetException ex) {
+            output = ex.getCause().toString();
+        }        
+        if(shapeType == CShapes.C_B_A) {
+            if(addType == AddType.ADD) {
+                assertEquals(output, null);
+                assertEquals(result, "B");
+            }
+            else //redeclare
+                assertEquals(output, "java.lang.AbstractMethodError: Method B.m()Ljava/lang/String; is abstract");
+        }
+        else if(shapeType == CShapes.C_I_AB2) {
+            assertEquals(output, null);
+            assertEquals(result, "A");
+        }
+        else if(shapeType == CShapes.C_CI) {
+            assertEquals(output, null);
+            assertEquals(result, "D");
+        }
+        else if(shapeType == CShapes.C_I_AB3) {
+            assertEquals(output, null);
+            assertEquals(result, "AB");
+        }
+        else            
+            assertTrue(output.matches("java.lang.AbstractMethodError: Conflicting default methods: .+[.]m .+[.]m"));        
+    }
+    
+    enum CShapes implements Template { //shapes of class hirarchy
+        //class C implements interface A, B
+        C_AB("",            
+           "class C implements A, B {}"), 
+        //class C implments interface B, B extends interface A
+        C_B_A("extends A", 
+           "class C implements B {}"),
+        //class C implments interface AB, AB extends interface A, B
+        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 { default String m() { 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 { default String m() { 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 sB_DECL;
+        private final String sC;
+        
+        CShapes(String sB_DECL, String sC) {
+            this.sB_DECL = sB_DECL;
+            this.sC = sC;
+        }
+        
+        public String expand(String selector) {
+            switch(selector) {
+                case "B_DECL": return sB_DECL;
+                case "C": return sC;
+                default: return toString();
+            }            
+        }        
+    }
+    
+    enum AddType implements Template { // add by adding default method or abstract interface method
+        ADD("default String m() { return \"B\"; }"),
+        REDECLARE("String m();");
+        
+        final String newCode;
+        
+        AddType(String str) {
+            newCode = str;
+        }
+        
+        public String expand(String selector) {
+            return newCode;        
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/DefaultMethodRemoveTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.testng.annotations.Factory;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import tools.javac.combo.*;
+
+/**
+ * DefaultMethodRemoveTest: Test default method by running bytecode compiled at different times
+ *                          where default methods are removed or redeclared
+ */
+public class DefaultMethodRemoveTest extends ComboTestBase<DefaultMethodRemoveTest> {
+    @Factory
+    public static Object[] testDefalutMethodRemove() throws Exception {
+        return factory(DefaultMethodRemoveTest.class);
+    }
+    
+    @DimensionVar("SHAPE") CShapes shapeType;
+    
+    /**
+     * The separate-compilation operation to be performed, such as removing a default method, 
+     * redeclaring as abstract interface method, etc
+     */  
+    @DimensionVar("REMOVE") RemoveType removeType;
+    
+    @SourceFile(value="B.java", group="A")
+    String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{REMOVE} }";
+      
+    @SourceFile(value="A.java", group="B")
+    String interfaceA = "interface A { default String m() { return \"A\"; } }";
+    
+    @SourceFile(value="B.java", group="B")
+    String interfaceB = "interface B #{SHAPE.B_DECL} { default String m() { return \"B\"; } }";
+        
+    @SourceFile(value="C.java", group="B")
+    String classC = "#{SHAPE.C}";
+    
+    @SourceFile(value="Main.java", group="B")
+    String classMain = "public class Main {\n" +
+                       "    public String main() {\n" +
+                       "        return new C().m();\n" +                       
+                       "    }\n" +
+                       "}";    
+
+    @Override
+    protected boolean shouldRun() { return true; }
+    
+    @Override
+    protected void postCompile(String group) {
+        if( group.equals("A") && shapeType == CShapes.C_B_AD && removeType == RemoveType.REMOVE )
+            assertCompileErrors("compiler.err.types.incompatible.unrelated.defaults");
+    }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Method m = clazz.getMethod("main");
+        Object obj = clazz.newInstance();
+        String result = null, output = null;
+        try {
+            result = (String) m.invoke(obj);
+        } catch (InvocationTargetException ex) {
+            output = ex.getCause().toString();            
+        }
+        if(shapeType == CShapes.C_B_A) {
+            if(removeType == RemoveType.REMOVE)
+                assertEquals(result, "A");
+            else
+                assertEquals(output, "java.lang.AbstractMethodError: Method B.m()Ljava/lang/String; is abstract");
+        }
+        else if(shapeType == CShapes.C_CI)
+            assertEquals(result, "D");
+        else if(shapeType == CShapes.C_B_AD) {
+            if(removeType == RemoveType.REMOVE)
+                assertEquals(output, "java.lang.AbstractMethodError: C.m()Ljava/lang/String;");
+            else    
+                assertEquals(output, "java.lang.AbstractMethodError: Method B.m()Ljava/lang/String; is abstract");
+        }
+        else { //C_B
+            if( removeType == RemoveType.REMOVE)
+                assertEquals(output, "java.lang.NoSuchMethodError: C.m()Ljava/lang/String;");
+            else
+                assertEquals(output, "java.lang.AbstractMethodError: C.m()Ljava/lang/String;");
+        }
+    }
+    
+    enum CShapes implements Template { //shapes of class hirarchy
+        //class C implements interface B
+        C_B("", 
+            "class C implements B {}"), 
+        //class C implments interface B, B extends interface 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", 
+               "interface D { default String m() { 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 sB_DECL;
+        private final String sC;
+        
+        CShapes(String sB_DECL, String sC) {
+            this.sB_DECL = sB_DECL;
+            this.sC = sC;            
+        }
+        
+        public String expand(String selector) {
+            switch(selector) {
+                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
+        REMOVE(""),
+        REDECLARE("String m();");
+        
+        final String newCode;
+        
+        RemoveType(String str) {
+            newCode = str;
+        }
+        
+        public String expand(String selector) {
+            return newCode;        
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/LambdaArgAdaptationTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import tools.javac.combo.ComboTestBase;
+import tools.javac.combo.DimensionVar;
+import tools.javac.combo.SourceFile;
+import tools.javac.combo.Template;
+
+import java.lang.reflect.Method;
+import java.util.EnumMap;
+import java.util.EnumSet;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * LambdaArgAdaptationTest
+ */
+public class LambdaArgAdaptationTest extends ComboTestBase<LambdaArgAdaptationTest> {
+    @Factory
+    public static Object[] testArgAdaptation() throws Exception {
+        return factory(LambdaArgAdaptationTest.class);
+    }
+
+    @DimensionVar("FROM") Types fromType;
+    @DimensionVar("TO") Types toType;
+
+    @SourceFile("Sam.java")
+    String samFile = "public interface Sam { String m(#{FROM} arg); }";
+
+    @SourceFile("Main.java")
+    String clientFile = "public class Main {\n"
+                        +"  static String m(#{TO} arg) { \n"
+                        +"    return String.valueOf(arg);\n"
+                        +"  }\n"
+                        +"  public String main() { \n"
+                        + "   Sam s = Main::m;\n"
+                        + "   return s.m(#{FROM.ARG});\n"
+                        + " }\n"
+                        +"}";
+
+
+    @Override
+    protected String[] getCompileOptions(String group) {
+        return new String[] { "-XDlambdaToMethod" };
+    }
+
+    @Override
+    protected void postCompile(String group) {
+        if (fromType == Types.VOID || toType == Types.VOID)
+            assertCompileFailed();
+        else if (fromType.pr == PR.REF && toType.pr == PR.REF)
+            assertCompileSucceededIff(toType.clazz.isAssignableFrom(fromType.clazz));
+        else if (fromType.pr == PR.PRIM && toType.pr == PR.REF)
+            assertCompileSucceededIff(toType.clazz.isAssignableFrom(Types.boxMap.get(fromType).clazz));
+        else if (fromType.pr == PR.REF && toType.pr == PR.PRIM)
+            assertCompileSucceededIff(fromType.unboxed != null && Types.widenMap.get(fromType.unboxed).contains(toType));
+        else if (fromType.pr == PR.PRIM && toType.pr == PR.PRIM)
+            assertCompileSucceededIff(Types.widenMap.get(fromType).contains(toType));
+        else
+            assertCompileSucceeded();
+    }
+
+    @Override
+    protected boolean shouldRun() { return true; }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Method m = clazz.getMethod("main");
+        Object obj = clazz.newInstance();
+        String result = (String) m.invoke(obj);
+        String formatted = fromType.asObject.toString();
+        if (fromType == Types.CHAR || fromType == Types.BOXED_CHAR) {
+            result = result.replace("A", "65");
+            formatted = formatted.replace("A", "65");
+        }
+        assertEquals(result.replace(".0", ""), formatted.replace(".0", ""));
+    }
+}
+
+enum PR {PRIM, REF}
+
+enum Types implements Template {
+    BYTE(PR.PRIM, "byte", byte.class, "(byte) 1", (byte) 1),
+    SHORT(PR.PRIM, "short", short.class, "(short) 2", (short) 2),
+    CHAR(PR.PRIM, "char", char.class, "'A'", 'A'),
+    INT(PR.PRIM, "int", int.class, "3", 3),
+    LONG(PR.PRIM, "long", long.class, "4L", 4L),
+    FLOAT(PR.PRIM, "float", float.class, "5.0f", 5.0f),
+    DOUBLE(PR.PRIM, "double", double.class, "6.0", 6.0),
+    BOOLEAN(PR.PRIM, "boolean", boolean.class, "true", true),
+    VOID(PR.PRIM, "void", void.class, "null", null),
+    BOXED_BYTE(PR.REF, "Byte", Byte.class, "Byte.valueOf((byte) 1)", (byte) 1, BYTE),
+    BOXED_SHORT(PR.REF, "Short", Short.class, "Short.valueOf((short) 2)", (short) 2, SHORT),
+    BOXED_CHAR(PR.REF, "Character", Character.class, "Character.valueOf('A')", 'A', CHAR),
+    BOXED_INT(PR.REF, "Integer", Integer.class, "Integer.valueOf(3)", 3, INT),
+    BOXED_LONG(PR.REF, "Long", Long.class, "Long.valueOf(4)", (long) 4, LONG),
+    BOXED_FLOAT(PR.REF, "Float", Float.class, "Float.valueOf(5.0f)", 5.0f, FLOAT),
+    BOXED_DOUBLE(PR.REF, "Double", Double.class, "Double.valueOf(6.0)", 6.0, DOUBLE),
+    BOXED_BOOLEAN(PR.REF, "Boolean", Boolean.class, "Boolean.valueOf(true)", true, BOOLEAN),
+    NUMBER(PR.REF, "Number", Number.class, "9", 9),
+    OBJECT(PR.REF, "Object", Object.class, "10", 10),
+    STRING(PR.REF, "String", String.class, "\"foo\"", "foo");
+
+    public static EnumMap<Types, Types> boxMap = new EnumMap<>(Types.class);
+    public static EnumMap<Types, Types> unboxMap = new EnumMap<>(Types.class);
+    public static EnumMap<Types, EnumSet<Types>> widenMap = new EnumMap<>(Types.class);
+
+    static {
+        for (Types t : values()) {
+            if (t.unboxed != null) {
+                boxMap.put(t.unboxed, t);
+                unboxMap.put(t, t.unboxed);
+            }
+        }
+
+        widenMap.put(BYTE, EnumSet.of(BYTE, SHORT, INT, LONG, FLOAT, DOUBLE));
+        widenMap.put(SHORT, EnumSet.of(SHORT, INT, LONG, FLOAT, DOUBLE));
+        widenMap.put(CHAR, EnumSet.of(CHAR, INT, LONG, FLOAT, DOUBLE));
+        widenMap.put(INT, EnumSet.of(INT, LONG, FLOAT, DOUBLE));
+        widenMap.put(LONG, EnumSet.of(LONG, FLOAT, DOUBLE));
+        widenMap.put(FLOAT, EnumSet.of(FLOAT, DOUBLE));
+        widenMap.put(DOUBLE, EnumSet.of(DOUBLE));
+        widenMap.put(BOOLEAN, EnumSet.of(BOOLEAN));
+    }
+
+    final PR pr;
+    final String name;
+    final Class<?> clazz;
+    final String valueString;
+    final Object asObject;
+    final Types unboxed;
+
+    Types(PR pr, String name, Class<?> clazz, String valueString, Object asObject) {
+        this (pr, name, clazz, valueString, asObject, null);
+    }
+
+    Types(PR pr, String name, Class<?> clazz, String valueString, Object asObject, Types unboxed) {
+        this.pr = pr;
+        this.name = name;
+        this.clazz = clazz;
+        this.valueString = valueString;
+        this.asObject = asObject;
+        this.unboxed = unboxed;
+    }
+
+    public String expand(String selector) {
+        switch (selector) {
+            case "ARG": return valueString;
+            default: return name;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/LambdaCaptureTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+import tools.javac.combo.*;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * LambdaCaptureTest
+ *
+ * @author Brian Goetz
+ */
+public class LambdaCaptureTest extends ComboTestBase<LambdaCaptureTest> {
+    @Factory
+    public static Object[] testCombo() throws Exception {
+        return factory(LambdaCaptureTest.class);
+    }
+
+    final int arity;
+    final ArgType[] argTypes;
+    final int capArity;
+    final CapType[] capTypes;
+    final boolean shouldSkip;
+
+    public LambdaCaptureTest(@DimensionVar(value = "ARITY", rangeLower = 0, rangeUpper = 2) int arity,
+                             @DimensionVar("ARGTYPE1") ArgType argType1,
+                             @DimensionVar("ARGTYPE2") ArgType argType2,
+                             @DimensionVar(value = "CAP_ARITY", rangeLower = 0, rangeUpper = 2) int capArity,
+                             @DimensionVar("CAPTYPE1") CapType capType1,
+                             @DimensionVar("CAPTYPE2") CapType capType2) {
+        this.arity = arity;
+        this.capArity = capArity;
+        this.argTypes = new ArgType[] { argType1, argType2 };
+        this.capTypes = new CapType[] { capType1, capType2 };
+        shouldSkip = skipConstrained(arity, argTypes) || skipConstrained(capArity, capTypes);
+    }
+
+    @Override
+    protected String[] getCompileOptions(String group) {
+        return new String[] { "-XDlambdaToMethod" };
+    }
+
+    @SourceFile("Main.java") String test
+            = "public class Main {\n"
+            + "  #{CAPTYPE1} f0 = #{CAPV.1};\n"
+            + "  #{CAPTYPE2} f1 = #{CAPV.2};\n"
+            + "  interface Target { String m(#{SAM_FORMALS}); }\n"
+            + "  public String convert() { #{CAPTYPE1} loc0 = #{CAPV.1};\n"
+            + "                            #{CAPTYPE2} loc1 = #{CAPV.2};\n"
+            + "                            Target lambda = (#{LAMBDA_FORMALS}) -> String.format(\"#{FORMAT_STRING}\" #{FORMAT_ARGS});\n"
+            + "                            return lambda.m(#{INVOKE_ARGS}); }\n"
+            + "}";
+
+    @TemplateVar("LAMBDA_FORMALS") Template formalArgs = new Template() {
+        public String expand(String selector) {
+            List<String> list = new ArrayList<>();
+            for (int i=0; i<arity; i++)
+                list.add(argTypes[i].typeName + " a" + i);
+            return intersperse(list, ", ");
+        }
+    };
+
+    @TemplateVar("SAM_FORMALS") Template samArgs = new Template() {
+        public String expand(String selector) {
+            List<String> list = new ArrayList<>();
+            for (int i=0; i<arity; i++)
+                list.add(argTypes[i].typeName + " a" + i);
+            return intersperse(list, ", ");
+        }
+    };
+
+    @TemplateVar("FORMAT_STRING") Template formatString = new Template() {
+        public String expand(String selector) {
+            List<String> list = new ArrayList<>();
+            for (int i=0; i<capArity; i++)
+                list.add(capTypes[i].argType.format);
+            for (int i=0; i<arity; i++)
+                list.add(argTypes[i].format);
+            return intersperse(list, " ");
+        }
+    };
+
+    @TemplateVar("FORMAT_ARGS") Template formatArgs = new Template() {
+        public String expand(String selector) {
+            List<String> list = new ArrayList<>();
+            for (int i=0; i<capArity; i++)
+                list.add((capTypes[i].lf == LF.LOCAL ? "loc" : "f") + i);
+            for (int i=0; i<arity; i++)
+                list.add("a" + i);
+            return ((list.size()) > 0 ? ", " : "") + intersperse(list, ", ");
+        }
+    };
+
+    @TemplateVar("INVOKE_ARGS") Template invokeArgs = new Template() {
+        public String expand(String selector) {
+            List<String> list = new ArrayList<>();
+            for (int i=0; i<arity; i++)
+                list.add(argTypes[i].formatValue(i+capArity));
+            return intersperse(list, ", ");
+        }
+    };
+
+    @TemplateVar("CAPV") Template capv = new Template() {
+        public String expand(String selector) {
+            int i = Integer.parseInt(selector) - 1;
+            return capTypes[i].argType.formatValue(i);
+        }
+    };
+
+    private String intersperse(List<String> list, String delim) {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (String s : list) {
+            if (!first)
+                sb.append(delim);
+            first = false;
+            sb.append(s);
+        }
+        return sb.toString();
+    }
+
+    @Override
+    protected boolean shouldSkip() {
+        return shouldSkip;
+    }
+
+    @Override
+    protected boolean shouldRun() {
+        return true;
+    }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Object obj = clazz.newInstance();
+        Method m = clazz.getMethod("convert");
+        Object o = m.invoke(obj);
+
+        List<String> list = new ArrayList<>();
+        for (int i=0; i<capArity; i++)
+            list.add(capTypes[i].argType.formatResult(i));
+        for (int i=0; i<arity; i++)
+            list.add(argTypes[i].formatResult(i+capArity));
+        String result = intersperse(list, " ");
+        assertEquals(result, o);
+    }
+
+    static enum ArgType implements Template {
+        LONG("long", "Long", "J%d", null) {
+            String formatValue(int x) { return String.format("(long) %d", x); }
+            String formatResult(int x) { return "J" + Integer.toString(x); }
+        },
+        BYTE("byte", "Byte", "B%d", LONG) {
+            String formatValue(int x) { return String.format("(byte) %d", x); }
+            String formatResult(int x) { return "B" + Integer.toString(x); }
+        },
+        SHORT("short", "Short", "S%d", LONG) {
+            String formatValue(int x) { return String.format("(short) %d", x); }
+            String formatResult(int x) { return "S" + Integer.toString(x); }
+        },
+        CHAR("char", "Character", "C%c", LONG) {
+            String formatValue(int x) { return String.format("(char) (((int) 'A') + %d)", x); }
+            String formatResult(int x) { return "C" + (char) (((int) 'A') + x); }
+        },
+        INT("int", "Integer", "I%d", LONG) {
+            String formatValue(int x) { return String.format("%d", x); }
+            String formatResult(int x) { return "I" + Integer.toString(x); }
+        },
+        BOOLEAN("boolean", "Boolean", "Z%b", null) {
+            String formatValue(int x) { return String.format("%d %% 2 != 0", x); }
+            String formatResult(int x) { return "Z" + (x % 2 != 0); }
+        },
+        DOUBLE("double", "Double", "D%f", null) {
+            String formatValue(int x) { return String.format("(double) %d", x); }
+            String formatResult(int x) { return "D" + String.format("%f", (double) x); }
+        },
+        FLOAT("float", "Float", "F%f", DOUBLE) {
+            String formatValue(int x) { return String.format("(float) %d", x); }
+            String formatResult(int x) { return "F" + String.format("%f", (float) x); }
+        },
+        OBJECT("Object", "Object", "O%s", null) {
+            String formatValue(int x) { return String.format("Integer.toString(%d)", x); }
+            String formatResult(int x) { return "O" + Integer.toString(x); }
+        },
+        STRING("String", "String", "S%s", null) {
+            String formatValue(int x) { return String.format("Integer.toString(%d)", x); }
+            String formatResult(int x) { return "S" + Integer.toString(x); }
+        };
+
+        final String typeName, boxed, format;
+        final ArgType widened;
+
+        ArgType(String typeName, String boxed, String format, ArgType widened) {
+            this.typeName = typeName;
+            this.boxed = boxed;
+            this.format = format;
+            this.widened = widened;
+        }
+
+        abstract String formatValue(int x);
+        abstract String formatResult(int x);
+
+        public String expand(String selector) {
+            return typeName;
+        }
+    }
+
+    private static enum LF { LOCAL, FIELD }
+
+    static enum CapType implements Template {
+        LOCAL_INT(ArgType.INT, LF.LOCAL),
+        LOCAL_LONG(ArgType.LONG, LF.LOCAL),
+        LOCAL_STRING(ArgType.STRING, LF.LOCAL),
+        FIELD_INT(ArgType.INT, LF.FIELD),
+        FIELD_LONG(ArgType.LONG, LF.FIELD),
+        FIELD_STRING(ArgType.STRING, LF.FIELD);
+
+        final ArgType argType;
+        final LF lf;
+
+        CapType(ArgType argType, LF lf) {
+            this.argType = argType;
+            this.lf = lf;
+        }
+
+        public String expand(String selector) {
+            return argType.typeName;
+        }
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/LambdaConversionTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import tools.javac.combo.*;
+
+/**
+ * LambdaConversionTestCase
+ *
+ * @author Maurizio Cimadamore
+ */
+public class LambdaConversionTest extends ComboTestBase<LambdaConversionTest> {
+
+    @Factory
+    public static Object[] testCombo() throws Exception {
+        return factory(LambdaConversionTest.class);
+    }
+
+    @DimensionVar("PACKAGE")  PackageKind  samPkg;
+    @DimensionVar("MODIFIER") ModifierKind modKind;
+    @DimensionVar("CLASS")    SamKind      samKind;
+    @DimensionVar("METH")     MethodKind   meth;
+    @DimensionVar("RET")      TypeKind     retType;
+    @DimensionVar("ARG")      TypeKind     argType;
+    @DimensionVar("THROWN")   TypeKind     thrownType;
+
+    @SourceFile("Sam.java")
+    String samSource = "#{PACKAGE.PACKAGE_DECL} \n #{CLASS}";
+
+    @SourceFile("PackageClass.java")
+    String packageSource = "#{PACKAGE.PACKAGE_DECL}\n #{MODIFIER} class PackageClass extends Exception { }";
+
+    @SourceFile("Client.java")
+    String clientSource = "#{PACKAGE.IMPORT_STATEMENT}\n class Client { Sam s = x -> null; }";
+
+    @Override
+    protected void postCompile(String group) {
+        if (samKind != SamKind.INTERFACE) {
+            assertCompileFailed("SAM type must be an interface");
+        } else if (meth != MethodKind.NON_GENERIC) {
+            assertCompileFailed("target method must be non-generic");
+        } else if (samPkg != PackageKind.NO_PKG &&
+                   modKind != ModifierKind.PUBLIC &&
+                   (retType == TypeKind.PKG_CLASS
+                           || argType == TypeKind.PKG_CLASS
+                           || thrownType == TypeKind.PKG_CLASS)) {
+            assertCompileFailed("target must not contain inaccessible types");
+        } else {
+            assertCompileSucceeded();
+        }
+    }
+
+    static enum PackageKind implements Template {
+        NO_PKG(""),
+        PKG_A("a");
+
+        String pkg;
+
+        PackageKind(String pkg) {
+            this.pkg = pkg;
+        }
+
+        public String expand(String selector) {
+            if (this == NO_PKG)
+                return "";
+            switch (selector) {
+                case "PACKAGE_DECL": return String.format("package %s;", pkg);
+                case "IMPORT_STATEMENT":  return String.format("import %s.*;", pkg);
+                default: throw new IllegalArgumentException(selector);
+            }
+        }
+    }
+
+    static enum SamKind implements Template {
+        CLASS("public class Sam {  }"),
+        ABSTRACT_CLASS("public abstract class Sam {  }"),
+        ANNOTATION("public @interface Sam {  }"),
+        ENUM("public enum Sam { }"),
+        INTERFACE("public interface Sam { \n #{METH}; \n }");
+
+        String template;
+
+        SamKind(String template) { this.template = template; }
+
+        public String expand(String selector) { return template; }
+    }
+
+    static enum ModifierKind implements Template {
+        PUBLIC("public"),
+        PACKAGE("");
+
+        String template;
+
+        ModifierKind(String template) { this.template = template; }
+
+        public String expand(String selector) { return template; }
+    }
+
+    static enum TypeKind implements Template {
+        EXCEPTION("Exception"),
+        PKG_CLASS("PackageClass");
+
+        String template;
+
+        private TypeKind(String template) { this.template = template; }
+
+        public String expand(String selector) { return template; }
+    }
+
+    static enum MethodKind implements Template {
+        NONE(""),
+        NON_GENERIC("public #{RET} m(#{ARG} s) throws #{THROWN};"),
+        GENERIC("public <X> #{RET} m(#{ARG} s) throws #{THROWN};");
+
+        String template;
+
+        private MethodKind(String template) { this.template = template; }
+
+        public String expand(String selector) { return template; }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/LambdaExpressionTypeInferenceTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import tools.javac.combo.ComboTestBase;
+import tools.javac.combo.DimensionVar;
+import tools.javac.combo.SourceFile;
+import tools.javac.combo.Template;
+
+import static tools.javac.combo.StackProcessingUtils.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * LambdaExpressionTypeInferenceTest
+ */
+public class LambdaExpressionTypeInferenceTest extends ComboTestBase<LambdaExpressionTypeInferenceTest> {
+    @Factory
+    public static Object[] testLambdaExpressionInference() throws Exception {
+        return factory(LambdaExpressionTypeInferenceTest.class);
+    }
+
+    @DimensionVar("FORMAL_SHAPE") FormalTypeShape formalShape;
+    @DimensionVar("TREE_SHAPE") TreeShape treeShape;
+    @DimensionVar("ARG_SHAPE_1") ArgTypeShape argShape1;
+    @DimensionVar("ARG_SHAPE_2") ArgTypeShape argShape2;
+    @DimensionVar("ARG_SHAPE_3") ArgTypeShape argShape3;
+
+    @SourceFile("SAM.java")
+    String samFile = "public interface SAM<X,Y> {\n"
+            +"  Y apply(X x);\n"
+            +"}";
+
+
+    @SourceFile("Main.java")
+    String clientFile = "import java.util.*;\n"
+            +"public class Main {\n"
+            +"  <A,R> void m(#{FORMAL_SHAPE} x) { }\n"
+            +"  void test() {\n"
+            +"     m(#{TREE_SHAPE});\n"
+            +"  }\n"
+            +"}";
+
+    @Override
+    protected void postCompile(String grp) {
+        if (treeShape.compute().typeCheck(formalShape.compute(), new Type[] { argShape1.compute(), argShape2.compute(), argShape3.compute() }).isErroneous()) {
+            assertCompileFailed();
+        } else {
+            assertCompileSucceeded();
+        }
+    }
+
+    @Override
+    protected boolean shouldSkip() {
+        return argShape2.ordinal() != 0 && treeShape.depth < 2 || argShape3.ordinal() != 0 && treeShape.depth < 3;
+    }
+
+    static class Tree {
+        TreeTag treeTag;
+        Tree[] subtrees;
+
+        Tree(TreeTag treeTag, Tree... subtrees) {
+            this.treeTag = treeTag;
+            this.subtrees = subtrees;
+        }
+
+        public String toString() {
+            Object[] substrings = new Object[subtrees.length];
+            for (int i = 0; i < subtrees.length; i++) {
+                substrings[i] = subtrees[i].toString();
+            }
+            return String.format(treeTag.treeStr, substrings);
+        }
+
+        Type typeCheck(Type target, Type[] argtypes) {
+            switch (treeTag) {
+                case INT:   
+                   Type type = new Type(TypeToken.INTEGER);
+                   return type.compatibleWith(target) ? type : errType;
+                case STRING:
+                   type = new Type(TypeToken.STRING);
+                   return type.compatibleWith(target) ? type : errType;
+                case EXPR_LAMBDA:
+                    Type restype = target.getReturnType();
+                    if (restype == null) {
+                        return errType;
+                    }
+                    Type argtype = target.getArgType();
+                    int idx = subtrees[0].treeTag.argIndex();
+                    if (idx >= 0 && !argtypes[idx].compatibleWith(argtype)) {
+                        //arg type mismatch
+                        return errType;
+                    }
+                    
+                    for (int i = 1; i < subtrees.length; i++) {
+                        if (subtrees[i].typeCheck(restype, argtypes).isErroneous()) {
+                            return errType;
+                        }
+                    }
+                    return target;
+                case COND:
+                    Type typeToCheck = target;
+                    if (subtrees[0].treeTag == TreeTag.INT && subtrees[1].treeTag == TreeTag.INT) {
+                        Type owntype = new Type(TypeToken.INTEGER);
+                        return owntype.compatibleWith(target) ? owntype : errType;
+                    } else {
+                        for (int i = 0; i < subtrees.length; i++) {
+                            if (subtrees[i].typeCheck(target, argtypes).isErroneous()) {
+                                return errType;
+                            }
+                        }
+                        return target;
+                    }
+                default:
+                    throw new AssertionError();
+            }
+        }
+    }
+
+    enum TreeTag implements StackItem<TreeTag> {
+        INT("1", 0),
+        STRING("\"\"", 0),
+        COND("true ? %s : %s", 2),
+        EXPR_LAMBDA("(%s)->%s", 2),
+        IMPLICIT_1("x1", 0),
+        IMPLICIT_2("x2", 0),
+        IMPLICIT_3("x3", 0),
+        EXPLICIT_1("#{ARG_SHAPE_1} x1", 0),
+        EXPLICIT_2("#{ARG_SHAPE_2} x2", 0),
+        EXPLICIT_3("#{ARG_SHAPE_3} x3", 0);
+
+        String treeStr;
+        int arity;
+
+        TreeTag(String treeStr, int arity) {
+            this.treeStr = treeStr;
+            this.arity = arity;
+        }
+
+        public int arity() {
+            return arity;
+        }
+
+        Tree apply(Tree... args) {
+            return new Tree(this, args);
+        }
+
+        int argIndex() {
+            switch (this) {
+                case EXPLICIT_1:
+                    return 0;
+                case EXPLICIT_2:
+                    return 1;
+                case EXPLICIT_3:
+                    return 2;
+                default:
+                    return -1;
+            }
+        }
+    }
+
+    enum TreeShape implements Template, StackReducer<TreeTag, Tree, Void> {
+        LAMBDA_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.INT),
+        LAMBDA_STRING(1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.STRING),
+        LAMBDA_COND_INT_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.INT, TreeTag.INT),
+        IMPL_LAMBDA_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_1, TreeTag.INT),
+        IMPL_LAMBDA_STRING(1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_1, TreeTag.STRING),
+        IMPL_LAMBDA_COND_INT_INT(1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_1, TreeTag.COND, TreeTag.INT, TreeTag.INT),
+        LAMBDA_LAMBDA_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.INT),
+        LAMBDA_LAMBDA_STRING(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.STRING),
+        LAMBDA_LAMBDA_COND_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT),
+        LAMBDA_IMPL_LAMBDA_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.INT),
+        LAMBDA_IMPL_LAMBDA_STRING(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.STRING),
+        LAMBDA_IMPL_LAMBDA_COND_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT),
+        LAMBDA_COND_LAMBDA_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.INT, TreeTag.INT),
+        LAMBDA_COND_LAMBDA_STRING_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.STRING, TreeTag.INT),
+        LAMBDA_COND_LAMBDA_COND_INT_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT, TreeTag.INT),
+        LAMBDA_COND_IMPL_LAMBDA_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.INT, TreeTag.INT),
+        LAMBDA_COND_IMPL_LAMBDA_STRING_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.STRING, TreeTag.INT),
+        LAMBDA_COND_IMPL_LAMBDA_COND_INT_INT_INT(2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.COND, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_2, TreeTag.COND, TreeTag.INT, TreeTag.INT, TreeTag.INT),
+        LAMBDA_LAMBDA_LAMBDA_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_3, TreeTag.INT),
+        LAMBDA_LAMBDA_LAMBDA_STRING(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_3, TreeTag.STRING),
+        LAMBDA_LAMBDA_LAMBDA_COND_INT_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_3, TreeTag.COND, TreeTag.INT, TreeTag.INT),
+        LAMBDA_LAMBDA_IMPL_LAMBDA_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_3, TreeTag.INT),
+        LAMBDA_LAMBDA_IMPL_LAMBDA_STRING(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_3, TreeTag.STRING),
+        LAMBDA_LAMBDA_IMPL_LAMBDA_COND_INT_INT(3, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_1, TreeTag.EXPR_LAMBDA, TreeTag.EXPLICIT_2, TreeTag.EXPR_LAMBDA, TreeTag.IMPLICIT_3, TreeTag.COND, TreeTag.INT, TreeTag.INT);
+
+        TreeTag[] treeTags;
+        int depth;
+
+        TreeShape(int depth, TreeTag... treeTags) {
+            this.depth = depth;
+            this.treeTags = treeTags;
+        }
+
+        Tree compute() {
+            return process(treeTags, this, null);
+        }
+
+        public String expand(String selector) {
+            return compute().toString();
+        }
+
+        public Tree reduce(TreeTag tag, Tree[] args, Void _unused) {
+            return new Tree(tag, args);
+        }
+
+        public Void reducerArg(TreeTag item, int i) { return null; }
+
+        public Class<Tree> resultToken() {
+            return Tree.class;
+        }
+    }
+
+    static class Type {
+        TypeToken typeToken;
+        Type[] typeargs;
+
+        Type(TypeToken typeToken, Type... typeargs) {
+            this.typeToken = typeToken;
+            this.typeargs = typeargs;
+        }
+
+        public String toString() {
+            Object[] typeargStrings = new Object[typeargs.length];
+            for (int i = 0; i < typeargs.length; i++) {
+                typeargStrings[i] = typeargs[i].toString();
+            }
+            return String.format(typeToken.tokenStr, typeargStrings);
+        }
+
+        boolean isErroneous() { return false; }
+
+        Type getReturnType() {
+            return typeToken == TypeToken.SAM ?
+                typeargs[1] : null;
+        }
+
+        Type getArgType() {
+            return typeToken == TypeToken.SAM ?
+                typeargs[0] : null;
+        }
+
+        boolean isFree() {
+            switch (typeToken) {
+                case A:
+                case R:
+                    return true;
+                default:
+                    for (Type t : typeargs) {
+                        if (t.isFree()) return true;
+                    }
+                    return false;    
+            }
+        }
+
+        boolean isFreeVar() {
+            switch (typeToken) {
+                case A:
+                case R:
+                    return true;
+                default:                    
+                    return false;    
+            }
+        }
+
+        boolean compatibleWith(Type that) {
+            if (that.isFreeVar()) {
+                return true;
+            } else {
+                if (typeToken != that.typeToken)
+                    return false;
+                if (typeargs.length != that.typeargs.length) {
+                    return false;
+                }
+                for (int i = 0; i < typeargs.length ; i++) {
+                    if (!typeargs[i].compatibleWith(that.typeargs[i]))
+                        return false;
+                }
+                return true;
+            }
+        }
+    }
+
+    static Type errType = new Type(null) {
+        boolean isErroneous() {
+            return true;
+        }
+    };
+
+    enum TypeToken implements StackItem<TypeToken> {
+        STRING("String", 0),
+        INTEGER("Integer", 0),
+        A("A", 0),
+        R("R", 0),
+        LIST("List<%s>", 1),
+        SAM("SAM<%s,%s>", 2);
+
+        int arity;
+        String tokenStr;
+
+        TypeToken(String tokenStr, int arity) {
+            this.tokenStr = tokenStr;
+            this.arity = arity;
+        }
+
+        public int arity() {
+            return arity;
+        }
+    }
+
+    enum ArgTypeShape implements Template, StackReducer<TypeToken, Type, Void> {
+        STRING(TypeToken.STRING),
+        INTEGER(TypeToken.INTEGER),
+        LIST_STRING(TypeToken.LIST, TypeToken.STRING),
+        LIST_INTEGER(TypeToken.LIST, TypeToken.INTEGER);
+
+        TypeToken[] tokens;
+
+        ArgTypeShape(TypeToken... tokens) {
+            this.tokens = tokens;
+        }
+
+        Type compute() {
+            return process(tokens, this, null);
+        }
+
+        public String expand(String selector) {
+            return compute().toString();
+        }
+
+        public Type reduce(TypeToken token, Type[] args, Void _unused) {
+            return new Type(token, args);
+        }
+
+        public Void reducerArg(TypeToken item, int i) { return null; }
+
+        public Class<Type> resultToken() {
+            return Type.class;
+        }
+    }
+
+    enum FormalTypeShape implements Template, StackReducer<TypeToken, Type, Void> {
+        SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.STRING),
+        SAM_Integer_String(TypeToken.SAM, TypeToken.INTEGER, TypeToken.STRING),
+        SAM_List_String_String(TypeToken.SAM, TypeToken.LIST, TypeToken.STRING, TypeToken.STRING),
+        SAM_List_Integer_String(TypeToken.SAM, TypeToken.LIST, TypeToken.INTEGER, TypeToken.STRING),
+        SAM_A_String(TypeToken.SAM, TypeToken.A, TypeToken.STRING),
+        SAM_List_A_String(TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.STRING),
+        SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.R),
+        SAM_A_R(TypeToken.SAM, TypeToken.A, TypeToken.R),
+        SAM_List_A_R(TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.R),
+        SAM_String_SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING),
+        SAM_String_SAM_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.INTEGER, TypeToken.STRING),
+        SAM_String_SAM_List_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.STRING, TypeToken.STRING),
+        SAM_String_SAM_List_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.INTEGER, TypeToken.STRING),
+        SAM_String_SAM_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.STRING),
+        SAM_String_SAM_List_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.STRING),
+        SAM_String_SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.R),
+        SAM_String_SAM_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.R),
+        SAM_String_SAM_List_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.R),
+        SAM_A_SAM_String_String(TypeToken.SAM, TypeToken.A, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.INTEGER, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_List_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.STRING, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_List_Integer_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.INTEGER, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_List_A_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.STRING),
+        SAM_String_SAM_String_SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.R),
+        SAM_String_SAM_String_SAM_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.R),
+        SAM_String_SAM_String_SAM_List_A_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.LIST, TypeToken.A, TypeToken.R),
+        SAM_String_SAM_A_SAM_String_String(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.SAM, TypeToken.STRING, TypeToken.STRING),
+        SAM_String_SAM_A_SAM_String_R(TypeToken.SAM, TypeToken.STRING, TypeToken.SAM, TypeToken.A, TypeToken.SAM, TypeToken.STRING, TypeToken.R);
+
+        TypeToken[] tokens;
+
+        FormalTypeShape(TypeToken... tokens) {
+            this.tokens = tokens;
+        }
+
+        Type compute() {
+            return process(tokens, this, null);
+        }
+
+        public String expand(String selector) {
+            return compute().toString();
+        }
+
+        public Type reduce(TypeToken token, Type[] args, Void _unused) {
+            return new Type(token, args);
+        }
+
+        public Void reducerArg(TypeToken item, int i) { return null; }
+
+        public Class<Type> resultToken() {
+            return Type.class;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/LambdaReturnAdaptationTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import tools.javac.combo.*;
+
+import java.lang.reflect.Method;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * LambaReturnAdaptationTest
+ */
+public class LambdaReturnAdaptationTest extends ComboTestBase<LambdaReturnAdaptationTest> {
+    @Factory
+    public static Object[] testReturnAdaptation() throws Exception {
+        return factory(LambdaReturnAdaptationTest.class);
+    }
+
+    @DimensionVar("FROM") Types fromType;
+    @DimensionVar("TO") Types toType;
+
+    @SourceFile("Sam.java")
+    String samFile = "public interface Sam { #{TO} m(int arg); }";
+
+    @SourceFile("Main.java")
+    String clientFile = "public class Main {\n"
+                        +"  static #{FROM} m(int arg) { \n"
+                        +"    #{RET};\n"
+                        +"  }\n"
+                        +"  public #{TO} main() { \n"
+                        + "   Sam s = Main::m;\n"
+                        + "   #{RET_MAIN};\n"
+                        + " }\n"
+                        +"}";
+
+    @TemplateVar("RET")
+    Template retTemplate = new Template() {
+        public String expand(String selector) {
+            if (fromType == Types.VOID)
+                return "";
+            else if (fromType == Types.STRING)
+                return "return \"66\"";
+            else if (fromType == Types.BOOLEAN || fromType == Types.BOXED_BOOLEAN)
+                return "return true";
+            else if (fromType.unboxed != null)
+                return "return (" + fromType.unboxed.name + ") arg";
+            else
+                return "return (" + fromType.name + ") arg";
+        }
+    };
+
+    @TemplateVar("RET_MAIN")
+    Template retMainTemplate = new Template() {
+        public String expand(String selector) {
+            return toType == Types.VOID ? "s.m(66)" : "return s.m(66)";
+        }
+    };
+
+    @Override
+    protected String[] getCompileOptions(String group) {
+        return new String[] { "-XDlambdaToMethod" };
+    }
+
+    @Override
+    protected void postCompile(String group) {
+        if (fromType != Types.VOID && toType == Types.VOID)
+            assertCompileSucceeded();
+        else if (fromType == Types.VOID && toType != Types.VOID)
+            assertCompileFailed();
+        else if (fromType == Types.VOID && toType == Types.VOID)
+            assertCompileSucceeded();
+        else if (fromType.pr == PR.REF && toType.pr == PR.REF)
+            assertCompileSucceededIff(toType.clazz.isAssignableFrom(fromType.clazz));
+        else if (fromType.pr == PR.PRIM && toType.pr == PR.REF)
+            assertCompileSucceededIff(toType.clazz.isAssignableFrom(Types.boxMap.get(fromType).clazz));
+        else if (fromType.pr == PR.REF && toType.pr == PR.PRIM)
+            assertCompileSucceededIff(fromType.unboxed != null && Types.widenMap.get(fromType.unboxed).contains(toType));
+        else if (fromType.pr == PR.PRIM && toType.pr == PR.PRIM)
+            assertCompileSucceededIff(Types.widenMap.get(fromType).contains(toType));
+        else
+            assertCompileSucceeded();
+    }
+
+    @Override
+    protected boolean shouldRun() { return true; }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Method m = clazz.getMethod("main");
+        Object obj = clazz.newInstance();
+        Object in = 66;
+        Object out = m.invoke(obj);
+        if (toType == Types.VOID)
+            assertTrue(out == null);
+        else if (fromType == Types.BOOLEAN || fromType == Types.BOXED_BOOLEAN)
+            assertEquals("true", out.toString());
+        else
+            assertEquals(in.toString(), out.toString().replace("B", "66").replace(".0", ""));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/MethodRefCaptureTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import tools.javac.combo.*;
+
+/**
+ * MethodRefCaptureTest
+ *
+ * @author Brian Goetz
+ */
+public class MethodRefCaptureTest extends ComboTestBase<MethodRefCaptureTest> {
+    @Factory
+    public static Object[] testCombo() throws Exception {
+        return factory(MethodRefCaptureTest.class);
+    }
+
+    @DimensionVar("VAR") ContextKind context;
+    @DimensionVar("LOCATION") LocationKind location;
+    @DimensionVar("ACC") AccessibilityKind accessibility;
+    @DimensionVar("METHOD") RefKind ref;
+
+    @TemplateVar("PACKAGE")
+    String makePackage() {
+        return location == LocationKind.OTHER_PACKAGE ? "package a;" : "";
+    }
+
+    // @@@ not yet used
+    @TemplateVar("MAIN") String main = "public static void main(String[] args) { #{METHOD.SAMTYPE} x = #{VAR.REF}";
+
+    @SourceFile("Sam1.java") String sam1 = "#{PACKAGE} \npublic interface Sam1 { public String get(String s); }";
+    @SourceFile("Sam2.java") String sam2 = "#{PACKAGE} \npublic interface Sam2<T> { public String get(T target, String s); }";
+    @SourceFile("Sam3.java") String sam3 = "#{PACKAGE} \npublic interface Sam3<T> { public T get(String s); }";
+    @SourceFile("A.java") String mainFile = "#{LOCATION.CAPTURING_CLASS}";
+    @SourceFile("Target.java") String extFile = "#{LOCATION.EXT_CLASS}";
+
+    @Override
+    protected String[] getCompileOptions(String group) {
+        return new String[] { "-XDlambdaToMethod" };
+    }
+
+    @Override
+    protected void postCompile(String group) {
+        if (location == LocationKind.OTHER_FILE && accessibility == AccessibilityKind.PRIVATE)
+            assertCompileFailed();
+        else if (location == LocationKind.OTHER_PACKAGE && accessibility != AccessibilityKind.PUBLIC)
+            assertCompileFailed();
+        else
+            assertCompileSucceeded();
+    }
+
+
+    static enum ContextKind implements Template {
+        STATIC_FIELD_INIT("static #{METHOD.SAMTYPE} var = #{METHOD.MREF};"),
+        STATIC_FIELD_CLINIT("static #{METHOD.SAMTYPE} var; static { var = #{METHOD.MREF}; };"),
+        INSTANCE_FIELD_INIT("#{METHOD.SAMTYPE} var = #{METHOD.MREF};"),
+        LOCAL_VAR("void m() { #{METHOD.SAMTYPE} var = #{METHOD.MREF}; };"),
+        METHOD_CALL("static void m(#{METHOD.SAMTYPE} s) { }; static void m() { m(#{METHOD.MREF}); };"),
+        RETURN("#{METHOD.SAMTYPE} m() { return #{METHOD.MREF}; };"),
+        ARRAY_INITIALIZER("#{METHOD.SAMTYPE}[] var = (#{METHOD.SAMTYPE}[]) new #{METHOD.ERASED_SAMTYPE}[] { (#{METHOD.SAMTYPE}) #{METHOD.MREF} };"),
+        CONDITIONAL("#{METHOD.SAMTYPE} var = new Object().equals(new Object()) ? #{METHOD.MREF} : #{METHOD.MREF};"),
+        CAST("#{METHOD.SAMTYPE} var = (#{METHOD.SAMTYPE}) #{METHOD.MREF};");
+
+        private final String t1;
+
+        ContextKind(String t1) { this.t1 = t1; }
+
+        public String expand(String selector) {
+            switch (selector) {
+                case "DECL": return t1;
+                default:     throw new IllegalArgumentException(selector);
+            }
+        }
+    }
+
+    static enum LocationKind implements Template {
+        SAME_CLASS("class Target { \n#{VAR.DECL} \n#{METHOD.DECL} }"),
+        ENCLOSING_CLASS("class Target { \n#{METHOD.DECL} \nstatic class Capturing { #{VAR.DECL} } }"),
+        SIBLING_INNER_CLASS("class Outer { \nstatic class Capturing { #{VAR.DECL} }  \nstatic class Target { #{METHOD.DECL} } }"),
+        NESTED_CLASS("class Capturing { \n#{VAR.DECL} \nstatic class Target { #{METHOD.DECL} } }"),
+        OTHER_FILE("class Capturing { \n#{VAR.DECL} }", "class Target { \n#{METHOD.DECL} }"),
+        OTHER_PACKAGE("package a; \nimport b.*; \nclass Capturing { \n#{VAR.DECL} }",
+                      "package b; \npublic class Target { \n#{METHOD.DECL} }");
+
+        private final String t1, t2;
+
+        LocationKind(String t1, String t2) {
+            this.t1 = t1;
+            this.t2 = t2;
+        }
+        LocationKind(String t1) { this(t1, "class Unused {}"); }
+
+        public String expand(String selector) {
+            switch (selector) {
+                case "CAPTURING_CLASS": return t1;
+                case "EXT_CLASS":       return t2;
+                default:                throw new IllegalArgumentException(selector);
+            }
+        }
+    }
+
+    static enum AccessibilityKind implements Template {
+        PUBLIC("public"),
+        PROTECTED("protected"),
+        PACKAGE(""),
+        PRIVATE("private");
+
+        private final String template;
+
+        AccessibilityKind(String template) { this.template = template; }
+
+        public String expand(String selector) { return template; }
+    }
+
+    static enum RefKind implements Template {
+        STATIC(0, "Target::staticMethod", "static #{ACC} String staticMethod(String s) { return \"1\"; }"),
+        UNBOUND_INSTANCE(1, "Target::instanceMethod", "#{ACC} String instanceMethod(String s) { return \"2\"; }"),
+        BOUND_INSTANCE(0, "(new Target())::instanceMethod", "#{ACC} String instanceMethod(String s) { return \"3\"; }"),
+        CTOR(2, "Target::new", "#{ACC} Target(String s) { }"),
+//    UNBOUND_INNER_CTOR,
+//    BOUND_INNER_CTOR
+//    , SUPER
+        ;
+
+        private static final String[] sams = { "Sam1", "Sam2<Target>", "Sam3<Target>" };
+        private final int samNo;
+        private final String t1, t2;
+
+        RefKind(int samNo, String t1, String t2) { this.samNo = samNo; this.t1 = t1; this.t2 = t2; }
+
+        public String expand(String selector) {
+            switch (selector) {
+                case "MREF": return t1;
+                case "DECL": return t2;
+                case "SAMTYPE": return sams[samNo];
+                case "ERASED_SAMTYPE": return sams[samNo].replaceAll("<Target>", "<?>");
+                default:   throw new IllegalArgumentException(selector);
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/NestedGenericMethodCallTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+import tools.javac.combo.ComboTestBase;
+import tools.javac.combo.DimensionVar;
+import tools.javac.combo.SourceFile;
+import tools.javac.combo.Template;
+
+import static tools.javac.combo.StackProcessingUtils.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * NestedGenericMethodCallTest
+ */
+public class NestedGenericMethodCallTest extends ComboTestBase<NestedGenericMethodCallTest> {
+    @Factory
+    public static Object[] testNestedGenericMethodCallType() throws Exception {
+        return factory(NestedGenericMethodCallTest.class);
+    }
+
+    @Test(enabled=false)
+    public void test() throws Exception {
+        //disabled as the test has never been updated to support graph inference
+        super.test();
+    }
+
+    @DimensionVar("ID_METHOD") IdMethod idMethod;
+    @DimensionVar("NIL_METHOD") NilMethod nilMethod;
+    @DimensionVar("CONS_METHOD") ConsMethod consMethod;
+    @DimensionVar("SHAPE") Shape shape;
+    @DimensionVar("TARGET") Type target;
+
+    @SourceFile("Main.java")
+    String clientFile = "import java.util.*;\n"
+            +"public class Main {\n"
+            +"  #{ID_METHOD}\n"
+            +"  #{NIL_METHOD}\n"
+            +"  #{CONS_METHOD}\n"
+            +"  void test() { \n"
+            + "   #{TARGET} t = #{SHAPE};\n"
+            + " }\n"
+            +"}";
+
+    @Override
+    protected void postCompile(String grp) {
+        Type res = shape.compile(idMethod, nilMethod, consMethod, target);
+        if (res.asSubtypeOf(target).isError()) {
+            assertCompileFailed("Bad result = " + res);
+        } else {
+            assertCompileSucceeded();
+        }
+    }
+
+    @Override
+    protected boolean shouldSkip() {
+        return target.free || target == Type.ERROR;
+    }
+
+    enum Type implements Template {
+        Z("Z", true),
+        OBJECT("Object", false),
+        STRING("String", false),
+        LIST_Z("List<Z>", true),
+        LIST_OBJECT("List<Object>", false),
+        LIST_STRING("List<String>", false),
+        ERROR("<any>", false);
+
+        String typeStr;
+        boolean free;
+
+        Type(String typeStr, boolean free) {
+            this.typeStr = typeStr;
+            this.free = free;
+        }
+
+        boolean isError() {
+            return this == ERROR;
+        }
+
+        Type asSubtypeOf(Type that) {
+            return asSubtypeMap[this.ordinal()][that.ordinal()];
+        }
+ 
+        boolean isSubtypeOf(Type that) {
+            return !asSubtypeOf(that).isError();
+        }
+
+        public String expand(String selector) {
+            return typeStr;
+        }
+
+        enum ConstraintKind {
+            Z_EXT_OBJ(false, OBJECT),
+            Z_EXT_STRING(false, STRING),
+            Z_EXT_LIST_OBJECT(false, LIST_OBJECT),
+            Z_EXT_LIST_STRING(false, STRING),
+            Z_SUP_OBJECT(true, OBJECT),
+            Z_SUP_STRING(true, STRING),
+            Z_SUP_LIST_OBJECT(true, LIST_OBJECT),
+            Z_SUP_LIST_STRING(true, LIST_STRING),
+            ERROR(false, Type.ERROR);
+
+            boolean isSuper;
+            Type type;
+
+            ConstraintKind(boolean isSuper, Type type) {
+                this.isSuper = isSuper;
+                this.type = type;
+            }
+        }
+
+        static Type[][] asSubtypeMap = new Type[][] {
+                //                   Z           OBJECT      STRING       LIST_Z      LIST_OBJECT      LIST_STRING        ERROR
+                { /* Z           */  OBJECT     ,OBJECT     ,STRING      ,ERROR      ,LIST_OBJECT     ,LIST_STRING       ,ERROR        },
+                { /* OBJECT      */  OBJECT     ,OBJECT     ,ERROR       ,ERROR      ,ERROR           ,ERROR             ,ERROR        },
+                { /* STRING      */  STRING     ,STRING     ,STRING      ,ERROR      ,ERROR           ,ERROR             ,ERROR        },
+                { /* LIST_Z      */  LIST_OBJECT,LIST_OBJECT,ERROR       ,LIST_OBJECT,LIST_OBJECT     ,LIST_STRING       ,ERROR        },
+                { /* LIST_OBJECT */  LIST_OBJECT,LIST_OBJECT,ERROR       ,LIST_OBJECT,LIST_OBJECT     ,ERROR             ,ERROR        },
+                { /* LIST_STRING */  LIST_STRING,LIST_STRING,ERROR       ,LIST_STRING,ERROR           ,LIST_STRING       ,ERROR        },
+                { /* ERROR       */  ERROR      ,ERROR      ,ERROR       ,ERROR      ,ERROR           ,ERROR             ,ERROR        }};
+
+        static boolean isSubtypes(Type[] ts1, Type[] ts2) {
+            assertEquals(ts1.length, ts2.length);
+            for (int i = 0; i < ts1.length ; i++) {
+                if (!ts1[i].isSubtypeOf(ts2[i])) return false;
+            }
+            return true;
+        }
+
+        static Type listOf(Type t) {
+            switch (t) {
+                case OBJECT: return LIST_OBJECT;
+                case STRING: return LIST_STRING;
+                case Z: return LIST_Z;              
+                default: return ERROR;
+            }
+        }
+
+        static Type elemtype(Type t) {
+            switch (t) {
+                case LIST_OBJECT: return OBJECT;
+                case LIST_STRING: return STRING;
+                case LIST_Z: return Z;
+                default: return ERROR;
+            }
+        }   
+
+        static Type lub(Type t1, Type t2) {
+            if (!t1.asSubtypeOf(t2).isError()) {
+                return t2;
+            } else if (!t2.asSubtypeOf(t1).isError()) {
+                return t1;
+            } else {
+                return Type.ERROR;
+            }
+        }
+    }
+
+    interface MethodSig {
+        Type apply(Type target, Type... argTypes);
+        Type[] getFormals();
+    }
+
+    enum IdMethod implements Template, MethodSig {
+        NON_GENERIC_1("String id(String s) { return null; };", Type.STRING),
+        NON_GENERIC_2("List<String> id(List<String> s) { return null; };", Type.LIST_STRING),
+        GENERIC_1("<Z> Z id(Z z) { return null; };", Type.Z),
+        GENERIC_2("<Z> List<Z> id(List<Z> z) { return null; };", Type.LIST_Z);
+
+        String sig;
+        Type formal;
+
+        IdMethod(String sig, Type formal) {
+            this.sig = sig;
+            this.formal = formal;
+        }
+
+        public String expand(String selector) {
+            return sig;
+        }
+
+        public Type apply(Type target, Type... argTypes) {
+            return argTypes[0].asSubtypeOf(formal);
+        }
+
+        public Type[] getFormals() {
+            return new Type[] { formal };
+        }
+    }
+
+    enum NilMethod implements Template, MethodSig {
+        NON_GENERIC("List<String> nil() { return null; }", Type.LIST_STRING),
+        GENERIC("<Z> List<Z> nil() { return null; }", Type.LIST_Z);
+
+        String sig;
+        Type returnType;
+
+        NilMethod(String sig, Type returnType) {
+            this.sig = sig;
+            this.returnType = returnType;
+        }
+
+        public String expand(String selector) {
+            return sig;
+        }
+
+        public Type apply(Type target, Type... argTypes) {            
+            return this == NON_GENERIC ?
+                Type.LIST_STRING :
+                returnType.asSubtypeOf(target);
+        }
+
+        public Type[] getFormals() {
+            return null;
+        }
+    }
+
+    enum ConsMethod implements Template, MethodSig {
+        NON_GENERIC("List<String> cons(String s, List<String> ls) { return null; }", Type.STRING, Type.LIST_STRING) {
+            Type getReturnType(Type target, Type... argTypes) { return Type.LIST_STRING; }
+        },
+        GENERIC_1("<Z> List<Z> cons(Z z, List<String> ls) { return null; }", Type.Z, Type.LIST_STRING) {
+            Type getReturnType(Type target, Type... argTypes) { 
+                 switch (target) {
+                     case LIST_OBJECT:
+                     case LIST_STRING:
+                        return Type.LIST_Z.asSubtypeOf(target);
+                     default:
+                        return Type.listOf(argTypes[0].asSubtypeOf(Type.Z));
+                 }
+            }
+        },
+        GENERIC_2("<Z> List<Z> cons(String s, List<Z> lz) { return null; }", Type.STRING, Type.LIST_Z) {
+            Type getReturnType(Type target, Type... argTypes) { return Type.listOf(Type.elemtype(argTypes[1].asSubtypeOf(Type.LIST_Z))); }
+        },
+        GENERIC_3("<Z> List<Z> cons(Z z, List<Z> lz) { return null; }", Type.Z, Type.LIST_Z) {
+            Type getReturnType(Type target, Type... argTypes) {
+                Type lub = Type.lub(argTypes[0], Type.elemtype(argTypes[1].asSubtypeOf(Type.LIST_Z)));
+                return lub.isError() ? lub : Type.listOf(lub);
+            }
+        },
+        GENERIC_4("<U, V> List<U> cons(U z, List<V> lz) { return null; }", Type.Z, Type.LIST_Z) {
+            Type getReturnType(Type target, Type... argTypes) { 
+                switch (target) {
+                    case LIST_OBJECT:
+                    case LIST_STRING:
+                        return Type.LIST_Z.asSubtypeOf(target);
+                    default:
+                        return Type.listOf(argTypes[0].asSubtypeOf(Type.Z));
+                }
+            }
+        };
+
+        String sig;
+        Type[] formals;
+
+        ConsMethod(String sig, Type... formals) {
+            this.sig = sig;
+            this.formals = formals;
+        }
+
+        public String expand(String selector) {
+            return sig;
+        }
+
+        public Type apply(Type target, Type... argTypes) {
+            return Type.isSubtypes(argTypes, formals) ?
+                    getReturnType(target, argTypes) : Type.ERROR;
+        }
+
+        abstract Type getReturnType(Type target, Type... argTypes);
+
+        public Type[] getFormals() {
+            return formals;
+        }
+    }
+
+    enum Token implements StackItem<Token> {
+        NIL(0, "nil"),
+        DIAMOND(0, "new ArrayList<>"),
+        STRING(0, "\"\""),
+        ID(1, "id"),
+        CONS(2, "cons");
+
+        int arity;
+        String tokenStr;
+
+        Token(int arity, String tokenStr) {
+            this.arity = arity;
+            this.tokenStr = tokenStr;
+        }
+
+        public int arity() { return arity; }
+    }
+
+    enum Shape implements Template {
+        NIL(Token.NIL),
+        ID_NIL(Token.ID, Token.NIL),
+        ID_ID_NIL(Token.ID, Token.ID, Token.NIL),
+        CONS_STRING_NIL(Token.CONS, Token.STRING, Token.NIL),
+        CONS_STRING_ID_NIL(Token.CONS, Token.STRING, Token.ID, Token.NIL),
+        CONS_ID_STRING_NIL(Token.CONS, Token.ID, Token.STRING, Token.NIL),
+        CONS_ID_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL),
+        CONS_ID_STRING_CONS_STRING_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.NIL),
+        CONS_ID_STRING_CONS_ID_STRING_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.NIL),
+        CONS_ID_STRING_CONS_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.ID, Token.NIL),
+        CONS_ID_STRING_CONS_ID_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL),
+        CONS_ID_STRING_ID_CONS_ID_STRING_ID_NIL(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL),
+        ID_CONS_ID_STRING_ID_CONS_ID_STRING_ID_NIL(Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.NIL),
+        DIAMOND(Token.DIAMOND),
+        ID_DIAMOND(Token.ID, Token.DIAMOND),
+        CONS_STRING_DIAMOND(Token.CONS, Token.STRING, Token.DIAMOND),
+        CONS_STRING_ID_DIAMOND(Token.CONS, Token.STRING, Token.ID, Token.DIAMOND),
+        CONS_ID_STRING_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.DIAMOND),
+        CONS_ID_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND),
+        CONS_ID_STRING_CONS_STRING_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.DIAMOND),
+        CONS_ID_STRING_CONS_ID_STRING_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.DIAMOND),
+        CONS_ID_STRING_CONS_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.STRING, Token.ID, Token.DIAMOND),
+        CONS_ID_STRING_CONS_ID_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND),
+        CONS_ID_STRING_ID_CONS_ID_STRING_ID_DIAMOND(Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND),
+        ID_CONS_ID_STRING_ID_CONS_ID_STRING_ID_DIAMOND(Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.CONS, Token.ID, Token.STRING, Token.ID, Token.DIAMOND);
+
+        Token[] tokens;
+
+        Shape(Token... tokens) {
+            this.tokens = tokens;
+        }
+
+        Type compile(final IdMethod idMethod, final NilMethod nilMethod, final ConsMethod consMethod, Type target) {
+            return process(tokens, new StackReducer<Token, Type, Type>() {
+                public Type reduce(Token t, Type[] operands, Type target) {
+                    switch (t) {
+                        case DIAMOND: return Type.LIST_Z.asSubtypeOf(target);
+                        case NIL: return nilMethod.apply(target, operands);
+                        case STRING: return Type.STRING;
+                        case ID: return idMethod.apply(target, operands);
+                        case CONS: return consMethod.apply(target, operands);
+                        default: throw new AssertionError();
+                    }
+                }
+                public Class<Type> resultToken() { return Type.class; }
+                public Type reducerArg(Token item, int i) {
+                    switch (item) {
+                        case ID:
+                            return idMethod.getFormals()[i];
+                        case CONS:
+                            return consMethod.getFormals()[i];
+                        default: return Type.OBJECT;
+                    }
+                }
+            }, target);
+        }
+
+        public String expand(String selector) {
+            return process(tokens, new StackReducer<Token, String, Void>() {
+                public String reduce(Token t, String[] operands, Void _unused) {
+                    switch (t) {
+                        case DIAMOND:
+                        case NIL:
+                        case ID:
+                        case CONS:
+                            StringBuilder buf = new StringBuilder();
+                            String sep = "";
+                            for (int i = 0; i < t.arity; i ++) {
+                                buf.append(sep);
+                                buf.append(operands[i]);
+                                sep = ",";
+                            }
+                            buf.insert(0, "(");
+                            buf.insert(0, t.tokenStr);
+                            buf.append(")");
+                            return buf.toString();
+                        case STRING:
+                            return t.tokenStr;
+                        default: throw new AssertionError();
+                    }
+                }
+                public Class<String> resultToken() { return String.class; }
+                public Void reducerArg(Token item, int i) { return null; }
+            }, null);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/SourceTargetVersionTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.testng.annotations.Factory;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import tools.javac.combo.*;
+
+/**
+ * SourceTargetVersionTest: 
+ * Test source and class file compatibility by compiling and running lambda specific code 
+ * against some class files compiled separately with different source and target option 
+ * (1.5, 1.6, and 1.7).
+ * The goal is achieved by putting source files in different groups (A, B, C..,), each group 
+ * is set with its own compile options, and we compile in the reverse alphebetic order for the 
+ * groups (..., C, B, A) to set a previously compiled group of files as classpath for the next group. 
+ * And when executing, we Run class Main with classpath A:B:C... in the order. 
+ * 
+ */
+public class SourceTargetVersionTest extends ComboTestBase<SourceTargetVersionTest> {
+    @Factory
+    public static Object[] testSourceTarget() throws Exception {
+        return factory(SourceTargetVersionTest.class);
+    }
+   
+    @DimensionVar("SHAPE") CShapes shapeType;
+    @DimensionVar("CLIENT_CODE") ClientType clientType;
+    @DimensionVar("RELEASE") ReleaseVersion rv;
+    
+    @SourceFile(value="A.java", group="B")
+    String interfaceA = "interface A { #{SHAPE.METHOD} }";    
+    
+    @SourceFile(value="B.java", group="A")
+    String interfaceB = "interface B #{SHAPE.EXTEND} { default String m() { return \"B\"; } }";
+    
+    @SourceFile(value="C.java", group="A")
+    String classC = "class C #{SHAPE.IMPLEMENT} {\n" +
+                    "    #{CLIENT_CODE}\n" +
+                    "}";
+    
+    @SourceFile(value="Main.java", group="A")
+    String classMain = "public class Main {\n" +
+                       "    public String main() {\n" +
+                       "        return new C().m();\n" +                       
+                       "    }\n" +
+                       "}";
+    
+    @TemplateVar("LAMBDA_EXP") String le = "public String m() {\n" +
+                                           "    A a = () -> \"A\";\n" +
+                                           "    return a.m();\n" +
+                                           "}";
+    @TemplateVar("METHOD_REF") String mr = "String foo() {\n" +
+                                           "    return \"foo\";\n" +
+                                           "}\n\n" +
+                                           
+                                           "public String m() {\n" +
+                                           "    A a = this::foo;\n" +
+                                           "    return a.m();\n" +
+                                           "}";
+    
+    @Override
+    protected boolean shouldSkip() {
+        return (shapeType == CShapes.C_AB && clientType != ClientType.DEF_MED) ||
+               (shapeType == CShapes.C && clientType == ClientType.DEF_MED);
+    }
+
+    @Override
+    protected boolean shouldRun() { return true; }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Method m = clazz.getMethod("main");
+        Object obj = clazz.newInstance();
+        String result = (String) m.invoke(obj);
+        String expected = clientType.returnValue;
+        assertEquals(result, expected);
+    }
+    
+    @Override
+    protected String[] getCompileOptions(String group) {
+        switch(group) {
+            case "B": return new String[]{"-source", rv.versionStr, "-target", rv.versionStr};
+            default: return new String[0];
+        }
+    }
+       
+    enum CShapes implements Template { //shapes of class hirarchy
+        //class C implements interface A, B
+        C_AB("", "", "implements A, B"), 
+        //class C implments interface B, B extends interface A
+        C_B_A("String m();", "extends A", "implements B"), 
+        //class C
+        C("String m();", "", ""); 
+        
+        private final String absMethod;
+        private final String extend;
+        private final String implement;
+        
+        CShapes(String absMethod, String extend, String implement) {
+            this.absMethod = absMethod;
+            this.extend = extend;
+            this.implement = implement;
+        }
+                
+        public String expand(String selector) {
+            switch(selector) {
+                case "METHOD": return absMethod;
+                case "EXTEND": return extend;
+                case "IMPLEMENT": return implement;
+                default: return toString();
+            }
+        }        
+    }
+    
+    enum ClientType implements Template { // jdk8 specific code in client program
+        LAMBDA_EXP("#{LAMBDA_EXP}", "A"), // lambda expressions
+        METHOD_REF("#{METHOD_REF}", "foo"), // method references
+        DEF_MED("", "B"); // default method inheritance
+        
+        private final String clientCode;
+        private final String returnValue;
+        
+        ClientType(String str, String ret) {
+            clientCode = str;
+            returnValue = ret;
+        }
+        
+        public String expand(String selector) {
+            return clientCode;        
+        }
+    }
+    
+    enum ReleaseVersion implements Template {
+        FIVE("1.5"),
+        SIX("1.6"),
+        SEVEN("1.7");
+        
+        final String versionStr;
+        
+        ReleaseVersion(String vstr) {
+            versionStr = vstr;
+        }
+        
+        public String expand(String selector) {
+            return toString();        
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/combo-tests/tests/tools/javac/lambda/StaticMethodTest.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tools.javac.lambda;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.testng.annotations.Factory;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import tools.javac.combo.*;
+
+/**
+ * StaticMethodTest: Test static methods in interfaces by running bytecode 
+ *                   compiled at different times; where a static method is added/declared
+ *                   in one interface and only that interface is recompiled.
+ *
+ *                   Static methods in interface are not inherited and 
+ *                   are not visible to any implementing (extending) classes (interfaces).
+ * @bug    8005968
+ * @author sogoel
+ * 
+ */
+public class StaticMethodTest extends ComboTestBase<StaticMethodTest> {
+    @Factory
+    public static Object[] testStaticMethod() throws Exception {
+        return factory(StaticMethodTest.class);
+    }
+    
+    @DimensionVar("SHAPE") CShapes shapeType;
+    
+    @DimensionVar("ADD") AddType addType;
+        
+    @SourceFile(value="B.java", group="A")
+    String interfaceBModified = "interface B #{SHAPE.B_DECL} { #{ADD} }";
+    
+    @SourceFile(value="B.java", group="B")
+    String interfaceB =         "interface B #{SHAPE.B_DECL} {}";
+    
+    @SourceFile(value="A.java", group="B")
+    String interfaceA =         "interface A { static String m() { return \"A\"; } }";
+    
+    @SourceFile(value="C.java", group="B")
+    String classC = "#{SHAPE.C}";
+    
+    @SourceFile(value="Main.java", group="B")
+    String classMain = "public class Main {\n" +
+                       "    public String main() {\n" +
+                       "        return new C().m();\n" +
+                       "    }\n" +
+                       "}";
+
+    @Override
+    protected boolean shouldRun() { return true; }
+
+    @Override
+    protected void run(Class<?> clazz) throws ReflectiveOperationException {
+        Method m = clazz.getMethod("main");
+        Object obj = clazz.newInstance();
+        String result = null, output = null;
+        try {
+            result = (String) m.invoke(obj);
+        } catch (InvocationTargetException ex) {
+            output = ex.getCause().toString();
+        }
+        assertEquals(output, null);
+        assertEquals(result, "C");
+    }
+
+    /*
+     * In order for class Main to compile in group B, object of class C should have
+     * access to a method m(). Therefore, a method m() is needed in class C.
+     * static m() in interfaces A, B is not visible to C.
+     */
+    static String methodSig = "public String m () { return \"C\"; }"; 
+    enum CShapes implements Template { //shapes of class hierarchy
+        //class C implements interface A, B
+        C_AB("",
+           "class C implements A, B { " + methodSig + " }"), 
+        //class C implements interface B, B extends interface A
+        C_B_A("extends A",
+           "class C implements B { " + methodSig + " }"),
+        //class C implements interface AB, AB extends interface A, B
+        C_I_AB("",
+           "interface AB extends A, B {  }\n" +
+           "class C implements AB { " + methodSig + " }"),
+        //class C implements interface AB, AB extends interface A, B and defines its own static method 
+        C_I_AB2("",
+        "interface AB extends A, B { static String m() { return \"AB\"; } }\n" +
+        "class C implements AB { " + methodSig + " }"),
+        //class C extends Class D implements Interface B
+        C_CI("",
+            "class D { public String m() { return \"D\"; } }\n" +
+            "class C extends D implements B { " + methodSig + " }");
+
+        private final String sB_DECL;
+        private final String sC;
+
+        CShapes(String sB_DECL, String sC) {
+            this.sB_DECL = sB_DECL;
+            this.sC = sC;
+        }
+
+        public String expand(String selector) {
+            switch(selector) {
+                case "B_DECL": return sB_DECL;
+                case "C": return sC;
+                default: return toString();
+            }
+        }
+    }
+
+    enum AddType implements Template { // add by adding static method or abstract interface method
+        ADD("static String m() { return \"B\"; }"),
+        REDECLARE("String m();");
+
+        final String newCode;
+
+        AddType(String str) {
+            newCode = str;
+        }
+
+        public String expand(String selector) {
+            return newCode;
+        }
+    }
+}
+
--- a/make/common/internal/Defs-langtools.gmk	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/common/internal/Defs-langtools.gmk	Wed Aug 14 15:53:13 2013 -0700
@@ -28,7 +28,8 @@
 IMPORT_RT_PACKAGES +=               \
       javax/annotation/processing   \
       javax/lang/model              \
-      javax/tools
+      javax/tools                   \
+      com/sun/runtime
 
 IMPORT_TOOLS_PACKAGES +=            \
       com/sun/javadoc               \
--- a/make/docs/NON_CORE_PKGS.gmk	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/docs/NON_CORE_PKGS.gmk	Wed Aug 14 15:53:13 2013 -0700
@@ -84,6 +84,8 @@
 
 SCTPAPI_PKGS     = com.sun.nio.sctp
 
+LAMBDA_RTAPI     = com.sun.runtime
+
 ifeq ($(PLATFORM), macosx)
 APPLE_EXT_PKGS   = com.apple.concurrent   \
                    com.apple.eawt         \
@@ -101,5 +103,6 @@
                    $(HTTPSERVER_PKGS) \
                    $(SMARTCARDIO_PKGS) \
                    $(SCTPAPI_PKGS) \
+                   $(LAMBDA_RTAPI) \
                    $(APPLE_EXT_PKGS)
 
--- a/make/java/java/FILES_java.gmk	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/java/java/FILES_java.gmk	Wed Aug 14 15:53:13 2013 -0700
@@ -300,12 +300,20 @@
 	java/util/EnumMap.java \
     java/util/Arrays.java \
     java/util/ArraysParallelSortHelpers.java \
+    java/util/ArrayPrefixHelpers.java \
+    java/util/ArraySortHelpers.java \
     java/util/DualPivotQuicksort.java \
     java/util/TimSort.java \
     java/util/ComparableTimSort.java \
+    java/util/Comparators.java \
     java/util/ConcurrentModificationException.java \
+    java/util/OptionalDouble.java \
+    java/util/OptionalInt.java \
+    java/util/Optional.java \
+    java/util/OptionalLong.java \
     java/util/ServiceLoader.java \
     java/util/ServiceConfigurationError.java \
+    java/util/StringJoiner.java \
     java/util/Timer.java \
     java/util/TimerTask.java \
     java/util/Objects.java \
@@ -334,6 +342,8 @@
     java/util/concurrent/CyclicBarrier.java \
     java/util/concurrent/DelayQueue.java \
     java/util/concurrent/Delayed.java \
+    java/util/concurrent/DoubleAdder.java \
+    java/util/concurrent/DoubleMaxUpdater.java \
     java/util/concurrent/Exchanger.java \
     java/util/concurrent/ExecutionException.java \
     java/util/concurrent/Executor.java \
@@ -348,6 +358,10 @@
     java/util/concurrent/LinkedBlockingDeque.java \
     java/util/concurrent/LinkedBlockingQueue.java \
     java/util/concurrent/LinkedTransferQueue.java \
+    java/util/concurrent/LongAdder.java \
+    java/util/concurrent/LongAdderTable.java \
+    java/util/concurrent/LongMaxUpdater.java \
+    java/util/concurrent/package-info.java \
     java/util/concurrent/Phaser.java \
     java/util/concurrent/PriorityBlockingQueue.java \
     java/util/concurrent/RecursiveAction.java \
@@ -360,6 +374,8 @@
     java/util/concurrent/ScheduledFuture.java \
     java/util/concurrent/ScheduledThreadPoolExecutor.java \
     java/util/concurrent/Semaphore.java \
+    java/util/concurrent/SequenceLock.java \
+    java/util/concurrent/Striped64.java \
     java/util/concurrent/SynchronousQueue.java \
     java/util/concurrent/ThreadFactory.java \
     java/util/concurrent/ThreadLocalRandom.java \
@@ -379,18 +395,17 @@
     java/util/concurrent/atomic/AtomicReferenceArray.java \
     java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java \
     java/util/concurrent/atomic/AtomicStampedReference.java \
-    java/util/concurrent/atomic/DoubleAccumulator.java \
-    java/util/concurrent/atomic/DoubleAdder.java \
-    java/util/concurrent/atomic/LongAccumulator.java \
-    java/util/concurrent/atomic/LongAdder.java \
-    java/util/concurrent/atomic/Striped64.java \
+    java/util/concurrent/atomic/package-info.java \
+    java/util/concurrent/extra/AtomicDoubleArray.java \
+    java/util/concurrent/extra/AtomicDouble.java \
+    java/util/concurrent/extra/ReadMostlyVector.java \
     java/util/concurrent/locks/AbstractOwnableSynchronizer.java \
     java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java \
     java/util/concurrent/locks/AbstractQueuedSynchronizer.java \
-    java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java \
     java/util/concurrent/locks/Condition.java \
     java/util/concurrent/locks/Lock.java \
     java/util/concurrent/locks/LockSupport.java \
+    java/util/concurrent/locks/package-info.java \
     java/util/concurrent/locks/ReadWriteLock.java \
     java/util/concurrent/locks/ReentrantLock.java \
     java/util/concurrent/locks/ReentrantReadWriteLock.java \
--- a/make/java/java/Makefile	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/java/java/Makefile	Wed Aug 14 15:53:13 2013 -0700
@@ -37,7 +37,7 @@
 JAVAC_MAX_WARNINGS=true
 include $(BUILDDIR)/common/Defs.gmk
 
-AUTO_FILES_JAVA_DIRS = java/util/function
+AUTO_FILES_JAVA_DIRS = java/util/concurrent java/util/function java/util/stream
 
 # windows compiler flags
 ifeq ($(PLATFORM),windows)
@@ -51,7 +51,7 @@
 OTHER_CFLAGS += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \
                 -DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"' \
                 -DJDK_MICRO_VERSION='"$(JDK_MICRO_VERSION)"' \
-                -DJDK_BUILD_NUMBER='"$(JDK_BUILD_NUMBER)"' 
+                -DJDK_BUILD_NUMBER='"$(JDK_BUILD_NUMBER)"'
 
 ifdef JDK_UPDATE_VERSION
 OTHER_CFLAGS += -DJDK_UPDATE_VERSION='"$(JDK_UPDATE_VERSION)"'
@@ -279,7 +279,7 @@
 $(GENSRCDIR)/java/lang/UNIXProcess.java: $(PLATFORM_UNIX_PROCESS)
 	$(install-file)
 
-clean:: 
+clean::
 	$(RM) $(GENSRCDIR)/java/lang/UNIXProcess.java
 
 endif
@@ -293,10 +293,10 @@
 #
 # Special rules.
 #
-clean:: 
+clean::
 	$(RM) -r $(CLASSHDRDIR)
 
-clobber:: 
+clobber::
 	$(RM) -r $(CLASSBINDIR)/java/io $(CLASSBINDIR)/java/lang \
 		$(CLASSBINDIR)/java/security $(CLASSBINDIR)/java/util \
 		$(CLASSBINDIR)/sun/misc
@@ -313,12 +313,6 @@
 CAL_PROPS = calendars.properties
 
 #
-# Rule to copy Hijrah-umalqura calendar properties file.
-#
-HIJRAH_UMALQURA_PROPS = hijrah-config-umalqura.properties
-
-
-#
 # Rule to copy tzmappings file on Windows
 #
 ifeq ($(PLATFORM), windows)
@@ -330,7 +324,7 @@
 	$(call chmod-file, 444)
 endif
 
-build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(LIBDIR)/$(HIJRAH_UMALQURA_PROPS) $(TZMAP)
+build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(TZMAP)
 
 $(LIBDIR)/$(PROPS): $(PLATFORM_SRC)/lib/$(PROPS)
 	$(install-file)
@@ -338,10 +332,7 @@
 $(LIBDIR)/$(CAL_PROPS): $(SHARE_SRC)/lib/$(CAL_PROPS)
 	$(install-file)
 
-$(LIBDIR)/$(HIJRAH_UMALQURA_PROPS): $(SHARE_SRC)/lib/$(HIJRAH_UMALQURA_PROPS)
-	$(install-file)
-
-clean:: 
+clean::
 	$(RM) -r $(LIBDIR)/$(PROPS) $(TZMAP)
 
 #
@@ -362,12 +353,12 @@
 	$(MV) $@.temp $@
 	$(call chmod-file, 444)
 
-clean:: 
+clean::
 	$(RM) $(CURDATA)
 
 
 #
-# Rules to create $(GENSRCDIR)/sun/lang/CharacterData*.java 
+# Rules to create $(GENSRCDIR)/sun/lang/CharacterData*.java
 #
 CHARACTERDATA = $(BUILDDIR)/tools/GenerateCharacter
 UNICODEDATA   = $(BUILDDIR)/tools/UnicodeData
@@ -422,12 +413,12 @@
 	$(install-file)
 
 clean::
-	$(RM) $(GENSRCDIR)/java/lang/CharacterDataLatin1.java 
+	$(RM) $(GENSRCDIR)/java/lang/CharacterDataLatin1.java
 	$(RM) $(GENSRCDIR)/java/lang/CharacterData00.java
-	$(RM) $(GENSRCDIR)/java/lang/CharacterData01.java 
+	$(RM) $(GENSRCDIR)/java/lang/CharacterData01.java
 	$(RM) $(GENSRCDIR)/java/lang/CharacterData02.java
 	$(RM) $(GENSRCDIR)/java/lang/CharacterData0E.java
-	$(RM) $(GENSRCDIR)/java/lang/CharacterDataUndefined.java 
+	$(RM) $(GENSRCDIR)/java/lang/CharacterDataUndefined.java
 	$(RM) $(GENSRCDIR)/java/lang/CharacterDataPrivateUse.java
 
 #
@@ -448,7 +439,7 @@
 	build.tools.generatecharacter.CharacterName \
 		$(UNICODEDATA)/UnicodeData.txt $(UNINAME)
 
-clean:: 
+clean::
 	$(RM) $(UNINAME)
 
 #
@@ -456,15 +447,15 @@
 #
 
 #
-# Rule to precompile CoreResourceBundleControl.java 
+# Rule to precompile CoreResourceBundleControl.java
 #
 LOCALES_GEN_SH = localelist.sh
 
 $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java: \
 	$(SHARE_SRC)/classes/sun/util/CoreResourceBundleControl-XLocales.java.template $(LOCALES_GEN_SH)
-	@$(prep-target) 
+	@$(prep-target)
 	NAWK="$(NAWK)" SED="$(SED)" $(SH) $(LOCALES_GEN_SH) "$(JRE_NONEXIST_LOCALES)" \
-		$< $@ 
+		$< $@
 clean::
 	$(RM) $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java
 
--- a/make/netbeans/common/java-data-native.ent	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/netbeans/common/java-data-native.ent	Wed Aug 14 15:53:13 2013 -0700
@@ -31,13 +31,13 @@
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -->
 
-<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3">
+<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
     <compilation-unit>
         <package-root>${root}/src/share/classes</package-root>
         <package-root>${root}/src/macosx/classes</package-root>
         <package-root>${root}/src/solaris/classes</package-root>
         <package-root>${root}/src/windows/classes</package-root>
-        <classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
+<!--        <classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath> -->
         <built-to>${root}/build/${platform}-${arch}/classes</built-to>
         <javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
         <source-level>1.8</source-level>
--- a/make/netbeans/common/java-data-no-native.ent	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/netbeans/common/java-data-no-native.ent	Wed Aug 14 15:53:13 2013 -0700
@@ -31,10 +31,10 @@
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -->
 
-<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3">
+<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
     <compilation-unit>
         <package-root>${root}/src/share/classes</package-root>
-        <classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath>
+<!--        <classpath mode="boot">${bootstrap.jdk}/jre/lib/rt.jar</classpath> -->
         <built-to>${root}/build/${platform}-${arch}/classes</built-to>
         <javadoc-built-to>${root}/build/${platform}-${arch}/docs/api</javadoc-built-to>
         <source-level>1.8</source-level>
--- a/make/netbeans/common/shared.xml	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/netbeans/common/shared.xml	Wed Aug 14 15:53:13 2013 -0700
@@ -77,10 +77,10 @@
         <echo level="verbose">System configuration claims architecture is ${platform}-${arch}</echo>
         <property name="build.dir" location="${root}/build/${platform}-${arch}"/>
         <property name="bin.dir" location="${build.dir}/bin"/>
-        <property name="make.dir" location="${root}/make"/> <!-- this is old build make files! -->
+        <property name="make.dir" location="${root}/makefiles"/>
         <property name="gensrc.dir" location="${build.dir}/gensrc"/>
         <property name="classes.dir" location="${build.dir}/classes"/>
-        <property name="jtreg.dir" location="${build.dir}/jtreg/${ant.project.name}"/>
+        <property name="jtreg.dir" location="${build.dir}/testoutput"/>
         <property name="dist.dir" value="${root}/dist"/>
         <property name="includes" value="(nothing)"/>
         <property name="excludes" value=""/>
--- a/make/org/Makefile	Tue Aug 13 10:42:37 2013 -0700
+++ b/make/org/Makefile	Wed Aug 14 15:53:13 2013 -0700
@@ -31,7 +31,7 @@
 PRODUCT = org
 include $(BUILDDIR)/common/Defs.gmk
 
-SUBDIRS = ietf jcp
+SUBDIRS = asm ietf jcp
 include $(BUILDDIR)/common/Subdirs.gmk
 
 all build clean clobber::
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Wed Aug 14 15:53:13 2013 -0700
@@ -193,8 +193,8 @@
         } else {
             return new ConstantCallSite(
                     MethodHandles.Lookup.IMPL_LOOKUP
-                         .findConstructor(innerClass, constructorType)
-                         .asType(constructorType.changeReturnType(samBase)));
+                                        .findConstructor(innerClass, constructorType)
+                                        .asType(constructorType.changeReturnType(samBase)));
         }
     }
 
@@ -320,8 +320,8 @@
         TypeConvertingMethodAdapter mv
                 = new TypeConvertingMethodAdapter(
                     cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
-                    NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
-                    null, null));
+                                                                 NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
+                                                                 null, null));
 
         mv.visitCode();
         mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
--- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed Aug 14 15:53:13 2013 -0700
@@ -295,6 +295,9 @@
 
         String invokerDesc = invokerType.toMethodDescriptorString();
         mv = cw.visitMethod(Opcodes.ACC_STATIC, invokerName, invokerDesc, null, null);
+
+        // Force inlining of this invoker method.
+        mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
     }
 
     /**
@@ -521,9 +524,6 @@
         // Mark this method as a compiled LambdaForm
         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true);
 
-        // Force inlining of this invoker method.
-        mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
-
         // iterate over the form's names, generating bytecode instructions for each
         // start iterating at the first name following the arguments
         for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
@@ -943,9 +943,6 @@
         // Suppress this method in backtraces displayed to the user.
         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 
-        // Don't inline the interpreter entry.
-        mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
-
         // create parameter array
         emitIconstInsn(invokerType.parameterCount());
         mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
@@ -1008,9 +1005,6 @@
         // Suppress this method in backtraces displayed to the user.
         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 
-        // Force inlining of this invoker method.
-        mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
-
         // Load receiver
         emitAloadInsn(0);
 
--- a/src/share/classes/java/lang/invoke/LambdaForm.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/LambdaForm.java	Wed Aug 14 15:53:13 2013 -0700
@@ -69,7 +69,7 @@
  * A lambda has a void result if and only if its result index is -1.
  * If a temporary has the type "V", it cannot be the subject of a NameRef,
  * even though possesses a number.
- * Note that all reference types are erased to "L", which stands for {@code Object).
+ * Note that all reference types are erased to "L", which stands for {@code Object}.
  * All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}.
  * The other types stand for the usual primitive types.
  * <p>
@@ -592,7 +592,6 @@
     private int invocationCounter = 0;
 
     @Hidden
-    @DontInline
     /** Interpretively invoke this form on the given arguments. */
     Object interpretWithArguments(Object... argumentValues) throws Throwable {
         if (TRACE_INTERPRETER)
@@ -607,7 +606,6 @@
     }
 
     @Hidden
-    @DontInline
     /** Evaluate a single Name within this form, applying its function to its arguments. */
     Object interpretName(Name name, Object[] values) throws Throwable {
         if (TRACE_INTERPRETER)
--- a/src/share/classes/java/lang/invoke/MemberName.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MemberName.java	Wed Aug 14 15:53:13 2013 -0700
@@ -236,8 +236,7 @@
             assert(MethodHandleNatives.refKindIsMethod(refKind));
             if (clazz.isInterface())
                 assert(refKind == REF_invokeInterface ||
-                       refKind == REF_invokeStatic    ||
-                       refKind == REF_invokeSpecial   ||
+                       refKind == REF_invokeStatic ||
                        refKind == REF_invokeVirtual && isObjectPublicMethod());
         } else {
             assert(false);
@@ -270,7 +269,7 @@
             assert(refKind == REF_invokeSpecial) : this;
             return true;
         }
-        assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
+        assert(false) : this;
         return true;
     }
     private boolean staticIsConsistent() {
@@ -288,8 +287,12 @@
             assert(vmindex >= 0) : vmindex + ":" + this;
             assert(vmtarget instanceof Class);
         } else {
-            if (MethodHandleNatives.refKindDoesDispatch(refKind))
-                assert(vmindex >= 0) : vmindex + ":" + this;
+            if (MethodHandleNatives.refKindDoesDispatch(refKind)) {
+                // invokeStatic can reference either method table or interface table
+                if (refKind != REF_invokeStatic) {
+                    assert(vmindex >= 0) : vmindex + ":" + this;
+                }
+            }
             else
                 assert(vmindex < 0) : vmindex;
             assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
@@ -487,19 +490,14 @@
         if (this.type == null)
             this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
         if (wantSpecial) {
-            assert(!isAbstract()) : this;
             if (getReferenceKind() == REF_invokeVirtual)
                 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
-            else if (getReferenceKind() == REF_invokeInterface)
-                // invokeSpecial on a default method
-                changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
         }
     }
     public MemberName asSpecial() {
         switch (getReferenceKind()) {
         case REF_invokeSpecial:     return this;
         case REF_invokeVirtual:     return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
-        case REF_invokeInterface:   return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
         case REF_newInvokeSpecial:  return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
         }
         throw new IllegalArgumentException(this.toString());
--- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Aug 14 15:53:13 2013 -0700
@@ -312,9 +312,9 @@
     }
 
     static class AsVarargsCollector extends MethodHandle {
-        private final MethodHandle target;
-        private final Class<?> arrayType;
-        private MethodHandle cache;
+        MethodHandle target;
+        final Class<?> arrayType;
+        MethodHandle cache;
 
         AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
             super(type, reinvokerForm(type));
--- a/src/share/classes/java/lang/invoke/MethodHandleInfo.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MethodHandleInfo.java	Wed Aug 14 15:53:13 2013 -0700
@@ -27,10 +27,10 @@
 import java.lang.invoke.MethodHandleNatives.Constants;
 
 /**
- * Cracking (reflecting) method handles back into their constituent symbolic parts.
- *
+ * Cracking (reflecting) method handles back into their constituent symbolic parts. 
+ * 
  */
-final class MethodHandleInfo {
+public final class MethodHandleInfo {
    public static final int
        REF_getField                = Constants.REF_getField,
        REF_getStatic               = Constants.REF_getStatic,
@@ -72,15 +72,15 @@
        return methodType;
    }
 
-   public int getModifiers() {
-       return -1; //TODO
-   }
+    public int getModifiers() {
+        return -1; //TODO
+    }
 
    public int getReferenceKind() {
        return referenceKind;
    }
-
-   static String getReferenceKindString(int referenceKind) {
+    
+   public static String getReferenceKindString(int referenceKind) {
         switch (referenceKind) {
             case REF_getField: return "getfield";
             case REF_getStatic: return "getstatic";
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Wed Aug 14 15:53:13 2013 -0700
@@ -215,6 +215,7 @@
     static boolean refKindDoesDispatch(byte refKind) {
         assert(refKindIsValid(refKind));
         return (refKind == REF_invokeVirtual ||
+                refKind == REF_invokeStatic ||
                 refKind == REF_invokeInterface);
     }
     static {
--- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java	Wed Aug 14 15:53:13 2013 -0700
@@ -142,7 +142,7 @@
     @CallerSensitive
     public static
     <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
-        if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
+        if (!intfc.isInterface()/* || !Modifier.isPublic(intfc.getModifiers())*/)
             throw new IllegalArgumentException("not a public interface: "+intfc.getName());
         final MethodHandle mh;
         if (System.getSecurityManager() != null) {
--- a/src/share/classes/java/nio/file/DirectoryStream.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/nio/file/DirectoryStream.java	Wed Aug 14 15:53:13 2013 -0700
@@ -28,16 +28,21 @@
 import java.util.Iterator;
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 /**
  * An object to iterate over the entries in a directory. A directory stream
- * allows for the convenient use of the for-each construct to iterate over a
- * directory.
+ * allows for the convenient use of the for-each construct or the {@link
+ * Stream} API to iterate over a directory.
  *
  * <p> <b> While {@code DirectoryStream} extends {@code Iterable}, it is not a
- * general-purpose {@code Iterable} as it supports only a single {@code
- * Iterator}; invoking the {@link #iterator iterator} method to obtain a second
- * or subsequent iterator throws {@code IllegalStateException}. </b>
+ * general-purpose {@code Iterable}. A {@code DirectoryStream} supports only a
+ * single iteration via either the {@link #iterator iterator} or the {@link
+ * #stream stream} method. Invoking either method to do a second or
+ * subsequent iteration throws {@code IllegalStateException}. </b>
  *
  * <p> An important property of the directory stream's {@code Iterator} is that
  * its {@link Iterator#hasNext() hasNext} method is guaranteed to read-ahead by
@@ -61,13 +66,13 @@
  *   }
  * </pre>
  *
- * <p> Once a directory stream is closed, then further access to the directory,
- * using the {@code Iterator}, behaves as if the end of stream has been reached.
- * Due to read-ahead, the {@code Iterator} may return one or more elements
- * after the directory stream has been closed. Once these buffered elements
- * have been read, then subsequent calls to the {@code hasNext} method returns
- * {@code false}, and subsequent calls to the {@code next} method will throw
- * {@code NoSuchElementException}.
+ * <p> Once a directory stream is closed, then further access to the
+ * directory, using the {@code Iterator} or {@code Stream}, behaves as if the
+ * end of stream has been reached. Due to read-ahead, one or more elements may
+ * be returned after the directory stream has been closed. Once these buffered
+ * elements have been read, then subsequent calls to the {@code hasNext}
+ * method returns {@code false}, and subsequent calls to the {@code next}
+ * method will throw {@code NoSuchElementException}.
  *
  * <p> A directory stream is not required to be <i>asynchronously closeable</i>.
  * If a thread is blocked on the directory stream's iterator reading from the
@@ -75,13 +80,14 @@
  * second thread may block until the read operation is complete.
  *
  * <p> If an I/O error is encountered when accessing the directory then it
- * causes the {@code Iterator}'s {@code hasNext} or {@code next} methods to
- * throw {@link DirectoryIteratorException} with the {@link IOException} as the
- * cause. As stated above, the {@code hasNext} method is guaranteed to
- * read-ahead by at least one element. This means that if {@code hasNext} method
- * returns {@code true}, and is followed by a call to the {@code next} method,
- * then it is guaranteed that the {@code next} method will not fail with a
- * {@code DirectoryIteratorException}.
+ * causes the methods to throw {@link DirectoryIteratorException} with the
+ * {@link IOException} as the cause. This could be the {@code Iterator}'s
+ * {@code hasNext} or {@code next} method or one of the {@code Stream} methods.
+ * As stated above, the {@code hasNext} method is guaranteed to read-ahead by
+ * at least one element. This means that if {@code hasNext} method returns
+ * {@code true}, and is followed by a call to the {@code next} method, then it
+ * is guaranteed that the {@code next} method will not fail with a {@code
+ * DirectoryIteratorException}.
  *
  * <p> The elements returned by the iterator are in no specific order. Some file
  * systems maintain special links to the directory itself and the directory's
@@ -151,9 +157,23 @@
      * @return  the iterator associated with this {@code DirectoryStream}
      *
      * @throws  IllegalStateException
-     *          if this directory stream is closed or the iterator has already
-     *          been returned
+     *          if this directory stream is closed or the iterator or stream
+     *          has already been returned
      */
     @Override
     Iterator<T> iterator();
+
+    /**
+     * Returns the stream associated with this {@code DirectoryStream}.
+     *
+     * @return the stream associated with this {@code DirectoryStream}
+     *
+     * @throws IllegalStateException
+     *         if this directory stream is closed or the iterator or stream
+     *         has already been returned
+     * @since 1.8
+     */
+    default Stream<T> stream() {
+        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator(), Spliterator.DISTINCT), false);
+    }
 }
--- a/src/share/classes/java/nio/file/Files.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/nio/file/Files.java	Wed Aug 14 15:53:13 2013 -0700
@@ -25,24 +25,54 @@
 
 package java.nio.file;
 
-import java.nio.file.attribute.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.DosFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileOwnerAttributeView;
+import java.nio.file.attribute.FileStoreAttributeView;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
 import java.nio.file.spi.FileSystemProvider;
 import java.nio.file.spi.FileTypeDetector;
-import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
-import java.nio.channels.SeekableByteChannel;
-import java.io.Closeable;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.MayHoldCloseableResource;
+import java.util.Objects;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.function.BiPredicate;
 import java.util.stream.CloseableStream;
 import java.util.stream.DelegatingStream;
@@ -74,6 +104,21 @@
         return path.getFileSystem().provider();
     }
 
+    /**
+     * Convert a Closeable to a Runnable by converting checked IOException
+     * to UncheckedIOException
+     */
+    private static Runnable asUncheckedRunnable(Closeable c) {
+        return () -> {
+            try {
+                c.close();
+            }
+            catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        };
+    }
+
     // -- File contents --
 
     /**
@@ -3228,29 +3273,7 @@
     // -- Stream APIs --
 
     /**
-     * Implementation of CloseableStream
-     */
-    private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
-        implements CloseableStream<T>
-    {
-        private final Closeable closeable;
-
-        DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
-            super(delegate);
-            this.closeable = c;
-        }
-
-        public void close() {
-            try {
-                closeable.close();
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-    }
-
-    /**
-     * Return a lazily populated {@code CloseableStream}, the elements of
+     * Return a lazily populated {@code Stream}, the elements of
      * which are the entries in the directory.  The listing is not recursive.
      *
      * <p> The elements of the stream are {@link Path} objects that are
@@ -3265,7 +3288,7 @@
      * method.
      *
      * <p> When not using the try-with-resources construct, then the stream's
-     * {@link CloseableStream#close close} method should be invoked after the
+     * {@link Stream#close close} method should be invoked after the
      * operation is completed so as to free any resources held for the open
      * directory. Operating on a closed stream behaves as if the end of stream
      * has been reached. Due to read-ahead, one or more elements may be
@@ -3278,7 +3301,7 @@
      *
      * @param   dir  The path to the directory
      *
-     * @return  The {@code CloseableStream} describing the content of the
+     * @return  The {@code Stream} describing the content of the
      *          directory
      *
      * @throws  NotDirectoryException
@@ -3294,43 +3317,47 @@
      * @see     #newDirectoryStream(Path)
      * @since   1.8
      */
-    public static CloseableStream<Path> list(Path dir) throws IOException {
+    @MayHoldCloseableResource.HoldsResource
+    public static Stream<Path> list(Path dir) throws IOException {
         DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
-        final Iterator<Path> delegate = ds.iterator();
+        try {
+            final Iterator<Path> delegate = ds.iterator();
 
-        // Re-wrap DirectoryIteratorException to UncheckedIOException
-        Iterator<Path> it = new Iterator<Path>() {
-            public boolean hasNext() {
-                try {
-                    return delegate.hasNext();
-                } catch (DirectoryIteratorException e) {
-                    throw new UncheckedIOException(e.getCause());
+            // Re-wrap DirectoryIteratorException to UncheckedIOException
+            Iterator<Path> it = new Iterator<Path>() {
+                public boolean hasNext() {
+                    try {
+                        return delegate.hasNext();
+                    } catch (DirectoryIteratorException e) {
+                        throw new UncheckedIOException(e.getCause());
+                    }
                 }
-            }
-            public Path next() {
-                try {
-                    return delegate.next();
-                } catch (DirectoryIteratorException e) {
-                    throw new UncheckedIOException(e.getCause());
+                public Path next() {
+                    try {
+                        return delegate.next();
+                    } catch (DirectoryIteratorException e) {
+                        throw new UncheckedIOException(e.getCause());
+                    }
                 }
-            }
-        };
+            };
 
-        Stream<Path> s = StreamSupport.stream(
-                Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT),
-                false);
-        return new DelegatingCloseableStream<>(ds, s);
+            return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false)
+                                .onClose(asUncheckedRunnable(ds));
+        } catch (Error|RuntimeException e) {
+            ds.close();
+            throw e;
+        }
     }
 
     /**
-     * Return a {@code CloseableStream} that is lazily populated with {@code
+     * Return a {@code Stream} that is lazily populated with {@code
      * Path} by walking the file tree rooted at a given starting file.  The
      * file tree is traversed <em>depth-first</em>, the elements in the stream
      * are {@link Path} objects that are obtained as if by {@link
      * Path#resolve(Path) resolving} the relative path against {@code start}.
      *
      * <p> The {@code stream} walks the file tree as elements are consumed.
-     * The {@code CloseableStream} returned is guaranteed to have at least one
+     * The {@code Stream} returned is guaranteed to have at least one
      * element, the starting file itself. For each file visited, the stream
      * attempts to read its {@link BasicFileAttributes}. If the file is a
      * directory and can be opened successfully, entries in the directory, and
@@ -3371,7 +3398,7 @@
      * (or directory), then it is ignored and not included in the stream.
      *
      * <p> When not using the try-with-resources construct, then the stream's
-     * {@link CloseableStream#close close} method should be invoked after the
+     * {@link Stream#close close} method should be invoked after the
      * operation is completed so as to free any resources held for the open
      * directory. Operate the stream after it is closed will throw an
      * {@link java.lang.IllegalStateException}.
@@ -3388,7 +3415,7 @@
      * @param   options
      *          options to configure the traversal
      *
-     * @return  the {@link CloseableStream} of {@link Path}
+     * @return  the {@link Stream} of {@link Path}
      *
      * @throws  IllegalArgumentException
      *          if the {@code maxDepth} parameter is negative
@@ -3401,21 +3428,23 @@
      *          if an I/O error is thrown when accessing the starting file.
      * @since   1.8
      */
-    public static CloseableStream<Path> walk(Path start, int maxDepth,
-                                             FileVisitOption... options)
-        throws IOException
-    {
+    @MayHoldCloseableResource.HoldsResource
+    public static Stream<Path> walk(Path start, int maxDepth,
+                                    FileVisitOption... options)
+            throws IOException {
         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
-
-        Stream<Path> s = StreamSupport.stream(
-                Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT),
-                false).
-                map(entry -> entry.file());
-        return new DelegatingCloseableStream<>(iterator, s);
+        try {
+            return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
+                                .onClose(iterator::close)
+                                .map(entry -> entry.file());
+        } catch (Error|RuntimeException e) {
+            iterator.close();
+            throw e;
+        }
     }
 
     /**
-     * Return a {@code CloseableStream} that is lazily populated with {@code
+     * Return a {@code Stream} that is lazily populated with {@code
      * Path} by walking the file tree rooted at a given starting file.  The
      * file tree is traversed <em>depth-first</em>, the elements in the stream
      * are {@link Path} objects that are obtained as if by {@link
@@ -3433,7 +3462,7 @@
      * @param   options
      *          options to configure the traversal
      *
-     * @return  the {@link CloseableStream} of {@link Path}
+     * @return  the {@link Stream} of {@link Path}
      *
      * @throws  SecurityException
      *          If the security manager denies access to the starting file.
@@ -3446,15 +3475,15 @@
      * @see     #walk(Path, int, FileVisitOption...)
      * @since   1.8
      */
-    public static CloseableStream<Path> walk(Path start,
-                                             FileVisitOption... options)
-        throws IOException
-    {
+    @MayHoldCloseableResource.HoldsResource
+    public static Stream<Path> walk(Path start,
+                                    FileVisitOption... options)
+            throws IOException {
         return walk(start, Integer.MAX_VALUE, options);
     }
 
     /**
-     * Return a {@code CloseableStream} that is lazily populated with {@code
+     * Return a {@code Stream} that is lazily populated with {@code
      * Path} by searching for files in a file tree rooted at a given starting
      * file.
      *
@@ -3463,7 +3492,7 @@
      * {@link BiPredicate} is invoked with its {@link Path} and {@link
      * BasicFileAttributes}. The {@code Path} object is obtained as if by
      * {@link Path#resolve(Path) resolving} the relative path against {@code
-     * start} and is only included in the returned {@link CloseableStream} if
+     * start} and is only included in the returned {@link Stream} if
      * the {@code BiPredicate} returns true. Compare to calling {@link
      * java.util.stream.Stream#filter filter} on the {@code Stream}
      * returned by {@code walk} method, this method may be more efficient by
@@ -3484,7 +3513,7 @@
      * @param   options
      *          options to configure the traversal
      *
-     * @return  the {@link CloseableStream} of {@link Path}
+     * @return  the {@link Stream} of {@link Path}
      *
      * @throws  IllegalArgumentException
      *          if the {@code maxDepth} parameter is negative
@@ -3499,24 +3528,26 @@
      * @see     #walk(Path, int, FileVisitOption...)
      * @since   1.8
      */
-    public static CloseableStream<Path> find(Path start,
-                                             int maxDepth,
-                                             BiPredicate<Path, BasicFileAttributes> matcher,
-                                             FileVisitOption... options)
-        throws IOException
-    {
+    @MayHoldCloseableResource.HoldsResource
+    public static Stream<Path> find(Path start,
+                                    int maxDepth,
+                                    BiPredicate<Path, BasicFileAttributes> matcher,
+                                    FileVisitOption... options)
+            throws IOException {
         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
-
-        Stream<Path> s = StreamSupport.stream(
-                Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT),
-                false).
-                filter(entry -> matcher.test(entry.file(), entry.attributes())).
-                map(entry -> entry.file());
-        return new DelegatingCloseableStream<>(iterator, s);
+        try {
+            return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
+                                .onClose(iterator::close)
+                                .filter(entry -> matcher.test(entry.file(), entry.attributes()))
+                                .map(entry -> entry.file());
+        } catch (Error|RuntimeException e) {
+            iterator.close();
+            throw e;
+        }
     }
 
     /**
-     * Read all lines from a file as a {@code CloseableStream}.  Unlike {@link
+     * Read all lines from a file as a {@code Stream}.  Unlike {@link
      * #readAllLines(Path, Charset) readAllLines}, this method does not read
      * all lines into a {@code List}, but instead populates lazily as the stream
      * is consumed.
@@ -3534,7 +3565,7 @@
      * it is also wrapped as an {@code UncheckedIOException}.
      *
      * <p> When not using the try-with-resources construct, then stream's
-     * {@link CloseableStream#close close} method should be invoked after
+     * {@link Stream#close close} method should be invoked after
      * operation is completed so as to free any resources held for the open
      * file.
      *
@@ -3543,7 +3574,7 @@
      * @param   cs
      *          the charset to use for decoding
      *
-     * @return  the lines from the file as a {@code CloseableStream}
+     * @return  the lines from the file as a {@code Stream}
      *
      * @throws  IOException
      *          if an I/O error occurs opening the file
@@ -3557,10 +3588,14 @@
      * @see     java.io.BufferedReader#lines()
      * @since   1.8
      */
-    public static CloseableStream<String> lines(Path path, Charset cs)
-        throws IOException
-    {
+    @MayHoldCloseableResource.HoldsResource
+    public static Stream<String> lines(Path path, Charset cs) throws IOException {
         BufferedReader br = Files.newBufferedReader(path, cs);
-        return new DelegatingCloseableStream<>(br, br.lines());
+        try {
+            return br.lines().onClose(asUncheckedRunnable(br));
+        } catch (Error|RuntimeException e) {
+            br.close();
+            throw e;
+        }
     }
 }
--- a/src/share/classes/java/util/ArrayDeque.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/ArrayDeque.java	Wed Aug 14 15:53:13 2013 -0700
@@ -888,6 +888,19 @@
             elements[i] = s.readObject();
     }
 
+    /**
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
+     * deque.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
+     * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
+     * {@link Spliterator#NONNULL}.  Overriding implementations should document
+     * the reporting of additional characteristic values.
+     *
+     * @return a {@code Spliterator} over the elements in this deque
+     * @since 1.8
+     */
     public Spliterator<E> spliterator() {
         return new DeqSpliterator<E>(this, -1, -1);
     }
--- a/src/share/classes/java/util/ArrayList.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/ArrayList.java	Wed Aug 14 15:53:13 2013 -0700
@@ -1238,6 +1238,20 @@
         }
     }
 
+    /**
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
+     * list.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
+     * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
+     * Overriding implementations should document the reporting of additional
+     * characteristic values.
+     *
+     * @return a {@code Spliterator} over the elements in this list
+     * @since 1.8
+     */
+    @Override
     public Spliterator<E> spliterator() {
         return new ArrayListSpliterator<>(this, 0, -1, 0);
     }
--- a/src/share/classes/java/util/Arrays.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Arrays.java	Wed Aug 14 15:53:13 2013 -0700
@@ -1568,7 +1568,7 @@
     // Parallel prefix
 
     /**
-     * Cumulates, in parallel, each element of the given array in place,
+     * Cumulates in parallel each element of the given array in place,
      * using the supplied function. For example if the array initially
      * holds {@code [2, 1, 0, 3]} and the operation performs addition,
      * then upon return the array holds {@code [2, 3, 3, 6]}.
@@ -1613,7 +1613,7 @@
     }
 
     /**
-     * Cumulates, in parallel, each element of the given array in place,
+     * Cumulates in parallel each element of the given array in place,
      * using the supplied function. For example if the array initially
      * holds {@code [2, 1, 0, 3]} and the operation performs addition,
      * then upon return the array holds {@code [2, 3, 3, 6]}.
@@ -1656,19 +1656,16 @@
     }
 
     /**
-     * Cumulates, in parallel, each element of the given array in place,
+     * Cumulates in parallel each element of the given array in place,
      * using the supplied function. For example if the array initially
-     * holds {@code [2.0, 1.0, 0.0, 3.0]} and the operation performs addition,
-     * then upon return the array holds {@code [2.0, 3.0, 3.0, 6.0]}.
+     * holds {@code [2, 1, 0, 3]} and the operation performs addition,
+     * then upon return the array holds {@code [2, 3, 3, 6]}.
      * Parallel prefix computation is usually more efficient than
      * sequential loops for large arrays.
      *
-     * <p> Because floating-point operations may not be strictly associative,
-     * the returned result may not be identical to the value that would be
-     * obtained if the operation was performed sequentially.
-     *
      * @param array the array, which is modified in-place by this method
-     * @param op a side-effect-free function to perform the cumulation
+     * @param op a side-effect-free, associative function to perform the
+     * cumulation
      * @throws NullPointerException if the specified array or function is null
      * @since 1.8
      */
@@ -1702,7 +1699,7 @@
     }
 
     /**
-     * Cumulates, in parallel, each element of the given array in place,
+     * Cumulates in parallel each element of the given array in place,
      * using the supplied function. For example if the array initially
      * holds {@code [2, 1, 0, 3]} and the operation performs addition,
      * then upon return the array holds {@code [2, 3, 3, 6]}.
--- a/src/share/classes/java/util/Collection.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Collection.java	Wed Aug 14 15:53:13 2013 -0700
@@ -504,7 +504,10 @@
      *
      * <p>The returned {@code Spliterator} must report the characteristic
      * {@link Spliterator#SIZED}; implementations should document any additional
-     * characteristic values reported by the returned Spliterator.
+     * characteristic values reported by the returned spliterator.  If
+     * this collection contains no elements then the returned spliterator is
+     * only required to report {@link Spliterator#SIZED} and is not required to
+     * report additional characteristic values (if any).
      *
      * <p>The default implementation should be overridden by subclasses that
      * can return a more efficient spliterator.  In order to
@@ -535,9 +538,18 @@
      * The returned {@code Spliterator} additionally reports
      * {@link Spliterator#SUBSIZED}.
      *
+     * <p>If a spliterator covers no elements then the reporting of additional
+     * characteristic values, beyond that of {@code SIZED} and {@code SUBSIZED},
+     * does not aid clients to control, specialize or simplify computation.
+     * However, this does enable shared use of an immutable and empty
+     * spliterator instance (see {@link Spliterators#emptySpliterator()} for
+     * empty collections, and enables clients to determine if such a spliterator
+     * covers no elements.
+     *
      * @return a {@code Spliterator} over the elements in this collection
      * @since 1.8
      */
+    @Override
     default Spliterator<E> spliterator() {
         return Spliterators.spliterator(this, 0);
     }
--- a/src/share/classes/java/util/Collections.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Collections.java	Wed Aug 14 15:53:13 2013 -0700
@@ -27,7 +27,6 @@
 import java.io.Serializable;
 import java.io.ObjectOutputStream;
 import java.io.IOException;
-import java.io.InvalidObjectException;
 import java.lang.reflect.Array;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
@@ -35,6 +34,7 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -1148,7 +1148,14 @@
         public Spliterator<E> spliterator() {
             return (Spliterator<E>)c.spliterator();
         }
-
+        @Override
+        public Stream<E> stream() {
+            return (Stream<E>)c.stream();
+        }
+        @Override
+        public Stream<E> parallelStream() {
+            return (Stream<E>)c.parallelStream();
+        }
     }
 
     /**
@@ -2009,8 +2016,8 @@
      * through the returned collection.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * collection when traversing it via {@link Iterator} or
-     * {@link Spliterator}:
+     * collection when traversing it via {@link Iterator}, {@link Spliterator}
+     * or {@link Stream}:
      * <pre>
      *  Collection c = Collections.synchronizedCollection(myCollection);
      *     ...
@@ -2120,6 +2127,14 @@
         public Spliterator<E> spliterator() {
             return c.spliterator(); // Must be manually synched by user!
         }
+        @Override
+        public Stream<E> stream() {
+            return c.stream(); // Must be manually synched by user!
+        }
+        @Override
+        public Stream<E> parallelStream() {
+            return c.parallelStream(); // Must be manually synched by user!
+        }
         private void writeObject(ObjectOutputStream s) throws IOException {
             synchronized (mutex) {s.defaultWriteObject();}
         }
@@ -3172,6 +3187,10 @@
         }
         @Override
         public Spliterator<E> spliterator() {return c.spliterator();}
+        @Override
+        public Stream<E> stream()           {return c.stream();}
+        @Override
+        public Stream<E> parallelStream()   {return c.parallelStream();}
     }
 
     /**
@@ -5097,6 +5116,22 @@
                                                    ") > toIndex(" + toIndex + ")");
             return new CopiesList<>(toIndex - fromIndex, element);
         }
+
+        // Override default methods in Collection
+        @Override
+        public Stream<E> stream() {
+            return IntStream.range(0, n).mapToObj(i -> element);
+        }
+
+        @Override
+        public Stream<E> parallelStream() {
+            return IntStream.range(0, n).parallel().mapToObj(i -> element);
+        }
+
+        @Override
+        public Spliterator<E> spliterator() {
+            return stream().spliterator();
+        }
     }
 
     /**
@@ -5504,6 +5539,10 @@
 
         @Override
         public Spliterator<E> spliterator() {return s.spliterator();}
+        @Override
+        public Stream<E> stream()           {return s.stream();}
+        @Override
+        public Stream<E> parallelStream()   {return s.parallelStream();}
 
         private static final long serialVersionUID = 2454657854757543876L;
 
@@ -5569,10 +5608,14 @@
         @Override
         public void forEach(Consumer<? super E> action) {q.forEach(action);}
         @Override
+        public boolean removeIf(Predicate<? super E> filter) {
+            return q.removeIf(filter);
+        }
+        @Override
         public Spliterator<E> spliterator() {return q.spliterator();}
         @Override
-        public boolean removeIf(Predicate<? super E> filter) {
-            return q.removeIf(filter);
-        }
+        public Stream<E> stream()           {return q.stream();}
+        @Override
+        public Stream<E> parallelStream()   {return q.parallelStream();}
     }
 }
--- a/src/share/classes/java/util/HashSet.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/HashSet.java	Wed Aug 14 15:53:13 2013 -0700
@@ -312,6 +312,18 @@
         }
     }
 
+    /**
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
+     * set.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
+     * {@link Spliterator#DISTINCT}.  Overriding implementations should document
+     * the reporting of additional characteristic values.
+     *
+     * @return a {@code Spliterator} over the elements in this set
+     * @since 1.8
+     */
     public Spliterator<E> spliterator() {
         return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0);
     }
--- a/src/share/classes/java/util/LinkedHashMap.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/LinkedHashMap.java	Wed Aug 14 15:53:13 2013 -0700
@@ -129,10 +129,20 @@
  * exception for its correctness:   <i>the fail-fast behavior of iterators
  * should be used only to detect bugs.</i>
  *
+ * <p>The spliterators returned by the spliterator method of the collections
+ * returned by all of this class's collection view methods are
+ * <em><a href="Spliterator.html#binding">late-binding</a></em>,
+ * <em>fail-fast</em>, and additionally report {@link Spliterator#ORDERED}.
+ *
  * <p>This class is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
+ * @implNote
+ * The spliterators returned by the spliterator method of the collections
+ * returned by all of this class's collection view methods are created from
+ * the iterators of the corresponding collections.
+ *
  * @param <K> the type of keys maintained by this map
  * @param <V> the type of mapped values
  *
--- a/src/share/classes/java/util/LinkedHashSet.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/LinkedHashSet.java	Wed Aug 14 15:53:13 2013 -0700
@@ -170,13 +170,23 @@
     }
 
     /**
-     * Creates a {@code Spliterator}, over the elements in this set, that
-     * reports {@code SIZED}, {@code DISTINCT} and {@code ORDERED}.
-     * Overriding implementations are expected to document if the
-     * {@code Spliterator} reports any additional and relevant characteristic
-     * values.
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@code Spliterator} over the elements in this set.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
+     * {@link Spliterator#DISTINCT}, and {@code ORDERED}.  Implementations
+     * should document the reporting of additional characteristic values.
+     *
+     * @implNote
+     * The implementation creates a
+     * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
+     * from the set's {@code Iterator}.  The spliterator inherits the
+     * <em>fail-fast</em> properties of the set's iterator.
+     * The created {@code Spliterator} additionally reports
+     * {@link Spliterator#SUBSIZED}.
      *
      * @return a {@code Spliterator} over the elements in this set
+     * @since 1.8
      */
     @Override
     public Spliterator<E> spliterator() {
--- a/src/share/classes/java/util/LinkedList.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/LinkedList.java	Wed Aug 14 15:53:13 2013 -0700
@@ -1149,6 +1149,23 @@
             linkLast((E)s.readObject());
     }
 
+    /**
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
+     * list.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
+     * {@link Spliterator#ORDERED}.  Overriding implementations should document
+     * the reporting of additional characteristic values.
+     *
+     * @implNote
+     * The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}
+     * and implements {@code trySplit} to permit limited parallelism..
+     *
+     * @return a {@code Spliterator} over the elements in this list
+     * @since 1.8
+     */
+    @Override
     public Spliterator<E> spliterator() {
         return new LLSpliterator<E>(this, -1, 0);
     }
--- a/src/share/classes/java/util/List.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/List.java	Wed Aug 14 15:53:13 2013 -0700
@@ -671,7 +671,7 @@
      * The default implementation creates a
      * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
      * from the list's {@code Iterator}.  The spliterator inherits the
-     * <em>fail-fast</em> properties of the collection's iterator.
+     * <em>fail-fast</em> properties of the list's iterator.
      *
      * @implNote
      * The created {@code Spliterator} additionally reports
--- a/src/share/classes/java/util/Map.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Map.java	Wed Aug 14 15:53:13 2013 -0700
@@ -579,10 +579,12 @@
     }
 
     /**
-     * Performs the given action on each entry in this map, in the order entries
-     * are returned by an entry set iterator (which may be unspecified), until
-     * all entries have been processed or the action throws an {@code Exception}.
-     * Exceptions thrown by the action are relayed to the caller.
+     * Performs the given action on each entry in this map until all entries
+     * have been processed or the action throws an {@code Exception}.
+     * Exceptions thrown by the action are relayed to the caller. The entries
+     * will be processed in the same order as the entry set iterator unless that
+     * order is unspecified in which case implementations may use an order which
+     * differs from the entry set iterator.
      *
      * <p>The default implementation should be overridden by implementations if
      * they can provide a more performant implementation than an iterator-based
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/MayHoldCloseableResource.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An object that may (but need not) hold one or more references to
+ * resources that will be released when closed.  Such objects may be
+ * used with try-with-resources or related {@code try...finally}
+ * constructions that ensure they are closed as soon as they are no
+ * longer needed.  Interface {@code MayHoldCloseableResource} indicates that
+ * only a minority of usages warrant resource control constructions:
+ * those specialized to known resource-bearing instances, or those
+ * that must operate in complete generality.
+ *
+ * <p>For example, most usages of the {@link java.util.stream.Stream}
+ * classes operate on data sources such as an array, {@code
+ * Collection}, or generator function that do not require or benefit
+ * from explicit resource control.  However, some uses of IO channels
+ * as data sources do.
+ *
+ * <p>Annotation {@link HoldsResource} may be used to guide users or static
+ * analysis tools to deciding whether resource-control constructions are
+ * warranted when using particular instantiations of
+ * {@code MayHoldCloseableResource}.
+ *
+ * @see AutoCloseable
+ * @see HoldsResource
+ */
+public interface MayHoldCloseableResource extends AutoCloseable {
+    /**
+     * Closes this resource, relinquishing any underlying resources.
+     * This method is invoked automatically on objects managed by the
+     * {@code try}-with-resources statement.
+     *
+     * Implementers of this interface are strongly encouraged
+     * to make their {@code close} methods idempotent.
+     *
+     * @see AutoCloseable#close()
+     */
+    @Override
+    void close();
+
+    /**
+     * Indicates that a variable holding a {@code MayHoldCloseableResource} or
+     * a method returning a {@code MayHoldCloseableResource} definitely does
+     * hold a closeable resource.
+     */
+    @Retention(RetentionPolicy.CLASS)
+    @Documented
+    @interface HoldsResource { }
+}
--- a/src/share/classes/java/util/PrimitiveIterator.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/PrimitiveIterator.java	Wed Aug 14 15:53:13 2013 -0700
@@ -56,12 +56,12 @@
  * primitive values occur when operating on primitive subtype specializations.
  *
  * @param <T> the type of elements returned by this PrimitiveIterator.  The
- *        type must be a wrapper type for a primitive type, such as
- *        {@code Integer} for the primitive {@code int} type.
+ * type must be a wrapper type for a primitive type, such as {@code Integer}
+ * for the primitive {@code int} type.
  * @param <T_CONS> the type of primitive consumer.  The type must be a
- *        primitive specialization of {@link java.util.function.Consumer} for
- *        {@code T}, such as {@link java.util.function.IntConsumer} for
- *        {@code Integer}.
+ * primitive specialization of {@link java.util.function.Consumer} for
+ * {@code T}, such as {@link java.util.function.IntConsumer} for
+ * {@code Integer}.
  *
  * @since 1.8
  */
--- a/src/share/classes/java/util/PriorityQueue.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/PriorityQueue.java	Wed Aug 14 15:53:13 2013 -0700
@@ -795,6 +795,19 @@
         heapify();
     }
 
+    /**
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
+     * queue.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
+     * {@link Spliterator#SUBSIZED}, and {@link Spliterator#NONNULL}.
+     * Overriding implementations should document the reporting of additional
+     * characteristic values.
+     *
+     * @return a {@code Spliterator} over the elements in this queue
+     * @since 1.8
+     */
     public final Spliterator<E> spliterator() {
         return new PriorityQueueSpliterator<E>(this, 0, -1, 0);
     }
--- a/src/share/classes/java/util/Random.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Random.java	Wed Aug 14 15:53:13 2013 -0700
@@ -26,9 +26,13 @@
 package java.util;
 import java.io.*;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
 import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
+import java.util.stream.StreamSupport;
 
 import sun.misc.Unsafe;
 
@@ -85,6 +89,13 @@
     private static final long addend = 0xBL;
     private static final long mask = (1L << 48) - 1;
 
+    private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
+
+    // IllegalArgumentException messages
+    static final String BadBound = "bound must be positive";
+    static final String BadRange = "bound must be greater than origin";
+    static final String BadSize  = "size must be non-negative";
+
     /**
      * Creates a new random number generator. This constructor sets
      * the seed of the random number generator to a value very likely
@@ -222,6 +233,85 @@
     }
 
     /**
+     * The form of nextLong used by LongStream Spliterators.  If
+     * origin is greater than bound, acts as unbounded form of
+     * nextLong, else as bounded form.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final long internalNextLong(long origin, long bound) {
+        long r = nextLong();
+        if (origin < bound) {
+            long n = bound - origin, m = n - 1;
+            if ((n & m) == 0L)  // power of two
+                r = (r & m) + origin;
+            else if (n > 0L) {  // reject over-represented candidates
+                for (long u = r >>> 1;            // ensure nonnegative
+                     u + m - (r = u % n) < 0L;    // rejection check
+                     u = nextLong() >>> 1) // retry
+                    ;
+                r += origin;
+            }
+            else {              // range not representable as long
+                while (r < origin || r >= bound)
+                    r = nextLong();
+            }
+        }
+        return r;
+    }
+
+    /**
+     * The form of nextInt used by IntStream Spliterators.
+     * Exactly the same as long version, except for types.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final int internalNextInt(int origin, int bound) {
+        if (origin < bound) {
+            int r = next(31);
+            int n = bound - origin, m = n - 1;
+            if ((n & m) == 0)
+                r = (int)((n * (long)r) >> 31) + origin;
+            else if (n > 0) {
+                for (int u = r;
+                     u - (r = u % n) + m < 0;
+                     u = next(31))
+                    ;
+                r += origin;
+            }
+            else {
+                while (r < origin || r >= bound)
+                    r = next(32);
+            }
+            return r;
+        }
+        else {
+            return next(32);
+        }
+    }
+
+    /**
+     * The form of nextDouble used by DoubleStream Spliterators.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final double internalNextDouble(double origin, double bound) {
+        double r = nextDouble();
+        if (origin < bound) {
+            r = r * (bound - origin) + origin;
+            if (r >= bound) // correct for rounding
+                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
+        }
+        return r;
+    }
+
+    /**
      * Returns the next pseudorandom, uniformly distributed {@code int}
      * value from this random number generator's sequence. The general
      * contract of {@code nextInt} is that one {@code int} value is
@@ -289,7 +379,7 @@
      * greatly increases the length of the sequence of values returned by
      * successive calls to this method if n is a small power of two.
      *
-     * @param n the bound on the random number to be returned.  Must be
+     * @param bound the bound on the random number to be returned.  Must be
      *        positive.
      * @return the next pseudorandom, uniformly distributed {@code int}
      *         value between {@code 0} (inclusive) and {@code n} (exclusive)
@@ -297,20 +387,39 @@
      * @throws IllegalArgumentException if n is not positive
      * @since 1.2
      */
+    public int nextInt(int bound) {
+        if (bound <= 0)
+            throw new IllegalArgumentException(BadBound);
 
-    public int nextInt(int n) {
-        if (n <= 0)
-            throw new IllegalArgumentException("n must be positive");
+        int r = next(31);
+        int m = bound - 1;
+        if ((bound & m) == 0)  // i.e., bound is a power of 2
+            r = (int)((bound * (long)r) >> 31);
+        else {
+            for (int u = r;
+                 u - (r = u % bound) + m < 0;
+                 u = next(31))
+                ;
+        }
+        return r;
+    }
 
-        if ((n & -n) == n)  // i.e., n is a power of 2
-            return (int)((n * (long)next(31)) >> 31);
-
-        int bits, val;
-        do {
-            bits = next(31);
-            val = bits % n;
-        } while (bits - val + (n-1) < 0);
-        return val;
+    /**
+     * Returns a pseudorandom {@code int} value between the specified
+     * origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param origin the least value returned
+     * @param bound the upper bound (exclusive)
+     * @return a pseudorandom {@code int} value between the origin
+     *         (inclusive) and the bound (exclusive)
+     * @throws IllegalArgumentException if {@code origin} is greater than
+     *         or equal to {@code bound}
+     */
+    public int nextInt(int origin, int bound) {
+        // @@@ Document algorithm as for other int methods?
+        if (origin >= bound)
+            throw new IllegalArgumentException(BadRange);
+        return internalNextInt(origin, bound);
     }
 
     /**
@@ -338,6 +447,40 @@
     }
 
     /**
+     * Returns a pseudorandom {@code long} value between zero (inclusive)
+     * and the specified bound (exclusive).
+     *
+     * @param bound the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return a pseudorandom {@code long} value between zero
+     *         (inclusive) and the bound (exclusive)
+     * @throws IllegalArgumentException if {@code bound} is not positive
+     */
+    public long nextLong(long bound) {
+        if (bound <= 0)
+            throw new IllegalArgumentException(BadBound);
+        return internalNextLong(0, bound);
+    }
+
+    /**
+     * Returns a pseudorandom {@code long} value between the specified
+     * origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param origin the least value returned
+     * @param bound the upper bound (exclusive)
+     * @return a pseudorandom {@code long} value between the origin
+     *         (inclusive) and the bound (exclusive)
+     * @throws IllegalArgumentException if {@code origin} is greater than
+     *         or equal to {@code bound}
+     */
+    public long nextLong(long origin, long bound) {
+        if (origin >= bound)
+            throw new IllegalArgumentException(BadRange);
+        return internalNextLong(origin, bound);
+    }
+
+
+    /**
      * Returns the next pseudorandom, uniformly distributed
      * {@code boolean} value from this random number generator's
      * sequence. The general contract of {@code nextBoolean} is that one
@@ -442,8 +585,42 @@
      * @see Math#random
      */
     public double nextDouble() {
-        return (((long)(next(26)) << 27) + next(27))
-            / (double)(1L << 53);
+        return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT;
+    }
+
+    /**
+     * Returns a pseudorandom {@code double} value between 0.0
+     * (inclusive) and the specified bound (exclusive).
+     *
+     * @param bound the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return a pseudorandom {@code double} value between zero
+     *         (inclusive) and the bound (exclusive)
+     * @throws IllegalArgumentException if {@code bound} is not positive
+     */
+    public double nextDouble(double bound) {
+        if (!(bound > 0.0))
+            throw new IllegalArgumentException(BadBound);
+        double result = nextDouble() * bound;
+        return (result < bound) ?  result : // correct for rounding
+               Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
+    }
+
+    /**
+     * Returns a pseudorandom {@code double} value between the specified
+     * origin (inclusive) and bound (exclusive).
+     *
+     * @param origin the least value returned
+     * @param bound the upper bound
+     * @return a pseudorandom {@code double} value between the origin
+     *         (inclusive) and the bound (exclusive)
+     * @throws IllegalArgumentException if {@code origin} is greater than
+     *         or equal to {@code bound}
+     */
+    public double nextDouble(double origin, double bound) {
+        if (!(origin < bound))
+            throw new IllegalArgumentException(BadRange);
+        return internalNextDouble(origin, bound);
     }
 
     private double nextNextGaussian;
@@ -513,57 +690,430 @@
         }
     }
 
+    // stream methods, coded in a way intended to better isolate for
+    // maintenance purposes the small differences across forms.
+
     /**
-     * Returns a stream of pseudorandom, uniformly distributed
-     * {@code integer} values from this random number generator's
-     * sequence. Values are obtained as needed by calling
-     * {@link #nextInt()}.
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code int} values.
      *
-     * @return an infinite stream of {@code integer} values
-     * @since 1.8
+     * @param streamSize the number of values to generate
+     * @return a stream of pseudorandom {@code int} values
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
      */
-    public IntStream ints() {
-        return IntStream.generate(this::nextInt);
+    public IntStream ints(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, streamSize, Integer.MAX_VALUE, 0),
+                 false);
     }
 
     /**
-     * Returns a stream of pseudorandom, uniformly distributed
-     * {@code long} values from this random number generator's
-     * sequence. Values are obtained as needed by calling
-     * {@link #nextLong()}.
+     * Returns an effectively unlimited stream of pseudorandom {@code int}
+     * values.
      *
-     * @return an infinite stream of {@code long} values
-     * @since 1.8
+     * @implNote This method is implemented to be equivalent to {@code
+     * ints(Long.MAX_VALUE)}.
+     *
+     * @return a stream of pseudorandom {@code int} values
      */
-    public LongStream longs() {
-        return LongStream.generate(this::nextLong);
+    public IntStream ints() {
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
+                 false);
     }
 
     /**
-     * Returns a stream of pseudorandom, uniformly distributed
-     * {@code double} values between {@code 0.0} and {@code 1.0}
-     * from this random number generator's sequence. Values are
-     * obtained as needed by calling {@link #nextDouble()}.
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code int} values, each conforming to the given
+     * origin and bound.
      *
-     * @return an infinite stream of {@code double} values
-     * @since 1.8
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the origin of each random value
+     * @param randomNumberBound the bound of each random value
+     * @return a stream of pseudorandom {@code int} values,
+     *         each with the given origin and bound
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
      */
-    public DoubleStream doubles() {
-        return DoubleStream.generate(this::nextDouble);
+    public IntStream ints(long streamSize, int randomNumberOrigin,
+                          int randomNumberBound) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
+                 false);
     }
 
     /**
-     * Returns a stream of pseudorandom, Gaussian ("normally")
-     * distributed {@code double} values with mean {@code 0.0}
-     * and standard deviation {@code 1.0} from this random number
-     * generator's sequence. Values are obtained as needed by
-     * calling {@link #nextGaussian()}.
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * int} values, each conforming to the given origin and bound.
      *
-     * @return an infinite stream of {@code double} values
-     * @since 1.8
+     * @implNote This method is implemented to be equivalent to {@code
+     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     *
+     * @param randomNumberOrigin the origin of each random value
+     * @param randomNumberBound the bound of each random value
+     * @return a stream of pseudorandom {@code int} values,
+     *         each with the given origin and bound
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
      */
-    public DoubleStream gaussians() {
-        return DoubleStream.generate(this::nextGaussian);
+    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.intStream
+                (new RandomIntsSpliterator
+                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code long} values.
+     *
+     * @param streamSize the number of values to generate
+     * @return a stream of pseudorandom {@code long} values
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     */
+    public LongStream longs(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, streamSize, Long.MAX_VALUE, 0L),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code long}
+     * values.
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * longs(Long.MAX_VALUE)}.
+     *
+     * @return a stream of pseudorandom {@code long} values
+     */
+    public LongStream longs() {
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code long} values, each conforming to the
+     * given origin and bound.
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the origin of each random value
+     * @param randomNumberBound the bound of each random value
+     * @return a stream of pseudorandom {@code long} values,
+     *         each with the given origin and bound
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     */
+    public LongStream longs(long streamSize, long randomNumberOrigin,
+                            long randomNumberBound) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * long} values, each conforming to the given origin and bound.
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     *
+     * @param randomNumberOrigin the origin of each random value
+     * @param randomNumberBound the bound of each random value
+     * @return a stream of pseudorandom {@code long} values,
+     *         each with the given origin and bound
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     */
+    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
+        if (randomNumberOrigin >= randomNumberBound)
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.longStream
+                (new RandomLongsSpliterator
+                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code double} values, each between zero
+     * (inclusive) and one (exclusive).
+     *
+     * @param streamSize the number of values to generate
+     * @return a stream of {@code double} values
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     */
+    public DoubleStream doubles(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * double} values, each between zero (inclusive) and one
+     * (exclusive).
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * doubles(Long.MAX_VALUE)}.
+     *
+     * @return a stream of pseudorandom {@code double} values
+     */
+    public DoubleStream doubles() {
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
+                 false);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandom {@code double} values, each conforming to the
+     * given origin and bound.
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the origin of each random value
+     * @param randomNumberBound the bound of each random value
+     * @return a stream of pseudorandom {@code double} values,
+     * each with the given origin and bound
+     * @throws IllegalArgumentException if {@code streamSize} is
+     * less than zero
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     */
+    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
+                                double randomNumberBound) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BadSize);
+        if (!(randomNumberOrigin < randomNumberBound))
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandom {@code
+     * double} values, each conforming to the given origin and bound.
+     *
+     * @implNote This method is implemented to be equivalent to {@code
+     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     *
+     * @param randomNumberOrigin the origin of each random value
+     * @param randomNumberBound the bound of each random value
+     * @return a stream of pseudorandom {@code double} values,
+     * each with the given origin and bound
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     */
+    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
+        if (!(randomNumberOrigin < randomNumberBound))
+            throw new IllegalArgumentException(BadRange);
+        return StreamSupport.doubleStream
+                (new RandomDoublesSpliterator
+                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+                 false);
+    }
+
+    /**
+     * Spliterator for int streams.  We multiplex the four int
+     * versions into one class by treating a bound less than origin as
+     * unbounded, and also by treating "infinite" as equivalent to
+     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
+     * approach. The long and double versions of this class are
+     * identical except for types.
+     */
+    static final class RandomIntsSpliterator implements Spliterator.OfInt {
+        final Random rng;
+        long index;
+        final long fence;
+        final int origin;
+        final int bound;
+        RandomIntsSpliterator(Random rng, long index, long fence,
+                              int origin, int bound) {
+            this.rng = rng; this.index = index; this.fence = fence;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public RandomIntsSpliterator trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            return (m <= i) ? null :
+                   new RandomIntsSpliterator(rng, i, index = m, origin, bound);
+        }
+
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+
+        public boolean tryAdvance(IntConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(rng.internalNextInt(origin, bound));
+                index = i + 1;
+                return true;
+            }
+            return false;
+        }
+
+        public void forEachRemaining(IntConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                Random r = rng;
+                int o = origin, b = bound;
+                do {
+                    consumer.accept(r.internalNextInt(o, b));
+                } while (++i < f);
+            }
+        }
+    }
+
+    /**
+     * Spliterator for long streams.
+     */
+    static final class RandomLongsSpliterator implements Spliterator.OfLong {
+        final Random rng;
+        long index;
+        final long fence;
+        final long origin;
+        final long bound;
+        RandomLongsSpliterator(Random rng, long index, long fence,
+                               long origin, long bound) {
+            this.rng = rng; this.index = index; this.fence = fence;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public RandomLongsSpliterator trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            return (m <= i) ? null :
+                   new RandomLongsSpliterator(rng, i, index = m, origin, bound);
+        }
+
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+
+        public boolean tryAdvance(LongConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(rng.internalNextLong(origin, bound));
+                index = i + 1;
+                return true;
+            }
+            return false;
+        }
+
+        public void forEachRemaining(LongConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                Random r = rng;
+                long o = origin, b = bound;
+                do {
+                    consumer.accept(r.internalNextLong(o, b));
+                } while (++i < f);
+            }
+        }
+
+    }
+
+    /**
+     * Spliterator for double streams.
+     */
+    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
+        final Random rng;
+        long index;
+        final long fence;
+        final double origin;
+        final double bound;
+        RandomDoublesSpliterator(Random rng, long index, long fence,
+                                 double origin, double bound) {
+            this.rng = rng; this.index = index; this.fence = fence;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public RandomDoublesSpliterator trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            return (m <= i) ? null :
+                   new RandomDoublesSpliterator(rng, i, index = m, origin, bound);
+        }
+
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+
+        public boolean tryAdvance(DoubleConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(rng.internalNextDouble(origin, bound));
+                index = i + 1;
+                return true;
+            }
+            return false;
+        }
+
+        public void forEachRemaining(DoubleConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                Random r = rng;
+                double o = origin, b = bound;
+                do {
+                    consumer.accept(r.internalNextDouble(o, b));
+                } while (++i < f);
+            }
+        }
     }
 
     /**
--- a/src/share/classes/java/util/Set.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Set.java	Wed Aug 14 15:53:13 2013 -0700
@@ -394,7 +394,7 @@
      * The default implementation creates a
      * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
      * from the set's {@code Iterator}.  The spliterator inherits the
-     * <em>fail-fast</em> properties of the collection's iterator.
+     * <em>fail-fast</em> properties of the set's iterator.
      *
      * @implNote
      * The created {@code Spliterator} additionally reports
--- a/src/share/classes/java/util/SortedSet.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/SortedSet.java	Wed Aug 14 15:53:13 2013 -0700
@@ -238,7 +238,7 @@
      * The default implementation creates a
      * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
      * from the sorted set's {@code Iterator}.  The spliterator inherits the
-     * <em>fail-fast</em> properties of the collection's iterator.  The
+     * <em>fail-fast</em> properties of the set's iterator.  The
      * spliterator's comparator is the same as the sorted set's comparator.
      *
      * @implNote
--- a/src/share/classes/java/util/Spliterator.java	Tue Aug 13 10:42:37 2013 -0700
+++ b/src/share/classes/java/util/Spliterator.java	Wed Aug 14 15:53:13 2013 -0700
@@ -74,7 +74,11 @@
  * source prior to binding are reflected when the Spliterator is traversed.
  * After binding a Spliterator should, on a best-effort basis, throw
  * {@link ConcurrentModificationException} if structural interference is
- * detected.  Spliterators that do this are called <em>fail-fast</em>.
+ * detected.  Spliterators that do this are called <em>fail-fast</em>.  The
+ * bulk traversal method ({@link #forEachRemaining forEachRemaining()}) of a
+ * Spliterator may optimize traversal and check for structural interface after
+ * all elements have been traversed, rather than checking per-element and
+ * failing immediately.
  *
  * <p>Spliterators can provide an estimate of the number of remaining elements
  * via the {@link #estimateSize} method.  Ideally, as reflected in characteristic
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/SplittableRandom.java	Wed Aug 14 15:53:13 2013 -0700
@@ -0,0 +1,985 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util;
+
+import java.net.InetAddress;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.Spliterator;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+import java.util.function.DoubleConsumer;
+import java.util.stream.StreamSupport;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.DoubleStream;
+
+/**
+ * A generator of uniform pseudorandom values applicable for use in
+ * (among other contexts) isolated parallel computations that may
+ * generate subtasks. Class SplittableRandom supports methods for
+ * producing pseudorandom numbers of type {@code int}, {@code long},
+ * and {@code double} with similar usages as for class
+ * {@link java.util.Random} but differs in the following ways:
+ *
+ * <ul>
+ *
+ * <li>Series of generated values pass the DieHarder suite testing
+ * independence and uniformity properties of random number generators.
+ * (Most recently validated with <a
+ * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
+ * 3.31.1</a>.) These tests validate only the methods for certain
+ * types and ranges, but similar properties are expected to hold, at
+ * least approximately, for others as well. The <em>period</em>
+ * (length of any series of generated values before it repeats) is at
+ * least 2<sup>64</sup>. </li>
+ *
+ * <li> Method {@link #split} constructs and returns a new
+ * SplittableRandom instance that shares no mutable state with the
+ * current instance. However, with very high probability, the
+ * values collectively generated by the two objects have the same
+ * statistical properties as if the same quantity of values were
+ * generated by a single thread using a single {@code
+ * SplittableRandom} object.  </li>
+ *
+ * <li>Instances of SplittableRandom are <em>not</em> thread-safe.
+ * They are designed to be split, not shared, across threads. For
+ * example, a {@link java.util.concurrent.ForkJoinTask
+ * fork/join-style} computation using random numbers might include a
+ * construction of the form {@code new
+ * Subtask(aSplittableRandom.split()).fork()}.
+ *
+ * <li>This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in {@code
+ * stream.parallel()} mode.</li>
+ *
+ * </ul>
+ *
+ * @author  Guy Steele
+ * @author  Doug Lea
+ * @since   1.8
+ */
+public class SplittableRandom {
+
+    /*
+     * Implementation Overview.
+     *
+     * This algorithm was inspired by the "DotMix" algorithm by
+     * Leiserson, Schardl, and Sukha "Deterministic Parallel
+     * Random-Number Generation for Dynamic-Multithreading Platforms",
+     * PPoPP 2012, as well as those in "Parallel random numbers: as
+     * easy as 1, 2, 3" by Salmon, Morae, Dror, and Shaw, SC 2011.  It
+     * differs mainly in simplifying and cheapening operations.
+     *
+     * The primary update step (method nextSeed()) is to add a
+     * constant ("gamma") to the current (64 bit) seed, forming a
+     * simple sequence.  The seed and the gamma values for any two
+     * SplittableRandom instances are highly likely to be different.
+     *
+     * Methods nextLong, nextInt, and derivatives do not return the
+     * sequence (seed) values, but instead a hash-like bit-mix of
+     * their bits, producing more independently distributed sequences.
+     * For nextLong, the mix64 bit-mixing function computes the same
+     * value as the "64-bit finalizer" function in Austin Appleby's
+     * MurmurHash3 algorithm.  See
+     * http://code.google.com/p/smhasher/wiki/MurmurHash3 , which
+     * comments: "The constants for the finalizers were generated by a
+     * simple simulated-annealing algorithm, and both avalanche all
+     * bits of 'h' to within 0.25% bias." The mix32 function is
+     * equivalent to (int)(mix64(seed) >>> 32), but faster because it
+     * omits a step that doesn't contribute to result.
+     *
+     * The split operation uses the current generator to form the seed
+     * and gamma for another SplittableRandom.  To conservatively
+     * avoid potential correlations between seed and value generation,
+     * gamma selection (method nextGamma) uses the "Mix13" constants
+     * for MurmurHash3 described by David Stafford
+     * (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
+     * To avoid potential weaknesses in bit-mixing transformations, we
+     * restrict gammas to odd values with at least 12 and no more than
+     * 52 bits set.  Rather than rejecting candidates with too few or
+     * too many bits set, method nextGamma flips some bits (which has
+     * the effect of mapping at most 4 to any given gamma value).
+     * This reduces the effective set of 64bit odd gamma values by
+     * about 2<sup>14</sup>, a very tiny percentage, and serves as an
+     * automated screening for sequence constant selection that is
+     * left as an empirical decision in some other hashing and crypto
+     * algorithms.
+     *
+     * The resulting generator thus transforms a sequence in which
+     * (typically) many bits change on each step, with an inexpensive
+     * mixer with good (but less than cryptographically secure)
+     * avalanching.
+     *
+     * The default (no-argument) constructor, in essence, invokes
+     * split() for a common "seeder" SplittableRandom.  Unlike other
+     * cases, this split must be performed in a thread-safe manner, so
+     * we use an AtomicLong to represent the seed rather than use an
+     * explicit SplittableRandom. To bootstrap the seeder, we start
+     * off using a seed based on current time and host. This serves as
+     * a slimmed-down (and insecure) variant of SecureRandom that also
+     * avoids stalls that may occur when using /dev/random.
+     *
+     * It is a relatively simple matter to apply the basic design here
+     * to use 128 bit seeds. However, emulating 128bit arithmetic and
+     * carrying around twice the state add more overhead than appears
+     * warranted for current usages.
+     *
+     * File organization: First the non-public methods that constitute
+     * the main algorithm, then the main public methods, followed by
+     * some custom spliterator classes needed for stream methods.
+     */
+
+    /**
+     * The initial gamma value for (unsplit) SplittableRandoms. Must
+     * be odd with at least 12 and no more than 52 bits set. Currently
+     * set to the golden ratio scaled to 64bits.
+     */
+    private static final long INITIAL_GAMMA = 0x9e3779b97f4a7c15L;
+
+    /**
+     * The least non-zero value returned by nextDouble(). This value
+     * is scaled by a random value of 53 bits to produce a result.
+     */
+    private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
+
+    /**
+     * The seed. Updated only via method nextSeed.
+     */
+    private long seed;
+
+    /**
+     * The step value.
+     */
+    private final long gamma;
+
+    /**
+     * Internal constructor used by all others except default constructor.
+     */
+    private SplittableRandom(long seed, long gamma) {
+        this.seed = seed;
+        this.gamma = gamma;
+    }
+
+    /**
+     * Computes MurmurHash3 64bit mix function.
+     */
+    private static long mix64(long z) {
+        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
+        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
+        return z ^ (z >>> 33);
+    }
+
+    /**
+     * Returns the 32 high bits of mix64(z) as int.
+     */
+    private static int mix32(long z) {
+        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
+        return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
+    }
+
+    /**
+     * Returns the gamma value to use for a new split instance.
+     */
+    private static long nextGamma(long z) {
+        z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; // Stafford "Mix13"
+        z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
+        z = (z ^ (z >>> 31)) | 1L; // force to be odd
+        int n = Long.bitCount(z);  // ensure enough 0 and 1 bits
+        return (n < 12 || n > 52) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
+    }
+
+    /**
+     * Adds gamma to seed.
+     */
+    private long nextSeed() {
+        return seed += gamma;
+    }
+
+    /**
+     * The seed generator for default constructors.
+     */
+    private static final AtomicLong seeder =
+        new AtomicLong(mix64((((long)hashedHostAddress()) << 32) ^
+                             System.currentTimeMillis()) ^
+                       mix64(System.nanoTime()));
+
+    /**
+     * Returns hash of local host IP address, if available; else 0.
+     */
+    private static int hashedHostAddress() {
+        try {
+            return InetAddress.getLocalHost().hashCode();
+        } catch (Exception ex) {
+            return 0;
+        }
+    }
+
+    // IllegalArgumentException messages
+    static final String BadBound = "bound must be positive";
+    static final String BadRange = "bound must be greater than origin";
+    static final String BadSize  = "size must be non-negative";
+
+    /*
+     * Internal versions of nextX methods used by streams, as well as
+     * the public nextX(origin, bound) methods.  These exist mainly to
+     * avoid the need for multiple versions of stream spliterators
+     * across the different exported forms of streams.
+     */
+
+    /**
+     * The form of nextLong used by LongStream Spliterators.  If
+     * origin is greater than bound, acts as unbounded form of
+     * nextLong, else as bounded form.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final long internalNextLong(long origin, long bound) {
+        /*
+         * Four Cases:
+         *
+         * 1. If the arguments indicate unbounded form, act as
+         * nextLong().
+         *
+         * 2. If the range is an exact power of two, apply the
+         * associated bit mask.
+         *
+         * 3. If the range is positive, loop to avoid potential bias
+         * when the implicit nextLong() bound (2<sup>64</sup>) is not
+         * evenly divisible by the range. The loop rejects candidates
+         * computed from otherwise over-represented values.  The
+         * expected number of iterations under an ideal generator
+         * varies from 1 to 2, depending on the bound. The loop itself
+         * takes an unlovable form. Because the first candidate is
+         * already available, we need a break-in-the-middle
+         * construction, which is concisely but cryptically performed
+         * within the while-condition of a body-less for loop.
+         *
+         * 4. Otherwise, the range cannot be represented as a positive
+         * long.  The loop repeatedly generates unbounded longs until
+         * obtaining a candidate meeting constraints (with an expected
+         * number of iterations of less than two).
+         */
+
+        long r = mix64(nextSeed());
+        if (origin < bound) {
+            long n = bound - origin, m = n - 1;
+            if ((n & m) == 0L)  // power of two
+                r = (r & m) + origin;
+            else if (n > 0L) {  // reject over-represented candidates
+                for (long u = r >>> 1;            // ensure nonnegative
+                     u + m - (r = u % n) < 0L;    // rejection check
+                     u = mix64(nextSeed()) >>> 1) // retry
+                    ;
+                r += origin;
+            }
+            else {              // range not representable as long
+                while (r < origin || r >= bound)
+                    r = mix64(nextSeed());
+            }
+        }
+        return r;
+    }
+
+    /**
+     * The form of nextInt used by IntStream Spliterators.
+     * Exactly the same as long version, except for types.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final int internalNextInt(int origin, int bound) {
+        int r = mix32(nextSeed());
+        if (origin < bound) {
+            int n = bound - origin, m = n - 1;
+            if ((n & m) == 0)
+                r = (r & m) + origin;
+            else if (n > 0) {
+                for (int u = r >>> 1;
+                     u + m - (r = u % n) < 0;
+                     u = mix32(nextSeed()) >>> 1)
+                    ;
+                r += origin;
+            }
+            else {
+                while (r < origin || r >= bound)
+                    r = mix32(nextSeed());
+            }
+        }
+        return r;
+    }
+
+    /**
+     * The form of nextDouble used by DoubleStream Spliterators.
+     *
+     * @param origin the least value, unless greater than bound
+     * @param bound the upper bound (exclusive), must not equal origin
+     * @return a pseudorandom value
+     */
+    final double internalNextDouble(double origin, double bound) {
+        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
+        if (origin < bound) {
+            r = r * (bound - origin) + origin;
+            if (r >= bound) // correct for rounding
+                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
+        }
+        return r;
+    }
+
+    /* ---------------- public methods ---------------- */
+
+    /**
+     * Creates a new SplittableRandom instance using the specified
+     * initial seed. SplittableRandom instances created with the same
+     * seed in the same program generate identical sequences of values.
+     *
+     * @param seed the initial seed
+     */
+    public SplittableRandom(long seed) {
+        this(seed, INITIAL_GAMMA);
+    }
+
+    /**
+     * Creates a new SplittableRandom instance that is likely to
+     * generate sequences of values that are statistically independent
+     * of those of any other instances in the current program; and
+     * may, and typically does, vary across program invocations.
+     */
+    public SplittableRandom() { // emulate seeder.split()
+        this.gamma = nextGamma(this.seed = seeder.addAndGet(INITIAL_GAMMA));
+    }
+
+    /**
+     * Constructs and returns a new SplittableRandom instance that
+     * shares no mutable state with this instance. However, with very
+     * high probability, the set of values collectively ge