changeset 7264:e246bc03c8cb

Merge
author lana
date Wed, 05 Jun 2013 00:37:11 -0700
parents 9a8e0140123a 7eae7c89dab4
children 3e904a3f3c9f
files test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh
diffstat 142 files changed, 5475 insertions(+), 2806 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Jun 03 16:37:13 2013 +0400
+++ b/.hgtags	Wed Jun 05 00:37:11 2013 -0700
@@ -212,3 +212,5 @@
 8dbb4b159e04de3c447c9242c70505e71f8624c7 jdk8-b88
 845025546e35519fbb8970e79fc2a834063a5e19 jdk8-b89
 c63eda8f63008a4398d2c22ac8d72f7fef6f9238 jdk8-b90
+169451cf0cc53bde5af24f9820ea3f35ec4b4df4 jdk8-b91
+a2a2a91075ad85becbe10a39d7fd04ef9bea8df5 jdk8-b92
--- a/make/sun/awt/FILES_c_unix.gmk	Mon Jun 03 16:37:13 2013 +0400
+++ b/make/sun/awt/FILES_c_unix.gmk	Wed Jun 05 00:37:11 2013 -0700
@@ -171,3 +171,13 @@
         GLXSurfaceData.c \
         AccelGlyphCache.c \
 	CUPSfuncs.c
+
+ifeq ($(PLATFORM), macosx)
+FILES_NO_MOTIF_objc = \
+		AWTFont.m \
+		AWTStrike.m \
+		CCharToGlyphMapper.m \
+		CGGlyphImages.m \
+		CGGlyphOutlines.m \
+		CoreTextSupport.m
+endif # PLATFORM
--- a/make/sun/awt/FILES_export_unix.gmk	Mon Jun 03 16:37:13 2013 +0400
+++ b/make/sun/awt/FILES_export_unix.gmk	Wed Jun 05 00:37:11 2013 -0700
@@ -187,3 +187,14 @@
 	java/awt/dnd/DnDConstants.java \
 	sun/awt/CausedFocusEvent.java
 
+ifeq ($(PLATFORM), macosx)
+ifeq ($(HEADLESS), true)
+FILES_export += \
+	sun/awt/SunHints.java \
+	sun/font/CCharToGlyphMapper.java \
+	sun/font/CFont.java \
+	sun/font/CFontManager.java \
+	sun/font/CStrike.java \
+	sun/font/CStrikeDisposer.java
+endif # HEADLESS
+endif # PLATFORM
--- a/make/sun/awt/mawt.gmk	Mon Jun 03 16:37:13 2013 +0400
+++ b/make/sun/awt/mawt.gmk	Wed Jun 05 00:37:11 2013 -0700
@@ -43,6 +43,10 @@
 # compiled based on the motif version.
 FILES_c = $(FILES_NO_MOTIF_c)
 
+ifeq ($(PLATFORM), macosx)
+FILES_objc = $(FILES_NO_MOTIF_objc)
+endif # PLATFORM
+
 ifeq ($(PLATFORM), solaris)
   ifneq ($(ARCH), amd64)
     FILES_reorder += reorder-$(ARCH)
@@ -97,6 +101,10 @@
 vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)/image
 vpath %.c   $(PLATFORM_SRC)/native/$(PKGDIR)/robot_child
 
+ifeq ($(PLATFORM), macosx)
+vpath %.m   $(call NativeSrcDirList,,native/sun/font)
+endif # PLATFORM
+
 #
 # Libraries to link in.
 #
@@ -192,13 +200,21 @@
         $(EVENT_MODEL)
 
 ifeq ($(PLATFORM), macosx)
-CPPFLAGS += -I$(CUPS_HEADERS_PATH)
+CPPFLAGS += -I$(CUPS_HEADERS_PATH) \
+			$(call NativeSrcDirList,-I,native/sun/awt) \
+			$(call NativeSrcDirList,-I,native/sun/font)
 
 ifndef HEADLESS
 CPPFLAGS += -I$(MOTIF_DIR)/include \
             -I$(OPENWIN_HOME)/include 
 LDFLAGS  += -L$(MOTIF_LIB) -L$(OPENWIN_LIB)
-
+else
+LDFLAGS  += -framework Accelerate \
+			-framework ApplicationServices \
+			-framework Cocoa \
+			-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+			-framework JavaNativeFoundation \
+			-framework JavaRuntimeSupport
 endif # !HEADLESS
 endif # PLATFORM
 
--- a/makefiles/CompileNativeLibraries.gmk	Mon Jun 03 16:37:13 2013 +0400
+++ b/makefiles/CompileNativeLibraries.gmk	Wed Jun 05 00:37:11 2013 -0700
@@ -2314,6 +2314,10 @@
 			$(JDK_TOPDIR)/src/solaris/native/sun/java2d/opengl \
 			$(JDK_TOPDIR)/src/solaris/native/sun/java2d/x11
 
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+	LIBAWT_HEADLESS_DIRS+=$(JDK_TOPDIR)/src/macosx/native/sun/font
+endif
+
 LIBAWT_HEADLESS_CFLAGS:=-DHEADLESS=true \
                           -DX11_PATH=\"$(X11_PATH)\" -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
 			  $(CUPS_CFLAGS) \
@@ -2328,6 +2332,12 @@
 			  -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/jdga \
                           $(foreach dir,$(LIBAWT_HEADLESS_DIRS),-I$(dir))
 
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+	LIBAWT_HEADLESS_CFLAGS+=\
+		-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+		-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
+endif
+
 LIBAWT_HEADLESS_FILES:=\
 	awt_Font.c \
 	HeadlessToolkit.c \
@@ -2356,6 +2366,16 @@
         AccelGlyphCache.c \
 	CUPSfuncs.c
 
+ifeq ($(OPENJDK_TARGET_OS),macosx)
+	LIBAWT_HEADLESS_FILES+=\
+		AWTFont.m \
+		AWTStrike.m \
+		CCharToGlyphMapper.m \
+		CGGlyphImages.m \
+		CGGlyphOutlines.m \
+		CoreTextSupport.m
+endif
+
 LIBAWT_HEADLESS_REORDER:=
 ifeq ($(OPENJDK_TARGET_OS), solaris)
 	ifneq ($(OPENJDK_TARGET_CPU), x86_64)
@@ -2382,7 +2402,13 @@
 		REORDER:=$(LIBAWT_HEADLESS_REORDER), \
 		LDFLAGS_SUFFIX_linux:=-ljvm -lawt -lm $(LIBDL) -ljava,\
 		LDFLAGS_SUFFIX_solaris:=$(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX) -lc,\
-		LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava,\
+		LDFLAGS_SUFFIX_macosx:=-ljvm $(LIBCXX) -lawt $(LIBDL) -ljava \
+				 -framework Accelerate \
+				 -framework ApplicationServices \
+				 -framework Cocoa \
+				 -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
+				 -framework JavaNativeFoundation \
+				 -framework JavaRuntimeSupport,\
 		OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libawt_headless,\
 		DEBUG_SYMBOLS:=$(DEBUG_ALL_BINARIES)))
 
--- a/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Wed Jun 05 00:37:11 2013 -0700
@@ -36,6 +36,7 @@
 import javax.print.*;
 import javax.print.attribute.PrintRequestAttributeSet;
 import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.standard.PageRanges;
 
 import sun.java2d.*;
 import sun.print.*;
@@ -173,6 +174,19 @@
         if (nsPrintInfo != null) {
             fNSPrintInfo = nsPrintInfo.getValue();
         }
+
+        PageRanges pageRangesAttr =  (PageRanges)attributes.get(PageRanges.class);
+        if (isSupportedValue(pageRangesAttr, attributes)) {
+            SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
+            // If rangeSelect is not null, we are using AWT's print dialog that has
+            // All, Selection, and Range radio buttons
+            if (rangeSelect == null || rangeSelect == SunPageSelection.RANGE) {
+                int[][] range = pageRangesAttr.getMembers();
+                // setPageRange will set firstPage and lastPage as called in getFirstPage
+                // and getLastPage
+                setPageRange(range[0][0] - 1, range[0][1] - 1);
+            }
+        }
     }
 
     volatile boolean onEventThread;
@@ -225,7 +239,6 @@
          * the end of the document. Note that firstPage
          * and lastPage are 0 based page indices.
          */
-        int numPages = mDocument.getNumberOfPages();
 
         int firstPage = getFirstPage();
         int lastPage = getLastPage();
@@ -242,42 +255,53 @@
                 userCancelled = false;
             }
 
