diff --git a/.hgtags b/.hgtags
index 5cfc1c804be..c3213062fb5 100644
--- a/.hgtags
+++ b/.hgtags
@@ -86,3 +86,5 @@ c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99
e02b4d709e177d08d56130a4bc68061e4bbacc7d jdk7-b109
a6442d6bc38a44152e0662688213ce4d2701f42a jdk7-b110
69f3edf083477955b5bd2f754252c7504167d8e1 jdk7-b111
+f960f117f1623629f64203e2b09a92a8f6f14ff5 jdk7-b112
+1fee41c7ed2b3388970a756a85aa693c0de8407a jdk7-b113
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 19a3f1c2601..91c72f80940 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -86,3 +86,5 @@ f8be576feefce0c6695f188ef97ec16b73ad9cfd jdk7-b104
81dfc728d7bb7e1fff4a4dc6d0f7cea5a3315667 jdk7-b109
2a02d4a6955c7c078aee9a604cb3be409800d82c jdk7-b110
9702d6fef68e17533ee7fcf5923b11ead3e912ce jdk7-b111
+b852103caf73da70068473777ae867a457bb3ae1 jdk7-b112
+c1df968c4527bfab5f97662a89245f15d12d378b jdk7-b113
diff --git a/Makefile b/Makefile
index 065e0c55edc..d42650e58ce 100644
--- a/Makefile
+++ b/Makefile
@@ -558,9 +558,12 @@ endif
# rule to test
################################################################
-.NOTPARALLEL: test
+.NOTPARALLEL: test_run
-test: test_clean test_start test_summary
+test:
+ $(MAKE) test_run
+
+test_run: test_clean test_start test_summary
test_start:
@$(ECHO) "Tests started at `$(DATE)`"
@@ -586,7 +589,7 @@ test_summary: $(OUTPUTDIR)/test_failures.txt
# Get failure list from log
$(OUTPUTDIR)/test_failures.txt: $(OUTPUTDIR)/test_log.txt
@$(RM) $@
- @( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) > $@
+ @( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) | $(NAWK) 'length>0' > $@
# Get log file of all tests run
JDK_TO_TEST := $(shell \
@@ -598,10 +601,11 @@ JDK_TO_TEST := $(shell \
$(ECHO) "$(PRODUCT_HOME)"; \
fi \
)
+TEST_TARGETS=all
$(OUTPUTDIR)/test_log.txt:
$(RM) $@
- ( $(CD) test && \
- $(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) \
+ ( $(CD) test && \
+ $(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) $(TEST_TARGETS) \
) | tee $@
################################################################
@@ -614,7 +618,7 @@ include ./make/jprt.gmk
# PHONY
################################################################
-.PHONY: all test test_start test_summary test_clean \
+.PHONY: all test test_run test_start test_summary test_clean \
generic_build_repo_series \
what clobber insane \
dev dev-build dev-sanity dev-clobber \
diff --git a/corba/.hgtags b/corba/.hgtags
index 9f6d3054114..03eadfbbb1b 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -86,3 +86,5 @@ a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100
c3dd858e09b20206459d9e7b0ead99d27ab00eab jdk7-b109
0e1f80fda2271f53d4bbb59ec3f301dfbcef6a0a jdk7-b110
640fa4d4e2ad4c2d7e4815c955026740d8c52b7a jdk7-b111
+cc67fdc4fee9a5b25caee4e71b51a8ff24ae7d1a jdk7-b112
+a89a6c5be9d1a754868d3d359cbf7ad36aa95631 jdk7-b113
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 71539d8e572..da1bccd72ad 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -121,3 +121,5 @@ e44a93947ccbfce712b51725f313163606f15486 jdk7-b108
cc4bb3022b3144dc5db0805b9ef6c7eff2aa3b81 jdk7-b109
2f25f2b8de2700a1822463b1bd3d02b5e218018f jdk7-b110
07b042e13dde4f3479ba9ec55120fcd5e8623323 jdk7-b111
+5511edd5d719f3fc9fdd04879482026a3d2c8652 jdk7-b112
+beef35b96b81129c375d572357fb9548d9020db1 jdk7-b113
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index e7b0a593feb..e3050dd6df5 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -86,3 +86,5 @@ d42c4acb6424a094bdafe2ad9c8c1c7ca7fb7b7e jdk7-b104
0f382d6120fc07aed2209484a42458cabf405916 jdk7-b109
d422dbdd09766269344b796b3a46a5b3f74557e1 jdk7-b110
8106c747067c905d814a737a57fea0e29057b33f jdk7-b111
+1b05254242881527b4d5d711295c0fe708c8823a jdk7-b112
+bc0c84ce54c34d3e8b0604b94da0d7c75c26755e jdk7-b113
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 7d3a0bc9d25..12e62c797d0 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -86,3 +86,5 @@ b1ca39340238a239ba6d8489ad5315215e1366ca jdk7-b108
4f626e0d70bda68c76bbd0e89d2bc2407f979736 jdk7-b109
95ecac35fb11530752bd0404c9bf02bcfb30990e jdk7-b110
2575ebca96c7fb1b78f6ae025a97321210aba309 jdk7-b111
+8e0f0054817f0f73fb33e80fb1333fb45b1d513d jdk7-b112
+d35c94fd22362f478f75b4bfcd2bef6a83cb9b3f jdk7-b113
diff --git a/jdk/.hgtags b/jdk/.hgtags
index e69a21ab6c0..b49ddeec2f9 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -86,3 +86,5 @@ b91ef6b60f4e19bf4592c6dd594c9bac62487519 jdk7-b106
ab0d3f54a63f2aadfcdd2e14b81f79362ce454e2 jdk7-b109
176586cd040e4dd17a5ff6e91f72df10d7442453 jdk7-b110
fb63a2688db807a73e2a3de7d9bab298f1bff0e8 jdk7-b111
+b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
+61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113
diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk
index 4043c374a02..acbc8a73230 100644
--- a/jdk/make/java/java/FILES_java.gmk
+++ b/jdk/make/java/java/FILES_java.gmk
@@ -466,14 +466,11 @@ JAVA_JAVA_java = \
java/security/ProtectionDomain.java \
java/net/URLClassLoader.java \
java/net/URLConnection.java \
+ sun/misc/BootClassLoaderHook.java \
sun/misc/Launcher.java \
sun/misc/MetaIndex.java \
sun/misc/URLClassPath.java \
sun/misc/Version.java \
- sun/net/www/protocol/jar/Handler.java \
- sun/net/www/protocol/jar/JarURLConnection.java \
- sun/net/www/protocol/file/Handler.java \
- sun/net/www/protocol/file/FileURLConnection.java \
sun/misc/FileURLMapper.java \
sun/misc/MessageUtils.java \
sun/misc/GC.java \
@@ -483,6 +480,10 @@ JAVA_JAVA_java = \
sun/misc/JavaIOFileDescriptorAccess.java \
sun/misc/JavaNioAccess.java \
sun/misc/Perf.java \
- sun/misc/PerfCounter.java
+ sun/misc/PerfCounter.java \
+ sun/net/www/protocol/jar/Handler.java \
+ sun/net/www/protocol/jar/JarURLConnection.java \
+ sun/net/www/protocol/file/Handler.java \
+ sun/net/www/protocol/file/FileURLConnection.java
FILES_java = $(JAVA_JAVA_java)
diff --git a/jdk/make/mkdemo/Makefile b/jdk/make/mkdemo/Makefile
index cda377f83f2..5a54d2795cd 100644
--- a/jdk/make/mkdemo/Makefile
+++ b/jdk/make/mkdemo/Makefile
@@ -31,7 +31,7 @@ BUILDDIR = ..
PRODUCT = demos
include $(BUILDDIR)/common/Defs.gmk
-SUBDIRS = jni
+SUBDIRS = jni nio
SUBDIRS_desktop = applets jfc
SUBDIRS_management = management
SUBDIRS_misc = scripting
diff --git a/jdk/make/mkdemo/nio/Makefile b/jdk/make/mkdemo/nio/Makefile
new file mode 100644
index 00000000000..26dc772b213
--- /dev/null
+++ b/jdk/make/mkdemo/nio/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 1997, 2007, 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.
+#
+
+#
+# Makefile for building the jfc demos
+#
+
+BUILDDIR = ../..
+PRODUCT = demos
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = zipfs
+include $(BUILDDIR)/common/Subdirs.gmk
+
+all build clean clobber::
+ $(SUBDIRS-loop)
+
diff --git a/jdk/make/mkdemo/nio/zipfs/Makefile b/jdk/make/mkdemo/nio/zipfs/Makefile
new file mode 100644
index 00000000000..16e71a9ba45
--- /dev/null
+++ b/jdk/make/mkdemo/nio/zipfs/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 1997, 2002, 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.
+#
+
+#
+# Makefile to build the ZipFileSystem demo.
+#
+
+BUILDDIR = ../../..
+PRODUCT = demo/zipfs
+DEMONAME = zipfs
+include $(BUILDDIR)/common/Defs.gmk
+
+DEMO_ROOT = $(SHARE_SRC)/demo/nio/$(DEMONAME)
+DEMO_TOPFILES = ./README.txt
+DEMO_SRCDIR = $(DEMO_ROOT)
+DEMO_DESTDIR = $(DEMODIR)/nio/$(DEMONAME)
+
+#
+# Demo jar building rules.
+#
+include $(BUILDDIR)/common/Demo.gmk
+
diff --git a/jdk/make/sun/cmm/lcms/Makefile b/jdk/make/sun/cmm/lcms/Makefile
index 1072c2fac7b..702c32680c8 100644
--- a/jdk/make/sun/cmm/lcms/Makefile
+++ b/jdk/make/sun/cmm/lcms/Makefile
@@ -80,7 +80,12 @@ vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
vpath %.c $(SHARE_SRC)/native/sun/java2d
ifeq ($(PLATFORM), windows)
-OTHER_CFLAGS += -DCMS_IS_WINDOWS_ -Dsqrtf=sqrt
+OTHER_CFLAGS += -DCMS_IS_WINDOWS_
+
+ifeq ($(COMPILER_VERSION), VS2003)
+OTHER_CFLAGS += -Dsqrtf=sqrt
+endif
+
OTHER_LDLIBS = $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \
-I$(SHARE_SRC)/native/sun/awt/debug
diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c
index 4c61fb7c853..01eeb2a0547 100644
--- a/jdk/src/share/bin/java.c
+++ b/jdk/src/share/bin/java.c
@@ -355,7 +355,6 @@ JavaMain(void * _args)
JavaVM *vm = 0;
JNIEnv *env = 0;
- jstring mainClassName;
jclass mainClass;
jmethodID mainID;
jobjectArray mainArgs;
diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c
index 2c916d87cb5..61b8bdb6b69 100644
--- a/jdk/src/share/bin/parse_manifest.c
+++ b/jdk/src/share/bin/parse_manifest.c
@@ -72,7 +72,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
if (entry->how == STORED) {
*(char *)((size_t)in + entry->csize) = '\0';
if (size_out) {
- *size_out = entry->csize;
+ *size_out = (int)entry->csize;
}
return (in);
} else if (entry->how == DEFLATED) {
@@ -103,7 +103,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
return (NULL);
}
if (size_out) {
- *size_out = entry->isize;
+ *size_out = (int)entry->isize;
}
return (out);
} else
@@ -317,7 +317,7 @@ find_file(int fd, zentry *entry, const char *file_name)
* manifest. If so, build the entry record from the data found in
* the header located and return success.
*/
- if (CENNAM(p) == JLI_StrLen(file_name) &&
+ if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
free(buffer);
@@ -606,8 +606,5 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
}
free(mp);
close(fd);
- if (rc == 0)
- return (0);
- else
- return (-2);
+ return (rc == 0) ? 0 : -2;
}
diff --git a/jdk/src/share/bin/wildcard.c b/jdk/src/share/bin/wildcard.c
index 3abcd18a97c..0d834e635b5 100644
--- a/jdk/src/share/bin/wildcard.c
+++ b/jdk/src/share/bin/wildcard.c
@@ -290,12 +290,12 @@ FileList_join(FileList fl, char sep)
char *path;
char *p;
for (i = 0, size = 1; i < fl->size; i++)
- size += JLI_StrLen(fl->files[i]) + 1;
+ size += (int)JLI_StrLen(fl->files[i]) + 1;
path = JLI_MemAlloc(size);
for (i = 0, p = path; i < fl->size; i++) {
- int len = JLI_StrLen(fl->files[i]);
+ int len = (int)JLI_StrLen(fl->files[i]);
if (i > 0) *p++ = sep;
memcpy(p, fl->files[i], len);
p += len;
@@ -309,7 +309,7 @@ static FileList
FileList_split(const char *path, char sep)
{
const char *p, *q;
- int len = JLI_StrLen(path);
+ int len = (int)JLI_StrLen(path);
int count;
FileList fl;
for (count = 1, p = path; p < path + len; p++)
@@ -330,7 +330,7 @@ FileList_split(const char *path, char sep)
static int
isJarFileName(const char *filename)
{
- int len = JLI_StrLen(filename);
+ int len = (int)JLI_StrLen(filename);
return (len >= 4) &&
(filename[len - 4] == '.') &&
(equal(filename + len - 3, "jar") ||
@@ -342,8 +342,8 @@ isJarFileName(const char *filename)
static char *
wildcardConcat(const char *wildcard, const char *basename)
{
- int wildlen = JLI_StrLen(wildcard);
- int baselen = JLI_StrLen(basename);
+ int wildlen = (int)JLI_StrLen(wildcard);
+ int baselen = (int)JLI_StrLen(basename);
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
/* Replace the trailing '*' with basename */
memcpy(filename, wildcard, wildlen-1);
@@ -369,7 +369,7 @@ wildcardFileList(const char *wildcard)
static int
isWildcard(const char *filename)
{
- int len = JLI_StrLen(filename);
+ int len = (int)JLI_StrLen(filename);
return (len > 0) &&
(filename[len - 1] == '*') &&
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java
index 0c1b0954300..b662ebb9683 100644
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java
@@ -654,8 +654,8 @@ class Attribute implements Comparable, Constants {
String layout;
public FormatException(String message,
int ctype, String name, String layout) {
- super(ATTR_CONTEXT_NAME[ctype]+"."+name
- +(message == null? "": (": "+message)));
+ super(ATTR_CONTEXT_NAME[ctype]+ " attribute \"" + name + "\"" +
+ (message == null? "" : (": " + message)));
this.ctype = ctype;
this.name = name;
this.layout = layout;
diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java
index a14bf350a6f..fd28171a75b 100644
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java
@@ -30,6 +30,7 @@ import java.util.*;
import com.sun.java.util.jar.pack.Package.Class;
import com.sun.java.util.jar.pack.Package.InnerClass;
import com.sun.java.util.jar.pack.ConstantPool.*;
+import com.sun.tools.classfile.AttributeException;
/**
* Reader for a class file that is being incorporated into a package.
@@ -246,7 +247,9 @@ class ClassReader implements Constants {
fixups[fptr++] = in.readUnsignedShort();
break;
default:
- throw new IOException("Bad constant pool tag "+tag);
+ throw new ClassFormatException("Bad constant pool tag " +
+ tag + " in File: " + cls.file.nameString +
+ " at pos: " + inPos);
}
}
@@ -403,7 +406,7 @@ class ClassReader implements Constants {
skip(length, "unknown "+name+" attribute in "+h);
continue;
} else {
- String message = "unknown in "+h;
+ String message = " is unknown attribute in class " + h;
throw new Attribute.FormatException(message, ctype, name,
unknownAttrCommand);
}
@@ -415,7 +418,12 @@ class ClassReader implements Constants {
if (a.name() == "Code") {
Class.Method m = (Class.Method) h;
m.code = new Code(m);
- readCode(m.code);
+ try {
+ readCode(m.code);
+ } catch (Instruction.FormatException iie) {
+ String message = iie.getMessage() + " in " + h;
+ throw new ClassReader.ClassFormatException(message);
+ }
} else {
assert(h == cls);
readInnerClasses(cls);
@@ -427,6 +435,10 @@ class ClassReader implements Constants {
in.readFully(bytes);
a = a.addContent(bytes);
}
+ if (a.size() == 0 && !a.layout().isEmpty()) {
+ throw new ClassFormatException(name +
+ ": attribute length cannot be zero, in " + h);
+ }
h.addAttribute(a);
if (verbose > 2)
Utils.log.fine("read "+a);
@@ -438,6 +450,7 @@ class ClassReader implements Constants {
code.max_locals = readUnsignedShort();
code.bytes = new byte[readInt()];
in.readFully(code.bytes);
+ Instruction.opcodeChecker(code.bytes);
int nh = readUnsignedShort();
code.setHandlerCount(nh);
for (int i = 0; i < nh; i++) {
@@ -463,4 +476,10 @@ class ClassReader implements Constants {
cls.innerClasses = ics; // set directly; do not use setInnerClasses.
// (Later, ics may be transferred to the pkg.)
}
+
+ class ClassFormatException extends IOException {
+ public ClassFormatException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java
index bef43fd0f03..2eb4604ec08 100644
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java
@@ -25,6 +25,8 @@
package com.sun.java.util.jar.pack;
+import java.io.IOException;
+
/**
* A parsed bytecode instruction.
* Provides accessors to various relevant bits.
@@ -628,4 +630,21 @@ class Instruction implements Constants {
}
}
}
+
+ public static void opcodeChecker(byte[] code) throws FormatException {
+ Instruction i = at(code, 0);
+ while (i != null) {
+ int opcode = i.getBC();
+ if (opcode == _xxxunusedxxx || opcode < _nop || opcode > _jsr_w) {
+ String message = "illegal opcode: " + opcode + " " + i;
+ throw new FormatException(message);
+ }
+ i = i.next();
+ }
+ }
+ static class FormatException extends IOException {
+ FormatException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
index 449bbbeb5b1..a45a4bcba09 100644
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
@@ -496,15 +496,29 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
reader.unknownAttrCommand = unknownAttrCommand;
try {
reader.read();
- } catch (Attribute.FormatException ee) {
- // He passed up the category to us in layout.
- if (ee.layout.equals(Pack200.Packer.PASS)) {
- Utils.log.warning("Passing class file uncompressed due to unrecognized attribute: "+fname);
- Utils.log.info(ee.toString());
- return null;
+ } catch (IOException ioe) {
+ String message = "Passing class file uncompressed due to";
+ if (ioe instanceof Attribute.FormatException) {
+ Attribute.FormatException ee = (Attribute.FormatException) ioe;
+ // He passed up the category to us in layout.
+ if (ee.layout.equals(Pack200.Packer.PASS)) {
+ Utils.log.info(ee.toString());
+ Utils.log.warning(message + " unrecognized attribute: " +
+ fname);
+ return null;
+ }
+ } else if (ioe instanceof ClassReader.ClassFormatException) {
+ ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe;
+ // %% TODO: Do we invent a new property for this or reuse %%
+ if (unknownAttrCommand.equals(Pack200.Packer.PASS)) {
+ Utils.log.info(ce.toString());
+ Utils.log.warning(message + " unknown class format: " +
+ fname);
+ return null;
+ }
}
// Otherwise, it must be an error.
- throw ee;
+ throw ioe;
}
pkg.addClass(cls);
return cls.file;
diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java
index 2dc47c41464..84f65ac2ccf 100644
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java
@@ -182,11 +182,8 @@ class Utils {
}
public void warning(String msg, Object param) {
- int verbose = currentPropMap().getInteger(DEBUG_VERBOSE);
- if (verbose > 0) {
getLogger().warning(msg, param);
}
- }
public void warning(String msg) {
warning(msg, null);
@@ -216,7 +213,9 @@ class Utils {
// Returns the Max Version String of this implementation
static String getVersionString() {
- return "Pack200, Vendor: Sun Microsystems, Version: " +
+ return "Pack200, Vendor: " +
+ System.getProperty("java.vendor") +
+ ", Version: " +
Constants.JAVA6_PACKAGE_MAJOR_VERSION + "." +
Constants.JAVA6_PACKAGE_MINOR_VERSION;
}
diff --git a/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java b/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java
index 2b1303b406d..666ab0b2c1b 100644
--- a/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java
+++ b/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java
@@ -24,9 +24,6 @@
*/
package com.sun.net.httpserver;
-import java.net.*;
-import java.io.*;
-import java.util.*;
/**
* BasicAuthenticator provides an implementation of HTTP Basic
@@ -57,7 +54,6 @@ public abstract class BasicAuthenticator extends Authenticator {
public Result authenticate (HttpExchange t)
{
- HttpContext context = t.getHttpContext();
Headers rmap = (Headers) t.getRequestHeaders();
/*
* look for auth token
diff --git a/jdk/src/share/classes/com/sun/net/httpserver/Filter.java b/jdk/src/share/classes/com/sun/net/httpserver/Filter.java
index 7e8c6e7a957..a870d6518d3 100644
--- a/jdk/src/share/classes/com/sun/net/httpserver/Filter.java
+++ b/jdk/src/share/classes/com/sun/net/httpserver/Filter.java
@@ -25,11 +25,7 @@
package com.sun.net.httpserver;
-import java.net.*;
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import sun.net.www.MessageHeader;
+import java.io.IOException;
import java.util.*;
/**
@@ -56,12 +52,10 @@ public abstract class Filter {
/* the last element in the chain must invoke the users
* handler
*/
- private List filters;
private ListIterator iter;
private HttpHandler handler;
public Chain (List filters, HttpHandler handler) {
- this.filters = filters;
iter = filters.listIterator();
this.handler = handler;
}
diff --git a/jdk/src/share/classes/com/sun/net/httpserver/Headers.java b/jdk/src/share/classes/com/sun/net/httpserver/Headers.java
index efac6042861..b9176917368 100644
--- a/jdk/src/share/classes/com/sun/net/httpserver/Headers.java
+++ b/jdk/src/share/classes/com/sun/net/httpserver/Headers.java
@@ -26,7 +26,6 @@
package com.sun.net.httpserver;
import java.util.*;
-import java.io.*;
/**
* HTTP request and response headers are represented by this class which implements
@@ -77,19 +76,16 @@ public class Headers implements Map> {
if (len == 0) {
return key;
}
- char[] b = new char [len];
- String s = null;
- b = key.toCharArray();
- if (b[0] >= 'a' && b[0] <= 'z') {
- b[0] = (char)(b[0] - ('a' - 'A'));
+ char[] b = key.toCharArray();
+ if (b[0] >= 'a' && b[0] <= 'z') {
+ b[0] = (char)(b[0] - ('a' - 'A'));
+ }
+ for (int i=1; i= 'A' && b[i] <= 'Z') {
+ b[i] = (char) (b[i] + ('a' - 'A'));
}
- for (int i=1; i= 'A' && b[i] <= 'Z') {
- b[i] = (char) (b[i] + ('a' - 'A'));
- }
- }
- s = new String (b);
- return s;
+ }
+ return new String(b);
}
public int size() {return map.size();}
diff --git a/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java b/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java
index 13ddc3e658c..c54e917c02e 100644
--- a/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java
+++ b/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java
@@ -24,9 +24,7 @@
*/
package com.sun.net.httpserver;
-import java.net.*;
-import java.io.*;
-import java.util.*;
+import java.net.InetSocketAddress;
import javax.net.ssl.SSLParameters;
/**
@@ -90,7 +88,7 @@ public abstract class HttpsParameters {
* have been set.
*/
public String[] getCipherSuites() {
- return cipherSuites;
+ return cipherSuites != null ? cipherSuites.clone() : null;
}
/**
@@ -99,7 +97,7 @@ public abstract class HttpsParameters {
* @param cipherSuites the array of ciphersuites (or null)
*/
public void setCipherSuites(String[] cipherSuites) {
- this.cipherSuites = cipherSuites;
+ this.cipherSuites = cipherSuites != null ? cipherSuites.clone() : null;
}
/**
@@ -110,7 +108,7 @@ public abstract class HttpsParameters {
* have been set.
*/
public String[] getProtocols() {
- return protocols;
+ return protocols != null ? protocols.clone() : null;
}
/**
@@ -119,7 +117,7 @@ public abstract class HttpsParameters {
* @param protocols the array of protocols (or null)
*/
public void setProtocols(String[] protocols) {
- this.protocols = protocols;
+ this.protocols = protocols != null ? protocols.clone() : null;
}
/**
diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java
index d469399b71d..bfba75dd2ae 100644
--- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java
+++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java
@@ -3,7 +3,7 @@
* DO NOT REMOVE OR ALTER!
*/
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2010 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,66 +23,70 @@ package com.sun.org.apache.xml.internal.security.utils;
import java.io.OutputStream;
/**
- * A simple Unsynced ByteArryOutputStream
+ * A simple Unsynced ByteArrayOutputStream
* @author raul
*
*/
public class UnsyncByteArrayOutputStream extends OutputStream {
- private static ThreadLocal bufCahce = new ThreadLocal() {
+ private static final int INITIAL_SIZE = 8192;
+ private static ThreadLocal bufCache = new ThreadLocal() {
protected synchronized Object initialValue() {
- return new byte[8*1024];
+ return new byte[INITIAL_SIZE];
}
};
- byte[] buf;
- int size=8*1024;//buf.length;
- int pos=0;
- public UnsyncByteArrayOutputStream() {
- buf=(byte[])bufCahce.get();
- }
- /** @inheritDoc */
- public void write(byte[] arg0) {
- int newPos=pos+arg0.length;
- if (newPos>size) {
- expandSize();
- }
- System.arraycopy(arg0,0,buf,pos,arg0.length);
- pos=newPos;
- }
- /** @inheritDoc */
- public void write(byte[] arg0, int arg1, int arg2) {
- int newPos=pos+arg2;
- if (newPos>size) {
- expandSize();
- }
- System.arraycopy(arg0,arg1,buf,pos,arg2);
- pos=newPos;
- }
- /** @inheritDoc */
- public void write(int arg0) {
- if (pos>=size) {
- expandSize();
- }
- buf[pos++]=(byte)arg0;
- }
- /** @inheritDoc */
- public byte[] toByteArray() {
- byte result[]=new byte[pos];
- System.arraycopy(buf,0,result,0,pos);
- return result;
- }
- /** @inheritDoc */
- public void reset() {
- pos=0;
- }
+ private byte[] buf;
+ private int size = INITIAL_SIZE;
+ private int pos = 0;
- /** @inheritDoc */
- void expandSize() {
- int newSize=size<<2;
- byte newBuf[]=new byte[newSize];
- System.arraycopy(buf,0,newBuf,0,pos);
- buf=newBuf;
- size=newSize;
+ public UnsyncByteArrayOutputStream() {
+ buf = (byte[])bufCache.get();
+ }
+ public void write(byte[] arg0) {
+ int newPos = pos + arg0.length;
+ if (newPos > size) {
+ expandSize(newPos);
}
+ System.arraycopy(arg0, 0, buf, pos, arg0.length);
+ pos = newPos;
+ }
+
+ public void write(byte[] arg0, int arg1, int arg2) {
+ int newPos = pos + arg2;
+ if (newPos > size) {
+ expandSize(newPos);
+ }
+ System.arraycopy(arg0, arg1, buf, pos, arg2);
+ pos = newPos;
+ }
+
+ public void write(int arg0) {
+ int newPos = pos + 1;
+ if (newPos > size) {
+ expandSize(newPos);
+ }
+ buf[pos++] = (byte)arg0;
+ }
+
+ public byte[] toByteArray() {
+ byte result[] = new byte[pos];
+ System.arraycopy(buf, 0, result, 0, pos);
+ return result;
+ }
+
+ public void reset() {
+ pos = 0;
+ }
+
+ private void expandSize(int newPos) {
+ int newSize = size;
+ while (newPos > newSize) {
+ newSize = newSize<<2;
+ }
+ byte newBuf[] = new byte[newSize];
+ System.arraycopy(buf, 0, newBuf, 0, pos);
+ buf = newBuf;
+ size = newSize;
+ }
}
diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java
index 3e2effd1dc0..36a3502e3ba 100644
--- a/jdk/src/share/classes/java/awt/Dialog.java
+++ b/jdk/src/share/classes/java/awt/Dialog.java
@@ -1068,7 +1068,7 @@ public class Dialog extends Window {
modalityPushed();
try {
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
- secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 5000);
+ secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 0);
if (!secondaryLoop.enter()) {
secondaryLoop = null;
}
diff --git a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java
index 0c272763508..07ecefe1def 100644
--- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java
@@ -142,6 +142,9 @@ public abstract class KeyboardFocusManager
public void removeLastFocusRequest(Component heavyweight) {
KeyboardFocusManager.removeLastFocusRequest(heavyweight);
}
+ public void setMostRecentFocusOwner(Window window, Component component) {
+ KeyboardFocusManager.setMostRecentFocusOwner(window, component);
+ }
}
);
}
diff --git a/jdk/src/share/classes/java/awt/event/ActionEvent.java b/jdk/src/share/classes/java/awt/event/ActionEvent.java
index ec29e6d09f5..3d5280aa658 100644
--- a/jdk/src/share/classes/java/awt/event/ActionEvent.java
+++ b/jdk/src/share/classes/java/awt/event/ActionEvent.java
@@ -51,7 +51,7 @@ import java.awt.Event;
* in the range from {@code ACTION_FIRST} to {@code ACTION_LAST}.
*
* @see ActionListener
- * @see Tutorial: Java 1.1 Event Model
+ * @see Tutorial: How to Write an Action Listener
*
* @author Carl Quinn
* @since 1.1
diff --git a/jdk/src/share/classes/java/awt/image/SampleModel.java b/jdk/src/share/classes/java/awt/image/SampleModel.java
index cb7bd8a491f..a2b02c44a62 100644
--- a/jdk/src/share/classes/java/awt/image/SampleModel.java
+++ b/jdk/src/share/classes/java/awt/image/SampleModel.java
@@ -937,14 +937,22 @@ public abstract class SampleModel
int iArray[], DataBuffer data) {
int pixels[];
int Offset=0;
+ int x1 = x + w;
+ int y1 = y + h;
+
+ if (x < 0 || x1 < x || x1 > width ||
+ y < 0 || y1 < y || y1 > height)
+ {
+ throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
+ }
if (iArray != null)
pixels = iArray;
else
pixels = new int[w * h];
- for(int i=y; i<(h+y); i++) {
- for (int j=x; j<(w+x); j++) {
+ for(int i=y; i width ||
+ y < 0 || y1 < y || y1 > height)
+ {
+ throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
+ }
if (fArray != null)
pixels = fArray;
else
pixels = new float[w * h];
- for (int i=y; i<(h+y); i++) {
- for (int j=x; j<(w+x); j++) {
+ for (int i=y; i width ||
+ y < 0 || y1 < y || y1 > height)
+ {
+ throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
+ }
if (dArray != null)
pixels = dArray;
else
pixels = new double[w * h];
- for (int i=y; i<(y+h); i++) {
- for (int j=x; j<(x+w); j++) {
+ for (int i=y; i type, String name, int args) {
- for (Method method : type.getMethods()) {
- if (method.getName().equals(name) && (args == method.getParameterTypes().length)) {
- try {
- return MethodFinder.findAccessibleMethod(method);
+ /**
+ * Internal support for finding a target methodName with a given
+ * parameter list on a given class.
+ */
+ private static Method internalFindMethod(Class start, String methodName,
+ int argCount, Class args[]) {
+ // For overriden methods we need to find the most derived version.
+ // So we start with the given class and walk up the superclass chain.
+
+ Method method = null;
+
+ for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
+ Method methods[] = getPublicDeclaredMethods(cl);
+ for (int i = 0; i < methods.length; i++) {
+ method = methods[i];
+ if (method == null) {
+ continue;
}
- catch (NoSuchMethodException exception) {
- // continue search for a method with the specified count of parameters
+
+ // make sure method signature matches.
+ Class params[] = FeatureDescriptor.getParameterTypes(start, method);
+ if (method.getName().equals(methodName) &&
+ params.length == argCount) {
+ if (args != null) {
+ boolean different = false;
+ if (argCount > 0) {
+ for (int j = 0; j < argCount; j++) {
+ if (params[j] != args[j]) {
+ different = true;
+ continue;
+ }
+ }
+ if (different) {
+ continue;
+ }
+ }
+ }
+ return method;
}
}
}
- return null;
+ method = null;
+
+ // Now check any inherited interfaces. This is necessary both when
+ // the argument class is itself an interface, and when the argument
+ // class is an abstract class.
+ Class ifcs[] = start.getInterfaces();
+ for (int i = 0 ; i < ifcs.length; i++) {
+ // Note: The original implementation had both methods calling
+ // the 3 arg method. This is preserved but perhaps it should
+ // pass the args array instead of null.
+ method = internalFindMethod(ifcs[i], methodName, argCount, null);
+ if (method != null) {
+ break;
+ }
+ }
+ return method;
}
- static Method findInstanceMethod(Class> type, String name, Class>... args) {
- try {
- return MethodFinder.findInstanceMethod(type, name, args);
- }
- catch (NoSuchMethodException exception) {
+ /**
+ * Find a target methodName on a given class.
+ */
+ static Method findMethod(Class cls, String methodName, int argCount) {
+ return findMethod(cls, methodName, argCount, null);
+ }
+
+ /**
+ * Find a target methodName with specific parameter list on a given class.
+ *
+ * Used in the contructors of the EventSetDescriptor,
+ * PropertyDescriptor and the IndexedPropertyDescriptor.
+ *
+ * @param cls The Class object on which to retrieve the method.
+ * @param methodName Name of the method.
+ * @param argCount Number of arguments for the desired method.
+ * @param args Array of argument types for the method.
+ * @return the method or null if not found
+ */
+ static Method findMethod(Class cls, String methodName, int argCount,
+ Class args[]) {
+ if (methodName == null) {
return null;
}
+ return internalFindMethod(cls, methodName, argCount, args);
}
/**
diff --git a/jdk/src/share/classes/java/beans/MethodDescriptor.java b/jdk/src/share/classes/java/beans/MethodDescriptor.java
index 74a7a16782d..d9e78be516f 100644
--- a/jdk/src/share/classes/java/beans/MethodDescriptor.java
+++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java
@@ -90,13 +90,13 @@ public class MethodDescriptor extends FeatureDescriptor {
// Find methods for up to 2 params. We are guessing here.
// This block should never execute unless the classloader
// that loaded the argument classes disappears.
- method = Introspector.findMethod(cls, name, i);
+ method = Introspector.findMethod(cls, name, i, null);
if (method != null) {
break;
}
}
} else {
- method = Statement.getMethod(cls, name, params);
+ method = Introspector.findMethod(cls, name, params.length, params);
}
setMethod(method);
}
diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java
index c7524e3026f..429d2b4079b 100644
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java
@@ -112,7 +112,8 @@ public class PropertyDescriptor extends FeatureDescriptor {
// If this class or one of its base classes allow PropertyChangeListener,
// then we assume that any properties we discover are "bound".
// See Introspector.getTargetPropertyInfo() method.
- this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class);
+ Class[] args = { PropertyChangeListener.class };
+ this.bound = null != Introspector.findMethod(beanClass, "addPropertyChangeListener", args.length, args);
}
/**
@@ -223,10 +224,10 @@ public class PropertyDescriptor extends FeatureDescriptor {
// property type is. For booleans, there can be "is" and "get"
// methods. If an "is" method exists, this is the official
// reader method so look for this one first.
- readMethod = Introspector.findInstanceMethod(cls, readMethodName);
+ readMethod = Introspector.findMethod(cls, readMethodName, 0);
if (readMethod == null) {
readMethodName = Introspector.GET_PREFIX + getBaseName();
- readMethod = Introspector.findInstanceMethod(cls, readMethodName);
+ readMethod = Introspector.findMethod(cls, readMethodName, 0);
}
try {
setReadMethod(readMethod);
@@ -291,7 +292,8 @@ public class PropertyDescriptor extends FeatureDescriptor {
writeMethodName = Introspector.SET_PREFIX + getBaseName();
}
- writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type);
+ Class[] args = (type == null) ? null : new Class[] { type };
+ writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args);
if (writeMethod != null) {
if (!writeMethod.getReturnType().equals(void.class)) {
writeMethod = null;
diff --git a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java
index 46a14a0aa20..d495f07c3f6 100644
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java
@@ -100,7 +100,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @param minimumCapacity the minimum desired capacity.
*/
public void ensureCapacity(int minimumCapacity) {
- ensureCapacityInternal(minimumCapacity);
+ if (minimumCapacity > 0)
+ ensureCapacityInternal(minimumCapacity);
}
/**
@@ -108,6 +109,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* never synchronized.
*/
private void ensureCapacityInternal(int minimumCapacity) {
+ // overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
index fd9ba91d720..ce7f0e655e8 100644
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2010, 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,8 +100,11 @@ import sun.security.util.SecurityConstants;
* themselves at their class initialization time by invoking the
* {@link
* #registerAsParallelCapable ClassLoader.registerAsParallelCapable}
- * method. In environments in which the delegation model is not strictly
- * hierarchical, class loaders need to be parallel capable, otherise class
+ * method. Note that the ClassLoader class is registered as parallel
+ * capable by default. However, its subclasses still need to register themselves
+ * if they are parallel capable.
+ * In environments in which the delegation model is not strictly
+ * hierarchical, class loaders need to be parallel capable, otherwise class
* loading can lead to deadlocks because the loader lock is held for the
* duration of the class loading process (see {@link #loadClass
* loadClass} methods).
@@ -1218,14 +1221,14 @@ public abstract class ClassLoader {
private static native Class extends ClassLoader> getCaller(int index);
/**
- * Registers the caller class loader as parallel capable.
- * In order for the registration to succeed, all super classes
- * of the caller class loader must also be registered as
- * parallel capable when this method is called.
- * Note that once a class loader is registered as
- * parallel capable, there is no way to change it back.
- * In addition, registration should be done statically before
- * any instance of the caller classloader being constructed.
+ * Registers the caller as parallel capable.
+ * The registration succeeds if and only if all of the following
+ * conditions are met:
+ * 1. no instance of the caller has been created
+ * 2. all of the super classes (except class Object) of the caller are
+ * registered as parallel capable
+ * Note that once a class loader is registered as parallel capable, there
+ * is no way to change it back.
*
* @return true if the caller is successfully registered as
* parallel capable and false if otherwise.
diff --git a/jdk/src/share/classes/java/lang/Integer.java b/jdk/src/share/classes/java/lang/Integer.java
index ab68cf23c25..ab68f4b2558 100644
--- a/jdk/src/share/classes/java/lang/Integer.java
+++ b/jdk/src/share/classes/java/lang/Integer.java
@@ -586,25 +586,13 @@ public final class Integer extends Number implements Comparable {
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
- * The cache is initialized on first usage. During VM initialization the
- * getAndRemoveCacheProperties method may be used to get and remove any system
- * properites that configure the cache size. At this time, the size of the
- * cache may be controlled by the -XX:AutoBoxCacheMax= option.
+ * The cache is initialized on first usage. The size of the cache
+ * may be controlled by the -XX:AutoBoxCacheMax= option.
+ * During VM initialization, java.lang.Integer.IntegerCache.high property
+ * may be set and saved in the private system properties in the
+ * sun.misc.VM class.
*/
- // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
- private static String integerCacheHighPropValue;
-
- static void getAndRemoveCacheProperties() {
- if (!sun.misc.VM.isBooted()) {
- Properties props = System.getProperties();
- integerCacheHighPropValue =
- (String)props.remove("java.lang.Integer.IntegerCache.high");
- if (integerCacheHighPropValue != null)
- System.setProperties(props); // remove from system props
- }
- }
-
private static class IntegerCache {
static final int low = -128;
static final int high;
@@ -613,6 +601,8 @@ public final class Integer extends Number implements Comparable {
static {
// high value may be configured by property
int h = 127;
+ String integerCacheHighPropValue =
+ sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java
index 42431865f25..6df4af69505 100644
--- a/jdk/src/share/classes/java/lang/System.java
+++ b/jdk/src/share/classes/java/lang/System.java
@@ -53,7 +53,13 @@ import sun.reflect.annotation.AnnotationType;
*/
public final class System {
- /* First thing---register the natives */
+ /* register the natives via the static initializer.
+ *
+ * VM will invoke the initializeSystemClass method to complete
+ * the initialization for this class separated from clinit.
+ * Note that to use properties set by the VM, see the constraints
+ * described in the initializeSystemClass method.
+ */
private static native void registerNatives();
static {
registerNatives();
@@ -1096,17 +1102,21 @@ public final class System {
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
- props = new Properties();
- initProperties(props);
+ // There are certain system configurations that may be controlled by
+ // VM options such as the maximum amount of direct memory and
+ // Integer cache size used to support the object identity semantics
+ // of autoboxing. Typically, the library will obtain these values
+ // from the properties set by the VM. If the properties are for
+ // internal implementation use only, these properties should be
+ // removed from the system properties.
+ //
+ // See java.lang.Integer.IntegerCache and the
+ // sun.misc.VM.saveAndRemoveProperties method for example.
+ props = initSystemProperties();
+
lineSeparator = props.getProperty("line.separator");
sun.misc.Version.init();
- // Gets and removes system properties that configure the Integer
- // cache used to support the object identity semantics of autoboxing.
- // At this time, the size of the cache may be controlled by the
- // vm option -XX:AutoBoxCacheMax=.
- Integer.getAndRemoveCacheProperties();
-
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
@@ -1127,17 +1137,6 @@ public final class System {
// classes are used.
sun.misc.VM.initializeOSEnvironment();
- // Set the maximum amount of direct memory. This value is controlled
- // by the vm option -XX:MaxDirectMemorySize=. This method acts
- // as an initializer only if it is called before sun.misc.VM.booted().
- sun.misc.VM.maxDirectMemory();
-
- // Set a boolean to determine whether ClassLoader.loadClass accepts
- // array syntax. This value is controlled by the system property
- // "sun.lang.ClassLoader.allowArraySyntax". This method acts as
- // an initializer only if it is called before sun.misc.VM.booted().
- sun.misc.VM.allowArraySyntax();
-
// Subsystems that are invoked during initialization can invoke
// sun.misc.VM.isBooted() in order to avoid doing things that should
// wait until the application class loader has been set up.
@@ -1152,6 +1151,18 @@ public final class System {
setJavaLangAccess();
}
+ private static Properties initSystemProperties() {
+ Properties props = new Properties();
+ initProperties(props); // initialized by the VM
+
+ // Save a private copy of the system properties object that
+ // can only be accessed by the internal implementation. Remove
+ // certain system properties that are not intended for public access.
+ sun.misc.VM.saveAndRemoveProperties(props);
+
+ return props;
+ }
+
private static void setJavaLangAccess() {
// Allow privileged classes outside of java.lang
sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess(){
diff --git a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
index d8053d7b719..a902de61212 100644
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
@@ -28,9 +28,7 @@ package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.InterruptedIOException;
import java.io.FileDescriptor;
-import java.io.ByteArrayOutputStream;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
@@ -58,7 +56,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected int fdUseCount = 0;
/* lock when increment/decrementing fdUseCount */
- protected Object fdLock = new Object();
+ protected final Object fdLock = new Object();
/* indicates a close is pending on the file descriptor */
protected boolean closePending = false;
@@ -68,7 +66,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
private int CONNECTION_RESET_PENDING = 1;
private int CONNECTION_RESET = 2;
private int resetState;
- private Object resetLock = new Object();
+ private final Object resetLock = new Object();
/**
* Load net library into runtime.
@@ -100,25 +98,24 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected void connect(String host, int port)
throws UnknownHostException, IOException
{
- IOException pending = null;
+ boolean connected = false;
try {
InetAddress address = InetAddress.getByName(host);
this.port = port;
this.address = address;
- try {
- connectToAddress(address, port, timeout);
- return;
- } catch (IOException e) {
- pending = e;
+ connectToAddress(address, port, timeout);
+ connected = true;
+ } finally {
+ if (!connected) {
+ try {
+ close();
+ } catch (IOException ioe) {
+ /* Do nothing. If connect threw an exception then
+ it will be passed up the call stack */
+ }
}
- } catch (UnknownHostException e) {
- pending = e;
}
-
- // everything failed
- close();
- throw pending;
}
/**
@@ -151,22 +148,29 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
* SocketAddress subclass not supported by this socket
* @since 1.4
*/
- protected void connect(SocketAddress address, int timeout) throws IOException {
- if (address == null || !(address instanceof InetSocketAddress))
- throw new IllegalArgumentException("unsupported address type");
- InetSocketAddress addr = (InetSocketAddress) address;
- if (addr.isUnresolved())
- throw new UnknownHostException(addr.getHostName());
- this.port = addr.getPort();
- this.address = addr.getAddress();
-
+ protected void connect(SocketAddress address, int timeout)
+ throws IOException {
+ boolean connected = false;
try {
+ if (address == null || !(address instanceof InetSocketAddress))
+ throw new IllegalArgumentException("unsupported address type");
+ InetSocketAddress addr = (InetSocketAddress) address;
+ if (addr.isUnresolved())
+ throw new UnknownHostException(addr.getHostName());
+ this.port = addr.getPort();
+ this.address = addr.getAddress();
+
connectToAddress(this.address, port, timeout);
- return;
- } catch (IOException e) {
- // everything failed
- close();
- throw e;
+ connected = true;
+ } finally {
+ if (!connected) {
+ try {
+ close();
+ } catch (IOException ioe) {
+ /* Do nothing. If connect threw an exception then
+ it will be passed up the call stack */
+ }
+ }
}
}
@@ -311,7 +315,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
}
}
try {
- FileDescriptor fd = acquireFD();
+ acquireFD();
try {
socketConnect(address, port, timeout);
/* socket may have been closed during poll/select */
@@ -370,7 +374,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
* @param s the connection
*/
protected void accept(SocketImpl s) throws IOException {
- FileDescriptor fd = acquireFD();
+ acquireFD();
try {
socketAccept(s);
} finally {
@@ -562,7 +566,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
close();
}
-
/*
* "Acquires" and returns the FileDescriptor for this impl
*
diff --git a/jdk/src/share/classes/java/nio/Bits.java b/jdk/src/share/classes/java/nio/Bits.java
index fa11b6be785..54f004b6ea9 100644
--- a/jdk/src/share/classes/java/nio/Bits.java
+++ b/jdk/src/share/classes/java/nio/Bits.java
@@ -622,7 +622,7 @@ class Bits { // package-private
// initialization if it is launched with "-XX:MaxDirectMemorySize=".
private static volatile long maxMemory = VM.maxDirectMemory();
private static volatile long reservedMemory;
- private static volatile long usedMemory;
+ private static volatile long totalCapacity;
private static volatile long count;
private static boolean memoryLimitSet = false;
@@ -630,15 +630,17 @@ class Bits { // package-private
// freed. They allow the user to control the amount of direct memory
// which a process may access. All sizes are specified in bytes.
static void reserveMemory(long size, int cap) {
-
synchronized (Bits.class) {
if (!memoryLimitSet && VM.isBooted()) {
maxMemory = VM.maxDirectMemory();
memoryLimitSet = true;
}
- if (size <= maxMemory - reservedMemory) {
+ // -XX:MaxDirectMemorySize limits the total capacity rather than the
+ // actual memory usage, which will differ when buffers are page
+ // aligned.
+ if (cap <= maxMemory - totalCapacity) {
reservedMemory += size;
- usedMemory += cap;
+ totalCapacity += cap;
count++;
return;
}
@@ -652,10 +654,10 @@ class Bits { // package-private
Thread.currentThread().interrupt();
}
synchronized (Bits.class) {
- if (reservedMemory + size > maxMemory)
+ if (totalCapacity + cap > maxMemory)
throw new OutOfMemoryError("Direct buffer memory");
reservedMemory += size;
- usedMemory += cap;
+ totalCapacity += cap;
count++;
}
@@ -664,7 +666,7 @@ class Bits { // package-private
static synchronized void unreserveMemory(long size, int cap) {
if (reservedMemory > 0) {
reservedMemory -= size;
- usedMemory -= cap;
+ totalCapacity -= cap;
count--;
assert (reservedMemory > -1);
}
@@ -689,7 +691,7 @@ class Bits { // package-private
}
@Override
public long getTotalCapacity() {
- return Bits.usedMemory;
+ return Bits.totalCapacity;
}
@Override
public long getMemoryUsed() {
diff --git a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template
index 520b9c46504..0b785175a66 100644
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template
+++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template
@@ -27,8 +27,10 @@
package java.nio;
+import java.io.FileDescriptor;
import sun.misc.Cleaner;
import sun.misc.Unsafe;
+import sun.misc.VM;
import sun.nio.ch.DirectBuffer;
@@ -113,9 +115,10 @@ class Direct$Type$Buffer$RW$$BO$
//
Direct$Type$Buffer$RW$(int cap) { // package-private
#if[rw]
- super(-1, 0, cap, cap, false);
+ super(-1, 0, cap, cap);
+ boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
- int size = cap + ps;
+ long size = Math.max(1L, (long)cap + (pa ? ps : 0));
Bits.reserveMemory(size, cap);
long base = 0;
@@ -126,7 +129,7 @@ class Direct$Type$Buffer$RW$$BO$
throw x;
}
unsafe.setMemory(base, size, (byte) 0);
- if (base % ps != 0) {
+ if (pa && (base % ps != 0)) {
// Round up to page boundary
address = base + ps - (base & (ps - 1));
} else {
@@ -143,7 +146,7 @@ class Direct$Type$Buffer$RW$$BO$
// Invoked only by JNI: NewDirectByteBuffer(void*, long)
//
private Direct$Type$Buffer(long addr, int cap) {
- super(-1, 0, cap, cap, false);
+ super(-1, 0, cap, cap);
address = addr;
cleaner = null;
}
@@ -152,14 +155,17 @@ class Direct$Type$Buffer$RW$$BO$
// For memory-mapped buffers -- invoked by FileChannelImpl via reflection
//
- protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
+ protected Direct$Type$Buffer$RW$(int cap, long addr,
+ FileDescriptor fd,
+ Runnable unmapper)
+ {
#if[rw]
- super(-1, 0, cap, cap, true);
+ super(-1, 0, cap, cap, fd);
address = addr;
viewedBuffer = null;
cleaner = Cleaner.create(this, unmapper);
#else[rw]
- super(cap, addr, unmapper);
+ super(cap, addr, fd, unmapper);
#end[rw]
}
diff --git a/jdk/src/share/classes/java/nio/MappedByteBuffer.java b/jdk/src/share/classes/java/nio/MappedByteBuffer.java
index 4811f41d2e1..9c2a446716f 100644
--- a/jdk/src/share/classes/java/nio/MappedByteBuffer.java
+++ b/jdk/src/share/classes/java/nio/MappedByteBuffer.java
@@ -25,6 +25,7 @@
package java.nio;
+import java.io.FileDescriptor;
import sun.misc.Unsafe;
@@ -71,26 +72,26 @@ public abstract class MappedByteBuffer
// for optimization purposes, it's easier to do it the other way around.
// This works because DirectByteBuffer is a package-private class.
- // Volatile to make sure that the finalization thread sees the current
- // value of this so that a region is not accidentally unmapped again later.
- volatile boolean isAMappedBuffer; // package-private
+ // For mapped buffers, a FileDescriptor that may be used for mapping
+ // operations if valid; null if the buffer is not mapped.
+ private final FileDescriptor fd;
// This should only be invoked by the DirectByteBuffer constructors
//
MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
- boolean mapped)
+ FileDescriptor fd)
{
super(mark, pos, lim, cap);
- isAMappedBuffer = mapped;
+ this.fd = fd;
}
MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
super(mark, pos, lim, cap);
- isAMappedBuffer = false;
+ this.fd = null;
}
private void checkMapped() {
- if (!isAMappedBuffer)
+ if (fd == null)
// Can only happen if a luser explicitly casts a direct byte buffer
throw new UnsupportedOperationException();
}
@@ -191,13 +192,12 @@ public abstract class MappedByteBuffer
checkMapped();
if ((address != 0) && (capacity() != 0)) {
long offset = mappingOffset();
- force0(mappingAddress(offset), mappingLength(offset));
+ force0(fd, mappingAddress(offset), mappingLength(offset));
}
return this;
}
private native boolean isLoaded0(long address, long length, int pageCount);
private native void load0(long address, long length);
- private native void force0(long address, long length);
-
+ private native void force0(FileDescriptor fd, long address, long length);
}
diff --git a/jdk/src/share/classes/java/security/cert/CertificateRevokedException.java b/jdk/src/share/classes/java/security/cert/CertificateRevokedException.java
index 7f4660bd74c..a76299ccc0d 100644
--- a/jdk/src/share/classes/java/security/cert/CertificateRevokedException.java
+++ b/jdk/src/share/classes/java/security/cert/CertificateRevokedException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, 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
@@ -61,8 +61,8 @@ public class CertificateRevokedException extends CertificateException {
*/
private final CRLReason reason;
/**
- * @serial the name of the authority that signed the certificate's
- * revocation status information
+ * @serial the X500Principal that represents the name of the
+ * authority that signed the certificate's revocation status information
*/
private final X500Principal authority;
@@ -79,8 +79,9 @@ public class CertificateRevokedException extends CertificateException {
* @param extensions a map of X.509 Extensions. Each key is an OID String
* that maps to the corresponding Extension. The map is copied to
* prevent subsequent modification.
- * @param authority the name of the authority that signed the certificate's
- * revocation status information
+ * @param authority the X500Principal that represents the name
+ * of the authority that signed the certificate's revocation status
+ * information
* @throws NullPointerException if revocationDate,
* reason, authority, or
* extensions is null
@@ -121,8 +122,8 @@ public class CertificateRevokedException extends CertificateException {
* Returns the name of the authority that signed the certificate's
* revocation status information.
*
- * @return the name of the authority that signed the certificate's
- * revocation status information
+ * @return the X500Principal that represents the name of the
+ * authority that signed the certificate's revocation status information
*/
public X500Principal getAuthorityName() {
return authority;
diff --git a/jdk/src/share/classes/java/util/ArrayList.java b/jdk/src/share/classes/java/util/ArrayList.java
index 4b746ea0124..7c6eded3a83 100644
--- a/jdk/src/share/classes/java/util/ArrayList.java
+++ b/jdk/src/share/classes/java/util/ArrayList.java
@@ -176,6 +176,11 @@ public class ArrayList extends AbstractList
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
+ if (minCapacity > 0)
+ ensureCapacityInternal(minCapacity);
+ }
+
+ private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
@@ -403,7 +408,7 @@ public class ArrayList extends AbstractList
* @return true (as specified by {@link Collection#add})
*/
public boolean add(E e) {
- ensureCapacity(size + 1); // Increments modCount!!
+ ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
@@ -420,7 +425,7 @@ public class ArrayList extends AbstractList
public void add(int index, E element) {
rangeCheckForAdd(index);
- ensureCapacity(size + 1); // Increments modCount!!
+ ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
@@ -524,7 +529,7 @@ public class ArrayList extends AbstractList
public boolean addAll(Collection extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
- ensureCapacity(size + numNew); // Increments modCount
+ ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
@@ -550,7 +555,7 @@ public class ArrayList extends AbstractList
Object[] a = c.toArray();
int numNew = a.length;
- ensureCapacity(size + numNew); // Increments modCount
+ ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
diff --git a/jdk/src/share/classes/java/util/Arrays.java b/jdk/src/share/classes/java/util/Arrays.java
index 54abbb27c8d..b4951e14f11 100644
--- a/jdk/src/share/classes/java/util/Arrays.java
+++ b/jdk/src/share/classes/java/util/Arrays.java
@@ -97,7 +97,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(int[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
@@ -136,7 +137,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(long[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
@@ -175,7 +177,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(short[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
@@ -214,7 +217,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(char[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
@@ -253,7 +257,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(byte[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
@@ -308,7 +313,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(float[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/**
@@ -363,12 +369,12 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public static void sort(double[] a, int fromIndex, int toIndex) {
- DualPivotQuicksort.sort(a, fromIndex, toIndex);
+ rangeCheck(a.length, fromIndex, toIndex);
+ DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
}
/*
* Sorting of complex type arrays.
- *
*/
/**
diff --git a/jdk/src/share/classes/java/util/DualPivotQuicksort.java b/jdk/src/share/classes/java/util/DualPivotQuicksort.java
index 873230a2c73..616ee2e2fe2 100644
--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java
@@ -36,7 +36,7 @@ package java.util;
* @author Jon Bentley
* @author Josh Bloch
*
- * @version 2010.06.21 m765.827.12i:5\7
+ * @version 2010.10.13 m765.827.12i:5\7p
* @since 1.7
*/
final class DualPivotQuicksort {
@@ -54,26 +54,26 @@ final class DualPivotQuicksort {
* If the length of an array to be sorted is less than this
* constant, insertion sort is used in preference to Quicksort.
*/
- private static final int INSERTION_SORT_THRESHOLD = 32;
+ private static final int INSERTION_SORT_THRESHOLD = 47;
/**
- * If the length of a byte array to be sorted is greater than
- * this constant, counting sort is used in preference to Quicksort.
+ * If the length of a byte array to be sorted is greater than this
+ * constant, counting sort is used in preference to insertion sort.
*/
- private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 128;
+ private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 29;
/**
* If the length of a short or char array to be sorted is greater
* than this constant, counting sort is used in preference to Quicksort.
*/
- private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
+ private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 3200;
/*
* Sorting methods for seven primitive types.
*/
/**
- * Sorts the specified array into ascending numerical order.
+ * Sorts the specified array.
*
* @param a the array to be sorted
*/
@@ -82,58 +82,34 @@ final class DualPivotQuicksort {
}
/**
- * 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 (and the call is a no-op).
- *
- * @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}
- */
- public static void sort(int[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- sort(a, fromIndex, toIndex - 1, true);
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
+ * 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
- * @param leftmost indicates if the part is the most left in the range
+ */
+ public static void sort(int[] a, int left, int right) {
+ sort(a, left, right, true);
+ }
+
+ /**
+ * Sorts the specified range of the array by Dual-Pivot Quicksort.
+ *
+ * @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 leftmost indicates if this part is the leftmost in the range
*/
private static void sort(int[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on tiny arrays
+ // Use insertion sort on small arrays
if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
+ if (leftmost) {
/*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- int ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
+ * Traditional (without sentinel) insertion sort,
+ * optimized for server VM, is used in case of
+ * the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
int ai = a[i + 1];
@@ -145,12 +121,54 @@ final class DualPivotQuicksort {
}
a[j + 1] = ai;
}
+ } else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left++ >= right) {
+ return;
+ }
+ } while (a[left - 1] <= a[left]);
+
+ /*
+ * Every element from adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid the
+ * left range check on each iteration. Moreover, we use
+ * the best improved algorithm, so called pair insertion
+ * sort, which is faster than traditional implementation
+ * in the context of Dual-Pivot Quicksort.
+ */
+ for (int k = left--; (left += 2) <= right; ) {
+ int a1, a2; k = left - 1;
+
+ if (a[k] < a[left]) {
+ a2 = a[k]; a1 = a[left];
+ } else {
+ a1 = a[k]; a2 = a[left];
+ }
+ while (a1 < a[--k]) {
+ a[k + 2] = a[k];
+ }
+ a[++k + 1] = a1;
+
+ while (a2 < a[--k]) {
+ a[k + 1] = a[k];
+ }
+ a[k + 1] = a2;
+ }
+ int last = a[right];
+
+ while (last < a[--right]) {
+ a[right + 1] = a[right];
+ }
+ a[right + 1] = last;
}
return;
}
// Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
+ int seventh = (length >> 3) + (length >> 6) + 1;
/*
* Sort five evenly spaced elements around (and including) the
@@ -232,10 +250,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
int ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
+ /*
+ * Here and below we use "a[i] = b; i++;" instead
+ * of "a[i++] = b;" due to performance issue.
+ */
a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
@@ -244,13 +266,17 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
+ /*
+ * Here and below we use "a[i] = b; i--;" instead
+ * of "a[i--] = b;" due to performance issue.
+ */
a[great] = ak;
great--;
}
@@ -265,7 +291,7 @@ final class DualPivotQuicksort {
sort(a, great + 2, right, false);
/*
- * If center part is too large (comprises > 5/7 of the array),
+ * If center part is too large (comprises > 4/7 of the array),
* swap internal pivot values to ends.
*/
if (less < e1 && e5 < great) {
@@ -299,7 +325,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
int ak = a[k];
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
@@ -311,7 +337,7 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] == pivot1) {
+ if (a[great] == pivot1) { // a[great] < pivot2
a[k] = a[less];
/*
* Even though a[great] equals to pivot1, the
@@ -337,7 +363,7 @@ final class DualPivotQuicksort {
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way
+ * Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
@@ -356,28 +382,20 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left; k <= great; k++) {
+ for (int k = less; k <= great; ++k) {
if (a[k] == pivot1) {
continue;
}
int ak = a[k];
-
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
less++;
} else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
while (a[great] > pivot1) {
- // assert great > k;
great--;
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot1
a[k] = a[less];
a[less] = a[great];
less++;
@@ -397,14 +415,18 @@ final class DualPivotQuicksort {
}
}
- // Sort left and right parts recursively
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
sort(a, left, less - 1, leftmost);
sort(a, great + 1, right, false);
}
}
/**
- * Sorts the specified array into ascending numerical order.
+ * Sorts the specified array.
*
* @param a the array to be sorted
*/
@@ -413,58 +435,34 @@ final class DualPivotQuicksort {
}
/**
- * 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 (and the call is a no-op).
- *
- * @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}
- */
- public static void sort(long[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- sort(a, fromIndex, toIndex - 1, true);
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
+ * 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
- * @param leftmost indicates if the part is the most left in the range
+ */
+ public static void sort(long[] a, int left, int right) {
+ sort(a, left, right, true);
+ }
+
+ /**
+ * Sorts the specified range of the array by Dual-Pivot Quicksort.
+ *
+ * @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 leftmost indicates if this part is the leftmost in the range
*/
private static void sort(long[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on tiny arrays
+ // Use insertion sort on small arrays
if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
+ if (leftmost) {
/*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- long ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
+ * Traditional (without sentinel) insertion sort,
+ * optimized for server VM, is used in case of
+ * the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
long ai = a[i + 1];
@@ -476,12 +474,54 @@ final class DualPivotQuicksort {
}
a[j + 1] = ai;
}
+ } else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left++ >= right) {
+ return;
+ }
+ } while (a[left - 1] <= a[left]);
+
+ /*
+ * Every element from adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid the
+ * left range check on each iteration. Moreover, we use
+ * the best improved algorithm, so called pair insertion
+ * sort, which is faster than traditional implementation
+ * in the context of Dual-Pivot Quicksort.
+ */
+ for (int k = left--; (left += 2) <= right; ) {
+ long a1, a2; k = left - 1;
+
+ if (a[k] < a[left]) {
+ a2 = a[k]; a1 = a[left];
+ } else {
+ a1 = a[k]; a2 = a[left];
+ }
+ while (a1 < a[--k]) {
+ a[k + 2] = a[k];
+ }
+ a[++k + 1] = a1;
+
+ while (a2 < a[--k]) {
+ a[k + 1] = a[k];
+ }
+ a[k + 1] = a2;
+ }
+ long last = a[right];
+
+ while (last < a[--right]) {
+ a[right + 1] = a[right];
+ }
+ a[right + 1] = last;
}
return;
}
// Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
+ int seventh = (length >> 3) + (length >> 6) + 1;
/*
* Sort five evenly spaced elements around (and including) the
@@ -563,10 +603,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
long ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
+ /*
+ * Here and below we use "a[i] = b; i++;" instead
+ * of "a[i++] = b;" due to performance issue.
+ */
a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
@@ -575,13 +619,17 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
+ /*
+ * Here and below we use "a[i] = b; i--;" instead
+ * of "a[i--] = b;" due to performance issue.
+ */
a[great] = ak;
great--;
}
@@ -596,7 +644,7 @@ final class DualPivotQuicksort {
sort(a, great + 2, right, false);
/*
- * If center part is too large (comprises > 5/7 of the array),
+ * If center part is too large (comprises > 4/7 of the array),
* swap internal pivot values to ends.
*/
if (less < e1 && e5 < great) {
@@ -630,7 +678,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
long ak = a[k];
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
@@ -642,7 +690,7 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] == pivot1) {
+ if (a[great] == pivot1) { // a[great] < pivot2
a[k] = a[less];
/*
* Even though a[great] equals to pivot1, the
@@ -668,7 +716,7 @@ final class DualPivotQuicksort {
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way
+ * Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
@@ -687,28 +735,20 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left; k <= great; k++) {
+ for (int k = less; k <= great; ++k) {
if (a[k] == pivot1) {
continue;
}
long ak = a[k];
-
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
less++;
} else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
while (a[great] > pivot1) {
- // assert great > k;
great--;
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot1
a[k] = a[less];
a[less] = a[great];
less++;
@@ -728,45 +768,51 @@ final class DualPivotQuicksort {
}
}
- // Sort left and right parts recursively
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
sort(a, left, less - 1, leftmost);
sort(a, great + 1, right, false);
}
}
/**
- * Sorts the specified array into ascending numerical order.
+ * Sorts the specified array.
*
* @param a the array to be sorted
*/
public static void sort(short[] a) {
- if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
- countingSort(a, 0, a.length - 1);
- } else {
- sort(a, 0, a.length - 1, true);
- }
+ sort(a, 0, a.length - 1);
}
/**
- * 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 (and the call is a no-op).
+ * Sorts the specified range of the array.
*
* @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}
+ * @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(short[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
+ public static void sort(short[] a, int left, int right) {
+ // Use counting sort on large arrays
+ if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+ int[] count = new int[NUM_SHORT_VALUES];
- if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
- countingSort(a, fromIndex, toIndex - 1);
- } else {
- sort(a, fromIndex, toIndex - 1, true);
+ for (int i = left - 1; ++i <= right; ) {
+ count[a[i] - Short.MIN_VALUE]++;
+ }
+ for (int i = NUM_SHORT_VALUES, k = right + 1; k > left; ) {
+ while (count[--i] == 0);
+ short value = (short) (i + Short.MIN_VALUE);
+ int s = count[i];
+
+ do {
+ a[--k] = value;
+ } while (--s > 0);
+ }
+ } else { // Use Dual-Pivot Quicksort on small arrays
+ sort(a, left, right, true);
}
}
@@ -774,66 +820,23 @@ final class DualPivotQuicksort {
private static final int NUM_SHORT_VALUES = 1 << 16;
/**
- * Sorts the specified range of the array by counting sort.
+ * Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @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
- */
- private static void countingSort(short[] a, int left, int right) {
- int[] count = new int[NUM_SHORT_VALUES];
-
- for (int i = left; i <= right; i++) {
- count[a[i] - Short.MIN_VALUE]++;
- }
- for (int i = NUM_SHORT_VALUES - 1, k = right; k >= left; i--) {
- while (count[i] == 0) {
- i--;
- }
- short value = (short) (i + Short.MIN_VALUE);
- int s = count[i];
-
- do {
- a[k--] = value;
- } while (--s > 0);
- }
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
- *
- * @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 leftmost indicates if the part is the most left in the range
+ * @param leftmost indicates if this part is the leftmost in the range
*/
private static void sort(short[] a, int left, int right,boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on tiny arrays
+ // Use insertion sort on small arrays
if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
+ if (leftmost) {
/*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- short ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
+ * Traditional (without sentinel) insertion sort,
+ * optimized for server VM, is used in case of
+ * the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
short ai = a[i + 1];
@@ -845,12 +848,54 @@ final class DualPivotQuicksort {
}
a[j + 1] = ai;
}
+ } else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left++ >= right) {
+ return;
+ }
+ } while (a[left - 1] <= a[left]);
+
+ /*
+ * Every element from adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid the
+ * left range check on each iteration. Moreover, we use
+ * the best improved algorithm, so called pair insertion
+ * sort, which is faster than traditional implementation
+ * in the context of Dual-Pivot Quicksort.
+ */
+ for (int k = left--; (left += 2) <= right; ) {
+ short a1, a2; k = left - 1;
+
+ if (a[k] < a[left]) {
+ a2 = a[k]; a1 = a[left];
+ } else {
+ a1 = a[k]; a2 = a[left];
+ }
+ while (a1 < a[--k]) {
+ a[k + 2] = a[k];
+ }
+ a[++k + 1] = a1;
+
+ while (a2 < a[--k]) {
+ a[k + 1] = a[k];
+ }
+ a[k + 1] = a2;
+ }
+ short last = a[right];
+
+ while (last < a[--right]) {
+ a[right + 1] = a[right];
+ }
+ a[right + 1] = last;
}
return;
}
// Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
+ int seventh = (length >> 3) + (length >> 6) + 1;
/*
* Sort five evenly spaced elements around (and including) the
@@ -932,10 +977,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
short ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
+ /*
+ * Here and below we use "a[i] = b; i++;" instead
+ * of "a[i++] = b;" due to performance issue.
+ */
a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
@@ -944,13 +993,17 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
+ /*
+ * Here and below we use "a[i] = b; i--;" instead
+ * of "a[i--] = b;" due to performance issue.
+ */
a[great] = ak;
great--;
}
@@ -965,7 +1018,7 @@ final class DualPivotQuicksort {
sort(a, great + 2, right, false);
/*
- * If center part is too large (comprises > 5/7 of the array),
+ * If center part is too large (comprises > 4/7 of the array),
* swap internal pivot values to ends.
*/
if (less < e1 && e5 < great) {
@@ -999,7 +1052,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
short ak = a[k];
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
@@ -1011,7 +1064,7 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] == pivot1) {
+ if (a[great] == pivot1) { // a[great] < pivot2
a[k] = a[less];
/*
* Even though a[great] equals to pivot1, the
@@ -1037,7 +1090,7 @@ final class DualPivotQuicksort {
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way
+ * Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
@@ -1056,28 +1109,20 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left; k <= great; k++) {
+ for (int k = less; k <= great; ++k) {
if (a[k] == pivot1) {
continue;
}
short ak = a[k];
-
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
less++;
} else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
while (a[great] > pivot1) {
- // assert great > k;
great--;
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot1
a[k] = a[less];
a[less] = a[great];
less++;
@@ -1097,45 +1142,51 @@ final class DualPivotQuicksort {
}
}
- // Sort left and right parts recursively
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
sort(a, left, less - 1, leftmost);
sort(a, great + 1, right, false);
}
}
/**
- * Sorts the specified array into ascending numerical order.
+ * Sorts the specified array.
*
* @param a the array to be sorted
*/
public static void sort(char[] a) {
- if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
- countingSort(a, 0, a.length - 1);
- } else {
- sort(a, 0, a.length - 1, true);
- }
+ sort(a, 0, a.length - 1);
}
/**
- * 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 (and the call is a no-op).
+ * Sorts the specified range of the array.
*
* @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}
+ * @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(char[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
+ public static void sort(char[] a, int left, int right) {
+ // Use counting sort on large arrays
+ if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+ int[] count = new int[NUM_CHAR_VALUES];
- if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
- countingSort(a, fromIndex, toIndex - 1);
- } else {
- sort(a, fromIndex, toIndex - 1, true);
+ for (int i = left - 1; ++i <= right; ) {
+ count[a[i]]++;
+ }
+ for (int i = NUM_CHAR_VALUES, k = right + 1; k > left; ) {
+ while (count[--i] == 0);
+ char value = (char) i;
+ int s = count[i];
+
+ do {
+ a[--k] = value;
+ } while (--s > 0);
+ }
+ } else { // Use Dual-Pivot Quicksort on small arrays
+ sort(a, left, right, true);
}
}
@@ -1143,66 +1194,23 @@ final class DualPivotQuicksort {
private static final int NUM_CHAR_VALUES = 1 << 16;
/**
- * Sorts the specified range of the array by counting sort.
+ * Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @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
- */
- private static void countingSort(char[] a, int left, int right) {
- int[] count = new int[NUM_CHAR_VALUES];
-
- for (int i = left; i <= right; i++) {
- count[a[i]]++;
- }
- for (int i = 0, k = left; k <= right; i++) {
- while (count[i] == 0) {
- i++;
- }
- char value = (char) i;
- int s = count[i];
-
- do {
- a[k++] = value;
- } while (--s > 0);
- }
- }
-
- /**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
- *
- * @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 leftmost indicates if the part is the most left in the range
+ * @param leftmost indicates if this part is the leftmost in the range
*/
private static void sort(char[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on tiny arrays
+ // Use insertion sort on small arrays
if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
+ if (leftmost) {
/*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- char ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
+ * Traditional (without sentinel) insertion sort,
+ * optimized for server VM, is used in case of
+ * the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
char ai = a[i + 1];
@@ -1214,12 +1222,54 @@ final class DualPivotQuicksort {
}
a[j + 1] = ai;
}
+ } else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left++ >= right) {
+ return;
+ }
+ } while (a[left - 1] <= a[left]);
+
+ /*
+ * Every element from adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid the
+ * left range check on each iteration. Moreover, we use
+ * the best improved algorithm, so called pair insertion
+ * sort, which is faster than traditional implementation
+ * in the context of Dual-Pivot Quicksort.
+ */
+ for (int k = left--; (left += 2) <= right; ) {
+ char a1, a2; k = left - 1;
+
+ if (a[k] < a[left]) {
+ a2 = a[k]; a1 = a[left];
+ } else {
+ a1 = a[k]; a2 = a[left];
+ }
+ while (a1 < a[--k]) {
+ a[k + 2] = a[k];
+ }
+ a[++k + 1] = a1;
+
+ while (a2 < a[--k]) {
+ a[k + 1] = a[k];
+ }
+ a[k + 1] = a2;
+ }
+ char last = a[right];
+
+ while (last < a[--right]) {
+ a[right + 1] = a[right];
+ }
+ a[right + 1] = last;
}
return;
}
// Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
+ int seventh = (length >> 3) + (length >> 6) + 1;
/*
* Sort five evenly spaced elements around (and including) the
@@ -1301,10 +1351,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
char ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
+ /*
+ * Here and below we use "a[i] = b; i++;" instead
+ * of "a[i++] = b;" due to performance issue.
+ */
a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
@@ -1313,13 +1367,17 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
+ /*
+ * Here and below we use "a[i] = b; i--;" instead
+ * of "a[i--] = b;" due to performance issue.
+ */
a[great] = ak;
great--;
}
@@ -1334,7 +1392,7 @@ final class DualPivotQuicksort {
sort(a, great + 2, right, false);
/*
- * If center part is too large (comprises > 5/7 of the array),
+ * If center part is too large (comprises > 4/7 of the array),
* swap internal pivot values to ends.
*/
if (less < e1 && e5 < great) {
@@ -1368,7 +1426,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
char ak = a[k];
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
@@ -1380,7 +1438,7 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] == pivot1) {
+ if (a[great] == pivot1) { // a[great] < pivot2
a[k] = a[less];
/*
* Even though a[great] equals to pivot1, the
@@ -1406,7 +1464,7 @@ final class DualPivotQuicksort {
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way
+ * Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
@@ -1425,28 +1483,20 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left; k <= great; k++) {
+ for (int k = less; k <= great; ++k) {
if (a[k] == pivot1) {
continue;
}
char ak = a[k];
-
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
less++;
} else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
while (a[great] > pivot1) {
- // assert great > k;
great--;
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot1
a[k] = a[less];
a[less] = a[great];
less++;
@@ -1466,442 +1516,90 @@ final class DualPivotQuicksort {
}
}
- // Sort left and right parts recursively
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
sort(a, left, less - 1, leftmost);
sort(a, great + 1, right, false);
}
}
- /**
- * Sorts the specified array into ascending numerical order.
- *
- * @param a the array to be sorted
- */
- public static void sort(byte[] a) {
- if (a.length > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
- countingSort(a, 0, a.length - 1);
- } else {
- sort(a, 0, a.length - 1, true);
- }
- }
-
- /**
- * 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 (and the call is a no-op).
- *
- * @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}
- */
- public static void sort(byte[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
-
- if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
- countingSort(a, fromIndex, toIndex - 1);
- } else {
- sort(a, fromIndex, toIndex - 1, true);
- }
- }
-
/** The number of distinct byte values. */
private static final int NUM_BYTE_VALUES = 1 << 8;
/**
- * Sorts the specified range of the array by counting sort.
+ * 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
*/
- private static void countingSort(byte[] a, int left, int right) {
- int[] count = new int[NUM_BYTE_VALUES];
+ public 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];
- for (int i = left; i <= right; i++) {
- count[a[i] - Byte.MIN_VALUE]++;
- }
- for (int i = NUM_BYTE_VALUES - 1, k = right; k >= left; i--) {
- while (count[i] == 0) {
- i--;
+ for (int i = left - 1; ++i <= right; ) {
+ count[a[i] - Byte.MIN_VALUE]++;
}
- byte value = (byte) (i + Byte.MIN_VALUE);
- int s = count[i];
+ for (int i = NUM_BYTE_VALUES, k = right + 1; k > left; ) {
+ while (count[--i] == 0);
+ byte value = (byte) (i + Byte.MIN_VALUE);
+ int s = count[i];
- do {
- a[k--] = value;
- } while (--s > 0);
+ do {
+ a[--k] = value;
+ } while (--s > 0);
+ }
+ } else { // Use insertion sort on small arrays
+ for (int i = left, j = i; i < right; j = ++i) {
+ byte ai = a[i + 1];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
}
}
/**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
- *
- * @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 leftmost indicates if the part is the most left in the range
- */
- private static void sort(byte[] a, int left, int right, boolean leftmost) {
- int length = right - left + 1;
-
- // Use insertion sort on tiny arrays
- if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
- /*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- byte ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
- */
- for (int i = left, j = i; i < right; j = ++i) {
- byte ai = a[i + 1];
- while (ai < a[j]) {
- a[j + 1] = a[j];
- if (j-- == left) {
- break;
- }
- }
- a[j + 1] = ai;
- }
- }
- return;
- }
-
- // Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
-
- /*
- * Sort five evenly spaced elements around (and including) the
- * center element in the range. These elements will be used for
- * pivot selection as described below. The choice for spacing
- * these elements was empirically determined to work well on
- * a wide variety of inputs.
- */
- int e3 = (left + right) >>> 1; // The midpoint
- int e2 = e3 - seventh;
- int e1 = e2 - seventh;
- int e4 = e3 + seventh;
- int e5 = e4 + seventh;
-
- // Sort these elements using insertion sort
- if (a[e2] < a[e1]) { byte t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
-
- if (a[e3] < a[e2]) { byte t = a[e3]; a[e3] = a[e2]; a[e2] = t;
- if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
- }
- if (a[e4] < a[e3]) { byte t = a[e4]; a[e4] = a[e3]; a[e3] = t;
- if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
- if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
- }
- }
- if (a[e5] < a[e4]) { byte t = a[e5]; a[e5] = a[e4]; a[e4] = t;
- if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
- if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
- if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
- }
- }
- }
-
- /*
- * Use the second and fourth of the five sorted elements as pivots.
- * These values are inexpensive approximations of the first and
- * second terciles of the array. Note that pivot1 <= pivot2.
- */
- byte pivot1 = a[e2];
- byte pivot2 = a[e4];
-
- // Pointers
- int less = left; // The index of the first element of center part
- int great = right; // The index before the first element of right part
-
- if (pivot1 != pivot2) {
- /*
- * The first and the last elements to be sorted are moved to the
- * locations formerly occupied by the pivots. When partitioning
- * is complete, the pivots are swapped back into their final
- * positions, and excluded from subsequent sorting.
- */
- a[e2] = a[left];
- a[e4] = a[right];
-
- /*
- * Skip elements, which are less or greater than pivot values.
- */
- while (a[++less] < pivot1);
- while (a[--great] > pivot2);
-
- /*
- * Partitioning:
- *
- * left part center part right part
- * +--------------------------------------------------------------+
- * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
- * +--------------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (left, less) < pivot1
- * pivot1 <= all in [less, k) <= pivot2
- * all in (great, right) > pivot2
- *
- * Pointer k is the first index of ?-part.
- */
- outer:
- for (int k = less; k <= great; k++) {
- byte ak = a[k];
- if (ak < pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less] = ak;
- less++;
- } else if (ak > pivot2) { // Move a[k] to right part
- while (a[great] > pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] < pivot1) {
- a[k] = a[less];
- a[less] = a[great];
- less++;
- } else { // pivot1 <= a[great] <= pivot2
- a[k] = a[great];
- }
- a[great] = ak;
- great--;
- }
- }
-
- // Swap pivots into their final positions
- a[left] = a[less - 1]; a[less - 1] = pivot1;
- a[right] = a[great + 1]; a[great + 1] = pivot2;
-
- // Sort left and right parts recursively, excluding known pivots
- sort(a, left, less - 2, leftmost);
- sort(a, great + 2, right, false);
-
- /*
- * If center part is too large (comprises > 5/7 of the array),
- * swap internal pivot values to ends.
- */
- if (less < e1 && e5 < great) {
- /*
- * Skip elements, which are equal to pivot values.
- */
- while (a[less] == pivot1) {
- less++;
- }
- while (a[great] == pivot2) {
- great--;
- }
-
- /*
- * Partitioning:
- *
- * left part center part right part
- * +----------------------------------------------------------+
- * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
- * +----------------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (*, less) == pivot1
- * pivot1 < all in [less, k) < pivot2
- * all in (great, *) == pivot2
- *
- * Pointer k is the first index of ?-part.
- */
- outer:
- for (int k = less; k <= great; k++) {
- byte ak = a[k];
- if (ak == pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less] = ak;
- less++;
- } else if (ak == pivot2) { // Move a[k] to right part
- while (a[great] == pivot2) {
- if (great-- == k) {
- break outer;
- }
- }
- if (a[great] == pivot1) {
- a[k] = a[less];
- /*
- * Even though a[great] equals to pivot1, the
- * assignment a[less] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point zeros
- * of different signs. Therefore in float and
- * double sorting methods we have to use more
- * accurate assignment a[less] = a[great].
- */
- a[less] = pivot1;
- less++;
- } else { // pivot1 < a[great] < pivot2
- a[k] = a[great];
- }
- a[great] = ak;
- great--;
- }
- }
- }
-
- // Sort center part recursively
- sort(a, less, great, false);
-
- } else { // Pivots are equal
- /*
- * Partition degenerates to the traditional 3-way
- * (or "Dutch National Flag") schema:
- *
- * left part center part right part
- * +-------------------------------------------------+
- * | < pivot | == pivot | ? | > pivot |
- * +-------------------------------------------------+
- * ^ ^ ^
- * | | |
- * less k great
- *
- * Invariants:
- *
- * all in (left, less) < pivot
- * all in [less, k) == pivot
- * all in (great, right) > pivot
- *
- * Pointer k is the first index of ?-part.
- */
- for (int k = left; k <= great; k++) {
- if (a[k] == pivot1) {
- continue;
- }
- byte ak = a[k];
-
- if (ak < pivot1) { // Move a[k] to left part
- a[k] = a[less];
- a[less] = ak;
- less++;
- } else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
- while (a[great] > pivot1) {
- // assert great > k;
- great--;
- }
- if (a[great] < pivot1) {
- a[k] = a[less];
- a[less] = a[great];
- less++;
- } else { // a[great] == pivot1
- /*
- * Even though a[great] equals to pivot1, the
- * assignment a[k] = pivot1 may be incorrect,
- * if a[great] and pivot1 are floating-point
- * zeros of different signs. Therefore in float
- * and double sorting methods we have to use
- * more accurate assignment a[k] = a[great].
- */
- a[k] = pivot1;
- }
- a[great] = ak;
- great--;
- }
- }
-
- // Sort left and right parts recursively
- sort(a, left, less - 1, leftmost);
- sort(a, great + 1, right, false);
- }
- }
-
- /**
- * Sorts the specified array into ascending numerical order.
- *
- *
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.
+ * Sorts the specified array.
*
* @param a the array to be sorted
*/
public static void sort(float[] a) {
- sortNegZeroAndNaN(a, 0, a.length - 1);
+ sort(a, 0, a.length - 1);
}
/**
- * 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 (and the call is a no-op).
- *
- *
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.
- *
- * @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}
- */
- public static void sort(float[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The
- * sort is done in three phases to avoid expensive comparisons in the
- * inner loop. The comparisons would be expensive due to anomalies
- * associated with negative zero {@code -0.0f} and {@code Float.NaN}.
+ * 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
*/
- private static void sortNegZeroAndNaN(float[] a, int left, int right) {
+ public static void sort(float[] a, int left, int right) {
/*
* Phase 1: Move NaNs to the end of the array.
*/
while (left <= right && Float.isNaN(a[right])) {
right--;
}
- for (int k = right - 1; k >= left; k--) {
+ for (int k = right; --k >= left; ) {
float ak = a[k];
if (ak != ak) { // a[k] is NaN
a[k] = a[right];
@@ -1921,7 +1619,7 @@ final class DualPivotQuicksort {
int hi = right;
/*
- * Search first zero, or first positive, or last negative element.
+ * Find the first zero, or first positive, or last negative element.
*/
while (left < hi) {
int middle = (left + hi) >>> 1;
@@ -1946,12 +1644,12 @@ final class DualPivotQuicksort {
*
* Partitioning:
*
- * +---------------------------------------------------+
- * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
- * +---------------------------------------------------+
- * ^ ^ ^
- * | | |
- * left p k
+ * +----------------------------------------------------+
+ * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
+ * +----------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * left p k
*
* Invariants:
*
@@ -1962,53 +1660,36 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left + 1, p = left; k <= right; k++) {
+ for (int k = left, p = left - 1; ++k <= right; ) {
float ak = a[k];
if (ak != 0.0f) {
break;
}
if (Float.floatToRawIntBits(ak) < 0) { // ak is -0.0f
a[k] = 0.0f;
- a[p++] = -0.0f;
+ a[++p] = -0.0f;
}
}
}
/**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
+ * Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @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 leftmost indicates if the part is the most left in the range
+ * @param leftmost indicates if this part is the leftmost in the range
*/
private static void sort(float[] a, int left, int right,boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on tiny arrays
+ // Use insertion sort on small arrays
if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
+ if (leftmost) {
/*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- float ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
+ * Traditional (without sentinel) insertion sort,
+ * optimized for server VM, is used in case of
+ * the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
float ai = a[i + 1];
@@ -2020,12 +1701,54 @@ final class DualPivotQuicksort {
}
a[j + 1] = ai;
}
+ } else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left++ >= right) {
+ return;
+ }
+ } while (a[left - 1] <= a[left]);
+
+ /*
+ * Every element from adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid the
+ * left range check on each iteration. Moreover, we use
+ * the best improved algorithm, so called pair insertion
+ * sort, which is faster than traditional implementation
+ * in the context of Dual-Pivot Quicksort.
+ */
+ for (int k = left--; (left += 2) <= right; ) {
+ float a1, a2; k = left - 1;
+
+ if (a[k] < a[left]) {
+ a2 = a[k]; a1 = a[left];
+ } else {
+ a1 = a[k]; a2 = a[left];
+ }
+ while (a1 < a[--k]) {
+ a[k + 2] = a[k];
+ }
+ a[++k + 1] = a1;
+
+ while (a2 < a[--k]) {
+ a[k + 1] = a[k];
+ }
+ a[k + 1] = a2;
+ }
+ float last = a[right];
+
+ while (last < a[--right]) {
+ a[right + 1] = a[right];
+ }
+ a[right + 1] = last;
}
return;
}
// Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
+ int seventh = (length >> 3) + (length >> 6) + 1;
/*
* Sort five evenly spaced elements around (and including) the
@@ -2107,10 +1830,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
float ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
+ /*
+ * Here and below we use "a[i] = b; i++;" instead
+ * of "a[i++] = b;" due to performance issue.
+ */
a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
@@ -2119,13 +1846,17 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
+ /*
+ * Here and below we use "a[i] = b; i--;" instead
+ * of "a[i--] = b;" due to performance issue.
+ */
a[great] = ak;
great--;
}
@@ -2140,7 +1871,7 @@ final class DualPivotQuicksort {
sort(a, great + 2, right, false);
/*
- * If center part is too large (comprises > 5/7 of the array),
+ * If center part is too large (comprises > 4/7 of the array),
* swap internal pivot values to ends.
*/
if (less < e1 && e5 < great) {
@@ -2174,7 +1905,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
float ak = a[k];
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
@@ -2186,7 +1917,7 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] == pivot1) {
+ if (a[great] == pivot1) { // a[great] < pivot2
a[k] = a[less];
/*
* Even though a[great] equals to pivot1, the
@@ -2212,7 +1943,7 @@ final class DualPivotQuicksort {
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way
+ * Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
@@ -2231,28 +1962,20 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left; k <= great; k++) {
+ for (int k = less; k <= great; ++k) {
if (a[k] == pivot1) {
continue;
}
float ak = a[k];
-
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
less++;
} else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
while (a[great] > pivot1) {
- // assert great > k;
great--;
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot1
a[k] = a[less];
a[less] = a[great];
less++;
@@ -2272,73 +1995,40 @@ final class DualPivotQuicksort {
}
}
- // Sort left and right parts recursively
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
sort(a, left, less - 1, leftmost);
sort(a, great + 1, right, false);
}
}
/**
- * Sorts the specified array into ascending numerical order.
- *
- *
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.
+ * Sorts the specified array.
*
* @param a the array to be sorted
*/
public static void sort(double[] a) {
- sortNegZeroAndNaN(a, 0, a.length - 1);
+ sort(a, 0, a.length - 1);
}
/**
- * 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 (and the call is a no-op).
- *
- *
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.
- *
- * @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}
- */
- public static void sort(double[] a, int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
- }
-
- /**
- * Sorts the specified range of the array into ascending order. The
- * sort is done in three phases to avoid expensive comparisons in the
- * inner loop. The comparisons would be expensive due to anomalies
- * associated with negative zero {@code -0.0d} and {@code Double.NaN}.
+ * 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
*/
- private static void sortNegZeroAndNaN(double[] a, int left, int right) {
+ public static void sort(double[] a, int left, int right) {
/*
* Phase 1: Move NaNs to the end of the array.
*/
while (left <= right && Double.isNaN(a[right])) {
right--;
}
- for (int k = right - 1; k >= left; k--) {
+ for (int k = right; --k >= left; ) {
double ak = a[k];
if (ak != ak) { // a[k] is NaN
a[k] = a[right];
@@ -2358,7 +2048,7 @@ final class DualPivotQuicksort {
int hi = right;
/*
- * Search first zero, or first positive, or last negative element.
+ * Find the first zero, or first positive, or last negative element.
*/
while (left < hi) {
int middle = (left + hi) >>> 1;
@@ -2383,12 +2073,12 @@ final class DualPivotQuicksort {
*
* Partitioning:
*
- * +---------------------------------------------------+
- * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
- * +---------------------------------------------------+
- * ^ ^ ^
- * | | |
- * left p k
+ * +----------------------------------------------------+
+ * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
+ * +----------------------------------------------------+
+ * ^ ^ ^
+ * | | |
+ * left p k
*
* Invariants:
*
@@ -2399,53 +2089,36 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left + 1, p = left; k <= right; k++) {
+ for (int k = left, p = left - 1; ++k <= right; ) {
double ak = a[k];
if (ak != 0.0d) {
break;
}
if (Double.doubleToRawLongBits(ak) < 0) { // ak is -0.0d
a[k] = 0.0d;
- a[p++] = -0.0d;
+ a[++p] = -0.0d;
}
}
}
/**
- * Sorts the specified range of the array into ascending order by the
- * Dual-Pivot Quicksort algorithm. This method differs from the public
- * {@code sort} method in that the {@code right} index is inclusive,
- * it does no range checking on {@code left} or {@code right}, and has
- * boolean flag whether insertion sort with sentinel is used or not.
+ * Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @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 leftmost indicates if the part is the most left in the range
+ * @param leftmost indicates if this part is the leftmost in the range
*/
private static void sort(double[] a, int left,int right,boolean leftmost) {
int length = right - left + 1;
- // Use insertion sort on tiny arrays
+ // Use insertion sort on small arrays
if (length < INSERTION_SORT_THRESHOLD) {
- if (!leftmost) {
+ if (leftmost) {
/*
- * Every element in adjoining part plays the role
- * of sentinel, therefore this allows us to avoid
- * the j >= left check on each iteration.
- */
- for (int j, i = left + 1; i <= right; i++) {
- double ai = a[i];
- for (j = i - 1; ai < a[j]; j--) {
- // assert j >= left;
- a[j + 1] = a[j];
- }
- a[j + 1] = ai;
- }
- } else {
- /*
- * For case of leftmost part traditional (without a sentinel)
- * insertion sort, optimized for server JVM, is used.
+ * Traditional (without sentinel) insertion sort,
+ * optimized for server VM, is used in case of
+ * the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
double ai = a[i + 1];
@@ -2457,12 +2130,54 @@ final class DualPivotQuicksort {
}
a[j + 1] = ai;
}
+ } else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left++ >= right) {
+ return;
+ }
+ } while (a[left - 1] <= a[left]);
+
+ /*
+ * Every element from adjoining part plays the role
+ * of sentinel, therefore this allows us to avoid the
+ * left range check on each iteration. Moreover, we use
+ * the best improved algorithm, so called pair insertion
+ * sort, which is faster than traditional implementation
+ * in the context of Dual-Pivot Quicksort.
+ */
+ for (int k = left--; (left += 2) <= right; ) {
+ double a1, a2; k = left - 1;
+
+ if (a[k] < a[left]) {
+ a2 = a[k]; a1 = a[left];
+ } else {
+ a1 = a[k]; a2 = a[left];
+ }
+ while (a1 < a[--k]) {
+ a[k + 2] = a[k];
+ }
+ a[++k + 1] = a1;
+
+ while (a2 < a[--k]) {
+ a[k + 1] = a[k];
+ }
+ a[k + 1] = a2;
+ }
+ double last = a[right];
+
+ while (last < a[--right]) {
+ a[right + 1] = a[right];
+ }
+ a[right + 1] = last;
}
return;
}
// Inexpensive approximation of length / 7
- int seventh = (length >>> 3) + (length >>> 6) + 1;
+ int seventh = (length >> 3) + (length >> 6) + 1;
/*
* Sort five evenly spaced elements around (and including) the
@@ -2544,10 +2259,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
double ak = a[k];
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
+ /*
+ * Here and below we use "a[i] = b; i++;" instead
+ * of "a[i++] = b;" due to performance issue.
+ */
a[less] = ak;
less++;
} else if (ak > pivot2) { // Move a[k] to right part
@@ -2556,13 +2275,17 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot2
a[k] = a[less];
a[less] = a[great];
less++;
} else { // pivot1 <= a[great] <= pivot2
a[k] = a[great];
}
+ /*
+ * Here and below we use "a[i] = b; i--;" instead
+ * of "a[i--] = b;" due to performance issue.
+ */
a[great] = ak;
great--;
}
@@ -2577,7 +2300,7 @@ final class DualPivotQuicksort {
sort(a, great + 2, right, false);
/*
- * If center part is too large (comprises > 5/7 of the array),
+ * If center part is too large (comprises > 4/7 of the array),
* swap internal pivot values to ends.
*/
if (less < e1 && e5 < great) {
@@ -2611,7 +2334,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
*/
outer:
- for (int k = less; k <= great; k++) {
+ for (int k = less - 1; ++k <= great; ) {
double ak = a[k];
if (ak == pivot1) { // Move a[k] to left part
a[k] = a[less];
@@ -2623,7 +2346,7 @@ final class DualPivotQuicksort {
break outer;
}
}
- if (a[great] == pivot1) {
+ if (a[great] == pivot1) { // a[great] < pivot2
a[k] = a[less];
/*
* Even though a[great] equals to pivot1, the
@@ -2649,7 +2372,7 @@ final class DualPivotQuicksort {
} else { // Pivots are equal
/*
- * Partition degenerates to the traditional 3-way
+ * Partitioning degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
@@ -2668,28 +2391,20 @@ final class DualPivotQuicksort {
*
* Pointer k is the first index of ?-part.
*/
- for (int k = left; k <= great; k++) {
+ for (int k = less; k <= great; ++k) {
if (a[k] == pivot1) {
continue;
}
double ak = a[k];
-
if (ak < pivot1) { // Move a[k] to left part
a[k] = a[less];
a[less] = ak;
less++;
} else { // a[k] > pivot1 - Move a[k] to right part
- /*
- * We know that pivot1 == a[e3] == pivot2. Thus, we know
- * that great will still be >= k when the following loop
- * terminates, even though we don't test for it explicitly.
- * In other words, a[e3] acts as a sentinel for great.
- */
while (a[great] > pivot1) {
- // assert great > k;
great--;
}
- if (a[great] < pivot1) {
+ if (a[great] < pivot1) { // a[great] <= pivot1
a[k] = a[less];
a[less] = a[great];
less++;
@@ -2709,26 +2424,13 @@ final class DualPivotQuicksort {
}
}
- // Sort left and right parts recursively
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
sort(a, left, less - 1, leftmost);
sort(a, great + 1, right, false);
}
}
-
- /**
- * Checks that {@code fromIndex} and {@code toIndex} are in the range,
- * otherwise throws an appropriate exception.
- */
- 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);
- }
- }
}
diff --git a/jdk/src/share/classes/java/util/Locale.java b/jdk/src/share/classes/java/util/Locale.java
index 49b85866ed3..1043c8792c4 100644
--- a/jdk/src/share/classes/java/util/Locale.java
+++ b/jdk/src/share/classes/java/util/Locale.java
@@ -569,6 +569,9 @@ public final class Locale implements Cloneable, Serializable {
* @exception NullPointerException thrown if any argument is null.
*/
public Locale(String language, String country, String variant) {
+ if (language== null || country == null || variant == null) {
+ throw new NullPointerException();
+ }
_baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
_extensions = getCompatibilityExtensions(language, "", country, variant);
}
diff --git a/jdk/src/share/classes/java/util/Properties.java b/jdk/src/share/classes/java/util/Properties.java
index 6f9c562e4f8..ee6d17c4e4d 100644
--- a/jdk/src/share/classes/java/util/Properties.java
+++ b/jdk/src/share/classes/java/util/Properties.java
@@ -705,7 +705,7 @@ class Properties extends Hashtable