-            if (EventQueue.isDispatchThread()) {
-                // This is an AWT EventQueue, and this print rendering loop needs to block it.
+            //Add support for PageRange
+            PageRanges pr = (attributes == null) ?  null
+                                                 : (PageRanges)attributes.get(PageRanges.class);
+            int[][] prMembers = (pr == null) ? new int[0][0] : pr.getMembers();
+            int loopi = 0;
+            do {
+                if (EventQueue.isDispatchThread()) {
+                    // This is an AWT EventQueue, and this print rendering loop needs to block it.
 
-                onEventThread = true;
+                    onEventThread = true;
 
-                printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
-                    @Override
-                    public SecondaryLoop run() {
-                        return Toolkit.getDefaultToolkit()
-                                .getSystemEventQueue()
-                                .createSecondaryLoop();
+                    printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
+                        @Override
+                        public SecondaryLoop run() {
+                            return Toolkit.getDefaultToolkit()
+                                    .getSystemEventQueue()
+                                    .createSecondaryLoop();
+                        }
+                    });
+
+                    try {
+                        // Fire off the print rendering loop on the AppKit thread, and don't have
+                        //  it wait and block this thread.
+                        if (printLoop(false, firstPage, lastPage)) {
+                            // Start a secondary loop on EDT until printing operation is finished or cancelled
+                            printingLoop.enter();
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
                     }
-                });
+              } else {
+                    // Fire off the print rendering loop on the AppKit, and block this thread
+                    //  until it is done.
+                    // But don't actually block... we need to come back here!
+                    onEventThread = false;
 
-                try {
-                    // Fire off the print rendering loop on the AppKit thread, and don't have
-                    //  it wait and block this thread.
-                    if (printLoop(false, firstPage, lastPage)) {
-                        // Start a secondary loop on EDT until printing operation is finished or cancelled
-                        printingLoop.enter();
+                    try {
+                        printLoop(true, firstPage, lastPage);
+                    } catch (Exception e) {
+                        e.printStackTrace();
                     }
-                } catch (Exception e) {
-                    e.printStackTrace();
                 }
-            } else {
-                // Fire off the print rendering loop on the AppKit, and block this thread
-                //  until it is done.
-                // But don't actually block... we need to come back here!
-                onEventThread = false;
-
-                try {
-                    printLoop(true, firstPage, lastPage);
-                } catch (Exception e) {
-                    e.printStackTrace();
+                if (++loopi < prMembers.length) {
+                     firstPage = prMembers[loopi][0]-1;
+                     lastPage = prMembers[loopi][1] -1;
                 }
-            }
+            }  while (loopi < prMembers.length);
         } finally {
             synchronized (this) {
                 // NOTE: Native code shouldn't allow exceptions out while
--- a/src/macosx/native/sun/font/AWTFont.m	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/macosx/native/sun/font/AWTFont.m	Wed Jun 05 00:37:11 2013 -0700
@@ -395,6 +395,7 @@
 
 #pragma mark --- Miscellaneous JNI ---
 
+#ifndef HEADLESS
 /*
  * Class:     sun_awt_PlatformFont
  * Method:    initIDs
@@ -416,3 +417,4 @@
     (JNIEnv *env, jclass cls)
 {
 }
+#endif
--- a/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -90,14 +90,16 @@
      * Constructs a new instance of Continuation.
      * @param top The name of the object that is to be resolved/operated upon.
      *          This becomes the Continuation's 'starter' and is used to
-     *          calculate the "resolved name" when filling  in a NamingException.
+     *          calculate the "resolved name" when filling in a NamingException.
      * @param environment The environment used by the caller. It is used
-     * when setting the "environment" of a CannotProceedException.
+     *          when setting the "environment" of a CannotProceedException.
      */
+    @SuppressWarnings("unchecked")  // For Hashtable clone: environment.clone()
     public Continuation(Name top, Hashtable<?,?> environment) {
         super();
         starter = top;
-        this.environment = environment;
+        this.environment = (Hashtable<?,?>)
+                ((environment == null) ? null : environment.clone());
     }
 
     /**
--- a/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/com/sun/jndi/toolkit/dir/LazySearchEnumerationImpl.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -69,6 +69,7 @@
             }
     }
 
+    @SuppressWarnings("unchecked")      // For Hashtable clone: env.clone()
     public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
         AttrFilter filter, SearchControls cons,
         Context ctx, Hashtable<String, Object> env, boolean useFactory)
@@ -76,7 +77,8 @@
 
             this.candidates = candidates;
             this.filter = filter;
-            this.env = env;
+            this.env = (Hashtable<String, Object>)
+                    ((env == null) ? null : env.clone());
             this.context = ctx;
             this.useFactory = useFactory;
 
--- a/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -53,7 +53,8 @@
     @SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
     public GenericURLContext(Hashtable<?,?> env) {
         // context that is not tied to any specific URL
-        myEnv = (Hashtable<String, Object>)env;  // copied on write
+        myEnv =
+            (Hashtable<String, Object>)(env == null ? null : env.clone());
     }
 
     public void close() throws NamingException {
@@ -488,22 +489,19 @@
         return result;
     }
 
-    @SuppressWarnings("unchecked") // clone()
     public Object removeFromEnvironment(String propName)
         throws NamingException {
             if (myEnv == null) {
                 return null;
             }
-            myEnv = (Hashtable<String, Object>)myEnv.clone();
             return myEnv.remove(propName);
     }
 
-    @SuppressWarnings("unchecked") // clone()
     public Object addToEnvironment(String propName, Object propVal)
         throws NamingException {
-            myEnv = (myEnv == null)
-                    ? new Hashtable<String, Object>(11, 0.75f)
-                    : (Hashtable<String, Object>)myEnv.clone();
+            if (myEnv == null) {
+                myEnv = new Hashtable<String, Object>(11, 0.75f);
+            }
             return myEnv.put(propName, propVal);
     }
 
--- a/src/share/classes/java/io/FileInputStream.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/io/FileInputStream.java	Wed Jun 05 00:37:11 2013 -0700
@@ -240,13 +240,15 @@
      *
      * <p>The <code>skip</code> method may, for a variety of
      * reasons, end up skipping over some smaller number of bytes,
-     * possibly <code>0</code>. If <code>n</code> is negative, an
-     * <code>IOException</code> is thrown, even though the <code>skip</code>
-     * method of the {@link InputStream} superclass does nothing in this case.
-     * The actual number of bytes skipped is returned.
+     * possibly <code>0</code>. If <code>n</code> is negative, the method
+     * will try to skip backwards. In case the backing file does not support
+     * backward skip at its current position, an <code>IOException</code> is
+     * thrown. The actual number of bytes skipped is returned. If it skips
+     * forwards, it returns a positive value. If it skips backwards, it
+     * returns a negative value.
      *
-     * <p>This method may skip more bytes than are remaining in the backing
-     * file. This produces no exception and the number of bytes skipped
+     * <p>This method may skip more bytes than what are remaining in the
+     * backing file. This produces no exception and the number of bytes skipped
      * may include some number of bytes that were beyond the EOF of the
      * backing file. Attempting to read from the stream after skipping past
      * the end will result in -1 indicating the end of the file.
@@ -261,9 +263,10 @@
     /**
      * Returns an estimate of the number of remaining bytes that can be read (or
      * skipped over) from this input stream without blocking by the next
-     * invocation of a method for this input stream. The next invocation might be
-     * the same thread or another thread.  A single read or skip of this
-     * many bytes will not block, but may read or skip fewer bytes.
+     * invocation of a method for this input stream. Returns 0 when the file
+     * position is beyond EOF. The next invocation might be the same thread
+     * or another thread. A single read or skip of this many bytes will not
+     * block, but may read or skip fewer bytes.
      *
      * <p> In some cases, a non-blocking read (or skip) may appear to be
      * blocked when it is merely slow, for example when reading large
--- a/src/share/classes/java/io/InputStream.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/io/InputStream.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -193,8 +193,10 @@
      * up skipping over some smaller number of bytes, possibly <code>0</code>.
      * This may result from any of a number of conditions; reaching end of file
      * before <code>n</code> bytes have been skipped is only one possibility.
-     * The actual number of bytes skipped is returned.  If <code>n</code> is
-     * negative, no bytes are skipped.
+     * The actual number of bytes skipped is returned. If {@code n} is
+     * negative, the {@code skip} method for class {@code InputStream} always
+     * returns 0, and no bytes are skipped. Subclasses may handle the negative
+     * value differently.
      *
      * <p> The <code>skip</code> method of this class creates a
      * byte array and then repeatedly reads into it until <code>n</code> bytes
--- a/src/share/classes/java/lang/Class.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/lang/Class.java	Wed Jun 05 00:37:11 2013 -0700
@@ -28,6 +28,7 @@
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.Member;
 import java.lang.reflect.Field;
 import java.lang.reflect.Executable;
@@ -115,9 +116,9 @@
  * @since   JDK1.0
  */
 public final class Class<T> implements java.io.Serializable,
-                              java.lang.reflect.GenericDeclaration,
-                              java.lang.reflect.Type,
-                              java.lang.reflect.AnnotatedElement {
+                              GenericDeclaration,
+                              Type,
+                              AnnotatedElement {
     private static final int ANNOTATION= 0x00002000;
     private static final int ENUM      = 0x00004000;
     private static final int SYNTHETIC = 0x00001000;
@@ -3182,7 +3183,7 @@
      */
     @Override
     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
-        return AnnotatedElement.super.isAnnotationPresent(annotationClass);
+        return GenericDeclaration.super.isAnnotationPresent(annotationClass);
     }
 
     /**
--- a/src/share/classes/java/lang/String.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/lang/String.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1010,13 +1010,14 @@
     private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
         char v1[] = value;
         char v2[] = sb.getValue();
-        int i = 0;
-        int n = value.length;
-        while (n-- != 0) {
+        int n = v1.length;
+        if (n != sb.length()) {
+            return false;
+        }
+        for (int i = 0; i < n; i++) {
             if (v1[i] != v2[i]) {
                 return false;
             }
-            i++;
         }
         return true;
     }
@@ -1038,8 +1039,6 @@
      * @since  1.5
      */
     public boolean contentEquals(CharSequence cs) {
-        if (value.length != cs.length())
-            return false;
         // Argument is a StringBuffer, StringBuilder
         if (cs instanceof AbstractStringBuilder) {
             if (cs instanceof StringBuffer) {
@@ -1055,12 +1054,14 @@
             return true;
         // Argument is a generic CharSequence
         char v1[] = value;
-        int i = 0;
-        int n = value.length;
-        while (n-- != 0) {
-            if (v1[i] != cs.charAt(i))
+        int n = v1.length;
+        if (n != cs.length()) {
+            return false;
+        }
+        for (int i = 0; i < n; i++) {
+            if (v1[i] != cs.charAt(i)) {
                 return false;
-            i++;
+            }
         }
         return true;
     }
--- a/src/share/classes/java/lang/StringBuffer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/lang/StringBuffer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -335,10 +335,8 @@
      * @since 1.5
      */
     @Override
-    public StringBuffer append(CharSequence s) {
-        // Note, synchronization achieved via invocations of other StringBuffer methods after
-        // narrowing of s to specific type
-        // Ditto for toStringCache clearing
+    public synchronized StringBuffer append(CharSequence s) {
+        toStringCache = null;
         super.append(s);
         return this;
     }
--- a/src/share/classes/java/lang/Thread.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/lang/Thread.java	Wed Jun 05 00:37:11 2013 -0700
@@ -145,10 +145,10 @@
         registerNatives();
     }
 
-    private char        name[];
-    private int         priority;
-    private Thread      threadQ;
-    private long        eetop;
+    private volatile char  name[];
+    private int            priority;
+    private Thread         threadQ;
+    private long           eetop;
 
     /* Whether or not to single_step this thread. */
     private boolean     single_step;
@@ -1135,7 +1135,7 @@
      * @see        #getName
      * @see        #checkAccess()
      */
-    public final void setName(String name) {
+    public final synchronized void setName(String name) {
         checkAccess();
         this.name = name.toCharArray();
         if (threadStatus != 0) {
@@ -1150,7 +1150,7 @@
      * @see     #setName(String)
      */
     public final String getName() {
-        return String.valueOf(name);
+        return new String(name, true);
     }
 
     /**
--- a/src/share/classes/java/lang/ref/Reference.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/lang/ref/Reference.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -138,8 +138,23 @@
                         pending = r.discovered;
                         r.discovered = null;
                     } else {
+                        // The waiting on the lock may cause an OOME because it may try to allocate
+                        // exception objects, so also catch OOME here to avoid silent exit of the
+                        // reference handler thread.
+                        //
+                        // Explicitly define the order of the two exceptions we catch here
+                        // when waiting for the lock.
+                        //
+                        // We do not want to try to potentially load the InterruptedException class
+                        // (which would be done if this was its first use, and InterruptedException
+                        // were checked first) in this situation.
+                        //
+                        // This may lead to the VM not ever trying to load the InterruptedException
+                        // class again.
                         try {
-                            lock.wait();
+                            try {
+                                lock.wait();
+                            } catch (OutOfMemoryError x) { }
                         } catch (InterruptedException x) { }
                         continue;
                     }
--- a/src/share/classes/java/lang/reflect/GenericDeclaration.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/lang/reflect/GenericDeclaration.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -30,7 +30,7 @@
  *
  * @since 1.5
  */
-public interface GenericDeclaration {
+public interface GenericDeclaration extends AnnotatedElement {
     /**
      * Returns an array of {@code TypeVariable} objects that
      * represent the type variables declared by the generic
--- a/src/share/classes/java/nio/charset/Charset-X-Coder.java.template	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/nio/charset/Charset-X-Coder.java.template	Wed Jun 05 00:37:11 2013 -0700
@@ -34,6 +34,7 @@
 import java.nio.BufferUnderflowException;
 import java.lang.ref.WeakReference;
 import java.nio.charset.CoderMalfunctionError;                  // javadoc
+import java.util.Arrays;
 
 
 /**
@@ -244,7 +245,12 @@
      *          which is never <tt>null</tt> and is never empty
      */
     public final $replType$ replacement() {
+#if[decoder]
         return replacement;
+#end[decoder]
+#if[encoder]
+        return Arrays.copyOf(replacement, replacement.$replLength$);
+#end[encoder]
     }
 
     /**
@@ -280,12 +286,15 @@
             throw new IllegalArgumentException("Empty replacement");
         if (len > max$ItypesPerOtype$)
             throw new IllegalArgumentException("Replacement too long");
+#if[decoder]
+        this.replacement = newReplacement;
+#end[decoder]
 #if[encoder]
         if (!isLegalReplacement(newReplacement))
             throw new IllegalArgumentException("Illegal replacement");
+        this.replacement = Arrays.copyOf(newReplacement, newReplacement.$replLength$);
 #end[encoder]
-        this.replacement = newReplacement;
-        implReplaceWith(newReplacement);
+        implReplaceWith(this.replacement);
         return this;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/file/FileTreeIterator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -0,0 +1,124 @@
+/*
+ * 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.nio.file;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.nio.file.FileTreeWalker.Event;
+
+/**
+ * An {@code Iterator to iterate over the nodes of a file tree.
+ *
+ * <pre>{@code
+ *     try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
+ *         while (iterator.hasNext()) {
+ *             Event ev = iterator.next();
+ *             Path path = ev.file();
+ *             BasicFileAttributes attrs = ev.attributes();
+ *         }
+ *     }
+ * }</pre>
+ */
+
+class FileTreeIterator implements Iterator<Event>, Closeable {
+    private final FileTreeWalker walker;
+    private Event next;
+
+    /**
+     * Creates a new iterator to walk the file tree starting at the given file.
+     *
+     * @throws  IllegalArgumentException
+     *          if {@code maxDepth} is negative
+     * @throws  IOException
+     *          if an I/O errors occurs opening the starting file
+     * @throws  SecurityException
+     *          if the security manager denies access to the starting file
+     * @throws  NullPointerException
+     *          if {@code start} or {@code options} is {@ocde null} or
+     *          the options array contains a {@code null} element
+     */
+    FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
+        throws IOException
+    {
+        this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
+        this.next = walker.walk(start);
+        assert next.type() == FileTreeWalker.EventType.ENTRY ||
+               next.type() == FileTreeWalker.EventType.START_DIRECTORY;
+
+        // IOException if there a problem accessing the starting file
+        IOException ioe = next.ioeException();
+        if (ioe != null)
+            throw ioe;
+    }
+
+    private void fetchNextIfNeeded() {
+        if (next == null) {
+            FileTreeWalker.Event ev = walker.next();
+            while (ev != null) {
+                IOException ioe = ev.ioeException();
+                if (ioe != null)
+                    throw new UncheckedIOException(ioe);
+
+                // END_DIRECTORY events are ignored
+                if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
+                    next = ev;
+                    return;
+                }
+                ev = walker.next();
+            }
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (!walker.isOpen())
+            throw new IllegalStateException();
+        fetchNextIfNeeded();
+        return next != null;
+    }
+
+    @Override
+    public Event next() {
+        if (!walker.isOpen())
+            throw new IllegalStateException();
+        fetchNextIfNeeded();
+        if (next == null)
+            throw new NoSuchElementException();
+        Event result = next;
+        next = null;
+        return result;
+    }
+
+    @Override
+    public void close() {
+        walker.close();
+    }
+}
--- a/src/share/classes/java/nio/file/FileTreeWalker.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/nio/file/FileTreeWalker.java	Wed Jun 05 00:37:11 2013 -0700
@@ -29,8 +29,8 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayDeque;
+import java.util.Collection;
 import java.util.Iterator;
-import java.util.Set;
 import sun.nio.fs.BasicFileAttributesHolder;
 
 /**
@@ -164,8 +164,17 @@
 
     /**
      * Creates a {@code FileTreeWalker}.
+     *
+     * @throws  IllegalArgumentException
+     *          if {@code maxDepth} is negative
+     * @throws  ClassCastException
+     *          if (@code options} contains an element that is not a
+     *          {@code FileVisitOption}
+     * @throws  NullPointerException
+     *          if {@code options} is {@ocde null} or the options
+     *          array contains a {@code null} element
      */
-    FileTreeWalker(Set<FileVisitOption> options, int maxDepth) {
+    FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
         boolean fl = false;
         for (FileVisitOption option: options) {
             // will throw NPE if options contains null
@@ -175,6 +184,9 @@
                     throw new AssertionError("Should not get here");
             }
         }
+        if (maxDepth < 0)
+            throw new IllegalArgumentException("'maxDepth' is negative");
+
         this.followLinks = fl;
         this.linkOptions = (fl) ? new LinkOption[0] :
             new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
--- a/src/share/classes/java/nio/file/Files.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/nio/file/Files.java	Wed Jun 05 00:37:11 2013 -0700
@@ -25,10 +25,13 @@
 
 package java.nio.file;
 
+import java.nio.ByteBuffer;
 import java.nio.file.attribute.*;
 import java.nio.file.spi.FileSystemProvider;
 import java.nio.file.spi.FileTypeDetector;
+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;
@@ -38,7 +41,13 @@
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.util.*;
+import java.util.function.BiPredicate;
+import java.util.stream.CloseableStream;
+import java.util.stream.DelegatingStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.nio.charset.Charset;
@@ -2587,9 +2596,6 @@
                                     FileVisitor<? super Path> visitor)
         throws IOException
     {
-        if (maxDepth < 0)
-            throw new IllegalArgumentException("'maxDepth' is negative");
-
         /**
          * Create a FileTreeWalker to walk the file tree, invoking the visitor
          * for each event.
@@ -2941,40 +2947,6 @@
     }
 
     /**
-     * Read all the bytes from an input stream. The {@code initialSize}
-     * parameter indicates the initial size of the byte[] to allocate.
-     */
-    private static byte[] read(InputStream source, int initialSize)
-        throws IOException
-    {
-        int capacity = initialSize;
-        byte[] buf = new byte[capacity];
-        int nread = 0;
-        int rem = buf.length;
-        int n;
-        // read to EOF which may read more or less than initialSize (eg: file
-        // is truncated while we are reading)
-        while ((n = source.read(buf, nread, rem)) > 0) {
-            nread += n;
-            rem -= n;
-            assert rem >= 0;
-            if (rem == 0) {
-                // need larger buffer
-                int newCapacity = capacity << 1;
-                if (newCapacity < 0) {
-                    if (capacity == Integer.MAX_VALUE)
-                        throw new OutOfMemoryError("Required array size too large");
-                    newCapacity = Integer.MAX_VALUE;
-                }
-                rem = newCapacity - capacity;
-                buf = Arrays.copyOf(buf, newCapacity);
-                capacity = newCapacity;
-            }
-        }
-        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
-    }
-
-    /**
      * Read all the bytes from a file. The method ensures that the file is
      * closed when all bytes have been read or an I/O error, or other runtime
      * exception, is thrown.
@@ -2999,12 +2971,22 @@
      *          method is invoked to check read access to the file.
      */
     public static byte[] readAllBytes(Path path) throws IOException {
-        long size = size(path);
-        if (size > (long)Integer.MAX_VALUE)
-            throw new OutOfMemoryError("Required array size too large");
+        try (FileChannel fc = FileChannel.open(path)) {
+            long size = fc.size();
+            if (size > (long)Integer.MAX_VALUE)
+                throw new OutOfMemoryError("Required array size too large");
 
-        try (InputStream in = newInputStream(path)) {
-             return read(in, (int)size);
+            byte[] arr = new byte[(int)size];
+            ByteBuffer bb = ByteBuffer.wrap(arr);
+            while (bb.hasRemaining()) {
+                if (fc.read(bb) < 0) {
+                    // truncated
+                    break;
+                }
+            }
+
+            int nread = bb.position();
+            return (nread == size) ? arr : Arrays.copyOf(arr, nread);
         }
     }
 
@@ -3177,4 +3159,336 @@
         }
         return path;
     }
+
+    // -- 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
+     * which are the entries in the directory.  The listing is not recursive.
+     *
+     * <p> The elements of the stream are {@link Path} objects that are
+     * obtained as if by {@link Path#resolve(Path) resolving} the name of the
+     * directory entry against {@code dir}. Some file systems maintain special
+     * links to the directory itself and the directory's parent directory.
+     * Entries representing these links are not included.
+     *
+     * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
+     * not freeze the directory while iterating, so it may (or may not)
+     * reflect updates to the directory that occur after returning from this
+     * method.
+     *
+     * <p> When not using the try-with-resources construct, then the stream's
+     * {@link CloseableStream#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
+     * returned after the stream has been closed.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the directory
+     * after this method has returned, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the method that caused
+     * the access to take place.
+     *
+     * @param   dir  The path to the directory
+     *
+     * @return  The {@code CloseableStream} describing the content of the
+     *          directory
+     *
+     * @throws  NotDirectoryException
+     *          if the file could not otherwise be opened because it is not
+     *          a directory <i>(optional specific exception)</i>
+     * @throws  IOException
+     *          if an I/O error occurs when opening the directory
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the directory.
+     *
+     * @see     #newDirectoryStream(Path)
+     * @since   1.8
+     */
+    public static CloseableStream<Path> list(Path dir) throws IOException {
+        DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
+        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());
+                }
+            }
+            public Path next() {
+                try {
+                    return delegate.next();
+                } catch (DirectoryIteratorException e) {
+                    throw new UncheckedIOException(e.getCause());
+                }
+            }
+        };
+
+        return new DelegatingCloseableStream<>(ds,
+            StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
+                                                                     Spliterator.DISTINCT)));
+    }
+
+    /**
+     * Return a {@code CloseableStream} 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
+     * 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
+     * their <em>descendants</em> will follow the directory in the stream as
+     * they are encountered. When all entries have been visited, then the
+     * directory is closed. The file tree walk then continues at the next
+     * <em>sibling</em> of the directory.
+     *
+     * <p> The stream is <i>weakly consistent</i>. It does not freeze the
+     * file tree while iterating, so it may (or may not) reflect updates to
+     * the file tree that occur after returned from this method.
+     *
+     * <p> By default, symbolic links are not automatically followed by this
+     * method. If the {@code options} parameter contains the {@link
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
+     * followed. When following links, and the attributes of the target cannot
+     * be read, then this method attempts to get the {@code BasicFileAttributes}
+     * of the link.
+     *
+     * <p> If the {@code options} parameter contains the {@link
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
+     * track of directories visited so that cycles can be detected. A cycle
+     * arises when there is an entry in a directory that is an ancestor of the
+     * directory. Cycle detection is done by recording the {@link
+     * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
+     * or if file keys are not available, by invoking the {@link #isSameFile
+     * isSameFile} method to test if a directory is the same file as an
+     * ancestor. When a cycle is detected it is treated as an I/O error with
+     * an instance of {@link FileSystemLoopException}.
+     *
+     * <p> The {@code maxDepth} parameter is the maximum number of levels of
+     * directories to visit. A value of {@code 0} means that only the starting
+     * file is visited, unless denied by the security manager. A value of
+     * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
+     * levels should be visited.
+     *
+     * <p> When a security manager is installed and it denies access to a file
+     * (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
+     * 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}.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the directory
+     * after this method has returned, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the method that caused
+     * the access to take place.
+     *
+     * @param   start
+     *          the starting file
+     * @param   maxDepth
+     *          the maximum number of directory levels to visit
+     * @param   options
+     *          options to configure the traversal
+     *
+     * @return  the {@link CloseableStream} of {@link Path}
+     *
+     * @throws  IllegalArgumentException
+     *          if the {@code maxDepth} parameter is negative
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to the directory.
+     * @throws  IOException
+     *          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
+    {
+        FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+        return new DelegatingCloseableStream<>(iterator,
+            StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+                   .map(entry -> entry.file()));
+    }
+
+    /**
+     * Return a {@code CloseableStream} 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> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <blockquote><pre>
+     * walk(start, Integer.MAX_VALUE, options)
+     * </pre></blockquote>
+     * In other words, it visits all levels of the file tree.
+     *
+     * @param   start
+     *          the starting file
+     * @param   options
+     *          options to configure the traversal
+     *
+     * @return  the {@link CloseableStream} of {@link Path}
+     *
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to the directory.
+     * @throws  IOException
+     *          if an I/O error is thrown when accessing the starting file.
+     *
+     * @see     #walk(Path, int, FileVisitOption...)
+     * @since   1.8
+     */
+    public static CloseableStream<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
+     * Path} by searching for files in a file tree rooted at a given starting
+     * file.
+     *
+     * <p> This method walks the file tree in exactly the manner specified by
+     * the {@link #walk walk} method. For each file encountered, the given
+     * {@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
+     * 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
+     * avoiding redundant retrieval of the {@code BasicFileAttributes}.
+     *
+     * <p> If an {@link IOException} is thrown when accessing the directory
+     * after returned from this method, it is wrapped in an {@link
+     * UncheckedIOException} which will be thrown from the method that caused
+     * the access to take place.
+     *
+     * @param   start
+     *          the starting file
+     * @param   maxDepth
+     *          the maximum number of directory levels to search
+     * @param   matcher
+     *          the function used to decide whether a file should be included
+     *          in the returned stream
+     * @param   options
+     *          options to configure the traversal
+     *
+     * @return  the {@link CloseableStream} of {@link Path}
+     *
+     * @throws  IllegalArgumentException
+     *          if the {@code maxDepth} parameter is negative
+     * @throws  SecurityException
+     *          If the security manager denies access to the starting file.
+     *          In the case of the default provider, the {@link
+     *          SecurityManager#checkRead(String) checkRead} method is invoked
+     *          to check read access to the directory.
+     * @throws  IOException
+     *          if an I/O error is thrown when accessing the starting file.
+     *
+     * @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
+    {
+        FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+        return new DelegatingCloseableStream<>(iterator,
+            StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+                   .filter(entry -> matcher.test(entry.file(), entry.attributes()))
+                   .map(entry -> entry.file()));
+    }
+
+    /**
+     * Read all lines from a file as a {@code CloseableStream}.  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.
+     *
+     * <p> Bytes from the file are decoded into characters using the specified
+     * charset and the same line terminators as specified by {@code
+     * readAllLines} are supported.
+     *
+     * <p> After this method returns, then any subsequent I/O exception that
+     * occurs while reading from the file or when a malformed or unmappable byte
+     * sequence is read, is wrapped in an {@link UncheckedIOException} that will
+     * be thrown form the
+     * {@link java.util.stream.Stream} method that caused the read to take
+     * place. In case an {@code IOException} is thrown when closing the file,
+     * 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
+     * operation is completed so as to free any resources held for the open
+     * file.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   cs
+     *          the charset to use for decoding
+     *
+     * @return  the lines from the file as a {@code CloseableStream}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs opening the file
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file.
+     *
+     * @see     #readAllLines(Path, Charset)
+     * @see     #newBufferedReader(Path, Charset)
+     * @see     java.io.BufferedReader#lines()
+     * @since   1.8
+     */
+    public static CloseableStream<String> lines(Path path, Charset cs)
+        throws IOException
+    {
+        BufferedReader br = Files.newBufferedReader(path, cs);
+        return new DelegatingCloseableStream<>(br, br.lines());
+    }
 }
--- a/src/share/classes/java/text/DateFormatSymbols.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/text/DateFormatSymbols.java	Wed Jun 05 00:37:11 2013 -0700
@@ -59,7 +59,7 @@
  * <code>DateFormatSymbols</code> is a public class for encapsulating
  * localizable date-time formatting data, such as the names of the
  * months, the names of the days of the week, and the time zone data.
- * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
+ * <code>SimpleDateFormat</code> uses
  * <code>DateFormatSymbols</code> to encapsulate this information.
  *
  * <p>
--- a/src/share/classes/java/util/Arrays.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/Arrays.java	Wed Jun 05 00:37:11 2013 -0700
@@ -40,7 +40,6 @@
 import java.util.stream.LongStream;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
-import static java.util.ArraysParallelSortHelpers.*;
 
 /**
  * This class contains various methods for manipulating arrays (such as
@@ -70,17 +69,62 @@
 public class Arrays {
 
     /**
-     * The minimum array length below which the sorting algorithm will not
-     * further partition the sorting task.
+     * The minimum array length below which a parallel sorting
+     * algorithm will not further partition the sorting task. Using
+     * smaller sizes typically results in memory contention across
+     * tasks that makes parallel speedups unlikely.
      */
-    // reasonable default so that we don't overcreate tasks
-    private static final int MIN_ARRAY_SORT_GRAN = 256;
+    private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
 
     // Suppresses default constructor, ensuring non-instantiability.
     private Arrays() {}
 
+    /**
+     * A comparator that implements the natural ordering of a group of
+     * mutually comparable elements. May be used when a supplied
+     * comparator is null. To simplify code-sharing within underlying
+     * implementations, the compare method only declares type Object
+     * for its second argument.
+     *
+     * Arrays class implementor's note: It is an empirical matter
+     * whether ComparableTimSort offers any performance benefit over
+     * TimSort used with this comparator.  If not, you are better off
+     * deleting or bypassing ComparableTimSort.  There is currently no
+     * empirical case for separating them for parallel sorting, so all
+     * public Object parallelSort methods use the same comparator
+     * based implementation.
+     */
+    static final class NaturalOrder implements Comparator<Object> {
+        @SuppressWarnings("unchecked")
+        public int compare(Object first, Object second) {
+            return ((Comparable<Object>)first).compareTo(second);
+        }
+        static final NaturalOrder INSTANCE = new NaturalOrder();
+    }
+
+    /**
+     * Checks that {@code fromIndex} and {@code toIndex} are in
+     * the range and throws an exception if they aren't.
+     */
+    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException(
+                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+        if (fromIndex < 0) {
+            throw new ArrayIndexOutOfBoundsException(fromIndex);
+        }
+        if (toIndex > arrayLength) {
+            throw new ArrayIndexOutOfBoundsException(toIndex);
+        }
+    }
+
     /*
-     * Sorting of primitive type arrays.
+     * Sorting methods. Note that all public "sort" methods take the
+     * same form: Performing argument checks if necessary, and then
+     * expanding arguments into those required for the internal
+     * implementation methods residing in other package-private
+     * classes (except for legacyMergeSort, included in this class).
      */
 
     /**
@@ -95,7 +139,7 @@
      * @param a the array to be sorted
      */
     public static void sort(int[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -120,7 +164,7 @@
      */
     public static void sort(int[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -135,7 +179,7 @@
      * @param a the array to be sorted
      */
     public static void sort(long[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -160,7 +204,7 @@
      */
     public static void sort(long[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -175,7 +219,7 @@
      * @param a the array to be sorted
      */
     public static void sort(short[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -200,7 +244,7 @@
      */
     public static void sort(short[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -215,7 +259,7 @@
      * @param a the array to be sorted
      */
     public static void sort(char[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -240,7 +284,7 @@
      */
     public static void sort(char[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -255,7 +299,7 @@
      * @param a the array to be sorted
      */
     public static void sort(byte[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1);
     }
 
     /**
@@ -303,7 +347,7 @@
      * @param a the array to be sorted
      */
     public static void sort(float[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -336,7 +380,7 @@
      */
     public static void sort(float[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
     }
 
     /**
@@ -359,7 +403,7 @@
      * @param a the array to be sorted
      */
     public static void sort(double[] a) {
-        DualPivotQuicksort.sort(a);
+        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
     }
 
     /**
@@ -392,7 +436,742 @@
      */
     public static void sort(double[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(byte[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(byte[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(byte[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1);
+        else
+            new ArraysParallelSortHelpers.FJByte.Sorter
+                (null, a, new byte[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(byte[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(byte[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(byte[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        else
+            new ArraysParallelSortHelpers.FJByte.Sorter
+                (null, a, new byte[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(char[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(char[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(char[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJChar.Sorter
+                (null, a, new char[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+      @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(char[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(char[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(char[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJChar.Sorter
+                (null, a, new char[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(short[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(short[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(short[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJShort.Sorter
+                (null, a, new short[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(short[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(short[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(short[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJShort.Sorter
+                (null, a, new short[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(int[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(int[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(int[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJInt.Sorter
+                (null, a, new int[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(int[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(int[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(int[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJInt.Sorter
+                (null, a, new int[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(long[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(long[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(long[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJLong.Sorter
+                (null, a, new long[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(long[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(long[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(long[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJLong.Sorter
+                (null, a, new long[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(float[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(float[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(float[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJFloat.Sorter
+                (null, a, new float[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(float[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(float[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(float[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJFloat.Sorter
+                (null, a, new float[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(double[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(double[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(double[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJDouble.Sorter
+                (null, a, new double[n], 0, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending numerical order.
+     * The range to be sorted extends from the index {@code fromIndex},
+     * inclusive, to the index {@code toIndex}, exclusive. If
+     * {@code fromIndex == toIndex}, the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(double[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(double[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     *
+     * @since 1.8
+     */
+    public static void parallelSort(double[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJDouble.Sorter
+                (null, a, new double[n], fromIndex, n, 0,
+                 ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g).invoke();
+    }
+
+    /**
+     * Sorts the specified array of objects into ascending order, according
+     * to the {@linkplain Comparable natural ordering} of its elements.
+     * All elements in the array must implement the {@link Comparable}
+     * interface.  Furthermore, all elements in the array must be
+     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
+     * not throw a {@code ClassCastException} for any elements {@code e1}
+     * and {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     *
+     * @throws ClassCastException if the array contains elements that are not
+     *         <i>mutually comparable</i> (for example, strings and integers)
+     * @throws IllegalArgumentException (optional) if the natural
+     *         ordering of the array elements is found to violate the
+     *         {@link Comparable} contract
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, 0, n, NaturalOrder.INSTANCE, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the specified array of objects into
+     * ascending order, according to the
+     * {@linkplain Comparable natural ordering} of its
+     * elements.  The range to be sorted extends from index
+     * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
+     * (If {@code fromIndex==toIndex}, the range to be sorted is empty.)  All
+     * elements in this range must implement the {@link Comparable}
+     * interface.  Furthermore, all elements in this range must be <i>mutually
+     * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
+     * {@code ClassCastException} for any elements {@code e1} and
+     * {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element (inclusive) to be
+     *        sorted
+     * @param toIndex the index of the last element (exclusive) to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+     *         (optional) if the natural ordering of the array elements is
+     *         found to violate the {@link Comparable} contract
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> (for example, strings and
+     *         integers).
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends Comparable<? super T>>
+    void parallelSort(T[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, fromIndex, toIndex, NaturalOrder.INSTANCE, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
+    }
+
+    /**
+     * Sorts the specified array of objects according to the order induced by
+     * the specified comparator.  All elements in the array must be
+     * <i>mutually comparable</i> by the specified comparator (that is,
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a
+     * working space no greater than the size of the original array. The
+     * {@link ForkJoinPool#commonPool() ForkJoin common pool} is used to
+     * execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param cmp the comparator to determine the order of the array.  A
+     *        {@code null} value indicates that the elements'
+     *        {@linkplain Comparable natural ordering} should be used.
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> using the specified comparator
+     * @throws IllegalArgumentException (optional) if the comparator is
+     *         found to violate the {@link java.util.Comparator} contract
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) {
+        if (cmp == null)
+            cmp = NaturalOrder.INSTANCE;
+        int n = a.length, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, 0, n, cmp, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
+    }
+
+    /**
+     * Sorts the specified range of the specified array of objects according
+     * to the order induced by the specified comparator.  The range to be
+     * sorted extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
+     * range to be sorted is empty.)  All elements in the range must be
+     * <i>mutually comparable</i> by the specified comparator (that is,
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the range).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * @implNote The sorting algorithm is a parallel sort-merge that breaks the
+     * array into sub-arrays that are themselves sorted and then merged. When
+     * the sub-array length reaches a minimum granularity, the sub-array is
+     * sorted using the appropriate {@link Arrays#sort(Object[]) Arrays.sort}
+     * method. If the length of the specified array is less than the minimum
+     * granularity, then it is sorted using the appropriate {@link
+     * Arrays#sort(Object[]) Arrays.sort} method. The algorithm requires a working
+     * space no greater than the size of the specified range of the original
+     * array. The {@link ForkJoinPool#commonPool() ForkJoin common pool} is
+     * used to execute any parallel tasks.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element (inclusive) to be
+     *        sorted
+     * @param toIndex the index of the last element (exclusive) to be sorted
+     * @param cmp the comparator to determine the order of the array.  A
+     *        {@code null} value indicates that the elements'
+     *        {@linkplain Comparable natural ordering} should be used.
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+     *         (optional) if the natural ordering of the array elements is
+     *         found to violate the {@link Comparable} contract
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> (for example, strings and
+     *         integers).
+     *
+     * @since 1.8
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
+                                        Comparator<? super T> cmp) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        if (cmp == null)
+            cmp = NaturalOrder.INSTANCE;
+        int n = toIndex - fromIndex, p, g;
+        if (n <= MIN_ARRAY_SORT_GRAN ||
+            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
+            TimSort.sort(a, fromIndex, toIndex, cmp, null, 0, 0);
+        else
+            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+                (null, a,
+                 (T[])Array.newInstance(a.getClass().getComponentType(), n),
+                 fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
+                 MIN_ARRAY_SORT_GRAN : g, cmp).invoke();
     }
 
     /*
@@ -412,39 +1191,6 @@
                     "java.util.Arrays.useLegacyMergeSort")).booleanValue();
     }
 
-    /*
-     * If this platform has an optimizing VM, check whether ComparableTimSort
-     * offers any performance benefit over TimSort in conjunction with a
-     * comparator that returns:
-     *    {@code ((Comparable)first).compareTo(Second)}.
-     * If not, you are better off deleting ComparableTimSort to
-     * eliminate the code duplication.  In other words, the commented
-     * out code below is the preferable implementation for sorting
-     * arrays of Comparables if it offers sufficient performance.
-     */
-
-//    /**
-//     * A comparator that implements the natural ordering of a group of
-//     * mutually comparable elements.  Using this comparator saves us
-//     * from duplicating most of the code in this file (one version for
-//     * Comparables, one for explicit Comparators).
-//     */
-//    private static final Comparator<Object> NATURAL_ORDER =
-//            new Comparator<Object>() {
-//        @SuppressWarnings("unchecked")
-//        public int compare(Object first, Object second) {
-//            return ((Comparable<Object>)first).compareTo(second);
-//        }
-//    };
-//
-//    public static void sort(Object[] a) {
-//        sort(a, 0, a.length, NATURAL_ORDER);
-//    }
-//
-//    public static void sort(Object[] a, int fromIndex, int toIndex) {
-//        sort(a, fromIndex, toIndex, NATURAL_ORDER);
-//    }
-
     /**
      * Sorts the specified array of objects into ascending order, according
      * to the {@linkplain Comparable natural ordering} of its elements.
@@ -491,7 +1237,7 @@
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a);
         else
-            ComparableTimSort.sort(a);
+            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
     }
 
     /** To be removed in a future release. */
@@ -553,16 +1299,16 @@
      *         integers).
      */
     public static void sort(Object[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a, fromIndex, toIndex);
         else
-            ComparableTimSort.sort(a, fromIndex, toIndex);
+            ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
     }
 
     /** To be removed in a future release. */
     private static void legacyMergeSort(Object[] a,
                                         int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
         Object[] aux = copyOfRange(a, fromIndex, toIndex);
         mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
     }
@@ -676,10 +1422,12 @@
      *         found to violate the {@link Comparator} contract
      */
     public static <T> void sort(T[] a, Comparator<? super T> c) {
+        if (c == null)
+            c = NaturalOrder.INSTANCE;
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a, c);
         else
-            TimSort.sort(a, c);
+            TimSort.sort(a, 0, a.length, c, null, 0, 0);
     }
 
     /** To be removed in a future release. */
@@ -744,16 +1492,18 @@
      */
     public static <T> void sort(T[] a, int fromIndex, int toIndex,
                                 Comparator<? super T> c) {
+        if (c == null)
+            c = NaturalOrder.INSTANCE;
+        rangeCheck(a.length, fromIndex, toIndex);
         if (LegacyMergeSort.userRequested)
             legacyMergeSort(a, fromIndex, toIndex, c);
         else
-            TimSort.sort(a, fromIndex, toIndex, c);
+            TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
     }
 
     /** To be removed in a future release. */
     private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
                                             Comparator<? super T> c) {
-        rangeCheck(a.length, fromIndex, toIndex);
         T[] aux = copyOfRange(a, fromIndex, toIndex);
         if (c==null)
             mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
@@ -809,630 +1559,6 @@
         }
     }
 
-    /*
-     * Parallel sorting of primitive type arrays.
-     */
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(byte[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(byte[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(byte[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(byte[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJByte.Sorter task = new FJByte.Sorter(a, new byte[a.length], fromIndex,
-                                               nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(char[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(char[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(char[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(char[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJChar.Sorter task = new FJChar.Sorter(a, new char[a.length], fromIndex,
-                                               nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(short[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(short[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(short[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(short[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJShort.Sorter task = new FJShort.Sorter(a, new short[a.length], fromIndex,
-                                                 nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(int[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(int[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(int[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(int[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJInt.Sorter task = new FJInt.Sorter(a, new int[a.length], fromIndex,
-                                             nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(long[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(long[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(long[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(long[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJLong.Sorter task = new FJLong.Sorter(a, new long[a.length], fromIndex,
-                                               nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on all float
-     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
-     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
-     * other value and all {@code Float.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(float[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(float[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>The {@code <} relation does not provide a total order on all float
-     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
-     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
-     * other value and all {@code Float.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(float[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(float[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJFloat.Sorter task = new FJFloat.Sorter(a, new float[a.length], fromIndex,
-                                                 nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on all double
-     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
-     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
-     * other value and all {@code Double.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(double[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(double[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order. The range
-     * to be sorted extends from the index {@code fromIndex}, inclusive, to
-     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>The {@code <} relation does not provide a total order on all double
-     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
-     * value compares neither less than, greater than, nor equal to any value,
-     * even itself. This method uses the total order imposed by the method
-     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
-     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
-     * other value and all {@code Double.NaN} values are considered equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(double[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusive, to be sorted
-     * @param toIndex the index of the last element, exclusive, to be sorted
-     *
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     *
-     * @since 1.8
-     */
-    public static void parallelSort(double[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        int gran = getSplitThreshold(nelements);
-        FJDouble.Sorter task = new FJDouble.Sorter(a, new double[a.length],
-                                                   fromIndex, nelements, gran);
-        task.invoke();
-    }
-
-    /*
-     * Parallel sorting of complex type arrays.
-     */
-
-    /**
-     * Sorts the specified array of objects into ascending order, according
-     * to the {@linkplain Comparable natural ordering} of its elements.
-     * All elements in the array must implement the {@link Comparable}
-     * interface.  Furthermore, all elements in the array must be
-     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
-     * not throw a {@code ClassCastException} for any elements {@code e1}
-     * and {@code e2} in the array).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     *
-     * @throws ClassCastException if the array contains elements that are not
-     *         <i>mutually comparable</i> (for example, strings and integers)
-     * @throws IllegalArgumentException (optional) if the natural
-     *         ordering of the array elements is found to violate the
-     *         {@link Comparable} contract
-     *
-     * @since 1.8
-     */
-    public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
-        parallelSort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the specified array of objects into
-     * ascending order, according to the
-     * {@linkplain Comparable natural ordering} of its
-     * elements.  The range to be sorted extends from index
-     * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
-     * (If {@code fromIndex==toIndex}, the range to be sorted is empty.)  All
-     * elements in this range must implement the {@link Comparable}
-     * interface.  Furthermore, all elements in this range must be <i>mutually
-     * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
-     * {@code ClassCastException} for any elements {@code e1} and
-     * {@code e2} in the array).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element (inclusive) to be
-     *        sorted
-     * @param toIndex the index of the last element (exclusive) to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
-     *         (optional) if the natural ordering of the array elements is
-     *         found to violate the {@link Comparable} contract
-     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
-     *         {@code toIndex > a.length}
-     * @throws ClassCastException if the array contains elements that are
-     *         not <i>mutually comparable</i> (for example, strings and
-     *         integers).
-     *
-     * @since 1.8
-     */
-    public static <T extends Comparable<? super T>>
-            void parallelSort(T[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        Class<?> tc = a.getClass().getComponentType();
-        @SuppressWarnings("unchecked")
-        T[] workspace = (T[])Array.newInstance(tc, a.length);
-        int gran = getSplitThreshold(nelements);
-        FJComparable.Sorter<T> task = new FJComparable.Sorter<>(a, workspace,
-                                                                fromIndex,
-                                                                nelements, gran);
-        task.invoke();
-    }
-
-    /**
-     * Sorts the specified array of objects according to the order induced by
-     * the specified comparator.  All elements in the array must be
-     * <i>mutually comparable</i> by the specified comparator (that is,
-     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
-     * for any elements {@code e1} and {@code e2} in the array).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param c the comparator to determine the order of the array.  A
-     *        {@code null} value indicates that the elements'
-     *        {@linkplain Comparable natural ordering} should be used.
-     * @throws ClassCastException if the array contains elements that are
-     *         not <i>mutually comparable</i> using the specified comparator
-     * @throws IllegalArgumentException (optional) if the comparator is
-     *         found to violate the {@link java.util.Comparator} contract
-     *
-     * @since 1.8
-     */
-    public static <T> void parallelSort(T[] a, Comparator<? super T> c) {
-        parallelSort(a, 0, a.length, c);
-    }
-
-    /**
-     * Sorts the specified range of the specified array of objects according
-     * to the order induced by the specified comparator.  The range to be
-     * sorted extends from index {@code fromIndex}, inclusive, to index
-     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
-     * range to be sorted is empty.)  All elements in the range must be
-     * <i>mutually comparable</i> by the specified comparator (that is,
-     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
-     * for any elements {@code e1} and {@code e2} in the range).
-     *
-     * <p>This sort is not guaranteed to be <i>stable</i>:  equal elements
-     * may be reordered as a result of the sort.
-     *
-     * <p>Implementation note: The sorting algorithm is a parallel sort-merge
-     * that breaks the array into sub-arrays that are themselves sorted and then
-     * merged. When the sub-array length reaches a minimum granularity, the
-     * sub-array is sorted using the appropriate {@link Arrays#sort(Object[])
-     * Arrays.sort} method. The algorithm requires a working space equal to the
-     * size of the original array. The {@link
-     * java.util.concurrent.ForkJoinPool#commonPool() ForkJoin common pool} is
-     * used to execute any parallel tasks.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element (inclusive) to be
-     *        sorted
-     * @param toIndex the index of the last element (exclusive) to be sorted
-     * @param c the comparator to determine the order of the array.  A
-     *        {@code null} value indicates that the elements'
-     *        {@linkplain Comparable natural ordering} should be used.
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
-     *         (optional) if the natural ordering of the array elements is
-     *         found to violate the {@link Comparable} contract
-     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
-     *         {@code toIndex > a.length}
-     * @throws ClassCastException if the array contains elements that are
-     *         not <i>mutually comparable</i> (for example, strings and
-     *         integers).
-     *
-     * @since 1.8
-     */
-    public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
-                                        Comparator<? super T> c) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        int nelements = toIndex - fromIndex;
-        Class<?> tc = a.getClass().getComponentType();
-        @SuppressWarnings("unchecked")
-        T[] workspace = (T[])Array.newInstance(tc, a.length);
-        int gran = getSplitThreshold(nelements);
-        FJComparator.Sorter<T> task = new FJComparator.Sorter<>(a, workspace,
-                                                                fromIndex,
-                                                                nelements, gran, c);
-        task.invoke();
-    }
-
-    /**
-     * Returns the size threshold for splitting into subtasks.
-     * By default, uses about 8 times as many tasks as threads
-     *
-     * @param n number of elements in the array to be processed
-     */
-    private static int getSplitThreshold(int n) {
-        int p = java.util.concurrent.ForkJoinPool.getCommonPoolParallelism();
-        int t = (p > 1) ? (1 + n / (p << 3)) : n;
-        return t < MIN_ARRAY_SORT_GRAN ? MIN_ARRAY_SORT_GRAN : t;
-    }
-
-    /**
-     * Checks that {@code fromIndex} and {@code toIndex} are in
-     * the range and throws an appropriate exception, if they aren't.
-     */
-    private static void rangeCheck(int length, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex) {
-            throw new IllegalArgumentException(
-                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
-        }
-        if (fromIndex < 0) {
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        }
-        if (toIndex > length) {
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-        }
-    }
-
     // Searching
 
     /**
--- a/src/share/classes/java/util/ArraysParallelSortHelpers.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/ArraysParallelSortHelpers.java	Wed Jun 05 00:37:11 2013 -0700
@@ -25,6 +25,7 @@
 package java.util;
 
 import java.util.concurrent.RecursiveAction;
+import java.util.concurrent.CountedCompleter;
 
 /**
  * Helper utilities for the parallel sort methods in Arrays.parallelSort.
@@ -44,1180 +45,966 @@
  *             c. merge them together
  *         3. merge together the two halves.
  *
- * One reason for splitting in quarters is that this guarantees
- * that the final sort is in the main array, not the workspace
- * array.  (workspace and main swap roles on each subsort step.)
- * Leaf-level sorts use a Sequential quicksort, that in turn uses
- * insertion sort if under threshold.  Otherwise it uses median of
- * three to pick pivot, and loops rather than recurses along left
- * path.
+ * One reason for splitting in quarters is that this guarantees that
+ * the final sort is in the main array, not the workspace array.
+ * (workspace and main swap roles on each subsort step.)  Leaf-level
+ * sorts use the associated sequential sort.
  *
+ * Merger classes perform merging for Sorter.  They are structured
+ * such that if the underlying sort is stable (as is true for
+ * TimSort), then so is the full sort.  If big enough, they split the
+ * largest of the two partitions in half, find the greatest point in
+ * smaller partition less than the beginning of the second half of
+ * larger via binary search; and then merge in parallel the two
+ * partitions.  In part to ensure tasks are triggered in
+ * stability-preserving order, the current CountedCompleter design
+ * requires some little tasks to serve as place holders for triggering
+ * completion tasks.  These classes (EmptyCompleter and Relay) don't
+ * need to keep track of the arrays, and are never themselves forked,
+ * so don't hold any task state.
  *
- * Merger classes perform merging for Sorter. If big enough, splits Left
- * partition in half; finds the greatest point in Right partition
- * less than the beginning of the second half of Left via binary
- * search; and then, in parallel, merges left half of Left with
- * elements of Right up to split point, and merges right half of
- * Left with elements of R past split point. At leaf, it just
- * sequentially merges. This is all messy to code; sadly we need
- * distinct versions for each type.
+ * The primitive class versions (FJByte... FJDouble) are
+ * identical to each other except for type declarations.
  *
+ * The base sequential sorts rely on non-public versions of TimSort,
+ * ComparableTimSort, and DualPivotQuicksort sort methods that accept
+ * temp workspace array slices that we will have already allocated, so
+ * avoids redundant allocation. (Except for DualPivotQuicksort byte[]
+ * sort, that does not ever use a workspace array.)
  */
 /*package*/ class ArraysParallelSortHelpers {
 
-    // RFE: we should only need a working array as large as the subarray
-    //      to be sorted, but the logic assumes that indices in the two
-    //      arrays always line-up
+    /*
+     * Style note: The task classes have a lot of parameters, that are
+     * stored as task fields and copied to local variables and used in
+     * compute() methods, We pack these into as few lines as possible,
+     * and hoist consistency checks among them before main loops, to
+     * reduce distraction.
+     */
+
+    /**
+     * A placeholder task for Sorters, used for the lowest
+     * quartile task, that does not need to maintain array state.
+     */
+    static final class EmptyCompleter extends CountedCompleter<Void> {
+        static final long serialVersionUID = 2446542900576103244L;
+        EmptyCompleter(CountedCompleter<?> p) { super(p); }
+        public final void compute() { }
+    }
+
+    /**
+     * A trigger for secondary merge of two merges
+     */
+    static final class Relay extends CountedCompleter<Void> {
+        static final long serialVersionUID = 2446542900576103244L;
+        final CountedCompleter<?> task;
+        Relay(CountedCompleter<?> task) {
+            super(null, 1);
+            this.task = task;
+        }
+        public final void compute() { }
+        public final void onCompletion(CountedCompleter<?> t) {
+            task.compute();
+        }
+    }
+
+    /** Object + Comparator support class */
+    static final class FJObject {
+        static final class Sorter<T> extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final T[] a, w;
+            final int base, size, wbase, gran;
+            Comparator<? super T> comparator;
+            Sorter(CountedCompleter<?> par, T[] a, T[] w, int base, int size,
+                   int wbase, int gran,
+                   Comparator<? super T> comparator) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
+                this.comparator = comparator;
+            }
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                Comparator<? super T> c = this.comparator;
+                T[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger<T>(s, w, a, wb, h,
+                                                       wb+h, n-h, b, g, c));
+                    Relay rc = new Relay(new Merger<T>(fc, a, w, b+h, q,
+                                                       b+u, n-u, wb+h, g, c));
+                    new Sorter<T>(rc, a, w, b+u, n-u, wb+u, g, c).fork();
+                    new Sorter<T>(rc, a, w, b+h, q, wb+h, g, c).fork();;
+                    Relay bc = new Relay(new Merger<T>(fc, a, w, b, q,
+                                                       b+q, h-q, wb, g, c));
+                    new Sorter<T>(bc, a, w, b+q, h-q, wb+q, g, c).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
+                }
+                TimSort.sort(a, b, b + n, c, w, wb, n);
+                s.tryComplete();
+            }
+        }
+
+        static final class Merger<T> extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final T[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Comparator<? super T> comparator;
+            Merger(CountedCompleter<?> par, T[] a, T[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran,
+                   Comparator<? super T> comparator) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
+                this.comparator = comparator;
+            }
+
+            public final void compute() {
+                Comparator<? super T> c = this.comparator;
+                T[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0 ||
+                    c == null)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        T split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (c.compare(split, a[rm + rb]) <= 0)
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
+                    }
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        T split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (c.compare(split, a[lm + lb]) <= 0)
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger<T> m = new Merger<T>(this, a, w, lb + lh, ln - lh,
+                                                rb + rh, rn - rh,
+                                                k + lh + rh, g, c);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
+                }
+
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    T t, al, ar;
+                    if (c.compare((al = a[lb]), (ar = a[rb])) <= 0) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
+                    w[k++] = t;
+                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+
+                tryComplete();
+            }
+
+        }
+    } // FJObject
 
     /** byte support class */
     static final class FJByte {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 749471161188027634L;
-            final byte[] a;     // array to be sorted.
-            final byte[] w;     // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(byte[] a, byte[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final byte[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, byte[] a, byte[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final byte[] a = this.a;
-                final byte[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,  g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l+h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h,
-                               l+h, n-h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   //skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                byte[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = -9090258248781844470L;
-            final byte[] a;
-            final byte[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(byte[] a, byte[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final byte[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, byte[] a, byte[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final byte[] a = this.a;
-                final byte[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    byte split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                byte[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        byte split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        byte split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    byte al = a[l];
-                    byte ar = a[r];
-                    byte t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    byte t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJByte
 
     /** char support class */
     static final class FJChar {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 8723376019074596641L;
-            final char[] a;     // array to be sorted.
-            final char[] w;     // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(char[] a, char[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final char[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, char[] a, char[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final char[] a = this.a;
-                final char[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                char[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = -1383975444621698926L;
-            final char[] a;
-            final char[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(char[] a, char[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final char[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, char[] a, char[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final char[] a = this.a;
-                final char[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    char split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                char[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        char split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        char split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    char al = a[l];
-                    char ar = a[r];
-                    char t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    char t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJChar
 
     /** short support class */
     static final class FJShort {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = -7886754793730583084L;
-            final short[] a;    // array to be sorted.
-            final short[] w;    // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(short[] a, short[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final short[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, short[] a, short[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final short[] a = this.a;
-                final short[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                short[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 3895749408536700048L;
-            final short[] a;
-            final short[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(short[] a, short[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final short[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, short[] a, short[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final short[] a = this.a;
-                final short[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    short split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                short[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        short split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        short split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    short al = a[l];
-                    short ar = a[r];
-                    short t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    short t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJShort
 
     /** int support class */
     static final class FJInt {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 4263311808957292729L;
-            final int[] a;     // array to be sorted.
-            final int[] w;     // workspace for merge
-            final int origin;  // origin of the part of array we deal with
-            final int n;       // Number of elements in (sub)arrays.
-            final int gran;    // split control
-
-            Sorter(int[] a, int[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final int[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, int[] a, int[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final int[] a = this.a;
-                final int[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                int[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = -8727507284219982792L;
-            final int[] a;
-            final int[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(int[] a, int[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final int[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, int[] a, int[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final int[] a = this.a;
-                final int[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    int split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                int[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        int split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        int split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    int al = a[l];
-                    int ar = a[r];
-                    int t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    int t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJInt
 
     /** long support class */
     static final class FJLong {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 6553695007444392455L;
-            final long[] a;     // array to be sorted.
-            final long[] w;     // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(long[] a, long[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final long[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, long[] a, long[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final long[] a = this.a;
-                final long[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                long[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 8843567516333283861L;
-            final long[] a;
-            final long[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(long[] a, long[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final long[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, long[] a, long[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final long[] a = this.a;
-                final long[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    long split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split <= a[ro + mid])
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                long[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        long split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                      nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        long split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    long al = a[l];
-                    long ar = a[r];
-                    long t;
-                    if (al <= ar) {++l; t=al;} else {++r; t = ar;}
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    long t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
+                    }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJLong
 
     /** float support class */
     static final class FJFloat {
-        static final class Sorter extends RecursiveAction {
-            static final long serialVersionUID = 1602600178202763377L;
-            final float[] a;    // array to be sorted.
-            final float[] w;    // workspace for merge
-            final int origin;   // origin of the part of array we deal with
-            final int n;        // Number of elements in (sub)arrays.
-            final int gran;     // split control
-
-            Sorter(float[] a, float[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+        static final class Sorter extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final float[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, float[] a, float[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final float[] a = this.a;
-                final float[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                float[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 1518176433845397426L;
-            final float[] a;
-            final float[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(float[] a, float[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final float[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, float[] a, float[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final float[] a = this.a;
-                final float[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    float split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (Float.compare(split, a[ro+mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                float[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        float split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        float split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    float al = a[l];
-                    float ar = a[r];
-                    float t;
-                    if (Float.compare(al, ar) <= 0) {
-                        ++l;
-                        t = al;
-                    } else {
-                        ++r;
-                        t = ar;
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    float t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
                     }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJFloat
 
     /** double support class */
     static final class FJDouble {
-        static final class Sorter extends RecursiveAction {
+        static final class Sorter extends CountedCompleter<Void> {
             static final long serialVersionUID = 2446542900576103244L;
-            final double[] a;    // array to be sorted.
-            final double[] w;    // workspace for merge
-            final int origin;    // origin of the part of array we deal with
-            final int n;         // Number of elements in (sub)arrays.
-            final int gran;      // split control
-
-            Sorter(double[] a, double[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
+            final double[] a, w;
+            final int base, size, wbase, gran;
+            Sorter(CountedCompleter<?> par, double[] a, double[] w, int base,
+                   int size, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w; this.base = base; this.size = size;
+                this.wbase = wbase; this.gran = gran;
             }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final double[] a = this.a;
-                final double[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter(a, w, l, q,   g),
-                                                     new Sorter(a, w, l+q, h-q, g),
-                                                     new Merger(a, w, l,   q,
-                                                                l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter(a, w, l + h, q,   g),
-                                                     new Sorter(a, w, l+u, n-u, g),
-                                                     new Merger(a, w, l+h, q,
-                                                                l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    DualPivotQuicksort.sort(a, l, l+n-1);   // skip rangeCheck
+            public final void compute() {
+                CountedCompleter<?> s = this;
+                double[] a = this.a, w = this.w; // localize all params
+                int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
+                while (n > g) {
+                    int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
+                    Relay fc = new Relay(new Merger(s, w, a, wb, h,
+                                                    wb+h, n-h, b, g));
+                    Relay rc = new Relay(new Merger(fc, a, w, b+h, q,
+                                                    b+u, n-u, wb+h, g));
+                    new Sorter(rc, a, w, b+u, n-u, wb+u, g).fork();
+                    new Sorter(rc, a, w, b+h, q, wb+h, g).fork();;
+                    Relay bc = new Relay(new Merger(fc, a, w, b, q,
+                                                    b+q, h-q, wb, g));
+                    new Sorter(bc, a, w, b+q, h-q, wb+q, g).fork();
+                    s = new EmptyCompleter(bc);
+                    n = q;
                 }
+                DualPivotQuicksort.sort(a, b, b + n - 1, w, wb, n);
+                s.tryComplete();
             }
         }
 
-        static final class Merger extends RecursiveAction {
-            static final long serialVersionUID = 8076242187166127592L;
-            final double[] a;
-            final double[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger next;
-
-            Merger(double[] a, double[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
+        static final class Merger extends CountedCompleter<Void> {
+            static final long serialVersionUID = 2446542900576103244L;
+            final double[] a, w; // main and workspace arrays
+            final int lbase, lsize, rbase, rsize, wbase, gran;
+            Merger(CountedCompleter<?> par, double[] a, double[] w,
+                   int lbase, int lsize, int rbase,
+                   int rsize, int wbase, int gran) {
+                super(par);
+                this.a = a; this.w = w;
+                this.lbase = lbase; this.lsize = lsize;
+                this.rbase = rbase; this.rsize = rsize;
+                this.wbase = wbase; this.gran = gran;
             }
 
-            public void compute() {
-                final double[] a = this.a;
-                final double[] w = this.w;
-                Merger rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    double split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (Double.compare(split, a[ro+mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
+            public final void compute() {
+                double[] a = this.a, w = this.w; // localize all params
+                int lb = this.lbase, ln = this.lsize, rb = this.rbase,
+                    rn = this.rsize, k = this.wbase, g = this.gran;
+                if (a == null || w == null || lb < 0 || rb < 0 || k < 0)
+                    throw new IllegalStateException(); // hoist checks
+                for (int lh, rh;;) {  // split larger, find point in smaller
+                    if (ln >= rn) {
+                        if (ln <= g)
+                            break;
+                        rh = rn;
+                        double split = a[(lh = ln >>> 1) + lb];
+                        for (int lo = 0; lo < rh; ) {
+                            int rm = (lo + rh) >>> 1;
+                            if (split <= a[rm + rb])
+                                rh = rm;
+                            else
+                                lo = rm + 1;
+                        }
                     }
-                    (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
-                                         nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
+                    else {
+                        if (rn <= g)
+                            break;
+                        lh = ln;
+                        double split = a[(rh = rn >>> 1) + rb];
+                        for (int lo = 0; lo < lh; ) {
+                            int lm = (lo + lh) >>> 1;
+                            if (split <= a[lm + lb])
+                                lh = lm;
+                            else
+                                lo = lm + 1;
+                        }
+                    }
+                    Merger m = new Merger(this, a, w, lb + lh, ln - lh,
+                                          rb + rh, rn - rh,
+                                          k + lh + rh, g);
+                    rn = rh;
+                    ln = lh;
+                    addToPendingCount(1);
+                    m.fork();
                 }
 
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    double al = a[l];
-                    double ar = a[r];
-                    double t;
-                    if (Double.compare(al, ar) <= 0) {
-                        ++l;
-                        t = al;
-                    } else {
-                        ++r;
-                        t = ar;
+                int lf = lb + ln, rf = rb + rn; // index bounds
+                while (lb < lf && rb < rf) {
+                    double t, al, ar;
+                    if ((al = a[lb]) <= (ar = a[rb])) {
+                        lb++; t = al;
+                    }
+                    else {
+                        rb++; t = ar;
                     }
                     w[k++] = t;
                 }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
+                if (rb < rf)
+                    System.arraycopy(a, rb, w, k, rf - rb);
+                else if (lb < lf)
+                    System.arraycopy(a, lb, w, k, lf - lb);
+                tryComplete();
             }
         }
     } // FJDouble
 
-    /** Comparable support class */
-    static final class FJComparable {
-        static final class Sorter<T extends Comparable<? super T>> extends RecursiveAction {
-            static final long serialVersionUID = -1024003289463302522L;
-            final T[] a;
-            final T[] w;
-            final int origin;
-            final int n;
-            final int gran;
-
-            Sorter(T[] a, T[] w, int origin, int n, int gran) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.gran = gran;
-            }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final T[] a = this.a;
-                final T[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1;
-                    int q = n >>> 2;
-                    int u = h + q;
-                    FJSubSorter ls = new FJSubSorter(new Sorter<>(a, w, l, q,   g),
-                                                     new Sorter<>(a, w, l+q, h-q, g),
-                                                     new Merger<>(a, w, l,   q,
-                                                                  l+q, h-q, l, g, null));
-                    FJSubSorter rs = new FJSubSorter(new Sorter<>(a, w, l+h, q,   g),
-                                                     new Sorter<>(a, w, l+u, n-u, g),
-                                                     new Merger<>(a, w, l+h, q,
-                                                                  l+u, n-u, l+h, g, null));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger<>(w, a, l, h, l + h, n - h, l, g, null).compute();
-                } else {
-                    Arrays.sort(a, l, l+n);
-                }
-            }
-        }
-
-        static final class Merger<T extends Comparable<? super T>> extends RecursiveAction {
-            static final long serialVersionUID = -3989771675258379302L;
-            final T[] a;
-            final T[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger<T> next;
-
-            Merger(T[] a, T[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger<T> next) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
-            }
-
-            public void compute() {
-                final T[] a = this.a;
-                final T[] w = this.w;
-                Merger<T> rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    T split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (split.compareTo(a[ro + mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
-                    }
-                    (rights = new Merger<>(a, w, splitIndex, nleft-lh, ro+rh,
-                                           nright-rh, wo+lh+rh, gran, rights)).fork();
-                    nleft = lh;
-                    nright = rh;
-                }
-
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    T al = a[l];
-                    T ar = a[r];
-                    T t;
-                    if (al.compareTo(ar) <= 0) {++l; t=al;} else {++r; t=ar; }
-                    w[k++] = t;
-                }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
-            }
-        }
-    } // FJComparable
-
-    /** Object + Comparator support class */
-    static final class FJComparator {
-        static final class Sorter<T> extends RecursiveAction {
-            static final long serialVersionUID = 9191600840025808581L;
-            final T[] a;       // array to be sorted.
-            final T[] w;       // workspace for merge
-            final int origin;  // origin of the part of array we deal with
-            final int n;       // Number of elements in (sub)arrays.
-            final int gran;    // split control
-            final Comparator<? super T> cmp; // Comparator to use
-
-            Sorter(T[] a, T[] w, int origin, int n, int gran, Comparator<? super T> cmp) {
-                this.a = a;
-                this.w = w;
-                this.origin = origin;
-                this.n = n;
-                this.cmp = cmp;
-                this.gran = gran;
-            }
-
-            public void compute() {
-                final int l = origin;
-                final int g = gran;
-                final int n = this.n;
-                final T[] a = this.a;
-                final T[] w = this.w;
-                if (n > g) {
-                    int h = n >>> 1; // half
-                    int q = n >>> 2; // lower quarter index
-                    int u = h + q;   // upper quarter
-                    FJSubSorter ls = new FJSubSorter(new Sorter<>(a, w, l, q,   g, cmp),
-                                                     new Sorter<>(a, w, l+q, h-q, g, cmp),
-                                                     new Merger<>(a, w, l,   q,
-                                                                  l+q, h-q, l, g, null, cmp));
-                    FJSubSorter rs = new FJSubSorter(new Sorter<>(a, w, l + h, q,   g, cmp),
-                                                     new Sorter<>(a, w, l+u, n-u, g, cmp),
-                                                     new Merger<>(a, w, l+h, q,
-                                                                  l+u, n-u, l+h, g, null, cmp));
-                    rs.fork();
-                    ls.compute();
-                    if (rs.tryUnfork()) rs.compute(); else rs.join();
-                    new Merger<>(w, a, l, h, l + h, n - h, l, g, null, cmp).compute();
-                } else {
-                    Arrays.sort(a, l, l+n, cmp);
-                }
-            }
-        }
-
-        static final class Merger<T> extends RecursiveAction {
-            static final long serialVersionUID = -2679539040379156203L;
-            final T[] a;
-            final T[] w;
-            final int lo;
-            final int ln;
-            final int ro;
-            final int rn;
-            final int wo;
-            final int gran;
-            final Merger<T> next;
-            final Comparator<? super T> cmp;
-
-            Merger(T[] a, T[] w, int lo, int ln, int ro, int rn, int wo,
-                   int gran, Merger<T> next, Comparator<? super T> cmp) {
-                this.a = a;
-                this.w = w;
-                this.lo = lo;
-                this.ln = ln;
-                this.ro = ro;
-                this.rn = rn;
-                this.wo = wo;
-                this.gran = gran;
-                this.next = next;
-                this.cmp = cmp;
-            }
-
-            public void compute() {
-                final T[] a = this.a;
-                final T[] w = this.w;
-                Merger<T> rights = null;
-                int nleft = ln;
-                int nright = rn;
-                while (nleft > gran) {
-                    int lh = nleft >>> 1;
-                    int splitIndex = lo + lh;
-                    T split = a[splitIndex];
-                    int rl = 0;
-                    int rh = nright;
-                    while (rl < rh) {
-                        int mid = (rl + rh) >>> 1;
-                        if (cmp.compare(split, a[ro+mid]) <= 0)
-                            rh = mid;
-                        else
-                            rl = mid + 1;
-                    }
-                    (rights = new Merger<>(a, w, splitIndex, nleft-lh, ro+rh,
-                                           nright-rh, wo+lh+rh, gran, rights, cmp)).fork();
-                    nleft = lh;
-                    nright = rh;
-                }
-
-                int l = lo;
-                int lFence = l + nleft;
-                int r = ro;
-                int rFence = r + nright;
-                int k = wo;
-                while (l < lFence && r < rFence) {
-                    T al = a[l];
-                    T ar = a[r];
-                    T t;
-                    if (cmp.compare(al, ar) <= 0) {
-                        ++l;
-                        t = al;
-                    } else {
-                        ++r;
-                        t = ar;
-                    }
-                    w[k++] = t;
-                }
-                while (l < lFence)
-                    w[k++] = a[l++];
-                while (r < rFence)
-                    w[k++] = a[r++];
-                while (rights != null) {
-                    if (rights.tryUnfork())
-                        rights.compute();
-                    else
-                        rights.join();
-                    rights = rights.next;
-                }
-            }
-        }
-    } // FJComparator
-
-    /** Utility class to sort half a partitioned array */
-    private static final class FJSubSorter extends RecursiveAction {
-        static final long serialVersionUID = 9159249695527935512L;
-        final RecursiveAction left;
-        final RecursiveAction right;
-        final RecursiveAction merger;
-
-        FJSubSorter(RecursiveAction left, RecursiveAction right,
-                    RecursiveAction merger) {
-            this.left = left;
-            this.right = right;
-            this.merger = merger;
-        }
-
-        public void compute() {
-            right.fork();
-            left.invoke();
-            right.join();
-            merger.invoke();
-        }
-    }
 }
--- a/src/share/classes/java/util/ComparableTimSort.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/ComparableTimSort.java	Wed Jun 05 00:37:11 2013 -0700
@@ -86,9 +86,13 @@
     private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
 
     /**
-     * Temp storage for merges.
+     * Temp storage for merges. A workspace array may optionally be
+     * provided in constructor, and if so will be used as long as it
+     * is big enough.
      */
     private Object[] tmp;
+    private int tmpBase; // base of tmp array slice
+    private int tmpLen;  // length of tmp array slice
 
     /**
      * A stack of pending runs yet to be merged.  Run i starts at
@@ -108,15 +112,27 @@
      * Creates a TimSort instance to maintain the state of an ongoing sort.
      *
      * @param a the array to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private ComparableTimSort(Object[] a) {
+    private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
         this.a = a;
 
         // Allocate temp storage (which may be increased later if necessary)
         int len = a.length;
-        Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
-                                       len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
-        tmp = newArray;
+        int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
+            len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
+        if (work == null || workLen < tlen || workBase + tlen > work.length) {
+            tmp = new Object[tlen];
+            tmpBase = 0;
+            tmpLen = tlen;
+        }
+        else {
+            tmp = work;
+            tmpBase = workBase;
+            tmpLen = workLen;
+        }
 
         /*
          * Allocate runs-to-be-merged stack (which cannot be expanded).  The
@@ -136,17 +152,28 @@
     }
 
     /*
-     * The next two methods (which are package private and static) constitute
-     * the entire API of this class.  Each of these methods obeys the contract
-     * of the public method with the same signature in java.util.Arrays.
+     * The next method (package private and static) constitutes the
+     * entire API of this class.
      */
 
-    static void sort(Object[] a) {
-          sort(a, 0, a.length);
-    }
+    /**
+     * Sorts the given range, using the given workspace array slice
+     * for temp storage when possible. This method is designed to be
+     * invoked from public methods (in class Arrays) after performing
+     * any necessary array bounds checks and expanding parameters into
+     * the required forms.
+     *
+     * @param a the array to be sorted
+     * @param lo the index of the first element, inclusive, to be sorted
+     * @param hi the index of the last element, exclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
+     * @since 1.8
+     */
+    static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
+        assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
 
-    static void sort(Object[] a, int lo, int hi) {
-        rangeCheck(a.length, lo, hi);
         int nRemaining  = hi - lo;
         if (nRemaining < 2)
             return;  // Arrays of size 0 and 1 are always sorted
@@ -163,7 +190,7 @@
          * extending short natural runs to minRun elements, and merging runs
          * to maintain stack invariant.
          */
-        ComparableTimSort ts = new ComparableTimSort(a);
+        ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
         int minRun = minRunLength(nRemaining);
         do {
             // Identify next run
@@ -619,11 +646,11 @@
         // Copy first run into temp array
         Object[] a = this.a; // For performance
         Object[] tmp = ensureCapacity(len1);
-        System.arraycopy(a, base1, tmp, 0, len1);
 
-        int cursor1 = 0;       // Indexes into tmp array
+        int cursor1 = tmpBase; // Indexes into tmp array
         int cursor2 = base2;   // Indexes int a
         int dest = base1;      // Indexes int a
+        System.arraycopy(a, base1, tmp, cursor1, len1);
 
         // Move first element of second run and deal with degenerate cases
         a[dest++] = a[cursor2++];
@@ -736,16 +763,17 @@
         // Copy second run into temp array
         Object[] a = this.a; // For performance
         Object[] tmp = ensureCapacity(len2);
-        System.arraycopy(a, base2, tmp, 0, len2);
+        int tmpBase = this.tmpBase;
+        System.arraycopy(a, base2, tmp, tmpBase, len2);
 
         int cursor1 = base1 + len1 - 1;  // Indexes into a
-        int cursor2 = len2 - 1;          // Indexes into tmp array
+        int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
         int dest = base2 + len2 - 1;     // Indexes into a
 
         // Move last element of first run and deal with degenerate cases
         a[dest--] = a[cursor1--];
         if (--len1 == 0) {
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
             return;
         }
         if (len2 == 1) {
@@ -803,7 +831,7 @@
                 if (--len2 == 1)
                     break outer;
 
-                count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1);
+                count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
                 if (count2 != 0) {
                     dest -= count2;
                     cursor2 -= count2;
@@ -835,7 +863,7 @@
         } else {
             assert len1 == 0;
             assert len2 > 0;
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
         }
     }
 
@@ -848,7 +876,7 @@
      * @return tmp, whether or not it grew
      */
     private Object[]  ensureCapacity(int minCapacity) {
-        if (tmp.length < minCapacity) {
+        if (tmpLen < minCapacity) {
             // Compute smallest power of 2 > minCapacity
             int newSize = minCapacity;
             newSize |= newSize >> 1;
@@ -863,30 +891,13 @@
             else
                 newSize = Math.min(newSize, a.length >>> 1);
 
+            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
             Object[] newArray = new Object[newSize];
             tmp = newArray;
+            tmpLen = newSize;
+            tmpBase = 0;
         }
         return tmp;
     }
 
-    /**
-     * Checks that fromIndex and toIndex are in range, and throws an
-     * appropriate exception if they aren't.
-     *
-     * @param arrayLen the length of the array
-     * @param fromIndex the index of the first element of the range
-     * @param toIndex the index after the last element of the range
-     * @throws IllegalArgumentException if fromIndex > toIndex
-     * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-     *         or toIndex > arrayLen
-     */
-    private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex(" + fromIndex +
-                       ") > toIndex(" + toIndex+")");
-        if (fromIndex < 0)
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        if (toIndex > arrayLen)
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-    }
 }
--- a/src/share/classes/java/util/DualPivotQuicksort.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/DualPivotQuicksort.java	Wed Jun 05 00:37:11 2013 -0700
@@ -32,6 +32,11 @@
  * quicksorts to degrade to quadratic performance, and is typically
  * faster than traditional (one-pivot) Quicksort implementations.
  *
+ * All exposed methods are package-private, designed to be invoked
+ * from public methods (in class Arrays) after performing any
+ * necessary array bounds checks and expanding parameters into the
+ * required forms.
+ *
  * @author Vladimir Yaroslavskiy
  * @author Jon Bentley
  * @author Josh Bloch
@@ -89,22 +94,18 @@
      */
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(int[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(int[] a, int left, int right) {
+    static void sort(int[] a, int left, int right,
+                     int[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -147,24 +148,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        int[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        int[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new int[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new int[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new int[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -172,21 +184,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             int[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -529,22 +542,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(long[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(long[] a, int left, int right) {
+    static void sort(long[] a, int left, int right,
+                     long[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -587,24 +596,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        long[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        long[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new long[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new long[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new long[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -612,21 +632,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             long[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -969,22 +990,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(short[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(short[] a, int left, int right) {
+    static void sort(short[] a, int left, int right,
+                     short[] work, int workBase, int workLen) {
         // Use counting sort on large arrays
         if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
             int[] count = new int[NUM_SHORT_VALUES];
@@ -1002,7 +1019,7 @@
                 } while (--s > 0);
             }
         } else { // Use Dual-Pivot Quicksort on small arrays
-            doSort(a, left, right);
+            doSort(a, left, right, work, workBase, workLen);
         }
     }
 
@@ -1015,8 +1032,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(short[] a, int left, int right) {
+    private static void doSort(short[] a, int left, int right,
+                               short[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -1059,24 +1080,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        short[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        short[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new short[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new short[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new short[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -1084,21 +1116,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             short[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -1441,22 +1474,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(char[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(char[] a, int left, int right) {
+    static void sort(char[] a, int left, int right,
+                     char[] work, int workBase, int workLen) {
         // Use counting sort on large arrays
         if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
             int[] count = new int[NUM_CHAR_VALUES];
@@ -1474,7 +1503,7 @@
                 } while (--s > 0);
             }
         } else { // Use Dual-Pivot Quicksort on small arrays
-            doSort(a, left, right);
+            doSort(a, left, right, work, workBase, workLen);
         }
     }
 
@@ -1487,8 +1516,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(char[] a, int left, int right) {
+    private static void doSort(char[] a, int left, int right,
+                               char[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -1531,24 +1564,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        char[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        char[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new char[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new char[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new char[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -1556,21 +1600,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             char[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -1916,22 +1961,13 @@
     private static final int NUM_BYTE_VALUES = 1 << 8;
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(byte[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
      * Sorts the specified range of the array.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    public static void sort(byte[] a, int left, int right) {
+    static void sort(byte[] a, int left, int right) {
         // Use counting sort on large arrays
         if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
             int[] count = new int[NUM_BYTE_VALUES];
@@ -1963,22 +1999,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(float[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(float[] a, int left, int right) {
+    static void sort(float[] a, int left, int right,
+                     float[] work, int workBase, int workLen) {
         /*
          * Phase 1: Move NaNs to the end of the array.
          */
@@ -1997,7 +2029,7 @@
         /*
          * Phase 2: Sort everything except NaNs (which are already in place).
          */
-        doSort(a, left, right);
+        doSort(a, left, right, work, workBase, workLen);
 
         /*
          * Phase 3: Place negative zeros before positive zeros.
@@ -2064,8 +2096,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(float[] a, int left, int right) {
+    private static void doSort(float[] a, int left, int right,
+                               float[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -2108,24 +2144,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        float[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        float[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new float[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new float[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new float[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -2133,21 +2180,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             float[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
@@ -2490,22 +2538,18 @@
     }
 
     /**
-     * Sorts the specified array.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(double[] a) {
-        sort(a, 0, a.length - 1);
-    }
-
-    /**
-     * Sorts the specified range of the array.
+     * Sorts the specified range of the array using the given
+     * workspace array slice if possible for merging
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    public static void sort(double[] a, int left, int right) {
+    static void sort(double[] a, int left, int right,
+                     double[] work, int workBase, int workLen) {
         /*
          * Phase 1: Move NaNs to the end of the array.
          */
@@ -2524,7 +2568,7 @@
         /*
          * Phase 2: Sort everything except NaNs (which are already in place).
          */
-        doSort(a, left, right);
+        doSort(a, left, right, work, workBase, workLen);
 
         /*
          * Phase 3: Place negative zeros before positive zeros.
@@ -2591,8 +2635,12 @@
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private static void doSort(double[] a, int left, int right) {
+    private static void doSort(double[] a, int left, int right,
+                               double[] work, int workBase, int workLen) {
         // Use Quicksort on small arrays
         if (right - left < QUICKSORT_THRESHOLD) {
             sort(a, left, right, true);
@@ -2635,24 +2683,35 @@
         }
 
         // Check special cases
+        // Implementation note: variable "right" is increased by 1.
         if (run[count] == right++) { // The last run contains one element
             run[++count] = right;
         } else if (count == 1) { // The array is already sorted
             return;
         }
 
-        /*
-         * Create temporary array, which is used for merging.
-         * Implementation note: variable "right" is increased by 1.
-         */
-        double[] b; byte odd = 0;
+        // Determine alternation base for merge
+        byte odd = 0;
         for (int n = 1; (n <<= 1) < count; odd ^= 1);
 
+        // Use or create temporary array b for merging
+        double[] b;                 // temp array; alternates with a
+        int ao, bo;              // array offsets from 'left'
+        int blen = right - left; // space needed for b
+        if (work == null || workLen < blen || workBase + blen > work.length) {
+            work = new double[blen];
+            workBase = 0;
+        }
         if (odd == 0) {
-            b = a; a = new double[b.length];
-            for (int i = left - 1; ++i < right; a[i] = b[i]);
+            System.arraycopy(a, left, work, workBase, blen);
+            b = a;
+            bo = 0;
+            a = work;
+            ao = workBase - left;
         } else {
-            b = new double[a.length];
+            b = work;
+            ao = 0;
+            bo = workBase - left;
         }
 
         // Merging
@@ -2660,21 +2719,22 @@
             for (int k = (last = 0) + 2; k <= count; k += 2) {
                 int hi = run[k], mi = run[k - 1];
                 for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
-                    if (q >= hi || p < mi && a[p] <= a[q]) {
-                        b[i] = a[p++];
+                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+                        b[i + bo] = a[p++ + ao];
                     } else {
-                        b[i] = a[q++];
+                        b[i + bo] = a[q++ + ao];
                     }
                 }
                 run[++last] = hi;
             }
             if ((count & 1) != 0) {
                 for (int i = right, lo = run[count - 1]; --i >= lo;
-                    b[i] = a[i]
+                    b[i + bo] = a[i + ao]
                 );
                 run[++last] = right;
             }
             double[] t = a; a = b; b = t;
+            int o = ao; ao = bo; bo = o;
         }
     }
 
--- a/src/share/classes/java/util/ListResourceBundle.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/ListResourceBundle.java	Wed Jun 05 00:37:11 2013 -0700
@@ -89,7 +89,7 @@
  *
  * public class MyResources_fr extends ListResourceBundle {
  *     protected Object[][] getContents() {
- *         return new Object[][] = {
+ *         return new Object[][] {
  *         // LOCALIZE THIS
  *             {"s1", "Le disque \"{1}\" {0}."},          // MessageFormat pattern
  *             {"s2", "1"},                               // location of {0} in pattern
--- a/src/share/classes/java/util/PropertyResourceBundle.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/PropertyResourceBundle.java	Wed Jun 05 00:37:11 2013 -0700
@@ -124,6 +124,8 @@
      *        to read from.
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if <code>stream</code> is null
+     * @throws IllegalArgumentException if {@code stream} contains a
+     *     malformed Unicode escape sequence.
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
     public PropertyResourceBundle (InputStream stream) throws IOException {
@@ -142,6 +144,8 @@
      *        read from.
      * @throws IOException if an I/O error occurs
      * @throws NullPointerException if <code>reader</code> is null
+     * @throws IllegalArgumentException if a malformed Unicode escape sequence appears
+     *     from {@code reader}.
      * @since 1.6
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
--- a/src/share/classes/java/util/Spliterator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/Spliterator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -140,32 +140,32 @@
  * (in approximate order of decreasing desirability):
  * <ul>
  * <li>The source cannot be structurally interfered with.
- * </br>For example, an instance of
+ * <br>For example, an instance of
  * {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
  * A Spliterator created from the source reports a characteristic of
  * {@code IMMUTABLE}.</li>
  * <li>The source manages concurrent modifications.
- * </br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
+ * <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
  * is a concurrent source.  A Spliterator created from the source reports a
  * characteristic of {@code CONCURRENT}.</li>
  * <li>The mutable source provides a late-binding and fail-fast Spliterator.
- * </br>Late binding narrows the window during which interference can affect
+ * <br>Late binding narrows the window during which interference can affect
  * the calculation; fail-fast detects, on a best-effort basis, that structural
  * interference has occurred after traversal has commenced and throws
  * {@link ConcurrentModificationException}.  For example, {@link ArrayList},
  * and many other non-concurrent {@code Collection} classes in the JDK, provide
  * a late-binding, fail-fast spliterator.</li>
  * <li>The mutable source provides a non-late-binding but fail-fast Spliterator.
- * </br>The source increases the likelihood of throwing
+ * <br>The source increases the likelihood of throwing
  * {@code ConcurrentModificationException} since the window of potential
  * interference is larger.</li>
  * <li>The mutable source provides a late-binding and non-fail-fast Spliterator.
- * </br>The source risks arbitrary, non-deterministic behavior after traversal
+ * <br>The source risks arbitrary, non-deterministic behavior after traversal
  * has commenced since interference is not detected.
  * </li>
  * <li>The mutable source provides a non-late-binding and non-fail-fast
  * Spliterator.
- * </br>The source increases the risk of arbitrary, non-deterministic behavior
+ * <br>The source increases the risk of arbitrary, non-deterministic behavior
  * since non-detected interference may occur after construction.
  * </li>
  * </ul>
@@ -284,6 +284,8 @@
  * is set to {@code true} then diagnostic warnings are reported if boxing of
  * primitive values occur when operating on primitive subtype specializations.
  *
+ * @param <T> the type of elements returned by this Spliterator
+ *
  * @see Collection
  * @since 1.8
  */
@@ -333,9 +335,8 @@
      * Upon non-null return:
      * <ul>
      * <li>the value reported for {@code estimateSize()} before splitting,
-     * if not already zero or {@code Long.MAX_VALUE}, must, after splitting, be
-     * greater than {@code estimateSize()} for this and the returned
-     * Spliterator; and</li>
+     * must, after splitting, be greater than or equal to {@code estimateSize()}
+     * for this and the returned Spliterator; and</li>
      * <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
      * for this spliterator before splitting must be equal to the sum of
      * {@code estimateSize()} for this and the returned Spliterator after
@@ -566,13 +567,28 @@
     public static final int SUBSIZED = 0x00004000;
 
     /**
-     * A Spliterator specialized for {@code int} values.
+     * A Spliterator specialized for primitive values.
+     *
+     * @param <T> the type of elements returned by this Spliterator.  The
+     * 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}.
+     * @param <T_SPLITR> the type of primitive Spliterator.  The type must be
+     * a primitive specialization of Spliterator for {@code T}, such as
+     * {@link Spliterator.OfInt} for {@code Integer}.
+     *
+     * @see Spliterator.OfInt
+     * @see Spliterator.OfLong
+     * @see Spliterator.OfDouble
      * @since 1.8
      */
-    public interface OfInt extends Spliterator<Integer> {
-
+    public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
+            extends Spliterator<T> {
         @Override
-        OfInt trySplit();
+        T_SPLITR trySplit();
 
         /**
          * If a remaining element exists, performs the given action on it,
@@ -586,7 +602,7 @@
          * upon entry to this method, else {@code true}.
          * @throws NullPointerException if the specified action is null
          */
-        boolean tryAdvance(IntConsumer action);
+        boolean tryAdvance(T_CONS action);
 
         /**
          * Performs the given action for each remaining element, sequentially in
@@ -603,6 +619,24 @@
          * @param action The action
          * @throws NullPointerException if the specified action is null
          */
+        default void forEachRemaining(T_CONS action) {
+            do { } while (tryAdvance(action));
+        }
+    }
+
+    /**
+     * A Spliterator specialized for {@code int} values.
+     * @since 1.8
+     */
+    public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
+
+        @Override
+        OfInt trySplit();
+
+        @Override
+        boolean tryAdvance(IntConsumer action);
+
+        @Override
         default void forEachRemaining(IntConsumer action) {
             do { } while (tryAdvance(action));
         }
@@ -658,40 +692,15 @@
      * A Spliterator specialized for {@code long} values.
      * @since 1.8
      */
-    public interface OfLong extends Spliterator<Long> {
+    public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
 
         @Override
         OfLong trySplit();
 
-        /**
-         * If a remaining element exists, performs the given action on it,
-         * returning {@code true}; else returns {@code false}.  If this
-         * Spliterator is {@link #ORDERED} the action is performed on the
-         * next element in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @param action The action
-         * @return {@code false} if no remaining elements existed
-         * upon entry to this method, else {@code true}.
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         boolean tryAdvance(LongConsumer action);
 
-        /**
-         * Performs the given action for each remaining element, sequentially in
-         * the current thread, until all elements have been processed or the
-         * action throws an exception.  If this Spliterator is {@link #ORDERED},
-         * actions are performed in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @implSpec
-         * The default implementation repeatedly invokes {@link #tryAdvance}
-         * until it returns {@code false}.  It should be overridden whenever
-         * possible.
-         *
-         * @param action The action
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         default void forEachRemaining(LongConsumer action) {
             do { } while (tryAdvance(action));
         }
@@ -747,40 +756,15 @@
      * A Spliterator specialized for {@code double} values.
      * @since 1.8
      */
-    public interface OfDouble extends Spliterator<Double> {
+    public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
 
         @Override
         OfDouble trySplit();
 
-        /**
-         * If a remaining element exists, performs the given action on it,
-         * returning {@code true}; else returns {@code false}.  If this
-         * Spliterator is {@link #ORDERED} the action is performed on the
-         * next element in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @param action The action
-         * @return {@code false} if no remaining elements existed
-         * upon entry to this method, else {@code true}.
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         boolean tryAdvance(DoubleConsumer action);
 
-        /**
-         * Performs the given action for each remaining element, sequentially in
-         * the current thread, until all elements have been processed or the
-         * action throws an exception.  If this Spliterator is {@link #ORDERED},
-         * actions are performed in encounter order.  Exceptions thrown by the
-         * action are relayed to the caller.
-         *
-         * @implSpec
-         * The default implementation repeatedly invokes {@link #tryAdvance}
-         * until it returns {@code false}.  It should be overridden whenever
-         * possible.
-         *
-         * @param action The action
-         * @throws NullPointerException if the specified action is null
-         */
+        @Override
         default void forEachRemaining(DoubleConsumer action) {
             do { } while (tryAdvance(action));
         }
--- a/src/share/classes/java/util/TimSort.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/TimSort.java	Wed Jun 05 00:37:11 2013 -0700
@@ -111,9 +111,13 @@
     private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
 
     /**
-     * Temp storage for merges.
+     * Temp storage for merges. A workspace array may optionally be
+     * provided in constructor, and if so will be used as long as it
+     * is big enough.
      */
-    private T[] tmp; // Actual runtime type will be Object[], regardless of T
+    private T[] tmp;
+    private int tmpBase; // base of tmp array slice
+    private int tmpLen;  // length of tmp array slice
 
     /**
      * A stack of pending runs yet to be merged.  Run i starts at
@@ -134,17 +138,31 @@
      *
      * @param a the array to be sorted
      * @param c the comparator to determine the order of the sort
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
      */
-    private TimSort(T[] a, Comparator<? super T> c) {
+    private TimSort(T[] a, Comparator<? super T> c, T[] work, int workBase, int workLen) {
         this.a = a;
         this.c = c;
 
         // Allocate temp storage (which may be increased later if necessary)
         int len = a.length;
-        @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
-        T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
-                                        len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
-        tmp = newArray;
+        int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
+            len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
+        if (work == null || workLen < tlen || workBase + tlen > work.length) {
+            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+            T[] newArray = (T[])java.lang.reflect.Array.newInstance
+                (a.getClass().getComponentType(), tlen);
+            tmp = newArray;
+            tmpBase = 0;
+            tmpLen = tlen;
+        }
+        else {
+            tmp = work;
+            tmpBase = workBase;
+            tmpLen = workLen;
+        }
 
         /*
          * Allocate runs-to-be-merged stack (which cannot be expanded).  The
@@ -164,22 +182,30 @@
     }
 
     /*
-     * The next two methods (which are package private and static) constitute
-     * the entire API of this class.  Each of these methods obeys the contract
-     * of the public method with the same signature in java.util.Arrays.
+     * The next method (package private and static) constitutes the
+     * entire API of this class.
      */
 
-    static <T> void sort(T[] a, Comparator<? super T> c) {
-        sort(a, 0, a.length, c);
-    }
+    /**
+     * Sorts the given range, using the given workspace array slice
+     * for temp storage when possible. This method is designed to be
+     * invoked from public methods (in class Arrays) after performing
+     * any necessary array bounds checks and expanding parameters into
+     * the required forms.
+     *
+     * @param a the array to be sorted
+     * @param lo the index of the first element, inclusive, to be sorted
+     * @param hi the index of the last element, exclusive, to be sorted
+     * @param c the comparator to use
+     * @param work a workspace array (slice)
+     * @param workBase origin of usable space in work array
+     * @param workLen usable size of work array
+     * @since 1.8
+     */
+    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
+                         T[] work, int workBase, int workLen) {
+        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
 
-    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) {
-        if (c == null) {
-            Arrays.sort(a, lo, hi);
-            return;
-        }
-
-        rangeCheck(a.length, lo, hi);
         int nRemaining  = hi - lo;
         if (nRemaining < 2)
             return;  // Arrays of size 0 and 1 are always sorted
@@ -196,7 +222,7 @@
          * extending short natural runs to minRun elements, and merging runs
          * to maintain stack invariant.
          */
-        TimSort<T> ts = new TimSort<>(a, c);
+        TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
         int minRun = minRunLength(nRemaining);
         do {
             // Identify next run
@@ -653,11 +679,10 @@
         // Copy first run into temp array
         T[] a = this.a; // For performance
         T[] tmp = ensureCapacity(len1);
-        System.arraycopy(a, base1, tmp, 0, len1);
-
-        int cursor1 = 0;       // Indexes into tmp array
+        int cursor1 = tmpBase; // Indexes into tmp array
         int cursor2 = base2;   // Indexes int a
         int dest = base1;      // Indexes int a
+        System.arraycopy(a, base1, tmp, cursor1, len1);
 
         // Move first element of second run and deal with degenerate cases
         a[dest++] = a[cursor2++];
@@ -770,16 +795,17 @@
         // Copy second run into temp array
         T[] a = this.a; // For performance
         T[] tmp = ensureCapacity(len2);
-        System.arraycopy(a, base2, tmp, 0, len2);
+        int tmpBase = this.tmpBase;
+        System.arraycopy(a, base2, tmp, tmpBase, len2);
 
         int cursor1 = base1 + len1 - 1;  // Indexes into a
-        int cursor2 = len2 - 1;          // Indexes into tmp array
+        int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
         int dest = base2 + len2 - 1;     // Indexes into a
 
         // Move last element of first run and deal with degenerate cases
         a[dest--] = a[cursor1--];
         if (--len1 == 0) {
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
             return;
         }
         if (len2 == 1) {
@@ -838,7 +864,7 @@
                 if (--len2 == 1)
                     break outer;
 
-                count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
+                count2 = len2 - gallopLeft(a[cursor1], tmp, tmpBase, len2, len2 - 1, c);
                 if (count2 != 0) {
                     dest -= count2;
                     cursor2 -= count2;
@@ -870,7 +896,7 @@
         } else {
             assert len1 == 0;
             assert len2 > 0;
-            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
         }
     }
 
@@ -883,7 +909,7 @@
      * @return tmp, whether or not it grew
      */
     private T[] ensureCapacity(int minCapacity) {
-        if (tmp.length < minCapacity) {
+        if (tmpLen < minCapacity) {
             // Compute smallest power of 2 > minCapacity
             int newSize = minCapacity;
             newSize |= newSize >> 1;
@@ -899,30 +925,12 @@
                 newSize = Math.min(newSize, a.length >>> 1);
 
             @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
-            T[] newArray = (T[]) new Object[newSize];
+            T[] newArray = (T[])java.lang.reflect.Array.newInstance
+                (a.getClass().getComponentType(), newSize);
             tmp = newArray;
+            tmpLen = newSize;
+            tmpBase = 0;
         }
         return tmp;
     }
-
-    /**
-     * Checks that fromIndex and toIndex are in range, and throws an
-     * appropriate exception if they aren't.
-     *
-     * @param arrayLen the length of the array
-     * @param fromIndex the index of the first element of the range
-     * @param toIndex the index after the last element of the range
-     * @throws IllegalArgumentException if fromIndex > toIndex
-     * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
-     *         or toIndex > arrayLen
-     */
-    private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
-        if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex(" + fromIndex +
-                       ") > toIndex(" + toIndex+")");
-        if (fromIndex < 0)
-            throw new ArrayIndexOutOfBoundsException(fromIndex);
-        if (toIndex > arrayLen)
-            throw new ArrayIndexOutOfBoundsException(toIndex);
-    }
 }
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jun 05 00:37:11 2013 -0700
@@ -44,19 +44,19 @@
  * adjustable expected concurrency for updates. This class obeys the
  * same functional specification as {@link java.util.Hashtable}, and
  * includes versions of methods corresponding to each method of
- * <tt>Hashtable</tt>. However, even though all operations are
+ * {@code Hashtable}. However, even though all operations are
  * thread-safe, retrieval operations do <em>not</em> entail locking,
  * and there is <em>not</em> any support for locking the entire table
  * in a way that prevents all access.  This class is fully
- * interoperable with <tt>Hashtable</tt> in programs that rely on its
+ * interoperable with {@code Hashtable} in programs that rely on its
  * thread safety but not on its synchronization details.
  *
- * <p> Retrieval operations (including <tt>get</tt>) generally do not
+ * <p> Retrieval operations (including {@code get}) generally do not
  * block, so may overlap with update operations (including
- * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
+ * {@code put} and {@code remove}). Retrievals reflect the results
  * of the most recently <em>completed</em> update operations holding
- * upon their onset.  For aggregate operations such as <tt>putAll</tt>
- * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
+ * upon their onset.  For aggregate operations such as {@code putAll}
+ * and {@code clear}, concurrent retrievals may reflect insertion or
  * removal of only some entries.  Similarly, Iterators and
  * Enumerations return elements reflecting the state of the hash table
  * at some point at or since the creation of the iterator/enumeration.
@@ -64,8 +64,8 @@
  * However, iterators are designed to be used by only one thread at a time.
  *
  * <p> The allowed concurrency among update operations is guided by
- * the optional <tt>concurrencyLevel</tt> constructor argument
- * (default <tt>16</tt>), which is used as a hint for internal sizing.  The
+ * the optional {@code concurrencyLevel} constructor argument
+ * (default {@code 16}), which is used as a hint for internal sizing.  The
  * table is internally partitioned to try to permit the indicated
  * number of concurrent updates without contention. Because placement
  * in hash tables is essentially random, the actual concurrency will
@@ -85,8 +85,8 @@
  * <em>optional</em> methods of the {@link Map} and {@link Iterator}
  * interfaces.
  *
- * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
- * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
+ * <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
+ * does <em>not</em> allow {@code null} to be used as a key or value.
  *
  * <p>This class is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -353,8 +353,8 @@
 
         /**
          * The table is rehashed when its size exceeds this threshold.
-         * (The value of this field is always <tt>(int)(capacity *
-         * loadFactor)</tt>.)
+         * (The value of this field is always {@code (int)(capacity *
+         * loadFactor)}.)
          */
         transient int threshold;
 
@@ -829,9 +829,9 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map contains no key-value mappings.
+     * Returns {@code true} if this map contains no key-value mappings.
      *
-     * @return <tt>true</tt> if this map contains no key-value mappings
+     * @return {@code true} if this map contains no key-value mappings
      */
     public boolean isEmpty() {
         /*
@@ -870,8 +870,8 @@
 
     /**
      * Returns the number of key-value mappings in this map.  If the
-     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
-     * <tt>Integer.MAX_VALUE</tt>.
+     * map contains more than {@code Integer.MAX_VALUE} elements, returns
+     * {@code Integer.MAX_VALUE}.
      *
      * @return the number of key-value mappings in this map
      */
@@ -948,10 +948,10 @@
     /**
      * Tests if the specified object is a key in this table.
      *
-     * @param  key   possible key
-     * @return <tt>true</tt> if and only if the specified object
+     * @param  key possible key
+     * @return {@code true} if and only if the specified object
      *         is a key in this table, as determined by the
-     *         <tt>equals</tt> method; <tt>false</tt> otherwise.
+     *         {@code equals} method; {@code false} otherwise
      * @throws NullPointerException if the specified key is null
      */
     @SuppressWarnings("unchecked")
@@ -974,13 +974,12 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map maps one or more keys to the
-     * specified value. Note: This method requires a full internal
-     * traversal of the hash table, and so is much slower than
-     * method <tt>containsKey</tt>.
+     * Returns {@code true} if this map maps one or more keys to the
+     * specified value. Note: This method requires a full traversal
+     * of the map, and so is much slower than method {@code containsKey}.
      *
      * @param value value whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map maps one or more keys to the
+     * @return {@code true} if this map maps one or more keys to the
      *         specified value
      * @throws NullPointerException if the specified value is null
      */
@@ -1033,16 +1032,16 @@
     /**
      * Legacy method testing if some key maps into the specified value
      * in this table.  This method is identical in functionality to
-     * {@link #containsValue}, and exists solely to ensure
+     * {@link #containsValue(Object)}, and exists solely to ensure
      * full compatibility with class {@link java.util.Hashtable},
      * which supported this method prior to introduction of the
      * Java Collections framework.
      *
      * @param  value a value to search for
-     * @return <tt>true</tt> if and only if some key maps to the
-     *         <tt>value</tt> argument in this table as
-     *         determined by the <tt>equals</tt> method;
-     *         <tt>false</tt> otherwise
+     * @return {@code true} if and only if some key maps to the
+     *         {@code value} argument in this table as
+     *         determined by the {@code equals} method;
+     *         {@code false} otherwise
      * @throws NullPointerException if the specified value is null
      */
     public boolean contains(Object value) {
@@ -1053,13 +1052,13 @@
      * Maps the specified key to the specified value in this table.
      * Neither the key nor the value can be null.
      *
-     * <p> The value can be retrieved by calling the <tt>get</tt> method
+     * <p>The value can be retrieved by calling the {@code get} method
      * with a key that is equal to the original key.
      *
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
-     * @return the previous value associated with <tt>key</tt>, or
-     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @return the previous value associated with {@code key}, or
+     *         {@code null} if there was no mapping for {@code key}
      * @throws NullPointerException if the specified key or value is null
      */
     @SuppressWarnings("unchecked")
@@ -1079,7 +1078,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws NullPointerException if the specified key or value is null
      */
     @SuppressWarnings("unchecked")
@@ -1112,8 +1111,8 @@
      * This method does nothing if the key is not in the map.
      *
      * @param  key the key that needs to be removed
-     * @return the previous value associated with <tt>key</tt>, or
-     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @return the previous value associated with {@code key}, or
+     *         {@code null} if there was no mapping for {@code key}
      * @throws NullPointerException if the specified key is null
      */
     public V remove(Object key) {
@@ -1151,7 +1150,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws NullPointerException if the specified key or value is null
      */
     public V replace(K key, V value) {
@@ -1177,14 +1176,14 @@
     /**
      * Returns a {@link Set} view of the keys contained in this map.
      * The set is backed by the map, so changes to the map are
-     * reflected in the set, and vice-versa.  The set supports element
+     * reflected in the set, and vice-versa. The set supports element
      * removal, which removes the corresponding mapping from this map,
-     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
-     * operations.  It does not support the <tt>add</tt> or
-     * <tt>addAll</tt> operations.
+     * via the {@code Iterator.remove}, {@code Set.remove},
+     * {@code removeAll}, {@code retainAll}, and {@code clear}
+     * operations.  It does not support the {@code add} or
+     * {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1200,12 +1199,12 @@
      * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  The collection
      * supports element removal, which removes the corresponding
-     * mapping from this map, via the <tt>Iterator.remove</tt>,
-     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
-     * <tt>retainAll</tt>, and <tt>clear</tt> operations.  It does not
-     * support the <tt>add</tt> or <tt>addAll</tt> operations.
+     * mapping from this map, via the {@code Iterator.remove},
+     * {@code Collection.remove}, {@code removeAll},
+     * {@code retainAll}, and {@code clear} operations.  It does not
+     * support the {@code add} or {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1221,12 +1220,12 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  The set supports element
      * removal, which removes the corresponding mapping from the map,
-     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
-     * operations.  It does not support the <tt>add</tt> or
-     * <tt>addAll</tt> operations.
+     * via the {@code Iterator.remove}, {@code Set.remove},
+     * {@code removeAll}, {@code retainAll}, and {@code clear}
+     * operations.  It does not support the {@code add} or
+     * {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1440,7 +1439,7 @@
     /* ---------------- Serialization Support -------------- */
 
     /**
-     * Saves the state of the <tt>ConcurrentHashMap</tt> instance to a
+     * Saves the state of the {@code ConcurrentHashMap} instance to a
      * stream (i.e., serializes it).
      * @param s the stream
      * @serialData
@@ -1477,8 +1476,7 @@
     }
 
     /**
-     * Reconstitutes the <tt>ConcurrentHashMap</tt> instance from a
-     * stream (i.e., deserializes it).
+     * Reconstitutes the instance from a stream (that is, deserializes it).
      * @param s the stream
      */
     @SuppressWarnings("unchecked")
--- a/src/share/classes/java/util/function/BiConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/BiConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,14 +24,16 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts two input arguments and returns no result. This is
  * the two-arity specialization of {@link Consumer}. Unlike most other
  * functional interfaces, {@code BiConsumer} is expected to operate via
  * side-effects.
  *
- * @param <T> the type of the first argument to the {@code accept} operation.
- * @param <U> the type of the second argument to the {@code accept} operation.
+ * @param <T> the type of the first argument to the {@code accept} operation
+ * @param <U> the type of the second argument to the {@code accept} operation
  *
  * @see Consumer
  * @since 1.8
@@ -47,4 +49,28 @@
      * @param u an input object
      */
     void accept(T t, U u);
+
+    /**
+     * Returns a {@code BiConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * the other {@code BiConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a BiConsumer which will be chained after this BiConsumer
+     * @return a BiConsumer which performs in sequence the {@code accept} method
+     * of this BiConsumer and the {@code accept} method of the specified
+     * BiConsumer operation
+     * @throws NullPointerException if other is null
+     */
+    default BiConsumer<T, U> chain(BiConsumer<? super T, ? super U> other) {
+        Objects.requireNonNull(other);
+
+        return (l, r) -> {
+            accept(l, r);
+            other.accept(l, r);
+        };
+    }
 }
--- a/src/share/classes/java/util/function/BiFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/BiFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,15 +24,17 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * Apply a function to the input arguments, yielding an appropriate result. This
  * is the two-arity specialization of {@link Function}. A function may
  * variously provide a mapping between types, object instances or keys and
  * values or any other form of transformation upon the input.
  *
- * @param <T> the type of the first argument to the {@code apply} operation.
- * @param <U> the type of the second argument to the {@code apply} operation.
- * @param <R> the type of results returned by the {@code apply} operation.
+ * @param <T> the type of the first argument to the {@code apply} operation
+ * @param <U> the type of the second argument to the {@code apply} operation
+ * @param <R> the type of results returned by the {@code apply} operation
  *
  * @see Function
  * @since 1.8
@@ -48,4 +50,22 @@
      * @return the function result
      */
     R apply(T t, U u);
+
+    /**
+     * Returns a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param <V> Type of output objects to the combined function. May be the
+     * same type as {@code <T>}, {@code <U>} or {@code <R>}
+     * @param after An additional function to be applied after this function is
+     * applied
+     * @return A function which performs this function followed by the provided
+     * function
+     * @throws NullPointerException if after is null
+     */
+    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
+        Objects.requireNonNull(after);
+        return (T t, U u) -> after.apply(apply(t, u));
+    }
 }
--- a/src/share/classes/java/util/function/BiPredicate.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/BiPredicate.java	Wed Jun 05 00:37:11 2013 -0700
@@ -30,8 +30,8 @@
  * Determines if the input objects match some criteria. This is the two-arity
  * specialization of {@link Predicate}.
  *
- * @param <T> the type of the first argument to {@code test}.
- * @param <U> the type of the second argument to {@code test}.
+ * @param <T> the type of the first argument to {@code test}
+ * @param <U> the type of the second argument to {@code test}
  *
  * @see Predicate
  * @since 1.8
@@ -42,9 +42,9 @@
     /**
      * Return {@code true} if the inputs match some criteria.
      *
-     * @param t an input object.
-     * @param u an input object.
-     * @return {@code true} if the inputs match some criteria.
+     * @param t an input object
+     * @param u an input object
+     * @return {@code true} if the inputs match some criteria
      */
     boolean test(T t, U u);
 
@@ -54,11 +54,12 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
+    default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
         Objects.requireNonNull(p);
         return (T t, U u) -> test(t, u) && p.test(t, u);
     }
@@ -67,9 +68,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default BiPredicate<T, U> negate() {
+    default BiPredicate<T, U> negate() {
         return (T t, U u) -> !test(t, u);
     }
 
@@ -79,25 +80,13 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
+    default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
         Objects.requireNonNull(p);
         return (T t, U u) -> test(t, u) || p.test(t, u);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     */
-    public default BiPredicate<T, U> xor(BiPredicate<? super T, ? super U> p) {
-        Objects.requireNonNull(p);
-        return (T t, U u) -> test(t, u) ^ p.test(t, u);
-    }
 }
--- a/src/share/classes/java/util/function/BooleanSupplier.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/BooleanSupplier.java	Wed Jun 05 00:37:11 2013 -0700
@@ -40,5 +40,5 @@
      *
      * @return a {@code boolean} value
      */
-    public boolean getAsBoolean();
+    boolean getAsBoolean();
 }
--- a/src/share/classes/java/util/function/Consumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/Consumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single input argument and returns no result.
  * Unlike most other functional interfaces, {@code Consumer} is expected to
@@ -41,5 +43,25 @@
      *
      * @param t the input object
      */
-    public void accept(T t);
+    void accept(T t);
+
+    /**
+     * Returns a {@code Consumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * the other {@code Consumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a Consumer which will be chained after this Consumer
+     * @return a Consumer which performs in sequence the {@code accept} method
+     * of this Consumer and the {@code accept} method of the specified Consumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default Consumer<T> chain(Consumer<? super T> other) {
+        Objects.requireNonNull(other);
+        return (T t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/src/share/classes/java/util/function/DoubleBinaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/DoubleBinaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -43,5 +43,5 @@
      * @param right the right operand value
      * @return the result of the operation
      */
-    public double applyAsDouble(double left, double right);
+    double applyAsDouble(double left, double right);
 }
--- a/src/share/classes/java/util/function/DoubleConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/DoubleConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single double argument and returns no result.
  * This is the primitive type specialization of {@link Consumer} for
@@ -41,5 +43,26 @@
      *
      * @param value the input value
      */
-    public void accept(double value);
+    void accept(double value);
+
+    /**
+     * Returns a {@code DoubleConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * another {@code DoubleConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a DoubleConsumer which will be chained after this
+     * DoubleConsumer
+     * @return an DoubleConsumer which performs in sequence the {@code accept} method
+     * of this DoubleConsumer and the {@code accept} method of the specified IntConsumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default DoubleConsumer chain(DoubleConsumer other) {
+        Objects.requireNonNull(other);
+        return (double t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/src/share/classes/java/util/function/DoubleFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/DoubleFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -43,5 +43,5 @@
      * @param value the input value
      * @return the function result
      */
-    public R apply(double value);
+    R apply(double value);
 }
--- a/src/share/classes/java/util/function/DoublePredicate.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/DoublePredicate.java	Wed Jun 05 00:37:11 2013 -0700
@@ -40,11 +40,11 @@
     /**
      * Returns {@code true} if the input value matches some criteria.
      *
-     * @param value the value to be tested.
+     * @param value the value to be tested
      * @return {@code true} if the input value matches some criteria, otherwise
-     * {@code false}.
+     * {@code false}
      */
-    public boolean test(double value);
+    boolean test(double value);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -52,11 +52,16 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default DoublePredicate and(DoublePredicate p) {
+    default DoublePredicate and(DoublePredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) && p.test(value);
     }
@@ -65,9 +70,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default DoublePredicate negate() {
+    default DoublePredicate negate() {
         return (value) -> !test(value);
     }
 
@@ -77,25 +82,17 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default DoublePredicate or(DoublePredicate p) {
+    default DoublePredicate or(DoublePredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) || p.test(value);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if all or none of the
-     * component predicates evaluate to {@code true}.
-     */
-    public default DoublePredicate xor(DoublePredicate p) {
-        Objects.requireNonNull(p);
-        return (value) -> test(value) ^ p.test(value);
-    }
 }
--- a/src/share/classes/java/util/function/DoubleSupplier.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/DoubleSupplier.java	Wed Jun 05 00:37:11 2013 -0700
@@ -39,5 +39,5 @@
      *
      * @return a {@code double} value
      */
-    public double getAsDouble();
+    double getAsDouble();
 }
--- a/src/share/classes/java/util/function/DoubleUnaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/DoubleUnaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation on a {@code double} operand yielding a {@code double}
  * result. This is the primitive type specialization of {@link UnaryOperator}
@@ -42,5 +44,46 @@
      * @param operand the operand value
      * @return the operation result value
      */
-    public double applyAsDouble(double operand);
+    double applyAsDouble(double operand);
+
+    /**
+     * Compose a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param before An additional function to be applied before this function
+     * is applied
+     * @return A function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default DoubleUnaryOperator compose(DoubleUnaryOperator before) {
+        Objects.requireNonNull(before);
+        return (double v) -> applyAsDouble(before.applyAsDouble(v));
+    }
+
+    /**
+     * Compose a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param after An additional function to be applied after this function is
+     * applied
+     * @return A function which performs this function followed by the provided
+     * function followed
+     * @throws NullPointerException if after is null
+     */
+    default DoubleUnaryOperator andThen(DoubleUnaryOperator after) {
+        Objects.requireNonNull(after);
+        return (double t) -> after.applyAsDouble(applyAsDouble(t));
+    }
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static DoubleUnaryOperator identity() {
+        return t -> t;
+    }
 }
--- a/src/share/classes/java/util/function/Function.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/Function.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,14 +24,15 @@
  */
 package java.util.function;
 
+import java.util.Objects;
 
 /**
  * Apply a function to the input argument, yielding an appropriate result.  A
  * function may variously provide a mapping between types, object instances or
  * keys and values or any other form of transformation upon the input.
  *
- * @param <T> the type of the input to the {@code apply} operation.
- * @param <R> the type of the result of the {@code apply} operation.
+ * @param <T> the type of the input to the {@code apply} operation
+ * @param <R> the type of the result of the {@code apply} operation
  *
  * @since 1.8
  */
@@ -44,5 +45,50 @@
      * @param t the input object
      * @return the function result
      */
-    public R apply(T t);
+    R apply(T t);
+
+    /**
+     * Returns a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param <V> type of input objects to the combined function. May be the
+     * same type as {@code <T>} or {@code <R>}
+     * @param before an additional function to be applied before this function
+     * is applied
+     * @return a function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
+        Objects.requireNonNull(before);
+        return (V v) -> apply(before.apply(v));
+    }
+
+    /**
+     * Returns a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param <V> type of output objects to the combined function. May be the
+     * same type as {@code <T>} or {@code <R>}
+     * @param after an additional function to be applied after this function is
+     * applied
+     * @return a function which performs this function followed by the provided
+     * function
+     * @throws NullPointerException if after is null
+     */
+    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
+        Objects.requireNonNull(after);
+        return (T t) -> after.apply(apply(t));
+    }
+
+    /**
+     * Returns a {@code Function} whose {@code apply} method returns its input.
+     *
+     * @param <T> the type of the input and output objects to the function
+     */
+    static <T> Function<T, T> identity() {
+        return t -> t;
+    }
 }
--- a/src/share/classes/java/util/function/IntBinaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/IntBinaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -44,5 +44,5 @@
      * @param right  the right operand value
      * @return the result of the operation
      */
-    public int applyAsInt(int left, int right);
+    int applyAsInt(int left, int right);
 }
--- a/src/share/classes/java/util/function/IntConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/IntConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single integer argument and returns no result.
  * This is the primitive type specialization of {@link Consumer} for {@code int}.
@@ -41,5 +43,26 @@
      *
      * @param value the input value
      */
-    public void accept(int value);
+    void accept(int value);
+
+    /**
+     * Returns an {@code IntConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * another {@code IntConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other an IntConsumer which will be chained after this
+     * IntConsumer
+     * @return an IntConsumer which performs in sequence the {@code accept} method
+     * of this IntConsumer and the {@code accept} method of the specified IntConsumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default IntConsumer chain(IntConsumer other) {
+        Objects.requireNonNull(other);
+        return (int t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/src/share/classes/java/util/function/IntFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/IntFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -43,5 +43,5 @@
      * @param value the input value
      * @return the function result
      */
-    public R apply(int value);
+    R apply(int value);
 }
--- a/src/share/classes/java/util/function/IntPredicate.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/IntPredicate.java	Wed Jun 05 00:37:11 2013 -0700
@@ -39,11 +39,11 @@
     /**
      * Returns {@code true} if the input value matches some criteria.
      *
-     * @param value the value to be tested.
+     * @param value the value to be tested
      * @return {@code true} if the input value matches some criteria, otherwise
      * {@code false}
      */
-    public boolean test(int value);
+    boolean test(int value);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default IntPredicate and(IntPredicate p) {
+    default IntPredicate and(IntPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) && p.test(value);
     }
@@ -64,9 +69,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default IntPredicate negate() {
+    default IntPredicate negate() {
         return (value) -> !test(value);
     }
 
@@ -76,25 +81,17 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default IntPredicate or(IntPredicate p) {
+    default IntPredicate or(IntPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) || p.test(value);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}
-     */
-    public default IntPredicate xor(IntPredicate p) {
-        Objects.requireNonNull(p);
-        return (value) -> test(value) ^ p.test(value);
-    }
 }
--- a/src/share/classes/java/util/function/IntSupplier.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/IntSupplier.java	Wed Jun 05 00:37:11 2013 -0700
@@ -39,5 +39,5 @@
      *
      * @return an {@code int} value
      */
-    public int getAsInt();
+    int getAsInt();
 }
--- a/src/share/classes/java/util/function/IntUnaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/IntUnaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation on a single {@code int} operand yielding an {@code int} result.
  * This is the primitive type specialization of {@link UnaryOperator} for
@@ -37,10 +39,51 @@
 
     /**
      * Returns the {@code int} value result of the operation upon the
-     * {@code int}  operand.
+     * {@code int} operand.
      *
      * @param operand the operand value
      * @return the operation result value
      */
-    public int applyAsInt(int operand);
+    int applyAsInt(int operand);
+
+    /**
+     * Compose a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param before an additional function to be applied before this function
+     * is applied
+     * @return a function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default IntUnaryOperator compose(IntUnaryOperator before) {
+        Objects.requireNonNull(before);
+        return (int v) -> applyAsInt(before.applyAsInt(v));
+    }
+
+    /**
+     * Compose a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param after an additional function to be applied after this function is
+     * applied
+     * @return a function which performs this function followed by the provided
+     * function followed
+     * @throws NullPointerException if after is null
+     */
+    default IntUnaryOperator andThen(IntUnaryOperator after) {
+        Objects.requireNonNull(after);
+        return (int t) -> after.applyAsInt(applyAsInt(t));
+    }
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static IntUnaryOperator identity() {
+        return t -> t;
+    }
 }
--- a/src/share/classes/java/util/function/LongBinaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/LongBinaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -44,5 +44,5 @@
      * @param right  the right operand value
      * @return the result of the operation
      */
-    public long applyAsLong(long left, long right);
+    long applyAsLong(long left, long right);
 }
--- a/src/share/classes/java/util/function/LongConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/LongConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation which accepts a single long argument and returns no result.
  * This is the {@code long}-consuming primitive type specialization of
@@ -41,5 +43,26 @@
      *
      * @param value the input value
      */
-    public void accept(long value);
+    void accept(long value);
+
+    /**
+     * Returns a {@code LongConsumer} which performs, in sequence, the operation
+     * represented by this object followed by the operation represented by
+     * another {@code LongConsumer}.
+     *
+     * <p>Any exceptions thrown by either {@code accept} method are relayed
+     * to the caller; if performing this operation throws an exception, the
+     * other operation will not be performed.
+     *
+     * @param other a LongConsumer which will be chained after this
+     * LongConsumer
+     * @return a LongConsumer which performs in sequence the {@code accept} method
+     * of this LongConsumer and the {@code accept} method of the specified LongConsumer
+     * operation
+     * @throws NullPointerException if other is null
+     */
+    default LongConsumer chain(LongConsumer other) {
+        Objects.requireNonNull(other);
+        return (long t) -> { accept(t); other.accept(t); };
+    }
 }
--- a/src/share/classes/java/util/function/LongFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/LongFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -43,5 +43,5 @@
      * @param value the input value
      * @return the function result
      */
-    public R apply(long value);
+    R apply(long value);
 }
--- a/src/share/classes/java/util/function/LongPredicate.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/LongPredicate.java	Wed Jun 05 00:37:11 2013 -0700
@@ -39,11 +39,11 @@
     /**
      * Returns {@code true} if the input value matches some criteria.
      *
-     * @param value the value to be tested.
+     * @param value the value to be tested
      * @return {@code true} if the input value matches some criteria, otherwise
-     * {@code false}.
+     * {@code false}
      */
-    public boolean test(long value);
+    boolean test(long value);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,15 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
      */
-    public default LongPredicate and(LongPredicate p) {
+    default LongPredicate and(LongPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) && p.test(value);
     }
@@ -64,9 +68,9 @@
      * Returns a predicate which negates the result of this predicate.
      *
      * @return a new predicate who's result is always the opposite of this
-     * predicate.
+     * predicate
      */
-    public default LongPredicate negate() {
+    default LongPredicate negate() {
         return (value) -> !test(value);
     }
 
@@ -76,25 +80,17 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default LongPredicate or(LongPredicate p) {
+    default LongPredicate or(LongPredicate p) {
         Objects.requireNonNull(p);
         return (value) -> test(value) || p.test(value);
     }
-
-    /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     *
-     * @param p a predicate which will be logically-XORed with this predicate.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
-     */
-    public default LongPredicate xor(LongPredicate p) {
-        Objects.requireNonNull(p);
-        return (value) -> test(value) ^ p.test(value);
-    }
 }
--- a/src/share/classes/java/util/function/LongSupplier.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/LongSupplier.java	Wed Jun 05 00:37:11 2013 -0700
@@ -39,5 +39,5 @@
      *
      * @return a {@code long} value
      */
-    public long getAsLong();
+    long getAsLong();
 }
--- a/src/share/classes/java/util/function/LongUnaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/LongUnaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -24,6 +24,8 @@
  */
 package java.util.function;
 
+import java.util.Objects;
+
 /**
  * An operation on a single {@code long} operand yielding a {@code long} result.
  * This is the primitive type specialization of {@link UnaryOperator} for
@@ -42,5 +44,46 @@
      * @param operand the operand value
      * @return the operation result value
      */
-    public long applyAsLong(long operand);
+    long applyAsLong(long operand);
+
+    /**
+     * Compose a new function which applies the provided function followed by
+     * this function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param before An additional function to be applied before this function
+     * is applied
+     * @return A function which performs the provided function followed by this
+     * function
+     * @throws NullPointerException if before is null
+     */
+    default LongUnaryOperator compose(LongUnaryOperator before) {
+        Objects.requireNonNull(before);
+        return (long v) -> applyAsLong(before.applyAsLong(v));
+    }
+
+    /**
+     * Compose a new function which applies this function followed by the
+     * provided function.  If either function throws an exception, it is relayed
+     * to the caller.
+     *
+     * @param after An additional function to be applied after this function is
+     * applied
+     * @return A function which performs this function followed by the provided
+     * function followed
+     * @throws NullPointerException if after is null
+     */
+    default LongUnaryOperator andThen(LongUnaryOperator after) {
+        Objects.requireNonNull(after);
+        return (long t) -> after.applyAsLong(applyAsLong(t));
+    }
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static LongUnaryOperator identity() {
+        return t -> t;
+    }
 }
--- a/src/share/classes/java/util/function/ObjDoubleConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ObjDoubleConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -44,5 +44,5 @@
      * @param t an input object
      * @param value an input value
      */
-    public void accept(T t, double value);
+    void accept(T t, double value);
 }
--- a/src/share/classes/java/util/function/ObjIntConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ObjIntConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -30,7 +30,7 @@
  * {@link BiConsumer}. Unlike most other functional interfaces,
  * {@code ObjIntConsumer} is expected to operate via side-effects.
  *
- * @param <T> Type of reference argument to {@code accept()}.
+ * @param <T> Type of reference argument to {@code accept()}
  *
  * @see BiConsumer
  * @since 1.8
@@ -44,5 +44,5 @@
      * @param t an input object
      * @param value an input value
      */
-    public void accept(T t, int value);
+    void accept(T t, int value);
 }
--- a/src/share/classes/java/util/function/ObjLongConsumer.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ObjLongConsumer.java	Wed Jun 05 00:37:11 2013 -0700
@@ -30,7 +30,7 @@
  * {@link BiConsumer}. Unlike most other functional interfaces,
  * {@code ObjLongConsumer} is expected to operate via side-effects.
  *
- * @param <T> Type of reference argument to {@code accept()}.
+ * @param <T> Type of reference argument to {@code accept()}
  *
  * @see BiConsumer
  * @since 1.8
@@ -44,5 +44,5 @@
      * @param t an input object
      * @param value an input value
      */
-    public void accept(T t, long value);
+    void accept(T t, long value);
 }
--- a/src/share/classes/java/util/function/Predicate.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/Predicate.java	Wed Jun 05 00:37:11 2013 -0700
@@ -43,7 +43,7 @@
      * @return {@code true} if the input object matches some criteria, otherwise
      * {@code false}
      */
-    public boolean test(T t);
+    boolean test(T t);
 
     /**
      * Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@
      * this predicate returns {@code false} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ANDed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ANDed with this predicate
      * @return a new predicate which returns {@code true} only if both
-     * predicates return {@code true}.
+     * predicates return {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default Predicate<T> and(Predicate<? super T> p) {
+    default Predicate<T> and(Predicate<? super T> p) {
         Objects.requireNonNull(p);
         return (t) -> test(t) && p.test(t);
     }
@@ -66,7 +71,7 @@
      * @return a new predicate who's result is always the opposite of this
      * predicate.
      */
-    public default Predicate<T> negate() {
+    default Predicate<T> negate() {
         return (t) -> !test(t);
     }
 
@@ -76,25 +81,32 @@
      * predicate returns {@code true} then the remaining predicate is not
      * evaluated.
      *
-     * @param p a predicate which will be logically-ORed with this predicate.
+     * <p>Any exceptions thrown by either {@code test} method are relayed
+     * to the caller; if performing first operation throws an exception, the
+     * second operation will not be performed.
+     *
+     * @param p a predicate which will be logically-ORed with this predicate
      * @return a new predicate which returns {@code true} if either predicate
-     * returns {@code true}.
+     * returns {@code true}
+     * @throws NullPointerException if p is null
      */
-    public default Predicate<T> or(Predicate<? super T> p) {
+    default Predicate<T> or(Predicate<? super T> p) {
         Objects.requireNonNull(p);
         return (t) -> test(t) || p.test(t);
     }
 
     /**
-     * Returns a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
+     * Returns a predicate who's result matches
+     * {@code Objects.equals(target, t)}.
      *
-     * @param p a predicate which will be logically-XORed with this predicte.
-     * @return a predicate that evaluates to {@code true} if both or neither of
-     * the component predicates evaluate to {@code true}.
+     * @param <T> the type of values evaluated by the predicate
+     * @param target the target value to be compared for equality
+     * @return a predicate who's result matches
+     * {@code Objects.equals(target, t)}
      */
-    public default Predicate<T> xor(Predicate<? super T> p) {
-        Objects.requireNonNull(p);
-        return (t) -> test(t) ^ p.test(t);
+    static <T> Predicate<T> isEqual(Object target) {
+        return (null == target)
+                ? Objects::isNull
+                : object -> target.equals(object);
     }
 }
--- a/src/share/classes/java/util/function/Supplier.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/Supplier.java	Wed Jun 05 00:37:11 2013 -0700
@@ -40,5 +40,5 @@
      *
      * @return an object
      */
-    public T get();
+    T get();
 }
--- a/src/share/classes/java/util/function/ToDoubleBiFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ToDoubleBiFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -46,5 +46,5 @@
      * @param u an input object
      * @return the function result value
      */
-    public double applyAsDouble(T t, U u);
+    double applyAsDouble(T t, U u);
 }
--- a/src/share/classes/java/util/function/ToDoubleFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ToDoubleFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -42,5 +42,5 @@
      * @param t the input object
      * @return the function result value
      */
-    public double applyAsDouble(T t);
+    double applyAsDouble(T t);
 }
--- a/src/share/classes/java/util/function/ToIntBiFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ToIntBiFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -28,10 +28,10 @@
  * Apply a function to the input arguments, yielding an appropriate result.
  * This is the {@code int}-bearing specialization for {@link BiFunction}.
  *
- * @param <T> the type of the first argument to the {@code applyAsLong}
- * operation.
- * @param <U> the type of the second argument to the {@code applyAsLong}
- * operation.
+ * @param <T> the type of the first argument to the {@code applyAsInt}
+ * operation
+ * @param <U> the type of the second argument to the {@code applyAsInt}
+ * operation
  *
  * @see BiFunction
  * @since 1.8
@@ -46,5 +46,5 @@
      * @param u an input object
      * @return the function result value
      */
-    public int applyAsInt(T t, U u);
+    int applyAsInt(T t, U u);
 }
--- a/src/share/classes/java/util/function/ToIntFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ToIntFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -42,5 +42,5 @@
      * @param t the input object
      * @return the function result value
      */
-    public int applyAsInt(T t);
+    int applyAsInt(T t);
 }
--- a/src/share/classes/java/util/function/ToLongBiFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ToLongBiFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -46,5 +46,5 @@
      * @param u an input object
      * @return the function result value
      */
-    public long applyAsLong(T t, U u);
+    long applyAsLong(T t, U u);
 }
--- a/src/share/classes/java/util/function/ToLongFunction.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/ToLongFunction.java	Wed Jun 05 00:37:11 2013 -0700
@@ -42,5 +42,5 @@
      * @param t the input object
      * @return the function result value
      */
-    public long applyAsLong(T t);
+    long applyAsLong(T t);
 }
--- a/src/share/classes/java/util/function/UnaryOperator.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/java/util/function/UnaryOperator.java	Wed Jun 05 00:37:11 2013 -0700
@@ -36,4 +36,13 @@
  */
 @FunctionalInterface
 public interface UnaryOperator<T> extends Function<T, T> {
+
+    /**
+     * Returns a unary operator that provides its input value as the result.
+     *
+     * @return a unary operator that provides its input value as the result
+     */
+    static <T> UnaryOperator<T> identity() {
+        return t -> t;
+    }
 }
--- a/src/share/classes/sun/management/Agent.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/management/Agent.java	Wed Jun 05 00:37:11 2013 -0700
@@ -77,7 +77,7 @@
     private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
             "sun.management.snmp.AdaptorBootstrap";
 
-    private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
+    private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
     private static final int JDP_DEFAULT_PORT = 7095;
 
     // The only active agent allowed
--- a/src/share/classes/sun/management/jdp/package-info.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/management/jdp/package-info.java	Wed Jun 05 00:37:11 2013 -0700
@@ -60,7 +60,7 @@
  *
  * - `INSTANCE_NAME` -- The user-provided name of the running instance
  *
- * The protocol sends packets to 239.255.255.225:7095 by default.
+ * The protocol sends packets to 224.0.23.178:7095 by default.
  *
  * The protocol uses system properties to control it's behaviour:
  * - `com.sun.management.jdp.port` -- override default port
--- a/src/share/classes/sun/nio/cs/UTF_8.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/nio/cs/UTF_8.java	Wed Jun 05 00:37:11 2013 -0700
@@ -682,6 +682,11 @@
                 return encodeBufferLoop(src, dst);
         }
 
+        private byte repl = (byte)'?';
+        protected void implReplaceWith(byte[] newReplacement) {
+            repl = newReplacement[0];
+        }
+
         // returns -1 if there is malformed char(s) and the
         // "action" for malformed input is not REPLACE.
         public int encode(char[] sa, int sp, int len, byte[] da) {
@@ -709,7 +714,7 @@
                     if (uc < 0) {
                         if (malformedInputAction() != CodingErrorAction.REPLACE)
                             return -1;
-                        da[dp++] = replacement()[0];
+                        da[dp++] = repl;
                     } else {
                         da[dp++] = (byte)(0xf0 | ((uc >> 18)));
                         da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
--- a/src/share/classes/sun/nio/cs/ext/DoubleByte.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/nio/cs/ext/DoubleByte.java	Wed Jun 05 00:37:11 2013 -0700
@@ -610,6 +610,11 @@
                 return encodeBufferLoop(src, dst);
         }
 
+        protected byte[] repl = replacement();
+        protected void implReplaceWith(byte[] newReplacement) {
+            repl = newReplacement;
+        }
+
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -622,7 +627,6 @@
                         Character.isLowSurrogate(src[sp])) {
                         sp++;
                     }
-                    byte[] repl = replacement();
                     dst[dp++] = repl[0];
                     if (repl.length > 1)
                         dst[dp++] = repl[1];
@@ -877,7 +881,6 @@
                         Character.isLowSurrogate(src[sp])) {
                         sp++;
                     }
-                    byte[] repl = replacement();
                     dst[dp++] = repl[0];
                     if (repl.length > 1)
                         dst[dp++] = repl[1];
--- a/src/share/classes/sun/nio/cs/ext/HKSCS.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/nio/cs/ext/HKSCS.java	Wed Jun 05 00:37:11 2013 -0700
@@ -356,6 +356,11 @@
                 return encodeBufferLoop(src, dst);
         }
 
+        private byte[] repl = replacement();
+        protected void implReplaceWith(byte[] newReplacement) {
+            repl = newReplacement;
+        }
+
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -367,7 +372,6 @@
                         !Character.isLowSurrogate(src[sp]) ||
                         (bb = encodeSupp(Character.toCodePoint(c, src[sp++])))
                         == UNMAPPABLE_ENCODING) {
-                        byte[] repl = replacement();
                         dst[dp++] = repl[0];
                         if (repl.length > 1)
                             dst[dp++] = repl[1];
--- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jun 05 00:37:11 2013 -0700
@@ -78,7 +78,7 @@
 
     private final String tabName;
     private long lastModified;
-    private int kt_vno;
+    private int kt_vno = KRB5_KT_VNO;
 
     private Vector<KeyTabEntry> entries = new Vector<>();
 
--- a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed Jun 05 00:37:11 2013 -0700
@@ -552,7 +552,7 @@
 
         try {
             Signature respSignature = Signature.getInstance(sigAlgId.getName());
-            respSignature.initVerify(cert);
+            respSignature.initVerify(cert.getPublicKey());
             respSignature.update(tbsResponseData);
 
             if (respSignature.verify(signature)) {
--- a/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1447,6 +1447,7 @@
         PERM_ARRAY.add(new AWTPerm());
         PERM_ARRAY.add(new DelegationPerm());
         PERM_ARRAY.add(new FilePerm());
+        PERM_ARRAY.add(new HttpURLPerm());
         PERM_ARRAY.add(new InqSecContextPerm());
         PERM_ARRAY.add(new LogPerm());
         PERM_ARRAY.add(new MgmtPerm());
@@ -3842,6 +3843,20 @@
     }
 }
 
+class HttpURLPerm extends Perm {
+    public HttpURLPerm() {
+        super("HttpURLPermission",
+                "java.net.HttpURLPermission",
+                new String[]    {
+                    "<"+ PolicyTool.rb.getString("url") + ">",
+                },
+                new String[]    {
+                    "<" + PolicyTool.rb.getString("method.list") + ">:<"
+                        + PolicyTool.rb.getString("request.headers.list") + ">",
+                });
+    }
+}
+
 class InqSecContextPerm extends Perm {
     public InqSecContextPerm() {
     super("InquireSecContextPermission",
--- a/src/share/classes/sun/security/tools/policytool/Resources.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/security/tools/policytool/Resources.java	Wed Jun 05 00:37:11 2013 -0700
@@ -139,6 +139,9 @@
         {"policy.type", "policy type"},
         {"property.name", "property name"},
         {"provider.name", "provider name"},
+        {"url", "url"},
+        {"method.list", "method list"},
+        {"request.headers.list", "request headers list"},
         {"Principal.List", "Principal List"},
         {"Permission.List", "Permission List"},
         {"Code.Base", "Code Base"},
--- a/src/share/classes/sun/text/resources/mt/FormatData_mt.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/text/resources/mt/FormatData_mt.java	Wed Jun 05 00:37:11 2013 -0700
@@ -54,7 +54,7 @@
                     "Mejju",
                     "\u0120unju",
                     "Lulju",
-                    "Awissu",
+                    "Awwissu",
                     "Settembru",
                     "Ottubru",
                     "Novembru",
@@ -71,7 +71,7 @@
                     "Mej",
                     "\u0120un",
                     "Lul",
-                    "Awi",
+                    "Aww",
                     "Set",
                     "Ott",
                     "Nov",
--- a/src/share/classes/sun/tools/jconsole/AboutDialog.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/tools/jconsole/AboutDialog.java	Wed Jun 05 00:37:11 2013 -0700
@@ -34,6 +34,7 @@
 import javax.swing.border.*;
 import javax.swing.event.*;
 
+import static sun.misc.Version.jdkMinorVersion;
 
 import static java.awt.BorderLayout.*;
 import static sun.tools.jconsole.Utilities.*;
@@ -73,7 +74,7 @@
         String jConsoleVersion = Version.getVersion();
         String vmName = System.getProperty("java.vm.name");
         String vmVersion = System.getProperty("java.vm.version");
-        String urlStr = Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
+        String urlStr = getOnlineDocUrl();
         if (isBrowseSupported()) {
             urlStr = "<a style='color:#35556b' href=\"" + urlStr + "\">" + urlStr + "</a>";
         }
@@ -86,8 +87,7 @@
                                 "<html><font color=#"+ colorStr + ">" +
                         Resources.format(Messages.HELP_ABOUT_DIALOG_JCONSOLE_VERSION, jConsoleVersion) +
                 "<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_JAVA_VERSION, (vmName +", "+ vmVersion)) +
-                "<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK, urlStr) +
-                                                 "</html>");
+                "<p>" + urlStr + "</html>");
         helpLink.setOpaque(false);
         helpLink.setEditable(false);
         helpLink.setForeground(textColor);
@@ -153,7 +153,7 @@
     }
 
     static void browseUserGuide(JConsole jConsole) {
-        getAboutDialog(jConsole).browse(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL);
+        getAboutDialog(jConsole).browse(getOnlineDocUrl());
     }
 
     static boolean isBrowseSupported() {
@@ -182,6 +182,12 @@
         };
     }
 
+    private static String getOnlineDocUrl() {
+        String version = Integer.toString(jdkMinorVersion());
+        return Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL,
+                                version);
+    }
+
     private static class TPanel extends JPanel {
         TPanel(int hgap, int vgap) {
             super(new BorderLayout(hgap, vgap));
--- a/src/share/classes/sun/tools/jconsole/VMPanel.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/tools/jconsole/VMPanel.java	Wed Jun 05 00:37:11 2013 -0700
@@ -55,6 +55,7 @@
     private VMInternalFrame vmIF = null;
     private static ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
     private boolean wasConnected = false;
+    private boolean userDisconnected = false;
 
     // The everConnected flag keeps track of whether the window can be
     // closed if the user clicks Cancel after a failed connection attempt.
@@ -125,6 +126,7 @@
                 if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) {
 
                     if (isConnected()) {
+                        userDisconnected = true;
                         disconnect();
                         wasConnected = false;
                     } else {
@@ -452,6 +454,11 @@
     private void vmPanelDied() {
         disconnect();
 
+        if (userDisconnected) {
+            userDisconnected = false;
+            return;
+        }
+
         JOptionPane optionPane;
         String msgTitle, msgExplanation, buttonStr;
 
--- a/src/share/classes/sun/tools/jconsole/resources/messages.properties	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/tools/jconsole/resources/messages.properties	Wed Jun 05 00:37:11 2013 -0700
@@ -105,7 +105,7 @@
 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=About JConsole
 HELP_ABOUT_DIALOG_TITLE=JConsole: About
 HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole &User Guide:<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
 HELP_MENU_ABOUT_TITLE=&About JConsole
 HELP_MENU_USER_GUIDE_TITLE=Online &User Guide
 HELP_MENU_TITLE=&Help
--- a/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties	Wed Jun 05 00:37:11 2013 -0700
@@ -105,7 +105,7 @@
 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=JConsole\u306B\u3064\u3044\u3066
 HELP_ABOUT_DIALOG_TITLE=JConsole: \u8A73\u7D30
 HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U):<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
 HELP_MENU_ABOUT_TITLE=JConsole\u306B\u3064\u3044\u3066(&A)
 HELP_MENU_USER_GUIDE_TITLE=\u30AA\u30F3\u30E9\u30A4\u30F3\u30FB\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U)
 HELP_MENU_TITLE=\u30D8\u30EB\u30D7(&H)
--- a/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties	Wed Jun 05 00:37:11 2013 -0700
@@ -105,7 +105,7 @@
 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=\u5173\u4E8E JConsole
 HELP_ABOUT_DIALOG_TITLE=JConsole: \u5173\u4E8E
 HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole \u7528\u6237\u6307\u5357(&U):<br>{0}
-HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
+HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
 HELP_MENU_ABOUT_TITLE=\u5173\u4E8E JConsole(&A)
 HELP_MENU_USER_GUIDE_TITLE=\u8054\u673A\u7528\u6237\u6307\u5357(&U)
 HELP_MENU_TITLE=\u5E2E\u52A9(&H)
--- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1085,13 +1085,13 @@
     }
 
     // Creates a new empty temporary file in the same directory as the
-    // specified file.  A variant of File.createTempFile.
+    // specified file.  A variant of Files.createTempFile.
     private Path createTempFileInSameDirectoryAs(Path path)
         throws IOException
     {
         Path parent = path.toAbsolutePath().getParent();
-        String dir = (parent == null)? "." : parent.toString();
-        Path tmpPath = File.createTempFile("zipfstmp", null, new File(dir)).toPath();
+        Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
+        Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
         tmppaths.add(tmpPath);
         return tmpPath;
     }
--- a/src/share/native/java/io/FileInputStream.c	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/native/java/io/FileInputStream.c	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -100,6 +100,8 @@
     if (IO_Available(fd, &ret)) {
         if (ret > INT_MAX) {
             ret = (jlong) INT_MAX;
+        } else if (ret < 0) {
+            ret = 0;
         }
         return jlong_to_jint(ret);
     }
--- a/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Wed Jun 05 00:37:11 2013 -0700
@@ -634,6 +634,8 @@
     cmsFloat64Number dnum = 0.0;
     int sign = 1;
 
+    if (Buffer == NULL) return 0.0;
+
     if (*Buffer == '-' || *Buffer == '+') {
 
          sign = (*Buffer == '-') ? -1 : 1;
--- a/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Wed Jun 05 00:37:11 2013 -0700
@@ -1021,6 +1021,8 @@
     mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
     cmsFreeToneCurveTriple(LabTable);
 
+    if (mpe == NULL) return NULL;
+
     mpe ->Implements = cmsSigLabV2toV4;
     return mpe;
 }
--- a/src/solaris/bin/arm/jvm.cfg	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/solaris/bin/arm/jvm.cfg	Wed Jun 05 00:37:11 2013 -0700
@@ -30,6 +30,6 @@
 # "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
 # and may not be available in a future release.
 #
--client KNOWN
+-client IF_SERVER_CLASS -server
 -server KNOWN
 -minimal KNOWN
--- a/src/solaris/classes/sun/print/IPPPrintService.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/solaris/classes/sun/print/IPPPrintService.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1023,6 +1023,13 @@
 
             // this is already supported in UnixPrintJob
             catList.add(Destination.class);
+
+            // It is unfortunate that CUPS doesn't provide a way to query
+            // if printer supports collation but since most printers
+            // now supports collation and that most OS has a way
+            // of setting it, it is a safe assumption to just always
+            // include SheetCollate as supported attribute.
+            catList.add(SheetCollate.class);
         }
 
         // With the assumption that  Chromaticity is equivalent to
--- a/src/windows/bin/cmdtoargs.c	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/bin/cmdtoargs.c	Wed Jun 05 00:37:11 2013 -0700
@@ -128,7 +128,9 @@
                 *wildcard = JNI_TRUE;
             }
             if (prev == '\\') {
-                *dest++ = prev;
+                for (i = 0 ; i < slashes ; i++) {
+                    *dest++ = prev;
+                }
             }
             *dest++ = ch;
             break;
@@ -184,7 +186,7 @@
         argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg));
         argv[nargs].arg = JLI_StringDup(arg);
         argv[nargs].has_wildcard = wildcard;
-
+        *arg = NULL;
         nargs++;
     } while (src != NULL);
 
@@ -602,6 +604,14 @@
     v->add("d", FALSE);
     vectors[i++] = v;
 
+    v= new Vector(argv[0], "\\\\?");
+    v->add("\\\\?", TRUE);
+    vectors[i++] = v;
+
+    v= new Vector(argv[0], "\\\\*");
+    v->add("\\\\*", TRUE);
+    vectors[i++] = v;
+
     dotest(vectors);
     printf("All tests pass [%d]\n", i);
     doexit(0);
--- a/src/windows/classes/sun/awt/windows/WPathGraphics.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/classes/sun/awt/windows/WPathGraphics.java	Wed Jun 05 00:37:11 2013 -0700
@@ -549,6 +549,8 @@
                 userx += xAdvance;
                 userpos.x += xAdvance;
                 deviceTransform.transform(userpos, devpos);
+                devx = devpos.x;
+                devy = devpos.y;
             }
         } else {
             super.drawString(str, x, y, font, frc, targetW);
--- a/src/windows/classes/sun/nio/fs/WindowsConstants.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/classes/sun/nio/fs/WindowsConstants.java	Wed Jun 05 00:37:11 2013 -0700
@@ -100,6 +100,7 @@
     public static final int ERROR_INVALID_LEVEL         = 124;
     public static final int ERROR_DIR_NOT_EMPTY         = 145;
     public static final int ERROR_ALREADY_EXISTS        = 183;
+    public static final int ERROR_MORE_DATA             = 234;
     public static final int ERROR_DIRECTORY             = 267;
     public static final int ERROR_NOTIFY_ENUM_DIR       = 1022;
     public static final int ERROR_NONE_MAPPED           = 1332;
--- a/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Wed Jun 05 00:37:11 2013 -0700
@@ -973,19 +973,19 @@
      * HANDLE CreateIoCompletionPort (
      *   HANDLE FileHandle,
      *   HANDLE ExistingCompletionPort,
-     *   DWORD CompletionKey,
+     *   ULONG_PTR CompletionKey,
      *   DWORD NumberOfConcurrentThreads
      * )
      */
     static native long CreateIoCompletionPort(long fileHandle, long existingPort,
-        int completionKey) throws WindowsException;
+        long completionKey) throws WindowsException;
 
 
     /**
      * GetQueuedCompletionStatus(
      *   HANDLE CompletionPort,
      *   LPDWORD lpNumberOfBytesTransferred,
-     *   LPDWORD lpCompletionKey,
+     *   PULONG_PTR lpCompletionKey,
      *   LPOVERLAPPED *lpOverlapped,
      *   DWORD dwMilliseconds
      */
@@ -999,12 +999,12 @@
     static class CompletionStatus {
         private int error;
         private int bytesTransferred;
-        private int completionKey;
+        private long completionKey;
         private CompletionStatus() { }
 
         int error() { return error; }
         int bytesTransferred() { return bytesTransferred; }
-        int completionKey() { return completionKey; }
+        long completionKey() { return completionKey; }
     }
     private static native void GetQueuedCompletionStatus0(long completionPort,
         CompletionStatus status) throws WindowsException;
@@ -1013,12 +1013,12 @@
      * PostQueuedCompletionStatus(
      *   HANDLE CompletionPort,
      *   DWORD dwNumberOfBytesTransferred,
-     *   DWORD dwCompletionKey,
+     *   ULONG_PTR dwCompletionKey,
      *   LPOVERLAPPED lpOverlapped
      * )
      */
     static native void PostQueuedCompletionStatus(long completionPort,
-        int completionKey) throws WindowsException;
+        long completionKey) throws WindowsException;
 
     /**
      * ReadDirectoryChangesW(
--- a/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jun 05 00:37:11 2013 -0700
@@ -41,6 +41,7 @@
 class WindowsWatchService
     extends AbstractWatchService
 {
+    private final static int WAKEUP_COMPLETION_KEY = 0;
     private final Unsafe unsafe = Unsafe.getUnsafe();
 
     // background thread to service I/O completion port
@@ -83,7 +84,7 @@
      */
     private class WindowsWatchKey extends AbstractWatchKey {
         // file key (used to detect existing registrations)
-        private FileKey fileKey;
+        private final FileKey fileKey;
 
         // handle to directory
         private volatile long handle = INVALID_HANDLE_VALUE;
@@ -223,8 +224,7 @@
             FileKey other = (FileKey)obj;
             if (this.volSerialNumber != other.volSerialNumber) return false;
             if (this.fileIndexHigh != other.fileIndexHigh) return false;
-            if (this.fileIndexLow != other.fileIndexLow) return false;
-            return true;
+            return this.fileIndexLow == other.fileIndexLow;
         }
     }
 
@@ -268,6 +268,7 @@
         private static final short OFFSETOF_FILENAME        = 12;
 
         // size of per-directory buffer for events (FIXME - make this configurable)
+        // Need to be less than 4*16384 = 65536. DWORD align.
         private static final int CHANGES_BUFFER_SIZE    = 16 * 1024;
 
         private final WindowsFileSystem fs;
@@ -275,27 +276,28 @@
         private final long port;
 
         // maps completion key to WatchKey
-        private final Map<Integer,WindowsWatchKey> int2key;
+        private final Map<Integer,WindowsWatchKey> ck2key;
 
         // maps file key to WatchKey
         private final Map<FileKey,WindowsWatchKey> fk2key;
 
         // unique completion key for each directory
+        // native completion key capacity is 64 bits on Win64.
         private int lastCompletionKey;
 
         Poller(WindowsFileSystem fs, WindowsWatchService watcher, long port) {
             this.fs = fs;
             this.watcher = watcher;
             this.port = port;
-            this.int2key = new HashMap<Integer,WindowsWatchKey>();
-            this.fk2key = new HashMap<FileKey,WindowsWatchKey>();
+            this.ck2key = new HashMap<>();
+            this.fk2key = new HashMap<>();
             this.lastCompletionKey = 0;
         }
 
         @Override
         void wakeup() throws IOException {
             try {
-                PostQueuedCompletionStatus(port, 0);
+                PostQueuedCompletionStatus(port, WAKEUP_COMPLETION_KEY);
             } catch (WindowsException x) {
                 throw new IOException(x.getMessage());
             }
@@ -322,7 +324,6 @@
             for (WatchEvent.Modifier modifier: modifiers) {
                 if (modifier == ExtendedWatchEventModifier.FILE_TREE) {
                     watchSubtree = true;
-                    continue;
                 } else {
                     if (modifier == null)
                         return new NullPointerException();
@@ -333,7 +334,7 @@
             }
 
             // open directory
-            long handle = -1L;
+            long handle;
             try {
                 handle = CreateFile(dir.getPathForWin32Calls(),
                                     FILE_LIST_DIRECTORY,
@@ -347,7 +348,7 @@
             boolean registered = false;
             try {
                 // read attributes and check file is a directory
-                WindowsFileAttributes attrs = null;
+                WindowsFileAttributes attrs;
                 try {
                     attrs = WindowsFileAttributes.readAttributes(handle);
                 } catch (WindowsException x) {
@@ -370,9 +371,10 @@
                     return existing;
                 }
 
-                // unique completion key (skip 0)
+                // Can overflow the int type capacity.
+                // Skip WAKEUP_COMPLETION_KEY value.
                 int completionKey = ++lastCompletionKey;
-                if (completionKey == 0)
+                if (completionKey == WAKEUP_COMPLETION_KEY)
                     completionKey = ++lastCompletionKey;
 
                 // associate handle with completion port
@@ -418,13 +420,13 @@
                     // 1. remove mapping from old completion key to existing watch key
                     // 2. release existing key's resources (handle/buffer)
                     // 3. re-initialize key with new handle/buffer
-                    int2key.remove(existing.completionKey());
+                    ck2key.remove(existing.completionKey());
                     existing.releaseResources();
                     watchKey = existing.init(handle, events, watchSubtree, buffer,
                         countAddress, overlappedAddress, completionKey);
                 }
                 // map completion map to watch key
-                int2key.put(completionKey, watchKey);
+                ck2key.put(completionKey, watchKey);
 
                 registered = true;
                 return watchKey;
@@ -440,7 +442,7 @@
             WindowsWatchKey key = (WindowsWatchKey)obj;
             if (key.isValid()) {
                 fk2key.remove(key.fileKey());
-                int2key.remove(key.completionKey());
+                ck2key.remove(key.completionKey());
                 key.invalidate();
             }
         }
@@ -449,11 +451,11 @@
         @Override
         void implCloseAll() {
             // cancel all keys
-            for (Map.Entry<Integer,WindowsWatchKey> entry: int2key.entrySet()) {
+            for (Map.Entry<Integer, WindowsWatchKey> entry: ck2key.entrySet()) {
                 entry.getValue().invalidate();
             }
             fk2key.clear();
-            int2key.clear();
+            ck2key.clear();
 
             // close I/O completion port
             CloseHandle(port);
@@ -517,7 +519,7 @@
         @Override
         public void run() {
             for (;;) {
-                CompletionStatus info = null;
+                CompletionStatus info;
                 try {
                     info = GetQueuedCompletionStatus(port);
                 } catch (WindowsException x) {
@@ -527,7 +529,7 @@
                 }
 
                 // wakeup
-                if (info.completionKey() == 0) {
+                if (info.completionKey() == WAKEUP_COMPLETION_KEY) {
                     boolean shutdown = processRequests();
                     if (shutdown) {
                         return;
@@ -536,7 +538,7 @@
                 }
 
                 // map completionKey to get WatchKey
-                WindowsWatchKey key = int2key.get(info.completionKey());
+                WindowsWatchKey key = ck2key.get((int)info.completionKey());
                 if (key == null) {
                     // We get here when a registration is changed. In that case
                     // the directory is closed which causes an event with the
@@ -544,38 +546,44 @@
                     continue;
                 }
 
-                // ReadDirectoryChangesW failed
-                if (info.error() != 0) {
+                boolean criticalError = false;
+                int errorCode = info.error();
+                int messageSize = info.bytesTransferred();
+                if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
                     // buffer overflow
-                    if (info.error() == ERROR_NOTIFY_ENUM_DIR) {
+                    key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
+                } else if (errorCode != 0 && errorCode != ERROR_MORE_DATA) {
+                    // ReadDirectoryChangesW failed
+                    criticalError = true;
+                } else {
+                    // ERROR_MORE_DATA is a warning about incomplite
+                    // data transfer over TCP/UDP stack. For the case
+                    // [messageSize] is zero in the most of cases.
+
+                    if (messageSize > 0) {
+                        // process non-empty events.
+                        processEvents(key, messageSize);
+                    } else if (errorCode == 0) {
+                        // insufficient buffer size
+                        // not described, but can happen.
                         key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
-                    } else {
-                        // other error so cancel key
-                        implCancelKey(key);
-                        key.signal();
                     }
-                    continue;
+
+                    // start read for next batch of changes
+                    try {
+                        ReadDirectoryChangesW(key.handle(),
+                                              key.buffer().address(),
+                                              CHANGES_BUFFER_SIZE,
+                                              key.watchSubtree(),
+                                              ALL_FILE_NOTIFY_EVENTS,
+                                              key.countAddress(),
+                                              key.overlappedAddress());
+                    } catch (WindowsException x) {
+                        // no choice but to cancel key
+                        criticalError = true;
+                    }
                 }
-
-                // process the events
-                if (info.bytesTransferred() > 0) {
-                    processEvents(key, info.bytesTransferred());
-                } else {
-                    // insufficient buffer size
-                    key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
-                }
-
-                // start read for next batch of changes
-                try {
-                    ReadDirectoryChangesW(key.handle(),
-                                          key.buffer().address(),
-                                          CHANGES_BUFFER_SIZE,
-                                          key.watchSubtree(),
-                                          ALL_FILE_NOTIFY_EVENTS,
-                                          key.countAddress(),
-                                          key.overlappedAddress());
-                } catch (WindowsException x) {
-                    // no choice but to cancel key
+                if (criticalError) {
                     implCancelKey(key);
                     key.signal();
                 }
--- a/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java	Wed Jun 05 00:37:11 2013 -0700
@@ -80,42 +80,24 @@
         } else {
             ktab.processArgs(args);
         }
-        try {
+        ktab.table = KeyTab.getInstance(ktab.name);
+        if (ktab.table.isMissing() && ktab.action != 'a') {
             if (ktab.name == null) {
-                //  ktab.admin = new KeyTabAdmin();    // use the default keytab.
-                ktab.table = KeyTab.getInstance();
-                if (ktab.table == null) {
-                    if (ktab.action == 'a') {
-                        ktab.table = KeyTab.create();
-                    } else {
-                        System.out.println("No default key table exists.");
-                        System.exit(-1);
-                    }
-                }
+                System.out.println("No default key table exists.");
             } else {
-                if ((ktab.action != 'a') &&
-                    !(new File(ktab.name)).exists()) {
-                    System.out.println("Key table " +
-                                ktab.name + " does not exist.");
-                    System.exit(-1);
-                } else {
-                    ktab.table = KeyTab.getInstance(ktab.name);
-                }
-                if (ktab.table == null) {
-                    if (ktab.action == 'a') {
-                        ktab.table = KeyTab.create(ktab.name);
-                    } else {
-                        System.out.println("The format of key table " +
-                                ktab.name + " is incorrect.");
-                        System.exit(-1);
-                    }
-                }
+                System.out.println("Key table " +
+                        ktab.name + " does not exist.");
             }
-        } catch (RealmException e) {
-            System.err.println("Error loading key table.");
             System.exit(-1);
-        } catch (IOException e) {
-            System.err.println("Error loading key table.");
+        }
+        if (!ktab.table.isValid()) {
+            if (ktab.name == null) {
+                System.out.println("The format of the default key table " +
+                        " is incorrect.");
+            } else {
+                System.out.println("The format of key table " +
+                        ktab.name + " is incorrect.");
+            }
             System.exit(-1);
         }
         switch (ktab.action) {
--- a/src/windows/native/java/io/WinNTFileSystem_md.c	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/native/java/io/WinNTFileSystem_md.c	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -199,7 +199,7 @@
 
 /**
  * If the given attributes are the attributes of a reparse point, then
- * read and return the attributes of the final target.
+ * read and return the attributes of the special cases.
  */
 DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
 {
@@ -213,6 +213,28 @@
     return a;
 }
 
+/**
+ * Take special cases into account when retrieving the attributes
+ * of path
+ */
+DWORD getFinalAttributes(WCHAR *path)
+{
+    DWORD attr = INVALID_FILE_ATTRIBUTES;
+
+    WIN32_FILE_ATTRIBUTE_DATA wfad;
+    WIN32_FIND_DATAW wfd;
+    HANDLE h;
+
+    if (GetFileAttributesExW(path, GetFileExInfoStandard, &wfad)) {
+        attr = getFinalAttributesIfReparsePoint(path, wfad.dwFileAttributes);
+    } else if (GetLastError() == ERROR_SHARING_VIOLATION &&
+               (h = FindFirstFileW(path, &wfd)) != INVALID_HANDLE_VALUE) {
+        attr = getFinalAttributesIfReparsePoint(path, wfd.dwFileAttributes);
+        CloseHandle(h);
+    }
+    return attr;
+}
+
 JNIEXPORT jstring JNICALL
 Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
                                            jstring pathname)
@@ -337,38 +359,21 @@
 Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
                                                   jobject file)
 {
-
     jint rv = 0;
     jint pathlen;
 
-    /* both pagefile.sys and hiberfil.sys have length 12 */
-#define SPECIALFILE_NAMELEN 12
-
     WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
-    WIN32_FILE_ATTRIBUTE_DATA wfad;
     if (pathbuf == NULL)
         return rv;
     if (!isReservedDeviceNameW(pathbuf)) {
-        if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
-            DWORD a = getFinalAttributesIfReparsePoint(pathbuf, wfad.dwFileAttributes);
-            if (a != INVALID_FILE_ATTRIBUTES) {
-                rv = (java_io_FileSystem_BA_EXISTS
-                    | ((a & FILE_ATTRIBUTE_DIRECTORY)
-                        ? java_io_FileSystem_BA_DIRECTORY
-                        : java_io_FileSystem_BA_REGULAR)
-                    | ((a & FILE_ATTRIBUTE_HIDDEN)
-                        ? java_io_FileSystem_BA_HIDDEN : 0));
-            }
-        } else { /* pagefile.sys is a special case */
-            if (GetLastError() == ERROR_SHARING_VIOLATION) {
-                rv = java_io_FileSystem_BA_EXISTS;
-                if ((pathlen = (jint)wcslen(pathbuf)) >= SPECIALFILE_NAMELEN &&
-                    (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
-                              L"pagefile.sys") == 0) ||
-                    (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
-                              L"hiberfil.sys") == 0))
-                  rv |= java_io_FileSystem_BA_REGULAR;
-            }
+        DWORD a = getFinalAttributes(pathbuf);
+        if (a != INVALID_FILE_ATTRIBUTES) {
+            rv = (java_io_FileSystem_BA_EXISTS
+                | ((a & FILE_ATTRIBUTE_DIRECTORY)
+                    ? java_io_FileSystem_BA_DIRECTORY
+                    : java_io_FileSystem_BA_REGULAR)
+                | ((a & FILE_ATTRIBUTE_HIDDEN)
+                    ? java_io_FileSystem_BA_HIDDEN : 0));
         }
     }
     free(pathbuf);
--- a/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Mon Jun 03 16:37:13 2013 +0400
+++ b/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c	Wed Jun 05 00:37:11 2013 -0700
@@ -162,7 +162,7 @@
     }
     completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
     completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
-    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
+    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
 
     clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult");
     if (clazz == NULL) {
@@ -1169,12 +1169,11 @@
 
 JNIEXPORT jlong JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
-    jlong fileHandle, jlong existingPort, jint completionKey)
+    jlong fileHandle, jlong existingPort, jlong completionKey)
 {
-    ULONG_PTR ck = completionKey;
     HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
                                          (HANDLE)jlong_to_ptr(existingPort),
-                                         ck,
+                                         (ULONG_PTR)completionKey,
                                          0);
     if (port == NULL) {
         throwWindowsException(env, GetLastError());
@@ -1203,21 +1202,20 @@
         (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
         (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
             (jint)bytesTransferred);
-        (*env)->SetIntField(env, obj, completionStatus_completionKey,
-            (jint)completionKey);
-
+        (*env)->SetLongField(env, obj, completionStatus_completionKey,
+            (jlong)completionKey);
     }
 }
 
 JNIEXPORT void JNICALL
 Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
-    jlong completionPort, jint completionKey)
+    jlong completionPort, jlong completionKey)
 {
     BOOL res;
 
     res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
                                      (DWORD)0,  /* dwNumberOfBytesTransferred */
-                                     (DWORD)completionKey,
+                                     (ULONG_PTR)completionKey,
                                      NULL);  /* lpOverlapped */
     if (res == 0) {
         throwWindowsException(env, GetLastError());
@@ -1232,7 +1230,17 @@
     BOOL res;
     BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
 
-    ((LPOVERLAPPED)jlong_to_ptr(pOverlapped))->hEvent = NULL;
+    /* Any unused members of [OVERLAPPED] structure should always be initialized to zero
+       before the structure is used in a function call.
+       Otherwise, the function may fail and return ERROR_INVALID_PARAMETER.
+       http://msdn.microsoft.com/en-us/library/windows/desktop/ms684342%28v=vs.85%29.aspx
+
+       The [Offset] and [OffsetHigh] members of this structure are not used.
+       http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
+
+       [hEvent] should be zero, other fields are the return values. */
+    ZeroMemory((LPOVERLAPPED)jlong_to_ptr(pOverlapped), sizeof(OVERLAPPED));
+
     res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
                                 (LPVOID)jlong_to_ptr(bufferAddress),
                                 (DWORD)bufferLength,
--- a/test/Makefile	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/Makefile	Wed Jun 05 00:37:11 2013 -0700
@@ -657,9 +657,12 @@
 # Multiple by 4 the timeout numbers
 JTREG_TIMEOUT_OPTION =  -timeoutFactor:4
 JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
-# Boost the max memory for jtreg to avoid gc thrashing
+# Set the max memory for jtreg control vm
 JTREG_MEMORY_OPTION = -J-Xmx512m
 JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
+# Set the max memory for jtreg target test vms
+JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
+JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
 
 # Make sure jtreg exists
 $(JTREG): $(JT_HOME)
--- a/test/ProblemList.txt	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/ProblemList.txt	Wed Jun 05 00:37:11 2013 -0700
@@ -137,15 +137,12 @@
 # 8008200
 java/lang/Class/asSubclass/BasicUnit.java                       generic-all
 
-# 8009552
-vm/verifier/TestStaticIF.java                                   generic-all
-
 ############################################################################
 
 # jdk_management
 
 # 8010897
-sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java	macosx-all 
+sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java	macosx-all
 
 ############################################################################
 
@@ -154,9 +151,6 @@
 # 6959636
 javax/management/loading/LibraryLoader/LibraryLoaderTest.java	windows-all
 
-# 8005472
-com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh windows-all
-
 ############################################################################
 
 # jdk_math
@@ -305,9 +299,6 @@
 # 7194428
 sun/security/mscapi/ShortRSAKey1024.sh                          windows-all
 
-# 8000897, vm crash
-sun/security/provider/DSA/TestAlgParameterGenerator.java        generic-all
-
 # 7144048, performance issue
 sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all
 
@@ -338,12 +329,9 @@
 sun/jvmstat/monitor/MonitoredVm/CR6672135.java                  generic-all
 
 # Tests take too long, on sparcs see 7143279
-tools/pack200/CommandLineTests.java                             solaris-all, macosx-all 
+tools/pack200/CommandLineTests.java                             solaris-all, macosx-all
 tools/pack200/Pack200Test.java                                  solaris-all, macosx-all
 
-# 7150569
-tools/launcher/UnicodeTest.java                                 macosx-all
-
 # 8007410
 tools/launcher/FXLauncherTest.java                              linux-all
 
--- a/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/Client.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,47 +1,78 @@
 
-import java.nio.charset.Charset;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardWatchEventKinds;
-import java.nio.file.WatchEvent;
-import java.nio.file.WatchService;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import javax.management.MBeanServerConnection;
 import javax.management.Notification;
 import javax.management.NotificationListener;
 import javax.management.ObjectName;
+import javax.management.remote.JMXConnectionNotification;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
 
 public class Client {
-    public static void main(String[] argv) throws Exception {
-        if (argv.length != 1) throw new IllegalArgumentException("Expecting exactly one jmx url argument");
+    public static void run(String url) throws Exception {
+        final int notifEmittedCnt = 10;
+        final CountDownLatch counter = new CountDownLatch(notifEmittedCnt);
+        final Set<Long> seqSet = Collections.synchronizedSet(new HashSet<Long>());
+        final AtomicBoolean duplNotification = new AtomicBoolean();
 
-        JMXServiceURL serverUrl = new JMXServiceURL(argv[0]);
+        JMXServiceURL serverUrl = new JMXServiceURL(url);
 
         ObjectName name = new ObjectName("test", "foo", "bar");
         JMXConnector jmxConnector = JMXConnectorFactory.connect(serverUrl);
         System.out.println("client connected");
         jmxConnector.addConnectionNotificationListener(new NotificationListener() {
+            @Override
             public void handleNotification(Notification notification, Object handback) {
-                System.err.println("no!" + notification);
+                System.out.println("connection notification: " + notification);
+                if (!seqSet.add(notification.getSequenceNumber())) {
+                    duplNotification.set(true);
+                }
+                if (notification.getType().equals(JMXConnectionNotification.NOTIFS_LOST)) {
+                    long lostNotifs = ((Long)((JMXConnectionNotification)notification).getUserData()).longValue();
+                    for(int i=0;i<lostNotifs;i++) {
+                        counter.countDown();
+                    }
+                }
             }
         }, null, null);
         MBeanServerConnection jmxServer = jmxConnector.getMBeanServerConnection();
 
         jmxServer.addNotificationListener(name, new NotificationListener() {
+            @Override
             public void handleNotification(Notification notification, Object handback) {
-                System.out.println("client got:" + notification);
+                System.out.println("client got: " + notification);
+                if (!seqSet.add(notification.getSequenceNumber())) {
+                    duplNotification.set(true);
+                }
+                counter.countDown();
             }
         }, null, null);
 
-        for(int i=0;i<10;i++) {
-            System.out.println("client invoking foo");
+        System.out.println("client invoking foo (" + notifEmittedCnt + " times)");
+        for(int i=0;i<notifEmittedCnt;i++) {
+            System.out.print(".");
             jmxServer.invoke(name, "foo", new Object[]{}, new String[]{});
-            Thread.sleep(50);
         }
-
-        System.err.println("happy!");
+        System.out.println();
+        try {
+            System.out.println("waiting for " + notifEmittedCnt + " notifications to arrive");
+            if (!counter.await(30, TimeUnit.SECONDS)) {
+                throw new InterruptedException();
+            }
+            if (duplNotification.get()) {
+                System.out.println("ERROR: received duplicated notifications");
+                throw new Error("received duplicated notifications");
+            }
+            System.out.println("\nshutting down client");
+        } catch (InterruptedException e) {
+            System.out.println("ERROR: notification processing thread interrupted");
+            throw new Error("notification thread interrupted unexpectedly");
+        }
     }
 }
--- a/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Server.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,11 +1,6 @@
+import java.io.File;
 import java.lang.management.ManagementFactory;
 import java.net.BindException;
-import java.nio.charset.Charset;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
 import java.rmi.registry.LocateRegistry;
 import java.rmi.server.ExportException;
 import java.util.Random;
@@ -16,7 +11,7 @@
 import javax.management.remote.JMXServiceURL;
 
 public class Server {
-    public static void main(String[] argv) throws Exception {
+    public static String start() throws Exception {
         int serverPort = 12345;
         ObjectName name = new ObjectName("test", "foo", "bar");
         MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
@@ -40,7 +35,7 @@
         JMXServiceURL serverUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + serverPort + "/test");
         JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(serverUrl, null, jmxServer);
         jmxConnector.start();
-        System.out.println(serverUrl);
-        System.err.println("server listening on " + serverUrl);
+
+        return serverUrl.toString();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.java	Wed Jun 05 00:37:11 2013 -0700
@@ -0,0 +1,123 @@
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+
+/**
+ * @test
+ * @summary Tests for the RMI unmarshalling errors not to cause silent failure.
+ * @author Jaroslav Bachorik
+ * @bug 6937053 8005472
+ *
+ * @run clean TestSerializationMismatch
+ * @run main TestSerializationMismatch
+ *
+ */
+public class TestSerializationMismatch {
+    static final String clientDir = "Client";
+    static final String serverDir = "Server";
+    static final String testSrc = System.getProperty("test.src");
+    static final String testSrcDir = testSrc != null ? testSrc : ".";
+    static final String testSrcClientDir = testSrcDir + File.separator + clientDir + File.separator;
+    static final String testSrcServerDir = testSrcDir + File.separator + serverDir + File.separator;
+    static final String testClasses = System.getProperty("test.classes");
+    static final String testClassesDir = testClasses != null ? testClasses : ".";
+    static final String testClassesClientDir = testClassesDir + File.separator + clientDir + File.separator;
+    static final String testClassesServerDir = testClassesDir + File.separator + serverDir + File.separator;
+
+    static final boolean debug = true;
+
+    public static void main(String[] args) throws Exception {
+        setup();
+
+        compileClient();
+        compileServer();
+
+        debug("starting server");
+        String url = startServer();
+        debug("server started and listening on " + url);
+        debug("starting client");
+        startClient(url);
+    }
+
+    static void setup() {
+        debug("setting up the output dirs");
+        cleanupDir(testClassesClientDir);
+        cleanupDir(testClassesServerDir);
+    }
+
+    static void cleanupDir(String path) {
+        debug("cleaning " + path);
+        File dir = new File(path);
+        if (dir.exists()) {
+            for(File src : dir.listFiles()) {
+                boolean rslt = src.delete();
+                debug((rslt == false ? "not " : "") + "deleted " + src);
+            }
+        } else {
+            dir.mkdirs();
+        }
+    }
+
+    static void compileClient() {
+        debug("compiling client");
+        compile("-d" , testClassesClientDir,
+            "-sourcepath", testSrcClientDir,
+            testSrcClientDir + "Client.java",
+            testSrcClientDir + "ConfigKey.java",
+            testSrcClientDir + "TestNotification.java");
+    }
+
+    static void compileServer() {
+        debug("compiling server");
+        compile("-d" , testClassesServerDir,
+            "-sourcepath", testSrcServerDir,
+            testSrcServerDir + "Server.java",
+            testSrcServerDir + "ConfigKey.java",
+            testSrcServerDir + "TestNotification.java",
+            testSrcServerDir + "Ste.java",
+            testSrcServerDir + "SteMBean.java");
+    }
+
+    static String startServer() throws Exception {
+        ClassLoader serverCL = customCL(testClassesServerDir);
+
+        Class serverClz = serverCL.loadClass("Server");
+        Method startMethod = serverClz.getMethod("start");
+        return (String)startMethod.invoke(null);
+    }
+
+    static void startClient(String url) throws Exception {
+        ClassLoader clientCL = customCL(testClassesClientDir);
+
+        Thread.currentThread().setContextClassLoader(clientCL);
+        Class clientClz = clientCL.loadClass("Client");
+        Method runMethod = clientClz.getMethod("run", String.class);
+        runMethod.invoke(null, url);
+    }
+
+    static ClassLoader customCL(String classDir) throws Exception {
+        return new URLClassLoader(
+            new URL[]{
+                new File(classDir).toURI().toURL()
+            },
+            TestSerializationMismatch.class.getClassLoader()
+        );
+    }
+
+    static void debug(Object message) {
+        if (debug) {
+            System.out.println(message);
+        }
+    }
+
+    /* run javac <args> */
+    static void compile(String... args) {
+        debug("Running: javac " + Arrays.toString(args));
+        if (com.sun.tools.javac.Main.compile(args) != 0) {
+            throw new RuntimeException("javac failed: args=" + Arrays.toString(args));
+        }
+    }
+}
--- a/test/com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh	Mon Jun 03 16:37:13 2013 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 2005, 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.
-#
-# 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.
-#
-
-# 
-# @test
-# @summary  Tests for the RMI unmarshalling errors not to cause silent failure.
-# @author   Jaroslav Bachorik
-# @bug      6937053
-#
-# @run shell TestSerializationMismatch.sh
-#
-
-#set -x
-
-#Set appropriate jdk
-#
-
-if [ ! -z "${TESTJAVA}" ] ; then
-     jdk="$TESTJAVA"
-else
-     echo "--Error: TESTJAVA must be defined as the pathname of a jdk to test."
-     exit 1
-fi
-
-SERVER_TESTCLASSES=$TESTCLASSES/Server
-CLIENT_TESTCLASSES=$TESTCLASSES/Client
-
-URL_PATH=$SERVER_TESTCLASSES/jmxurl
-
-rm $URL_PATH
-
-mkdir -p $SERVER_TESTCLASSES
-mkdir -p $CLIENT_TESTCLASSES
-
-$TESTJAVA/bin/javac -d $CLIENT_TESTCLASSES $TESTSRC/Client/ConfigKey.java $TESTSRC/Client/TestNotification.java $TESTSRC/Client/Client.java
-$TESTJAVA/bin/javac -d $SERVER_TESTCLASSES $TESTSRC/Server/ConfigKey.java $TESTSRC/Server/TestNotification.java $TESTSRC/Server/SteMBean.java $TESTSRC/Server/Ste.java $TESTSRC/Server/Server.java
-
-startServer()
-{
-   ($TESTJAVA/bin/java -classpath $SERVER_TESTCLASSES Server) 1>$URL_PATH &
-   SERVER_PID=$!
-}
-
-runClient() 
-{
-   while true
-   do
-      [ -f $URL_PATH ] && break
-      sleep 2
-   done
-   read JMXURL < $URL_PATH
-   
-   HAS_ERRORS=`($TESTJAVA/bin/java -classpath $CLIENT_TESTCLASSES Client $JMXURL) 2>&1 | grep -i "SEVERE: Failed to fetch notification, stopping thread. Error is: java.rmi.UnmarshalException"`
-}
-
-startServer
-
-runClient
-
-sleep 1 # wait for notifications to arrive
-
-kill "$SERVER_PID"
-
-if [ -z "$HAS_ERRORS" ]
-then
-  echo "Test PASSED"
-  exit 0
-fi
-
-echo "Test FAILED"
-echo $HAS_ERRORS 1>&2
-exit 1
-
--- a/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/java/awt/print/PrinterJob/Collate2DPrintingTest.java	Wed Jun 05 00:37:11 2013 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 6362683
+ * @bug 6362683 8012381
  * @summary Collation should work.
  * @run main/manual Collate2DPrintingTest
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/print/PrinterJob/PrintLatinCJKTest.java	Wed Jun 05 00:37:11 2013 -0700
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 800535
+ * @summary JDK7 Printing: CJK and Latin Text in string overlap
+ * @run main/manual=yesno PrintLatinCJKTest
+ */
+
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JTextArea;
+
+import javax.swing.SwingUtilities;
+
+public class PrintLatinCJKTest implements Printable, ActionListener {
+
+    static PrintLatinCJKTest testInstance = new PrintLatinCJKTest();
+    private PageFormat pf;
+
+    static String info =
+       "You need a printer for this test. If you have none, let "+
+       "the test pass. If there is a printer, press Print, send "+
+       "the output to the printer, and examine it. It should have "+
+       "text looking like this : \u4e00\u4e01\u4e02\u4e03\u4e04English.";
+
+    public static void showFrame() {
+         JFrame f = new JFrame();
+         JTextArea jta = new JTextArea(info, 4, 30);
+         jta.setLineWrap(true);
+         jta.setWrapStyleWord(true);
+         f.add("Center", jta);
+         JButton b = new JButton("Print");
+         b.addActionListener(testInstance);
+         f.add("South", b);
+         f.pack();
+         f.setVisible(true);
+    }
+
+    public int print(Graphics g, PageFormat pf, int pageIndex)
+                         throws PrinterException {
+
+        if (pageIndex > 0) {
+            return Printable.NO_SUCH_PAGE;
+        }
+        g.translate((int) pf.getImageableX(), (int) pf.getImageableY());
+        g.setFont(new Font("Dialog", Font.PLAIN, 36));
+        g.drawString("\u4e00\u4e01\u4e02\u4e03\u4e04English", 20, 100);
+        return Printable.PAGE_EXISTS;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        try {
+            PrinterJob job = PrinterJob.getPrinterJob();
+            job.setPrintable(testInstance);
+            if (job.printDialog()) {
+                job.print();
+            }
+        } catch (PrinterException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                showFrame();
+            }
+        });
+    }
+}
--- a/test/java/io/File/IsHidden.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/java/io/File/IsHidden.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -46,6 +46,11 @@
         Files.getFileAttributeView(f.toPath(), DosFileAttributeView.class).setHidden(value);
     }
 
+    private static void checkHidden(File f) {
+        if (!f.isHidden())
+            throw new RuntimeException(f + " should be hidden");
+    }
+
     private static void testWin32() throws Exception {
         File f = new File(dir, "test");
         f.deleteOnExit();
@@ -58,6 +63,11 @@
         }
         ck(".foo", false);
         ck("foo", false);
+
+        File pagefile = new File("C:\\pagefile.sys");
+        File hiberfil = new File("C:\\hiberfil.sys");
+        if (pagefile.exists()) checkHidden(pagefile);
+        if (hiberfil.exists()) checkHidden(hiberfil);
     }
 
     private static void testUnix() throws Exception {
--- a/test/java/io/FileInputStream/LargeFileAvailable.java	Mon Jun 03 16:37:13 2013 +0400
+++ b/test/java/io/FileInputStream/LargeFileAvailable.java	Wed Jun 05 00:37:11 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6402006 7030573
+ * @bug 6402006 7030573 8011136
  * @summary Test if available returns correct value when reading
  *          a large file.
  */
@@ -61,9 +61,12 @@
             remaining -= skipBytes(fis, bigSkip, remaining);
             remaining -= skipBytes(fis, 10L, remaining);
             remaining -= skipBytes(fis, bigSkip, remaining);
-            if (fis.available() != (int) remaining) {
-                 throw new RuntimeException("available() returns "
-                     + fis.available() + " but expected " + remaining);
+            int expected = (remaining >= Integer.MAX_VALUE)
+                           ? Integer.MAX_VALUE
+                           : (remaining > 0 ? (int) remaining : 0);
+            if (fis.available() != expected) {
+                throw new RuntimeException("available() returns "
+                        + fis.available() + " but expected " + expected);
             }
         } finally {
             file.delete();
@@ -77,19 +80,18 @@
         long skip = is.skip(toSkip);
         if (skip != toSkip) {
             throw new RuntimeException("skip() returns " + skip
-                + " but expected " + toSkip);
+                                       + " but expected " + toSkip);
         }
         long remaining = avail - skip;
-        int expected = remaining >= Integer.MAX_VALUE
-                           ? Integer.MAX_VALUE
-                           : (int) remaining;
+        int expected = (remaining >= Integer.MAX_VALUE)
+                       ? Integer.MAX_VALUE
+                       : (remaining > 0 ? (int) remaining : 0);
 
-        System.out.println("Skipped " + skip + " bytes "
-            + " available() returns " + expected +
-            " remaining=" + remaining);
+        System.out.println("Skipped " + skip + " bytes, available() returns "
+                           + expected + ", remaining " + remaining);
         if (is.available() != expected) {
             throw new RuntimeException("available() returns "
-                + is.available() + " but expected " + expected);
+                    + is.available() + " but expected " + expected);
         }
         return skip;
     }
--- a/test/java/io/FileInputStream/NegativeAvailable.java	Mon Jun 03 16:37:13 2013 +0400