diff --git a/.hgtags b/.hgtags
index 0e1e6146c83..4df81a1f51a 100644
--- a/.hgtags
+++ b/.hgtags
@@ -310,3 +310,4 @@ e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62
4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65
ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66
56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67
+5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 3b7f5316ae8..ca26adb6f6a 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -310,3 +310,4 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61
7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
dc6e8336f51bb6b67b7245766179eab5ca7720b4 jdk9-b66
f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
+70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68
diff --git a/corba/.hgtags b/corba/.hgtags
index 4c9c74c6bdb..43fb719ba7f 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -310,3 +310,4 @@ d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62
afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65
44ee68f7dbacab24a45115fd6a8ccdc7eb6e8f0b jdk9-b66
4418697e56f1f43597f55c7cb6573549c6117868 jdk9-b67
+8efad64f40eb8cd4df376c0a5275892eeb396bbd jdk9-b68
diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java
new file mode 100644
index 00000000000..54aae7c1df0
--- /dev/null
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.omg.CORBA;
+
+
+/**
+ * This Helper class is used to facilitate the marshalling of Bounds.
+ * For more information on Helper files, see
+ *
+ * "Generated Files: Helper Files".
+ */
+
+abstract public class BoundsHelper
+{
+ private static String _id = "IDL:omg.org/CORBA/Bounds:1.0";
+
+ public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.Bounds that)
+ {
+ org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+ a.type (type ());
+ write (out, that);
+ a.read_value (out.create_input_stream (), type ());
+ }
+
+ public static org.omg.CORBA.Bounds extract (org.omg.CORBA.Any a)
+ {
+ return read (a.create_input_stream ());
+ }
+
+ private static org.omg.CORBA.TypeCode __typeCode = null;
+ private static boolean __active = false;
+ synchronized public static org.omg.CORBA.TypeCode type ()
+ {
+ if (__typeCode == null)
+ {
+ synchronized (org.omg.CORBA.TypeCode.class)
+ {
+ if (__typeCode == null)
+ {
+ if (__active)
+ {
+ return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
+ }
+ __active = true;
+ org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
+ org.omg.CORBA.TypeCode _tcOf_members0 = null;
+ __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.BoundsHelper.id (), "Bounds", _members0);
+ __active = false;
+ }
+ }
+ }
+ return __typeCode;
+ }
+
+ public static String id ()
+ {
+ return _id;
+ }
+
+ public static org.omg.CORBA.Bounds read (org.omg.CORBA.portable.InputStream istream)
+ {
+ org.omg.CORBA.Bounds value = new org.omg.CORBA.Bounds ();
+ // read and discard the repository ID
+ istream.read_string ();
+ return value;
+ }
+
+ public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.Bounds value)
+ {
+ // write the repository ID
+ ostream.write_string (id ());
+ }
+
+}
diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java
new file mode 100644
index 00000000000..044e2b17eb4
--- /dev/null
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.omg.CORBA.ORBPackage;
+
+
+/**
+ * This Helper class is used to facilitate the marshalling of
+ * ORBPackage/InvalidName.
+ * For more information on Helper files, see
+ *
+ * "Generated Files: Helper Files".
+ */
+
+abstract public class InvalidNameHelper
+{
+ private static String _id = "IDL:omg.org.CORBA/ORB/InvalidName:1.0";
+
+ public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.ORBPackage.InvalidName that)
+ {
+ org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+ a.type (type ());
+ write (out, that);
+ a.read_value (out.create_input_stream (), type ());
+ }
+
+ public static org.omg.CORBA.ORBPackage.InvalidName extract (org.omg.CORBA.Any a)
+ {
+ return read (a.create_input_stream ());
+ }
+
+ private static org.omg.CORBA.TypeCode __typeCode = null;
+ private static boolean __active = false;
+ synchronized public static org.omg.CORBA.TypeCode type ()
+ {
+ if (__typeCode == null)
+ {
+ synchronized (org.omg.CORBA.TypeCode.class)
+ {
+ if (__typeCode == null)
+ {
+ if (__active)
+ {
+ return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
+ }
+ __active = true;
+ org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
+ org.omg.CORBA.TypeCode _tcOf_members0 = null;
+ __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.ORBPackage.InvalidNameHelper.id (), "InvalidName", _members0);
+ __active = false;
+ }
+ }
+ }
+ return __typeCode;
+ }
+
+ public static String id ()
+ {
+ return _id;
+ }
+
+ public static org.omg.CORBA.ORBPackage.InvalidName read (org.omg.CORBA.portable.InputStream istream)
+ {
+ org.omg.CORBA.ORBPackage.InvalidName value = new org.omg.CORBA.ORBPackage.InvalidName ();
+ // read and discard the repository ID
+ istream.read_string ();
+ return value;
+ }
+
+ public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.ORBPackage.InvalidName value)
+ {
+ // write the repository ID
+ ostream.write_string (id ());
+ }
+
+}
diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java
new file mode 100644
index 00000000000..755935698dd
--- /dev/null
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.omg.CORBA.TypeCodePackage;
+
+
+/**
+ * This Helper class is used to facilitate the marshalling of
+ * TypeCodePackage/BadKind.
+ * For more information on Helper files, see
+ *
+ * "Generated Files: Helper Files".
+ */
+
+abstract public class BadKindHelper
+{
+ private static String _id = "IDL:omg.org.CORBA/TypeCode/BadKind:1.0";
+
+ public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.BadKind that)
+ {
+ org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+ a.type (type ());
+ write (out, that);
+ a.read_value (out.create_input_stream (), type ());
+ }
+
+ public static org.omg.CORBA.TypeCodePackage.BadKind extract (org.omg.CORBA.Any a)
+ {
+ return read (a.create_input_stream ());
+ }
+
+ private static org.omg.CORBA.TypeCode __typeCode = null;
+ private static boolean __active = false;
+ synchronized public static org.omg.CORBA.TypeCode type ()
+ {
+ if (__typeCode == null)
+ {
+ synchronized (org.omg.CORBA.TypeCode.class)
+ {
+ if (__typeCode == null)
+ {
+ if (__active)
+ {
+ return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
+ }
+ __active = true;
+ org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
+ org.omg.CORBA.TypeCode _tcOf_members0 = null;
+ __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BadKindHelper.id (), "BadKind", _members0);
+ __active = false;
+ }
+ }
+ }
+ return __typeCode;
+ }
+
+ public static String id ()
+ {
+ return _id;
+ }
+
+ public static org.omg.CORBA.TypeCodePackage.BadKind read (org.omg.CORBA.portable.InputStream istream)
+ {
+ org.omg.CORBA.TypeCodePackage.BadKind value = new org.omg.CORBA.TypeCodePackage.BadKind ();
+ // read and discard the repository ID
+ istream.read_string ();
+ return value;
+ }
+
+ public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.BadKind value)
+ {
+ // write the repository ID
+ ostream.write_string (id ());
+ }
+
+}
diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java
new file mode 100644
index 00000000000..c234c595b17
--- /dev/null
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.omg.CORBA.TypeCodePackage;
+
+
+/**
+ * This Helper class is used to facilitate the marshalling of
+ * TypeCodePackage/Bounds.
+ * For more information on Helper files, see
+ *
+ * "Generated Files: Helper Files".
+ */
+
+abstract public class BoundsHelper
+{
+ private static String _id = "IDL:omg.org.CORBA/TypeCode/Bounds:1.0";
+
+ public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.Bounds that)
+ {
+ org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
+ a.type (type ());
+ write (out, that);
+ a.read_value (out.create_input_stream (), type ());
+ }
+
+ public static org.omg.CORBA.TypeCodePackage.Bounds extract (org.omg.CORBA.Any a)
+ {
+ return read (a.create_input_stream ());
+ }
+
+ private static org.omg.CORBA.TypeCode __typeCode = null;
+ private static boolean __active = false;
+ synchronized public static org.omg.CORBA.TypeCode type ()
+ {
+ if (__typeCode == null)
+ {
+ synchronized (org.omg.CORBA.TypeCode.class)
+ {
+ if (__typeCode == null)
+ {
+ if (__active)
+ {
+ return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
+ }
+ __active = true;
+ org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
+ org.omg.CORBA.TypeCode _tcOf_members0 = null;
+ __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BoundsHelper.id (), "Bounds", _members0);
+ __active = false;
+ }
+ }
+ }
+ return __typeCode;
+ }
+
+ public static String id ()
+ {
+ return _id;
+ }
+
+ public static org.omg.CORBA.TypeCodePackage.Bounds read (org.omg.CORBA.portable.InputStream istream)
+ {
+ org.omg.CORBA.TypeCodePackage.Bounds value = new org.omg.CORBA.TypeCodePackage.Bounds ();
+ // read and discard the repository ID
+ istream.read_string ();
+ return value;
+ }
+
+ public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.Bounds value)
+ {
+ // write the repository ID
+ ostream.write_string (id ());
+ }
+
+}
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 57051d33f64..8d7c7a914ad 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -470,3 +470,4 @@ bf92b8db249cdfa5651ef954b6c0743a7e0ea4cd jdk9-b64
e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65
197e94e0dacddd16816f101d24fc0442ab518326 jdk9-b66
d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67
+11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68
diff --git a/hotspot/make/linux/makefiles/dtrace.make b/hotspot/make/linux/makefiles/dtrace.make
index 4dbe4cbf21d..2c898d0e778 100644
--- a/hotspot/make/linux/makefiles/dtrace.make
+++ b/hotspot/make/linux/makefiles/dtrace.make
@@ -31,8 +31,8 @@ ifndef OPENJDK
REASON = "This JDK does not support SDT probes"
else
-# We need a recent GCC for the default
-ifeq "$(shell expr \( $(CC_VER_MAJOR) \>= 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) )" "0"
+# We need a recent GCC for the default (4.4 or later)
+ifeq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) \) \| \( $(CC_VER_MAJOR) \>= 5 \) )" "0"
REASON = "gcc version is too old"
else
diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk
index e62bc94abe2..e447560be56 100644
--- a/hotspot/make/test/JtregNative.gmk
+++ b/hotspot/make/test/JtregNative.gmk
@@ -44,6 +44,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(HOTSPOT_TOPDIR)/test/native_sanity \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
+ $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
#
BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index 01e0c805b5f..4a742755f29 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -3372,6 +3372,25 @@ operand immI() %{
interface(CONST_INTER);
%}
+// Integer Immediate: 0-bit
+operand immI0() %{
+ predicate(n->get_int() == 0);
+ match(ConI);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Integer Immediate: 5-bit
+operand immI5() %{
+ predicate(Assembler::is_simm5(n->get_int()));
+ match(ConI);
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Integer Immediate: 8-bit
operand immI8() %{
predicate(Assembler::is_simm8(n->get_int()));
@@ -3381,6 +3400,25 @@ operand immI8() %{
interface(CONST_INTER);
%}
+// Integer Immediate: the value 10
+operand immI10() %{
+ predicate(n->get_int() == 10);
+ match(ConI);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Integer Immediate: 11-bit
+operand immI11() %{
+ predicate(Assembler::is_simm11(n->get_int()));
+ match(ConI);
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Integer Immediate: 13-bit
operand immI13() %{
predicate(Assembler::is_simm13(n->get_int()));
@@ -3410,84 +3448,6 @@ operand immI16() %{
interface(CONST_INTER);
%}
-// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
-operand immU12() %{
- predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
- match(ConI);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Integer Immediate: 6-bit
-operand immU6() %{
- predicate(n->get_int() >= 0 && n->get_int() <= 63);
- match(ConI);
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Integer Immediate: 11-bit
-operand immI11() %{
- predicate(Assembler::is_simm11(n->get_int()));
- match(ConI);
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Integer Immediate: 5-bit
-operand immI5() %{
- predicate(Assembler::is_simm5(n->get_int()));
- match(ConI);
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Int Immediate non-negative
-operand immU31()
-%{
- predicate(n->get_int() >= 0);
- match(ConI);
-
- op_cost(0);
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Integer Immediate: 0-bit
-operand immI0() %{
- predicate(n->get_int() == 0);
- match(ConI);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Integer Immediate: the value 10
-operand immI10() %{
- predicate(n->get_int() == 10);
- match(ConI);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
-// Integer Immediate: the values 0-31
-operand immU5() %{
- predicate(n->get_int() >= 0 && n->get_int() <= 31);
- match(ConI);
- op_cost(0);
-
- format %{ %}
- interface(CONST_INTER);
-%}
-
// Integer Immediate: the values 1-31
operand immI_1_31() %{
predicate(n->get_int() >= 1 && n->get_int() <= 31);
@@ -3529,7 +3489,6 @@ operand immI_24() %{
format %{ %}
interface(CONST_INTER);
%}
-
// Integer Immediate: the value 255
operand immI_255() %{
predicate( n->get_int() == 255 );
@@ -3550,6 +3509,46 @@ operand immI_65535() %{
interface(CONST_INTER);
%}
+// Integer Immediate: the values 0-31
+operand immU5() %{
+ predicate(n->get_int() >= 0 && n->get_int() <= 31);
+ match(ConI);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Integer Immediate: 6-bit
+operand immU6() %{
+ predicate(n->get_int() >= 0 && n->get_int() <= 63);
+ match(ConI);
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
+operand immU12() %{
+ predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
+ match(ConI);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Integer Immediate non-negative
+operand immU31()
+%{
+ predicate(n->get_int() >= 0);
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Long Immediate: the value FF
operand immL_FF() %{
predicate( n->get_long() == 0xFFL );
@@ -5653,17 +5652,17 @@ instruct loadUB2L(iRegL dst, memory mem) %{
ins_pipe(iload_mem);
%}
-// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register
-instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{
+// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
+instruct loadUB2L_immI(iRegL dst, memory mem, immI mask) %{
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
size(2*4);
- format %{ "LDUB $mem,$dst\t# ubyte & 8-bit mask -> long\n\t"
- "AND $dst,$mask,$dst" %}
+ format %{ "LDUB $mem,$dst\t# ubyte & 32-bit mask -> long\n\t"
+ "AND $dst,right_n_bits($mask, 8),$dst" %}
ins_encode %{
__ ldub($mem$$Address, $dst$$Register);
- __ and3($dst$$Register, $mask$$constant, $dst$$Register);
+ __ and3($dst$$Register, $mask$$constant & right_n_bits(8), $dst$$Register);
%}
ins_pipe(iload_mem);
%}
@@ -5776,20 +5775,20 @@ instruct loadUS2L_immI13(iRegL dst, memory mem, immI13 mask) %{
ins_pipe(iload_mem);
%}
-// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register
-instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{
+// Load Unsigned Short/Char (16bit UNsigned) with a 32-bit mask into a Long Register
+instruct loadUS2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
- format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
- "SET $mask,$tmp\n\t"
+ format %{ "LDUH $mem,$dst\t! ushort/char & 32-bit mask -> long\n\t"
+ "SET right_n_bits($mask, 16),$tmp\n\t"
"AND $dst,$tmp,$dst" %}
ins_encode %{
Register Rdst = $dst$$Register;
Register Rtmp = $tmp$$Register;
__ lduh($mem$$Address, Rdst);
- __ set($mask$$constant, Rtmp);
+ __ set($mask$$constant & right_n_bits(16), Rtmp);
__ and3(Rdst, Rtmp, Rdst);
%}
ins_pipe(iload_mem);
diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad
index 23731beea1a..be2f7e65b36 100644
--- a/hotspot/src/cpu/x86/vm/x86_32.ad
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad
@@ -5431,18 +5431,18 @@ instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{
%}
// Load Unsigned Byte (8 bit UNsigned) with mask into Long Register
-instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{
+instruct loadUB2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
effect(KILL cr);
- format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t"
+ format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 32-bit mask -> long\n\t"
"XOR $dst.hi,$dst.hi\n\t"
- "AND $dst.lo,$mask" %}
+ "AND $dst.lo,right_n_bits($mask, 8)" %}
ins_encode %{
Register Rdst = $dst$$Register;
__ movzbl(Rdst, $mem$$Address);
__ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- __ andl(Rdst, $mask$$constant);
+ __ andl(Rdst, $mask$$constant & right_n_bits(8));
%}
ins_pipe(ialu_reg_mem);
%}
@@ -5550,19 +5550,19 @@ instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %
ins_pipe(ialu_reg_mem);
%}
-// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register
-instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{
+// Load Unsigned Short/Char (16 bit UNsigned) with a 32-bit mask into Long Register
+instruct loadUS2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
effect(KILL cr);
- format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t"
+ format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 32-bit mask -> long\n\t"
"XOR $dst.hi,$dst.hi\n\t"
- "AND $dst.lo,$mask" %}
+ "AND $dst.lo,right_n_bits($mask, 16)" %}
ins_encode %{
Register Rdst = $dst$$Register;
__ movzwl(Rdst, $mem$$Address);
__ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
- __ andl(Rdst, $mask$$constant);
+ __ andl(Rdst, $mask$$constant & right_n_bits(16));
%}
ins_pipe(ialu_reg_mem);
%}
diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad
index 538ec3a360d..ea8b1c81276 100644
--- a/hotspot/src/cpu/x86/vm/x86_64.ad
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad
@@ -4753,17 +4753,17 @@ instruct loadUB2L(rRegL dst, memory mem)
ins_pipe(ialu_reg_mem);
%}
-// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register
-instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{
+// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
+instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
effect(KILL cr);
- format %{ "movzbq $dst, $mem\t# ubyte & 8-bit mask -> long\n\t"
- "andl $dst, $mask" %}
+ format %{ "movzbq $dst, $mem\t# ubyte & 32-bit mask -> long\n\t"
+ "andl $dst, right_n_bits($mask, 8)" %}
ins_encode %{
Register Rdst = $dst$$Register;
__ movzbq(Rdst, $mem$$Address);
- __ andl(Rdst, $mask$$constant);
+ __ andl(Rdst, $mask$$constant & right_n_bits(8));
%}
ins_pipe(ialu_reg_mem);
%}
@@ -4863,17 +4863,17 @@ instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
ins_pipe(ialu_reg_mem);
%}
-// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register
-instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{
+// Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register
+instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
effect(KILL cr);
- format %{ "movzwq $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t"
- "andl $dst, $mask" %}
+ format %{ "movzwq $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t"
+ "andl $dst, right_n_bits($mask, 16)" %}
ins_encode %{
Register Rdst = $dst$$Register;
__ movzwq(Rdst, $mem$$Address);
- __ andl(Rdst, $mask$$constant);
+ __ andl(Rdst, $mask$$constant & right_n_bits(16));
%}
ins_pipe(ialu_reg_mem);
%}
diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index eee444ea1fb..49b5c63d7f1 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -1267,10 +1267,6 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
- abort(dump_core, NULL, NULL);
-}
-
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index d725b35350b..84bc8a9cff8 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -1131,10 +1131,6 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
- abort(dump_core, NULL, NULL);
-}
-
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index 3ae38ebed3c..f893061e288 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -1478,10 +1478,6 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
- abort(dump_core, NULL, NULL);
-}
-
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp
index befdb29b5cc..7ece72dd792 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp
@@ -1520,10 +1520,6 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
- abort(dump_core, NULL, NULL);
-}
-
void os::abort(bool dump_core, void* siginfo, void* context) {
os::shutdown();
if (dump_core) {
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 2bae2d0e992..faf658a71ca 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -997,7 +997,16 @@ void os::check_dump_limit(char* buffer, size_t buffsz) {
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
status = false;
- } else {
+ }
+
+#ifndef ASSERT
+ if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
+ jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
+ status = false;
+ }
+#endif
+
+ if (status) {
const char* cwd = get_current_directory(NULL, 0);
int pid = current_process_id();
if (cwd != NULL) {
@@ -1086,10 +1095,6 @@ void os::abort(bool dump_core, void* siginfo, void* context) {
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
-void os::abort(bool dump_core) {
- abort(dump_core, NULL, NULL);
-}
-
// Die immediately, no exit hook, no abort hook, no cleanup.
void os::die() {
win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
diff --git a/hotspot/src/share/vm/ci/ciCallSite.cpp b/hotspot/src/share/vm/ci/ciCallSite.cpp
index 028a4ed724f..fb222fe3f5a 100644
--- a/hotspot/src/share/vm/ci/ciCallSite.cpp
+++ b/hotspot/src/share/vm/ci/ciCallSite.cpp
@@ -49,25 +49,6 @@ ciMethodHandle* ciCallSite::get_target() const {
return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
}
-// ------------------------------------------------------------------
-// ciCallSite::get_context
-//
-// Return the target MethodHandle of this CallSite.
-ciKlass* ciCallSite::get_context() {
- assert(!is_constant_call_site(), "");
-
- VM_ENTRY_MARK;
- oop call_site_oop = get_oop();
- InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site_oop);
- if (ctxk == NULL) {
- // The call site doesn't have a context associated. Set it to the default context.
- oop def_context_oop = java_lang_invoke_CallSite::default_context();
- java_lang_invoke_CallSite::set_context_cas(call_site_oop, def_context_oop, /*expected=*/NULL);
- ctxk = MethodHandles::get_call_site_context(call_site_oop);
- }
- return (CURRENT_ENV->get_metadata(ctxk))->as_klass();
-}
-
// ------------------------------------------------------------------
// ciCallSite::print
//
diff --git a/hotspot/src/share/vm/ci/ciCallSite.hpp b/hotspot/src/share/vm/ci/ciCallSite.hpp
index 040e894d0df..063f1e3a5fe 100644
--- a/hotspot/src/share/vm/ci/ciCallSite.hpp
+++ b/hotspot/src/share/vm/ci/ciCallSite.hpp
@@ -43,7 +43,6 @@ public:
// Return the target MethodHandle of this CallSite.
ciMethodHandle* get_target() const;
- ciKlass* get_context();
void print();
};
diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp
index b95ca80d6dc..6473606d499 100644
--- a/hotspot/src/share/vm/ci/ciEnv.cpp
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp
@@ -709,24 +709,23 @@ Method* ciEnv::lookup_method(InstanceKlass* accessor,
KlassHandle h_holder(THREAD, holder);
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
methodHandle dest_method;
+ LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
switch (bc) {
case Bytecodes::_invokestatic:
dest_method =
- LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
+ LinkResolver::resolve_static_call_or_null(link_info);
break;
case Bytecodes::_invokespecial:
dest_method =
- LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
+ LinkResolver::resolve_special_call_or_null(link_info);
break;
case Bytecodes::_invokeinterface:
dest_method =
- LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
- h_accessor, true);
+ LinkResolver::linktime_resolve_interface_method_or_null(link_info);
break;
case Bytecodes::_invokevirtual:
dest_method =
- LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
- h_accessor, true);
+ LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
break;
default: ShouldNotReachHere();
}
diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp
index ba3d07157aa..9fe63de27bf 100644
--- a/hotspot/src/share/vm/ci/ciField.cpp
+++ b/hotspot/src/share/vm/ci/ciField.cpp
@@ -352,11 +352,11 @@ bool ciField::will_link(ciInstanceKlass* accessing_klass,
}
}
+ LinkInfo link_info(_holder->get_instanceKlass(),
+ _name->get_symbol(), _signature->get_symbol(),
+ accessing_klass->get_Klass());
fieldDescriptor result;
- LinkResolver::resolve_field(result, _holder->get_instanceKlass(),
- _name->get_symbol(), _signature->get_symbol(),
- accessing_klass->get_Klass(), bc, true, false,
- KILL_COMPILE_ON_FATAL_(false));
+ LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false));
// update the hit-cache, unless there is a problem with memory scoping:
if (accessing_klass->is_shared() || !is_shared()) {
diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp
index b81206a1616..ec97e100d48 100644
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp
@@ -453,8 +453,12 @@ int ciInstanceKlass::compute_nonstatic_fields() {
if (fields == NULL) {
// This can happen if this class (java.lang.Class) has invisible fields.
- _nonstatic_fields = super_fields;
- return super_fields->length();
+ if (super_fields != NULL) {
+ _nonstatic_fields = super_fields;
+ return super_fields->length();
+ } else {
+ return 0;
+ }
}
int flen = fields->length();
diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp
index 859bd3eef4c..81ef4bf37df 100644
--- a/hotspot/src/share/vm/ci/ciMethod.cpp
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, 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
@@ -786,6 +786,7 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo
Symbol* h_name = name()->get_symbol();
Symbol* h_signature = signature()->get_symbol();
+ LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
methodHandle m;
// Only do exact lookup if receiver klass has been linked. Otherwise,
// the vtable has not been setup, and the LinkResolver will fail.
@@ -793,9 +794,9 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo
||
InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) {
if (holder()->is_interface()) {
- m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
+ m = LinkResolver::resolve_interface_call_or_null(h_recv, link_info);
} else {
- m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
+ m = LinkResolver::resolve_virtual_call_or_null(h_recv, link_info);
}
}
@@ -839,7 +840,8 @@ int ciMethod::resolve_vtable_index(ciKlass* caller, ciKlass* receiver) {
Symbol* h_name = name()->get_symbol();
Symbol* h_signature = signature()->get_symbol();
- vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass);
+ LinkInfo link_info(h_recv, h_name, h_signature, caller_klass);
+ vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info);
if (vtable_index == Method::nonvirtual_vtable_index) {
// A statically bound method. Return "no such index".
vtable_index = Method::invalid_vtable_index;
@@ -1285,10 +1287,8 @@ bool ciMethod::check_call(int refinfo_index, bool is_static) const {
EXCEPTION_MARK;
HandleMark hm(THREAD);
constantPoolHandle pool (THREAD, get_Method()->constants());
- methodHandle spec_method;
- KlassHandle spec_klass;
Bytecodes::Code code = (is_static ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual);
- LinkResolver::resolve_method_statically(spec_method, spec_klass, code, pool, refinfo_index, THREAD);
+ methodHandle spec_method = LinkResolver::resolve_method_statically(code, pool, refinfo_index, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return false;
diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp
index 9ac84cc631f..a50e6762164 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp
@@ -2967,47 +2967,42 @@ int java_lang_invoke_MethodType::rtype_slot_count(oop mt) {
int java_lang_invoke_CallSite::_target_offset;
int java_lang_invoke_CallSite::_context_offset;
-int java_lang_invoke_CallSite::_default_context_offset;
void java_lang_invoke_CallSite::compute_offsets() {
Klass* k = SystemDictionary::CallSite_klass();
if (k != NULL) {
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
- compute_offset(_context_offset, k, vmSymbols::context_name(), vmSymbols::sun_misc_Cleaner_signature());
- compute_offset(_default_context_offset, k,
- vmSymbols::DEFAULT_CONTEXT_name(), vmSymbols::sun_misc_Cleaner_signature(),
- /*is_static=*/true, /*allow_super=*/false);
+ compute_offset(_context_offset, k, vmSymbols::context_name(),
+ vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
}
}
-oop java_lang_invoke_CallSite::context_volatile(oop call_site) {
+oop java_lang_invoke_CallSite::context(oop call_site) {
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
- oop dep_oop = call_site->obj_field_volatile(_context_offset);
+ oop dep_oop = call_site->obj_field(_context_offset);
return dep_oop;
}
-void java_lang_invoke_CallSite::set_context_volatile(oop call_site, oop context) {
- assert(java_lang_invoke_CallSite::is_instance(call_site), "");
- call_site->obj_field_put_volatile(_context_offset, context);
-}
+// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext
-bool java_lang_invoke_CallSite::set_context_cas(oop call_site, oop context, oop expected) {
- assert(java_lang_invoke_CallSite::is_instance(call_site), "");
- HeapWord* context_addr = call_site->obj_field_addr(_context_offset);
- oop res = oopDesc::atomic_compare_exchange_oop(context, context_addr, expected, true);
- bool success = (res == expected);
- if (success) {
- update_barrier_set((void*)context_addr, context);
+int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
+
+void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
+ Klass* k = SystemDictionary::Context_klass();
+ if (k != NULL) {
+ CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
- return success;
}
-oop java_lang_invoke_CallSite::default_context() {
- InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::CallSite_klass());
- oop def_context_oop = ik->java_mirror()->obj_field(_default_context_offset);
- assert(!oopDesc::is_null(def_context_oop), "");
- return def_context_oop;
+nmethodBucket* java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
+ assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
+ return (nmethodBucket*) (address) call_site->long_field(_vmdependencies_offset);
+}
+
+void java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(oop call_site, nmethodBucket* context) {
+ assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
+ call_site->long_field_put(_vmdependencies_offset, (jlong) (address) context);
}
// Support for java_security_AccessControlContext
@@ -3403,6 +3398,7 @@ void JavaClasses::compute_offsets() {
java_lang_invoke_LambdaForm::compute_offsets();
java_lang_invoke_MethodType::compute_offsets();
java_lang_invoke_CallSite::compute_offsets();
+ java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets();
java_security_AccessControlContext::compute_offsets();
// Initialize reflection classes. The layouts of these classes
// changed with the new reflection implementation in JDK 1.4, and
diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp
index 700cf4afab5..8410c8c2a2d 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp
@@ -1170,8 +1170,6 @@ class java_lang_invoke_CallSite: AllStatic {
private:
static int _target_offset;
static int _context_offset;
- static int _default_context_offset;
-
static void compute_offsets();
@@ -1181,11 +1179,7 @@ public:
static void set_target( oop site, oop target);
static void set_target_volatile( oop site, oop target);
- static oop context_volatile(oop site);
- static void set_context_volatile(oop site, oop context);
- static bool set_context_cas (oop site, oop context, oop expected);
-
- static oop default_context();
+ static oop context(oop site);
// Testers
static bool is_subclass(Klass* klass) {
@@ -1197,6 +1191,31 @@ public:
static int target_offset_in_bytes() { return _target_offset; }
};
+// Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects
+
+#define CALLSITECONTEXT_INJECTED_FIELDS(macro) \
+ macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, vmdependencies, intptr_signature, false)
+
+class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic {
+ friend class JavaClasses;
+
+private:
+ static int _vmdependencies_offset;
+
+ static void compute_offsets();
+
+public:
+ // Accessors
+ static nmethodBucket* vmdependencies(oop context);
+ static void set_vmdependencies(oop context, nmethodBucket* bucket);
+
+ // Testers
+ static bool is_subclass(Klass* klass) {
+ return klass->is_subclass_of(SystemDictionary::Context_klass());
+ }
+ static bool is_instance(oop obj);
+};
+
// Interface to java.security.AccessControlContext objects
class java_security_AccessControlContext: AllStatic {
@@ -1406,7 +1425,8 @@ class InjectedField {
#define ALL_INJECTED_FIELDS(macro) \
CLASS_INJECTED_FIELDS(macro) \
CLASSLOADER_INJECTED_FIELDS(macro) \
- MEMBERNAME_INJECTED_FIELDS(macro)
+ MEMBERNAME_INJECTED_FIELDS(macro) \
+ CALLSITECONTEXT_INJECTED_FIELDS(macro)
// Interface to hard-coded offset checking
diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
index c5b2f32066d..723c2e86757 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
@@ -49,6 +49,10 @@ inline bool java_lang_invoke_CallSite::is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
+inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) {
+ return obj != NULL && is_subclass(obj->klass());
+}
+
inline bool java_lang_invoke_MemberName::is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp
index 126fc31d872..1f5644c236d 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp
@@ -159,6 +159,7 @@ class Ticks;
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre ) \
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre ) \
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre ) \
+ do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre ) \
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre ) \
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre ) \
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp
index f922aa3e96d..cdfe83edd9b 100644
--- a/hotspot/src/share/vm/classfile/verifier.cpp
+++ b/hotspot/src/share/vm/classfile/verifier.cpp
@@ -45,6 +45,8 @@
#include "runtime/javaCalls.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/os.hpp"
+#include "runtime/thread.hpp"
+#include "services/threadService.hpp"
#include "utilities/bytes.hpp"
#define NOFAILOVER_MAJOR_VERSION 51
@@ -130,6 +132,16 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul
return true;
}
+ // Timer includes any side effects of class verification (resolution,
+ // etc), but not recursive calls to Verifier::verify().
+ JavaThread* jt = (JavaThread*)THREAD;
+ PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
+ ClassLoader::perf_class_verify_selftime(),
+ ClassLoader::perf_classes_verified(),
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::CLASS_VERIFY);
+
// If the class should be verified, first see if we can use the split
// verifier. If not, or if verification fails and FailOverToOldVerifier
// is set, then call the inference verifier.
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index 8d9f53e359d..c2548215b6f 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -274,12 +274,14 @@
/* internal classes known only to the JVM: */ \
template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \
template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \
+ template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
+ template(java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, "Ljava/lang/invoke/MethodHandleNatives$CallSiteContext;") \
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
template(findMethodHandleType_name, "findMethodHandleType") \
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
@@ -401,7 +403,7 @@
template(protection_domain_name, "protection_domain") \
template(signers_name, "signers_name") \
template(loader_data_name, "loader_data") \
- template(dependencies_name, "dependencies") \
+ template(vmdependencies_name, "vmdependencies") \
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
template(getFileURL_name, "getFileURL") \
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp
index 8d801094d0f..16ee831ddb1 100644
--- a/hotspot/src/share/vm/code/codeCache.cpp
+++ b/hotspot/src/share/vm/code/codeCache.cpp
@@ -1047,40 +1047,6 @@ void CodeCache::flush_dependents_on(instanceKlassHandle dependee) {
}
}
-// Flushes compiled methods dependent on a particular CallSite
-// instance when its target is different than the given MethodHandle.
-void CodeCache::flush_dependents_on(Handle call_site, Handle method_handle) {
- assert_lock_strong(Compile_lock);
-
- if (number_of_nmethods_with_dependencies() == 0) return;
-
- // CodeCache can only be updated by a thread_in_VM and they will all be
- // stopped during the safepoint so CodeCache will be safe to update without
- // holding the CodeCache_lock.
-
- CallSiteDepChange changes(call_site(), method_handle());
-
- // Compute the dependent nmethods that have a reference to a
- // CallSite object. We use InstanceKlass::mark_dependent_nmethod
- // directly instead of CodeCache::mark_for_deoptimization because we
- // want dependents on the call site class only not all classes in
- // the ContextStream.
- int marked = 0;
- {
- MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
- if (ctxk == NULL) {
- return; // No dependencies to invalidate yet.
- }
- marked = ctxk->mark_dependent_nmethods(changes);
- }
- if (marked > 0) {
- // At least one nmethod has been marked for deoptimization
- VM_Deoptimize op;
- VMThread::execute(&op);
- }
-}
-
#ifdef HOTSWAP
// Flushes compiled methods dependent on dependee in the evolutionary sense
void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp
index 09879b125da..7030df6fc84 100644
--- a/hotspot/src/share/vm/code/codeCache.hpp
+++ b/hotspot/src/share/vm/code/codeCache.hpp
@@ -224,7 +224,6 @@ class CodeCache : AllStatic {
// Flushing and deoptimization
static void flush_dependents_on(instanceKlassHandle dependee);
- static void flush_dependents_on(Handle call_site, Handle method_handle);
#ifdef HOTSWAP
// Flushing and deoptimization in case of evolution
static void flush_evol_dependents_on(instanceKlassHandle dependee);
diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp
index 1f56103be5b..132bc162d42 100644
--- a/hotspot/src/share/vm/code/dependencies.cpp
+++ b/hotspot/src/share/vm/code/dependencies.cpp
@@ -117,9 +117,7 @@ void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) {
}
void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
- ciKlass* ctxk = call_site->get_context();
- check_ctxk(ctxk);
- assert_common_3(call_site_target_value, ctxk, call_site, method_handle);
+ assert_common_2(call_site_target_value, call_site, method_handle);
}
// Helper function. If we are adding a new dep. under ctxk2,
@@ -175,7 +173,6 @@ void Dependencies::assert_common_2(DepType dept,
}
}
} else {
- assert(dep_implicit_context_arg(dept) == 0, "sanity");
if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
// look in this bucket for redundant assertions
const int stride = 2;
@@ -389,7 +386,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = {
3, // unique_concrete_subtypes_2 ctxk, k1, k2
3, // unique_concrete_methods_2 ctxk, m1, m2
1, // no_finalizable_subclasses ctxk
- 3 // call_site_target_value ctxk, call_site, method_handle
+ 2 // call_site_target_value call_site, method_handle
};
const char* Dependencies::dep_name(Dependencies::DepType dept) {
@@ -1515,16 +1512,11 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh
return find_finalizable_subclass(search_at);
}
-Klass* Dependencies::check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) {
- assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity");
+Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
+ assert(!oopDesc::is_null(call_site), "sanity");
assert(!oopDesc::is_null(method_handle), "sanity");
+ assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity");
- Klass* call_site_ctxk = MethodHandles::get_call_site_context(call_site);
- assert(!Klass::is_null(call_site_ctxk), "call site context should be initialized already");
- if (recorded_ctxk != call_site_ctxk) {
- // Stale context
- return recorded_ctxk;
- }
if (changes == NULL) {
// Validate all CallSites
if (java_lang_invoke_CallSite::target(call_site) != method_handle)
@@ -1599,7 +1591,7 @@ Klass* Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* ch
Klass* witness = NULL;
switch (type()) {
case call_site_target_value:
- witness = check_call_site_target_value(context_type(), argument_oop(1), argument_oop(2), changes);
+ witness = check_call_site_target_value(argument_oop(0), argument_oop(1), changes);
break;
default:
witness = NULL;
diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp
index cacc5cac095..3129a2cb5de 100644
--- a/hotspot/src/share/vm/code/dependencies.hpp
+++ b/hotspot/src/share/vm/code/dependencies.hpp
@@ -173,7 +173,7 @@ class Dependencies: public ResourceObj {
non_klass_types = (1 << call_site_target_value),
klass_types = all_types & ~non_klass_types,
- non_ctxk_types = (1 << evol_method),
+ non_ctxk_types = (1 << evol_method) | (1 << call_site_target_value),
implicit_ctxk_types = 0,
explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types),
@@ -330,7 +330,7 @@ class Dependencies: public ResourceObj {
static Klass* check_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2,
KlassDepChange* changes = NULL);
static Klass* check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes = NULL);
- static Klass* check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
+ static Klass* check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
// A returned Klass* is NULL if the dependency assertion is still
// valid. A non-NULL Klass* is a 'witness' to the assertion
// failure, a point in the class hierarchy where the assertion has
@@ -496,7 +496,7 @@ class Dependencies: public ResourceObj {
bool next();
DepType type() { return _type; }
- bool is_oop_argument(int i) { return type() == call_site_target_value && i > 0; }
+ bool is_oop_argument(int i) { return type() == call_site_target_value; }
uintptr_t get_identifier(int i);
int argument_count() { return dep_args(type()); }
diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp
index 5063674ea29..c3d1c076b8a 100644
--- a/hotspot/src/share/vm/code/nmethod.cpp
+++ b/hotspot/src/share/vm/code/nmethod.cpp
@@ -565,13 +565,18 @@ nmethod* nmethod::new_nmethod(methodHandle method,
// the number of methods compiled. For applications with a lot
// classes the slow way is too slow.
for (Dependencies::DepStream deps(nm); deps.next(); ) {
- Klass* klass = deps.context_type();
- if (klass == NULL) {
- continue; // ignore things like evol_method
+ if (deps.type() == Dependencies::call_site_target_value) {
+ // CallSite dependencies are managed on per-CallSite instance basis.
+ oop call_site = deps.argument_oop(0);
+ MethodHandles::add_dependent_nmethod(call_site, nm);
+ } else {
+ Klass* klass = deps.context_type();
+ if (klass == NULL) {
+ continue; // ignore things like evol_method
+ }
+ // record this nmethod as dependent on this klass
+ InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
}
-
- // record this nmethod as dependent on this klass
- InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
}
NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
@@ -1464,13 +1469,20 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
if (!has_flushed_dependencies()) {
set_has_flushed_dependencies();
for (Dependencies::DepStream deps(this); deps.next(); ) {
- Klass* klass = deps.context_type();
- if (klass == NULL) continue; // ignore things like evol_method
-
- // During GC the is_alive closure is non-NULL, and is used to
- // determine liveness of dependees that need to be updated.
- if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
- InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
+ if (deps.type() == Dependencies::call_site_target_value) {
+ // CallSite dependencies are managed on per-CallSite instance basis.
+ oop call_site = deps.argument_oop(0);
+ MethodHandles::remove_dependent_nmethod(call_site, this);
+ } else {
+ Klass* klass = deps.context_type();
+ if (klass == NULL) {
+ continue; // ignore things like evol_method
+ }
+ // During GC the is_alive closure is non-NULL, and is used to
+ // determine liveness of dependees that need to be updated.
+ if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
+ InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
+ }
}
}
}
diff --git a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp
index 539aef1f569..54970b010a3 100644
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp
@@ -254,9 +254,9 @@ void VM_GenCollectFullConcurrent::doit_epilogue() {
if (_gc_cause != GCCause::_gc_locker &&
gch->total_full_collections_completed() <= _full_gc_count_before) {
// maybe we should change the condition to test _gc_cause ==
- // GCCause::_java_lang_system_gc, instead of
- // _gc_cause != GCCause::_gc_locker
- assert(_gc_cause == GCCause::_java_lang_system_gc,
+ // GCCause::_java_lang_system_gc or GCCause::_dcmd_gc_run,
+ // instead of _gc_cause != GCCause::_gc_locker
+ assert(GCCause::is_user_requested_gc(_gc_cause),
"the only way to get here if this was a System.gc()-induced GC");
assert(ExplicitGCInvokesConcurrent, "Error");
// Now, wait for witnessing concurrent gc cycle to complete,
diff --git a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp
index 29eb4dbf9c1..7bbe26ce0dc 100644
--- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp
+++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp
@@ -43,7 +43,7 @@ GangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) {
}
// Run a task; returns when the task is done, or the workers yield,
-// or the task is aborted, or the work gang is terminated via stop().
+// or the task is aborted.
// A task that has been yielded can be continued via this interface
// by using the same task repeatedly as the argument to the call.
// It is expected that the YieldingFlexibleGangTask carries the appropriate
@@ -297,16 +297,9 @@ void YieldingFlexibleGangWorker::loop() {
WorkData data;
int id;
while (true) {
- // Check if there is work to do or if we have been asked
- // to terminate
+ // Check if there is work to do.
gang()->internal_worker_poll(&data);
- if (data.terminate()) {
- // We have been asked to terminate.
- assert(gang()->task() == NULL, "No task binding");
- // set_status(TERMINATED);
- return;
- } else if (data.task() != NULL &&
- data.sequence_number() != previous_sequence_number) {
+ if (data.task() != NULL && data.sequence_number() != previous_sequence_number) {
// There is work to be done.
// First check if we need to become active or if there
// are already the requisite number of workers
diff --git a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp
index 3400f0fcfaf..23ddb321ffd 100644
--- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp
+++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp
@@ -176,7 +176,7 @@ public:
GangWorker* allocate_worker(uint which);
// Run a task; returns when the task is done, or the workers yield,
- // or the task is aborted, or the work gang is terminated via stop().
+ // or the task is aborted.
// A task that has been yielded can be continued via this same interface
// by using the same task repeatedly as the argument to the call.
// It is expected that the YieldingFlexibleGangTask carries the appropriate
diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
index 2ce9501550b..f17c1ea024c 100644
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
@@ -1183,7 +1183,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
IsGCActiveMark x;
// Timing
- assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
+ assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant");
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
{
@@ -2199,6 +2199,7 @@ bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
switch (cause) {
case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent;
+ case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
case GCCause::_g1_humongous_allocation: return true;
case GCCause::_update_allocation_context_stats_inc: return true;
case GCCause::_wb_conc_mark: return true;
diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp
index 48e8b2a5080..821d9f8716d 100644
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp
@@ -324,7 +324,8 @@ private:
// explicitly started if:
// (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or
// (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent.
- // (c) cause == _g1_humongous_allocation
+ // (c) cause == _dcmd_gc_run and +ExplicitGCInvokesConcurrent.
+ // (d) cause == _g1_humongous_allocation
bool should_do_concurrent_full_gc(GCCause::Cause cause);
// Keeps track of how many "old marking cycles" (i.e., Full GCs or
diff --git a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp
index 676d0751da5..90a74d367d5 100644
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp
@@ -168,7 +168,7 @@ void VM_G1IncCollectionPause::doit_epilogue() {
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
// that just started (or maybe one that was already in progress) to
// finish.
- if (_gc_cause == GCCause::_java_lang_system_gc &&
+ if (GCCause::is_user_requested_gc(_gc_cause) &&
_should_initiate_conc_mark) {
assert(ExplicitGCInvokesConcurrent,
"the only way to be here is if ExplicitGCInvokesConcurrent is set");
diff --git a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp
index 2992f8d22dc..51359c64d9c 100644
--- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp
+++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp
@@ -130,7 +130,7 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
// Update the pause time.
_major_timer.stop();
- if (gc_cause != GCCause::_java_lang_system_gc ||
+ if (!GCCause::is_user_requested_gc(gc_cause) ||
UseAdaptiveSizePolicyWithSystemGC) {
double major_pause_in_seconds = _major_timer.seconds();
double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS;
diff --git a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp
index cc8b33e064d..540ae77b9fd 100644
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp
@@ -272,7 +272,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
// Don't check if the size_policy is ready here. Let
// the size_policy check that internally.
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
- ((gc_cause != GCCause::_java_lang_system_gc) ||
+ (!GCCause::is_user_requested_gc(gc_cause) ||
UseAdaptiveSizePolicyWithSystemGC)) {
// Swap the survivor spaces if from_space is empty. The
// resize_young_gen() called below is normally used after
diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp
index 6b2553fb408..98c1b26bae0 100644
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp
@@ -2053,7 +2053,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer);
bool max_on_system_gc = UseMaximumCompactionOnSystemGC
- && gc_cause == GCCause::_java_lang_system_gc;
+ && GCCause::is_user_requested_gc(gc_cause);
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
@@ -2089,7 +2089,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
// Don't check if the size_policy is ready here. Let
// the size_policy check that internally.
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
- ((gc_cause != GCCause::_java_lang_system_gc) ||
+ (!GCCause::is_user_requested_gc(gc_cause) ||
UseAdaptiveSizePolicyWithSystemGC)) {
// Swap the survivor spaces if from_space is empty. The
// resize_young_gen() called below is normally used after
diff --git a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp
index 8f7b693b252..9023bd8997f 100644
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp
@@ -290,7 +290,7 @@ bool PSScavenge::invoke_no_policy() {
AdaptiveSizePolicyOutput(size_policy, heap->total_collections());
- if ((gc_cause != GCCause::_java_lang_system_gc) ||
+ if (!GCCause::is_user_requested_gc(gc_cause) ||
UseAdaptiveSizePolicyWithSystemGC) {
// Gather the feedback data for eden occupancy.
young_gen->eden_space()->accumulate_statistics();
diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
index 33a40c3744d..4374359b664 100644
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
@@ -960,7 +960,7 @@ void DefNewGeneration::gc_epilogue(bool full) {
GCCause::to_string(gch->gc_cause()));
}
assert(gch->gc_cause() == GCCause::_scavenge_alot ||
- (gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
+ (GCCause::is_user_requested_gc(gch->gc_cause()) && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
!gch->incremental_collection_failed(),
"Twice in a row");
seen_incremental_collection_failed = false;
diff --git a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp
index eba54f95aff..d2d90956073 100644
--- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp
+++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp
@@ -244,7 +244,7 @@ void AdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) {
// Update the pause time.
_minor_timer.stop();
- if (gc_cause != GCCause::_java_lang_system_gc ||
+ if (!GCCause::is_user_requested_gc(gc_cause) ||
UseAdaptiveSizePolicyWithSystemGC) {
double minor_pause_in_seconds = _minor_timer.seconds();
double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS;
diff --git a/hotspot/src/share/vm/gc/shared/gcCause.cpp b/hotspot/src/share/vm/gc/shared/gcCause.cpp
index e7fd667dc0c..526e4fc90cb 100644
--- a/hotspot/src/share/vm/gc/shared/gcCause.cpp
+++ b/hotspot/src/share/vm/gc/shared/gcCause.cpp
@@ -103,6 +103,9 @@ const char* GCCause::to_string(GCCause::Cause cause) {
case _last_ditch_collection:
return "Last ditch collection";
+ case _dcmd_gc_run:
+ return "Diagnostic Command";
+
case _last_gc_cause:
return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE";
diff --git a/hotspot/src/share/vm/gc/shared/gcCause.hpp b/hotspot/src/share/vm/gc/shared/gcCause.hpp
index 88dc37fe2a2..0d711d8c24a 100644
--- a/hotspot/src/share/vm/gc/shared/gcCause.hpp
+++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp
@@ -74,12 +74,15 @@ class GCCause : public AllStatic {
_g1_humongous_allocation,
_last_ditch_collection,
+
+ _dcmd_gc_run,
+
_last_gc_cause
};
inline static bool is_user_requested_gc(GCCause::Cause cause) {
return (cause == GCCause::_java_lang_system_gc ||
- cause == GCCause::_jvmti_force_gc);
+ cause == GCCause::_dcmd_gc_run);
}
inline static bool is_serviceability_requested_gc(GCCause::Cause
diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
index 5f490f61a7a..821df40b821 100644
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
@@ -304,9 +304,16 @@ bool GenCollectedHeap::must_clear_all_soft_refs() {
}
bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
- return UseConcMarkSweepGC &&
- ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
- (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
+ if (!UseConcMarkSweepGC) {
+ return false;
+ }
+
+ switch (cause) {
+ case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
+ case GCCause::_java_lang_system_gc:
+ case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
+ default: return false;
+ }
}
void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size,
diff --git a/hotspot/src/share/vm/gc/shared/workgroup.cpp b/hotspot/src/share/vm/gc/shared/workgroup.cpp
index 6d615dd7bcb..e2aaa9ae440 100644
--- a/hotspot/src/share/vm/gc/shared/workgroup.cpp
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp
@@ -47,7 +47,6 @@ AbstractWorkGang::AbstractWorkGang(const char* name,
/* allow_vm_block */ are_GC_task_threads,
Monitor::_safepoint_check_sometimes);
assert(monitor() != NULL, "Failed to allocate monitor");
- _terminate = false;
_task = NULL;
_sequence_number = 0;
_started_workers = 0;
@@ -106,18 +105,6 @@ bool WorkGang::initialize_workers() {
return true;
}
-AbstractWorkGang::~AbstractWorkGang() {
- if (TraceWorkGang) {
- tty->print_cr("Destructing work gang %s", name());
- }
- stop(); // stop all the workers
- for (uint worker = 0; worker < total_workers(); worker += 1) {
- delete gang_worker(worker);
- }
- delete gang_workers();
- delete monitor();
-}
-
GangWorker* AbstractWorkGang::gang_worker(uint i) const {
// Array index bounds checking.
GangWorker* result = NULL;
@@ -175,28 +162,9 @@ void FlexibleWorkGang::run_task(AbstractGangTask* task) {
WorkGang::run_task(task, (uint) active_workers());
}
-void AbstractWorkGang::stop() {
- // Tell all workers to terminate, then wait for them to become inactive.
- MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
- if (TraceWorkGang) {
- tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
- }
- _task = NULL;
- _terminate = true;
- monitor()->notify_all();
- while (finished_workers() < active_workers()) {
- if (TraceWorkGang) {
- tty->print_cr("Waiting in work gang %s: %u/%u finished",
- name(), finished_workers(), active_workers());
- }
- monitor()->wait(/* no_safepoint_check */ true);
- }
-}
-
void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
assert(monitor()->owned_by_self(), "worker_poll is an internal method");
assert(data != NULL, "worker data is null");
- data->set_terminate(terminate());
data->set_task(task());
data->set_sequence_number(sequence_number());
}
@@ -259,7 +227,7 @@ void GangWorker::initialize() {
void GangWorker::loop() {
int previous_sequence_number = 0;
Monitor* gang_monitor = gang()->monitor();
- for ( ; /* !terminate() */; ) {
+ for ( ; ; ) {
WorkData data;
int part; // Initialized below.
{
@@ -272,8 +240,6 @@ void GangWorker::loop() {
if (TraceWorkGang) {
tty->print("Polled outside for work in gang %s worker %u",
gang()->name(), id());
- tty->print(" terminate: %s",
- data.terminate() ? "true" : "false");
tty->print(" sequence: %d (prev: %d)",
data.sequence_number(), previous_sequence_number);
if (data.task() != NULL) {
@@ -283,13 +249,7 @@ void GangWorker::loop() {
}
tty->cr();
}
- for ( ; /* break or return */; ) {
- // Terminate if requested.
- if (data.terminate()) {
- gang()->internal_note_finish();
- gang_monitor->notify_all();
- return;
- }
+ for ( ; /* break */; ) {
// Check for new work.
if ((data.task() != NULL) &&
(data.sequence_number() != previous_sequence_number)) {
@@ -306,8 +266,6 @@ void GangWorker::loop() {
if (TraceWorkGang) {
tty->print("Polled inside for work in gang %s worker %u",
gang()->name(), id());
- tty->print(" terminate: %s",
- data.terminate() ? "true" : "false");
tty->print(" sequence: %d (prev: %d)",
data.sequence_number(), previous_sequence_number);
if (data.task() != NULL) {
diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp
index 1c0aad8cf0e..44464023a05 100644
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp
@@ -103,16 +103,15 @@ class AbstractGangTaskWOopQueues : public AbstractGangTask {
// An abstract class representing a gang of workers.
// You subclass this to supply an implementation of run_task().
class AbstractWorkGang: public CHeapObj {
- // Here's the public interface to this class.
+protected:
+ // Work gangs are never deleted, so no need to cleanup.
+ ~AbstractWorkGang() { ShouldNotReachHere(); }
public:
- // Constructor and destructor.
+ // Constructor.
AbstractWorkGang(const char* name, bool are_GC_task_threads,
bool are_ConcurrentGC_threads);
- ~AbstractWorkGang();
// Run a task, returns when the task is done (or terminated).
virtual void run_task(AbstractGangTask* task) = 0;
- // Stop and terminate all workers.
- virtual void stop();
// Return true if more workers should be applied to the task.
virtual bool needs_more_workers() const { return true; }
public:
@@ -129,8 +128,6 @@ protected:
Monitor* _monitor;
// The count of the number of workers in the gang.
uint _total_workers;
- // Whether the workers should terminate.
- bool _terminate;
// The array of worker threads for this gang.
// This is only needed for cleaning up.
GangWorker** _gang_workers;
@@ -153,9 +150,6 @@ public:
virtual uint active_workers() const {
return _total_workers;
}
- bool terminate() const {
- return _terminate;
- }
GangWorker** gang_workers() const {
return _gang_workers;
}
@@ -205,21 +199,16 @@ protected:
class WorkData: public StackObj {
// This would be a struct, but I want accessor methods.
private:
- bool _terminate;
AbstractGangTask* _task;
int _sequence_number;
public:
// Constructor and destructor
WorkData() {
- _terminate = false;
_task = NULL;
_sequence_number = 0;
}
~WorkData() {
}
- // Accessors and modifiers
- bool terminate() const { return _terminate; }
- void set_terminate(bool value) { _terminate = value; }
AbstractGangTask* task() const { return _task; }
void set_task(AbstractGangTask* value) { _task = value; }
int sequence_number() const { return _sequence_number; }
diff --git a/hotspot/src/share/vm/interpreter/bytecode.cpp b/hotspot/src/share/vm/interpreter/bytecode.cpp
index 70c3584e55c..80b95d627b5 100644
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -147,13 +147,10 @@ BasicType Bytecode_member_ref::result_type() const {
methodHandle Bytecode_invoke::static_target(TRAPS) {
- methodHandle m;
- KlassHandle resolved_klass;
constantPoolHandle constants(THREAD, this->constants());
Bytecodes::Code bc = invoke_code();
- LinkResolver::resolve_method_statically(m, resolved_klass, bc, constants, index(), CHECK_(methodHandle()));
- return m;
+ return LinkResolver::resolve_method_statically(bc, constants, index(), THREAD);
}
Handle Bytecode_invoke::appendix(TRAPS) {
diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp
index 5141f19dbc2..d3a97225c20 100644
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp
@@ -52,13 +52,17 @@
// Implementation of CallInfo
-void CallInfo::set_static(KlassHandle resolved_klass, methodHandle resolved_method, TRAPS) {
+void CallInfo::set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS) {
int vtable_index = Method::nonvirtual_vtable_index;
set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK);
}
-void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index, TRAPS) {
+void CallInfo::set_interface(KlassHandle resolved_klass,
+ KlassHandle selected_klass,
+ const methodHandle& resolved_method,
+ const methodHandle& selected_method,
+ int itable_index, TRAPS) {
// This is only called for interface methods. If the resolved_method
// comes from java/lang/Object, it can be the subject of a virtual call, so
// we should pick the vtable index from the resolved method.
@@ -68,7 +72,11 @@ void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_kl
set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK);
}
-void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
+void CallInfo::set_virtual(KlassHandle resolved_klass,
+ KlassHandle selected_klass,
+ const methodHandle& resolved_method,
+ const methodHandle& selected_method,
+ int vtable_index, TRAPS) {
assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "valid index");
assert(vtable_index < 0 || !resolved_method->has_vtable_index() || vtable_index == resolved_method->vtable_index(), "");
CallKind kind = (vtable_index >= 0 && !resolved_method->can_be_statically_bound() ? CallInfo::vtable_call : CallInfo::direct_call);
@@ -76,7 +84,9 @@ void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klas
assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call");
}
-void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) {
+void CallInfo::set_handle(const methodHandle& resolved_method,
+ Handle resolved_appendix,
+ Handle resolved_method_type, TRAPS) {
if (resolved_method.is_null()) {
THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null");
}
@@ -93,8 +103,8 @@ void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix
void CallInfo::set_common(KlassHandle resolved_klass,
KlassHandle selected_klass,
- methodHandle resolved_method,
- methodHandle selected_method,
+ const methodHandle& resolved_method,
+ const methodHandle& selected_method,
CallKind kind,
int index,
TRAPS) {
@@ -210,8 +220,52 @@ void CallInfo::verify() {
}
#endif //ASSERT
+#ifndef PRODUCT
+void CallInfo::print() {
+ ResourceMark rm;
+ const char* kindstr = "unknown";
+ switch (_call_kind) {
+ case direct_call: kindstr = "direct"; break;
+ case vtable_call: kindstr = "vtable"; break;
+ case itable_call: kindstr = "itable"; break;
+ }
+ tty->print_cr("Call %s@%d %s", kindstr, _call_index,
+ _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string());
+}
+#endif
+//------------------------------------------------------------------------------------------------------------------------
+// Implementation of LinkInfo
+LinkInfo::LinkInfo(constantPoolHandle pool, int index, TRAPS) {
+ // resolve klass
+ Klass* result = pool->klass_ref_at(index, CHECK);
+ _resolved_klass = KlassHandle(THREAD, result);
+
+ // Get name, signature, and static klass
+ _name = pool->name_ref_at(index);
+ _signature = pool->signature_ref_at(index);
+ _current_klass = KlassHandle(THREAD, pool->pool_holder());
+
+ // Coming from the constant pool always checks access
+ _check_access = true;
+}
+
+char* LinkInfo::method_string() const {
+ return Method::name_and_sig_as_C_string(_resolved_klass(), _name, _signature);
+}
+
+#ifndef PRODUCT
+void LinkInfo::print() {
+ ResourceMark rm;
+ tty->print_cr("Link resolved_klass=%s name=%s signature=%s current_klass=%s check_access=%s",
+ _resolved_klass->name()->as_C_string(),
+ _name->as_C_string(),
+ _signature->as_C_string(),
+ _current_klass.is_null() ? "(none)" : _current_klass->name()->as_C_string(),
+ _check_access ? "true" : "false");
+}
+#endif // PRODUCT
//------------------------------------------------------------------------------------------------------------------------
// Klass resolution
@@ -231,11 +285,6 @@ void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle
}
}
-void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) {
- Klass* result_oop = pool->klass_ref_at(index, CHECK);
- result = KlassHandle(THREAD, result_oop);
-}
-
//------------------------------------------------------------------------------------------------------------------------
// Method resolution
//
@@ -243,76 +292,84 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i
// Look up method in klasses, including static methods
// Then look up local default methods
-void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) {
+methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info,
+ bool checkpolymorphism,
+ bool in_imethod_resolve, TRAPS) {
+ KlassHandle klass = link_info.resolved_klass();
+ Symbol* name = link_info.name();
+ Symbol* signature = link_info.signature();
+
// Ignore overpasses so statics can be found during resolution
- Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
+ Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
if (klass->oop_is_array()) {
// Only consider klass and super klass for arrays
- result = methodHandle(THREAD, result_oop);
- return;
+ return methodHandle(THREAD, result);
}
// JDK 8, JVMS 5.4.3.4: Interface method resolution should
// ignore static and non-public methods of java.lang.Object,
// like clone, finalize, registerNatives.
if (in_imethod_resolve &&
- result_oop != NULL &&
+ result != NULL &&
klass->is_interface() &&
- (result_oop->is_static() || !result_oop->is_public()) &&
- result_oop->method_holder() == SystemDictionary::Object_klass()) {
- result_oop = NULL;
+ (result->is_static() || !result->is_public()) &&
+ result->method_holder() == SystemDictionary::Object_klass()) {
+ result = NULL;
}
// Before considering default methods, check for an overpass in the
// current class if a method has not been found.
- if (result_oop == NULL) {
- result_oop = InstanceKlass::cast(klass())->find_method(name, signature);
+ if (result == NULL) {
+ result = InstanceKlass::cast(klass())->find_method(name, signature);
}
- if (result_oop == NULL) {
+ if (result == NULL) {
Array* default_methods = InstanceKlass::cast(klass())->default_methods();
if (default_methods != NULL) {
- result_oop = InstanceKlass::find_method(default_methods, name, signature);
+ result = InstanceKlass::find_method(default_methods, name, signature);
}
}
- if (checkpolymorphism && result_oop != NULL) {
- vmIntrinsics::ID iid = result_oop->intrinsic_id();
+ if (checkpolymorphism && result != NULL) {
+ vmIntrinsics::ID iid = result->intrinsic_id();
if (MethodHandles::is_signature_polymorphic(iid)) {
// Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method.
- return;
+ return NULL;
}
}
- result = methodHandle(THREAD, result_oop);
+ return methodHandle(THREAD, result);
}
// returns first instance method
// Looks up method in classes, then looks up local default methods
-void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
- Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::find_overpass);
- result = methodHandle(THREAD, result_oop);
- while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) {
- KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super());
- result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::find_overpass));
+methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass,
+ Symbol* name,
+ Symbol* signature, TRAPS) {
+ Method* result = klass->uncached_lookup_method(name, signature, Klass::find_overpass);
+
+ while (result != NULL && result->is_static() && result->method_holder()->super() != NULL) {
+ Klass* super_klass = result->method_holder()->super();
+ result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass);
}
if (klass->oop_is_array()) {
// Only consider klass and super klass for arrays
- return;
+ return methodHandle(THREAD, result);
}
- if (result.is_null()) {
+ if (result == NULL) {
Array* default_methods = InstanceKlass::cast(klass())->default_methods();
if (default_methods != NULL) {
- result = methodHandle(InstanceKlass::find_method(default_methods, name, signature));
- assert(result.is_null() || !result->is_static(), "static defaults not allowed");
+ result = InstanceKlass::find_method(default_methods, name, signature);
+ assert(result == NULL || !result->is_static(), "static defaults not allowed");
}
}
+ return methodHandle(THREAD, result);
}
int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
- methodHandle resolved_method) {
+ const methodHandle& resolved_method) {
int vtable_index = Method::invalid_vtable_index;
Symbol* name = resolved_method->name();
@@ -336,21 +393,26 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
return vtable_index;
}
-void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
- InstanceKlass *ik = InstanceKlass::cast(klass());
+methodHandle LinkResolver::lookup_method_in_interfaces(const LinkInfo& cp_info, TRAPS) {
+ InstanceKlass *ik = InstanceKlass::cast(cp_info.resolved_klass()());
// Specify 'true' in order to skip default methods when searching the
// interfaces. Function lookup_method_in_klasses() already looked for
// the method in the default methods table.
- result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, Klass::skip_defaults));
+ return methodHandle(THREAD,
+ ik->lookup_method_in_all_interfaces(cp_info.name(), cp_info.signature(),
+ Klass::skip_defaults));
}
-void LinkResolver::lookup_polymorphic_method(methodHandle& result,
- KlassHandle klass, Symbol* name, Symbol* full_signature,
- KlassHandle current_klass,
+methodHandle LinkResolver::lookup_polymorphic_method(
+ const LinkInfo& link_info,
Handle *appendix_result_or_null,
Handle *method_type_result,
TRAPS) {
+ KlassHandle klass = link_info.resolved_klass();
+ Symbol* name = link_info.name();
+ Symbol* full_signature = link_info.signature();
+
vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
if (TraceMethodHandles) {
ResourceMark rm(THREAD);
@@ -365,7 +427,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
// Do not erase last argument type (MemberName) if it is a static linkTo method.
bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid);
TempNewSymbol basic_signature =
- MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK);
+ MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK_NULL);
if (TraceMethodHandles) {
ResourceMark rm(THREAD);
tty->print_cr("lookup_polymorphic_method %s %s => basic %s",
@@ -373,9 +435,9 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
full_signature->as_C_string(),
basic_signature->as_C_string());
}
- result = SystemDictionary::find_method_handle_intrinsic(iid,
+ methodHandle result = SystemDictionary::find_method_handle_intrinsic(iid,
basic_signature,
- CHECK);
+ CHECK_NULL);
if (result.not_null()) {
assert(result->is_method_handle_intrinsic(), "MH.invokeBasic or MH.linkTo* intrinsic");
assert(result->intrinsic_id() != vmIntrinsics::_invokeGeneric, "wrong place to find this");
@@ -384,8 +446,8 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
tty->print("lookup_polymorphic_method => intrinsic ");
result->print_on(tty);
}
- return;
}
+ return result;
} else if (iid == vmIntrinsics::_invokeGeneric
&& !THREAD->is_Compiler_thread()
&& appendix_result_or_null != NULL) {
@@ -399,18 +461,19 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
Handle(),
Handle(),
true,
- CHECK);
+ CHECK_NULL);
}
}
Handle appendix;
Handle method_type;
- result = SystemDictionary::find_method_handle_invoker(name,
+ methodHandle result = SystemDictionary::find_method_handle_invoker(
+ name,
full_signature,
- current_klass,
+ link_info.current_klass(),
&appendix,
&method_type,
- CHECK);
+ CHECK_NULL);
if (TraceMethodHandles) {
tty->print("lookup_polymorphic_method => (via Java) ");
result->print_on(tty);
@@ -423,7 +486,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
ResourceMark rm(THREAD);
TempNewSymbol basic_signature =
- MethodHandles::lookup_basic_type_signature(full_signature, CHECK);
+ MethodHandles::lookup_basic_type_signature(full_signature, CHECK_NULL);
int actual_size_of_params = result->size_of_parameters();
int expected_size_of_params = ArgumentSizeComputer(basic_signature).size();
// +1 for MethodHandle.this, +1 for trailing MethodType
@@ -441,16 +504,17 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result,
assert(appendix_result_or_null != NULL, "");
(*appendix_result_or_null) = appendix;
(*method_type_result) = method_type;
- return;
}
+ return result;
}
}
+ return NULL;
}
void LinkResolver::check_method_accessability(KlassHandle ref_klass,
KlassHandle resolved_klass,
KlassHandle sel_klass,
- methodHandle sel_method,
+ const methodHandle& sel_method,
TRAPS) {
AccessFlags flags = sel_method->access_flags();
@@ -493,8 +557,8 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass,
}
}
-void LinkResolver::resolve_method_statically(methodHandle& resolved_method, KlassHandle& resolved_klass,
- Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS) {
+methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code,
+ constantPoolHandle pool, int index, TRAPS) {
// This method is used only
// (1) in C2 from InlineTree::ok_to_inline (via ciMethod::check_call),
// and
@@ -502,49 +566,108 @@ void LinkResolver::resolve_method_statically(methodHandle& resolved_method, Klas
// It appears to fail when applied to an invokeinterface call site.
// FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points.
// resolve klass
+ KlassHandle resolved_klass;
if (code == Bytecodes::_invokedynamic) {
resolved_klass = SystemDictionary::MethodHandle_klass();
Symbol* method_name = vmSymbols::invoke_name();
Symbol* method_signature = pool->signature_ref_at(index);
KlassHandle current_klass(THREAD, pool->pool_holder());
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
- return;
+ LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass);
+ return resolve_method(link_info, /*require_methodref*/false, THREAD);
}
- resolve_klass(resolved_klass, pool, index, CHECK);
-
- Symbol* method_name = pool->name_ref_at(index);
- Symbol* method_signature = pool->signature_ref_at(index);
- KlassHandle current_klass(THREAD, pool->pool_holder());
+ LinkInfo link_info(pool, index, CHECK_NULL);
+ resolved_klass = link_info.resolved_klass();
if (pool->has_preresolution()
|| (resolved_klass() == SystemDictionary::MethodHandle_klass() &&
- MethodHandles::is_signature_polymorphic_name(resolved_klass(), method_name))) {
- Method* result_oop = ConstantPool::method_at_if_loaded(pool, index);
- if (result_oop != NULL) {
- resolved_method = methodHandle(THREAD, result_oop);
- return;
+ MethodHandles::is_signature_polymorphic_name(resolved_klass(), link_info.name()))) {
+ Method* result = ConstantPool::method_at_if_loaded(pool, index);
+ if (result != NULL) {
+ return methodHandle(THREAD, result);
}
}
if (code == Bytecodes::_invokeinterface) {
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+ return resolve_interface_method(link_info, true, THREAD);
} else if (code == Bytecodes::_invokevirtual) {
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+ return resolve_method(link_info, /*require_methodref*/true, THREAD);
} else if (!resolved_klass->is_interface()) {
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
+ return resolve_method(link_info, /*require_methodref*/false, THREAD);
} else {
bool nostatics = (code == Bytecodes::_invokestatic) ? false : true;
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK);
+ return resolve_interface_method(link_info, nostatics, THREAD);
}
}
-void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature,
- KlassHandle current_klass, bool check_access,
- bool require_methodref, TRAPS) {
+// Check and print a loader constraint violation message for method or interface method
+void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info,
+ const methodHandle& resolved_method,
+ const char* method_type, TRAPS) {
+ Handle current_loader(THREAD, link_info.current_klass()->class_loader());
+ Handle resolved_loader(THREAD, resolved_method->method_holder()->class_loader());
+
+ ResourceMark rm(THREAD);
+ Symbol* failed_type_symbol =
+ SystemDictionary::check_signature_loaders(link_info.signature(), current_loader,
+ resolved_loader, true, CHECK);
+ if (failed_type_symbol != NULL) {
+ const char* msg = "loader constraint violation: when resolving %s"
+ " \"%s\" the class loader (instance of %s) of the current class, %s,"
+ " and the class loader (instance of %s) for the method's defining class, %s, have"
+ " different Class objects for the type %s used in the signature";
+ char* sig = link_info.method_string();
+ const char* loader1_name = SystemDictionary::loader_name(current_loader());
+ char* current = link_info.current_klass()->name()->as_C_string();
+ const char* loader2_name = SystemDictionary::loader_name(resolved_loader());
+ char* target = resolved_method->method_holder()->name()->as_C_string();
+ char* failed_type_name = failed_type_symbol->as_C_string();
+ size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1_name) +
+ strlen(current) + strlen(loader2_name) + strlen(target) +
+ strlen(failed_type_name) + strlen(method_type) + 1;
+ char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
+ jio_snprintf(buf, buflen, msg, method_type, sig, loader1_name, current, loader2_name,
+ target, failed_type_name);
+ THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
+ }
+}
+
+void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig,
+ KlassHandle current_klass,
+ KlassHandle sel_klass, TRAPS) {
+ Handle ref_loader(THREAD, current_klass->class_loader());
+ Handle sel_loader(THREAD, sel_klass->class_loader());
+
+ ResourceMark rm(THREAD); // needed for check_signature_loaders
+ Symbol* failed_type_symbol =
+ SystemDictionary::check_signature_loaders(sig,
+ ref_loader, sel_loader,
+ false,
+ CHECK);
+ if (failed_type_symbol != NULL) {
+ const char* msg = "loader constraint violation: when resolving field"
+ " \"%s\" the class loader (instance of %s) of the referring class, "
+ "%s, and the class loader (instance of %s) for the field's resolved "
+ "type, %s, have different Class objects for that type";
+ char* field_name = field->as_C_string();
+ const char* loader1_name = SystemDictionary::loader_name(ref_loader());
+ char* sel = sel_klass->name()->as_C_string();
+ const char* loader2_name = SystemDictionary::loader_name(sel_loader());
+ char* failed_type_name = failed_type_symbol->as_C_string();
+ size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) +
+ strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1;
+ char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
+ jio_snprintf(buf, buflen, msg, field_name, loader1_name, sel, loader2_name,
+ failed_type_name);
+ THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
+ }
+}
+
+methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
+ bool require_methodref, TRAPS) {
Handle nested_exception;
+ KlassHandle resolved_klass = link_info.resolved_klass();
// 1. check if methodref required, that resolved_klass is not interfacemethodref
if (require_methodref && resolved_klass->is_interface()) {
@@ -552,20 +675,19 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
char buf[200];
jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected",
resolved_klass()->external_name());
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
// 2. lookup method in resolved klass and its super klasses
- lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK);
+ methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL);
if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy
// 3. lookup method in all the interfaces implemented by the resolved klass
- lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
+ resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
if (resolved_method.is_null()) {
// JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc
- lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature,
- current_klass, (Handle*)NULL, (Handle*)NULL, THREAD);
+ resolved_method = lookup_polymorphic_method(link_info, (Handle*)NULL, (Handle*)NULL, THREAD);
if (HAS_PENDING_EXCEPTION) {
nested_exception = Handle(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
@@ -576,15 +698,16 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
if (resolved_method.is_null()) {
// 4. method lookup failed
ResourceMark rm(THREAD);
- THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
+ THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(),
Method::name_and_sig_as_C_string(resolved_klass(),
- method_name,
- method_signature),
- nested_exception);
+ link_info.name(),
+ link_info.signature()),
+ nested_exception, NULL);
}
// 5. access checks, access checking may be turned off when calling from within the VM.
- if (check_access) {
+ KlassHandle current_klass = link_info.current_klass();
+ if (link_info.check_access()) {
assert(current_klass.not_null() , "current_klass should not be null");
// check if method can be accessed by the referring class
@@ -592,76 +715,50 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
resolved_klass,
KlassHandle(THREAD, resolved_method->method_holder()),
resolved_method,
- CHECK);
+ CHECK_NULL);
// check loader constraints
- Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
- Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
- {
- ResourceMark rm(THREAD);
- Symbol* failed_type_symbol =
- SystemDictionary::check_signature_loaders(method_signature, loader,
- class_loader, true, CHECK);
- if (failed_type_symbol != NULL) {
- const char* msg = "loader constraint violation: when resolving method"
- " \"%s\" the class loader (instance of %s) of the current class, %s,"
- " and the class loader (instance of %s) for the method's defining class, %s, have"
- " different Class objects for the type %s used in the signature";
- char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature);
- const char* loader1 = SystemDictionary::loader_name(loader());
- char* current = InstanceKlass::cast(current_klass())->name()->as_C_string();
- const char* loader2 = SystemDictionary::loader_name(class_loader());
- char* target = InstanceKlass::cast(resolved_method->method_holder())
- ->name()->as_C_string();
- char* failed_type_name = failed_type_symbol->as_C_string();
- size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
- strlen(current) + strlen(loader2) + strlen(target) +
- strlen(failed_type_name) + 1;
- char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
- jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
- target, failed_type_name);
- THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
- }
- }
+ check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL);
}
+
+ return resolved_method;
}
-void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
- KlassHandle resolved_klass,
- Symbol* method_name,
- Symbol* method_signature,
- KlassHandle current_klass,
- bool check_access,
- bool nostatics, TRAPS) {
+methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info,
+ bool nostatics, TRAPS) {
+
+ KlassHandle resolved_klass = link_info.resolved_klass();
// check if klass is interface
if (!resolved_klass->is_interface()) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name());
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
// lookup method in this interface or its super, java.lang.Object
// JDK8: also look for static methods
- lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK);
+ methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL);
if (resolved_method.is_null() && !resolved_klass->oop_is_array()) {
// lookup method in all the super-interfaces
- lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
+ resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
}
if (resolved_method.is_null()) {
// no method found
ResourceMark rm(THREAD);
- THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
- Method::name_and_sig_as_C_string(resolved_klass(),
- method_name,
- method_signature));
+ THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(),
+ Method::name_and_sig_as_C_string(resolved_klass(),
+ link_info.name(),
+ link_info.signature()));
}
- if (check_access) {
+ if (link_info.check_access()) {
// JDK8 adds non-public interface methods, and accessability check requirement
+ KlassHandle current_klass = link_info.current_klass();
+
assert(current_klass.not_null() , "current_klass should not be null");
// check if method can be accessed by the referring class
@@ -669,38 +766,9 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
resolved_klass,
KlassHandle(THREAD, resolved_method->method_holder()),
resolved_method,
- CHECK);
+ CHECK_NULL);
- HandleMark hm(THREAD);
- Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
- Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
- {
- ResourceMark rm(THREAD);
- Symbol* failed_type_symbol =
- SystemDictionary::check_signature_loaders(method_signature, loader,
- class_loader, true, CHECK);
- if (failed_type_symbol != NULL) {
- const char* msg = "loader constraint violation: when resolving "
- "interface method \"%s\" the class loader (instance of %s) of the "
- "current class, %s, and the class loader (instance of %s) for "
- "the method's defining class, %s, have different Class objects for the type %s "
- "used in the signature";
- char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature);
- const char* loader1 = SystemDictionary::loader_name(loader());
- char* current = InstanceKlass::cast(current_klass())->name()->as_C_string();
- const char* loader2 = SystemDictionary::loader_name(class_loader());
- char* target = InstanceKlass::cast(resolved_method->method_holder())
- ->name()->as_C_string();
- char* failed_type_name = failed_type_symbol->as_C_string();
- size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
- strlen(current) + strlen(loader2) + strlen(target) +
- strlen(failed_type_name) + 1;
- char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
- jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
- target, failed_type_name);
- THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
- }
- }
+ check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL);
}
if (nostatics && resolved_method->is_static()) {
@@ -709,28 +777,16 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s",
Method::name_and_sig_as_C_string(resolved_klass(),
resolved_method->name(), resolved_method->signature()));
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (TraceItables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
- (current_klass.is_null() ? "" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()),
- resolved_method->method_holder()->internal_name()
- );
- resolved_method->access_flags().print_on(tty);
- if (resolved_method->is_default_method()) {
- tty->print("default ");
- }
- if (resolved_method->is_overpass()) {
- tty->print("overpass");
- }
+ trace_method_resolution("invokeinterface resolved method: caller-class",
+ link_info.current_klass(), resolved_klass, resolved_method);
tty->cr();
}
+
+ return resolved_method;
}
//------------------------------------------------------------------------------------------------------------------------
@@ -739,7 +795,7 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
void LinkResolver::check_field_accessability(KlassHandle ref_klass,
KlassHandle resolved_klass,
KlassHandle sel_klass,
- fieldDescriptor& fd,
+ const fieldDescriptor& fd,
TRAPS) {
if (!Reflection::verify_field_access(ref_klass(),
resolved_klass(),
@@ -759,30 +815,27 @@ void LinkResolver::check_field_accessability(KlassHandle ref_klass,
}
}
-void LinkResolver::resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
- // Load these early in case the resolve of the containing klass fails
- Symbol* field = pool->name_ref_at(index);
- Symbol* sig = pool->signature_ref_at(index);
-
- // resolve specified klass
- KlassHandle resolved_klass;
- resolve_klass(resolved_klass, pool, index, CHECK);
-
- KlassHandle current_klass(THREAD, pool->pool_holder());
- resolve_field(result, resolved_klass, field, sig, current_klass, byte, true, true, CHECK);
+void LinkResolver::resolve_field_access(fieldDescriptor& fd, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
+ LinkInfo link_info(pool, index, CHECK);
+ resolve_field(fd, link_info, byte, true, CHECK);
}
-void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass, Symbol* field, Symbol* sig,
- KlassHandle current_klass, Bytecodes::Code byte, bool check_access, bool initialize_class,
+void LinkResolver::resolve_field(fieldDescriptor& fd,
+ const LinkInfo& link_info,
+ Bytecodes::Code byte, bool initialize_class,
TRAPS) {
assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
byte == Bytecodes::_getfield || byte == Bytecodes::_putfield ||
byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield ||
- (byte == Bytecodes::_nop && !check_access), "bad field access bytecode");
+ (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield);
// Check if there's a resolved klass containing the field
+ KlassHandle resolved_klass = link_info.resolved_klass();
+ Symbol* field = link_info.name();
+ Symbol* sig = link_info.signature();
+
if (resolved_klass.is_null()) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
@@ -796,11 +849,12 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass
THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
}
- if (!check_access)
+ if (!link_info.check_access())
// Access checking may be turned off when calling from within the VM.
return;
// check access
+ KlassHandle current_klass = link_info.current_klass();
check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
// check for errors
@@ -827,34 +881,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass
}
if (sel_klass() != current_klass()) {
- HandleMark hm(THREAD);
- Handle ref_loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
- Handle sel_loader (THREAD, InstanceKlass::cast(sel_klass())->class_loader());
- {
- ResourceMark rm(THREAD);
- Symbol* failed_type_symbol =
- SystemDictionary::check_signature_loaders(sig,
- ref_loader, sel_loader,
- false,
- CHECK);
- if (failed_type_symbol != NULL) {
- const char* msg = "loader constraint violation: when resolving field"
- " \"%s\" the class loader (instance of %s) of the referring class, "
- "%s, and the class loader (instance of %s) for the field's resolved "
- "type, %s, have different Class objects for that type";
- char* field_name = field->as_C_string();
- const char* loader1 = SystemDictionary::loader_name(ref_loader());
- char* sel = InstanceKlass::cast(sel_klass())->name()->as_C_string();
- const char* loader2 = SystemDictionary::loader_name(sel_loader());
- char* failed_type_name = failed_type_symbol->as_C_string();
- size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) +
- strlen(sel) + strlen(loader2) + strlen(failed_type_name) + 1;
- char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
- jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2,
- failed_type_name);
- THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
- }
- }
+ check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK);
}
// return information. note that the klass is set to the actual klass containing the
@@ -873,32 +900,38 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass
// recv_klass the receiver klass
-void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name,
- Symbol* method_signature, KlassHandle current_klass,
- bool check_access, bool initialize_class, TRAPS) {
- methodHandle resolved_method;
- linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
- resolved_klass = KlassHandle(THREAD, resolved_method->method_holder());
+void LinkResolver::resolve_static_call(CallInfo& result,
+ const LinkInfo& link_info,
+ bool initialize_class, TRAPS) {
+ methodHandle resolved_method = linktime_resolve_static_method(link_info, CHECK);
+ // The resolved class can change as a result of this resolution.
+ KlassHandle resolved_klass = KlassHandle(THREAD, resolved_method->method_holder());
+
+ Method* save_resolved_method = resolved_method();
// Initialize klass (this should only happen if everything is ok)
if (initialize_class && resolved_klass->should_be_initialized()) {
resolved_klass->initialize(CHECK);
- linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
+ // Use updated LinkInfo (to reresolve with resolved_klass as method_holder?)
+ LinkInfo new_info(resolved_klass, link_info.name(), link_info.signature(),
+ link_info.current_klass(), link_info.check_access());
+ resolved_method = linktime_resolve_static_method(new_info, CHECK);
}
+ assert(save_resolved_method == resolved_method(), "does this change?");
// setup result
result.set_static(resolved_klass, resolved_method, CHECK);
}
// throws linktime exceptions
-void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature,
- KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_info, TRAPS) {
+ KlassHandle resolved_klass = link_info.resolved_klass();
+ methodHandle resolved_method;
if (!resolved_klass->is_interface()) {
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+ resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL);
} else {
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+ resolved_method = resolve_interface_method(link_info, /*nostatics*/false, CHECK_NULL);
}
assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier");
@@ -909,22 +942,25 @@ void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method,
jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass(),
resolved_method->name(),
resolved_method->signature()));
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
+ return resolved_method;
}
-void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, Symbol* method_name,
- Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
- methodHandle resolved_method;
- linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
- runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK);
+void LinkResolver::resolve_special_call(CallInfo& result,
+ const LinkInfo& link_info,
+ TRAPS) {
+ methodHandle resolved_method = linktime_resolve_special_method(link_info, CHECK);
+ runtime_resolve_special_method(result, resolved_method,
+ link_info.resolved_klass(),
+ link_info.current_klass(),
+ link_info.check_access(), CHECK);
}
// throws linktime exceptions
-void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature,
- KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_info,
+ TRAPS) {
// Invokespecial is called for multiple special reasons:
//
@@ -932,11 +968,13 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
// superclass.method, which can also resolve to a default method
// and the selected method is recalculated relative to the direct superclass
// superinterface.method, which explicitly does not check shadowing
+ KlassHandle resolved_klass = link_info.resolved_klass();
+ methodHandle resolved_method;
if (!resolved_klass->is_interface()) {
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+ resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL);
} else {
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
+ resolved_method = resolve_interface_method(link_info, /*nostatics*/true, CHECK_NULL);
}
// check if method name is , that it is found in same klass as static type
@@ -951,10 +989,11 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
resolved_method->name()->as_C_string(),
resolved_method->signature()->as_C_string()
);
- return;
+ return NULL;
}
// check if invokespecial's interface method reference is in an indirect superinterface
+ KlassHandle current_klass = link_info.current_klass();
if (!current_klass.is_null() && resolved_klass->is_interface()) {
Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ?
current_klass() :
@@ -973,7 +1012,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
resolved_method->name(),
resolved_method->signature()),
current_klass->external_name());
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
}
@@ -984,35 +1023,26 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
jio_snprintf(buf, sizeof(buf),
"Expecting non-static method %s",
Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()));
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ resolved_method->name(),
+ resolved_method->signature()));
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (TraceItables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
- (current_klass.is_null() ? "" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()),
- resolved_method->method_holder()->internal_name()
- );
- resolved_method->access_flags().print_on(tty);
- if (resolved_method->is_default_method()) {
- tty->print("default ");
- }
- if (resolved_method->is_overpass()) {
- tty->print("overpass");
- }
+ trace_method_resolution("invokespecial resolved method: caller-class:",
+ current_klass, resolved_klass, resolved_method);
tty->cr();
}
+
+ return resolved_method;
}
// throws runtime exceptions
-void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
- KlassHandle current_klass, bool check_access, TRAPS) {
+void LinkResolver::runtime_resolve_special_method(CallInfo& result,
+ const methodHandle& resolved_method,
+ KlassHandle resolved_klass,
+ KlassHandle current_klass,
+ bool check_access, TRAPS) {
// resolved method is selected method unless we have an old-style lookup
// for a superclass method
@@ -1037,7 +1067,7 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
resolved_method->name() != vmSymbols::object_initializer_name()) {
// Lookup super method
KlassHandle super_klass(THREAD, current_klass->super());
- lookup_instance_method_in_klasses(sel_method, super_klass,
+ sel_method = lookup_instance_method_in_klasses(super_klass,
resolved_method->name(),
resolved_method->signature(), CHECK);
// check if found
@@ -1066,26 +1096,13 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
Method::name_and_sig_as_C_string(resolved_klass(),
- sel_method->name(),
- sel_method->signature()));
+ sel_method->name(),
+ sel_method->signature()));
}
if (TraceItables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
- (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- sel_method->name(),
- sel_method->signature()),
- sel_method->method_holder()->internal_name()
- );
- sel_method->access_flags().print_on(tty);
- if (sel_method->is_default_method()) {
- tty->print("default ");
- }
- if (sel_method->is_overpass()) {
- tty->print("overpass");
- }
+ trace_method_resolution("invokespecial selected method: resolved-class:",
+ resolved_klass, resolved_klass, sel_method);
tty->cr();
}
@@ -1093,25 +1110,29 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
result.set_static(resolved_klass, sel_method, CHECK);
}
-void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
- bool check_access, bool check_null_and_abstract, TRAPS) {
- methodHandle resolved_method;
- linktime_resolve_virtual_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
- runtime_resolve_virtual_method(result, resolved_method, resolved_klass, recv, receiver_klass, check_null_and_abstract, CHECK);
+void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass,
+ const LinkInfo& link_info,
+ bool check_null_and_abstract, TRAPS) {
+ methodHandle resolved_method = linktime_resolve_virtual_method(link_info, CHECK);
+ runtime_resolve_virtual_method(result, resolved_method,
+ link_info.resolved_klass(),
+ recv, receiver_klass,
+ check_null_and_abstract, CHECK);
}
// throws linktime exceptions
-void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature,
- KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_info,
+ TRAPS) {
// normal method resolution
- resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
+ methodHandle resolved_method = resolve_method(link_info, /*require_methodref*/true, CHECK_NULL);
assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
// check if private interface method
+ KlassHandle resolved_klass = link_info.resolved_klass();
+ KlassHandle current_klass = link_info.current_klass();
+
if (resolved_klass->is_interface() && resolved_method->is_private()) {
ResourceMark rm(THREAD);
char buf[200];
@@ -1120,7 +1141,7 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method
resolved_method->name(),
resolved_method->signature()),
(current_klass.is_null() ? "" : current_klass->internal_name()));
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
// check if not static
@@ -1130,33 +1151,21 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method
jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(),
resolved_method->name(),
resolved_method->signature()));
- THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (PrintVtables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
- (current_klass.is_null() ? "" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()),
- resolved_method->method_holder()->internal_name()
- );
- resolved_method->access_flags().print_on(tty);
- if (resolved_method->is_default_method()) {
- tty->print("default ");
- }
- if (resolved_method->is_overpass()) {
- tty->print("overpass");
- }
+ trace_method_resolution("invokevirtual resolved method: caller-class:",
+ current_klass, resolved_klass, resolved_method);
tty->cr();
}
+
+ return resolved_method;
}
// throws runtime exceptions
void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
- methodHandle resolved_method,
+ const methodHandle& resolved_method,
KlassHandle resolved_klass,
Handle recv,
KlassHandle recv_klass,
@@ -1227,50 +1236,40 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
}
if (PrintVtables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokevirtual selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: ",
- (recv_klass.is_null() ? "" : recv_klass->internal_name()),
- (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()),
- selected_method->method_holder()->internal_name(),
- vtable_index
- );
- selected_method->access_flags().print_on(tty);
- if (selected_method->is_default_method()) {
- tty->print("default ");
- }
- if (selected_method->is_overpass()) {
- tty->print("overpass");
- }
- tty->cr();
+ trace_method_resolution("invokevirtual selected method: receiver-class:",
+ recv_klass, resolved_klass, selected_method);
+ tty->print_cr("vtable_index:%d", vtable_index);
}
// setup result
result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
}
-void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
- bool check_access, bool check_null_and_abstract, TRAPS) {
- methodHandle resolved_method;
- linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
- runtime_resolve_interface_method(result, resolved_method, resolved_klass, recv, recv_klass, check_null_and_abstract, CHECK);
+void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass,
+ const LinkInfo& link_info,
+ bool check_null_and_abstract, TRAPS) {
+ // throws linktime exceptions
+ methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK);
+ runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(),
+ recv, recv_klass, check_null_and_abstract, CHECK);
}
-// throws linktime exceptions
-void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name,
- Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_interface_method(const LinkInfo& link_info,
+ TRAPS) {
// normal interface method resolution
- resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
-
+ methodHandle resolved_method = resolve_interface_method(link_info, true, CHECK_NULL);
assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
+
+ return resolved_method;
}
// throws runtime exceptions
-void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
- Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) {
+void LinkResolver::runtime_resolve_interface_method(CallInfo& result,
+ const methodHandle& resolved_method,
+ KlassHandle resolved_klass,
+ Handle recv,
+ KlassHandle recv_klass,
+ bool check_null_and_abstract, TRAPS) {
// check if receiver exists
if (check_null_and_abstract && recv.is_null()) {
THROW(vmSymbols::java_lang_NullPointerException());
@@ -1298,12 +1297,11 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
}
// do lookup based on receiver klass
- methodHandle sel_method;
// This search must match the linktime preparation search for itable initialization
// to correctly enforce loader constraints for interface method inheritance
- lookup_instance_method_in_klasses(sel_method, recv_klass,
- resolved_method->name(),
- resolved_method->signature(), CHECK);
+ methodHandle sel_method = lookup_instance_method_in_klasses(recv_klass,
+ resolved_method->name(),
+ resolved_method->signature(), CHECK);
if (sel_method.is_null() && !check_null_and_abstract) {
// In theory this is a harmless placeholder value, but
// in practice leaving in null affects the nsk default method tests.
@@ -1314,9 +1312,9 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
if (sel_method.is_null()) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
- Method::name_and_sig_as_C_string(recv_klass(),
- resolved_method->name(),
- resolved_method->signature()));
+ Method::name_and_sig_as_C_string(recv_klass(),
+ resolved_method->name(),
+ resolved_method->signature()));
}
// check access
// Throw Illegal Access Error if sel_method is not public.
@@ -1337,22 +1335,8 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
}
if (TraceItables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
- (recv_klass.is_null() ? "" : recv_klass->internal_name()),
- (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()),
- sel_method->method_holder()->internal_name()
- );
- sel_method->access_flags().print_on(tty);
- if (sel_method->is_default_method()) {
- tty->print("default ");
- }
- if (sel_method->is_overpass()) {
- tty->print("overpass");
- }
+ trace_method_resolution("invokeinterface selected method: receiver-class",
+ recv_klass, resolved_klass, sel_method);
tty->cr();
}
// setup result
@@ -1368,14 +1352,9 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
- KlassHandle resolved_klass,
- Symbol* method_name,
- Symbol* method_signature,
- KlassHandle current_klass,
- bool check_access) {
+ const LinkInfo& link_info) {
EXCEPTION_MARK;
- methodHandle method_result;
- linktime_resolve_interface_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD);
+ methodHandle method_result = linktime_resolve_interface_method(link_info, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return methodHandle();
@@ -1385,14 +1364,9 @@ methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
}
methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
- KlassHandle resolved_klass,
- Symbol* method_name,
- Symbol* method_signature,
- KlassHandle current_klass,
- bool check_access) {
+ const LinkInfo& link_info) {
EXCEPTION_MARK;
- methodHandle method_result;
- linktime_resolve_virtual_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD);
+ methodHandle method_result = linktime_resolve_virtual_method(link_info, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return methodHandle();
@@ -1403,14 +1377,10 @@ methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
methodHandle LinkResolver::resolve_virtual_call_or_null(
KlassHandle receiver_klass,
- KlassHandle resolved_klass,
- Symbol* name,
- Symbol* signature,
- KlassHandle current_klass,
- bool check_access) {
+ const LinkInfo& link_info) {
EXCEPTION_MARK;
CallInfo info;
- resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD);
+ resolve_virtual_call(info, Handle(), receiver_klass, link_info, false, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return methodHandle();
@@ -1420,14 +1390,10 @@ methodHandle LinkResolver::resolve_virtual_call_or_null(
methodHandle LinkResolver::resolve_interface_call_or_null(
KlassHandle receiver_klass,
- KlassHandle resolved_klass,
- Symbol* name,
- Symbol* signature,
- KlassHandle current_klass,
- bool check_access) {
+ const LinkInfo& link_info) {
EXCEPTION_MARK;
CallInfo info;
- resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD);
+ resolve_interface_call(info, Handle(), receiver_klass, link_info, false, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return methodHandle();
@@ -1435,15 +1401,12 @@ methodHandle LinkResolver::resolve_interface_call_or_null(
return info.selected_method();
}
-int LinkResolver::resolve_virtual_vtable_index(
- KlassHandle receiver_klass,
- KlassHandle resolved_klass,
- Symbol* name,
- Symbol* signature,
- KlassHandle current_klass) {
+int LinkResolver::resolve_virtual_vtable_index(KlassHandle receiver_klass,
+ const LinkInfo& link_info) {
EXCEPTION_MARK;
CallInfo info;
- resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD);
+ resolve_virtual_call(info, Handle(), receiver_klass, link_info,
+ /*check_null_or_abstract*/false, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return Method::invalid_vtable_index;
@@ -1451,15 +1414,10 @@ int LinkResolver::resolve_virtual_vtable_index(
return info.vtable_index();
}
-methodHandle LinkResolver::resolve_static_call_or_null(
- KlassHandle resolved_klass,
- Symbol* name,
- Symbol* signature,
- KlassHandle current_klass,
- bool check_access) {
+methodHandle LinkResolver::resolve_static_call_or_null(const LinkInfo& link_info) {
EXCEPTION_MARK;
CallInfo info;
- resolve_static_call(info, resolved_klass, name, signature, current_klass, check_access, false, THREAD);
+ resolve_static_call(info, link_info, /*initialize_class*/false, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return methodHandle();
@@ -1467,15 +1425,10 @@ methodHandle LinkResolver::resolve_static_call_or_null(
return info.selected_method();
}
-methodHandle LinkResolver::resolve_special_call_or_null(
- KlassHandle resolved_klass,
- Symbol* name,
- Symbol* signature,
- KlassHandle current_klass,
- bool check_access) {
+methodHandle LinkResolver::resolve_special_call_or_null(const LinkInfo& link_info) {
EXCEPTION_MARK;
CallInfo info;
- resolve_special_call(info, resolved_klass, name, signature, current_klass, check_access, THREAD);
+ resolve_special_call(info, link_info, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return methodHandle();
@@ -1500,35 +1453,15 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHan
return;
}
-void LinkResolver::resolve_pool(KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature,
- KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS) {
- // resolve klass
- resolve_klass(resolved_klass, pool, index, CHECK);
-
- // Get name, signature, and static klass
- method_name = pool->name_ref_at(index);
- method_signature = pool->signature_ref_at(index);
- current_klass = KlassHandle(THREAD, pool->pool_holder());
-}
-
-
void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
- KlassHandle resolved_klass;
- Symbol* method_name = NULL;
- Symbol* method_signature = NULL;
- KlassHandle current_klass;
- resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
- resolve_static_call(result, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+ LinkInfo link_info(pool, index, CHECK);
+ resolve_static_call(result, link_info, /*initialize_class*/true, CHECK);
}
void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
- KlassHandle resolved_klass;
- Symbol* method_name = NULL;
- Symbol* method_signature = NULL;
- KlassHandle current_klass;
- resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
- resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
+ LinkInfo link_info(pool, index, CHECK);
+ resolve_special_call(result, link_info, CHECK);
}
@@ -1536,54 +1469,40 @@ void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv,
constantPoolHandle pool, int index,
TRAPS) {
- KlassHandle resolved_klass;
- Symbol* method_name = NULL;
- Symbol* method_signature = NULL;
- KlassHandle current_klass;
- resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
+ LinkInfo link_info(pool, index, CHECK);
KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass());
- resolve_virtual_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+ resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK);
}
void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) {
- KlassHandle resolved_klass;
- Symbol* method_name = NULL;
- Symbol* method_signature = NULL;
- KlassHandle current_klass;
- resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
+ LinkInfo link_info(pool, index, CHECK);
KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass());
- resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+ resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK);
}
void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
// This guy is reached from InterpreterRuntime::resolve_invokehandle.
- KlassHandle resolved_klass;
- Symbol* method_name = NULL;
- Symbol* method_signature = NULL;
- KlassHandle current_klass;
- resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
+ LinkInfo link_info(pool, index, CHECK);
if (TraceMethodHandles) {
ResourceMark rm(THREAD);
- tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string());
+ tty->print_cr("resolve_invokehandle %s %s", link_info.name()->as_C_string(),
+ link_info.signature()->as_C_string());
}
- resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
+ resolve_handle_call(result, link_info, CHECK);
}
-void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_klass,
- Symbol* method_name, Symbol* method_signature,
- KlassHandle current_klass,
+void LinkResolver::resolve_handle_call(CallInfo& result,
+ const LinkInfo& link_info,
TRAPS) {
// JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar
- assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), "");
- assert(MethodHandles::is_signature_polymorphic_name(method_name), "");
- methodHandle resolved_method;
+ assert(link_info.resolved_klass()() == SystemDictionary::MethodHandle_klass(), "");
+ assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), "");
Handle resolved_appendix;
Handle resolved_method_type;
- lookup_polymorphic_method(resolved_method, resolved_klass,
- method_name, method_signature,
- current_klass, &resolved_appendix, &resolved_method_type, CHECK);
+ methodHandle resolved_method = lookup_polymorphic_method(link_info,
+ &resolved_appendix, &resolved_method_type, CHECK);
result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
}
@@ -1609,7 +1528,6 @@ static void wrap_invokedynamic_exception(TRAPS) {
}
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
- //resolve_pool(, method_name, method_signature, current_klass, pool, index, CHECK);
Symbol* method_name = pool->name_ref_at(index);
Symbol* method_signature = pool->signature_ref_at(index);
KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
@@ -1667,19 +1585,27 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result,
wrap_invokedynamic_exception(CHECK);
}
-//------------------------------------------------------------------------------------------------------------------------
#ifndef PRODUCT
-
-void CallInfo::print() {
+void LinkResolver::trace_method_resolution(const char* prefix,
+ KlassHandle klass,
+ KlassHandle resolved_klass,
+ const methodHandle& method) {
ResourceMark rm;
- const char* kindstr = "unknown";
- switch (_call_kind) {
- case direct_call: kindstr = "direct"; break;
- case vtable_call: kindstr = "vtable"; break;
- case itable_call: kindstr = "itable"; break;
+ tty->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
+ prefix,
+ (klass.is_null() ? "" : klass->internal_name()),
+ (resolved_klass.is_null() ? "" : resolved_klass->internal_name()),
+ Method::name_and_sig_as_C_string(resolved_klass(),
+ method->name(),
+ method->signature()),
+ method->method_holder()->internal_name()
+ );
+ method->access_flags().print_on(tty);
+ if (method->is_default_method()) {
+ tty->print("default ");
+ }
+ if (method->is_overpass()) {
+ tty->print("overpass ");
}
- tty->print_cr("Call %s@%d %s", kindstr, _call_index,
- _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string());
}
-
-#endif
+#endif // PRODUCT
diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp
index 5fa536491c9..d3fda4368ef 100644
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -36,7 +36,7 @@
// that method. If the info is invalid, the link has not been resolved
// successfully.
-class CallInfo VALUE_OBJ_CLASS_SPEC {
+class CallInfo : public StackObj {
public:
// Ways that a method call might be selected (or not) based on receiver type.
// Note that an invokevirtual instruction might be linked with no_dispatch,
@@ -58,11 +58,22 @@ class CallInfo VALUE_OBJ_CLASS_SPEC {
Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix)
Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites)
- void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS);
- void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index , TRAPS);
- void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS);
- void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS);
- void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS);
+ void set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS);
+ void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass,
+ const methodHandle& resolved_method,
+ const methodHandle& selected_method,
+ int itable_index, TRAPS);
+ void set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass,
+ const methodHandle& resolved_method,
+ const methodHandle& selected_method,
+ int vtable_index, TRAPS);
+ void set_handle(const methodHandle& resolved_method,
+ Handle resolved_appendix, Handle resolved_method_type, TRAPS);
+ void set_common(KlassHandle resolved_klass, KlassHandle selected_klass,
+ const methodHandle& resolved_method,
+ const methodHandle& selected_method,
+ CallKind kind,
+ int index, TRAPS);
friend class LinkResolver;
@@ -113,6 +124,37 @@ class CallInfo VALUE_OBJ_CLASS_SPEC {
void print() PRODUCT_RETURN;
};
+
+// Condensed information from constant pool to use to resolve the method or field.
+// resolved_klass = specified class (i.e., static receiver class)
+// current_klass = sending method holder (i.e., class containing the method
+// containing the call being resolved)
+class LinkInfo : public StackObj {
+ Symbol* _name; // extracted from JVM_CONSTANT_NameAndType
+ Symbol* _signature;
+ KlassHandle _resolved_klass; // class that the constant pool entry points to
+ KlassHandle _current_klass; // class that owns the constant pool
+ bool _check_access;
+ public:
+ LinkInfo(constantPoolHandle pool, int index, TRAPS);
+ // Condensed information from other call sites within the vm.
+ LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
+ KlassHandle current_klass, bool check_access = true) :
+ _resolved_klass(resolved_klass),
+ _name(name), _signature(signature), _current_klass(current_klass),
+ _check_access(check_access) {}
+
+ // accessors
+ Symbol* name() const { return _name; }
+ Symbol* signature() const { return _signature; }
+ KlassHandle resolved_klass() const { return _resolved_klass; }
+ KlassHandle current_klass() const { return _current_klass; }
+ bool check_access() const { return _check_access; }
+ char* method_string() const;
+
+ void print() PRODUCT_RETURN;
+};
+
// Link information for getfield/putfield & getstatic/putstatic bytecodes
// is represented using a fieldDescriptor.
@@ -124,85 +166,136 @@ class LinkResolver: AllStatic {
friend class klassItable;
private:
- static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS);
- static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
- static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
- static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
- KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
- static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS);
+ static methodHandle lookup_method_in_klasses(const LinkInfo& link_info,
+ bool checkpolymorphism,
+ bool in_imethod_resolve, TRAPS);
+ static methodHandle lookup_method_in_interfaces(const LinkInfo& link_info, TRAPS);
+ static methodHandle lookup_polymorphic_method(const LinkInfo& link_info,
+ Handle *appendix_result_or_null,
+ Handle *method_type_result, TRAPS);
+ // Not Linktime so doesn't take LinkInfo
+ static methodHandle lookup_instance_method_in_klasses (
+ KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
- static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
+ // Similar loader constraint checking functions that throw
+ // LinkageError with descriptive message.
+ static void check_method_loader_constraints(const LinkInfo& link_info,
+ const methodHandle& resolved_method,
+ const char* method_type, TRAPS);
+ static void check_field_loader_constraints(Symbol* field, Symbol* sig,
+ KlassHandle current_klass,
+ KlassHandle sel_klass, TRAPS);
- static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool nostatics, TRAPS);
- static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool require_methodref, TRAPS);
+ static methodHandle resolve_interface_method(const LinkInfo& link_info, bool nostatics, TRAPS);
+ static methodHandle resolve_method (const LinkInfo& link_info, bool require_methodref, TRAPS);
- static void linktime_resolve_static_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
- static void linktime_resolve_special_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
- static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
- static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+ static methodHandle linktime_resolve_static_method (const LinkInfo& link_info, TRAPS);
+ static methodHandle linktime_resolve_special_method (const LinkInfo& link_info, TRAPS);
+ static methodHandle linktime_resolve_virtual_method (const LinkInfo& link_info, TRAPS);
+ static methodHandle linktime_resolve_interface_method (const LinkInfo& link_info, TRAPS);
- static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS);
- static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
- static void runtime_resolve_interface_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
+ static void runtime_resolve_special_method (CallInfo& result,
+ const methodHandle& resolved_method,
+ KlassHandle resolved_klass,
+ KlassHandle current_klass,
+ bool check_access, TRAPS);
+ static void runtime_resolve_virtual_method (CallInfo& result,
+ const methodHandle& resolved_method,
+ KlassHandle resolved_klass,
+ Handle recv,
+ KlassHandle recv_klass,
+ bool check_null_and_abstract, TRAPS);
+ static void runtime_resolve_interface_method (CallInfo& result,
+ const methodHandle& resolved_method,
+ KlassHandle resolved_klass,
+ Handle recv,
+ KlassHandle recv_klass,
+ bool check_null_and_abstract, TRAPS);
- static void check_field_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, fieldDescriptor& fd, TRAPS);
- static void check_method_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, methodHandle sel_method, TRAPS);
+ static void check_field_accessability(KlassHandle ref_klass,
+ KlassHandle resolved_klass,
+ KlassHandle sel_klass,
+ const fieldDescriptor& fd, TRAPS);
+ static void check_method_accessability(KlassHandle ref_klass,
+ KlassHandle resolved_klass,
+ KlassHandle sel_klass,
+ const methodHandle& sel_method, TRAPS);
+ // runtime resolving from constant pool
+ static void resolve_invokestatic (CallInfo& result,
+ constantPoolHandle pool, int index, TRAPS);
+ static void resolve_invokespecial (CallInfo& result,
+ constantPoolHandle pool, int index, TRAPS);
+ static void resolve_invokevirtual (CallInfo& result, Handle recv,
+ constantPoolHandle pool, int index, TRAPS);
+ static void resolve_invokeinterface(CallInfo& result, Handle recv,
+ constantPoolHandle pool, int index, TRAPS);
+ static void resolve_invokedynamic (CallInfo& result,
+ constantPoolHandle pool, int index, TRAPS);
+ static void resolve_invokehandle (CallInfo& result,
+ constantPoolHandle pool, int index, TRAPS);
public:
// constant pool resolving
static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS);
- // static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target
- static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result,
- Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS);
+ // static resolving calls (will not run any Java code);
+ // used only from Bytecode_invoke::static_target
+ static methodHandle resolve_method_statically(Bytecodes::Code code,
+ constantPoolHandle pool,
+ int index, TRAPS);
- // runtime/static resolving for fields
- static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
- static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature,
- KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS);
+ static void resolve_field_access(fieldDescriptor& result,
+ constantPoolHandle pool,
+ int index, Bytecodes::Code byte, TRAPS);
+ static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info,
+ Bytecodes::Code access_kind,
+ bool initialize_class, TRAPS);
- // source of access_kind codes:
- static Bytecodes::Code field_access_kind(bool is_static, bool is_put) {
- return (is_static
- ? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic)
- : (is_put ? Bytecodes::_putfield : Bytecodes::_getfield ));
- }
+ static void resolve_static_call (CallInfo& result,
+ const LinkInfo& link_info,
+ bool initialize_klass, TRAPS);
+ static void resolve_special_call (CallInfo& result,
+ const LinkInfo& link_info,
+ TRAPS);
+ static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass,
+ const LinkInfo& link_info,
+ bool check_null_and_abstract, TRAPS);
+ static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass,
+ const LinkInfo& link_info,
+ bool check_null_and_abstract, TRAPS);
+ static void resolve_handle_call (CallInfo& result,
+ const LinkInfo& link_info, TRAPS);
+ static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier,
+ Symbol* method_name, Symbol* method_signature,
+ KlassHandle current_klass, TRAPS);
- // runtime resolving:
- // resolved_klass = specified class (i.e., static receiver class)
- // current_klass = sending method holder (i.e., class containing the method containing the call being resolved)
- static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
- static void resolve_special_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
- static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
- static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
- static void resolve_handle_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
- static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
+ // same as above for compile-time resolution; but returns null handle instead of throwing
+ // an exception on error also, does not initialize klass (i.e., no side effects)
+ static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass,
+ const LinkInfo& link_info);
+ static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass,
+ const LinkInfo& link_info);
+ static methodHandle resolve_static_call_or_null (const LinkInfo& link_info);
+ static methodHandle resolve_special_call_or_null (const LinkInfo& link_info);
- // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
- // also, does not initialize klass (i.e., no side effects)
- static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
- static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
- static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
- static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
- static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method);
+ static int vtable_index_of_interface_method(KlassHandle klass, const methodHandle& resolved_method);
// same as above for compile-time resolution; returns vtable_index if current_klass if linked
- static int resolve_virtual_vtable_index (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
+ static int resolve_virtual_vtable_index (KlassHandle receiver_klass,
+ const LinkInfo& link_info);
// static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful)
- static methodHandle linktime_resolve_virtual_method_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
- static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
+ static methodHandle linktime_resolve_virtual_method_or_null (const LinkInfo& link_info);
+ static methodHandle linktime_resolve_interface_method_or_null(const LinkInfo& link_info);
// runtime resolving from constant pool
- static void resolve_invokestatic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokehandle (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
-
- static void resolve_invoke (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
+ static void resolve_invoke(CallInfo& result, Handle recv,
+ constantPoolHandle pool, int index,
+ Bytecodes::Code byte, TRAPS);
+ private:
+ static void trace_method_resolution(const char* prefix, KlassHandle klass,
+ KlassHandle resolved_klass,
+ const methodHandle& method) PRODUCT_RETURN;
};
-
#endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP
diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp
index fd48fe11021..187be2ca38f 100644
--- a/hotspot/src/share/vm/memory/metaspace.cpp
+++ b/hotspot/src/share/vm/memory/metaspace.cpp
@@ -614,8 +614,7 @@ class SpaceManager : public CHeapObj {
Metachunk* _chunks_in_use[NumberOfInUseLists];
Metachunk* _current_chunk;
- // Number of small chunks to allocate to a manager
- // If class space manager, small chunks are unlimited
+ // Maximum number of small chunks to allocate to a SpaceManager
static uint const _small_chunk_limit;
// Sum of all space in allocated chunks
@@ -730,6 +729,8 @@ class SpaceManager : public CHeapObj {
// Block allocation and deallocation.
// Allocates a block from the current chunk
MetaWord* allocate(size_t word_size);
+ // Allocates a block from a small chunk
+ MetaWord* get_small_chunk_and_allocate(size_t word_size);
// Helper for allocations
MetaWord* allocate_work(size_t word_size);
@@ -2011,9 +2012,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to
- // _small_chunk_limit small chunks can be allocated but
- // once a medium chunk has been allocated, no more small
- // chunks will be allocated.
+ // _small_chunk_limit small chunks can be allocated.
+ // After that a medium chunk is preferred.
size_t chunk_word_size;
if (chunks_in_use(MediumIndex) == NULL &&
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
@@ -2081,7 +2081,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
word_size, words_used, words_left);
}
- // Get another chunk out of the virtual space
+ // Get another chunk
size_t grow_chunks_by_words = calc_chunk_size(word_size);
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
@@ -2412,6 +2412,43 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size,
return next;
}
+/*
+ * The policy is to allocate up to _small_chunk_limit small chunks
+ * after which only medium chunks are allocated. This is done to
+ * reduce fragmentation. In some cases, this can result in a lot
+ * of small chunks being allocated to the point where it's not
+ * possible to expand. If this happens, there may be no medium chunks
+ * available and OOME would be thrown. Instead of doing that,
+ * if the allocation request size fits in a small chunk, an attempt
+ * will be made to allocate a small chunk.
+ */
+MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
+ if (word_size + Metachunk::overhead() > small_chunk_size()) {
+ return NULL;
+ }
+
+ MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
+ MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
+
+ Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
+
+ MetaWord* mem = NULL;
+
+ if (chunk != NULL) {
+ // Add chunk to the in-use chunk list and do an allocation from it.
+ // Add to this manager's list of chunks in use.
+ add_chunk(chunk, false);
+ mem = chunk->allocate(word_size);
+
+ inc_used_metrics(word_size);
+
+ // Track metaspace memory usage statistic.
+ track_metaspace_memory_usage();
+ }
+
+ return mem;
+}
+
MetaWord* SpaceManager::allocate(size_t word_size) {
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
@@ -3560,7 +3597,18 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
}
if (result == NULL) {
- report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
+ SpaceManager* sm;
+ if (is_class_space_allocation(mdtype)) {
+ sm = loader_data->metaspace_non_null()->class_vsm();
+ } else {
+ sm = loader_data->metaspace_non_null()->vsm();
+ }
+
+ result = sm->get_small_chunk_and_allocate(word_size);
+
+ if (result == NULL) {
+ report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
+ }
}
// Zero initialize.
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index a3d6408bb15..f3eafba456c 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -622,14 +622,6 @@ bool InstanceKlass::link_class_impl(
if (!this_k->is_linked()) {
if (!this_k->is_rewritten()) {
{
- // Timer includes any side effects of class verification (resolution,
- // etc), but not recursive entry into verify_code().
- PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
- ClassLoader::perf_class_verify_selftime(),
- ClassLoader::perf_classes_verified(),
- jt->get_thread_stat()->perf_recursion_counts_addr(),
- jt->get_thread_stat()->perf_timers_addr(),
- PerfClassTraceTime::CLASS_VERIFY);
bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
if (!verify_ok) {
return false;
@@ -1830,11 +1822,10 @@ int nmethodBucket::decrement() {
// are dependent on the changes that were passed in and mark them for
// deoptimization. Returns the number of nmethods found.
//
-int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
+int nmethodBucket::mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes) {
assert_locked_or_safepoint(CodeCache_lock);
int found = 0;
- nmethodBucket* b = _dependencies;
- while (b != NULL) {
+ for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
nmethod* nm = b->get_nmethod();
// since dependencies aren't removed until an nmethod becomes a zombie,
// the dependency list may contain nmethods which aren't alive.
@@ -1842,7 +1833,6 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
if (TraceDependencies) {
ResourceMark rm;
tty->print_cr("Marked for deoptimization");
- tty->print_cr(" context = %s", this->external_name());
changes.print();
nm->print();
nm->print_dependencies();
@@ -1850,36 +1840,119 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
nm->mark_for_deoptimization();
found++;
}
- b = b->next();
}
return found;
}
+//
+// Add an nmethodBucket to the list of dependencies for this nmethod.
+// It's possible that an nmethod has multiple dependencies on this klass
+// so a count is kept for each bucket to guarantee that creation and
+// deletion of dependencies is consistent. Returns new head of the list.
+//
+nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+ if (nm == b->get_nmethod()) {
+ b->increment();
+ return deps;
+ }
+ }
+ return new nmethodBucket(nm, deps);
+}
+
+//
+// Decrement count of the nmethod in the dependency list and remove
+// the bucket completely when the count goes to 0. This method must
+// find a corresponding bucket otherwise there's a bug in the
+// recording of dependencies. Returns true if the bucket is ready for reclamation.
+//
+bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+ if (nm == b->get_nmethod()) {
+ int val = b->decrement();
+ guarantee(val >= 0, err_msg("Underflow: %d", val));
+ return (val == 0);
+ }
+ }
+#ifdef ASSERT
+ tty->print_raw_cr("### can't find dependent nmethod");
+ nm->print();
+#endif // ASSERT
+ ShouldNotReachHere();
+ return false;
+}
+
+//
+// Reclaim all unused buckets. Returns new head of the list.
+//
+nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) {
+ nmethodBucket* first = deps;
+ nmethodBucket* last = NULL;
+ nmethodBucket* b = first;
+
+ while (b != NULL) {
+ assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
+ nmethodBucket* next = b->next();
+ if (b->count() == 0) {
+ if (last == NULL) {
+ first = next;
+ } else {
+ last->set_next(next);
+ }
+ delete b;
+ // last stays the same.
+ } else {
+ last = b;
+ }
+ b = next;
+ }
+ return first;
+}
+
+#ifndef PRODUCT
+void nmethodBucket::print_dependent_nmethods(nmethodBucket* deps, bool verbose) {
+ int idx = 0;
+ for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+ nmethod* nm = b->get_nmethod();
+ tty->print("[%d] count=%d { ", idx++, b->count());
+ if (!verbose) {
+ nm->print_on(tty, "nmethod");
+ tty->print_cr(" } ");
+ } else {
+ nm->print();
+ nm->print_dependencies();
+ tty->print_cr("--- } ");
+ }
+ }
+}
+
+bool nmethodBucket::is_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+ for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+ if (nm == b->get_nmethod()) {
+#ifdef ASSERT
+ int count = b->count();
+ assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
+#endif
+ return true;
+ }
+ }
+ return false;
+}
+#endif //PRODUCT
+
+int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ return nmethodBucket::mark_dependent_nmethods(_dependencies, changes);
+}
+
void InstanceKlass::clean_dependent_nmethods() {
assert_locked_or_safepoint(CodeCache_lock);
if (has_unloaded_dependent()) {
- nmethodBucket* b = _dependencies;
- nmethodBucket* last = NULL;
- while (b != NULL) {
- assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
-
- nmethodBucket* next = b->next();
-
- if (b->count() == 0) {
- if (last == NULL) {
- _dependencies = next;
- } else {
- last->set_next(next);
- }
- delete b;
- // last stays the same.
- } else {
- last = b;
- }
-
- b = next;
- }
+ _dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies);
set_has_unloaded_dependent(false);
}
#ifdef ASSERT
@@ -1893,90 +1966,26 @@ void InstanceKlass::clean_dependent_nmethods() {
#endif
}
-//
-// Add an nmethodBucket to the list of dependencies for this nmethod.
-// It's possible that an nmethod has multiple dependencies on this klass
-// so a count is kept for each bucket to guarantee that creation and
-// deletion of dependencies is consistent.
-//
void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
- nmethodBucket* b = _dependencies;
- nmethodBucket* last = NULL;
- while (b != NULL) {
- if (nm == b->get_nmethod()) {
- b->increment();
- return;
- }
- b = b->next();
- }
- _dependencies = new nmethodBucket(nm, _dependencies);
+ _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
}
-
-//
-// Decrement count of the nmethod in the dependency list and remove
-// the bucket competely when the count goes to 0. This method must
-// find a corresponding bucket otherwise there's a bug in the
-// recording of dependecies.
-//
void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
- nmethodBucket* b = _dependencies;
- nmethodBucket* last = NULL;
- while (b != NULL) {
- if (nm == b->get_nmethod()) {
- int val = b->decrement();
- guarantee(val >= 0, err_msg("Underflow: %d", val));
- if (val == 0) {
- set_has_unloaded_dependent(true);
- }
- return;
- }
- last = b;
- b = b->next();
- }
-#ifdef ASSERT
- tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
- nm->print();
-#endif // ASSERT
- ShouldNotReachHere();
-}
+ if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
+ set_has_unloaded_dependent(true);
+ }
+}
#ifndef PRODUCT
void InstanceKlass::print_dependent_nmethods(bool verbose) {
- nmethodBucket* b = _dependencies;
- int idx = 0;
- while (b != NULL) {
- nmethod* nm = b->get_nmethod();
- tty->print("[%d] count=%d { ", idx++, b->count());
- if (!verbose) {
- nm->print_on(tty, "nmethod");
- tty->print_cr(" } ");
- } else {
- nm->print();
- nm->print_dependencies();
- tty->print_cr("--- } ");
- }
- b = b->next();
- }
+ nmethodBucket::print_dependent_nmethods(_dependencies, verbose);
}
-
bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
- nmethodBucket* b = _dependencies;
- while (b != NULL) {
- if (nm == b->get_nmethod()) {
-#ifdef ASSERT
- int count = b->count();
- assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
-#endif
- return true;
- }
- b = b->next();
- }
- return false;
+ return nmethodBucket::is_dependent_nmethod(_dependencies, nm);
}
#endif //PRODUCT
diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp
index b9aaa75480e..141ec1139e6 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp
@@ -1290,6 +1290,15 @@ class nmethodBucket: public CHeapObj {
nmethodBucket* next() { return _next; }
void set_next(nmethodBucket* b) { _next = b; }
nmethod* get_nmethod() { return _nmethod; }
+
+ static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes);
+ static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+ static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+ static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps);
+#ifndef PRODUCT
+ static void print_dependent_nmethods(nmethodBucket* deps, bool verbose);
+ static bool is_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+#endif //PRODUCT
};
// An iterator that's used to access the inner classes indices in the
diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp
index aa16cb6dc21..54df450637b 100644
--- a/hotspot/src/share/vm/oops/klassVtable.cpp
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp
@@ -1136,7 +1136,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
if (m->has_itable_index()) {
// This search must match the runtime resolution, i.e. selection search for invokeinterface
// to correctly enforce loader constraints for interface method inheritance
- LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK);
+ target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), CHECK);
}
if (target == NULL || !target->is_public() || target->is_abstract()) {
// Entry does not resolve. Leave it empty for AbstractMethodError.
diff --git a/hotspot/src/share/vm/opto/arraycopynode.cpp b/hotspot/src/share/vm/opto/arraycopynode.cpp
index a9e673cff58..64233d49722 100644
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp
@@ -599,10 +599,14 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
- const TypeOopPtr* dest_t = phase->type(in(ArrayCopyNode::Dest))->is_oopptr();
+ Node* dest = in(ArrayCopyNode::Dest);
+ if (dest->is_top()) {
+ return false;
+ }
+ const TypeOopPtr* dest_t = phase->type(dest)->is_oopptr();
assert(!dest_t->is_known_instance() || _dest_type->is_known_instance(), "result of EA not recorded");
- const TypeOopPtr* src_t = phase->type(in(ArrayCopyNode::Src))->is_oopptr();
- assert(!src_t->is_known_instance() || _src_type->is_known_instance(), "result of EA not recorded");
+ assert(in(ArrayCopyNode::Src)->is_top() || !phase->type(in(ArrayCopyNode::Src))->is_oopptr()->is_known_instance() ||
+ _src_type->is_known_instance(), "result of EA not recorded");
if (_dest_type != TypeOopPtr::BOTTOM || t_oop->is_known_instance()) {
assert(_dest_type == TypeOopPtr::BOTTOM || _dest_type->is_known_instance(), "result of EA is known instance");
diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp
index 36927498fff..7a4eeb0939a 100644
--- a/hotspot/src/share/vm/opto/callnode.cpp
+++ b/hotspot/src/share/vm/opto/callnode.cpp
@@ -1946,7 +1946,7 @@ bool CallLeafNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
}
}
}
- if (may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
+ if (!dest->is_top() && may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
return true;
}
return false;
diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp
index b52f90c4d34..e8ff735a150 100644
--- a/hotspot/src/share/vm/opto/graphKit.cpp
+++ b/hotspot/src/share/vm/opto/graphKit.cpp
@@ -1457,18 +1457,18 @@ void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) {
// factory methods in "int adr_idx"
Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
int adr_idx,
- MemNode::MemOrd mo, bool require_atomic_access) {
+ MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency, bool require_atomic_access) {
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
const TypePtr* adr_type = NULL; // debug-mode-only argument
debug_only(adr_type = C->get_adr_type(adr_idx));
Node* mem = memory(adr_idx);
Node* ld;
if (require_atomic_access && bt == T_LONG) {
- ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
+ ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
} else if (require_atomic_access && bt == T_DOUBLE) {
- ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
+ ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
} else {
- ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo);
+ ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency);
}
ld = _gvn.transform(ld);
if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp
index ce0178d6a5a..fbc34e1093e 100644
--- a/hotspot/src/share/vm/opto/graphKit.hpp
+++ b/hotspot/src/share/vm/opto/graphKit.hpp
@@ -512,21 +512,24 @@ class GraphKit : public Phase {
// adapted the `do_put_xxx' and `do_get_xxx' procedures for the case
// of volatile fields.
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
- MemNode::MemOrd mo, bool require_atomic_access = false) {
+ MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
+ bool require_atomic_access = false) {
// This version computes alias_index from bottom_type
return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(),
- mo, require_atomic_access);
+ mo, control_dependency, require_atomic_access);
}
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type,
- MemNode::MemOrd mo, bool require_atomic_access = false) {
+ MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
+ bool require_atomic_access = false) {
// This version computes alias_index from an address type
assert(adr_type != NULL, "use other make_load factory");
return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type),
- mo, require_atomic_access);
+ mo, control_dependency, require_atomic_access);
}
// This is the base version which is given an alias index.
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx,
- MemNode::MemOrd mo, bool require_atomic_access = false);
+ MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
+ bool require_atomic_access = false);
// Create & transform a StoreNode and store the effect into the
// parser's memory state.
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index 62ae310cc52..9d838252f3b 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -2631,7 +2631,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
if (!is_store) {
MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
- Node* p = make_load(control(), adr, value_type, type, adr_type, mo, is_volatile);
+ // To be valid, unsafe loads may depend on other conditions than
+ // the one that guards them: pin the Load node
+ Node* p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile);
// load value
switch (type) {
case T_BOOLEAN:
@@ -5488,7 +5490,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field
}
// Build the load.
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
- Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, is_vol);
+ Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, is_vol);
// If reference is volatile, prevent following memory ops from
// floating up past the volatile read. Also prevents commoning
// another volatile read.
diff --git a/hotspot/src/share/vm/opto/loopPredicate.cpp b/hotspot/src/share/vm/opto/loopPredicate.cpp
index d5157b79afb..7d25d965d91 100644
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp
@@ -437,7 +437,13 @@ class Invariance : public StackObj {
}
}
if (all_inputs_invariant) {
- _invariant.set(n->_idx); // I am a invariant too
+ // If n's control is a predicate that was moved out of the
+ // loop, it was marked invariant but n is only invariant if
+ // it depends only on that test. Otherwise, unless that test
+ // is out of the loop, it's not invariant.
+ if (n->is_CFG() || n->depends_only_on_test() || n->in(0) == NULL || !_phase->is_member(_lpt, n->in(0))) {
+ _invariant.set(n->_idx); // I am a invariant too
+ }
}
} else { // process next input
_stack.set_index(idx + 1);
diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp
index a73391a38a8..c9c033868fc 100644
--- a/hotspot/src/share/vm/opto/loopTransform.cpp
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp
@@ -1582,13 +1582,36 @@ void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) {
if (opc != ReductionNode::opcode(opc, def_node->bottom_type()->basic_type())) {
if (!def_node->is_reduction()) { // Not marked yet
// To be a reduction, the arithmetic node must have the phi as input and provide a def to it
+ bool ok = false;
for (unsigned j = 1; j < def_node->req(); j++) {
Node* in = def_node->in(j);
if (in == phi) {
- def_node->add_flag(Node::Flag_is_reduction);
+ ok = true;
break;
}
}
+
+ // do nothing if we did not match the initial criteria
+ if (ok == false) {
+ continue;
+ }
+
+ // The result of the reduction must not be used in the loop
+ for (DUIterator_Fast imax, i = def_node->fast_outs(imax); i < imax && ok; i++) {
+ Node* u = def_node->fast_out(i);
+ if (has_ctrl(u) && !loop->is_member(get_loop(get_ctrl(u)))) {
+ continue;
+ }
+ if (u == phi) {
+ continue;
+ }
+ ok = false;
+ }
+
+ // iff the uses conform
+ if (ok) {
+ def_node->add_flag(Node::Flag_is_reduction);
+ }
}
}
}
diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp
index ae221593d88..cee45df287e 100644
--- a/hotspot/src/share/vm/opto/loopopts.cpp
+++ b/hotspot/src/share/vm/opto/loopopts.cpp
@@ -718,7 +718,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) {
}
// Use same limit as split_if_with_blocks_post
- if( C->unique() > 35000 ) return n; // Method too big
+ if( C->live_nodes() > 35000 ) return n; // Method too big
// Split 'n' through the merge point if it is profitable
Node *phi = split_thru_phi( n, n_blk, policy );
@@ -802,7 +802,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
// Cloning Cmp through Phi's involves the split-if transform.
// FastLock is not used by an If
if( n->is_Cmp() && !n->is_FastLock() ) {
- if( C->unique() > 35000 ) return; // Method too big
+ if( C->live_nodes() > 35000 ) return; // Method too big
// Do not do 'split-if' if irreducible loops are present.
if( _has_irreducible_loops )
diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp
index d3dbc51c620..ee66e1aac4b 100644
--- a/hotspot/src/share/vm/opto/matcher.cpp
+++ b/hotspot/src/share/vm/opto/matcher.cpp
@@ -844,7 +844,7 @@ void Matcher::init_spill_mask( Node *ret ) {
MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
#endif
MachNode *spillI = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered));
- MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false));
+ MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false));
MachNode *spillF = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered));
MachNode *spillD = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered));
MachNode *spillP = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp
index c2a03c96b31..09438ea03f8 100644
--- a/hotspot/src/share/vm/opto/memnode.cpp
+++ b/hotspot/src/share/vm/opto/memnode.cpp
@@ -784,6 +784,9 @@ void LoadNode::dump_spec(outputStream *st) const {
// standard dump does this in Verbose and WizardMode
st->print(" #"); _type->dump_on(st);
}
+ if (!_depends_only_on_test) {
+ st->print(" (does not depend only on test)");
+ }
}
#endif
@@ -800,7 +803,7 @@ bool LoadNode::is_immutable_value(Node* adr) {
//----------------------------LoadNode::make-----------------------------------
// Polymorphic factory method:
-Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) {
+Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency) {
Compile* C = gvn.C;
// sanity check the alias category against the created node type
@@ -816,39 +819,39 @@ Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypeP
rt->isa_oopptr() || is_immutable_value(adr),
"raw memory operations should have control edge");
switch (bt) {
- case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
- case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
- case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo);
- case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
- case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
- case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo);
- case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo);
- case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo);
- case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo);
+ case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
+ case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
+ case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
+ case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
+ case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
+ case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency);
+ case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
+ case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
+ case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency);
case T_OBJECT:
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
- Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo));
+ Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency));
return new DecodeNNode(load, load->bottom_type()->make_ptr());
} else
#endif
{
assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
- return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo);
+ return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
}
}
ShouldNotReachHere();
return (LoadNode*)NULL;
}
-LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
+LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
bool require_atomic = true;
- return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic);
+ return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic);
}
-LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
+LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
bool require_atomic = true;
- return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic);
+ return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic);
}
diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp
index 814d6d410a6..8c389e16409 100644
--- a/hotspot/src/share/vm/opto/memnode.hpp
+++ b/hotspot/src/share/vm/opto/memnode.hpp
@@ -137,7 +137,33 @@ public:
//------------------------------LoadNode---------------------------------------
// Load value; requires Memory and Address
class LoadNode : public MemNode {
+public:
+ // Some loads (from unsafe) should be pinned: they don't depend only
+ // on the dominating test. The boolean field _depends_only_on_test
+ // below records whether that node depends only on the dominating
+ // test.
+ // Methods used to build LoadNodes pass an argument of type enum
+ // ControlDependency instead of a boolean because those methods
+ // typically have multiple boolean parameters with default values:
+ // passing the wrong boolean to one of these parameters by mistake
+ // goes easily unnoticed. Using an enum, the compiler can check that
+ // the type of a value and the type of the parameter match.
+ enum ControlDependency {
+ Pinned,
+ DependsOnlyOnTest
+ };
private:
+ // LoadNode::hash() doesn't take the _depends_only_on_test field
+ // into account: If the graph already has a non-pinned LoadNode and
+ // we add a pinned LoadNode with the same inputs, it's safe for GVN
+ // to replace the pinned LoadNode with the non-pinned LoadNode,
+ // otherwise it wouldn't be safe to have a non pinned LoadNode with
+ // those inputs in the first place. If the graph already has a
+ // pinned LoadNode and we add a non pinned LoadNode with the same
+ // inputs, it's safe (but suboptimal) for GVN to replace the
+ // non-pinned LoadNode by the pinned LoadNode.
+ bool _depends_only_on_test;
+
// On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish
// loads that can be reordered, and such requiring acquire semantics to
// adhere to the Java specification. The required behaviour is stored in
@@ -154,8 +180,8 @@ protected:
virtual Node* find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const;
public:
- LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo)
- : MemNode(c,mem,adr,at), _type(rt), _mo(mo) {
+ LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency)
+ : MemNode(c,mem,adr,at), _type(rt), _mo(mo), _depends_only_on_test(control_dependency == DependsOnlyOnTest) {
init_class_id(Class_Load);
}
inline bool is_unordered() const { return !is_acquire(); }
@@ -166,7 +192,8 @@ public:
// Polymorphic factory method:
static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
- const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo);
+ const TypePtr* at, const Type *rt, BasicType bt,
+ MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
virtual uint hash() const; // Check the type
@@ -234,16 +261,15 @@ protected:
// which produce results (new raw memory state) inside of loops preventing all
// manner of other optimizations). Basically, it's ugly but so is the alternative.
// See comment in macro.cpp, around line 125 expand_allocate_common().
- virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
-
+ virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM && _depends_only_on_test; }
};
//------------------------------LoadBNode--------------------------------------
// Load a byte (8bits signed) from memory
class LoadBNode : public LoadNode {
public:
- LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
- : LoadNode(c, mem, adr, at, ti, mo) {}
+ LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@@ -256,8 +282,8 @@ public:
// Load a unsigned byte (8bits unsigned) from memory
class LoadUBNode : public LoadNode {
public:
- LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo)
- : LoadNode(c, mem, adr, at, ti, mo) {}
+ LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
@@ -270,8 +296,8 @@ public:
// Load an unsigned short/char (16bits unsigned) from memory
class LoadUSNode : public LoadNode {
public:
- LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
- : LoadNode(c, mem, adr, at, ti, mo) {}
+ LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@@ -284,8 +310,8 @@ public:
// Load a short (16bits signed) from memory
class LoadSNode : public LoadNode {
public:
- LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
- : LoadNode(c, mem, adr, at, ti, mo) {}
+ LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@@ -298,8 +324,8 @@ public:
// Load an integer from memory
class LoadINode : public LoadNode {
public:
- LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
- : LoadNode(c, mem, adr, at, ti, mo) {}
+ LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegI; }
virtual int store_Opcode() const { return Op_StoreI; }
@@ -331,15 +357,15 @@ class LoadLNode : public LoadNode {
public:
LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl,
- MemOrd mo, bool require_atomic_access = false)
- : LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {}
+ MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
+ : LoadNode(c, mem, adr, at, tl, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegL; }
virtual int store_Opcode() const { return Op_StoreL; }
virtual BasicType memory_type() const { return T_LONG; }
bool require_atomic_access() const { return _require_atomic_access; }
static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
- const Type* rt, MemOrd mo);
+ const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const {
LoadNode::dump_spec(st);
@@ -352,8 +378,8 @@ public:
// Load a long from unaligned memory
class LoadL_unalignedNode : public LoadLNode {
public:
- LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
- : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {}
+ LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo, control_dependency) {}
virtual int Opcode() const;
};
@@ -361,8 +387,8 @@ public:
// Load a float (64 bits) from memory
class LoadFNode : public LoadNode {
public:
- LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo)
- : LoadNode(c, mem, adr, at, t, mo) {}
+ LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegF; }
virtual int store_Opcode() const { return Op_StoreF; }
@@ -382,15 +408,15 @@ class LoadDNode : public LoadNode {
public:
LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t,
- MemOrd mo, bool require_atomic_access = false)
- : LoadNode(c, mem, adr, at, t, mo), _require_atomic_access(require_atomic_access) {}
+ MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
+ : LoadNode(c, mem, adr, at, t, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegD; }
virtual int store_Opcode() const { return Op_StoreD; }
virtual BasicType memory_type() const { return T_DOUBLE; }
bool require_atomic_access() const { return _require_atomic_access; }
static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
- const Type* rt, MemOrd mo);
+ const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const {
LoadNode::dump_spec(st);
@@ -403,8 +429,8 @@ public:
// Load a double from unaligned memory
class LoadD_unalignedNode : public LoadDNode {
public:
- LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
- : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {}
+ LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo, control_dependency) {}
virtual int Opcode() const;
};
@@ -412,8 +438,8 @@ public:
// Load a pointer from memory (either object or array)
class LoadPNode : public LoadNode {
public:
- LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo)
- : LoadNode(c, mem, adr, at, t, mo) {}
+ LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegP; }
virtual int store_Opcode() const { return Op_StoreP; }
@@ -425,8 +451,8 @@ public:
// Load a narrow oop from memory (either object or array)
class LoadNNode : public LoadNode {
public:
- LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo)
- : LoadNode(c, mem, adr, at, t, mo) {}
+ LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegN; }
virtual int store_Opcode() const { return Op_StoreN; }
diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp
index 0f07506774e..f1cc539dc72 100644
--- a/hotspot/src/share/vm/opto/parse3.cpp
+++ b/hotspot/src/share/vm/opto/parse3.cpp
@@ -235,7 +235,7 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
//
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
- Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, needs_atomic_access);
+ Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, needs_atomic_access);
// Adjust Java stack
if (type2size[bt] == 1)
diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp
index 861a84f4d20..1426a31c9c5 100644
--- a/hotspot/src/share/vm/opto/phaseX.cpp
+++ b/hotspot/src/share/vm/opto/phaseX.cpp
@@ -1573,11 +1573,12 @@ void PhaseCCP::analyze() {
set_type(n, t);
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* m = n->fast_out(i); // Get user
- if( m->is_Region() ) { // New path to Region? Must recheck Phis too
+ if (m->is_Region()) { // New path to Region? Must recheck Phis too
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
Node* p = m->fast_out(i2); // Propagate changes to uses
- if( p->bottom_type() != type(p) ) // If not already bottomed out
+ if (p->bottom_type() != type(p)) { // If not already bottomed out
worklist.push(p); // Propagate change to user
+ }
}
}
// If we changed the receiver type to a call, we need to revisit
@@ -1587,12 +1588,31 @@ void PhaseCCP::analyze() {
if (m->is_Call()) {
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
Node* p = m->fast_out(i2); // Propagate changes to uses
- if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1)
+ if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1) {
worklist.push(p->unique_out());
+ }
}
}
- if( m->bottom_type() != type(m) ) // If not already bottomed out
+ if (m->bottom_type() != type(m)) { // If not already bottomed out
worklist.push(m); // Propagate change to user
+ }
+
+ // CmpU nodes can get their type information from two nodes up in the
+ // graph (instead of from the nodes immediately above). Make sure they
+ // are added to the worklist if nodes they depend on are updated, since
+ // they could be missed and get wrong types otherwise.
+ uint m_op = m->Opcode();
+ if (m_op == Op_AddI || m_op == Op_SubI) {
+ for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
+ Node* p = m->fast_out(i2); // Propagate changes to uses
+ if (p->Opcode() == Op_CmpU) {
+ // Got a CmpU which might need the new type information from node n.
+ if(p->bottom_type() != type(p)) { // If not already bottomed out
+ worklist.push(p); // Propagate change to user
+ }
+ }
+ }
+ }
}
}
}
diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp
index be63462c088..8dba68b8af2 100644
--- a/hotspot/src/share/vm/opto/superword.cpp
+++ b/hotspot/src/share/vm/opto/superword.cpp
@@ -1631,7 +1631,7 @@ void SuperWord::output() {
}
Node* adr = low_adr->in(MemNode::Address);
const TypePtr* atyp = n->adr_type();
- vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n));
+ vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p));
vlen_in_bytes = vn->as_LoadVector()->memory_size();
} else if (n->is_Store()) {
// Promote value to be stored to vector
@@ -2280,6 +2280,19 @@ Node* SuperWord::executed_last(Node_List* p) {
return n;
}
+LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) {
+ LoadNode::ControlDependency dep = LoadNode::DependsOnlyOnTest;
+ for (uint i = 0; i < p->size(); i++) {
+ Node* n = p->at(i);
+ assert(n->is_Load(), "only meaningful for loads");
+ if (!n->depends_only_on_test()) {
+ dep = LoadNode::Pinned;
+ }
+ }
+ return dep;
+}
+
+
//----------------------------align_initial_loop_index---------------------------
// Adjust pre-loop limit so that in main loop, a load/store reference
// to align_to_ref will be a position zero in the vector.
diff --git a/hotspot/src/share/vm/opto/superword.hpp b/hotspot/src/share/vm/opto/superword.hpp
index c56931a76fc..5ea8979c06b 100644
--- a/hotspot/src/share/vm/opto/superword.hpp
+++ b/hotspot/src/share/vm/opto/superword.hpp
@@ -428,6 +428,7 @@ class SuperWord : public ResourceObj {
Node* executed_first(Node_List* p);
// Return the node executed last in pack p.
Node* executed_last(Node_List* p);
+ static LoadNode::ControlDependency control_dependency(Node_List* p);
// Alignment within a vector memory reference
int memory_alignment(MemNode* s, int iv_adjust);
// (Start, end] half-open range defining which operands are vector
diff --git a/hotspot/src/share/vm/opto/vectornode.cpp b/hotspot/src/share/vm/opto/vectornode.cpp
index f1dae4cdc8a..8f88329bd05 100644
--- a/hotspot/src/share/vm/opto/vectornode.cpp
+++ b/hotspot/src/share/vm/opto/vectornode.cpp
@@ -406,9 +406,11 @@ PackNode* PackNode::binary_tree_pack(int lo, int hi) {
// Return the vector version of a scalar load node.
LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem,
- Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) {
+ Node* adr, const TypePtr* atyp,
+ uint vlen, BasicType bt,
+ ControlDependency control_dependency) {
const TypeVect* vt = TypeVect::make(bt, vlen);
- return new LoadVectorNode(ctl, mem, adr, atyp, vt);
+ return new LoadVectorNode(ctl, mem, adr, atyp, vt, control_dependency);
}
// Return the vector version of a scalar store node.
diff --git a/hotspot/src/share/vm/opto/vectornode.hpp b/hotspot/src/share/vm/opto/vectornode.hpp
index e848dc2ee91..572c44c8648 100644
--- a/hotspot/src/share/vm/opto/vectornode.hpp
+++ b/hotspot/src/share/vm/opto/vectornode.hpp
@@ -454,8 +454,8 @@ class XorVNode : public VectorNode {
// Load Vector from memory
class LoadVectorNode : public LoadNode {
public:
- LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt)
- : LoadNode(c, mem, adr, at, vt, MemNode::unordered) {
+ LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest)
+ : LoadNode(c, mem, adr, at, vt, MemNode::unordered, control_dependency) {
init_class_id(Class_LoadVector);
}
@@ -471,7 +471,9 @@ class LoadVectorNode : public LoadNode {
virtual int store_Opcode() const { return Op_StoreVector; }
static LoadVectorNode* make(int opc, Node* ctl, Node* mem,
- Node* adr, const TypePtr* atyp, uint vlen, BasicType bt);
+ Node* adr, const TypePtr* atyp,
+ uint vlen, BasicType bt,
+ ControlDependency control_dependency = LoadNode::DependsOnlyOnTest);
};
//------------------------------StoreVectorNode--------------------------------
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index a8b6ec79134..2061f6330e2 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -1126,39 +1126,32 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
Method* m = Method::resolve_jmethod_id(method_id);
number_of_parameters = m->size_of_parameters();
Klass* holder = m->method_holder();
- if (!(holder)->is_interface()) {
+ if (call_type != JNI_VIRTUAL) {
+ selected_method = m;
+ } else if (!m->has_itable_index()) {
// non-interface call -- for that little speed boost, don't handlize
debug_only(No_Safepoint_Verifier nosafepoint;)
- if (call_type == JNI_VIRTUAL) {
- // jni_GetMethodID makes sure class is linked and initialized
- // so m should have a valid vtable index.
- assert(!m->has_itable_index(), "");
- int vtbl_index = m->vtable_index();
- if (vtbl_index != Method::nonvirtual_vtable_index) {
- Klass* k = h_recv->klass();
- // k might be an arrayKlassOop but all vtables start at
- // the same place. The cast is to avoid virtual call and assertion.
- InstanceKlass *ik = (InstanceKlass*)k;
- selected_method = ik->method_at_vtable(vtbl_index);
- } else {
- // final method
- selected_method = m;
- }
+ // jni_GetMethodID makes sure class is linked and initialized
+ // so m should have a valid vtable index.
+ assert(m->valid_vtable_index(), "no valid vtable index");
+ int vtbl_index = m->vtable_index();
+ if (vtbl_index != Method::nonvirtual_vtable_index) {
+ Klass* k = h_recv->klass();
+ // k might be an arrayKlassOop but all vtables start at
+ // the same place. The cast is to avoid virtual call and assertion.
+ InstanceKlass *ik = (InstanceKlass*)k;
+ selected_method = ik->method_at_vtable(vtbl_index);
} else {
- // JNI_NONVIRTUAL call
+ // final method
selected_method = m;
}
} else {
// interface call
KlassHandle h_holder(THREAD, holder);
- if (call_type == JNI_VIRTUAL) {
- int itbl_index = m->itable_index();
- Klass* k = h_recv->klass();
- selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
- } else {
- selected_method = m;
- }
+ int itbl_index = m->itable_index();
+ Klass* k = h_recv->klass();
+ selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
}
}
diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
index 2d3d200f207..db0437ab119 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
@@ -842,7 +842,7 @@ JvmtiEnvBase::get_stack_trace(JavaThread *java_thread,
// optimize to limit the number of times that java_sender() is called
javaVFrame *jvf_cursor = jvf;
javaVFrame *jvf_prev = NULL;
- javaVFrame *jvf_prev_prev;
+ javaVFrame *jvf_prev_prev = NULL;
int j = 0;
while (jvf_cursor != NULL) {
jvf_prev_prev = jvf_prev;
diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp
index b9cf17732a4..0856cffa236 100644
--- a/hotspot/src/share/vm/prims/methodHandles.cpp
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp
@@ -677,24 +677,24 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
case IS_METHOD:
{
CallInfo result;
+ LinkInfo link_info(defc, name, type, caller, caller.not_null());
{
assert(!HAS_PENDING_EXCEPTION, "");
if (ref_kind == JVM_REF_invokeStatic) {
LinkResolver::resolve_static_call(result,
- defc, name, type, caller, caller.not_null(), false, THREAD);
+ link_info, false, THREAD);
} else if (ref_kind == JVM_REF_invokeInterface) {
LinkResolver::resolve_interface_call(result, Handle(), defc,
- defc, name, type, caller, caller.not_null(), false, THREAD);
+ link_info, false, THREAD);
} else if (mh_invoke_id != vmIntrinsics::_none) {
assert(!is_signature_polymorphic_static(mh_invoke_id), "");
- LinkResolver::resolve_handle_call(result,
- defc, name, type, caller, THREAD);
+ LinkResolver::resolve_handle_call(result, link_info, THREAD);
} else if (ref_kind == JVM_REF_invokeSpecial) {
LinkResolver::resolve_special_call(result,
- defc, name, type, caller, caller.not_null(), THREAD);
+ link_info, THREAD);
} else if (ref_kind == JVM_REF_invokeVirtual) {
LinkResolver::resolve_virtual_call(result, Handle(), defc,
- defc, name, type, caller, caller.not_null(), false, THREAD);
+ link_info, false, THREAD);
} else {
assert(false, err_msg("ref_kind=%d", ref_kind));
}
@@ -714,11 +714,11 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
case IS_CONSTRUCTOR:
{
CallInfo result;
+ LinkInfo link_info(defc, name, type, caller, caller.not_null());
{
assert(!HAS_PENDING_EXCEPTION, "");
if (name == vmSymbols::object_initializer_name()) {
- LinkResolver::resolve_special_call(result,
- defc, name, type, caller, caller.not_null(), THREAD);
+ LinkResolver::resolve_special_call(result, link_info, THREAD);
} else {
break; // will throw after end of switch
}
@@ -735,7 +735,8 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
fieldDescriptor result; // find_field initializes fd if found
{
assert(!HAS_PENDING_EXCEPTION, "");
- LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD);
+ LinkInfo link_info(defc, name, type, caller, /*check_access*/false);
+ LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
if (HAS_PENDING_EXCEPTION) {
return empty;
}
@@ -942,22 +943,56 @@ int MethodHandles::find_MemberNames(KlassHandle k,
return rfill + overflow;
}
-// Get context class for a CallSite instance: either extract existing context or use default one.
-InstanceKlass* MethodHandles::get_call_site_context(oop call_site) {
- // In order to extract a context the following traversal is performed:
- // CallSite.context => Cleaner.referent => Class._klass => Klass
- assert(java_lang_invoke_CallSite::is_instance(call_site), "");
- oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site);
- if (oopDesc::is_null(context_oop)) {
- return NULL; // The context hasn't been initialized yet.
+void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ oop context = java_lang_invoke_CallSite::context(call_site);
+ nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
+
+ nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm);
+ if (deps != new_deps) {
+ java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
}
- oop context_class_oop = java_lang_ref_Reference::referent(context_oop);
- if (oopDesc::is_null(context_class_oop)) {
- // The context reference was cleared by GC, so current dependency context
- // isn't usable anymore. Context should be fetched from CallSite again.
- return NULL;
+}
+
+void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ oop context = java_lang_invoke_CallSite::context(call_site);
+ nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
+
+ if (nmethodBucket::remove_dependent_nmethod(deps, nm)) {
+ nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
+ if (deps != new_deps) {
+ java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
+ }
+ }
+}
+
+void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) {
+ assert_lock_strong(Compile_lock);
+
+ int marked = 0;
+ CallSiteDepChange changes(call_site(), target());
+ {
+ MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+
+ oop context = java_lang_invoke_CallSite::context(call_site());
+ nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
+
+ marked = nmethodBucket::mark_dependent_nmethods(deps, changes);
+ if (marked > 0) {
+ nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
+ if (deps != new_deps) {
+ java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
+ }
+ }
+ }
+ if (marked > 0) {
+ // At least one nmethod has been marked for deoptimization
+ VM_Deoptimize op;
+ VMThread::execute(&op);
}
- return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
}
//------------------------------------------------------------------------------
@@ -1276,7 +1311,7 @@ JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject
{
// Walk all nmethods depending on this call site.
MutexLocker mu(Compile_lock, thread);
- CodeCache::flush_dependents_on(call_site, target);
+ MethodHandles::flush_dependent_nmethods(call_site, target);
java_lang_invoke_CallSite::set_target(call_site(), target());
}
}
@@ -1288,30 +1323,34 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec
{
// Walk all nmethods depending on this call site.
MutexLocker mu(Compile_lock, thread);
- CodeCache::flush_dependents_on(call_site, target);
+ MethodHandles::flush_dependent_nmethods(call_site, target);
java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
}
}
JVM_END
-JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) {
- Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
+JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
+ Handle context(THREAD, JNIHandles::resolve_non_null(context_jh));
{
// Walk all nmethods depending on this call site.
MutexLocker mu1(Compile_lock, thread);
- CallSiteDepChange changes(call_site(), Handle());
-
- InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
- if (ctxk == NULL) {
- return; // No dependencies to invalidate yet.
- }
int marked = 0;
{
MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- marked = ctxk->mark_dependent_nmethods(changes);
+ nmethodBucket* b = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context());
+ while(b != NULL) {
+ nmethod* nm = b->get_nmethod();
+ if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) {
+ nm->mark_for_deoptimization();
+ marked++;
+ }
+ nmethodBucket* next = b->next();
+ delete b;
+ b = next;
+ }
+ java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context(), NULL); // reset context
}
- java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state
if (marked > 0) {
// At least one nmethod has been marked for deoptimization
VM_Deoptimize op;
@@ -1357,6 +1396,7 @@ JVM_END
#define MT JLINV"MethodType;"
#define MH JLINV"MethodHandle;"
#define MEM JLINV"MemberName;"
+#define CTX JLINV"MethodHandleNatives$CallSiteContext;"
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@@ -1374,7 +1414,7 @@ static JNINativeMethod MHN_methods[] = {
{CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)},
{CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)},
{CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)},
- {CC"invalidateDependentNMethods", CC"("CS")V", FN_PTR(MHN_invalidateDependentNMethods)},
+ {CC"clearCallSiteContext", CC"("CTX")V", FN_PTR(MHN_clearCallSiteContext)},
{CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)},
{CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)},
{CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)}
diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp
index 5dd69bd42ff..ab41c31b4a3 100644
--- a/hotspot/src/share/vm/prims/methodHandles.hpp
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp
@@ -69,7 +69,10 @@ class MethodHandles: AllStatic {
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
// CallSite support
- static InstanceKlass* get_call_site_context(oop call_site);
+ static void add_dependent_nmethod(oop call_site, nmethod* nm);
+ static void remove_dependent_nmethod(oop call_site, nmethod* nm);
+
+ static void flush_dependent_nmethods(Handle call_site, Handle target);
// Generate MethodHandles adapters.
static bool generate_adapters();
diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
index 5ac9413e8d0..76c2aaa9f22 100644
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
@@ -64,7 +64,7 @@ void AdvancedThresholdPolicy::initialize() {
}
#endif
-#ifdef SPARC
+#if defined SPARC || defined AARCH64
if (FLAG_IS_DEFAULT(InlineSmallCode)) {
FLAG_SET_DEFAULT(InlineSmallCode, 2500);
}
diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp
index a7bdc680e93..9d4eccd8d69 100644
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -179,9 +179,9 @@ void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol*
CallInfo callinfo;
Handle receiver = args->receiver();
KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass());
+ LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false);
LinkResolver::resolve_virtual_call(
- callinfo, receiver, recvrKlass, spec_klass, name, signature,
- KlassHandle(), false, true, CHECK);
+ callinfo, receiver, recvrKlass, link_info, true, CHECK);
methodHandle method = callinfo.selected_method();
assert(method.not_null(), "should have thrown exception");
@@ -216,7 +216,8 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe
void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
CallInfo callinfo;
- LinkResolver::resolve_special_call(callinfo, klass, name, signature, KlassHandle(), false, CHECK);
+ LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+ LinkResolver::resolve_special_call(callinfo, link_info, CHECK);
methodHandle method = callinfo.selected_method();
assert(method.not_null(), "should have thrown exception");
@@ -250,7 +251,8 @@ void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle kla
void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
CallInfo callinfo;
- LinkResolver::resolve_static_call(callinfo, klass, name, signature, KlassHandle(), false, true, CHECK);
+ LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+ LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK);
methodHandle method = callinfo.selected_method();
assert(method.not_null(), "should have thrown exception");
diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp
index 525c1a929c8..9cc4ea92dd1 100644
--- a/hotspot/src/share/vm/runtime/os.cpp
+++ b/hotspot/src/share/vm/runtime/os.cpp
@@ -775,6 +775,10 @@ void os::start_thread(Thread* thread) {
pd_start_thread(thread);
}
+void os::abort(bool dump_core) {
+ abort(dump_core && CreateCoredumpOnCrash, NULL, NULL);
+}
+
//---------------------------------------------------------------------------
// Helper functions for fatal error handler
diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp
index 85a2b0aade3..0e439e87137 100644
--- a/hotspot/src/share/vm/runtime/reflection.cpp
+++ b/hotspot/src/share/vm/runtime/reflection.cpp
@@ -831,9 +831,9 @@ methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, metho
CallInfo info;
Symbol* signature = method->signature();
Symbol* name = method->name();
- LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass,
- name, signature,
- KlassHandle(), false, true,
+ LinkResolver::resolve_interface_call(info, receiver, recv_klass,
+ LinkInfo(klass, name, signature, KlassHandle(), false),
+ true,
CHECK_(methodHandle()));
return info.selected_method();
}
diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp
index 491f3568d47..6f50c76e16e 100644
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp
@@ -315,7 +315,7 @@ int VMUptimeDCmd::num_arguments() {
void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
if (!DisableExplicitGC) {
- Universe::heap()->collect(GCCause::_java_lang_system_gc);
+ Universe::heap()->collect(GCCause::_dcmd_gc_run);
} else {
output()->print_cr("Explicit GC is disabled, no GC has been performed.");
}
diff --git a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp
index 8c564004a91..e6a155aced4 100644
--- a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp
+++ b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp
@@ -89,11 +89,11 @@ private:
return ((uintx)1) << validate_tag(tag);
}
- static TagType validate_tag(uintx tag) {
- // Type of tag is not TagType to dodge useless MacOSX compiler warning.
- assert(tag < (sizeof(uintx) * BitsPerByte),
- err_msg("Tag " UINTX_FORMAT " is too large", tag));
- return static_cast(tag);
+ static TagType validate_tag(TagType tag) {
+ assert(0 <= tag, err_msg("Tag " INTX_FORMAT " is negative", (intx)tag));
+ assert(tag < BitsPerWord,
+ err_msg("Tag " UINTX_FORMAT " is too large", (uintx)tag));
+ return tag;
}
};
diff --git a/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java b/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java
new file mode 100644
index 00000000000..1492254a054
--- /dev/null
+++ b/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080699
+ * @summary eliminated arraycopy node still reachable through exception edges
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestDeadArrayCopyOnMemChain
+ *
+ */
+
+public class TestDeadArrayCopyOnMemChain {
+ static class A {
+ int f;
+ }
+
+ static void test_helper(Object o) {
+ }
+
+ static void test(int src_off, boolean flag) {
+ // dst is eliminated first. Eliminating dst causes src to be
+ // eliminated. When working on the safepoint at the uncommon
+ // trap in the exception handler, the eliminated ArrayCopyNode
+ // is reached through the exception edges.
+ Object[] dst = new Object[10];
+ Object[] src = new Object[10];
+
+ // src_off causes the exception handler to be run sometimes
+ try {
+ System.arraycopy(src, src_off, dst, 0, 10);
+ } catch (IndexOutOfBoundsException ioobe) {
+ // flag always false so test becomes uncommon trap. Make
+ // sure src is live at the unc.
+ if (flag) {
+ test_helper(src);
+ }
+ }
+ }
+
+ static public void main(String[] args) {
+ for (int i = 0; i < 20000; i++) {
+ test((i%2) == 0 ? 0 : -1, false);
+ }
+ }
+}
diff --git a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java
index 8005a990d83..d65bf424228 100644
--- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java
+++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java
@@ -24,12 +24,15 @@
/**
* @test
* @bug 8057967
- * @ignore 8079205
- * @run main/bootclasspath -Xbatch java.lang.invoke.CallSiteDepContextTest
+ * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading
+ * -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC
+ * -verbose:gc java.lang.invoke.CallSiteDepContextTest
*/
package java.lang.invoke;
import java.lang.ref.*;
+import java.lang.reflect.Field;
+
import jdk.internal.org.objectweb.asm.*;
import sun.misc.Unsafe;
@@ -96,6 +99,13 @@ public class CallSiteDepContextTest {
}
}
+ public static void testHiddenDepField() throws Exception {
+ try {
+ Field f = MethodHandleNatives.CallSiteContext.class.getDeclaredField("vmdependencies");
+ throw new AssertionError("Context.dependencies field should be hidden");
+ } catch(NoSuchFieldException e) { /* expected */ }
+ }
+
public static void testSharedCallSite() throws Throwable {
Class> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null);
Class> cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null);
@@ -132,12 +142,14 @@ public class CallSiteDepContextTest {
static ReferenceQueue rq = new ReferenceQueue();
static PhantomReference ref;
- public static void testGC() throws Throwable {
+ public static void testGC(boolean clear, boolean precompile) throws Throwable {
+ String id = "_" + clear + "_" + precompile;
+
mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
Class>[] cls = new Class[] {
- UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1"), null),
- UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2"), null),
+ UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null),
+ UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null),
};
MethodHandle[] mhs = new MethodHandle[] {
@@ -151,30 +163,38 @@ public class CallSiteDepContextTest {
execute(1, mhs);
ref = new PhantomReference<>(cls[0], rq);
- cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3"), null);
+ cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null);
mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);
do {
System.gc();
try {
- Reference ref1 = rq.remove(1000);
+ Reference ref1 = rq.remove(100);
if (ref1 == ref) {
- ref1.clear();
- System.gc(); // Ensure that the stale context is cleared
break;
}
} catch(InterruptedException e) { /* ignore */ }
} while (true);
- execute(1, mhs);
+ if (clear) {
+ ref.clear();
+ System.gc(); // Ensure that the stale context is unloaded
+ }
+ if (precompile) {
+ execute(1, mhs);
+ }
mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
execute(2, mhs);
}
public static void main(String[] args) throws Throwable {
+ testHiddenDepField();
testSharedCallSite();
testNonBoundCallSite();
- testGC();
+ testGC(false, false);
+ testGC(false, true);
+ testGC( true, false);
+ testGC( true, true);
System.out.println("TEST PASSED");
}
}
diff --git a/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java b/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java
new file mode 100644
index 00000000000..b8e1d72806c
--- /dev/null
+++ b/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080976
+ * @summary Loop variant use in reduction should prevent vectorization
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestReductionWithLoopVariantUse
+ *
+ */
+
+public class TestReductionWithLoopVariantUse {
+ static int m(int[] array) {
+ int c = 0;
+ for (int i = 0; i < 256; i++) {
+ c += array[i];
+ array[i] = c;
+ }
+ return c;
+ }
+
+ static public void main(String[] args) {
+ int[] array = new int[256];
+ int[] array2 = new int[256];
+ for (int j = 0; j < 256; j++) {
+ array2[j] = j;
+ }
+ for (int i = 0; i < 20000; i++) {
+ System.arraycopy(array2, 0, array, 0, 256);
+ int res = m(array);
+ boolean success = true;
+ int c = 0;
+ for (int j = 0; j < 256; j++) {
+ c += array2[j];
+ if (array[j] != c) {
+ System.out.println("Failed for " + j + " : " + array[j] + " != " + c);
+ success = false;
+ }
+ }
+ if (c != res) {
+ System.out.println("Failed for sum: " + c + " != " + res);
+ }
+ if (!success) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+ }
+}
diff --git a/hotspot/test/compiler/types/TestTypePropagationToCmpU.java b/hotspot/test/compiler/types/TestTypePropagationToCmpU.java
new file mode 100644
index 00000000000..9e08a8b4cf0
--- /dev/null
+++ b/hotspot/test/compiler/types/TestTypePropagationToCmpU.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080156 8060036
+ * @summary Test correctness of type propagation to CmpUNodes.
+ * @run main TestTypePropagationToCmpU
+ */
+public class TestTypePropagationToCmpU {
+ public static void main(String[] args) {
+ try {
+ // Trigger compilation
+ for (int i = 0; i < 100_000; ++i) {
+ test();
+ }
+ } catch (NullPointerException e) {
+ // Test should never throw a NullPointerException
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ static int global = 42;
+
+ public static void test() {
+ int a = Integer.MIN_VALUE;
+ int b = global;
+ char[] buf = { 0 };
+ for (int i = 0; i <= b; ++i) {
+ a = i - b;
+ }
+ // C2 adds a range check and an uncommon trap here to ensure that the array index
+ // is in bounds. If type information is not propagated correctly to the corresponding
+ // CmpUNode, this trap may be always taken. Because C2 also removes the unnecessary
+ // allocation of 'buf', a NullPointerException is thrown in this case.
+ char c = buf[(a * 11) / 2 - a]; // a is 0 here if global >= 0
+ buf[0] = 0;
+ }
+}
diff --git a/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
new file mode 100644
index 00000000000..edd55975378
--- /dev/null
+++ b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8077504
+ * @summary Unsafe load can loose control dependency and cause crash
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestUnsafeLoadControl
+ *
+ */
+
+import java.lang.reflect.Field;
+import sun.misc.Unsafe;
+
+public class TestUnsafeLoadControl {
+
+ private static final Unsafe UNSAFE;
+
+ static {
+ try {
+ Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ UNSAFE = (Unsafe) unsafeField.get(null);
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static int val;
+ static void test1(int[] a, boolean[] flags, boolean flag, long j) {
+ for (int i = 0; i < 10; i++) {
+ if (flags[i]) {
+ if (flag) {
+ long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET;
+ int v = UNSAFE.getInt(a, address);
+ val = v;
+ }
+ }
+ }
+ }
+
+ static int test2(int[] a, boolean[] flags, boolean flag, long j) {
+ int sum = 0;
+ for (int i = 0; i < 10; i++) {
+ if (flags[i]) {
+ if (flag) {
+ long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET;
+ int v = UNSAFE.getInt(a, address);
+ if (v == 0) {
+ sum++;
+ }
+ }
+ }
+ }
+ return sum;
+ }
+
+ static public void main(String[] args) {
+ boolean[] flags = new boolean[10];
+ for (int i = 0; i < flags.length; i++) {
+ flags[i] = true;
+ }
+ int[] array = new int[10];
+ for (int i = 0; i < 20000; i++) {
+ test1(array, flags, true, 0);
+ }
+ for (int i = 0; i < flags.length; i++) {
+ flags[i] = false;
+ }
+ test1(array, flags, true, Long.MAX_VALUE/4);
+
+ for (int i = 0; i < flags.length; i++) {
+ flags[i] = true;
+ }
+ for (int i = 0; i < 20000; i++) {
+ test2(array, flags, true, 0);
+ }
+ for (int i = 0; i < flags.length; i++) {
+ flags[i] = false;
+ }
+ test2(array, flags, true, Long.MAX_VALUE/4);
+ }
+}
diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java
index b78d558cb51..23c1b00a9c3 100644
--- a/hotspot/test/gc/TestSmallHeap.java
+++ b/hotspot/test/gc/TestSmallHeap.java
@@ -27,6 +27,7 @@
* @requires vm.gc=="null"
* @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false")
* @requires vm.compMode != "Xcomp"
+ * @requires vm.opt.UseCompressedOops != false
* @summary Verify that starting the VM with a small heap works
* @library /testlibrary /../../test/lib
* @modules java.management/sun.management
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/Dependency.java b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java
similarity index 62%
rename from langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/Dependency.java
rename to hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java
index cd9fbb6a529..e82d2bdfc98 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/dependencies/Dependency.java
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java
@@ -1,12 +1,10 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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.
+ * published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -22,12 +20,27 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package com.sun.tools.sjavac.comp.dependencies;
-import java.util.Set;
+/**
+ * Implementation of InterfaceWithToString.
+ */
+public class ImplementationOfWithToString implements InterfaceWithToString {
-import com.sun.tools.javac.code.Symbol.PackageSymbol;
+ /**
+ * @see InterfaceWithToString#someMethod()
+ * {@inheritDoc}
+ */
+ @Override
+ public void someMethod() {
+ // May do something here.
+ }
-interface Dependency {
- Set getPackages();
+ /**
+ * @see java.lang.Object#toString()
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return "toString() from " + getClass().getName();
+ }
}
diff --git a/langtools/test/tools/sjavac/test-input/src/pkg25/Cls25.java b/hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java
similarity index 74%
rename from langtools/test/tools/sjavac/test-input/src/pkg25/Cls25.java
rename to hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java
index 5478401b6a1..dbf06a15cc0 100644
--- a/langtools/test/tools/sjavac/test-input/src/pkg25/Cls25.java
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java
@@ -1,12 +1,10 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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.
+ * published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -22,7 +20,18 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package pkg25;
-public class Cls25 extends Throwable {
+/**
+ * Interface with toString declared.
+ */
+public interface InterfaceWithToString {
+
+ void someMethod();
+
+ /**
+ * Same as Object.toString().
+ *
+ * @return some custom string.
+ */
+ String toString();
}
diff --git a/langtools/test/tools/sjavac/test-input/src/pkg13/Cls13.java b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java
similarity index 67%
rename from langtools/test/tools/sjavac/test-input/src/pkg13/Cls13.java
rename to hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java
index 9a36751a4c3..02d4d55365e 100644
--- a/langtools/test/tools/sjavac/test-input/src/pkg13/Cls13.java
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java
@@ -1,12 +1,10 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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.
+ * published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -22,9 +20,22 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package pkg13;
-public class Cls13 {
- public pkg14.Cls14 getCls14() {
- return null;
+
+/* @test
+ * @bug 8072588
+ * @build InterfaceWithToString
+ * @build ImplementationOfWithToString
+ * @run main/native ToStringTest
+ */
+public final class ToStringTest {
+
+ static {
+ System.loadLibrary("ToStringTest");
+ }
+
+ native static void nTest();
+
+ public static void main(String[] args) throws Exception {
+ nTest();
}
}
diff --git a/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c b/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c
new file mode 100644
index 00000000000..2c4750fac07
--- /dev/null
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native test for ToStringInInterfaceTest.
+ */
+
+#include "jni.h"
+
+#define checkException(env) if ((*env)->ExceptionCheck(env)) { return; }
+
+jstring callStringMethod(JNIEnv* env, jobject jobj, jmethodID id, ...)
+{
+ jstring value;
+
+ va_list ap;
+ va_start(ap, id);
+ value = (jstring)(*env)->CallObjectMethodV(env, jobj, id, ap);
+ va_end(ap);
+ return value;
+}
+
+JNIEXPORT void JNICALL Java_ToStringTest_nTest(JNIEnv* env, jclass jclazz)
+{
+ jclass classOfInterfaceWithToString;
+ jclass classOfImplementationOfWithToString;
+ jmethodID constructorOfImplementationOfWithToString;
+ jobject instanceOfImplementationOfWithToString;
+ jmethodID toStringOfInterfaceWithToString;
+ jmethodID toStringOfImplementationOfWithToString;
+ jstring jstr;
+ const char *chars;
+
+ classOfInterfaceWithToString = (*env)->FindClass(env, "InterfaceWithToString");
+ checkException(env);
+ classOfImplementationOfWithToString = (*env)->FindClass(env, "ImplementationOfWithToString");
+ checkException(env);
+
+ constructorOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "", "()V");
+ checkException(env);
+
+ instanceOfImplementationOfWithToString = (*env)->NewObject(env, classOfImplementationOfWithToString, constructorOfImplementationOfWithToString);
+ checkException(env);
+
+ toStringOfInterfaceWithToString = (*env)->GetMethodID(env, classOfInterfaceWithToString, "toString", "()Ljava/lang/String;");
+ checkException(env);
+
+ toStringOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "toString", "()Ljava/lang/String;");
+ checkException(env);
+
+ jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfImplementationOfWithToString);
+ checkException(env);
+
+ chars = (*env)->GetStringUTFChars(env, jstr, NULL);
+ (*env)->ReleaseStringUTFChars(env, jstr, chars);
+
+ jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfInterfaceWithToString);
+ checkException(env);
+
+ chars = (*env)->GetStringUTFChars(env, jstr, NULL);
+ (*env)->ReleaseStringUTFChars(env, jstr, chars);
+}
diff --git a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java
index d34ca012bea..8746f7f26d6 100644
--- a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java
@@ -59,7 +59,7 @@ public class RunGCTest {
}
OutputAnalyzer output = new OutputAnalyzer(gcLog, "");
- output.shouldMatch(".*\\[Full GC \\(System(\\.gc\\(\\))?.*");
+ output.shouldContain("[Full GC (Diagnostic Command)");
}
@Test
diff --git a/hotspot/test/serviceability/sa/TestClassLoaderStats.java b/hotspot/test/serviceability/sa/TestClassLoaderStats.java
index 2f35d6a4edd..92bd3152752 100644
--- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java
+++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java
@@ -24,11 +24,14 @@
import jdk.test.lib.Platform;
import jdk.test.lib.ProcessTools;
import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.apps.LingeredApp;
/*
* @test
+ * @library /../../test/lib/share/classes
* @library /testlibrary
* @build jdk.test.lib.*
+ * @build jdk.test.lib.apps.*
* @run main TestClassLoaderStats
*/
public class TestClassLoaderStats {
@@ -39,19 +42,27 @@ public class TestClassLoaderStats {
return;
}
- ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
- "-XX:+UsePerfData",
- "sun.jvm.hotspot.tools.ClassLoaderStats",
- Integer.toString(ProcessTools.getProcessId()));
- OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
- System.out.println(output.getOutput());
+ LingeredApp app = null;
+ try {
+ app = LingeredApp.startApp();
- output.shouldHaveExitValue(0);
- output.shouldContain("Debugger attached successfully.");
- // The class loader stats header needs to be presented in the output:
- output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type");
- output.stderrShouldNotMatch("[E|e]xception");
- output.stderrShouldNotMatch("[E|e]rror");
+ System.out.println("Attaching sun.jvm.hotspot.tools.ClassLoaderStats to " + app.getPid());
+ ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UsePerfData",
+ "sun.jvm.hotspot.tools.ClassLoaderStats",
+ Long.toString(app.getPid()));
+ OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
+ System.out.println(output.getOutput());
+
+ output.shouldHaveExitValue(0);
+ output.shouldContain("Debugger attached successfully.");
+ // The class loader stats header needs to be presented in the output:
+ output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type");
+ output.stderrShouldNotMatch("[E|e]xception");
+ output.stderrShouldNotMatch("[E|e]rror");
+ } finally {
+ app.stopApp();
+ }
}
}
diff --git a/hotspot/test/serviceability/sa/TestStackTrace.java b/hotspot/test/serviceability/sa/TestStackTrace.java
index ba5a56a031d..6d5eb7b4d21 100644
--- a/hotspot/test/serviceability/sa/TestStackTrace.java
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java
@@ -24,11 +24,14 @@
import jdk.test.lib.OutputAnalyzer;
import jdk.test.lib.Platform;
import jdk.test.lib.ProcessTools;
+import jdk.test.lib.apps.LingeredApp;
/*
* @test
+ * @library /../../test/lib/share/classes
* @library /testlibrary
* @build jdk.test.lib.*
+ * @build jdk.test.lib.apps.*
* @run main TestStackTrace
*/
public class TestStackTrace {
@@ -39,17 +42,25 @@ public class TestStackTrace {
return;
}
- ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
- "-XX:+UsePerfData",
- "sun.jvm.hotspot.tools.StackTrace",
- Integer.toString(ProcessTools.getProcessId()));
- OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
- System.out.println(output.getOutput());
+ LingeredApp app = null;
+ try {
+ app = LingeredApp.startApp();
- output.shouldHaveExitValue(0);
- output.shouldContain("Debugger attached successfully.");
- output.stderrShouldNotMatch("[E|e]xception");
- output.stderrShouldNotMatch("[E|e]rror");
+ System.out.println("Attaching sun.jvm.hotspot.tools.StackTrace to " + app.getPid());
+ ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UsePerfData",
+ "sun.jvm.hotspot.tools.StackTrace",
+ Long.toString(app.getPid()));
+ OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
+ System.out.println(output.getOutput());
+
+ output.shouldHaveExitValue(0);
+ output.shouldContain("Debugger attached successfully.");
+ output.stderrShouldNotMatch("[E|e]xception");
+ output.stderrShouldNotMatch("[E|e]rror");
+ } finally {
+ app.stopApp();
+ }
}
}
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index 3ed239facb6..7a3b45f50d8 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -310,3 +310,4 @@ f4a4a54620370f077c2e830a5561c8cfa811712b jdk9-b61
ae7406e82828fe1c245ac7507a9da5fd5b1c9529 jdk9-b65
d5963ccce28d7a3e96ee3e2dc8a8676e61699b70 jdk9-b66
78c2685daabafae827c686ca2d1bb2e451faed2b jdk9-b67
+82aae947938ec9b0119fdd78a616d0b7263072ee jdk9-b68
diff --git a/jaxp/test/javax/xml/jaxp/functional/TEST.properties b/jaxp/test/javax/xml/jaxp/functional/TEST.properties
index a8ef42cafa3..f94f3b92152 100644
--- a/jaxp/test/javax/xml/jaxp/functional/TEST.properties
+++ b/jaxp/test/javax/xml/jaxp/functional/TEST.properties
@@ -7,3 +7,6 @@ lib.dirs = /javax/xml/jaxp/libs
# Tests that must run in othervm mode
othervm.dirs= /javax/xml/jaxp/functional
+# Declare module dependency
+modules=java.xml
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties
index e8445deaa68..23136c131a5 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties
+++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties
@@ -1,3 +1,6 @@
# jaxp test uses TestNG
TestNG.dirs = .
+# Declare module dependency
+modules=java.xml
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java
index 735efe8932b..ee5e2587d6c 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,37 +23,47 @@
package javax.xml.parsers.xinclude;
+import static java.lang.System.lineSeparator;
+import static org.testng.Assert.assertEquals;
+
import java.io.File;
-import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
-import org.testng.Assert;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
+import org.w3c.dom.NodeList;
/*
- * @bug 6794483
- * @summary Test JAXP parser can parse xml file using to include another xml, which has an empty element.
+ * @bug 6794483 8080908
+ * @summary Test JAXP parser can resolve the included content properly if the
+ * included xml contains an empty tag that ends with "/>", refer to XERCESJ-1134.
*/
public class Bug6794483Test {
@Test
- public final void test() {
- String xml = getClass().getResource("test1.xml").getPath();
- Document doc = parseXmlFile(xml);
+ public final void test() throws Exception {
+ Document doc = parseXmlFile(getClass().getResource("test1.xml").getPath());
+ // check node4
+ NodeList nodeList = doc.getElementsByTagName("node4");
+ assertEquals(nodeList.getLength(), 1);
+ assertEquals(nodeList.item(0).getTextContent(), "Node4 Value", "The data of node4 is missed in parsing: " + lineSeparator() + printXmlDoc(doc));
+
+ // check node6
+ nodeList = doc.getElementsByTagName("node6");
+ assertEquals(nodeList.getLength(), 1);
+ assertEquals(nodeList.item(0).getTextContent(), "Node6 Value", "The data of node6 is missed in parsing: " + lineSeparator() + printXmlDoc(doc));
+ }
+
+ public String printXmlDoc(Document doc) throws Exception {
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
@@ -61,27 +71,16 @@ public class Bug6794483Test {
transformerFact.setAttribute("indent-number", new Integer(4));
Transformer transformer;
- try {
- transformer = transformerFact.newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
- transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
-
- // "true" indicate Append content If file exist in system
- transformer.transform(new DOMSource(doc), result);
- System.out.println("test" + sw);
-
- } catch (TransformerConfigurationException ex) {
- ex.printStackTrace();
- Assert.fail("unexpected TransformerConfigurationException");
- } catch (TransformerException ex) {
- ex.printStackTrace();
- Assert.fail("unexpected TransformerException");
- }
+ transformer = transformerFact.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+ transformer.transform(new DOMSource(doc), result);
+ return sw.toString();
}
- public Document parseXmlFile(String fileName) {
+ public Document parseXmlFile(String fileName) throws Exception {
System.out.println("Parsing XML file... " + fileName);
DocumentBuilder docBuilder = null;
Document doc = null;
@@ -92,20 +91,10 @@ public class Bug6794483Test {
docBuilderFactory.setNamespaceAware(true);
docBuilderFactory.setExpandEntityReferences(true);
- try {
- docBuilder = docBuilderFactory.newDocumentBuilder();
- } catch (ParserConfigurationException e) {
- e.printStackTrace();
- }
+ docBuilder = docBuilderFactory.newDocumentBuilder();
File sourceFile = new File(fileName);
- try {
- doc = docBuilder.parse(sourceFile);
- } catch (SAXException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ doc = docBuilder.parse(sourceFile);
System.out.println("XML file parsed");
return doc;
diff --git a/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java
index 56aafde0bb5..0213f82a0d6 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java
@@ -44,6 +44,7 @@ import org.xml.sax.SAXException;
/*
+ * @bug 6439439 8080906
* @summary Test LSSerializer.
*/
public class LSSerializerTest {
@@ -98,6 +99,17 @@ public class LSSerializerTest {
}
}
+ /*
+ * @bug 8080906
+ * It will fail in a Jigsaw build until JDK-8080266 is fixed.
+ */
+ @Test
+ public void testDefaultLSSerializer() throws Exception {
+ DOMImplementationLS domImpl = (DOMImplementationLS) DocumentBuilderFactory.newInstance().newDocumentBuilder().getDOMImplementation();
+ LSSerializer lsSerializer = domImpl.createLSSerializer();
+ Assert.assertTrue(lsSerializer.getClass().getName().endsWith("dom3.LSSerializerImpl"));
+ }
+
@Test
public void testDOMErrorHandler() {
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 8dda55983d4..781a517b01c 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -313,3 +313,4 @@ df100399ed27d0eaa57c137ca99819a0fee66178 jdk9-b64
45ef73bb85c12ec1b291835c1d40e342a454e3f0 jdk9-b65
1232f4013417e4a9cd291096798d10f2e601d69d jdk9-b66
c9785bc8ade98a16a050d7520b70c68363857e00 jdk9-b67
+b5878b03d1b2e105917d959fbfa3c57c22495803 jdk9-b68
diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java
index 18ff8196bc7..a0329cf7744 100644
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java
@@ -68,6 +68,9 @@ class ContextFinder {
*/
private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
+ // previous value of JAXBContext.JAXB_CONTEXT_FACTORY, using also this to ensure backwards compatibility
+ private static final String JAXB_CONTEXT_FACTORY_DEPRECATED = "javax.xml.bind.context.factory";
+
private static final Logger logger;
static {
@@ -92,6 +95,14 @@ class ContextFinder {
}
}
+ private static ServiceLoaderUtil.ExceptionHandler EXCEPTION_HANDLER =
+ new ServiceLoaderUtil.ExceptionHandler() {
+ @Override
+ public JAXBException createException(Throwable throwable, String message) {
+ return new JAXBException(message, throwable);
+ }
+ };
+
/**
* If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped,
* throw the wrapped exception.
@@ -159,7 +170,10 @@ class ContextFinder {
}
}
- static JAXBContext newInstance(String contextPath, Class spFactory, ClassLoader classLoader, Map properties) throws JAXBException {
+ static JAXBContext newInstance(String contextPath,
+ Class spFactory,
+ ClassLoader classLoader,
+ Map properties) throws JAXBException {
try {
/*
@@ -239,6 +253,7 @@ class ContextFinder {
Map properties,
Class spFactory) throws JAXBException {
try {
+
Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
Object context = m.invoke(null, classes, properties);
if (!(context instanceof JAXBContext)) {
@@ -246,10 +261,10 @@ class ContextFinder {
throw handleClassCastException(context.getClass(), JAXBContext.class);
}
return (JAXBContext) context;
- } catch (NoSuchMethodException e) {
- throw new JAXBException(e);
- } catch (IllegalAccessException e) {
+
+ } catch (NoSuchMethodException | IllegalAccessException e) {
throw new JAXBException(e);
+
} catch (InvocationTargetException e) {
handleInvocationTargetException(e);
@@ -261,9 +276,10 @@ class ContextFinder {
}
}
- static JAXBContext find(String factoryId, String contextPath, ClassLoader classLoader, Map properties) throws JAXBException {
-
- // TODO: do we want/need another layer of searching in $java.home/lib/jaxb.properties like JAXP?
+ static JAXBContext find(String factoryId,
+ String contextPath,
+ ClassLoader classLoader,
+ Map properties) throws JAXBException {
StringTokenizer packages = new StringTokenizer(contextPath, ":");
if (!packages.hasMoreTokens()) {
@@ -275,63 +291,85 @@ class ContextFinder {
logger.fine("Searching jaxb.properties");
while (packages.hasMoreTokens()) {
// com.acme.foo - > com/acme/foo/jaxb.properties
- String className = classNameFromPackageProperties(factoryId, classLoader, packages.nextToken(":").replace('.', '/'));
- if (className != null) return newInstance(contextPath, className, classLoader, properties);
+ String factoryClassName =
+ classNameFromPackageProperties(
+ classLoader,
+ packages.nextToken(":").replace('.', '/'),
+ factoryId,
+ JAXB_CONTEXT_FACTORY_DEPRECATED);
+
+ if (factoryClassName != null) {
+ return newInstance(contextPath, factoryClassName, classLoader, properties);
+ }
}
String factoryName = classNameFromSystemProperties();
if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
- Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
+ JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader(
+ JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
+
+ if (obj != null) return obj.createContext(contextPath, classLoader, properties);
+
+ // to ensure backwards compatibility
+ factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
+ if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
+
+ Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader(
+ "javax.xml.bind.JAXBContext", logger);
+
if (ctxFactory != null) {
return newInstance(contextPath, ctxFactory, classLoader, properties);
}
- // TODO: SPEC change required! This is supposed to be!
- // JAXBContext obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER);
- // if (obj != null) return obj;
-
- // TODO: Deprecated - SPEC change required!
- factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader);
- if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties);
-
// else no provider found
logger.fine("Trying to create the platform default provider");
return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties);
}
- static JAXBContext find(Class[] classes, Map properties) throws JAXBException {
+ static JAXBContext find(Class>[] classes, Map properties) throws JAXBException {
// search for jaxb.properties in the class loader of each class first
logger.fine("Searching jaxb.properties");
for (final Class c : classes) {
// this classloader is used only to load jaxb.properties, so doing this should be safe.
- if (c.getPackage() == null) continue; // this is possible for primitives, arrays, and classes that are loaded by poorly implemented ClassLoaders
+ // this is possible for primitives, arrays, and classes that are
+ // loaded by poorly implemented ClassLoaders
+ if (c.getPackage() == null) continue;
// TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz
// classes from the same package might come from different class loades, so it might be a bad idea
// TODO: it's easier to look things up from the class
// c.getResourceAsStream("jaxb.properties");
- String className = classNameFromPackageProperties(JAXBContext.JAXB_CONTEXT_FACTORY, getClassClassLoader(c), c.getPackage().getName().replace('.', '/'));
- if (className != null) return newInstance(classes, properties, className);
+ String factoryClassName =
+ classNameFromPackageProperties(
+ getClassClassLoader(c),
+ c.getPackage().getName().replace('.', '/'),
+ JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED);
+
+ if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
}
- String factoryName = classNameFromSystemProperties();
- if (factoryName != null) return newInstance(classes, properties, factoryName);
+ String factoryClassName = classNameFromSystemProperties();
+ if (factoryClassName != null) return newInstance(classes, properties, factoryClassName);
- Class ctxFactoryClass = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
- if (ctxFactoryClass != null) {
- return newInstance(classes, properties, ctxFactoryClass);
- }
+ JAXBContextFactory factory =
+ ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
- // TODO: to be removed - deprecated!!! Requires SPEC change!!!
+ if (factory != null) return factory.createContext(classes, properties);
+
+ // to ensure backwards compatibility
String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader());
if (className != null) return newInstance(classes, properties, className);
- // // TODO: supposed to be:
- // obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER);
- // if (obj != null) return obj;
+ logger.fine("Trying to create the platform default provider");
+ Class ctxFactoryClass =
+ (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger);
+
+ if (ctxFactoryClass != null) {
+ return newInstance(classes, properties, ctxFactoryClass);
+ }
// else no provider found
logger.fine("Trying to create the platform default provider");
@@ -339,42 +377,69 @@ class ContextFinder {
}
- private static String classNameFromPackageProperties(String factoryId, ClassLoader classLoader, String packageName) throws JAXBException {
+ /**
+ * first factoryId should be the preffered one,
+ * more of those can be provided to support backwards compatibility
+ */
+ private static String classNameFromPackageProperties(ClassLoader classLoader,
+ String packageName,
+ String ... factoryIds) throws JAXBException {
+
String resourceName = packageName + "/jaxb.properties";
logger.log(Level.FINE, "Trying to locate {0}", resourceName);
Properties props = loadJAXBProperties(classLoader, resourceName);
if (props != null) {
- if (props.containsKey(factoryId)) {
- return props.getProperty(factoryId);
- } else {
- throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryId));
+ for(String factoryId : factoryIds) {
+ if (props.containsKey(factoryId)) {
+ return props.getProperty(factoryId);
+ }
}
+ throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0]));
}
return null;
}
private static String classNameFromSystemProperties() throws JAXBException {
- logger.log(Level.FINE, "Checking system property {0}", JAXBContext.JAXB_CONTEXT_FACTORY);
- // search for a system property second (javax.xml.bind.JAXBContext)
- String factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.JAXB_CONTEXT_FACTORY));
+
+ String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY);
+ if (factoryClassName != null) {
+ return factoryClassName;
+ }
+ // leave this here to assure compatibility
+ factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED);
+ if (factoryClassName != null) {
+ return factoryClassName;
+ }
+ // leave this here to assure compatibility
+ factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName());
if (factoryClassName != null) {
- logger.log(Level.FINE, " found {0}", factoryClassName);
return factoryClassName;
- } else { // leave this here to assure compatibility
- logger.fine(" not found");
- logger.log(Level.FINE, "Checking system property {0}", JAXBContext.class.getName());
- factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.class.getName()));
- if (factoryClassName != null) {
- logger.log(Level.FINE, " found {0}", factoryClassName);
- return factoryClassName;
- } else {
- logger.fine(" not found");
- }
}
return null;
}
- private static Properties loadJAXBProperties(ClassLoader classLoader, String propFileName) throws JAXBException {
+ private static String getDeprecatedSystemProperty(String property) {
+ String value = getSystemProperty(property);
+ if (value != null) {
+ logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.",
+ new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY});
+ }
+ return value;
+ }
+
+ private static String getSystemProperty(String property) {
+ logger.log(Level.FINE, "Checking system property {0}", property);
+ String value = AccessController.doPrivileged(new GetPropertyAction(property));
+ if (value != null) {
+ logger.log(Level.FINE, " found {0}", value);
+ } else {
+ logger.log(Level.FINE, " not found");
+ }
+ return value;
+ }
+
+ private static Properties loadJAXBProperties(ClassLoader classLoader,
+ String propFileName) throws JAXBException {
Properties props = null;
try {
@@ -480,17 +545,18 @@ class ContextFinder {
}
}
- // TODO: to be removed - SPEC change required
- // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead.
+ // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead.
@Deprecated
- static String firstByServiceLoaderDeprecated(Class spiClass, ClassLoader classLoader) throws JAXBException {
+ static String firstByServiceLoaderDeprecated(Class spiClass,
+ ClassLoader classLoader) throws JAXBException {
+
final String jaxbContextFQCN = spiClass.getName();
logger.fine("Searching META-INF/services");
// search META-INF services next
BufferedReader r = null;
- final String resource = new StringBuilder().append("META-INF/services/").append(jaxbContextFQCN).toString();
+ final String resource = "META-INF/services/" + jaxbContextFQCN;
try {
final InputStream resourceStream =
(classLoader == null) ?
@@ -510,9 +576,6 @@ class ContextFinder {
logger.log(Level.FINE, "Unable to load:{0}", resource);
return null;
}
- } catch (UnsupportedEncodingException e) {
- // should never happen
- throw new JAXBException(e);
} catch (IOException e) {
throw new JAXBException(e);
} finally {
diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java
index d5dc7bc4a5e..376b6738cb5 100644
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java
@@ -45,29 +45,20 @@ import java.io.InputStream;
* specialized forms of the method available:
*
*
- * - {@link #newInstance(String,ClassLoader) JAXBContext.newInstance( "com.acme.foo:com.acme.bar" )}
- * The JAXBContext instance is initialized from a list of colon
- * separated Java package names. Each java package contains
- * JAXB mapped classes, schema-derived classes and/or user annotated
- * classes. Additionally, the java package may contain JAXB package annotations
- * that must be processed. (see JLS, Section 7.4.1 "Named Packages").
- *
- * - {@link #newInstance(Class...) JAXBContext.newInstance( com.acme.foo.Foo.class )}
- * The JAXBContext instance is initialized with class(es)
- * passed as parameter(s) and classes that are statically reachable from
- * these class(es). See {@link #newInstance(Class...)} for details.
- *
+ * - {@link #newInstance(String, ClassLoader) JAXBContext.newInstance( "com.acme.foo:com.acme.bar" )}
+ * The JAXBContext instance is initialized from a list of colon
+ * separated Java package names. Each java package contains
+ * JAXB mapped classes, schema-derived classes and/or user annotated
+ * classes. Additionally, the java package may contain JAXB package annotations
+ * that must be processed. (see JLS, Section 7.4.1 "Named Packages").
+ *
+ * - {@link #newInstance(Class...) JAXBContext.newInstance( com.acme.foo.Foo.class )}
+ * The JAXBContext instance is initialized with class(es)
+ * passed as parameter(s) and classes that are statically reachable from
+ * these class(es). See {@link #newInstance(Class...)} for details.
+ *
*
*
- *
- * SPEC REQUIREMENT: the provider must supply an implementation
- * class containing the following method signatures:
- *
- *
{@code
- * public static JAXBContext createContext( String contextPath, ClassLoader classLoader, Map properties ) throws JAXBException
- * public static JAXBContext createContext( Class[] classes, Map properties ) throws JAXBException
- * }
- *
*
* The following JAXB 1.0 requirement is only required for schema to
* java interface/implementation binding. It does not apply to JAXB annotated
@@ -109,11 +100,11 @@ import java.io.InputStream;
* any of the schemas listed in the contextPath. For example:
*
*
- * JAXBContext jc = JAXBContext.newInstance( "com.acme.foo:com.acme.bar" );
- * Unmarshaller u = jc.createUnmarshaller();
- * FooObject fooObj = (FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
- * BarObject barObj = (BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
- * BazObject bazObj = (BazObject)u.unmarshal( new File( "baz.xml" ) ); // error, "com.acme.baz" not in contextPath
+ * JAXBContext jc = JAXBContext.newInstance( "com.acme.foo:com.acme.bar" );
+ * Unmarshaller u = jc.createUnmarshaller();
+ * FooObject fooObj = (FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
+ * BarObject barObj = (BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
+ * BazObject bazObj = (BazObject)u.unmarshal( new File( "baz.xml" ) ); // error, "com.acme.baz" not in contextPath
*
*
*
@@ -146,7 +137,7 @@ import java.io.InputStream;
* Section 4.2 Java Package of the specification.
*
*
- * SPEC REQUIREMENT: the provider must generate a class in each
+ * The provider must generate a class in each
* package that contains all of the necessary object factory methods for that
* package named ObjectFactory as well as the static
* newInstance( javaContentInterface ) method
@@ -214,6 +205,7 @@ import java.io.InputStream;
* by the following steps.
*
*
+ *
* -
* For each package/class explicitly passed in to the {@link #newInstance} method, in the order they are specified,
* jaxb.properties file is looked up in its package, by using the associated classloader —
@@ -223,7 +215,7 @@ import java.io.InputStream;
*
* If such a file is discovered, it is {@link Properties#load(InputStream) loaded} as a property file, and
* the value of the {@link #JAXB_CONTEXT_FACTORY} key will be assumed to be the provider factory class.
- * This class is then loaded by the associated classloader discussed above.
+ * This class is then loaded by the associated class loader discussed above.
*
*
* This phase of the look up allows some packages to force the use of a certain JAXB implementation.
@@ -234,10 +226,36 @@ import java.io.InputStream;
* factory class. This phase of the look up enables per-JVM override of the JAXB implementation.
*
*
-
- * Look for /META-INF/services/javax.xml.bind.JAXBContext file in the associated classloader.
- * This file follows the standard service descriptor convention, and if such a file exists, its content
- * is assumed to be the provider factory class. This phase of the look up is for automatic discovery.
- * It allows users to just put a JAXB implementation in a classpath and use it without any furhter configuration.
+ * Provider of {@link javax.xml.bind.JAXBContextFactory} is loaded using the service-provider loading
+ * facilities, defined by the {@link java.util.ServiceLoader} class, to attempt
+ * to locate and load an implementation of the service using the {@linkplain
+ * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}: the service-provider loading facility
+ * will use the {@linkplain java.lang.Thread#getContextClassLoader() current thread's context class loader}
+ * to attempt to load the context factory. If the context class loader is null, the
+ * {@linkplain ClassLoader#getSystemClassLoader() system class loader} will be used.
+ *
+ * In case of {@link java.util.ServiceConfigurationError service
+ * configuration error} a {@link javax.xml.bind.JAXBException} will be thrown.
+ *
+ *
+ * -
+ * Look for resource {@code /META-INF/services/javax.xml.bind.JAXBContext} using provided class loader.
+ * Methods without class loader parameter use {@code Thread.currentThread().getContextClassLoader()}.
+ * If such a resource exists, its content is assumed to be the provider factory class and must supply
+ * an implementation class containing the following method signatures:
+ *
+ *
+ *
+ * public static JAXBContext createContext(
+ * String contextPath,
+ * ClassLoader classLoader,
+ * Map<String,Object> properties throws JAXBException
+ *
+ * public static JAXBContext createContext(
+ * Class[] classes,
+ * Map<String,Object> properties ) throws JAXBException
+ *
+ * This configuration method is deprecated.
*
* -
* Finally, if all the steps above fail, then the rest of the look up is unspecified. That said,
@@ -246,17 +264,30 @@ import java.io.InputStream;
*
*
*
- * Once the provider factory class is discovered, its
- * public static JAXBContext createContext(String,ClassLoader,Map) method
- * (see {@link #newInstance(String, ClassLoader, Map)} for the parameter semantics.)
- * or public static JAXBContext createContet(Class[],Map) method
- * (see {@link #newInstance(Class[], Map)} for the parameter semantics) are invoked
+ * Once the provider factory class {@link javax.xml.bind.JAXBContextFactory} is discovered, one of its methods
+ * {@link javax.xml.bind.JAXBContextFactory#createContext(String, ClassLoader, java.util.Map)} or
+ * {@link javax.xml.bind.JAXBContextFactory#createContext(Class[], java.util.Map)} is invoked
* to create a {@link JAXBContext}.
*
- * @author
- Ryan Shoemaker, Sun Microsystems, Inc.
- Kohsuke Kawaguchi, Sun Microsystems, Inc.
- Joe Fialli, Sun Microsystems, Inc.
+ *
+ *
+ * @apiNote
+ * Service discovery method using file /META-INF/services/javax.xml.bind.JAXBContext (described in step 4)
+ * and leveraging provider's static methods is supported only to allow backwards compatibility, but it is strongly
+ * recommended to migrate to standard ServiceLoader mechanism (described in step 3).
+ *
+ * @implNote
+ * Within the last step, if Glassfish AS environment detected, its specific service loader is used to find factory class.
+ *
+ * @author
- Ryan Shoemaker, Sun Microsystems, Inc.
+ * - Kohsuke Kawaguchi, Sun Microsystems, Inc.
+ * - Joe Fialli, Sun Microsystems, Inc.
+ *
* @see Marshaller
* @see Unmarshaller
- * @see S 7.4.1 "Named Packages" in Java Language Specification
+ * @see S 7.4.1 "Named Packages"
+ * in Java Language Specification
+ *
* @since 1.6, JAXB 1.0
*/
public abstract class JAXBContext {
@@ -265,9 +296,7 @@ public abstract class JAXBContext {
* The name of the property that contains the name of the class capable
* of creating new JAXBContext objects.
*/
- public static final String JAXB_CONTEXT_FACTORY =
- "javax.xml.bind.context.factory";
-
+ public static final String JAXB_CONTEXT_FACTORY = "javax.xml.bind.JAXBContextFactory";
protected JAXBContext() {
}
@@ -275,7 +304,7 @@ public abstract class JAXBContext {
/**
*
- * Obtain a new instance of a JAXBContext class.
+ * Create a new instance of a JAXBContext class.
*
*
* This is a convenience method to invoke the
@@ -300,7 +329,7 @@ public abstract class JAXBContext {
/**
*
- * Obtain a new instance of a JAXBContext class.
+ * Create a new instance of a JAXBContext class.
*
*
* The client application must supply a context path which is a list of
@@ -396,7 +425,7 @@ public abstract class JAXBContext {
/**
*
- * Obtain a new instance of a JAXBContext class.
+ * Create a new instance of a JAXBContext class.
*
*
* This is mostly the same as {@link JAXBContext#newInstance(String, ClassLoader)},
@@ -425,8 +454,9 @@ public abstract class JAXBContext {
*
* @since 1.6, JAXB 2.0
*/
- public static JAXBContext newInstance( String contextPath, ClassLoader classLoader, Map properties )
- throws JAXBException {
+ public static JAXBContext newInstance( String contextPath,
+ ClassLoader classLoader,
+ Map properties ) throws JAXBException {
return ContextFinder.find(
/* The default property name according to the JAXB spec */
@@ -443,7 +473,7 @@ public abstract class JAXBContext {
// TODO: resurrect this once we introduce external annotations
// /**
// *
-// * Obtain a new instance of a JAXBContext class.
+// * Create a new instance of a JAXBContext class.
// *
// *
// * The client application must supply a list of classes that the new
@@ -479,7 +509,7 @@ public abstract class JAXBContext {
// * spec-defined classes will be returned.
// *
// * @return
-// * A new instance of a JAXBContext. Always non-null valid object.
+// * A new instance of a JAXBContext.
// *
// * @throws JAXBException
// * if an error was encountered while creating the
@@ -517,7 +547,7 @@ public abstract class JAXBContext {
/**
*
- * Obtain a new instance of a JAXBContext class.
+ * Create a new instance of a JAXBContext class.
*
*
* The client application must supply a list of classes that the new
@@ -559,7 +589,7 @@ public abstract class JAXBContext {
* spec-defined classes will be returned.
*
* @return
- * A new instance of a JAXBContext. Always non-null valid object.
+ * A new instance of a JAXBContext.
*
* @throws JAXBException
* if an error was encountered while creating the
@@ -578,7 +608,7 @@ public abstract class JAXBContext {
*
* @since 1.6, JAXB 2.0
*/
- public static JAXBContext newInstance( Class... classesToBeBound )
+ public static JAXBContext newInstance( Class> ... classesToBeBound )
throws JAXBException {
return newInstance(classesToBeBound,Collections.emptyMap());
@@ -586,7 +616,7 @@ public abstract class JAXBContext {
/**
*
- * Obtain a new instance of a JAXBContext class.
+ * Create a new instance of a JAXBContext class.
*
*
* An overloading of {@link JAXBContext#newInstance(Class...)}
@@ -605,7 +635,7 @@ public abstract class JAXBContext {
* in an empty map.
*
* @return
- * A new instance of a JAXBContext. Always non-null valid object.
+ * A new instance of a JAXBContext.
*
* @throws JAXBException
* if an error was encountered while creating the
@@ -624,7 +654,7 @@ public abstract class JAXBContext {
*
* @since 1.6, JAXB 2.0
*/
- public static JAXBContext newInstance( Class[] classesToBeBound, Map properties )
+ public static JAXBContext newInstance( Class>[] classesToBeBound, Map properties )
throws JAXBException {
if (classesToBeBound == null) {
@@ -756,9 +786,9 @@ public abstract class JAXBContext {
if (System.getSecurityManager() == null) {
return Thread.currentThread().getContextClassLoader();
} else {
- return (ClassLoader) java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public java.lang.Object run() {
+ return java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java
new file mode 100644
index 00000000000..9353f37ad3c
--- /dev/null
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.bind;
+
+import java.util.Map;
+
+/**
+ * Factory that creates new JAXBContext
instances.
+ *
+ * JAXBContextFactory can be located using {@link java.util.ServiceLoader#load(Class)}
+ *
+ * @since 1.9, JAXB 2.3
+ */
+public interface JAXBContextFactory {
+
+ /**
+ *
+ * Create a new instance of a JAXBContext class.
+ *
+ *
+ * For semantics see {@link javax.xml.bind.JAXBContext#newInstance(Class[], java.util.Map)}
+ *
+ * @param classesToBeBound
+ * list of java classes to be recognized by the new {@link JAXBContext}.
+ * Can be empty, in which case a {@link JAXBContext} that only knows about
+ * spec-defined classes will be returned.
+ * @param properties
+ * provider-specific properties. Can be null, which means the same thing as passing
+ * in an empty map.
+ *
+ * @return
+ * A new instance of a JAXBContext.
+ *
+ * @throws JAXBException
+ * if an error was encountered while creating the
+ * JAXBContext, such as (but not limited to):
+ *
+ * - Classes use JAXB annotations incorrectly
+ *
- Classes have colliding annotations (i.e., two classes with the same type name)
+ *
- The JAXB implementation was unable to locate
+ * provider-specific out-of-band information (such as additional
+ * files generated at the development time.)
+ *
+ *
+ * @throws IllegalArgumentException
+ * if the parameter contains {@code null} (i.e., {@code newInstance(null,someMap);})
+ *
+ * @since 1.9, JAXB 2.3
+ */
+ JAXBContext createContext(Class>[] classesToBeBound,
+ Map properties ) throws JAXBException;
+
+ /**
+ *
+ * Create a new instance of a JAXBContext class.
+ *
+ *
+ * For semantics see {@link javax.xml.bind.JAXBContext#newInstance(String, ClassLoader, java.util.Map)}
+ *
+ *
+ * The interpretation of properties is up to implementations. Implementations should
+ * throw JAXBException if it finds properties that it doesn't understand.
+ *
+ * @param contextPath list of java package names that contain schema derived classes
+ * @param classLoader
+ * This class loader will be used to locate the implementation classes.
+ * @param properties
+ * provider-specific properties. Can be null, which means the same thing as passing
+ * in an empty map.
+ *
+ * @return a new instance of a JAXBContext
+ * @throws JAXBException if an error was encountered while creating the
+ * JAXBContext such as
+ *
+ * - failure to locate either ObjectFactory.class or jaxb.index in the packages
+ * - an ambiguity among global elements contained in the contextPath
+ * - failure to locate a value for the context factory provider property
+ * - mixing schema derived packages from different providers on the same contextPath
+ *
+ * @since 1.9, JAXB 2.3
+ */
+ JAXBContext createContext(String contextPath,
+ ClassLoader classLoader,
+ Map properties ) throws JAXBException;
+
+}
diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java
index 159a7c13ca5..0efc25f2061 100644
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java
@@ -25,14 +25,9 @@
package javax.xml.bind;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.Iterator;
-import java.util.Properties;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -49,27 +44,27 @@ class ServiceLoaderUtil {
private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader";
private static final String OSGI_SERVICE_LOADER_METHOD_NAME = "lookupProviderClasses";
- static P firstByServiceLoader(Class
spiClass, Logger logger) {
+ static
P firstByServiceLoader(Class
spiClass,
+ Logger logger,
+ ExceptionHandler handler) throws T {
// service discovery
- ServiceLoader serviceLoader = ServiceLoader.load(spiClass);
- for (P impl : serviceLoader) {
- logger.fine("ServiceProvider loading Facility used; returning object [" + impl.getClass().getName() + "]");
- return impl;
+ try {
+ ServiceLoader
serviceLoader = ServiceLoader.load(spiClass);
+
+ for (P impl : serviceLoader) {
+ logger.fine("ServiceProvider loading Facility used; returning object [" +
+ impl.getClass().getName() + "]");
+
+ return impl;
+ }
+ } catch (Throwable t) {
+ throw handler.createException(t, "Error while searching for service [" + spiClass.getName() + "]");
}
return null;
}
- static boolean isOsgi(Logger logger) {
- try {
- Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
- return true;
- } catch (ClassNotFoundException ignored) {
- logger.log(Level.FINE, "OSGi classes not found, OSGi not available.", ignored);
- }
- return false;
- }
-
static Object lookupUsingOSGiServiceLoader(String factoryId, Logger logger) {
+
try {
// Use reflection to avoid having any dependendcy on ServiceLoader class
Class serviceClass = Class.forName(factoryId);
@@ -78,39 +73,22 @@ class ServiceLoaderUtil {
Iterator iter = ((Iterable) m.invoke(null, serviceClass)).iterator();
if (iter.hasNext()) {
Object next = iter.next();
- logger.fine("Found implementation using OSGi facility; returning object [" + next.getClass().getName() + "].");
+ logger.fine("Found implementation using OSGi facility; returning object [" +
+ next.getClass().getName() + "].");
return next;
} else {
return null;
}
- } catch (Exception ignored) {
+ } catch (IllegalAccessException |
+ InvocationTargetException |
+ ClassNotFoundException |
+ NoSuchMethodException ignored) {
+
logger.log(Level.FINE, "Unable to find from OSGi: [" + factoryId + "]", ignored);
return null;
}
}
- static String propertyFileLookup(final String configFullPath, final String factoryId) throws IOException {
- File f = new File(configFullPath);
- String factoryClassName = null;
- if (f.exists()) {
- Properties props = new Properties();
- FileInputStream stream = null;
- try {
- stream = new FileInputStream(f);
- props.load(stream);
- factoryClassName = props.getProperty(factoryId);
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException ignored) {
- }
- }
- }
- }
- return factoryClassName;
- }
-
static void checkPackageAccess(String className) {
// make sure that the current thread has an access to the package of the given name.
SecurityManager s = System.getSecurityManager();
@@ -130,18 +108,12 @@ class ServiceLoaderUtil {
}
}
- /**
- * Returns instance of required class. It checks package access (security) unless it is defaultClassname. It means if you
- * are trying to instantiate default implementation (fallback), pass the class name to both first and second parameter.
- *
- * @param className class to be instantiated
- * @param isDefaultClassname says whether default implementation class
- * @param handler exception handler - necessary for wrapping exceptions and logging
- * @param Type of exception being thrown (necessary to distinguish between Runtime and checked exceptions)
- * @return instantiated object or throws Runtime/checked exception, depending on ExceptionHandler's type
- * @throws T
- */
- static Object newInstance(String className, String defaultImplClassName, final ExceptionHandler handler) throws T {
+ // Returns instance of required class. It checks package access (security)
+ // unless it is defaultClassname. It means if you are trying to instantiate
+ // default implementation (fallback), pass the class name to both first and second parameter.
+ static Object newInstance(String className,
+ String defaultImplClassName,
+ final ExceptionHandler handler) throws T {
try {
return safeLoadClass(className, defaultImplClassName, contextClassLoader(handler)).newInstance();
} catch (ClassNotFoundException x) {
@@ -151,7 +123,10 @@ class ServiceLoaderUtil {
}
}
- static Class safeLoadClass(String className, String defaultImplClassName, ClassLoader classLoader) throws ClassNotFoundException {
+ static Class safeLoadClass(String className,
+ String defaultImplClassName,
+ ClassLoader classLoader) throws ClassNotFoundException {
+
try {
checkPackageAccess(className);
} catch (SecurityException se) {
@@ -165,16 +140,6 @@ class ServiceLoaderUtil {
return nullSafeLoadClass(className, classLoader);
}
- static String getJavaHomeLibConfigPath(String filename) {
- String javah = AccessController.doPrivileged(new PrivilegedAction() {
- @Override
- public String run() {
- return System.getProperty("java.home");
- }
- });
- return javah + File.separator + "lib" + File.separator + filename;
- }
-
static ClassLoader contextClassLoader(ExceptionHandler exceptionHandler) throws Exception {
try {
return Thread.currentThread().getContextClassLoader();
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 768fb1cb36b..412589019dd 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -310,3 +310,4 @@ fd3281c400347088b36aeb16273aa679d53a81a4 jdk9-b63
ed94f3e7ba6bbfec0772de6d24e39543e13f6d88 jdk9-b65
4fbcca8ab812198c7fb747ea7b213b6e404f36e9 jdk9-b66
1abd45df5480a04bff98fba1851d66a5230e67d4 jdk9-b67
+046fd17bb9a0cdf6681124866df9626d17b0516a jdk9-b68
diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk
index b0eb7e858db..ed40a831896 100644
--- a/jdk/make/lib/Lib-java.instrument.gmk
+++ b/jdk/make/lib/Lib-java.instrument.gmk
@@ -61,7 +61,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBINSTRUMENT_SRC), \
OPTIMIZATION := LOW, \
- CFLAGS := $(LIBINSTRUMENT_CFLAGS) $(CFLAGS_WARNINGS_ARE_ERRORS), \
+ CFLAGS := $(LIBINSTRUMENT_CFLAGS), \
CFLAGS_debug := -DJPLIS_LOGGING, \
CFLAGS_release := -DNO_JPLIS_LOGGING, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libinstrument/mapfile-vers, \
diff --git a/jdk/make/lib/Lib-java.management.gmk b/jdk/make/lib/Lib-java.management.gmk
index b0062445341..9f5aaaed3a9 100644
--- a/jdk/make/lib/Lib-java.management.gmk
+++ b/jdk/make/lib/Lib-java.management.gmk
@@ -50,7 +50,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBMANAGEMENT_SRC), \
OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(LIBMANAGEMENT_CFLAGS), \
+ CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_CFLAGS), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
diff --git a/jdk/make/lib/Lib-jdk.attach.gmk b/jdk/make/lib/Lib-jdk.attach.gmk
index dbabea5b733..d1bdd5e1bc0 100644
--- a/jdk/make/lib/Lib-jdk.attach.gmk
+++ b/jdk/make/lib/Lib-jdk.attach.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, 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
@@ -39,7 +39,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
+ CFLAGS := $(CFLAGS_JDKLIB) \
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.attach \
$(LIBJAVA_HEADER_FLAGS) $(LIBATTACH_CFLAGS), \
CFLAGS_windows := /Gy, \
diff --git a/jdk/make/lib/Lib-jdk.hprof.agent.gmk b/jdk/make/lib/Lib-jdk.hprof.agent.gmk
index 7c43331b33c..c6d1bbd1d04 100644
--- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk
+++ b/jdk/make/lib/Lib-jdk.hprof.agent.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, 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
@@ -31,7 +31,7 @@ BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof)
BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \
-I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo
-
+
BUILD_LIBHPROF_LDFLAGS :=
LIBHPROF_OPTIMIZATION := HIGHEST
@@ -46,7 +46,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBHPROF, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBHPROF_SRC), \
OPTIMIZATION := $(LIBHPROF_OPTIMIZATION), \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
+ CFLAGS := $(CFLAGS_JDKLIB) \
$(BUILD_LIBHPROF_CFLAGS), \
CFLAGS_debug := -DHPROF_LOGGING, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libhprof/mapfile-vers, \
@@ -75,7 +75,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA_CRW_DEMO, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAVA_CRW_DEMO_SRC), \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
+ CFLAGS := $(CFLAGS_JDKLIB) \
$(addprefix -I, $(LIBJAVA_CRW_DEMO_SRC)), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava_crw_demo/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk
index eb1de3b43c1..74d246f50d4 100644
--- a/jdk/make/lib/Lib-jdk.jdi.gmk
+++ b/jdk/make/lib/Lib-jdk.jdi.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, 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
@@ -44,7 +44,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBDT_SHMEM_SRC), \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) -DUSE_MMAP \
+ CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \
$(LIBDT_SHMEM_CPPFLAGS), \
LDFLAGS := $(LDFLAGS_JDKLIB), \
LDFLAGS_windows := -export:jdwpTransport_OnLoad, \
diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
index 0743ac85a97..03a1d3e3965 100644
--- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
+++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, 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
@@ -41,7 +41,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBDT_SOCKET_SRC), \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_CFLAGS_WARNINGS_ARE_ERRORS) -DUSE_MMAP \
+ CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \
$(LIBDT_SOCKET_CPPFLAGS), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
@@ -77,7 +77,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJDWP, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJDWP_SRC), \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) -DJDWP_LOGGING \
+ CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING \
$(LIBJDWP_CPPFLAGS) \
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.jdwp.agent, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjdwp/mapfile-vers, \
diff --git a/jdk/make/lib/Lib-jdk.management.gmk b/jdk/make/lib/Lib-jdk.management.gmk
index 84e71f7060c..8950738b453 100644
--- a/jdk/make/lib/Lib-jdk.management.gmk
+++ b/jdk/make/lib/Lib-jdk.management.gmk
@@ -59,7 +59,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT_EXT, \
SRC := $(LIBMANAGEMENT_EXT_SRC), \
LANG := C, \
OPTIMIZATION := $(LIBMANAGEMENT_EXT_OPTIMIZATION), \
- CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(LIBMANAGEMENT_EXT_CFLAGS), \
+ CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_EXT_CFLAGS), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement_ext/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
diff --git a/jdk/make/lib/Lib-jdk.sctp.gmk b/jdk/make/lib/Lib-jdk.sctp.gmk
index 15db8b3b380..dff84900595 100644
--- a/jdk/make/lib/Lib-jdk.sctp.gmk
+++ b/jdk/make/lib/Lib-jdk.sctp.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,8 @@ include LibCommon.gmk
ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
ifeq (, $(filter $(OPENJDK_TARGET_OS), macosx aix))
-
- # Suppress unused parameters required by exported JNI functions.
- SCTP_WERROR := -Werror -Wno-error=unused-parameter
- ifeq ($(OPENJDK_TARGET_CPU_ARCH), ppc)
- SCTP_WERROR :=
- endif
+ # DISABLED_WARNINGS_gcc := unused-parameter needed to
+ # suppress unused parameters required by exported JNI functions.
$(eval $(call SetupNativeCompilation,BUILD_LIBSCTP, \
LIBRARY := sctp, \
@@ -49,7 +45,7 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
$(LIBJAVA_HEADER_FLAGS) \
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.sctp \
-I$(SUPPORT_OUTPUTDIR)/headers/java.base, \
- CFLAGS_linux := $(SCTP_WERROR), \
+ DISABLED_WARNINGS_gcc := unused-parameter, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsctp/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
index cc406fa6e7a..855ac081431 100644
--- a/jdk/make/mapfiles/libjava/mapfile-vers
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
@@ -129,11 +129,11 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_defineClass0;
Java_java_lang_ClassLoader_defineClass1;
Java_java_lang_ClassLoader_defineClass2;
+ Java_java_lang_ClassLoader_findBuiltinLib;
Java_java_lang_ClassLoader_findLoadedClass0;
Java_java_lang_ClassLoader_00024NativeLibrary_find;
Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload;
- Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Double_longBitsToDouble;
Java_java_lang_Double_doubleToRawLongBits;
diff --git a/jdk/src/java.base/share/classes/java/io/FilePermission.java b/jdk/src/java.base/share/classes/java/io/FilePermission.java
index 0c5bcf35178..e3dc11f4eb5 100644
--- a/jdk/src/java.base/share/classes/java/io/FilePermission.java
+++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -27,11 +27,9 @@ package java.io;
import java.security.*;
import java.util.Enumeration;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Vector;
-import java.util.Collections;
import java.util.StringJoiner;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
import sun.security.util.SecurityConstants;
/**
@@ -288,7 +286,6 @@ public final class FilePermission extends Permission implements Serializable {
* @param path the pathname of the file/directory.
* @param mask the action mask to use.
*/
-
// package private for use by the FilePermissionCollection add method
FilePermission(String path, int mask) {
super(path);
@@ -315,6 +312,7 @@ public final class FilePermission extends Permission implements Serializable {
* null
and is implied by this object,
* false
otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof FilePermission))
return false;
@@ -387,6 +385,7 @@ public final class FilePermission extends Permission implements Serializable {
* pathname and actions as this FilePermission object,
* false
otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@@ -407,6 +406,7 @@ public final class FilePermission extends Permission implements Serializable {
*
* @return a hash code value for this object.
*/
+ @Override
public int hashCode() {
return 0;
}
@@ -587,6 +587,7 @@ public final class FilePermission extends Permission implements Serializable {
*
* @return the canonical string representation of the actions.
*/
+ @Override
public String getActions() {
if (actions == null)
actions = getActions(this.mask);
@@ -625,6 +626,7 @@ public final class FilePermission extends Permission implements Serializable {
* @return a new PermissionCollection object suitable for storing
* FilePermissions.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new FilePermissionCollection();
}
@@ -689,13 +691,13 @@ final class FilePermissionCollection extends PermissionCollection
implements Serializable
{
// Not serialized; see serialization section at end of class
- private transient List perms;
+ private transient ConcurrentHashMap perms;
/**
* Create an empty FilePermissionCollection object.
*/
public FilePermissionCollection() {
- perms = new ArrayList<>();
+ perms = new ConcurrentHashMap<>();
}
/**
@@ -710,6 +712,7 @@ final class FilePermissionCollection extends PermissionCollection
* @exception SecurityException - if this FilePermissionCollection object
* has been marked readonly
*/
+ @Override
public void add(Permission permission) {
if (! (permission instanceof FilePermission))
throw new IllegalArgumentException("invalid permission: "+
@@ -718,9 +721,31 @@ final class FilePermissionCollection extends PermissionCollection
throw new SecurityException(
"attempt to add a Permission to a readonly PermissionCollection");
- synchronized (this) {
- perms.add(permission);
- }
+ FilePermission fp = (FilePermission)permission;
+
+ // Add permission to map if it is absent, or replace with new
+ // permission if applicable. NOTE: cannot use lambda for
+ // remappingFunction parameter until JDK-8076596 is fixed.
+ perms.merge(fp.getName(), fp,
+ new java.util.function.BiFunction<>() {
+ @Override
+ public Permission apply(Permission existingVal,
+ Permission newVal) {
+ int oldMask = ((FilePermission)existingVal).getMask();
+ int newMask = ((FilePermission)newVal).getMask();
+ if (oldMask != newMask) {
+ int effective = oldMask | newMask;
+ if (effective == newMask) {
+ return newVal;
+ }
+ if (effective != oldMask) {
+ return new FilePermission(fp.getName(), effective);
+ }
+ }
+ return existingVal;
+ }
+ }
+ );
}
/**
@@ -732,26 +757,25 @@ final class FilePermissionCollection extends PermissionCollection
* @return true if "permission" is a proper subset of a permission in
* the set, false if not.
*/
+ @Override
public boolean implies(Permission permission) {
if (! (permission instanceof FilePermission))
return false;
- FilePermission fp = (FilePermission) permission;
+ FilePermission fperm = (FilePermission) permission;
- int desired = fp.getMask();
+ int desired = fperm.getMask();
int effective = 0;
int needed = desired;
- synchronized (this) {
- int len = perms.size();
- for (int i = 0; i < len; i++) {
- FilePermission x = (FilePermission) perms.get(i);
- if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) {
- effective |= x.getMask();
- if ((effective & desired) == desired)
- return true;
- needed = (desired ^ effective);
+ for (Permission perm : perms.values()) {
+ FilePermission fp = (FilePermission)perm;
+ if (((needed & fp.getMask()) != 0) && fp.impliesIgnoreMask(fperm)) {
+ effective |= fp.getMask();
+ if ((effective & desired) == desired) {
+ return true;
}
+ needed = (desired ^ effective);
}
}
return false;
@@ -763,11 +787,9 @@ final class FilePermissionCollection extends PermissionCollection
*
* @return an enumeration of all the FilePermission objects.
*/
+ @Override
public Enumeration elements() {
- // Convert Iterator into Enumeration
- synchronized (this) {
- return Collections.enumeration(perms);
- }
+ return perms.elements();
}
private static final long serialVersionUID = 2202956749081564585L;
@@ -795,10 +817,7 @@ final class FilePermissionCollection extends PermissionCollection
// Don't call out.defaultWriteObject()
// Write out Vector
- Vector permissions = new Vector<>(perms.size());
- synchronized (this) {
- permissions.addAll(perms);
- }
+ Vector permissions = new Vector<>(perms.values());
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", permissions);
@@ -819,7 +838,9 @@ final class FilePermissionCollection extends PermissionCollection
// Get the one we want
@SuppressWarnings("unchecked")
Vector permissions = (Vector)gfields.get("permissions", null);
- perms = new ArrayList<>(permissions.size());
- perms.addAll(permissions);
+ perms = new ConcurrentHashMap<>(permissions.size());
+ for (Permission perm : permissions) {
+ perms.put(perm.getName(), perm);
+ }
}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
index 295955847ca..2ba6f5d4f0d 100644
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
@@ -1702,7 +1702,6 @@ public abstract class ClassLoader {
native long find(String name);
native void unload(String name, boolean isBuiltin);
- static native String findBuiltinLib(String name);
public NativeLibrary(Class> fromClass, String name, boolean isBuiltin) {
this.name = name;
@@ -1861,9 +1860,11 @@ public abstract class ClassLoader {
throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
}
+ static native String findBuiltinLib(String name);
+
private static boolean loadLibrary0(Class> fromClass, final File file) {
// Check to see if we're attempting to access a static library
- String name = NativeLibrary.findBuiltinLib(file.getName());
+ String name = findBuiltinLib(file.getName());
boolean isBuiltin = (name != null);
if (!isBuiltin) {
name = AccessController.doPrivileged(
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java
index 11e452b96c9..13cf24ca0f2 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java
@@ -27,8 +27,6 @@ package java.lang.invoke;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
-import java.lang.reflect.Field;
-import sun.misc.Cleaner;
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
@@ -138,47 +136,9 @@ public class CallSite {
/**
* {@code CallSite} dependency context.
- * VM uses context class to store nmethod dependencies on the call site target.
- * Can be in 2 states: (a) null; or (b) {@code Cleaner} instance pointing to some Class instance.
- * Lazily initialized when CallSite instance is linked to some indy call site or VM needs
- * it to store dependencies. As a corollary, "null" context means there are no dependencies
- * registered yet. {@code Cleaner} is used in 2 roles:
- * (a) context class access for VM;
- * (b) stale context class cleanup.
- * {@code Cleaner} holds the context class until cleanup action is finished (see {@code PhantomReference}).
- * Though it's impossible to get the context class using {@code Reference.get()}, VM extracts it directly
- * from {@code Reference.referent} field.
+ * JVM uses CallSite.context to store nmethod dependencies on the call site target.
*/
- private volatile Cleaner context = null;
-
- /**
- * Default context.
- * VM uses it to initialize non-linked CallSite context.
- */
- private static class DefaultContext {}
- private static final Cleaner DEFAULT_CONTEXT = makeContext(DefaultContext.class, null);
-
- private static Cleaner makeContext(Class> referent, final CallSite holder) {
- return Cleaner.create(referent,
- new Runnable() {
- @Override public void run() {
- MethodHandleNatives.invalidateDependentNMethods(holder);
- }
- });
- }
-
- /** Initialize context class used for nmethod dependency tracking */
- /*package-private*/
- void initContext(Class> newContext) {
- // If there are concurrent actions, exactly one succeeds.
- if (context == null) {
- UNSAFE.compareAndSwapObject(this, CONTEXT_OFFSET, /*expected=*/null, makeContext(newContext, this));
- // No need to care about failed CAS attempt.
- // Since initContext is called from indy call site linkage in newContext class, there's no risk
- // that the context class becomes dead while corresponding context cleaner is alive (causing cleanup
- // action in the wrong context).
- }
- }
+ private final MethodHandleNatives.CallSiteContext context = MethodHandleNatives.CallSiteContext.make(this);
/**
* Returns the type of this call site's target.
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
index 3d3c47f689c..b53b44b99b1 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
@@ -30,6 +30,7 @@ import java.lang.reflect.Field;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+import sun.misc.Cleaner;
/**
* The JVM interface for the method handles package is all here.
@@ -61,8 +62,27 @@ class MethodHandleNatives {
static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
- /** Invalidate CallSite context: clean up dependent nmethods and reset call site context to initial state (null). */
- static native void invalidateDependentNMethods(CallSite site);
+ /** Represents a context to track nmethod dependencies on CallSite instance target. */
+ static class CallSiteContext implements Runnable {
+ //@Injected JVM_nmethodBucket* vmdependencies;
+
+ static CallSiteContext make(CallSite cs) {
+ final CallSiteContext newContext = new CallSiteContext();
+ // Cleaner is attached to CallSite instance and it clears native structures allocated for CallSite context.
+ // Though the CallSite can become unreachable, its Context is retained by the Cleaner instance (which is
+ // referenced from Cleaner class) until cleanup is performed.
+ Cleaner.create(cs, newContext);
+ return newContext;
+ }
+
+ @Override
+ public void run() {
+ MethodHandleNatives.clearCallSiteContext(this);
+ }
+ }
+
+ /** Invalidate all recorded nmethods. */
+ private static native void clearCallSiteContext(CallSiteContext context);
private static native void registerNatives();
static {
@@ -235,7 +255,6 @@ class MethodHandleNatives {
return Invokers.linkToTargetMethod(type);
} else {
appendixResult[0] = callSite;
- callSite.initContext(caller);
return Invokers.linkToCallSiteMethod(type);
}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java
index 7a39bae492d..980f365f098 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -36,6 +36,8 @@ public interface AnnotatedTypeVariable extends AnnotatedType {
/**
* Returns the potentially annotated bounds of this type variable.
+ * Note that if no bound is explicitly declared, the bound is unannotated
+ * {@code Object}.
*
* @return the potentially annotated bounds of this type variable
*/
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java
index 2d15f6c9770..650bd289f11 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -36,13 +36,18 @@ public interface AnnotatedWildcardType extends AnnotatedType {
/**
* Returns the potentially annotated lower bounds of this wildcard type.
+ * Note that if no lower bound is explicitly declared, the lower bound is the
+ * type of null. In this case, a zero length array is returned.
*
- * @return the potentially annotated lower bounds of this wildcard type
+ * @return the potentially annotated lower bounds of this wildcard type or
+ * an empty array if no lower bound is explicitly declared.
*/
AnnotatedType[] getAnnotatedLowerBounds();
/**
* Returns the potentially annotated upper bounds of this wildcard type.
+ * Note that if no upper bound is explicitly declared, the upper bound is
+ * unannotated {@code Object}
*
* @return the potentially annotated upper bounds of this wildcard type
*/
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java b/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java
index 39ffe4bf3c0..902fe70b42a 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -91,11 +91,11 @@ public interface TypeVariable extends Type, Annota
* Returns an array of AnnotatedType objects that represent the use of
* types to denote the upper bounds of the type parameter represented by
* this TypeVariable. The order of the objects in the array corresponds to
- * the order of the bounds in the declaration of the type parameter.
+ * the order of the bounds in the declaration of the type parameter. Note that
+ * if no upper bound is explicitly declared, the upper bound is unannotated
+ * {@code Object}.
*
- * Returns an array of length 0 if the type parameter declares no bounds.
- *
- * @return an array of objects representing the upper bounds of the type variable
+ * @return an array of objects representing the upper bound(s) of the type variable
* @since 1.8
*/
AnnotatedType[] getAnnotatedBounds();
diff --git a/jdk/src/java.base/share/classes/java/math/BigInteger.java b/jdk/src/java.base/share/classes/java/math/BigInteger.java
index 3690bea06b4..3b3cbf50739 100644
--- a/jdk/src/java.base/share/classes/java/math/BigInteger.java
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java
@@ -1963,6 +1963,43 @@ public class BigInteger extends Number implements Comparable {
* int array z. The contents of x are not changed.
*/
private static final int[] squareToLen(int[] x, int len, int[] z) {
+ int zlen = len << 1;
+ if (z == null || z.length < zlen)
+ z = new int[zlen];
+
+ // Execute checks before calling intrinsified method.
+ implSquareToLenChecks(x, len, z, zlen);
+ return implSquareToLen(x, len, z, zlen);
+ }
+
+ /**
+ * Parameters validation.
+ */
+ private static void implSquareToLenChecks(int[] x, int len, int[] z, int zlen) throws RuntimeException {
+ if (len < 1) {
+ throw new IllegalArgumentException("invalid input length: " + len);
+ }
+ if (len > x.length) {
+ throw new IllegalArgumentException("input length out of bound: " +
+ len + " > " + x.length);
+ }
+ if (len * 2 > z.length) {
+ throw new IllegalArgumentException("input length out of bound: " +
+ (len * 2) + " > " + z.length);
+ }
+ if (zlen < 1) {
+ throw new IllegalArgumentException("invalid input length: " + zlen);
+ }
+ if (zlen > z.length) {
+ throw new IllegalArgumentException("input length out of bound: " +
+ len + " > " + z.length);
+ }
+ }
+
+ /**
+ * Java Runtime may use intrinsic for this method.
+ */
+ private static final int[] implSquareToLen(int[] x, int len, int[] z, int zlen) {
/*
* The algorithm used here is adapted from Colin Plumb's C library.
* Technique: Consider the partial products in the multiplication
@@ -1997,9 +2034,6 @@ public class BigInteger extends Number implements Comparable {
* again. The low bit is simply a copy of the low bit of the
* input, so it doesn't need special care.
*/
- int zlen = len << 1;
- if (z == null || z.length < zlen)
- z = new int[zlen];
// Store the squares, right shifted one bit (i.e., divided by 2)
int lastProductLowWord = 0;
@@ -2857,6 +2891,32 @@ public class BigInteger extends Number implements Comparable {
* Multiply an array by one word k and add to result, return the carry
*/
static int mulAdd(int[] out, int[] in, int offset, int len, int k) {
+ implMulAddCheck(out, in, offset, len, k);
+ return implMulAdd(out, in, offset, len, k);
+ }
+
+ /**
+ * Parameters validation.
+ */
+ private static void implMulAddCheck(int[] out, int[] in, int offset, int len, int k) {
+ if (len > in.length) {
+ throw new IllegalArgumentException("input length is out of bound: " + len + " > " + in.length);
+ }
+ if (offset < 0) {
+ throw new IllegalArgumentException("input offset is invalid: " + offset);
+ }
+ if (offset > (out.length - 1)) {
+ throw new IllegalArgumentException("input offset is out of bound: " + offset + " > " + (out.length - 1));
+ }
+ if (len > (out.length - offset)) {
+ throw new IllegalArgumentException("input len is out of bound: " + len + " > " + (out.length - offset));
+ }
+ }
+
+ /**
+ * Java Runtime may use intrinsic for this method.
+ */
+ private static int implMulAdd(int[] out, int[] in, int offset, int len, int k) {
long kLong = k & LONG_MASK;
long carry = 0;
diff --git a/jdk/src/java.base/share/classes/java/net/SocketPermission.java b/jdk/src/java.base/share/classes/java/net/SocketPermission.java
index 52c71b0f7a3..eb046b7122a 100644
--- a/jdk/src/java.base/share/classes/java/net/SocketPermission.java
+++ b/jdk/src/java.base/share/classes/java/net/SocketPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -25,24 +25,24 @@
package java.net;
-import java.util.Enumeration;
-import java.util.Vector;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.StringJoiner;
-import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.io.Serializable;
import java.net.InetAddress;
+import java.security.AccessController;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.PrivilegedAction;
-import java.security.AccessController;
import java.security.Security;
-import java.io.Serializable;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.StringJoiner;
+import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentSkipListMap;
import sun.net.util.IPAddressUtil;
import sun.net.RegisteredDomain;
import sun.net.PortConfig;
@@ -832,6 +832,7 @@ public final class SocketPermission extends Permission
* @return true if the specified permission is implied by this object,
* false if not.
*/
+ @Override
public boolean implies(Permission p) {
int i,j;
@@ -1010,6 +1011,7 @@ public final class SocketPermission extends Permission
* SocketPermission object. However, port range will be ignored
* in the comparison if obj only contains the action, 'resolve'.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@@ -1069,7 +1071,7 @@ public final class SocketPermission extends Permission
*
* @return a hash code value for this object.
*/
-
+ @Override
public int hashCode() {
/*
* If this SocketPermission was initialized with an IP address
@@ -1137,6 +1139,7 @@ public final class SocketPermission extends Permission
*
* @return the canonical string representation of the actions.
*/
+ @Override
public String getActions()
{
if (actions == null)
@@ -1156,7 +1159,7 @@ public final class SocketPermission extends Permission
*
* @return a new PermissionCollection object suitable for storing SocketPermissions.
*/
-
+ @Override
public PermissionCollection newPermissionCollection() {
return new SocketPermissionCollection();
}
@@ -1320,15 +1323,16 @@ final class SocketPermissionCollection extends PermissionCollection
implements Serializable
{
// Not serialized; see serialization section at end of class
- private transient List perms;
+ // A ConcurrentSkipListMap is used to preserve order, so that most
+ // recently added permissions are checked first (see JDK-4301064).
+ private transient ConcurrentSkipListMap perms;
/**
* Create an empty SocketPermissions object.
*
*/
-
public SocketPermissionCollection() {
- perms = new ArrayList<>();
+ perms = new ConcurrentSkipListMap<>(new SPCComparator());
}
/**
@@ -1343,6 +1347,7 @@ final class SocketPermissionCollection extends PermissionCollection
* @exception SecurityException - if this SocketPermissionCollection object
* has been marked readonly
*/
+ @Override
public void add(Permission permission) {
if (! (permission instanceof SocketPermission))
throw new IllegalArgumentException("invalid permission: "+
@@ -1351,11 +1356,32 @@ final class SocketPermissionCollection extends PermissionCollection
throw new SecurityException(
"attempt to add a Permission to a readonly PermissionCollection");
- // optimization to ensure perms most likely to be tested
- // show up early (4301064)
- synchronized (this) {
- perms.add(0, (SocketPermission)permission);
- }
+ SocketPermission sp = (SocketPermission)permission;
+
+ // Add permission to map if it is absent, or replace with new
+ // permission if applicable. NOTE: cannot use lambda for
+ // remappingFunction parameter until JDK-8076596 is fixed.
+ perms.merge(sp.getName(), sp,
+ new java.util.function.BiFunction<>() {
+ @Override
+ public SocketPermission apply(SocketPermission existingVal,
+ SocketPermission newVal) {
+ int oldMask = existingVal.getMask();
+ int newMask = newVal.getMask();
+ if (oldMask != newMask) {
+ int effective = oldMask | newMask;
+ if (effective == newMask) {
+ return newVal;
+ }
+ if (effective != oldMask) {
+ return new SocketPermission(sp.getName(),
+ effective);
+ }
+ }
+ return existingVal;
+ }
+ }
+ );
}
/**
@@ -1367,7 +1393,7 @@ final class SocketPermissionCollection extends PermissionCollection
* @return true if "permission" is a proper subset of a permission in
* the collection, false if not.
*/
-
+ @Override
public boolean implies(Permission permission)
{
if (! (permission instanceof SocketPermission))
@@ -1379,18 +1405,15 @@ final class SocketPermissionCollection extends PermissionCollection
int effective = 0;
int needed = desired;
- synchronized (this) {
- int len = perms.size();
- //System.out.println("implies "+np);
- for (int i = 0; i < len; i++) {
- SocketPermission x = perms.get(i);
- //System.out.println(" trying "+x);
- if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) {
- effective |= x.getMask();
- if ((effective & desired) == desired)
- return true;
- needed = (desired ^ effective);
+ //System.out.println("implies "+np);
+ for (SocketPermission x : perms.values()) {
+ //System.out.println(" trying "+x);
+ if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) {
+ effective |= x.getMask();
+ if ((effective & desired) == desired) {
+ return true;
}
+ needed = (desired ^ effective);
}
}
return false;
@@ -1402,13 +1425,10 @@ final class SocketPermissionCollection extends PermissionCollection
*
* @return an enumeration of all the SocketPermission objects.
*/
-
+ @Override
@SuppressWarnings("unchecked")
public Enumeration elements() {
- // Convert Iterator into Enumeration
- synchronized (this) {
- return Collections.enumeration((List)(List)perms);
- }
+ return (Enumeration)Collections.enumeration(perms.values());
}
private static final long serialVersionUID = 2787186408602843674L;
@@ -1441,11 +1461,7 @@ final class SocketPermissionCollection extends PermissionCollection
// Don't call out.defaultWriteObject()
// Write out Vector
- Vector permissions = new Vector<>(perms.size());
-
- synchronized (this) {
- permissions.addAll(perms);
- }
+ Vector permissions = new Vector<>(perms.values());
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", permissions);
@@ -1466,7 +1482,22 @@ final class SocketPermissionCollection extends PermissionCollection
// Get the one we want
@SuppressWarnings("unchecked")
Vector permissions = (Vector)gfields.get("permissions", null);
- perms = new ArrayList<>(permissions.size());
- perms.addAll(permissions);
+ perms = new ConcurrentSkipListMap<>(new SPCComparator());
+ for (SocketPermission sp : permissions) {
+ perms.put(sp.getName(), sp);
+ }
+ }
+
+ /**
+ * A simple comparator that orders new non-equal entries at the beginning.
+ */
+ private static class SPCComparator implements Comparator {
+ @Override
+ public int compare(String s1, String s2) {
+ if (s1.equals(s2)) {
+ return 0;
+ }
+ return -1;
+ }
}
}
diff --git a/jdk/src/java.base/share/classes/java/security/BasicPermission.java b/jdk/src/java.base/share/classes/java/security/BasicPermission.java
index 92dbe345b26..fb5f2a260a3 100644
--- a/jdk/src/java.base/share/classes/java/security/BasicPermission.java
+++ b/jdk/src/java.base/share/classes/java/security/BasicPermission.java
@@ -25,15 +25,13 @@
package java.security;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Collections;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
/**
* The BasicPermission class extends the Permission class, and
@@ -165,6 +163,7 @@ public abstract class BasicPermission extends Permission
* @return true if the passed permission is equal to or
* implied by this permission, false otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if ((p == null) || (p.getClass() != getClass()))
return false;
@@ -200,6 +199,7 @@ public abstract class BasicPermission extends Permission
* @return true if {@code obj}'s class is the same as this object's class
* and has the same name as this BasicPermission object, false otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@@ -221,6 +221,7 @@ public abstract class BasicPermission extends Permission
*
* @return a hash code value for this object.
*/
+ @Override
public int hashCode() {
return this.getName().hashCode();
}
@@ -232,6 +233,7 @@ public abstract class BasicPermission extends Permission
*
* @return the empty string "".
*/
+ @Override
public String getActions() {
return "";
}
@@ -248,6 +250,7 @@ public abstract class BasicPermission extends Permission
* @return a new PermissionCollection object suitable for
* storing BasicPermissions.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new BasicPermissionCollection(this.getClass());
}
@@ -308,7 +311,7 @@ final class BasicPermissionCollection
* collection must be of the same type.
* Not serialized; see serialization section at end of class.
*/
- private transient Map perms;
+ private transient ConcurrentHashMap perms;
/**
* This is set to {@code true} if this BasicPermissionCollection
@@ -320,7 +323,7 @@ final class BasicPermissionCollection
/**
* The class to which all BasicPermissions in this
- * BasicPermissionCollection belongs.
+ * BasicPermissionCollection belong.
*
* @see #serialPersistentFields
*/
@@ -330,9 +333,8 @@ final class BasicPermissionCollection
* Create an empty BasicPermissionCollection object.
*
*/
-
public BasicPermissionCollection(Class> clazz) {
- perms = new HashMap<>(11);
+ perms = new ConcurrentHashMap<>(11);
all_allowed = false;
permClass = clazz;
}
@@ -352,6 +354,7 @@ final class BasicPermissionCollection
* @exception SecurityException - if this BasicPermissionCollection object
* has been marked readonly
*/
+ @Override
public void add(Permission permission) {
if (! (permission instanceof BasicPermission))
throw new IllegalArgumentException("invalid permission: "+
@@ -373,13 +376,12 @@ final class BasicPermissionCollection
permission);
}
- synchronized (this) {
- perms.put(bp.getCanonicalName(), permission);
- }
+ String canonName = bp.getCanonicalName();
+ perms.put(canonName, permission);
// No sync on all_allowed; staleness OK
if (!all_allowed) {
- if (bp.getCanonicalName().equals("*"))
+ if (canonName.equals("*"))
all_allowed = true;
}
}
@@ -393,6 +395,7 @@ final class BasicPermissionCollection
* @return true if "permission" is a proper subset of a permission in
* the set, false if not.
*/
+ @Override
public boolean implies(Permission permission) {
if (! (permission instanceof BasicPermission))
return false;
@@ -414,11 +417,7 @@ final class BasicPermissionCollection
String path = bp.getCanonicalName();
//System.out.println("check "+path);
- Permission x;
-
- synchronized (this) {
- x = perms.get(path);
- }
+ Permission x = perms.get(path);
if (x != null) {
// we have a direct hit!
@@ -435,9 +434,7 @@ final class BasicPermissionCollection
path = path.substring(0, last+1) + "*";
//System.out.println("check "+path);
- synchronized (this) {
- x = perms.get(path);
- }
+ x = perms.get(path);
if (x != null) {
return x.implies(permission);
@@ -456,11 +453,9 @@ final class BasicPermissionCollection
*
* @return an enumeration of all the BasicPermission objects.
*/
+ @Override
public Enumeration elements() {
- // Convert Iterator of Map values into an Enumeration
- synchronized (this) {
- return Collections.enumeration(perms.values());
- }
+ return perms.elements();
}
// Need to maintain serialization interoperability with earlier releases,
@@ -503,9 +498,7 @@ final class BasicPermissionCollection
Hashtable permissions =
new Hashtable<>(perms.size()*2);
- synchronized (this) {
- permissions.putAll(perms);
- }
+ permissions.putAll(perms);
// Write out serializable fields
ObjectOutputStream.PutField pfields = out.putFields();
@@ -533,7 +526,7 @@ final class BasicPermissionCollection
@SuppressWarnings("unchecked")
Hashtable permissions =
(Hashtable)gfields.get("permissions", null);
- perms = new HashMap<>(permissions.size()*2);
+ perms = new ConcurrentHashMap<>(permissions.size()*2);
perms.putAll(permissions);
// Get all_allowed
diff --git a/jdk/src/java.base/share/classes/java/security/CodeSource.java b/jdk/src/java.base/share/classes/java/security/CodeSource.java
index e05c68f9e49..afd3fffd05f 100644
--- a/jdk/src/java.base/share/classes/java/security/CodeSource.java
+++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -34,6 +34,7 @@ import java.util.Hashtable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.*;
+import sun.net.util.URLUtil;
/**
*
@@ -72,6 +73,15 @@ public class CodeSource implements java.io.Serializable {
// for generating cert paths
private transient CertificateFactory factory = null;
+ /**
+ * A String form of the URL for use as a key in HashMaps/Sets. The String
+ * form should be behave in the same manner as the URL when compared for
+ * equality in a HashMap/Set, except that no nameservice lookup is done
+ * on the hostname (only string comparison), and the fragment is not
+ * considered.
+ */
+ private transient String locationNoFragString;
+
/**
* Constructs a CodeSource and associates it with the specified
* location and set of certificates.
@@ -83,6 +93,9 @@ public class CodeSource implements java.io.Serializable {
*/
public CodeSource(URL url, java.security.cert.Certificate certs[]) {
this.location = url;
+ if (url != null) {
+ this.locationNoFragString = URLUtil.urlNoFragString(url);
+ }
// Copy the supplied certs
if (certs != null) {
@@ -102,6 +115,9 @@ public class CodeSource implements java.io.Serializable {
*/
public CodeSource(URL url, CodeSigner[] signers) {
this.location = url;
+ if (url != null) {
+ this.locationNoFragString = URLUtil.urlNoFragString(url);
+ }
// Copy the supplied signers
if (signers != null) {
@@ -168,6 +184,13 @@ public class CodeSource implements java.io.Serializable {
return this.location;
}
+ /**
+ * Returns a String form of the URL for use as a key in HashMaps/Sets.
+ */
+ String getLocationNoFragString() {
+ return locationNoFragString;
+ }
+
/**
* Returns the certificates associated with this CodeSource.
*
@@ -588,6 +611,10 @@ public class CodeSource implements java.io.Serializable {
} catch (IOException ioe) {
// no signers present
}
+
+ if (location != null) {
+ locationNoFragString = URLUtil.urlNoFragString(location);
+ }
}
/*
diff --git a/jdk/src/java.base/share/classes/java/security/Permissions.java b/jdk/src/java.base/share/classes/java/security/Permissions.java
index 56a5059351b..b9a834a40da 100644
--- a/jdk/src/java.base/share/classes/java/security/Permissions.java
+++ b/jdk/src/java.base/share/classes/java/security/Permissions.java
@@ -33,6 +33,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Iterator;
import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
import java.io.Serializable;
import java.io.ObjectStreamField;
import java.io.ObjectOutputStream;
@@ -85,7 +86,7 @@ implements Serializable
* Key is permissions Class, value is PermissionCollection for that class.
* Not serialized; see serialization section at end of class.
*/
- private transient Map, PermissionCollection> permsMap;
+ private transient ConcurrentHashMap, PermissionCollection> permsMap;
// optimization. keep track of whether unresolved permissions need to be
// checked
@@ -99,7 +100,7 @@ implements Serializable
* Creates a new Permissions object containing no PermissionCollections.
*/
public Permissions() {
- permsMap = new HashMap<>(11);
+ permsMap = new ConcurrentHashMap<>(11);
allPermission = null;
}
@@ -120,18 +121,14 @@ implements Serializable
*
* @see PermissionCollection#isReadOnly()
*/
-
+ @Override
public void add(Permission permission) {
if (isReadOnly())
throw new SecurityException(
"attempt to add a Permission to a readonly Permissions object");
- PermissionCollection pc;
-
- synchronized (this) {
- pc = getPermissionCollection(permission, true);
- pc.add(permission);
- }
+ PermissionCollection pc = getPermissionCollection(permission, true);
+ pc.add(permission);
// No sync; staleness -> optimizations delayed, which is OK
if (permission instanceof AllPermission) {
@@ -169,21 +166,19 @@ implements Serializable
* PermissionCollection it
* belongs to, false if not.
*/
-
+ @Override
public boolean implies(Permission permission) {
// No sync; staleness -> skip optimization, which is OK
if (allPermission != null) {
return true; // AllPermission has already been added
} else {
- synchronized (this) {
- PermissionCollection pc = getPermissionCollection(permission,
- false);
- if (pc != null) {
- return pc.implies(permission);
- } else {
- // none found
- return false;
- }
+ PermissionCollection pc = getPermissionCollection(permission,
+ false);
+ if (pc != null) {
+ return pc.implies(permission);
+ } else {
+ // none found
+ return false;
}
}
}
@@ -194,14 +189,12 @@ implements Serializable
*
* @return an enumeration of all the Permissions.
*/
-
+ @Override
public Enumeration elements() {
// go through each Permissions in the hash table
// and call their elements() function.
- synchronized (this) {
- return new PermissionsEnumerator(permsMap.values().iterator());
- }
+ return new PermissionsEnumerator(permsMap.values().iterator());
}
/**
@@ -236,34 +229,39 @@ implements Serializable
* It should be set to true when invoked from add().
*/
private PermissionCollection getPermissionCollection(Permission p,
- boolean createEmpty) {
+ boolean createEmpty) {
Class> c = p.getClass();
- PermissionCollection pc = permsMap.get(c);
-
if (!hasUnresolved && !createEmpty) {
- return pc;
- } else if (pc == null) {
-
- // Check for unresolved permissions
- pc = (hasUnresolved ? getUnresolvedPermissions(p) : null);
-
- // if still null, create a new collection
- if (pc == null && createEmpty) {
-
- pc = p.newPermissionCollection();
-
- // still no PermissionCollection?
- // We'll give them a PermissionsHash.
- if (pc == null)
- pc = new PermissionsHash();
- }
-
- if (pc != null) {
- permsMap.put(c, pc);
- }
+ return permsMap.get(c);
}
- return pc;
+
+ // Create and add permission collection to map if it is absent.
+ // NOTE: cannot use lambda for mappingFunction parameter until
+ // JDK-8076596 is fixed.
+ return permsMap.computeIfAbsent(c,
+ new java.util.function.Function<>() {
+ @Override
+ public PermissionCollection apply(Class> k) {
+ // Check for unresolved permissions
+ PermissionCollection pc =
+ (hasUnresolved ? getUnresolvedPermissions(p) : null);
+
+ // if still null, create a new collection
+ if (pc == null && createEmpty) {
+
+ pc = p.newPermissionCollection();
+
+ // still no PermissionCollection?
+ // We'll give them a PermissionsHash.
+ if (pc == null) {
+ pc = new PermissionsHash();
+ }
+ }
+ return pc;
+ }
+ }
+ );
}
/**
@@ -277,8 +275,6 @@ implements Serializable
*/
private PermissionCollection getUnresolvedPermissions(Permission p)
{
- // Called from within synchronized method so permsMap doesn't need lock
-
UnresolvedPermissionCollection uc =
(UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class);
@@ -362,9 +358,7 @@ implements Serializable
// Copy perms into a Hashtable
Hashtable, PermissionCollection> perms =
new Hashtable<>(permsMap.size()*2); // no sync; estimate
- synchronized (this) {
- perms.putAll(permsMap);
- }
+ perms.putAll(permsMap);
// Write out serializable fields
ObjectOutputStream.PutField pfields = out.putFields();
@@ -394,7 +388,7 @@ implements Serializable
@SuppressWarnings("unchecked")
Hashtable, PermissionCollection> perms =
(Hashtable, PermissionCollection>)gfields.get("perms", null);
- permsMap = new HashMap<>(perms.size()*2);
+ permsMap = new ConcurrentHashMap<>(perms.size()*2);
permsMap.putAll(perms);
// Set hasUnresolved
@@ -481,14 +475,13 @@ implements Serializable
* Key and value are (same) permissions objects.
* Not serialized; see serialization section at end of class.
*/
- private transient Map permsMap;
+ private transient ConcurrentHashMap permsMap;
/**
* Create an empty PermissionsHash object.
*/
-
PermissionsHash() {
- permsMap = new HashMap<>(11);
+ permsMap = new ConcurrentHashMap<>(11);
}
/**
@@ -496,11 +489,9 @@ implements Serializable
*
* @param permission the Permission object to add.
*/
-
+ @Override
public void add(Permission permission) {
- synchronized (this) {
- permsMap.put(permission, permission);
- }
+ permsMap.put(permission, permission);
}
/**
@@ -512,23 +503,21 @@ implements Serializable
* @return true if "permission" is a proper subset of a permission in
* the set, false if not.
*/
-
+ @Override
public boolean implies(Permission permission) {
// attempt a fast lookup and implies. If that fails
// then enumerate through all the permissions.
- synchronized (this) {
- Permission p = permsMap.get(permission);
+ Permission p = permsMap.get(permission);
- // If permission is found, then p.equals(permission)
- if (p == null) {
- for (Permission p_ : permsMap.values()) {
- if (p_.implies(permission))
- return true;
- }
- return false;
- } else {
- return true;
+ // If permission is found, then p.equals(permission)
+ if (p == null) {
+ for (Permission p_ : permsMap.values()) {
+ if (p_.implies(permission))
+ return true;
}
+ return false;
+ } else {
+ return true;
}
}
@@ -537,12 +526,9 @@ implements Serializable
*
* @return an enumeration of all the Permissions.
*/
-
+ @Override
public Enumeration elements() {
- // Convert Iterator of Map values into an Enumeration
- synchronized (this) {
- return Collections.enumeration(permsMap.values());
- }
+ return permsMap.elements();
}
private static final long serialVersionUID = -8491988220802933440L;
@@ -570,9 +556,7 @@ implements Serializable
// Copy perms into a Hashtable
Hashtable perms =
new Hashtable<>(permsMap.size()*2);
- synchronized (this) {
- perms.putAll(permsMap);
- }
+ perms.putAll(permsMap);
// Write out serializable fields
ObjectOutputStream.PutField pfields = out.putFields();
@@ -597,7 +581,7 @@ implements Serializable
@SuppressWarnings("unchecked")
Hashtable perms =
(Hashtable)gfields.get("perms", null);
- permsMap = new HashMap<>(perms.size()*2);
+ permsMap = new ConcurrentHashMap<>(perms.size()*2);
permsMap.putAll(perms);
}
}
diff --git a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java
index 41b84dbe683..dbcffe36136 100644
--- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java
@@ -47,10 +47,16 @@ public class SecureClassLoader extends ClassLoader {
*/
private final boolean initialized;
- // HashMap that maps CodeSource to ProtectionDomain
- // @GuardedBy("pdcache")
- private final HashMap pdcache =
- new HashMap<>(11);
+ /*
+ * HashMap that maps the CodeSource URL (as a String) to ProtectionDomain.
+ * We use a String instead of a CodeSource/URL as the key to avoid
+ * potential expensive name service lookups. This does mean that URLs that
+ * are equivalent after nameservice lookup will be placed in separate
+ * ProtectionDomains; however during policy enforcement these URLs will be
+ * canonicalized and resolved resulting in a consistent set of granted
+ * permissions.
+ */
+ private final HashMap pdcache = new HashMap<>(11);
private static final Debug debug = Debug.getInstance("scl");
@@ -196,16 +202,22 @@ public class SecureClassLoader extends ClassLoader {
* Returned cached ProtectionDomain for the specified CodeSource.
*/
private ProtectionDomain getProtectionDomain(CodeSource cs) {
- if (cs == null)
+ if (cs == null) {
return null;
+ }
ProtectionDomain pd = null;
synchronized (pdcache) {
- pd = pdcache.get(cs);
+ // Use a String form of the URL as the key. It should behave in the
+ // same manner as the URL when compared for equality except that no
+ // nameservice lookup is done on the hostname (String comparison
+ // only), and the fragment is not considered.
+ String key = cs.getLocationNoFragString();
+ pd = pdcache.get(key);
if (pd == null) {
PermissionCollection perms = getPermissions(cs);
pd = new ProtectionDomain(cs, perms, this, null);
- pdcache.put(cs, pd);
+ pdcache.put(key, pd);
if (debug != null) {
debug.println(" getPermissions "+ pd);
debug.println("");
diff --git a/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java b/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java
index 87ab32d54f9..5fdc3cbc8e0 100644
--- a/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java
+++ b/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -25,11 +25,13 @@
package java.security;
-import java.util.*;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* A UnresolvedPermissionCollection stores a collection
@@ -54,14 +56,14 @@ implements java.io.Serializable
* of the same type.
* Not serialized; see serialization section at end of class.
*/
- private transient Map> perms;
+ private transient ConcurrentHashMap> perms;
/**
* Create an empty UnresolvedPermissionCollection object.
*
*/
public UnresolvedPermissionCollection() {
- perms = new HashMap<>(11);
+ perms = new ConcurrentHashMap<>(11);
}
/**
@@ -70,25 +72,32 @@ implements java.io.Serializable
*
* @param permission the Permission object to add.
*/
-
- public void add(Permission permission)
- {
+ @Override
+ public void add(Permission permission) {
if (! (permission instanceof UnresolvedPermission))
throw new IllegalArgumentException("invalid permission: "+
permission);
UnresolvedPermission up = (UnresolvedPermission) permission;
- List v;
- synchronized (this) {
- v = perms.get(up.getName());
- if (v == null) {
- v = new ArrayList<>();
- perms.put(up.getName(), v);
+ // Add permission to map. NOTE: cannot use lambda for
+ // remappingFunction parameter until JDK-8076596 is fixed.
+ perms.compute(up.getName(),
+ new java.util.function.BiFunction<>() {
+ @Override
+ public List apply(String key,
+ List oldValue) {
+ if (oldValue == null) {
+ List v =
+ new CopyOnWriteArrayList<>();
+ v.add(up);
+ return v;
+ } else {
+ oldValue.add(up);
+ return oldValue;
+ }
+ }
}
- }
- synchronized (v) {
- v.add(up);
- }
+ );
}
/**
@@ -96,17 +105,15 @@ implements java.io.Serializable
* and return the List containing them.
*/
List getUnresolvedPermissions(Permission p) {
- synchronized (this) {
- return perms.get(p.getClass().getName());
- }
+ return perms.get(p.getClass().getName());
}
/**
* always returns false for unresolved permissions
*
*/
- public boolean implies(Permission permission)
- {
+ @Override
+ public boolean implies(Permission permission) {
return false;
}
@@ -116,18 +123,14 @@ implements java.io.Serializable
*
* @return an enumeration of all the UnresolvedPermission objects.
*/
-
+ @Override
public Enumeration elements() {
List results =
new ArrayList<>(); // where results are stored
// Get iterator of Map values (which are lists of permissions)
- synchronized (this) {
- for (List l : perms.values()) {
- synchronized (l) {
- results.addAll(l);
- }
- }
+ for (List l : perms.values()) {
+ results.addAll(l);
}
return Collections.enumeration(results);
@@ -164,19 +167,14 @@ implements java.io.Serializable
new Hashtable<>(perms.size()*2);
// Convert each entry (List) into a Vector
- synchronized (this) {
- Set>> set = perms.entrySet();
- for (Map.Entry> e : set) {
- // Convert list into Vector
- List list = e.getValue();
- Vector vec = new Vector<>(list.size());
- synchronized (list) {
- vec.addAll(list);
- }
+ Set>> set = perms.entrySet();
+ for (Map.Entry> e : set) {
+ // Convert list into Vector
+ List list = e.getValue();
+ Vector vec = new Vector<>(list);
- // Add to Hashtable being serialized
- permissions.put(e.getKey(), vec);
- }
+ // Add to Hashtable being serialized
+ permissions.put(e.getKey(), vec);
}
// Write out serializable fields
@@ -203,15 +201,14 @@ implements java.io.Serializable
Hashtable> permissions =
(Hashtable>)
gfields.get("permissions", null);
- perms = new HashMap<>(permissions.size()*2);
+ perms = new ConcurrentHashMap<>(permissions.size()*2);
// Convert each entry (Vector) into a List
Set>> set = permissions.entrySet();
for (Map.Entry> e : set) {
// Convert Vector into ArrayList
Vector vec = e.getValue();
- List list = new ArrayList<>(vec.size());
- list.addAll(vec);
+ List list = new CopyOnWriteArrayList<>(vec);
// Add to Hashtable being serialized
perms.put(e.getKey(), list);
diff --git a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java
index 4682ddee5d8..fbc0359ed37 100644
--- a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java
+++ b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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
@@ -60,11 +60,6 @@ final class DualPivotQuicksort {
*/
private static final int MAX_RUN_COUNT = 67;
- /**
- * The maximum length of run in merge sort.
- */
- private static final int MAX_RUN_LENGTH = 33;
-
/**
* If the length of an array to be sorted is less than this
* constant, Quicksort is used in preference to merge sort.
@@ -121,20 +116,24 @@ final class DualPivotQuicksort {
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
+ // Equal items in the beginning of the sequence
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break; // Sequence finishes with equal items
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]);
+ // Transform into an ascending sequence
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
+ }
+
+ // Merge a transformed descending sequence followed by an
+ // ascending sequence
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
}
/*
@@ -151,7 +150,7 @@ final class DualPivotQuicksort {
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
- } else if (count == 1) { // The array is already sorted
+ } else if (count <= 1) { // The array is already sorted
return;
}
@@ -569,20 +568,24 @@ final class DualPivotQuicksort {
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
+ // Equal items in the beginning of the sequence
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break; // Sequence finishes with equal items
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]);
+ // Transform into an ascending sequence
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
long t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
+ }
+
+ // Merge a transformed descending sequence followed by an
+ // ascending sequence
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
}
/*
@@ -599,7 +602,7 @@ final class DualPivotQuicksort {
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
- } else if (count == 1) { // The array is already sorted
+ } else if (count <= 1) { // The array is already sorted
return;
}
@@ -1053,20 +1056,24 @@ final class DualPivotQuicksort {
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
+ // Equal items in the beginning of the sequence
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break; // Sequence finishes with equal items
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]);
+ // Transform into an ascending sequence
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
short t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
+ }
+
+ // Merge a transformed descending sequence followed by an
+ // ascending sequence
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
}
/*
@@ -1083,7 +1090,7 @@ final class DualPivotQuicksort {
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
- } else if (count == 1) { // The array is already sorted
+ } else if (count <= 1) { // The array is already sorted
return;
}
@@ -1537,20 +1544,24 @@ final class DualPivotQuicksort {
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
+ // Equal items in the beginning of the sequence
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break; // Sequence finishes with equal items
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]);
+ // Transform into an ascending sequence
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
char t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
+ }
+
+ // Merge a transformed descending sequence followed by an
+ // ascending sequence
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
}
/*
@@ -1567,7 +1578,7 @@ final class DualPivotQuicksort {
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
- } else if (count == 1) { // The array is already sorted
+ } else if (count <= 1) { // The array is already sorted
return;
}
@@ -2117,20 +2128,24 @@ final class DualPivotQuicksort {
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
+ // Equal items in the beginning of the sequence
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break; // Sequence finishes with equal items
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]);
+ // Transform into an ascending sequence
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
float t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
+ }
+
+ // Merge a transformed descending sequence followed by an
+ // ascending sequence
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
}
/*
@@ -2147,7 +2162,7 @@ final class DualPivotQuicksort {
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
- } else if (count == 1) { // The array is already sorted
+ } else if (count <= 1) { // The array is already sorted
return;
}
@@ -2656,20 +2671,24 @@ final class DualPivotQuicksort {
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
+ // Equal items in the beginning of the sequence
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break; // Sequence finishes with equal items
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
while (++k <= right && a[k - 1] >= a[k]);
+ // Transform into an ascending sequence
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
double t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
+ }
+
+ // Merge a transformed descending sequence followed by an
+ // ascending sequence
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
}
/*
@@ -2686,7 +2705,7 @@ final class DualPivotQuicksort {
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
- } else if (count == 1) { // The array is already sorted
+ } else if (count <= 1) { // The array is already sorted
return;
}
diff --git a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java
index 7e818a90b64..329e0f94232 100644
--- a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java
+++ b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -25,18 +25,15 @@
package java.util;
-import java.io.Serializable;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.io.Serializable;
import java.security.*;
-import java.util.Map;
-import java.util.HashMap;
import java.util.Enumeration;
import java.util.Hashtable;
-import java.util.Collections;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
import sun.security.util.SecurityConstants;
/**
@@ -161,6 +158,16 @@ public final class PropertyPermission extends BasicPermission {
init(getMask(actions));
}
+ /**
+ * Creates a PropertyPermission object with the specified name and
+ * a pre-calculated mask. Avoids the overhead of re-computing the mask.
+ * Called by PropertyPermissionCollection.
+ */
+ PropertyPermission(String name, int mask) {
+ super(name, getActions(mask));
+ this.mask = mask;
+ }
+
/**
* Checks if this PropertyPermission object "implies" the specified
* permission.
@@ -178,6 +185,7 @@ public final class PropertyPermission extends BasicPermission {
* @return true if the specified permission is implied by this object,
* false if not.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof PropertyPermission))
return false;
@@ -198,6 +206,7 @@ public final class PropertyPermission extends BasicPermission {
* @return true if obj is a PropertyPermission, and has the same name and
* actions as this PropertyPermission object.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@@ -219,6 +228,7 @@ public final class PropertyPermission extends BasicPermission {
*
* @return a hash code value for this object.
*/
+ @Override
public int hashCode() {
return this.getName().hashCode();
}
@@ -345,6 +355,7 @@ public final class PropertyPermission extends BasicPermission {
*
* @return the canonical string representation of the actions.
*/
+ @Override
public String getActions() {
if (actions == null)
actions = getActions(this.mask);
@@ -369,6 +380,7 @@ public final class PropertyPermission extends BasicPermission {
* @return a new PermissionCollection object suitable for storing
* PropertyPermissions.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new PropertyPermissionCollection();
}
@@ -425,7 +437,7 @@ final class PropertyPermissionCollection extends PermissionCollection
* Key is property name; value is PropertyPermission.
* Not serialized; see serialization section at end of class.
*/
- private transient Map perms;
+ private transient ConcurrentHashMap perms;
/**
* Boolean saying if "*" is in the collection.
@@ -439,7 +451,7 @@ final class PropertyPermissionCollection extends PermissionCollection
* Create an empty PropertyPermissionCollection object.
*/
public PropertyPermissionCollection() {
- perms = new HashMap<>(32); // Capacity for default policy
+ perms = new ConcurrentHashMap<>(32); // Capacity for default policy
all_allowed = false;
}
@@ -455,6 +467,7 @@ final class PropertyPermissionCollection extends PermissionCollection
* @exception SecurityException - if this PropertyPermissionCollection
* object has been marked readonly
*/
+ @Override
public void add(Permission permission) {
if (! (permission instanceof PropertyPermission))
throw new IllegalArgumentException("invalid permission: "+
@@ -466,21 +479,30 @@ final class PropertyPermissionCollection extends PermissionCollection
PropertyPermission pp = (PropertyPermission) permission;
String propName = pp.getName();
- synchronized (this) {
- PropertyPermission existing = perms.get(propName);
+ // Add permission to map if it is absent, or replace with new
+ // permission if applicable. NOTE: cannot use lambda for
+ // remappingFunction parameter until JDK-8076596 is fixed.
+ perms.merge(propName, pp,
+ new java.util.function.BiFunction<>() {
+ @Override
+ public PropertyPermission apply(PropertyPermission existingVal,
+ PropertyPermission newVal) {
- if (existing != null) {
- int oldMask = existing.getMask();
- int newMask = pp.getMask();
- if (oldMask != newMask) {
- int effective = oldMask | newMask;
- String actions = PropertyPermission.getActions(effective);
- perms.put(propName, new PropertyPermission(propName, actions));
+ int oldMask = existingVal.getMask();
+ int newMask = newVal.getMask();
+ if (oldMask != newMask) {
+ int effective = oldMask | newMask;
+ if (effective == newMask) {
+ return newVal;
+ }
+ if (effective != oldMask) {
+ return new PropertyPermission(propName, effective);
+ }
+ }
+ return existingVal;
}
- } else {
- perms.put(propName, pp);
}
- }
+ );
if (!all_allowed) {
if (propName.equals("*"))
@@ -497,9 +519,10 @@ final class PropertyPermissionCollection extends PermissionCollection
* @return true if "permission" is a proper subset of a permission in
* the set, false if not.
*/
+ @Override
public boolean implies(Permission permission) {
if (! (permission instanceof PropertyPermission))
- return false;
+ return false;
PropertyPermission pp = (PropertyPermission) permission;
PropertyPermission x;
@@ -509,9 +532,7 @@ final class PropertyPermissionCollection extends PermissionCollection
// short circuit if the "*" Permission was added
if (all_allowed) {
- synchronized (this) {
- x = perms.get("*");
- }
+ x = perms.get("*");
if (x != null) {
effective |= x.getMask();
if ((effective & desired) == desired)
@@ -526,9 +547,7 @@ final class PropertyPermissionCollection extends PermissionCollection
String name = pp.getName();
//System.out.println("check "+name);
- synchronized (this) {
- x = perms.get(name);
- }
+ x = perms.get(name);
if (x != null) {
// we have a direct hit!
@@ -546,9 +565,7 @@ final class PropertyPermissionCollection extends PermissionCollection
name = name.substring(0, last+1) + "*";
//System.out.println("check "+name);
- synchronized (this) {
- x = perms.get(name);
- }
+ x = perms.get(name);
if (x != null) {
effective |= x.getMask();
@@ -569,16 +586,14 @@ final class PropertyPermissionCollection extends PermissionCollection
*
* @return an enumeration of all the PropertyPermission objects.
*/
+ @Override
@SuppressWarnings("unchecked")
public Enumeration elements() {
- // Convert Iterator of Map values into an Enumeration
- synchronized (this) {
- /**
- * Casting to rawtype since Enumeration
- * cannot be directly cast to Enumeration
- */
- return (Enumeration)Collections.enumeration(perms.values());
- }
+ /**
+ * Casting to rawtype since Enumeration
+ * cannot be directly cast to Enumeration
+ */
+ return (Enumeration)perms.elements();
}
private static final long serialVersionUID = 7015263904581634791L;
@@ -616,9 +631,7 @@ final class PropertyPermissionCollection extends PermissionCollection
// Copy perms into a Hashtable
Hashtable permissions =
new Hashtable<>(perms.size()*2);
- synchronized (this) {
- permissions.putAll(perms);
- }
+ permissions.putAll(perms);
// Write out serializable fields
ObjectOutputStream.PutField pfields = out.putFields();
@@ -646,7 +659,7 @@ final class PropertyPermissionCollection extends PermissionCollection
@SuppressWarnings("unchecked")
Hashtable permissions =
(Hashtable)gfields.get("permissions", null);
- perms = new HashMap<>(permissions.size()*2);
+ perms = new ConcurrentHashMap<>(permissions.size()*2);
perms.putAll(permissions);
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
index 5ebd04923d4..b59042653e7 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
@@ -780,7 +780,9 @@ public class LinkedTransferQueue extends AbstractQueue
}
/**
- * Version of firstOfMode used by Spliterator
+ * Version of firstOfMode used by Spliterator. Callers must
+ * recheck if the returned node's item field is null or
+ * self-linked before using.
*/
final Node firstDataNode() {
for (Node p = head; p != null;) {
@@ -953,11 +955,12 @@ public class LinkedTransferQueue extends AbstractQueue
Object[] a = new Object[n];
int i = 0;
do {
- if ((a[i] = p.item) != null)
+ Object e = p.item;
+ if (e != p && (a[i] = e) != null)
++i;
if (p == (p = p.next))
p = q.firstDataNode();
- } while (p != null && i < n);
+ } while (p != null && i < n && p.isData);
if ((current = p) == null)
exhausted = true;
if (i > 0) {
@@ -980,11 +983,11 @@ public class LinkedTransferQueue extends AbstractQueue
exhausted = true;
do {
Object e = p.item;
+ if (e != null && e != p)
+ action.accept((E)e);
if (p == (p = p.next))
p = q.firstDataNode();
- if (e != null)
- action.accept((E)e);
- } while (p != null);
+ } while (p != null && p.isData);
}
}
@@ -997,10 +1000,11 @@ public class LinkedTransferQueue extends AbstractQueue
((p = current) != null || (p = q.firstDataNode()) != null)) {
Object e;
do {
- e = p.item;
+ if ((e = p.item) == p)
+ e = null;
if (p == (p = p.next))
p = q.firstDataNode();
- } while (e == null && p != null);
+ } while (e == null && p != null && p.isData);
if ((current = p) == null)
exhausted = true;
if (e != null) {
diff --git a/jdk/src/java.base/share/classes/sun/misc/ExtensionDependency.java b/jdk/src/java.base/share/classes/sun/misc/ExtensionDependency.java
deleted file mode 100644
index 97c9480efd8..00000000000
--- a/jdk/src/java.base/share/classes/sun/misc/ExtensionDependency.java
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.Enumeration;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-import java.net.URL;
-import java.net.MalformedURLException;
-import sun.net.www.ParseUtil;
-
-/**
- * This class checks dependent extensions a particular jar file may have
- * declared through its manifest attributes.
- *
- * Jar file declared dependent extensions through the extension-list
- * attribute. The extension-list contains a list of keys used to
- * fetch the other attributes describing the required extension.
- * If key is the extension key declared in the extension-list
- * attribute, the following describing attribute can be found in
- * the manifest:
- *
- * - key-Extension-Name: (Specification package name)
- * - key-Specification-Version: (Specification-Version)
- * - key-Implementation-Version: (Implementation-Version)
- * - key-Implementation-Vendor-Id: (Imlementation-Vendor-Id)
- * - key-Implementation-Version: (Implementation version)
- * - key-Implementation-URL: (URL to download the requested extension)
- *
- *
- * This class also maintain versioning consistency of installed
- * extensions dependencies declared in jar file manifest.
- *
- * @deprecated this class will be removed in a future release.
- * @author Jerome Dochez
- */
-@Deprecated
-public class ExtensionDependency {
-
- /* Callbak interfaces to delegate installation of missing extensions */
- private static Vector providers;
-
- /**
- * Register an ExtensionInstallationProvider. The provider is responsible
- * for handling the installation (upgrade) of any missing extensions.
- *
- * @param eip ExtensionInstallationProvider implementation
- */
- public synchronized static void addExtensionInstallationProvider
- (ExtensionInstallationProvider eip)
- {
- if (providers == null) {
- providers = new Vector<>();
- }
- providers.add(eip);
- }
-
- /**
- * Unregister a previously installed installation provider
- */
- public synchronized static void removeExtensionInstallationProvider
- (ExtensionInstallationProvider eip)
- {
- providers.remove(eip);
- }
-
- /**
- * Checks the dependencies of the jar file on installed extension.
- *
- * @param jar containing the attributes declaring the dependencies
- */
- public static boolean checkExtensionsDependencies(JarFile jar)
- {
- if (providers == null) {
- // no need to bother, nobody is registered to install missing
- // extensions
- return true;
- }
-
- try {
- ExtensionDependency extDep = new ExtensionDependency();
- return extDep.checkExtensions(jar);
- } catch (ExtensionInstallationException e) {
- debug(e.getMessage());
- }
- return false;
- }
-
- /*
- * Check for all declared required extensions in the jar file
- * manifest.
- */
- protected boolean checkExtensions(JarFile jar)
- throws ExtensionInstallationException
- {
- Manifest man;
- try {
- man = jar.getManifest();
- } catch (IOException e) {
- return false;
- }
-
- if (man == null) {
- // The applet does not define a manifest file, so
- // we just assume all dependencies are satisfied.
- return true;
- }
-
- boolean result = true;
- Attributes attr = man.getMainAttributes();
- if (attr != null) {
- // Let's get the list of declared dependencies
- String value = attr.getValue(Name.EXTENSION_LIST);
- if (value != null) {
- StringTokenizer st = new StringTokenizer(value);
- // Iterate over all declared dependencies
- while (st.hasMoreTokens()) {
- String extensionName = st.nextToken();
- debug("The file " + jar.getName() +
- " appears to depend on " + extensionName);
- // Sanity Check
- String extName = extensionName + "-" +
- Name.EXTENSION_NAME.toString();
- if (attr.getValue(extName) == null) {
- debug("The jar file " + jar.getName() +
- " appers to depend on "
- + extensionName + " but does not define the " +
- extName + " attribute in its manifest ");
-
- } else {
- if (!checkExtension(extensionName, attr)) {
- debug("Failed installing " + extensionName);
- result = false;
- }
- }
- }
- } else {
- debug("No dependencies for " + jar.getName());
- }
- }
- return result;
- }
-
-
- /*
- * Check that a particular dependency on an extension is satisfied.
- *
- * @param extensionName is the key used for the attributes in the manifest
- * @param attr is the attributes of the manifest file
- *
- * @return true if the dependency is satisfied by the installed extensions
- */
- protected synchronized boolean checkExtension(final String extensionName,
- final Attributes attr)
- throws ExtensionInstallationException
- {
- debug("Checking extension " + extensionName);
- if (checkExtensionAgainstInstalled(extensionName, attr))
- return true;
-
- debug("Extension not currently installed ");
- ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
- return installExtension(reqInfo, null);
- }
-
- /*
- * Check if a particular extension is part of the currently installed
- * extensions.
- *
- * @param extensionName is the key for the attributes in the manifest
- * @param attr is the attributes of the manifest
- *
- * @return true if the requested extension is already installed
- */
- boolean checkExtensionAgainstInstalled(String extensionName,
- Attributes attr)
- throws ExtensionInstallationException
- {
- File fExtension = checkExtensionExists(extensionName);
-
- if (fExtension != null) {
- // Extension already installed, just check against this one
- try {
- if (checkExtensionAgainst(extensionName, attr, fExtension))
- return true;
- } catch (FileNotFoundException e) {
- debugException(e);
- } catch (IOException e) {
- debugException(e);
- }
- return false;
-
- } else {
- // Not sure if extension is already installed, so check all the
- // installed extension jar files to see if we get a match
-
- File[] installedExts;
-
- try {
- // Get the list of installed extension jar files so we can
- // compare the installed versus the requested extension
- installedExts = getInstalledExtensions();
- } catch(IOException e) {
- debugException(e);
- return false;
- }
-
- for (int i=0;i() {
- public Manifest run()
- throws IOException, FileNotFoundException {
- if (!file.exists())
- throw new FileNotFoundException(file.getName());
- JarFile jarFile = new JarFile(file);
- return jarFile.getManifest();
- }
- });
- } catch(PrivilegedActionException e) {
- if (e.getException() instanceof FileNotFoundException)
- throw (FileNotFoundException) e.getException();
- throw (IOException) e.getException();
- }
-
- // Construct the extension information object
- ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr);
- debug("Requested Extension : " + reqInfo);
-
- int isCompatible = ExtensionInfo.INCOMPATIBLE;
- ExtensionInfo instInfo = null;
-
- if (man != null) {
- Attributes instAttr = man.getMainAttributes();
- if (instAttr != null) {
- instInfo = new ExtensionInfo(null, instAttr);
- debug("Extension Installed " + instInfo);
- isCompatible = instInfo.isCompatibleWith(reqInfo);
- switch(isCompatible) {
- case ExtensionInfo.COMPATIBLE:
- debug("Extensions are compatible");
- return true;
-
- case ExtensionInfo.INCOMPATIBLE:
- debug("Extensions are incompatible");
- return false;
-
- default:
- // everything else
- debug("Extensions require an upgrade or vendor switch");
- return installExtension(reqInfo, instInfo);
-
- }
- }
- }
- return false;
- }
-
- /*
- * An required extension is missing, if an ExtensionInstallationProvider is
- * registered, delegate the installation of that particular extension to it.
- *
- * @param reqInfo Missing extension information
- * @param instInfo Older installed version information
- *
- * @return true if the installation is successful
- */
- protected boolean installExtension(ExtensionInfo reqInfo,
- ExtensionInfo instInfo)
- throws ExtensionInstallationException
- {
- Vector currentProviders;
- synchronized(providers) {
- @SuppressWarnings("unchecked")
- Vector tmp =
- (Vector) providers.clone();
- currentProviders = tmp;
- }
- for (Enumeration e = currentProviders.elements();
- e.hasMoreElements();) {
- ExtensionInstallationProvider eip = e.nextElement();
-
- if (eip!=null) {
- // delegate the installation to the provider
- if (eip.installExtension(reqInfo, instInfo)) {
- debug(reqInfo.name + " installation successful");
- Launcher.ExtClassLoader cl = (Launcher.ExtClassLoader)
- Launcher.getLauncher().getClassLoader().getParent();
- addNewExtensionsToClassLoader(cl);
- return true;
- }
- }
- }
- // We have tried all of our providers, noone could install this
- // extension, we just return failure at this point
- debug(reqInfo.name + " installation failed");
- return false;
- }
-
- /**
- * Checks if the extension, that is specified in the extension-list in
- * the applet jar manifest, is already installed (i.e. exists in the
- * extension directory).
- *
- * @param extensionName extension name in the extension-list
- *
- * @return the extension if it exists in the extension directory
- */
- private File checkExtensionExists(String extensionName) {
- // Function added to fix bug 4504166
- final String extName = extensionName;
- final String[] fileExt = {".jar", ".zip"};
-
- return AccessController.doPrivileged(
- new PrivilegedAction() {
- public File run() {
- try {
- File fExtension;
- File[] dirs = getExtDirs();
-
- // Search the extension directories for the extension that is specified
- // in the attribute extension-list in the applet jar manifest
- for (int i=0;i urls = new Vector();
- for (int i = 0; i < dirs.length; i++) {
- String[] files = dirs[i].list(new JarFilter());
- if (files != null) {
- debug("getExtFiles files.length " + files.length);
- for (int j = 0; j < files.length; j++) {
- File f = new File(dirs[i], files[j]);
- urls.add(f);
- debug("getExtFiles f["+j+"] "+ f);
- }
- }
- }
- File[] ua = new File[urls.size()];
- urls.copyInto(ua);
- debug("getExtFiles ua.length " + ua.length);
- return ua;
- }
-
- /*
- * @return the list of installed extensions jar files
- */
- private File[] getInstalledExtensions() throws IOException {
- return AccessController.doPrivileged(
- new PrivilegedAction() {
- public File[] run() {
- try {
- return getExtFiles(getExtDirs());
- } catch(IOException e) {
- debug("Cannot get list of installed extensions");
- debugException(e);
- return new File[0];
- }
- }
- });
- }
-
- /*
- * Add the newly installed jar file to the extension class loader.
- *
- * @param cl the current installed extension class loader
- *
- * @return true if successful
- */
- private Boolean addNewExtensionsToClassLoader(Launcher.ExtClassLoader cl) {
- try {
- File[] installedExts = getInstalledExtensions();
- for (int i=0;i() {
- public URL run() {
- try {
- return ParseUtil.fileToEncodedURL(instFile);
- } catch (MalformedURLException e) {
- debugException(e);
- return null;
- }
- }
- });
- if (instURL != null) {
- URL[] urls = cl.getURLs();
- boolean found=false;
- for (int j = 0; j{@code
- * < 0 if source < version
- * > 0 if source > version
- * = 0 if source = version}
- */
- private int compareExtensionVersion(String source, String target)
- throws NumberFormatException
- {
- source = source.toLowerCase();
- target = target.toLowerCase();
-
- return strictCompareExtensionVersion(source, target);
- }
-
-
- /*
- * helper method to compare two versions.
- * version are in the x.y.z.t pattern.
- *
- * @param source version to compare to
- * @param target version used to compare against
- * @return {@code
- * < 0 if source < version
- * > 0 if source > version
- * = 0 if source = version}
- */
- private int strictCompareExtensionVersion(String source, String target)
- throws NumberFormatException
- {
- if (source.equals(target))
- return 0;
-
- StringTokenizer stk = new StringTokenizer(source, ".,");
- StringTokenizer ttk = new StringTokenizer(target, ".,");
-
- // Compare number
- int n = 0, m = 0, result = 0;
-
- // Convert token into meaning number for comparision
- if (stk.hasMoreTokens())
- n = convertToken(stk.nextToken().toString());
-
- // Convert token into meaning number for comparision
- if (ttk.hasMoreTokens())
- m = convertToken(ttk.nextToken().toString());
-
- if (n > m)
- return 1;
- else if (m > n)
- return -1;
- else
- {
- // Look for index of "." in the string
- int sIdx = source.indexOf('.');
- int tIdx = target.indexOf('.');
-
- if (sIdx == -1)
- sIdx = source.length() - 1;
-
- if (tIdx == -1)
- tIdx = target.length() - 1;
-
- return strictCompareExtensionVersion(source.substring(sIdx + 1),
- target.substring(tIdx + 1));
- }
- }
-
- private int convertToken(String token)
- {
- if (token == null || token.equals(""))
- return 0;
-
- int charValue = 0;
- int charVersion = 0;
- int patchVersion = 0;
- int strLength = token.length();
- int endIndex = strLength;
- char lastChar;
-
- Object[] args = {name};
- MessageFormat mf = new MessageFormat(rb.getString("optpkg.versionerror"));
- String versionError = mf.format(args);
-
- // Look for "-" for pre-release
- int prIndex = token.indexOf('-');
-
- // Look for "_" for patch release
- int patchIndex = token.indexOf('_');
-
- if (prIndex == -1 && patchIndex == -1)
- {
- // This is a FCS release
- try {
- return Integer.parseInt(token) * 100;
- } catch (NumberFormatException e) {
- System.out.println(versionError);
- return 0;
- }
- }
- else if (patchIndex != -1)
- {
- // This is a patch (update) release
- int prversion;
- try {
- // Obtain the version
- prversion = Integer.parseInt(token.substring(0, patchIndex));
-
- // Check to see if the patch version is in the n.n.n_nnl format (special release)
- lastChar = token.charAt(strLength-1);
- if (Character.isLetter(lastChar)) {
- // letters a-z have values from 10-35
- charValue = Character.getNumericValue(lastChar);
- endIndex = strLength-1;
-
- // Obtain the patch version id
- patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex));
-
- if (charValue >= Character.getNumericValue('a') && charValue <= Character.getNumericValue('z')) {
- // This is a special release
- charVersion = (patchVersion * 100) + charValue;
- } else {
- // character is not a a-z letter, ignore
- charVersion = 0;
- System.out.println(versionError);
- }
- } else {
- // This is a regular update release. Obtain the patch version id
- patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex));
- }
- } catch (NumberFormatException e) {
- System.out.println(versionError);
- return 0;
- }
- return prversion * 100 + (patchVersion + charVersion);
- }
- else
- {
- //This is a milestone release, either a early access, alpha, beta, or RC
-
- // Obtain the version
- int mrversion;
- try {
- mrversion = Integer.parseInt(token.substring(0, prIndex));
- } catch (NumberFormatException e) {
- System.out.println(versionError);
- return 0;
- }
-
- // Obtain the patch version string, including the milestone + version
- String prString = token.substring(prIndex + 1);
-
- // Milestone version
- String msVersion = "";
- int delta = 0;
-
- if (prString.indexOf("ea") != -1)
- {
- msVersion = prString.substring(2);
- delta = 50;
- }
- else if (prString.indexOf("alpha") != -1)
- {
- msVersion = prString.substring(5);
- delta = 40;
- }
- else if (prString.indexOf("beta") != -1)
- {
- msVersion = prString.substring(4);
- delta = 30;
- }
- else if (prString.indexOf("rc") != -1)
- {
- msVersion = prString.substring(2);
- delta = 20;
- }
-
- if (msVersion == null || msVersion.equals(""))
- {
- // No version after the milestone, assume 0
- return mrversion * 100 - delta ;
- }
- else
- {
- // Convert the milestone version
- try {
- return mrversion * 100 - delta + Integer.parseInt(msVersion);
- } catch (NumberFormatException e) {
- System.out.println(versionError);
- return 0;
- }
- }
- }
- }
-}
diff --git a/jdk/src/java.base/share/classes/sun/misc/ExtensionInstallationProvider.java b/jdk/src/java.base/share/classes/sun/misc/ExtensionInstallationProvider.java
deleted file mode 100644
index 438e396b2c2..00000000000
--- a/jdk/src/java.base/share/classes/sun/misc/ExtensionInstallationProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * This interface defines the contract a extension installation capable
- * provided to the extension installation dependency mechanism to
- * install new extensions on the user's disk
- *
- * @deprecated this class will be removed in a future release.
- * @author Jerome Dochez
- */
-@Deprecated
-public interface ExtensionInstallationProvider {
-
- /*
- *
- * Request the installation of an extension in the extension directory
- *
- *
- * @param requestExtInfo information on the extension that need to be
- * installed
- * @param installedExtInfo information on the current compatible installed
- * extension. Can be null if no current installation has been found.
- * @return true if the installation is successful, false if the
- * installation could not be attempted.
- * @exception ExtensionInstallationException if an installation was
- * attempted but did not succeed.
- */
- boolean installExtension(ExtensionInfo requestExtInfo,
- ExtensionInfo installedExtInfo)
- throws ExtensionInstallationException;
-}
diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
index ae32624c071..aa1538fae79 100644
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, 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
@@ -277,8 +277,14 @@ public final class AnnotatedTypeFactory {
@Override
public AnnotatedType[] getAnnotatedUpperBounds() {
- if (!hasUpperBounds())
- return new AnnotatedType[0];
+ if (!hasUpperBounds()) {
+ return new AnnotatedType[] { buildAnnotatedType(Object.class,
+ LocationInfo.BASE_LOCATION,
+ new TypeAnnotation[0],
+ new TypeAnnotation[0],
+ null)
+ };
+ }
return getAnnotatedBounds(getWildcardType().getUpperBounds());
}
diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java
index 9640ffb8589..453f6752ed0 100644
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java
@@ -28,6 +28,7 @@ package sun.security.ssl;
import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
import java.security.PrivateKey;
+import java.security.Security;
import java.util.Set;
import java.util.HashSet;
@@ -415,10 +416,12 @@ final class SignatureAndHashAlgorithm {
"SHA1withRSA", --p);
supports(HashAlgorithm.SHA1, SignatureAlgorithm.ECDSA,
"SHA1withECDSA", --p);
+ if (Security.getProvider("SunMSCAPI") == null) {
supports(HashAlgorithm.SHA224, SignatureAlgorithm.RSA,
"SHA224withRSA", --p);
supports(HashAlgorithm.SHA224, SignatureAlgorithm.ECDSA,
"SHA224withECDSA", --p);
+ }
supports(HashAlgorithm.SHA256, SignatureAlgorithm.RSA,
"SHA256withRSA", --p);
supports(HashAlgorithm.SHA256, SignatureAlgorithm.ECDSA,
diff --git a/jdk/src/java.base/share/native/libjava/ClassLoader.c b/jdk/src/java.base/share/native/libjava/ClassLoader.c
index ae69096bd50..5a8d86156b9 100644
--- a/jdk/src/java.base/share/native/libjava/ClassLoader.c
+++ b/jdk/src/java.base/share/native/libjava/ClassLoader.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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
@@ -479,12 +479,12 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find
return res;
}
/*
- * Class: java_lang_ClassLoader_NativeLibrary
+ * Class: java_lang_ClassLoader
* Method: findBuiltinLib
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
-Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib
+Java_java_lang_ClassLoader_findBuiltinLib
(JNIEnv *env, jclass cls, jstring name)
{
const char *cname;
@@ -500,8 +500,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib
JNU_ThrowInternalError(env, "NULL filename for native library");
return NULL;
}
- // Can't call initIDs because it will recurse into NativeLibrary via
- // FindClass to check context so set prochandle here as well.
procHandle = getProcessHandle();
cname = JNU_GetStringPlatformChars(env, name, 0);
if (cname == NULL) {
diff --git a/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c b/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c
index 487e8a2bac3..cd166933363 100644
--- a/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c
+++ b/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, 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
@@ -27,7 +27,12 @@
#include
#include
#include
+#ifdef MACOSX
+#include
+#include
+#else
#include
+#endif
#include
#include
#include
@@ -46,8 +51,10 @@
#define dirent64 dirent
#define readdir64_r readdir_r
#define stat64 stat
+#ifndef MACOSX
#define statvfs64 statvfs
#endif
+#endif
/* -- Field IDs -- */
@@ -432,8 +439,32 @@ Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
jlong rv = 0L;
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+#ifdef MACOSX
+ struct statfs fsstat;
+#else
struct statvfs64 fsstat;
+#endif
memset(&fsstat, 0, sizeof(fsstat));
+#ifdef MACOSX
+ if (statfs(path, &fsstat) == 0) {
+ switch(t) {
+ case java_io_FileSystem_SPACE_TOTAL:
+ rv = jlong_mul(long_to_jlong(fsstat.f_bsize),
+ long_to_jlong(fsstat.f_blocks));
+ break;
+ case java_io_FileSystem_SPACE_FREE:
+ rv = jlong_mul(long_to_jlong(fsstat.f_bsize),
+ long_to_jlong(fsstat.f_bfree));
+ break;
+ case java_io_FileSystem_SPACE_USABLE:
+ rv = jlong_mul(long_to_jlong(fsstat.f_bsize),
+ long_to_jlong(fsstat.f_bavail));
+ break;
+ default:
+ assert(0);
+ }
+ }
+#else
if (statvfs64(path, &fsstat) == 0) {
switch(t) {
case java_io_FileSystem_SPACE_TOTAL:
@@ -452,6 +483,7 @@ Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
assert(0);
}
}
+#endif
} END_PLATFORM_STRING(env, path);
return rv;
}
diff --git a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
index e8a1623a87d..2808cc189f8 100644
--- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
+++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
@@ -35,7 +35,12 @@
#include
#include
#include
+#ifdef MACOSX
+#include
+#include
+#else
#include
+#endif
#include
#ifdef __solaris__
@@ -50,7 +55,9 @@
#include
#define stat64 stat
+#ifndef MACOSX
#define statvfs64 statvfs
+#endif
#define open64 open
#define fstat64 fstat
@@ -901,11 +908,18 @@ Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
jlong pathAddress, jobject attrs)
{
int err;
+#ifdef MACOSX
+ struct statfs buf;
+#else
struct statvfs64 buf;
+#endif
const char* path = (const char*)jlong_to_ptr(pathAddress);
-
+#ifdef MACOSX
+ RESTARTABLE(statfs(path, &buf), err);
+#else
RESTARTABLE(statvfs64(path, &buf), err);
+#endif
if (err == -1) {
throwUnixException(env, errno);
} else {
@@ -921,7 +935,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
buf.f_bavail = 0;
}
#endif
+#ifdef MACOSX
+ (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_bsize));
+#else
(*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize));
+#endif
(*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks));
(*env)->SetLongField(env, attrs, attrs_f_bfree, long_to_jlong(buf.f_bfree));
(*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail));
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
index 77c6585ec87..09001e45829 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
@@ -540,9 +540,10 @@ public class LogManager {
return result;
}
- Logger demandSystemLogger(String name, String resourceBundleName) {
+ Logger demandSystemLogger(String name, String resourceBundleName, Class> caller) {
// Add a system logger in the system context's namespace
- final Logger sysLogger = getSystemContext().demandLogger(name, resourceBundleName);
+ final Logger sysLogger = getSystemContext()
+ .demandLogger(name, resourceBundleName, caller);
// Add the system logger to the LogManager's namespace if not exist
// so that there is only one single logger of the given name.
@@ -627,11 +628,11 @@ public class LogManager {
return global;
}
- Logger demandLogger(String name, String resourceBundleName) {
+ Logger demandLogger(String name, String resourceBundleName, Class> caller) {
// a LogManager subclass may have its own implementation to add and
// get a Logger. So delegate to the LogManager to do the work.
final LogManager owner = getOwner();
- return owner.demandLogger(name, resourceBundleName, null);
+ return owner.demandLogger(name, resourceBundleName, caller);
}
@@ -869,7 +870,7 @@ public class LogManager {
owner.getProperty(pname + ".handlers") != null) {
// This pname has a level/handlers definition.
// Make sure it exists.
- demandLogger(pname, null);
+ demandLogger(pname, null, null);
}
ix = ix2+1;
}
@@ -912,11 +913,11 @@ public class LogManager {
// one single logger of the given name. System loggers are visible
// to applications unless a logger of the same name has been added.
@Override
- Logger demandLogger(String name, String resourceBundleName) {
+ Logger demandLogger(String name, String resourceBundleName, Class> caller) {
Logger result = findLogger(name);
if (result == null) {
// only allocate the new system logger once
- Logger newLogger = new Logger(name, resourceBundleName, null, getOwner(), true);
+ Logger newLogger = new Logger(name, resourceBundleName, caller, getOwner(), true);
do {
if (addLocalLogger(newLogger)) {
// We successfully added the new Logger that we
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java
index 8a50a433acb..22e114acb48 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java
@@ -450,7 +450,7 @@ public class Logger {
SecurityManager sm = System.getSecurityManager();
if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
if (caller.getClassLoader() == null) {
- return manager.demandSystemLogger(name, resourceBundleName);
+ return manager.demandSystemLogger(name, resourceBundleName, caller);
}
}
return manager.demandLogger(name, resourceBundleName, caller);
@@ -500,7 +500,23 @@ public class Logger {
// would throw an IllegalArgumentException in the second call
// because the wrapper would result in an attempt to replace
// the existing "resourceBundleForFoo" with null.
- return demandLogger(name, null, Reflection.getCallerClass());
+ return Logger.getLogger(name, Reflection.getCallerClass());
+ }
+
+ /**
+ * Find or create a logger for a named subsystem on behalf
+ * of the given caller.
+ *
+ * This method is called by {@link #getLogger(java.lang.String)} after
+ * it has obtained a reference to its caller's class.
+ *
+ * @param name A name for the logger.
+ * @param callerClass The class that called {@link
+ * #getLogger(java.lang.String)}.
+ * @return a suitable Logger for {@code callerClass}.
+ */
+ private static Logger getLogger(String name, Class> callerClass) {
+ return demandLogger(name, null, callerClass);
}
/**
@@ -550,7 +566,30 @@ public class Logger {
// adding a new Logger object is handled by LogManager.addLogger().
@CallerSensitive
public static Logger getLogger(String name, String resourceBundleName) {
- Class> callerClass = Reflection.getCallerClass();
+ return Logger.getLogger(name, resourceBundleName, Reflection.getCallerClass());
+ }
+
+ /**
+ * Find or create a logger for a named subsystem on behalf
+ * of the given caller.
+ *
+ * This method is called by {@link
+ * #getLogger(java.lang.String, java.lang.String)} after
+ * it has obtained a reference to its caller's class.
+ *
+ * @param name A name for the logger.
+ * @param resourceBundleName name of ResourceBundle to be used for localizing
+ * messages for this logger. May be {@code null}
+ * if none of the messages require localization.
+ * @param callerClass The class that called {@link
+ * #getLogger(java.lang.String, java.lang.String)}.
+ * This class will also be used for locating the
+ * resource bundle if {@code resourceBundleName} is
+ * not {@code null}.
+ * @return a suitable Logger for {@code callerClass}.
+ */
+ private static Logger getLogger(String name, String resourceBundleName,
+ Class> callerClass) {
Logger result = demandLogger(name, resourceBundleName, callerClass);
// MissingResourceException or IllegalArgumentException can be
@@ -573,8 +612,9 @@ public class Logger {
LogManager manager = LogManager.getLogManager();
// all loggers in the system context will default to
- // the system logger's resource bundle
- Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME);
+ // the system logger's resource bundle - therefore the caller won't
+ // be needed and can be null.
+ Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, null);
return result;
}
diff --git a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java
index f9a4ea14ecb..108505dbb52 100644
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -25,14 +25,15 @@
package javax.security.auth.kerberos;
-import java.util.*;
-import java.security.Permission;
-import java.security.BasicPermission;
-import java.security.PermissionCollection;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This class is used to restrict the usage of the Kerberos
@@ -137,6 +138,7 @@ public final class DelegationPermission extends BasicPermission
* @return true if the specified permission is implied by this object,
* false if not.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof DelegationPermission))
return false;
@@ -159,6 +161,7 @@ public final class DelegationPermission extends BasicPermission
* has the same subordinate and service principal as this.
* DelegationPermission object.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@@ -175,11 +178,11 @@ public final class DelegationPermission extends BasicPermission
*
* @return a hash code value for this object.
*/
+ @Override
public int hashCode() {
return getName().hashCode();
}
-
/**
* Returns a PermissionCollection object for storing
* DelegationPermission objects.
@@ -192,7 +195,7 @@ public final class DelegationPermission extends BasicPermission
* @return a new PermissionCollection object suitable for storing
* DelegationPermissions.
*/
-
+ @Override
public PermissionCollection newPermissionCollection() {
return new KrbDelegationPermissionCollection();
}
@@ -263,13 +266,12 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
implements java.io.Serializable {
// Not serialized; see serialization section at end of class.
- private transient List perms;
+ private transient ConcurrentHashMap perms;
public KrbDelegationPermissionCollection() {
- perms = new ArrayList();
+ perms = new ConcurrentHashMap<>();
}
-
/**
* Check and see if this collection of permissions implies the permissions
* expressed in "permission".
@@ -279,18 +281,13 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
* @return true if "permission" is a proper subset of a permission in
* the collection, false if not.
*/
+ @Override
public boolean implies(Permission permission) {
if (! (permission instanceof DelegationPermission))
- return false;
-
- synchronized (this) {
- for (Permission x : perms) {
- if (x.implies(permission))
- return true;
- }
- }
- return false;
+ return false;
+ // if map contains key, then it automatically implies it
+ return perms.containsKey(permission);
}
/**
@@ -305,6 +302,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
* @exception SecurityException - if this PermissionCollection object
* has been marked readonly
*/
+ @Override
public void add(Permission permission) {
if (! (permission instanceof DelegationPermission))
throw new IllegalArgumentException("invalid permission: "+
@@ -312,9 +310,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
- synchronized (this) {
- perms.add(0, permission);
- }
+ perms.put(permission, Boolean.TRUE);
}
/**
@@ -323,11 +319,9 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
*
* @return an enumeration of all the DelegationPermission objects.
*/
+ @Override
public Enumeration elements() {
- // Convert Iterator into Enumeration
- synchronized (this) {
- return Collections.enumeration(perms);
- }
+ return perms.keys();
}
private static final long serialVersionUID = -3383936936589966948L;
@@ -354,11 +348,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
// Don't call out.defaultWriteObject()
// Write out Vector
- Vector permissions = new Vector<>(perms.size());
-
- synchronized (this) {
- permissions.addAll(perms);
- }
+ Vector permissions = new Vector<>(perms.keySet());
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", permissions);
@@ -379,8 +369,10 @@ final class KrbDelegationPermissionCollection extends PermissionCollection
// Get the one we want
Vector permissions =
- (Vector)gfields.get("permissions", null);
- perms = new ArrayList(permissions.size());
- perms.addAll(permissions);
+ (Vector)gfields.get("permissions", null);
+ perms = new ConcurrentHashMap<>(permissions.size());
+ for (Permission perm : permissions) {
+ perms.put(perm, Boolean.TRUE);
+ }
}
}
diff --git a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java
index ea89c1f8ae8..648ab959d5f 100644
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java
@@ -25,13 +25,14 @@
package javax.security.auth.kerberos;
-import java.util.*;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
import java.security.Permission;
import java.security.PermissionCollection;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This class is used to protect Kerberos services and the
@@ -149,6 +150,15 @@ public final class ServicePermission extends Permission
init(servicePrincipal, getMask(action));
}
+ /**
+ * Creates a ServicePermission object with the specified servicePrincipal
+ * and a pre-calculated mask. Avoids the overhead of re-computing the mask.
+ * Called by ServicePermissionCollection.
+ */
+ ServicePermission(String servicePrincipal, int mask) {
+ super(servicePrincipal);
+ init(servicePrincipal, mask);
+ }
/**
* Initialize the ServicePermission object.
@@ -175,6 +185,7 @@ public final class ServicePermission extends Permission
* @return true if the specified permission is implied by this object,
* false if not.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof ServicePermission))
return false;
@@ -200,6 +211,7 @@ public final class ServicePermission extends Permission
* same service principal, and actions as this
* ServicePermission object.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this)
return true;
@@ -219,7 +231,7 @@ public final class ServicePermission extends Permission
*
* @return a hash code value for this object.
*/
-
+ @Override
public int hashCode() {
return (getName().hashCode() ^ mask);
}
@@ -234,7 +246,7 @@ public final class ServicePermission extends Permission
* @param mask a specific integer action mask to translate into a string
* @return the canonical string representation of the actions
*/
- private static String getActions(int mask)
+ static String getActions(int mask)
{
StringBuilder sb = new StringBuilder();
boolean comma = false;
@@ -259,6 +271,7 @@ public final class ServicePermission extends Permission
* Always returns present actions in the following order:
* initiate, accept.
*/
+ @Override
public String getActions() {
if (actions == null)
actions = getActions(this.mask);
@@ -279,6 +292,7 @@ public final class ServicePermission extends Permission
* @return a new PermissionCollection object suitable for storing
* ServicePermissions.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new KrbServicePermissionCollection();
}
@@ -453,11 +467,12 @@ public final class ServicePermission extends Permission
final class KrbServicePermissionCollection extends PermissionCollection
implements java.io.Serializable {
+ // Key is the service principal, value is the ServicePermission.
// Not serialized; see serialization section at end of class
- private transient List perms;
+ private transient ConcurrentHashMap perms;
public KrbServicePermissionCollection() {
- perms = new ArrayList();
+ perms = new ConcurrentHashMap<>();
}
/**
@@ -469,32 +484,28 @@ final class KrbServicePermissionCollection extends PermissionCollection
* @return true if "permission" is a proper subset of a permission in
* the collection, false if not.
*/
+ @Override
public boolean implies(Permission permission) {
if (! (permission instanceof ServicePermission))
- return false;
+ return false;
ServicePermission np = (ServicePermission) permission;
int desired = np.getMask();
- int effective = 0;
- int needed = desired;
- synchronized (this) {
- int len = perms.size();
+ // first, check for wildcard principal
+ ServicePermission x = (ServicePermission)perms.get("*");
+ if (x != null) {
+ if ((x.getMask() & desired) == desired) {
+ return true;
+ }
+ }
- // need to deal with the case where the needed permission has
- // more than one action and the collection has individual permissions
- // that sum up to the needed.
-
- for (int i = 0; i < len; i++) {
- ServicePermission x = (ServicePermission) perms.get(i);
-
- //System.out.println(" trying "+x);
- if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) {
- effective |= x.getMask();
- if ((effective & desired) == desired)
- return true;
- needed = (desired ^ effective);
- }
+ // otherwise, check for match on principal
+ x = (ServicePermission)perms.get(np.getName());
+ if (x != null) {
+ //System.out.println(" trying "+x);
+ if ((x.getMask() & desired) == desired) {
+ return true;
}
}
return false;
@@ -512,6 +523,7 @@ final class KrbServicePermissionCollection extends PermissionCollection
* @exception SecurityException - if this PermissionCollection object
* has been marked readonly
*/
+ @Override
public void add(Permission permission) {
if (! (permission instanceof ServicePermission))
throw new IllegalArgumentException("invalid permission: "+
@@ -519,9 +531,32 @@ final class KrbServicePermissionCollection extends PermissionCollection
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
- synchronized (this) {
- perms.add(0, permission);
- }
+ ServicePermission sp = (ServicePermission)permission;
+ String princName = sp.getName();
+
+ // Add permission to map if it is absent, or replace with new
+ // permission if applicable. NOTE: cannot use lambda for
+ // remappingFunction parameter until JDK-8076596 is fixed.
+ perms.merge(princName, sp,
+ new java.util.function.BiFunction<>() {
+ @Override
+ public Permission apply(Permission existingVal,
+ Permission newVal) {
+ int oldMask = ((ServicePermission)existingVal).getMask();
+ int newMask = ((ServicePermission)newVal).getMask();
+ if (oldMask != newMask) {
+ int effective = oldMask | newMask;
+ if (effective == newMask) {
+ return newVal;
+ }
+ if (effective != oldMask) {
+ return new ServicePermission(princName, effective);
+ }
+ }
+ return existingVal;
+ }
+ }
+ );
}
/**
@@ -530,12 +565,9 @@ final class KrbServicePermissionCollection extends PermissionCollection
*
* @return an enumeration of all the ServicePermission objects.
*/
-
+ @Override
public Enumeration elements() {
- // Convert Iterator into Enumeration
- synchronized (this) {
- return Collections.enumeration(perms);
- }
+ return perms.elements();
}
private static final long serialVersionUID = -4118834211490102011L;
@@ -563,11 +595,7 @@ final class KrbServicePermissionCollection extends PermissionCollection
// Don't call out.defaultWriteObject()
// Write out Vector
- Vector permissions = new Vector<>(perms.size());
-
- synchronized (this) {
- permissions.addAll(perms);
- }
+ Vector permissions = new Vector<>(perms.values());
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", permissions);
@@ -589,7 +617,9 @@ final class KrbServicePermissionCollection extends PermissionCollection
// Get the one we want
Vector permissions =
(Vector)gfields.get("permissions", null);
- perms = new ArrayList(permissions.size());
- perms.addAll(permissions);
+ perms = new ConcurrentHashMap<>(permissions.size());
+ for (Permission perm : permissions) {
+ perms.put(perm.getName(), perm);
+ }
}
}
diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XalanXPathAPI.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XalanXPathAPI.java
index f9fab3033d8..75d3430eba2 100644
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XalanXPathAPI.java
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XalanXPathAPI.java
@@ -167,6 +167,13 @@ public class XalanXPathAPI implements XPathAPI {
private synchronized static void fixupFunctionTable() {
installed = false;
+ if (new FunctionTable().functionAvailable("here")) {
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Here function already registered");
+ }
+ installed = true;
+ return;
+ }
if (log.isLoggable(java.util.logging.Level.FINE)) {
log.log(java.util.logging.Level.FINE, "Registering Here function");
}
diff --git a/jdk/src/linux/doc/man/ja/native2ascii.1 b/jdk/src/linux/doc/man/ja/native2ascii.1
deleted file mode 100644
index 4ac8a594815..00000000000
--- a/jdk/src/linux/doc/man/ja/native2ascii.1
+++ /dev/null
@@ -1,98 +0,0 @@
-'\" t
-.\" Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
-.\" Title: native2ascii
-.\" Language: English
-.\" Date: 2013年11月21日
-.\" SectDesc: 国際化ツール
-.\" Software: JDK 8
-.\" Arch: 汎用
-.\"
-.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-.\"
-.\" This code is free software; you can redistribute it and/or modify it
-.\" under the terms of the GNU General Public License version 2 only, as
-.\" published by the Free Software Foundation.
-.\"
-.\" This code is distributed in the hope that it will be useful, but WITHOUT
-.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-.\" version 2 for more details (a copy is included in the LICENSE file that
-.\" accompanied this code).
-.\"
-.\" You should have received a copy of the GNU General Public License version
-.\" 2 along with this work; if not, write to the Free Software Foundation,
-.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-.\"
-.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-.\" or visit www.oracle.com if you need additional information or have any
-.\" questions.
-.\"
-.pl 99999
-.TH "native2ascii" "1" "2013年11月21日" "JDK 8" "国際化ツール"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-.SH "NAME"
-native2ascii \- サポートされている任意の文字エンコーディングの文字を含むファイルを、ASCIIおよびUnicodeでエスケープされたファイルに変換して(またはその逆)、ローカライズ可能なアプリケーションを作成します。
-.SH "概要"
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-\fInative2ascii\fR [ \fIinputfile\fR ] [ \fIoutputfile\fR ]
-.fi
-.if n \{\
-.RE
-.\}
-.PP
-\fIinputfile\fR
-.RS 4
-ASCIIに変換するエンコードされたファイル。
-.RE
-.PP
-\fIoutputfile\fR
-.RS 4
-変換されたASCIIファイル。
-.RE
-.SH "説明"
-.PP
-\fInative2ascii\fRコマンドは、ASCIIキャラクタ・セットに含まれないすべての文字にUnicodeエスケープ(\fI\eu\fR\fIxxxx\fR)表記法を使用して、Java Runtime Environment (JRE)でサポートされているエンコードされたファイルを、ASCIIでエンコードされたファイルに変換します。このプロセスは、ISO\-8859\-1文字セットに含まれない文字が含まれているプロパティ・ファイルで必要です。このツールは、その逆の変換を実行することもできます。
-.PP
-\fIoutputfile\fR値を省略した場合、標準出力に出力されます。さらに、\fIinputfile\fR値を省略した場合、標準入力から入力されます。
-.SH "オプション"
-.PP
-\-reverse
-.RS 4
-逆の処理を行います。つまり、ISO\-8859\-1でUnicodeエスケープを使用してエンコードされたファイルを、JREでサポートされる文字エンコーディングのファイルに変換します。
-.RE
-.PP
-\-encoding \fIencoding_name\fR
-.RS 4
-変換処理で使用する文字エンコーディングの名前を指定します。このオプションが存在しない場合は、デフォルトの文字エンコーディング(\fIjava\&.nio\&.charset\&.Charset\&.defaultCharset\fRメソッドで定義された)が使用されます。\fIencoding_name\fR文字列は、JREでサポートされている文字エンコーディングの名前にする必要があります。http://docs\&.oracle\&.com/javase/8/docs/technotes/guides/intl/encoding\&.doc\&.htmlにある
-「サポートされているエンコーディング」を参照してください
-.RE
-.PP
-\-J\fIoption\fR
-.RS 4
-Java仮想マシン(JVM)に\fIoption\fRを渡します。optionには、Javaアプリケーション起動ツールのリファレンス・ページに記載されているオプションを1つ指定します。たとえば、\fI\-J\-Xms48m\fRと指定すると、スタートアップ・メモリーは48MBに設定されます。java(1)を参照してください。
-.RE
-.br
-'pl 8.5i
-'bp
diff --git a/jdk/src/linux/doc/man/native2ascii.1 b/jdk/src/linux/doc/man/native2ascii.1
deleted file mode 100644
index 7e7ec7cfaa9..00000000000
--- a/jdk/src/linux/doc/man/native2ascii.1
+++ /dev/null
@@ -1,87 +0,0 @@
-'\" t
-.\" Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
-.\"
-.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-.\"
-.\" This code is free software; you can redistribute it and/or modify it
-.\" under the terms of the GNU General Public License version 2 only, as
-.\" published by the Free Software Foundation.
-.\"
-.\" This code is distributed in the hope that it will be useful, but WITHOUT
-.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-.\" version 2 for more details (a copy is included in the LICENSE file that
-.\" accompanied this code).
-.\"
-.\" You should have received a copy of the GNU General Public License version
-.\" 2 along with this work; if not, write to the Free Software Foundation,
-.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-.\"
-.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-.\" or visit www.oracle.com if you need additional information or have any
-.\" questions.
-.\"
-.\" Arch: generic
-.\" Software: JDK 8
-.\" Date: 21 November 2013
-.\" SectDesc: Internationalization Tools
-.\" Title: native2ascii.1
-.\"
-.if n .pl 99999
-.TH native2ascii 1 "21 November 2013" "JDK 8" "Internationalization Tools"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-
-.SH NAME
-native2ascii \- Creates localizable applications by converting a file with characters in any supported character encoding to one with ASCII and/or Unicode escapes or vice versa\&.
-.SH SYNOPSIS
-.sp
-.nf
-
-\fBnative2ascii\fR [ \fIinputfile\fR ] [ \fIoutputfile\fR ]
-.fi
-.sp
-.TP
-\fIinputfile\fR
-The encoded file to be converted to ASCII\&.
-.TP
-\fIoutputfile\fR
-The converted ASCII file\&.
-.SH DESCRIPTION
-The \f3native2ascii\fR command converts encoded files supported by the Java Runtime Environment (JRE) to files encoded in ASCII, using Unicode escapes (\f3\eu\fR\fIxxxx\fR) notation for all characters that are not part of the ASCII character set\&. This process is required for properties files that contain characters not in ISO-8859-1 character sets\&. The tool can also perform the reverse conversion\&.
-.PP
-If the \f3outputfile\fR value is omitted, then standard output is used for output\&. If, in addition, the \f3inputfile\fR value is omitted, then standard input is used for input\&.
-.SH OPTIONS
-.TP
--reverse
-.br
-Perform the reverse operation: Converts a file encoded in ISO-8859-1 with Unicode escapes to a file in any character encoding supported by the JRE\&.
-.TP
--encoding \fIencoding_name\fR
-.br
-Specifies the name of the character encoding to be used by the conversion procedure\&. If this option is not present, then the default character encoding (as determined by the \f3java\&.nio\&.charset\&.Charset\&.defaultCharset\fR method) is used\&. The \f3encoding_name\fR string must be the name of a character encoding that is supported by the JRE\&. See Supported Encodings at http://docs\&.oracle\&.com/javase/8/docs/technotes/guides/intl/encoding\&.doc\&.html
-.TP
--J\fIoption\fR
-.br
-Passes \f3option\fR to the Java Virtual Machine (JVM), where option is one of the options described on the reference page for the Java application launcher\&. For example, \f3-J-Xms48m\fR sets the startup memory to 48 MB\&. See java(1)\&.
-.RE
-.br
-'pl 8.5i
-'bp
diff --git a/jdk/src/solaris/doc/sun/man/man1/ja/native2ascii.1 b/jdk/src/solaris/doc/sun/man/man1/ja/native2ascii.1
deleted file mode 100644
index 4ac8a594815..00000000000
--- a/jdk/src/solaris/doc/sun/man/man1/ja/native2ascii.1
+++ /dev/null
@@ -1,98 +0,0 @@
-'\" t
-.\" Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
-.\" Title: native2ascii
-.\" Language: English
-.\" Date: 2013年11月21日
-.\" SectDesc: 国際化ツール
-.\" Software: JDK 8
-.\" Arch: 汎用
-.\"
-.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-.\"
-.\" This code is free software; you can redistribute it and/or modify it
-.\" under the terms of the GNU General Public License version 2 only, as
-.\" published by the Free Software Foundation.
-.\"
-.\" This code is distributed in the hope that it will be useful, but WITHOUT
-.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-.\" version 2 for more details (a copy is included in the LICENSE file that
-.\" accompanied this code).
-.\"
-.\" You should have received a copy of the GNU General Public License version
-.\" 2 along with this work; if not, write to the Free Software Foundation,
-.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-.\"
-.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-.\" or visit www.oracle.com if you need additional information or have any
-.\" questions.
-.\"
-.pl 99999
-.TH "native2ascii" "1" "2013年11月21日" "JDK 8" "国際化ツール"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-.SH "NAME"
-native2ascii \- サポートされている任意の文字エンコーディングの文字を含むファイルを、ASCIIおよびUnicodeでエスケープされたファイルに変換して(またはその逆)、ローカライズ可能なアプリケーションを作成します。
-.SH "概要"
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-\fInative2ascii\fR [ \fIinputfile\fR ] [ \fIoutputfile\fR ]
-.fi
-.if n \{\
-.RE
-.\}
-.PP
-\fIinputfile\fR
-.RS 4
-ASCIIに変換するエンコードされたファイル。
-.RE
-.PP
-\fIoutputfile\fR
-.RS 4
-変換されたASCIIファイル。
-.RE
-.SH "説明"
-.PP
-\fInative2ascii\fRコマンドは、ASCIIキャラクタ・セットに含まれないすべての文字にUnicodeエスケープ(\fI\eu\fR\fIxxxx\fR)表記法を使用して、Java Runtime Environment (JRE)でサポートされているエンコードされたファイルを、ASCIIでエンコードされたファイルに変換します。このプロセスは、ISO\-8859\-1文字セットに含まれない文字が含まれているプロパティ・ファイルで必要です。このツールは、その逆の変換を実行することもできます。
-.PP
-\fIoutputfile\fR値を省略した場合、標準出力に出力されます。さらに、\fIinputfile\fR値を省略した場合、標準入力から入力されます。
-.SH "オプション"
-.PP
-\-reverse
-.RS 4
-逆の処理を行います。つまり、ISO\-8859\-1でUnicodeエスケープを使用してエンコードされたファイルを、JREでサポートされる文字エンコーディングのファイルに変換します。
-.RE
-.PP
-\-encoding \fIencoding_name\fR
-.RS 4
-変換処理で使用する文字エンコーディングの名前を指定します。このオプションが存在しない場合は、デフォルトの文字エンコーディング(\fIjava\&.nio\&.charset\&.Charset\&.defaultCharset\fRメソッドで定義された)が使用されます。\fIencoding_name\fR文字列は、JREでサポートされている文字エンコーディングの名前にする必要があります。http://docs\&.oracle\&.com/javase/8/docs/technotes/guides/intl/encoding\&.doc\&.htmlにある
-「サポートされているエンコーディング」を参照してください
-.RE
-.PP
-\-J\fIoption\fR
-.RS 4
-Java仮想マシン(JVM)に\fIoption\fRを渡します。optionには、Javaアプリケーション起動ツールのリファレンス・ページに記載されているオプションを1つ指定します。たとえば、\fI\-J\-Xms48m\fRと指定すると、スタートアップ・メモリーは48MBに設定されます。java(1)を参照してください。
-.RE
-.br
-'pl 8.5i
-'bp
diff --git a/jdk/src/solaris/doc/sun/man/man1/native2ascii.1 b/jdk/src/solaris/doc/sun/man/man1/native2ascii.1
deleted file mode 100644
index 7e7ec7cfaa9..00000000000
--- a/jdk/src/solaris/doc/sun/man/man1/native2ascii.1
+++ /dev/null
@@ -1,87 +0,0 @@
-'\" t
-.\" Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
-.\"
-.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-.\"
-.\" This code is free software; you can redistribute it and/or modify it
-.\" under the terms of the GNU General Public License version 2 only, as
-.\" published by the Free Software Foundation.
-.\"
-.\" This code is distributed in the hope that it will be useful, but WITHOUT
-.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-.\" version 2 for more details (a copy is included in the LICENSE file that
-.\" accompanied this code).
-.\"
-.\" You should have received a copy of the GNU General Public License version
-.\" 2 along with this work; if not, write to the Free Software Foundation,
-.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-.\"
-.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-.\" or visit www.oracle.com if you need additional information or have any
-.\" questions.
-.\"
-.\" Arch: generic
-.\" Software: JDK 8
-.\" Date: 21 November 2013
-.\" SectDesc: Internationalization Tools
-.\" Title: native2ascii.1
-.\"
-.if n .pl 99999
-.TH native2ascii 1 "21 November 2013" "JDK 8" "Internationalization Tools"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-
-.SH NAME
-native2ascii \- Creates localizable applications by converting a file with characters in any supported character encoding to one with ASCII and/or Unicode escapes or vice versa\&.
-.SH SYNOPSIS
-.sp
-.nf
-
-\fBnative2ascii\fR [ \fIinputfile\fR ] [ \fIoutputfile\fR ]
-.fi
-.sp
-.TP
-\fIinputfile\fR
-The encoded file to be converted to ASCII\&.
-.TP
-\fIoutputfile\fR
-The converted ASCII file\&.
-.SH DESCRIPTION
-The \f3native2ascii\fR command converts encoded files supported by the Java Runtime Environment (JRE) to files encoded in ASCII, using Unicode escapes (\f3\eu\fR\fIxxxx\fR) notation for all characters that are not part of the ASCII character set\&. This process is required for properties files that contain characters not in ISO-8859-1 character sets\&. The tool can also perform the reverse conversion\&.
-.PP
-If the \f3outputfile\fR value is omitted, then standard output is used for output\&. If, in addition, the \f3inputfile\fR value is omitted, then standard input is used for input\&.
-.SH OPTIONS
-.TP
--reverse
-.br
-Perform the reverse operation: Converts a file encoded in ISO-8859-1 with Unicode escapes to a file in any character encoding supported by the JRE\&.
-.TP
--encoding \fIencoding_name\fR
-.br
-Specifies the name of the character encoding to be used by the conversion procedure\&. If this option is not present, then the default character encoding (as determined by the \f3java\&.nio\&.charset\&.Charset\&.defaultCharset\fR method) is used\&. The \f3encoding_name\fR string must be the name of a character encoding that is supported by the JRE\&. See Supported Encodings at http://docs\&.oracle\&.com/javase/8/docs/technotes/guides/intl/encoding\&.doc\&.html
-.TP
--J\fIoption\fR
-.br
-Passes \f3option\fR to the Java Virtual Machine (JVM), where option is one of the options described on the reference page for the Java application launcher\&. For example, \f3-J-Xms48m\fR sets the startup memory to 48 MB\&. See java(1)\&.
-.RE
-.br
-'pl 8.5i
-'bp
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index df34b7e011c..bed59bc7d24 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -123,9 +123,6 @@
# 8029891
java/lang/ClassLoader/deadlock/GetResource.java generic-all
-# 8080428
-java/lang/invoke/8022701/MHIllegalAccess.java generic-all
-
############################################################################
# jdk_instrument
diff --git a/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java b/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java
new file mode 100644
index 00000000000..6130a83420d
--- /dev/null
+++ b/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7130985
+ * @summary Four helper classes missing in Sun JDK
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main CorbaExceptionsCompileTest
+ */
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.rmi.RemoteException;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.CORBA.TypeCodePackage.BadKind;
+import org.omg.CORBA.TypeCodePackage.Bounds;
+
+import jdk.testlibrary.FileUtils;
+import jdk.testlibrary.JDKToolLauncher;
+
+public class CorbaExceptionsCompileTest implements CorbaExceptionsTest {
+
+ public CorbaExceptionsCompileTest() {
+ super();
+ }
+
+ public void testExceptionInvalidName()
+ throws java.rmi.RemoteException, InvalidName {}
+
+ public void testExceptionBounds()
+ throws java.rmi.RemoteException, Bounds {}
+
+ public void testExceptionBadKind()
+ throws java.rmi.RemoteException, BadKind {}
+
+ public void testExceptionCorba_Bounds()
+ throws java.rmi.RemoteException, org.omg.CORBA.Bounds {}
+
+ public static void main(String[] args) throws Exception {
+ final File f = new File(
+ CorbaExceptionsCompileTest.class.getProtectionDomain()
+ .getCodeSource().getLocation().getPath());
+ System.out.println(f.getCanonicalPath());
+ ProcessBuilder pb = new ProcessBuilder("ls", "-l");
+ pb.directory(f);
+ Process p = pb.start();
+ p.waitFor();
+ if (p.exitValue() == 0) {
+ try (BufferedReader br = new BufferedReader(
+ new InputStreamReader(p.getInputStream()))) {
+ StringBuilder builder = new StringBuilder();
+ String line = null;
+ while ( (line = br.readLine()) != null) {
+ builder.append(line + "\n");
+ }
+ String result = builder.toString();
+ System.out.println(result);
+ }
+ }
+
+ Path outDir = Paths.get("CorbaExceptionsCompileTest-compiled");
+ outDir = Files.createDirectory(outDir).toAbsolutePath();
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("rmic");
+ launcher.addToolArg("-classpath").addToolArg(f.getCanonicalPath())
+ .addToolArg("-d").addToolArg(outDir.toString())
+ .addToolArg("-iiop").addToolArg("CorbaExceptionsCompileTest");
+
+ pb = new ProcessBuilder(launcher.getCommand());
+ pb.directory(f);
+ System.out.println("Working Directory: " + pb.directory());
+ System.out.println("CorbaExceptionsCompileTest.class exists: "
+ + new File(f, "CorbaExceptionsCompileTest.class").exists());
+
+ p = pb.start();
+ p.waitFor();
+ if (p.exitValue() != 0) {
+ try (BufferedReader br = new BufferedReader(
+ new InputStreamReader(p.getInputStream()))) {
+ StringBuilder builder = new StringBuilder();
+ String line = null;
+ while ( (line = br.readLine()) != null) {
+ builder.append(line + "\n");
+ }
+ String result = builder.toString();
+ System.out.println(result);
+ throw new RuntimeException(launcher.getCommand() +
+ " -iiop CorbaExceptionsCompileTest failed with status: "
+ + p.exitValue());
+ }
+ }
+
+ if (Files.exists(outDir))
+ FileUtils.deleteFileTreeWithRetry(outDir);
+ }
+}
diff --git a/jdk/test/com/sun/corba/7130985/CorbaExceptionsTest.java b/jdk/test/com/sun/corba/7130985/CorbaExceptionsTest.java
new file mode 100644
index 00000000000..da0a2587ff4
--- /dev/null
+++ b/jdk/test/com/sun/corba/7130985/CorbaExceptionsTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.rmi.Remote;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.CORBA.TypeCodePackage.BadKind;
+import org.omg.CORBA.TypeCodePackage.Bounds;
+
+public interface CorbaExceptionsTest extends Remote {
+ public void testExceptionInvalidName() throws java.rmi.RemoteException, InvalidName;
+ public void testExceptionBounds() throws java.rmi.RemoteException, Bounds;
+ public void testExceptionBadKind() throws java.rmi.RemoteException, BadKind;
+ public void testExceptionCorba_Bounds() throws java.rmi.RemoteException, org.omg.CORBA.Bounds;
+}
+
diff --git a/jdk/test/java/io/FilePermission/FilePermissionCollection.java b/jdk/test/java/io/FilePermission/FilePermissionCollection.java
new file mode 100644
index 00000000000..dd4dd47882a
--- /dev/null
+++ b/jdk/test/java/io/FilePermission/FilePermissionCollection.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8056179
+ * @summary Unit test for FilePermissionCollection subclass
+ */
+
+import java.io.FilePermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.SecurityPermission;
+import java.util.Enumeration;
+
+public class FilePermissionCollection {
+
+ public static void main(String[] args) throws Exception {
+
+ int testFail = 0;
+
+ FilePermission perm = new FilePermission("/tmp/foo", "read");
+ PermissionCollection perms = perm.newPermissionCollection();
+
+ // test 1
+ System.out.println
+ ("test 1: add throws IllegalArgExc for wrong perm type");
+ try {
+ perms.add(new SecurityPermission("createAccessControlContext"));
+ System.err.println("Expected IllegalArgumentException");
+ testFail++;
+ } catch (IllegalArgumentException iae) {}
+
+ // test 2
+ System.out.println("test 2: implies returns false for wrong perm type");
+ if (perms.implies(new SecurityPermission("getPolicy"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 3
+ System.out.println("test 3: implies returns true for match on " +
+ "name and action");
+ perms.add(new FilePermission("/tmp/foo", "read"));
+ if (!perms.implies(new FilePermission("/tmp/foo", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 4
+ System.out.println("test 4: implies returns false for match on " +
+ "name but not action");
+ if (perms.implies(new FilePermission("/tmp/foo", "write"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 5
+ System.out.println("test 5: implies returns true for match on " +
+ "name and subset of actions");
+ perms.add(new FilePermission("/tmp/bar", "read, write"));
+ if (!perms.implies(new FilePermission("/tmp/bar", "write"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 6
+ System.out.println("test 6: implies returns true for aggregate " +
+ "match on name and action");
+ perms.add(new FilePermission("/tmp/baz", "read"));
+ perms.add(new FilePermission("/tmp/baz", "write"));
+ if (!perms.implies(new FilePermission("/tmp/baz", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+ if (!perms.implies(new FilePermission("/tmp/baz", "write,read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 7
+ System.out.println("test 7: implies returns true for wildcard " +
+ "and match on action");
+ perms.add(new FilePermission("/usr/tmp/*", "read"));
+ if (!perms.implies(new FilePermission("/usr/tmp/foo", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 8
+ System.out.println
+ ("test 8: implies returns false for non-match on wildcard");
+ if (perms.implies(new FilePermission("/usr/tmp/bar/foo", "read"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 9
+ System.out.println
+ ("test 9: implies returns true for deep wildcard match");
+ perms.add(new FilePermission("/usr/tmp/-", "read"));
+ if (!perms.implies(new FilePermission("/usr/tmp/bar/foo", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 10
+ System.out.println("test 10: implies returns true for relative match");
+ perms.add(new FilePermission(".", "read"));
+ if (!perms.implies(new FilePermission(System.getProperty("user.dir"),
+ "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 11
+ System.out.println("test 11: implies returns true for all " +
+ "wildcard and match on action");
+ perms.add(new FilePermission("<>", "read"));
+ if (!perms.implies(new FilePermission("/tmp/foobar", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 12
+ System.out.println("test 12: implies returns false for wildcard " +
+ "and non-match on action");
+ if (perms.implies(new FilePermission("/tmp/foobar", "write"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 13
+ System.out.println("test 13: elements returns correct number of perms");
+ int numPerms = 0;
+ Enumeration e = perms.elements();
+ while (e.hasMoreElements()) {
+ numPerms++;
+ System.out.println(e.nextElement());
+ }
+ // the two "/tmp/baz" entries were combined into one
+ if (numPerms != 7) {
+ System.err.println("Expected 7, got " + numPerms);
+ testFail++;
+ }
+
+ if (testFail > 0) {
+ throw new Exception(testFail + " test(s) failed");
+ }
+ }
+}
diff --git a/jdk/test/java/lang/Runtime/exec/LotsOfOutput.java b/jdk/test/java/lang/Runtime/exec/LotsOfOutput.java
index 8d0c9514486..a77ffcb01a0 100644
--- a/jdk/test/java/lang/Runtime/exec/LotsOfOutput.java
+++ b/jdk/test/java/lang/Runtime/exec/LotsOfOutput.java
@@ -48,20 +48,21 @@ public class LotsOfOutput {
UnixCommands.ensureCommandsAvailable("cat");
Process p = runtime.exec(UnixCommands.cat() + " /dev/zero");
- long initMemory = usedMemory();
- boolean growing = false;
+ long prev = usedMemory();
+ int growing = 0;
for (int i = 1; i < 10; i++) {
Thread.sleep(100);
long used = usedMemory();
- if (used != initMemory) {
- System.out.printf("consuming memory: i: %d, initial: %d, used: %d, delta: %d%n",
- i, initMemory, used, used - initMemory);
+ if (used != prev) {
+ System.out.printf("consuming memory: i: %d, prev: %d, used: %d, delta: %d%n",
+ i, prev, used, used - prev);
}
- if (used > initMemory + THRESHOLD)
- growing = true;
+ if (used > prev + THRESHOLD)
+ growing += 1;
+ prev = used;
}
- if (growing)
- throw new Exception("Process consumes memory.");
+ if (growing > 2)
+ throw new Exception("Process consumes memory: growing " + growing);
}
}
diff --git a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java
index 2c7da746a7f..f409a67b682 100644
--- a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8004698 8007073 8022343
+ * @bug 8004698 8007073 8022343 8054304 8058595
* @summary Unit test for type annotations
*/
@@ -200,6 +200,17 @@ public class TypeAnnotationReflection {
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("M Runnable"));
+
+ // Check that AnnotatedTypeVariable.getAnnotatedBounds() returns jlO for a naked
+ // type variable (i.e no bounds, no annotations)
+ Method m4 = TestClassTypeVarAndField.class.getDeclaredMethod("foo4", (Class>[])null);
+ AnnotatedType ret4 = m4.getAnnotatedReturnType();
+ AnnotatedType[] annotatedBounds4 = ((AnnotatedTypeVariable)ret4).getAnnotatedBounds();
+ check(annotatedBounds4.length == 1);
+
+ annos = annotatedBounds4[0].getAnnotations();
+ check(annos.length == 0);
+ check(annotatedBounds4[0].getType().equals(Object.class));
}
private static void testFields() throws Exception {
@@ -231,7 +242,7 @@ public class TypeAnnotationReflection {
private static void testClassTypeVar() throws Exception {
TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters();
Annotation[] annos;
- check(typeVars.length == 2);
+ check(typeVars.length == 3);
// First TypeVar
AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds();
@@ -262,6 +273,14 @@ public class TypeAnnotationReflection {
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno2.class));
check(((TypeAnno2)annos[0]).value().equals("EEBound"));
+
+ // third Typevar V declared without explicit bounds should see jlO as its bound.
+ annotatedBounds = typeVars[2].getAnnotatedBounds();
+ check(annotatedBounds.length == 1);
+
+ annos = annotatedBounds[0].getAnnotations();
+ check(annos.length == 0);
+ check(annotatedBounds[0].getType().equals(Object.class));
}
private static void testMethodTypeVar() throws Exception {
@@ -282,7 +301,7 @@ public class TypeAnnotationReflection {
// Second method
m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class>[])null);
t = m2.getTypeParameters();
- check(t.length == 1);
+ check(t.length == 2);
annos = t[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
@@ -293,6 +312,14 @@ public class TypeAnnotationReflection {
annos = annotatedBounds2[0].getAnnotations();
check(annos.length == 0);
+
+ // for the naked type variable L of foo3, we should see jlO as its bound.
+ annotatedBounds2 = t[1].getAnnotatedBounds();
+ check(annotatedBounds2.length == 1);
+ check(annotatedBounds2[0].getType().equals(Object.class));
+
+ annos = annotatedBounds2[0].getAnnotations();
+ check(annos.length == 0);
}
private static void testParameterizedType() {
@@ -357,9 +384,24 @@ public class TypeAnnotationReflection {
w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
.getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
t = w.getAnnotatedUpperBounds();
- check(t.length == 0);
+ check(t.length == 1);
+ check(t[0].getType().equals(Object.class));
+ annos = t[0].getAnnotations();
+ check(annos.length == 0);
t = w.getAnnotatedLowerBounds();
check(t.length == 1);
+
+ // for an unbounded wildcard, we should see jlO as its upperbound and null type as its lower bound.
+ f = TestWildcardType.class.getDeclaredField("f3");
+ w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
+ .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
+ t = w.getAnnotatedUpperBounds();
+ check(t.length == 1);
+ check(t[0].getType().equals(Object.class));
+ annos = t[0].getAnnotations();
+ check(annos.length == 0);
+ t = w.getAnnotatedLowerBounds();
+ check(t.length == 0);
}
private static void testParameterTypes() throws Exception {
@@ -515,6 +557,7 @@ abstract class TestWildcardType {
public List super T> foo() { return null;}
public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1;
public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2;
+ public Class<@TypeAnno("5") ?> f3;
}
abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
@@ -555,14 +598,15 @@ abstract class TestClassException {
abstract class TestClassTypeVarAndField {
+ @TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable, V > {
@TypeAnno("T1 field") @TypeAnno2("T2 field") T field1;
T field2;
@TypeAnno("Object field") Object field3;
public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
public M foo2() {return null;}
- public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;}
+ public <@TypeAnno("K") K extends Cloneable, L> K foo3() {return null;}
+ public L foo4() {return null;}
}
@Target(ElementType.TYPE_USE)
diff --git a/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java b/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java
index a5099dd60c5..5c1f64bf9b0 100644
--- a/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java
+++ b/jdk/test/java/lang/invoke/8022701/InvokeSeveralWays.java
@@ -38,12 +38,19 @@ public class InvokeSeveralWays {
failures++;
} catch (InvocationTargetException e) {
Throwable c = e.getCause();
- if (expected.isInstance(c))
- System.out.println("EXPECTED: " + expected.getName() + ", "+ c);
- else {
- failures++;
- System.out.println("FAIL: Unexpected wrapped exception " + c);
- e.printStackTrace(System.out);
+ if (BootstrapMethodError.class.isInstance(c)) {
+ c = c.getCause();
+ if (expected.isInstance(c))
+ System.out.println("EXPECTED: " + expected.getName() + ", "+ c);
+ else {
+ failures++;
+ System.out.println("FAIL: Unexpected wrapped exception " + c);
+ e.printStackTrace(System.out);
+ }
+ } else {
+ failures++;
+ System.out.println("FAIL: Exception from MethodHandle invocation not wrapped in BootstrapMethodError " + c);
+ e.printStackTrace(System.out);
}
} catch (Throwable e) {
failures++;
@@ -74,14 +81,19 @@ public class InvokeSeveralWays {
Invoker.invoke();
System.out.println("FAIL: No exception throw, probably failed to load modified bytecodes for MethodSupplier");
failures++;
- } catch (Throwable e) {
- if (expected.isInstance(e))
- System.out.println("EXPECTED: " + expected.getName() + ", "+ e);
+ } catch (BootstrapMethodError e) {
+ Throwable c = e.getCause();
+ if (expected.isInstance(c))
+ System.out.println("EXPECTED: " + expected.getName() + ", "+ c);
else {
- failures++;
- System.out.println("FAIL: Unexpected exception has been caught " + e);
- e.printStackTrace(System.out);
+ failures++;
+ System.out.println("FAIL: Unexpected exception has been caught " + c);
+ e.printStackTrace(System.out);
}
+ } catch (Throwable e) {
+ failures++;
+ System.out.println("FAIL: Exception from MethodHandle invocation not wrapped in BootstrapMethodError " + e);
+ e.printStackTrace(System.out);
}
System.out.println();
try {
diff --git a/jdk/test/java/net/SocketPermission/SocketPermissionCollection.java b/jdk/test/java/net/SocketPermission/SocketPermissionCollection.java
new file mode 100644
index 00000000000..855a1ce0672
--- /dev/null
+++ b/jdk/test/java/net/SocketPermission/SocketPermissionCollection.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8056179
+ * @summary Unit test for PermissionCollection subclasses
+ */
+
+import java.net.SocketPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.SecurityPermission;
+import java.util.Enumeration;
+
+public class SocketPermissionCollection {
+
+ public static void main(String[] args) throws Exception {
+
+ int testFail = 0;
+
+ SocketPermission perm = new SocketPermission("www.example.com",
+ "connect");
+ PermissionCollection perms = perm.newPermissionCollection();
+
+ // test 1
+ System.out.println
+ ("test 1: add throws IllegalArgExc for wrong perm type");
+ try {
+ perms.add(new SecurityPermission("createAccessControlContext"));
+ System.err.println("Expected IllegalArgumentException");
+ testFail++;
+ } catch (IllegalArgumentException iae) {}
+
+ // test 2
+ System.out.println("test 2: implies returns false for wrong perm type");
+ if (perms.implies(new SecurityPermission("getPolicy"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 3
+ System.out.println
+ ("test 3: implies returns true for match on name and action");
+ perms.add(new SocketPermission("www.example.com", "connect"));
+ if (!perms.implies(new SocketPermission("www.example.com", "connect"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 4
+ System.out.println
+ ("test 4: implies returns false for match on name but not action");
+ if (perms.implies(new SocketPermission("www.example.com", "accept"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 5
+ System.out.println("test 5: implies returns true for match on " +
+ "name and subset of actions");
+ perms.add(new SocketPermission("www.example.org", "accept, connect"));
+ if (!perms.implies(new SocketPermission("www.example.org", "connect"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 6
+ System.out.println("test 6: implies returns true for aggregate " +
+ "match on name and action");
+ perms.add(new SocketPermission("www.example.us", "accept"));
+ perms.add(new SocketPermission("www.example.us", "connect"));
+ if (!perms.implies(new SocketPermission("www.example.us", "accept"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+ if (!perms.implies(new SocketPermission("www.example.us",
+ "connect,accept"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 7
+ System.out.println("test 7: implies returns true for wildcard " +
+ "and match on action");
+ perms.add(new SocketPermission("*.example.edu", "resolve"));
+ if (!perms.implies(new SocketPermission("foo.example.edu", "resolve"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 8
+ System.out.println("test 8: implies returns false for non-match " +
+ "on wildcard");
+ if (perms.implies(new SocketPermission("foo.example.edu", "connect"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 9
+ System.out.println("test 9: implies returns true for matching " +
+ "port range and action");
+ perms.add(new SocketPermission("204.160.241.0:1024-65535", "connect"));
+ if (!perms.implies(new SocketPermission("204.160.241.0:1025", "connect"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 13
+ System.out.println("test 13: elements returns correct number of perms");
+ int numPerms = 0;
+ Enumeration e = perms.elements();
+ while (e.hasMoreElements()) {
+ numPerms++;
+ System.out.println(e.nextElement());
+ }
+ // the two "/tmp/baz" entries were combined into one
+ if (numPerms != 5) {
+ System.err.println("Expected 5, got " + numPerms);
+ testFail++;
+ }
+
+ if (testFail > 0) {
+ throw new Exception(testFail + " test(s) failed");
+ }
+ }
+}
diff --git a/jdk/test/java/security/BasicPermission/BasicPermissionCollection.java b/jdk/test/java/security/BasicPermission/BasicPermissionCollection.java
new file mode 100644
index 00000000000..274afe3284e
--- /dev/null
+++ b/jdk/test/java/security/BasicPermission/BasicPermissionCollection.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8056179
+ * @summary Unit test for BasicPermissionCollection subclass
+ */
+
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.SecurityPermission;
+import java.util.Enumeration;
+
+public class BasicPermissionCollection {
+
+ public static void main(String[] args) throws Exception {
+
+ int testFail = 0;
+
+ TestPermission perm = new TestPermission("foo");
+ PermissionCollection perms = perm.newPermissionCollection();
+
+ // test 1
+ System.out.println("test 1: add throws IllegalArgumentExc");
+ try {
+ perms.add(new SecurityPermission("createAccessControlContext"));
+ System.err.println("Expected IllegalArgumentException");
+ testFail++;
+ } catch (IllegalArgumentException iae) {}
+
+ // test 2
+ System.out.println("test 2: implies returns false for wrong class");
+ if (perms.implies(new SecurityPermission("getPolicy"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 3
+ System.out.println("test 3: implies returns true for match on name");
+ perms.add(new TestPermission("foo"));
+ if (!perms.implies(new TestPermission("foo"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 4
+ System.out.println("test 4: implies returns true for wildcard match");
+ perms.add(new TestPermission("bar.*"));
+ if (!perms.implies(new TestPermission("bar.foo"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 5
+ System.out.println
+ ("test 5: implies returns false for invalid wildcard");
+ perms.add(new TestPermission("baz*"));
+ if (perms.implies(new TestPermission("baz.foo"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 6
+ System.out.println
+ ("test 6: implies returns true for deep wildcard match");
+ if (!perms.implies(new TestPermission("bar.foo.baz"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 7
+ System.out.println
+ ("test 7: implies returns true for all wildcard match");
+ perms.add(new TestPermission("*"));
+ if (!perms.implies(new TestPermission("yes"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 8
+ System.out.println("test 8: elements returns correct number of perms");
+ int numPerms = 0;
+ Enumeration e = perms.elements();
+ while (e.hasMoreElements()) {
+ numPerms++;
+ System.out.println(e.nextElement());
+ }
+ if (numPerms != 4) {
+ System.err.println("Expected 4, got " + numPerms);
+ testFail++;
+ }
+
+ if (testFail > 0) {
+ throw new Exception(testFail + " test(s) failed");
+ }
+ }
+
+ private static class TestPermission extends BasicPermission {
+ TestPermission(String name) {
+ super(name);
+ }
+ }
+}
diff --git a/jdk/test/java/security/PermissionCollection/Concurrent.java b/jdk/test/java/security/PermissionCollection/Concurrent.java
index 81915141d0c..056be387080 100644
--- a/jdk/test/java/security/PermissionCollection/Concurrent.java
+++ b/jdk/test/java/security/PermissionCollection/Concurrent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -104,13 +104,11 @@ public class Concurrent {
System.out.println(perm[perm.length-1] + " implies " + result);
}
- synchronized (pc) {
- Enumeration en = pc.elements();
- while (en.hasMoreElements()) {
- Object obj = en.nextElement();
- if (debug) {
- System.out.println(obj);
- }
+ Enumeration en = pc.elements();
+ while (en.hasMoreElements()) {
+ Object obj = en.nextElement();
+ if (debug) {
+ System.out.println(obj);
}
}
}
@@ -151,13 +149,11 @@ public class Concurrent {
}
}
- synchronized (pc) {
- Enumeration en = pc.elements();
- while (en.hasMoreElements()) {
- Object obj = en.nextElement();
- if (debug) {
- System.out.println(obj);
- }
+ Enumeration en = pc.elements();
+ while (en.hasMoreElements()) {
+ Object obj = en.nextElement();
+ if (debug) {
+ System.out.println(obj);
}
}
}
diff --git a/jdk/test/java/security/SecureClassLoader/DefineClass.java b/jdk/test/java/security/SecureClassLoader/DefineClass.java
new file mode 100644
index 00000000000..c54ef2215cd
--- /dev/null
+++ b/jdk/test/java/security/SecureClassLoader/DefineClass.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.PropertyPermission;
+
+/*
+ * @test
+ * @bug 6826789
+ * @summary Make sure equivalent ProtectionDomains are granted the same
+ * permissions when the CodeSource URLs are different but resolve
+ * to the same ip address after name service resolution.
+ * @run main/othervm/java.security.policy=DefineClass.policy DefineClass
+ */
+
+public class DefineClass {
+
+ // permissions that are expected to be granted by the policy file
+ private final static Permission[] GRANTED_PERMS = new Permission[] {
+ new PropertyPermission("user.home", "read"),
+ new PropertyPermission("user.name", "read")
+ };
+
+ // Base64 encoded bytes of a simple class: "public class Foo {}"
+ private final static String FOO_CLASS =
+ "yv66vgAAADQADQoAAwAKBwALBwAMAQAGPGluaXQ+AQADKClWAQAEQ29kZQEA" +
+ "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhGb28uamF2YQwABAAF" +
+ "AQADRm9vAQAQamF2YS9sYW5nL09iamVjdAAhAAIAAwAAAAAAAQABAAQABQAB" +
+ "AAYAAAAdAAEAAQAAAAUqtwABsQAAAAEABwAAAAYAAQAAAAEAAQAIAAAAAgAJ";
+
+ // Base64 encoded bytes of a simple class: "public class Bar {}"
+ private final static String BAR_CLASS =
+ "yv66vgAAADQADQoAAwAKBwALBwAMAQAGPGluaXQ+AQADKClWAQAEQ29kZQEA" +
+ "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhCYXIuamF2YQwABAAF" +
+ "AQADQmFyAQAQamF2YS9sYW5nL09iamVjdAAhAAIAAwAAAAAAAQABAAQABQAB" +
+ "AAYAAAAdAAEAAQAAAAUqtwABsQAAAAEABwAAAAYAAQAAAAEAAQAIAAAAAgAJ";
+
+ public static void main(String[] args) throws Exception {
+
+ MySecureClassLoader scl = new MySecureClassLoader();
+ Policy p = Policy.getPolicy();
+ ArrayList perms1 = getPermissions(scl, p,
+ "http://localhost/",
+ "Foo", FOO_CLASS);
+ checkPerms(perms1, GRANTED_PERMS);
+ ArrayList perms2 = getPermissions(scl, p,
+ "http://127.0.0.1/",
+ "Bar", BAR_CLASS);
+ checkPerms(perms2, GRANTED_PERMS);
+ assert(perms1.equals(perms2));
+ }
+
+ // returns the permissions granted to the codebase URL
+ private static ArrayList getPermissions(MySecureClassLoader scl,
+ Policy p, String url,
+ String className,
+ String classBytes)
+ throws IOException {
+ CodeSource cs = new CodeSource(new URL(url), (Certificate[])null);
+ Base64.Decoder bd = Base64.getDecoder();
+ byte[] bytes = bd.decode(classBytes);
+ Class> c = scl.defineMyClass(className, bytes, cs);
+ ProtectionDomain pd = c.getProtectionDomain();
+ return Collections.list(p.getPermissions(pd).elements());
+ }
+
+ private static void checkPerms(List perms,
+ Permission... grantedPerms)
+ throws Exception
+ {
+ if (!perms.containsAll(Arrays.asList(grantedPerms))) {
+ throw new Exception("Granted permissions not correct");
+ }
+ }
+
+ // A SecureClassLoader that allows the test to define its own classes
+ private static class MySecureClassLoader extends SecureClassLoader {
+ Class> defineMyClass(String name, byte[] b, CodeSource cs) {
+ return super.defineClass(name, b, 0, b.length, cs);
+ }
+ }
+}
diff --git a/jdk/test/java/security/SecureClassLoader/DefineClass.policy b/jdk/test/java/security/SecureClassLoader/DefineClass.policy
new file mode 100644
index 00000000000..ea7eae7c003
--- /dev/null
+++ b/jdk/test/java/security/SecureClassLoader/DefineClass.policy
@@ -0,0 +1,11 @@
+grant {
+ permission java.lang.RuntimePermission "createClassLoader";
+ permission java.lang.RuntimePermission "getProtectionDomain";
+ permission java.security.SecurityPermission "getPolicy";
+};
+grant codebase "http://localhost/" {
+ permission java.util.PropertyPermission "user.home", "read";
+};
+grant codebase "http://127.0.0.1/" {
+ permission java.util.PropertyPermission "user.name", "read";
+};
diff --git a/jdk/test/java/util/Arrays/ParallelPrefix.java b/jdk/test/java/util/Arrays/ParallelPrefix.java
index b926880178f..f69d71a0293 100644
--- a/jdk/test/java/util/Arrays/ParallelPrefix.java
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java
@@ -26,6 +26,7 @@
* @summary unit test for Arrays.ParallelPrefix().
* @author Tristan Yan
* @run testng ParallelPrefix
+ * @key intermittent
*/
import java.util.Arrays;
diff --git a/jdk/test/java/util/Arrays/SortingIntBenchmarkTestJMH.java b/jdk/test/java/util/Arrays/SortingIntBenchmarkTestJMH.java
new file mode 100644
index 00000000000..bd0ab1366f1
--- /dev/null
+++ b/jdk/test/java/util/Arrays/SortingIntBenchmarkTestJMH.java
@@ -0,0 +1,708 @@
+/*
+ * Copyright 2015 Goldman Sachs.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@State(Scope.Thread)
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+public class SortingIntBenchmarkTestJMH {
+ private static final int QUICKSORT_THRESHOLD = 286;
+ private static final int MAX_RUN_COUNT = 67;
+ private static final int INSERTION_SORT_THRESHOLD = 47;
+ public static final int MAX_VALUE = 1_000_000;
+
+ @Param({"pairFlipZeroPairFlip", "pairFlipOneHundredPairFlip"
+ , "zeroHi", "hiZeroLow", "hiFlatLow", "identical",
+ "randomDups", "randomNoDups", "sortedReversedSorted", "pairFlip", "endLessThan"})
+
+ public String listType;
+
+ private int[] array;
+ private static final int LIST_SIZE = 10_000_000;
+ public static final int NUMBER_OF_ITERATIONS = 10;
+
+ @Setup
+ public void setUp() {
+ Random random = new Random(123456789012345L);
+ this.array = new int[LIST_SIZE];
+ int threeQuarters = (int) (LIST_SIZE * 0.75);
+ if ("zeroHi".equals(this.listType)) {
+ for (int i = 0; i < threeQuarters; i++) {
+ this.array[i] = 0;
+ }
+ int k = 1;
+ for (int i = threeQuarters; i < LIST_SIZE; i++) {
+ this.array[i] = k;
+ k++;
+ }
+ }
+ else if ("hiFlatLow".equals(this.listType)) {
+ int oneThird = LIST_SIZE / 3;
+ for (int i = 0; i < oneThird; i++) {
+ this.array[i] = i;
+ }
+ int twoThirds = oneThird * 2;
+ int constant = oneThird - 1;
+ for (int i = oneThird; i < twoThirds; i++) {
+ this.array[i] = constant;
+ }
+ for (int i = twoThirds; i < LIST_SIZE; i++) {
+ this.array[i] = constant - i + twoThirds;
+ }
+ }
+ else if ("hiZeroLow".equals(this.listType)) {
+ int oneThird = LIST_SIZE / 3;
+ for (int i = 0; i < oneThird; i++) {
+ this.array[i] = i;
+ }
+ int twoThirds = oneThird * 2;
+ for (int i = oneThird; i < twoThirds; i++) {
+ this.array[i] = 0;
+ }
+ for (int i = twoThirds; i < LIST_SIZE; i++) {
+ this.array[i] = oneThird - i + twoThirds;
+ }
+ }
+ else if ("identical".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = 0;
+ }
+ }
+ else if ("randomDups".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = random.nextInt(1000);
+ }
+ }
+ else if ("randomNoDups".equals(this.listType)) {
+ Set set = new HashSet();
+ while (set.size() < LIST_SIZE + 1) {
+ set.add(random.nextInt());
+ }
+ List list = new ArrayList<>(LIST_SIZE);
+ list.addAll(set);
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = list.get(i);
+ }
+ }
+ else if ("sortedReversedSorted".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE / 2; i++) {
+ this.array[i] = i;
+ }
+ int num = 0;
+ for (int i = LIST_SIZE / 2; i < LIST_SIZE; i++) {
+ this.array[i] = LIST_SIZE - num;
+ num++;
+ }
+ }
+ else if ("pairFlip".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = i;
+ }
+ for (int i = 0; i < LIST_SIZE; i += 2) {
+ int temp = this.array[i];
+ this.array[i] = this.array[i + 1];
+ this.array[i + 1] = temp;
+ }
+ }
+ else if ("endLessThan".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE - 1; i++) {
+ this.array[i] = 3;
+ }
+ this.array[LIST_SIZE - 1] = 1;
+ }
+ else if ("pairFlipZeroPairFlip".equals(this.listType)) {
+ //pairflip
+ for (int i = 0; i < 64; i++) {
+ this.array[i] = i;
+ }
+ for (int i = 0; i < 64; i += 2) {
+ int temp = this.array[i];
+ this.array[i] = this.array[i + 1];
+ this.array[i + 1] = temp;
+ }
+ //zero
+ for (int i = 64; i < this.array.length - 64; i++) {
+ this.array[i] = 0;
+ }
+ //pairflip
+ for (int i = this.array.length - 64; i < this.array.length; i++) {
+ this.array[i] = i;
+ }
+ for (int i = this.array.length - 64; i < this.array.length; i += 2) {
+ int temp = this.array[i];
+ this.array[i] = this.array[i + 1];
+ this.array[i + 1] = temp;
+ }
+ }
+ else if ("pairFlipOneHundredPairFlip".equals(this.listType)) {
+ //10, 5
+ for (int i = 0; i < 64; i++) {
+ if (i % 2 == 0) {
+ this.array[i] = 10;
+ }
+ else {
+ this.array[i] = 5;
+ }
+ }
+
+ //100
+ for (int i = 64; i < this.array.length - 64; i++) {
+ this.array[i] = 100;
+ }
+
+ //10, 5
+ for (int i = this.array.length - 64; i < this.array.length; i++) {
+ if (i % 2 == 0) {
+ this.array[i] = 10;
+ }
+ else {
+ this.array[i] = 5;
+ }
+ }
+ }
+ }
+
+ @Warmup(iterations = 20)
+ @Measurement(iterations = 10)
+ @Benchmark
+ public void sortNewWay() {
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ SortingIntTestJMH.sort(this.array, 0, this.array.length - 1, null, 0, 0);
+ }
+ }
+
+ @Warmup(iterations = 20)
+ @Measurement(iterations = 10)
+ @Benchmark
+ public void sortCurrentWay() {
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ Arrays.sort(this.array);
+ }
+ }
+
+ static void sort(int[] a, int left, int right,
+ int[] work, int workBase, int workLen) {
+ // Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ SortingIntTestJMH.sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT + 1];
+ int count = 0;
+ run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break;
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]) ;
+ }
+ else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]) ;
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ int t = a[lo];
+ a[lo] = a[hi];
+ a[hi] = t;
+ }
+ }
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
+ }
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ // Implementation note: variable "right" is increased by 1.
+ if (run[count] == right++) {
+ run[++count] = right;
+ }
+ if (count <= 1) { // The array is already sorted
+ return;
+ }
+
+ // Determine alternation base for merge
+ byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1) {
+ }
+
+ // Use or create temporary array b for merging
+ int[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new int[blen];
+ workBase = 0;
+ }
+ if (odd == 0) {
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
+ }
+ else {
+ b = work;
+ ao = 0;
+ bo = workBase - left;
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
+ }
+ else {
+ b[i + bo] = a[q++ + ao];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i + bo] = a[i + ao]
+ ) {
+ }
+ run[++last] = right;
+ }
+ int[] t = a;
+ a = b;
+ b = t;
+ int o = ao;
+ ao = bo;
+ bo = o;
+ }
+ }
+
+ private static void sort(int[] 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) {
+ /*
+ * 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];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left >= right) {
+ return;
+ }
+ }
+ while (a[++left] >= a[left - 1]);
+
+ /*
+ * 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 more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
+ */
+ for (int k = left; ++left <= right; k = ++left) {
+ int a1 = a[k], a2 = a[left];
+
+ if (a1 < a2) {
+ a2 = a1;
+ a1 = 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;
+
+ /*
+ * 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]) {
+ int t = a[e2];
+ a[e2] = a[e1];
+ a[e1] = t;
+ }
+
+ if (a[e3] < a[e2]) {
+ int 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]) {
+ int 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]) {
+ int 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;
+ }
+ }
+ }
+ }
+
+ // 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 (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ int pivot1 = a[e2];
+ int pivot2 = a[e4];
+
+ /*
+ * 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 - 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
+ while (a[great] > pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ 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;
+ }
+ }
+
+ // 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
+ SortingIntTestJMH.sort(a, left, less - 2, leftmost);
+ SortingIntTestJMH.sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 4/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 - 1; ++k <= great; ) {
+ int 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[great] < pivot2
+ 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
+ SortingIntTestJMH.sort(a, less, great, false);
+ }
+ else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ int pivot = a[e3];
+
+ /*
+ * Partitioning 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 = less; k <= great; ++k) {
+ if (a[k] == pivot) {
+ continue;
+ }
+ int ak = a[k];
+ if (ak < pivot) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ ++less;
+ }
+ else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
+ }
+ if (a[great] < pivot) { // a[great] <= pivot
+ a[k] = a[less];
+ a[less] = a[great];
+ ++less;
+ }
+ else { // a[great] == pivot
+ /*
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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] = pivot;
+ }
+ a[great] = ak;
+ --great;
+ }
+ }
+
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
+ SortingIntTestJMH.sort(a, left, less - 1, leftmost);
+ SortingIntTestJMH.sort(a, great + 1, right, false);
+ }
+ }
+
+ private static void swap(int[] arr, int i, int j) {
+ int tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+}
diff --git a/jdk/test/java/util/Arrays/SortingLongBenchmarkTestJMH.java b/jdk/test/java/util/Arrays/SortingLongBenchmarkTestJMH.java
new file mode 100644
index 00000000000..d1e9ae60119
--- /dev/null
+++ b/jdk/test/java/util/Arrays/SortingLongBenchmarkTestJMH.java
@@ -0,0 +1,725 @@
+/*
+ * Copyright 2015 Goldman Sachs.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@State(Scope.Thread)
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+public class SortingLongBenchmarkTestJMH {
+ private static final int QUICKSORT_THRESHOLD = 286;
+ private static final int MAX_RUN_COUNT = 67;
+ private static final int INSERTION_SORT_THRESHOLD = 47;
+ public static final int MAX_VALUE = 1_000_000;
+
+ @Param({"pairFlipZeroPairFlip", "descendingAscending", "zeroHi", "hiZeroLow", "hiFlatLow", "identical",
+ "randomDups", "randomNoDups", "sortedReversedSorted", "pairFlip", "endLessThan"})
+ public String listType;
+
+ private long[] array;
+ private static final int LIST_SIZE = 10_000_000;
+ public static final int NUMBER_OF_ITERATIONS = 10;
+
+ @Setup
+ public void setUp() {
+ Random random = new Random(123456789012345L);
+ this.array = new long[LIST_SIZE];
+ int threeQuarters = (int) (LIST_SIZE * 0.75);
+ if ("zeroHi".equals(this.listType)) {
+ for (int i = 0; i < threeQuarters; i++) {
+ this.array[i] = 0;
+ }
+ int k = 1;
+ for (int i = threeQuarters; i < LIST_SIZE; i++) {
+ this.array[i] = k;
+ k++;
+ }
+ }
+ else if ("hiFlatLow".equals(this.listType)) {
+ int oneThird = LIST_SIZE / 3;
+ for (int i = 0; i < oneThird; i++) {
+ this.array[i] = i;
+ }
+ int twoThirds = oneThird * 2;
+ int constant = oneThird - 1;
+ for (int i = oneThird; i < twoThirds; i++) {
+ this.array[i] = constant;
+ }
+ for (int i = twoThirds; i < LIST_SIZE; i++) {
+ this.array[i] = constant - i + twoThirds;
+ }
+ }
+ else if ("hiZeroLow".equals(this.listType)) {
+ int oneThird = LIST_SIZE / 3;
+ for (int i = 0; i < oneThird; i++) {
+ this.array[i] = i;
+ }
+ int twoThirds = oneThird * 2;
+ for (int i = oneThird; i < twoThirds; i++) {
+ this.array[i] = 0;
+ }
+ for (int i = twoThirds; i < LIST_SIZE; i++) {
+ this.array[i] = oneThird - i + twoThirds;
+ }
+ }
+ else if ("identical".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = 0;
+ }
+ }
+ else if ("randomDups".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = random.nextInt(1000);
+ }
+ }
+ else if ("randomNoDups".equals(this.listType)) {
+ Set set = new HashSet<>();
+ while (set.size() < LIST_SIZE + 1) {
+ set.add(random.nextInt());
+ }
+ List list = new ArrayList<>(LIST_SIZE);
+ list.addAll(set);
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = list.get(i);
+ }
+ }
+ else if ("sortedReversedSorted".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE / 2; i++) {
+ this.array[i] = i;
+ }
+ int num = 0;
+ for (int i = LIST_SIZE / 2; i < LIST_SIZE; i++) {
+ this.array[i] = LIST_SIZE - num;
+ num++;
+ }
+ }
+ else if ("pairFlip".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE; i++) {
+ this.array[i] = i;
+ }
+ for (int i = 0; i < LIST_SIZE; i += 2) {
+ long temp = this.array[i];
+ this.array[i] = this.array[i + 1];
+ this.array[i + 1] = temp;
+ }
+ }
+ else if ("endLessThan".equals(this.listType)) {
+ for (int i = 0; i < LIST_SIZE - 1; i++) {
+ this.array[i] = 3;
+ }
+ this.array[LIST_SIZE - 1] = 1;
+ }
+ else if ("pairFlipZeroPairFlip".equals(this.listType)) {
+ //pairflip
+ for (int i = 0; i < 64; i++) {
+ this.array[i] = i;
+ }
+ for (int i = 0; i < 64; i += 2) {
+ long temp = this.array[i];
+ this.array[i] = this.array[i + 1];
+ this.array[i + 1] = temp;
+ }
+ //zero
+ for (int i = 64; i < this.array.length - 64; i++) {
+ this.array[i] = 0;
+ }
+ //pairflip
+ for (int i = this.array.length - 64; i < this.array.length; i++) {
+ this.array[i] = i;
+ }
+ for (int i = this.array.length - 64; i < this.array.length; i += 2) {
+ long temp = this.array[i];
+ this.array[i] = this.array[i + 1];
+ this.array[i + 1] = temp;
+ }
+ }
+ else if ("pairFlipOneHundredPairFlip".equals(this.listType)) {
+ //10, 5
+ for (int i = 0; i < 64; i++) {
+ if (i % 2 == 0) {
+ this.array[i] = 10;
+ }
+ else {
+ this.array[i] = 5;
+ }
+ }
+
+ //100
+ for (int i = 64; i < this.array.length - 64; i++) {
+ this.array[i] = 100;
+ }
+
+ //10, 5
+ for (int i = this.array.length - 64; i < this.array.length; i++) {
+ if (i % 2 == 0) {
+ this.array[i] = 10;
+ }
+ else {
+ this.array[i] = 5;
+ }
+ }
+ }
+ }
+
+ @Warmup(iterations = 20)
+ @Measurement(iterations = 10)
+ @Benchmark
+ public void sortNewWay() {
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ SortingLongTestJMH.sort(this.array, 0, this.array.length - 1, null, 0, 0);
+ }
+ }
+
+ @Warmup(iterations = 20)
+ @Measurement(iterations = 10)
+ @Benchmark
+ public void sortOldWay() {
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ Arrays.sort(this.array);
+ }
+ }
+
+ /**
+ * Sorts the specified range of the array using the given
+ * workspace array slice if possible for merging
+ *
+ * @param a the array to be sorted
+ * @param left the index of the first element, inclusive, to be sorted
+ * @param right the index of the last element, inclusive, to be sorted
+ * @param work a workspace array (slice)
+ * @param workBase origin of usable space in work array
+ * @param workLen usable size of work array
+ */
+ static void sort(long[] a, int left, int right,
+ long[] work, int workBase, int workLen) {
+// Use Quicksort on small arrays
+ if (right - left < QUICKSORT_THRESHOLD) {
+ SortingLongTestJMH.sort(a, left, right, true);
+ return;
+ }
+
+ /*
+ * Index run[i] is the start of i-th run
+ * (ascending or descending sequence).
+ */
+ int[] run = new int[MAX_RUN_COUNT + 1];
+ int count = 0;
+ run[0] = left;
+
+ // Check if the array is nearly sorted
+ for (int k = left; k < right; run[count] = k) {
+ while (k < right && a[k] == a[k + 1])
+ k++;
+ if (k == right) break;
+ if (a[k] < a[k + 1]) { // ascending
+ while (++k <= right && a[k - 1] <= a[k]) ;
+ }
+ else if (a[k] > a[k + 1]) { // descending
+ while (++k <= right && a[k - 1] >= a[k]) ;
+ for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
+ long t = a[lo];
+ a[lo] = a[hi];
+ a[hi] = t;
+ }
+ }
+ if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+ count--;
+ }
+ /*
+ * The array is not highly structured,
+ * use Quicksort instead of merge sort.
+ */
+ if (++count == MAX_RUN_COUNT) {
+ sort(a, left, right, true);
+ return;
+ }
+ }
+
+ // Check special cases
+ // Implementation note: variable "right" is increased by 1.
+ if (run[count] == right++) {
+ run[++count] = right;
+ }
+ if (count <= 1) { // The array is already sorted
+ return;
+ }
+
+ // Determine alternation base for merge
+ byte odd = 0;
+ for (int n = 1; (n <<= 1) < count; odd ^= 1) {
+ }
+
+ // Use or create temporary array b for merging
+ long[] b; // temp array; alternates with a
+ int ao, bo; // array offsets from 'left'
+ int blen = right - left; // space needed for b
+ if (work == null || workLen < blen || workBase + blen > work.length) {
+ work = new long[blen];
+ workBase = 0;
+ }
+ if (odd == 0) {
+ System.arraycopy(a, left, work, workBase, blen);
+ b = a;
+ bo = 0;
+ a = work;
+ ao = workBase - left;
+ }
+ else {
+ b = work;
+ ao = 0;
+ bo = workBase - left;
+ }
+
+ // Merging
+ for (int last; count > 1; count = last) {
+ for (int k = (last = 0) + 2; k <= count; k += 2) {
+ int hi = run[k], mi = run[k - 1];
+ for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
+ if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
+ b[i + bo] = a[p++ + ao];
+ }
+ else {
+ b[i + bo] = a[q++ + ao];
+ }
+ }
+ run[++last] = hi;
+ }
+ if ((count & 1) != 0) {
+ for (int i = right, lo = run[count - 1]; --i >= lo;
+ b[i + bo] = a[i + ao]
+ ) {
+ }
+ run[++last] = right;
+ }
+ long[] t = a;
+ a = b;
+ b = t;
+ int o = ao;
+ ao = bo;
+ bo = o;
+ }
+ }
+
+ /**
+ * 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
+ if (length < INSERTION_SORT_THRESHOLD) {
+ if (leftmost) {
+ /*
+ * 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];
+ while (ai < a[j]) {
+ a[j + 1] = a[j];
+ if (j-- == left) {
+ break;
+ }
+ }
+ a[j + 1] = ai;
+ }
+ }
+ else {
+ /*
+ * Skip the longest ascending sequence.
+ */
+ do {
+ if (left >= right) {
+ return;
+ }
+ }
+ while (a[++left] >= a[left - 1]);
+
+ /*
+ * 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 more optimized algorithm, so called pair insertion
+ * sort, which is faster (in the context of Quicksort)
+ * than traditional implementation of insertion sort.
+ */
+ for (int k = left; ++left <= right; k = ++left) {
+ long a1 = a[k], a2 = a[left];
+
+ if (a1 < a2) {
+ a2 = a1;
+ a1 = 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;
+
+ /*
+ * 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]) {
+ long t = a[e2];
+ a[e2] = a[e1];
+ a[e1] = t;
+ }
+
+ if (a[e3] < a[e2]) {
+ long 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]) {
+ long 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]) {
+ long 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;
+ }
+ }
+ }
+ }
+
+ // 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 (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
+ /*
+ * 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.
+ */
+ long pivot1 = a[e2];
+ long pivot2 = a[e4];
+
+ /*
+ * 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 - 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
+ while (a[great] > pivot2) {
+ if (great-- == k) {
+ break outer;
+ }
+ }
+ 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;
+ }
+ }
+
+ // 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
+ SortingLongTestJMH.sort(a, left, less - 2, leftmost);
+ SortingLongTestJMH.sort(a, great + 2, right, false);
+
+ /*
+ * If center part is too large (comprises > 4/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 - 1; ++k <= great; ) {
+ long 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[great] < pivot2
+ 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
+ SortingLongTestJMH.sort(a, less, great, false);
+ }
+ else { // Partitioning with one pivot
+ /*
+ * Use the third of the five sorted elements as pivot.
+ * This value is inexpensive approximation of the median.
+ */
+ long pivot = a[e3];
+
+ /*
+ * Partitioning 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 = less; k <= great; ++k) {
+ if (a[k] == pivot) {
+ continue;
+ }
+ long ak = a[k];
+ if (ak < pivot) { // Move a[k] to left part
+ a[k] = a[less];
+ a[less] = ak;
+ ++less;
+ }
+ else { // a[k] > pivot - Move a[k] to right part
+ while (a[great] > pivot) {
+ --great;
+ }
+ if (a[great] < pivot) { // a[great] <= pivot
+ a[k] = a[less];
+ a[less] = a[great];
+ ++less;
+ }
+ else { // a[great] == pivot
+ /*
+ * Even though a[great] equals to pivot, the
+ * assignment a[k] = pivot may be incorrect,
+ * if a[great] and pivot 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] = pivot;
+ }
+ a[great] = ak;
+ --great;
+ }
+ }
+
+ /*
+ * Sort left and right parts recursively.
+ * All elements from center part are equal
+ * and, therefore, already sorted.
+ */
+ SortingLongTestJMH.sort(a, left, less - 1, leftmost);
+ SortingLongTestJMH.sort(a, great + 1, right, false);
+ }
+ }
+
+ private static void swap(long[] arr, int i, int j) {
+ long tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+}
diff --git a/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java b/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java
new file mode 100644
index 00000000000..99bd4cf04d2
--- /dev/null
+++ b/jdk/test/java/util/Arrays/SortingNearlySortedPrimitive.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2015 Goldman Sachs.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @summary Tests the sorting of a large array of sorted primitive values,
+ * predominently for cases where the array is nearly sorted. This tests
+ * code that detects patterns in the array to determine if it is nearly
+ * sorted and if so employs and optimizes merge sort rather than a
+ * Dual-Pivot QuickSort.
+ *
+ * @run testng SortingNearlySortedPrimitive
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.function.Supplier;
+
+public class SortingNearlySortedPrimitive {
+ private static final int ARRAY_SIZE = 1_000_000;
+
+ @DataProvider(name = "arrays")
+ public Object[][] createData() {
+ return new Object[][]{
+ {"hiZeroLowTest", (Supplier) this::hiZeroLowData},
+ {"endLessThanTest", (Supplier) this::endLessThanData},
+ {"highFlatLowTest", (Supplier) this::highFlatLowData},
+ {"identicalTest", (Supplier) this::identicalData},
+ {"sortedReversedSortedTest", (Supplier) this::sortedReversedSortedData},
+ {"pairFlipTest", (Supplier) this::pairFlipData},
+ {"zeroHiTest", (Supplier) this::zeroHiData},
+ };
+ }
+
+ @Test(dataProvider = "arrays")
+ public void runTests(String testName, Supplier dataMethod) throws Exception {
+ int[] intSourceArray = dataMethod.get();
+
+ // Clone source array to ensure it is not modified
+ this.sortAndAssert(intSourceArray.clone());
+ this.sortAndAssert(floatCopyFromInt(intSourceArray));
+ this.sortAndAssert(doubleCopyFromInt(intSourceArray));
+ this.sortAndAssert(longCopyFromInt(intSourceArray));
+ this.sortAndAssert(shortCopyFromInt(intSourceArray));
+ this.sortAndAssert(charCopyFromInt(intSourceArray));
+ }
+
+ private float[] floatCopyFromInt(int[] src) {
+ float[] result = new float[src.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = src[i];
+ }
+ return result;
+ }
+
+ private double[] doubleCopyFromInt(int[] src) {
+ double[] result = new double[src.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = src[i];
+ }
+ return result;
+ }
+
+ private long[] longCopyFromInt(int[] src) {
+ long[] result = new long[src.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = src[i];
+ }
+ return result;
+ }
+
+ private short[] shortCopyFromInt(int[] src) {
+ short[] result = new short[src.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (short) src[i];
+ }
+ return result;
+ }
+
+ private char[] charCopyFromInt(int[] src) {
+ char[] result = new char[src.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (char) src[i];
+ }
+ return result;
+ }
+
+ private void sortAndAssert(int[] array) {
+ Arrays.sort(array);
+ for (int i = 1; i < ARRAY_SIZE; i++) {
+ if (array[i] < array[i - 1]) {
+ throw new AssertionError("not sorted");
+ }
+ }
+ Assert.assertEquals(ARRAY_SIZE, array.length);
+ }
+
+ private void sortAndAssert(char[] array) {
+ Arrays.sort(array);
+ for (int i = 1; i < ARRAY_SIZE; i++) {
+ if (array[i] < array[i - 1]) {
+ throw new AssertionError("not sorted");
+ }
+ }
+ Assert.assertEquals(ARRAY_SIZE, array.length);
+ }
+
+ private void sortAndAssert(short[] array) {
+ Arrays.sort(array);
+ for (int i = 1; i < ARRAY_SIZE; i++) {
+ if (array[i] < array[i - 1]) {
+ throw new AssertionError("not sorted");
+ }
+ }
+ Assert.assertEquals(ARRAY_SIZE, array.length);
+ }
+
+ private void sortAndAssert(double[] array) {
+ Arrays.sort(array);
+ for (int i = 1; i < ARRAY_SIZE; i++) {
+ if (array[i] < array[i - 1]) {
+ throw new AssertionError("not sorted");
+ }
+ }
+ Assert.assertEquals(ARRAY_SIZE, array.length);
+ }
+
+ private void sortAndAssert(float[] array) {
+ Arrays.sort(array);
+ for (int i = 1; i < ARRAY_SIZE; i++) {
+ if (array[i] < array[i - 1]) {
+ throw new AssertionError("not sorted");
+ }
+ }
+ Assert.assertEquals(ARRAY_SIZE, array.length);
+ }
+
+ private void sortAndAssert(long[] array) {
+ Arrays.sort(array);
+ for (int i = 1; i < ARRAY_SIZE; i++) {
+ if (array[i] < array[i - 1]) {
+ throw new AssertionError("not sorted");
+ }
+ }
+ Assert.assertEquals(ARRAY_SIZE, array.length);
+ }
+
+ private int[] zeroHiData() {
+ int[] array = new int[ARRAY_SIZE];
+
+ int threeQuarters = (int) (ARRAY_SIZE * 0.75);
+ for (int i = 0; i < threeQuarters; i++) {
+ array[i] = 0;
+ }
+ int k = 1;
+ for (int i = threeQuarters; i < ARRAY_SIZE; i++) {
+ array[i] = k;
+ k++;
+ }
+
+ return array;
+ }
+
+ private int[] hiZeroLowData() {
+ int[] array = new int[ARRAY_SIZE];
+
+ int oneThird = ARRAY_SIZE / 3;
+ for (int i = 0; i < oneThird; i++) {
+ array[i] = i;
+ }
+ int twoThirds = oneThird * 2;
+ for (int i = oneThird; i < twoThirds; i++) {
+ array[i] = 0;
+ }
+ for (int i = twoThirds; i < ARRAY_SIZE; i++) {
+ array[i] = oneThird - i + twoThirds;
+ }
+ return array;
+ }
+
+ private int[] highFlatLowData() {
+ int[] array = new int[ARRAY_SIZE];
+
+ int oneThird = ARRAY_SIZE / 3;
+ for (int i = 0; i < oneThird; i++) {
+ array[i] = i;
+ }
+ int twoThirds = oneThird * 2;
+ int constant = oneThird - 1;
+ for (int i = oneThird; i < twoThirds; i++) {
+ array[i] = constant;
+ }
+ for (int i = twoThirds; i < ARRAY_SIZE; i++) {
+ array[i] = constant - i + twoThirds;
+ }
+
+ return array;
+ }
+
+ private int[] identicalData() {
+ int[] array = new int[ARRAY_SIZE];
+ int listNumber = 24;
+
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = listNumber;
+ }
+
+ return array;
+ }
+
+ private int[] endLessThanData() {
+ int[] array = new int[ARRAY_SIZE];
+
+ for (int i = 0; i < ARRAY_SIZE - 1; i++) {
+ array[i] = 3;
+ }
+ array[ARRAY_SIZE - 1] = 1;
+
+ return array;
+ }
+
+ private int[] sortedReversedSortedData() {
+ int[] array = new int[ARRAY_SIZE];
+
+ for (int i = 0; i < ARRAY_SIZE / 2; i++) {
+ array[i] = i;
+ }
+ int num = 0;
+ for (int i = ARRAY_SIZE / 2; i < ARRAY_SIZE; i++) {
+ array[i] = ARRAY_SIZE - num;
+ num++;
+ }
+
+ return array;
+ }
+
+ private int[] pairFlipData() {
+ int[] array = new int[ARRAY_SIZE];
+
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = i;
+ }
+ for (int i = 0; i < ARRAY_SIZE; i += 2) {
+ int temp = array[i];
+ array[i] = array[i + 1];
+ array[i + 1] = temp;
+ }
+
+ return array;
+ }
+}
diff --git a/jdk/test/java/util/PropertyPermission/PropertyPermissionCollection.java b/jdk/test/java/util/PropertyPermission/PropertyPermissionCollection.java
new file mode 100644
index 00000000000..b5d2d163720
--- /dev/null
+++ b/jdk/test/java/util/PropertyPermission/PropertyPermissionCollection.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8056179
+ * @summary Unit test for PropertyPermissionCollection subclass
+ */
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.SecurityPermission;
+import java.util.Enumeration;
+import java.util.PropertyPermission;
+
+public class PropertyPermissionCollection {
+
+ public static void main(String[] args) throws Exception {
+
+ int testFail = 0;
+
+ PropertyPermission perm = new PropertyPermission("user.home", "read");
+ PermissionCollection perms = perm.newPermissionCollection();
+
+ // test 1
+ System.out.println
+ ("test 1: add throws IllegalArgExc for wrong perm type");
+ try {
+ perms.add(new SecurityPermission("createAccessControlContext"));
+ System.err.println("Expected IllegalArgumentException");
+ testFail++;
+ } catch (IllegalArgumentException iae) {}
+
+ // test 2
+ System.out.println("test 2: implies returns false for wrong perm type");
+ if (perms.implies(new SecurityPermission("getPolicy"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 3
+ System.out.println
+ ("test 3: implies returns true for match on name and action");
+ perms.add(new PropertyPermission("user.home", "read"));
+ if (!perms.implies(new PropertyPermission("user.home", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 4
+ System.out.println
+ ("test 4: implies returns false for match on name but not action");
+ if (perms.implies(new PropertyPermission("user.home", "write"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 5
+ System.out.println("test 5: implies returns true for match " +
+ "on name and subset of actions");
+ perms.add(new PropertyPermission("java.home", "read, write"));
+ if (!perms.implies(new PropertyPermission("java.home", "write"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 6
+ System.out.println("test 6: implies returns true for aggregate " +
+ "match on name and action");
+ perms.add(new PropertyPermission("user.name", "read"));
+ perms.add(new PropertyPermission("user.name", "write"));
+ if (!perms.implies(new PropertyPermission("user.name", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+ if (!perms.implies(new PropertyPermission("user.name", "write,read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 7
+ System.out.println("test 7: implies returns true for wildcard " +
+ "and match on action");
+ perms.add(new PropertyPermission("foo.*", "read"));
+ if (!perms.implies(new PropertyPermission("foo.bar", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 8
+ System.out.println("test 8: implies returns true for deep " +
+ "wildcard and match on action");
+ if (!perms.implies(new PropertyPermission("foo.bar.baz", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 8
+ System.out.println
+ ("test 8: implies returns false for invalid wildcard");
+ perms.add(new PropertyPermission("baz*", "read"));
+ if (perms.implies(new PropertyPermission("baz.foo", "read"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 9
+ System.out.println("test 9: implies returns true for all " +
+ "wildcard and match on action");
+ perms.add(new PropertyPermission("*", "read"));
+ if (!perms.implies(new PropertyPermission("java.version", "read"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 10
+ System.out.println("test 10: implies returns false for wildcard " +
+ "and non-match on action");
+ if (perms.implies(new PropertyPermission("java.version", "write"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 11
+ System.out.println("test 11: elements returns correct number of perms");
+ int numPerms = 0;
+ Enumeration e = perms.elements();
+ while (e.hasMoreElements()) {
+ numPerms++;
+ System.out.println(e.nextElement());
+ }
+ // the 2 user.name permissions added were combined into one
+ if (numPerms != 6) {
+ System.err.println("Expected 6, got " + numPerms);
+ testFail++;
+ }
+
+ if (testFail > 0) {
+ throw new Exception(testFail + " test(s) failed");
+ }
+ }
+}
diff --git a/jdk/test/java/util/concurrent/LinkedTransferQueue/SpliteratorTraverseAddRemoveTest.java b/jdk/test/java/util/concurrent/LinkedTransferQueue/SpliteratorTraverseAddRemoveTest.java
new file mode 100644
index 00000000000..4d288a27845
--- /dev/null
+++ b/jdk/test/java/util/concurrent/LinkedTransferQueue/SpliteratorTraverseAddRemoveTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @run testng SpliteratorTraverseAddRemoveTest
+ * @bug 8085978
+ * @summary repeatedly traverse the queue using the spliterator while
+ * concurrently adding and removing an element to test that self-linked
+ * nodes are never erroneously reported on traversal
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Spliterator;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+
+@Test
+public class SpliteratorTraverseAddRemoveTest {
+
+ static Object[] of(String desc, Consumer> c) {
+ return new Object[]{desc, c};
+ }
+
+ static void assertIsString(Object e) {
+ Assert.assertTrue(e instanceof String,
+ String.format("Object instanceof %s (actual: instanceof %s)",
+ String.class.getName(),
+ e.getClass().getName()));
+ }
+
+ @DataProvider()
+ public static Object[][] spliteratorTraversers() {
+ return new Object[][]{
+ of("forEachRemaining", q -> {
+ q.spliterator().forEachRemaining(SpliteratorTraverseAddRemoveTest::assertIsString);
+ }),
+ of("tryAdvance", q -> {
+ Spliterator> s = q.spliterator();
+ while (s.tryAdvance(SpliteratorTraverseAddRemoveTest::assertIsString))
+ ;
+ }),
+ of("trySplit then forEachRemaining", q -> {
+ Spliterator> r = q.spliterator();
+
+ List> ss = new ArrayList<>();
+ Spliterator> l;
+ while ((l = r.trySplit()) != null) {
+ ss.add(l);
+ }
+ ss.add(r);
+
+ ss.forEach(s -> s.forEachRemaining(SpliteratorTraverseAddRemoveTest::assertIsString));
+ }),
+ };
+ }
+
+ @Test(dataProvider = "spliteratorTraversers")
+ public void testQueue(String desc, Consumer> c)
+ throws InterruptedException {
+ AtomicBoolean done = new AtomicBoolean(false);
+ Queue msgs = new LinkedTransferQueue<>();
+
+ CompletableFuture traversalTask = CompletableFuture.runAsync(() -> {
+ while (!done.get()) {
+ // Traversal will fail if self-linked nodes of
+ // LinkedTransferQueue are erroneously reported
+ c.accept(msgs);
+ }
+ });
+ CompletableFuture addAndRemoveTask = CompletableFuture.runAsync(() -> {
+ while (!traversalTask.isDone()) {
+ msgs.add("msg");
+ msgs.remove("msg");
+ }
+ });
+
+ Thread.sleep(TimeUnit.SECONDS.toMillis(1));
+ done.set(true);
+
+ addAndRemoveTask.join();
+ Assert.assertTrue(traversalTask.isDone());
+ traversalTask.join();
+ }
+}
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSUnSupportedCiphersTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java
similarity index 90%
rename from jdk/test/javax/net/ssl/DTLS/DTLSUnSupportedCiphersTest.java
rename to jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java
index 9a2755c0408..15569a7dd9d 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSUnSupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java
@@ -27,14 +27,14 @@
* @summary Testing that try to enable unsupported ciphers
* causes IllegalArgumentException.
* @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
- * @run main/othervm -Dtest.security.protocol=DTLS DTLSUnSupportedCiphersTest
+ * @run main/othervm -Dtest.security.protocol=DTLS DTLSUnsupportedCiphersTest
*/
/**
* Testing that a try to enable unsupported ciphers causes IllegalArgumentException.
*/
-public class DTLSUnSupportedCiphersTest {
+public class DTLSUnsupportedCiphersTest {
public static void main(String[] args) {
- UnSupportedCiphersTest.main(args);
+ UnsupportedCiphersTest.main(args);
}
}
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnSupportedCiphersTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java
similarity index 92%
rename from jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnSupportedCiphersTest.java
rename to jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java
index 3cd90f3b0cb..0e656eaad90 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnSupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java
@@ -28,14 +28,14 @@
* causes IllegalArgumentException.
* @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
* @run main/othervm -Dtest.security.protocol=DTLSv1.0
- * DTLSv10UnSupportedCiphersTest
+ * DTLSv10UnsupportedCiphersTest
*/
/**
* Testing that a try to enable unsupported ciphers causes IllegalArgumentException.
*/
-public class DTLSv10UnSupportedCiphersTest {
+public class DTLSv10UnsupportedCiphersTest {
public static void main(String[] args) {
- UnSupportedCiphersTest.main(args);
+ UnsupportedCiphersTest.main(args);
}
}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java b/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java
new file mode 100644
index 00000000000..1d3e49efc42
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS application data exchange using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSDataExchangeTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSDataExchangeTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=krb TLSDataExchangeTest
+ */
+
+/**
+ * Testing TLS application data exchange using each of the supported cipher
+ * suites.
+ */
+public class TLSDataExchangeTest {
+ public static void main(String[] args) {
+ DataExchangeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java
new file mode 100644
index 00000000000..4c9dea4a427
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines closing using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=krb TLSEnginesClosureTest
+ */
+
+/**
+ * Testing TLS engines closing using each of the supported cipher suites.
+ */
+public class TLSEnginesClosureTest {
+ public static void main(String[] args) {
+ EnginesClosureTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java b/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java
new file mode 100644
index 00000000000..0ae33347a2e
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines handshake using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSHandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSHandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=krb TLSHandshakeTest
+ */
+
+/**
+ * Testing TLS engines handshake using each of the supported cipher suites.
+ */
+public class TLSHandshakeTest {
+ public static void main(String[] args) {
+ HandshakeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java b/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java
new file mode 100644
index 00000000000..cde859e891b
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines handshake using each of the supported
+ * cipher suites with different maximum fragment length. Testing of
+ * MFLN extension.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSMFLNTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSMFLNTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=krb TLSMFLNTest
+ */
+
+/**
+ * Testing TLS engines handshake using each of the supported cipher suites with
+ * different maximum fragment length. Testing of MFLN extension.
+ */
+public class TLSMFLNTest {
+ public static void main(String[] args) {
+ MFLNTest.main(args);
+ }
+}
diff --git a/langtools/test/tools/sjavac/test-input/src/pkg10/Cls10.java b/jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java
similarity index 63%
rename from langtools/test/tools/sjavac/test-input/src/pkg10/Cls10.java
rename to jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java
index 41b679a8101..37dd90efc1a 100644
--- a/langtools/test/tools/sjavac/test-input/src/pkg10/Cls10.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java
@@ -1,12 +1,10 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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.
+ * published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -22,9 +20,20 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package pkg10;
-public class Cls10 {
- public pkg13.Cls13 getCls13() {
- return null;
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines do not enable RC4 ciphers by default.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS TLSNotEnabledRC4Test
+ */
+
+/**
+ * Testing DTLS engines do not enable RC4 ciphers by default.
+ */
+public class TLSNotEnabledRC4Test {
+ public static void main(String[] args) throws Exception {
+ NotEnabledRC4Test.main(args);
}
}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java
new file mode 100644
index 00000000000..09d93ccb761
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSRehandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSRehandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=krb TLSRehandshakeTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking using each of the supported cipher
+ * suites.
+ */
+public class TLSRehandshakeTest {
+ public static void main(String[] args) {
+ RehandshakeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java
new file mode 100644
index 00000000000..c16b673dbed
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking with cipher change. New cipher
+ * is taken randomly from the supporetd ciphers list.
+ * @key randomness
+ * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS TLSRehandshakeWithCipherChangeTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking with cipher change. New cipher is taken
+ * randomly from the supported ciphers list.
+ */
+public class TLSRehandshakeWithCipherChangeTest {
+ public static void main(String[] args) {
+ RehandshakeWithCipherChangeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java
new file mode 100644
index 00000000000..a84cd914e72
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking using each of the supported
+ * cipher suites with application data exchange before and after
+ * re-handshake and closing of the engines.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSRehandshakeWithDataExTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSRehandshakeWithDataExTest
+ * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=krb TLSRehandshakeWithDataExTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking using each of the supported cipher suites
+ * with application data exchange before and after re-handshake and closing of
+ * the engines.
+ */
+public class TLSRehandshakeWithDataExTest {
+ public static void main(String[] args) {
+ RehandshakeWithDataExTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java
new file mode 100644
index 00000000000..300ab9b84e6
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing that try to enable unsupported ciphers
+ * causes IllegalArgumentException.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLS TLSUnsupportedCiphersTest
+ */
+
+/**
+ * Testing that a try to enable unsupported ciphers causes IllegalArgumentException.
+ */
+public class TLSUnsupportedCiphersTest {
+ public static void main(String[] args) {
+ UnsupportedCiphersTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSCommon/UnSupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLSCommon/UnsupportedCiphersTest.java
similarity index 93%
rename from jdk/test/javax/net/ssl/TLSCommon/UnSupportedCiphersTest.java
rename to jdk/test/javax/net/ssl/TLSCommon/UnsupportedCiphersTest.java
index dbb5c8a1850..3f7459a8803 100644
--- a/jdk/test/javax/net/ssl/TLSCommon/UnSupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/TLSCommon/UnsupportedCiphersTest.java
@@ -27,10 +27,10 @@ import javax.net.ssl.SSLEngine;
/**
* Testing that try to enable unsupported ciphers causes IllegalArgumentException.
*/
-public class UnSupportedCiphersTest extends SSLEngineTestCase {
+public class UnsupportedCiphersTest extends SSLEngineTestCase {
public static void main(String[] s) {
- UnSupportedCiphersTest test = new UnSupportedCiphersTest();
+ UnsupportedCiphersTest test = new UnsupportedCiphersTest();
test.runTests(Ciphers.UNSUPPORTED_CIPHERS);
}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java
new file mode 100644
index 00000000000..47748467a09
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS application data exchange using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSDataExchangeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm_sni TLSDataExchangeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=krb TLSDataExchangeTest
+ */
+
+/**
+ * Testing TLS application data exchange using each of the supported cipher
+ * suites.
+ */
+public class TLSDataExchangeTest {
+ public static void main(String[] args) {
+ DataExchangeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java
new file mode 100644
index 00000000000..fa875962256
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines closing using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm_sni TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=krb TLSEnginesClosureTest
+ */
+
+/**
+ * Testing TLS engines closing using each of the supported cipher suites.
+ */
+public class TLSEnginesClosureTest {
+ public static void main(String[] args) {
+ EnginesClosureTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java
new file mode 100644
index 00000000000..f48666a40eb
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines handshake using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSHandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm_sni TLSHandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=krb TLSHandshakeTest
+ */
+
+/**
+ * Testing TLS engines handshake using each of the supported cipher suites.
+ */
+public class TLSHandshakeTest {
+ public static void main(String[] args) {
+ HandshakeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java
new file mode 100644
index 00000000000..6df9debe003
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines handshake using each of the supported
+ * cipher suites with different maximum fragment length. Testing of
+ * MFLN extension.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSMFLNTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm_sni TLSMFLNTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=krb TLSMFLNTest
+ */
+
+/**
+ * Testing TLS engines handshake using each of the supported cipher suites with
+ * different maximum fragment length. Testing of MFLN extension.
+ */
+public class TLSMFLNTest {
+ public static void main(String[] args) {
+ MFLNTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java b/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java
new file mode 100644
index 00000000000..d00b09dd382
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines do not enable RC4 ciphers by default.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 TLSNotEnabledRC4Test
+ */
+
+/**
+ * Testing DTLS engines do not enable RC4 ciphers by default.
+ */
+public class TLSNotEnabledRC4Test {
+ public static void main(String[] args) throws Exception {
+ NotEnabledRC4Test.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java
new file mode 100644
index 00000000000..acb69f0ad61
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSRehandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm_sni TLSRehandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=krb TLSRehandshakeTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking using each of the supported cipher
+ * suites.
+ */
+public class TLSRehandshakeTest {
+ public static void main(String[] args) {
+ RehandshakeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java
new file mode 100644
index 00000000000..cf634faabb6
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking with cipher change. New cipher
+ * is taken randomly from the supporetd ciphers list.
+ * @key randomness
+ * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 TLSRehandshakeWithCipherChangeTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking with cipher change. New cipher is taken
+ * randomly from the supported ciphers list.
+ */
+public class TLSRehandshakeWithCipherChangeTest {
+ public static void main(String[] args) {
+ RehandshakeWithCipherChangeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java
new file mode 100644
index 00000000000..601ed311a40
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking using each of the supported
+ * cipher suites with application data exchange before and after
+ * re-handshake and closing of the engines.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSRehandshakeWithDataExTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm_sni TLSRehandshakeWithDataExTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=krb TLSRehandshakeWithDataExTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking using each of the supported cipher suites
+ * with application data exchange before and after re-handshake and closing of
+ * the engines.
+ */
+public class TLSRehandshakeWithDataExTest {
+ public static void main(String[] args) {
+ RehandshakeWithDataExTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java
new file mode 100644
index 00000000000..7cea3e5c2bd
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing that try to enable unsupported ciphers
+ * causes IllegalArgumentException.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1 TLSUnsupportedCiphersTest
+ */
+
+/**
+ * Testing that a try to enable unsupported ciphers causes IllegalArgumentException.
+ */
+public class TLSUnsupportedCiphersTest {
+ public static void main(String[] args) {
+ UnsupportedCiphersTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java
new file mode 100644
index 00000000000..a07a303176c
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS application data exchange using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSDataExchangeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm_sni TLSDataExchangeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=krb TLSDataExchangeTest
+ */
+
+/**
+ * Testing TLS application data exchange using each of the supported cipher
+ * suites.
+ */
+public class TLSDataExchangeTest {
+ public static void main(String[] args) {
+ DataExchangeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java
new file mode 100644
index 00000000000..4a591be9912
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines closing using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm_sni TLSEnginesClosureTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=krb TLSEnginesClosureTest
+ */
+
+/**
+ * Testing TLS engines closing using each of the supported cipher suites.
+ */
+public class TLSEnginesClosureTest {
+ public static void main(String[] args) {
+ EnginesClosureTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java
new file mode 100644
index 00000000000..516a46b9877
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines handshake using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSHandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm_sni TLSHandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=krb TLSHandshakeTest
+ */
+
+/**
+ * Testing TLS engines handshake using each of the supported cipher suites.
+ */
+public class TLSHandshakeTest {
+ public static void main(String[] args) {
+ HandshakeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java
new file mode 100644
index 00000000000..6c6073f190d
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines handshake using each of the supported
+ * cipher suites with different maximum fragment length. Testing of
+ * MFLN extension.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSMFLNTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm_sni TLSMFLNTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=krb TLSMFLNTest
+ */
+
+/**
+ * Testing TLS engines handshake using each of the supported cipher suites with
+ * different maximum fragment length. Testing of MFLN extension.
+ */
+public class TLSMFLNTest {
+ public static void main(String[] args) {
+ MFLNTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java b/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java
new file mode 100644
index 00000000000..c97b1d0ce7f
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines do not enable RC4 ciphers by default.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 TLSNotEnabledRC4Test
+ */
+
+/**
+ * Testing DTLS engines do not enable RC4 ciphers by default.
+ */
+public class TLSNotEnabledRC4Test {
+ public static void main(String[] args) throws Exception {
+ NotEnabledRC4Test.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java
new file mode 100644
index 00000000000..a81868c31e6
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking using each of the supported
+ * cipher suites.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSRehandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm_sni TLSRehandshakeTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=krb TLSRehandshakeTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking using each of the supported cipher
+ * suites.
+ */
+public class TLSRehandshakeTest {
+ public static void main(String[] args) {
+ RehandshakeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java
new file mode 100644
index 00000000000..1537676eafc
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking with cipher change. New cipher
+ * is taken randomly from the supporetd ciphers list.
+ * @key randomness
+ * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 TLSRehandshakeWithCipherChangeTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking with cipher change. New cipher is taken
+ * randomly from the supported ciphers list.
+ */
+public class TLSRehandshakeWithCipherChangeTest {
+ public static void main(String[] args) {
+ RehandshakeWithCipherChangeTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java
new file mode 100644
index 00000000000..00f3acc207c
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing TLS engines re-handshaking using each of the supported
+ * cipher suites with application data exchange before and after
+ * re-handshake and closing of the engines.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSRehandshakeWithDataExTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm_sni TLSRehandshakeWithDataExTest
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=krb TLSRehandshakeWithDataExTest
+ */
+
+/**
+ * Testing TLS engines re-handshaking using each of the supported cipher suites
+ * with application data exchange before and after re-handshake and closing of
+ * the engines.
+ */
+public class TLSRehandshakeWithDataExTest {
+ public static void main(String[] args) {
+ RehandshakeWithDataExTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java
new file mode 100644
index 00000000000..357e93d4ad2
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8085979
+ * @summary Testing that try to enable unsupported ciphers
+ * causes IllegalArgumentException.
+ * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
+ * @run main/othervm -Dtest.security.protocol=TLSv1.1 TLSUnsupportedCiphersTest
+ */
+
+/**
+ * Testing that a try to enable unsupported ciphers causes IllegalArgumentException.
+ */
+public class TLSUnsupportedCiphersTest {
+ public static void main(String[] args) {
+ UnsupportedCiphersTest.main(args);
+ }
+}
diff --git a/jdk/test/javax/security/auth/kerberos/DelegationPermissionCollection.java b/jdk/test/javax/security/auth/kerberos/DelegationPermissionCollection.java
new file mode 100644
index 00000000000..5813cd043ae
--- /dev/null
+++ b/jdk/test/javax/security/auth/kerberos/DelegationPermissionCollection.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8056179
+ * @summary Unit test for DelegationPermissionCollection subclass
+ */
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.SecurityPermission;
+import java.util.Enumeration;
+import javax.security.auth.kerberos.DelegationPermission;
+
+public class DelegationPermissionCollection {
+
+ private static final String FOO = "\"host/foo.example.com@EXAMPLE.COM\"";
+ private static final String BAR = "\"host/bar.example.com@EXAMPLE.COM\"";
+ private static final String TGT = "\"krbtgt/EXAMPLE.COM@EXAMPLE.COM\"";
+
+ public static void main(String[] args) throws Exception {
+
+ int testFail = 0;
+
+ DelegationPermission perm = new DelegationPermission(FOO + " " + TGT);
+ PermissionCollection perms = perm.newPermissionCollection();
+
+ // test 1
+ System.out.println
+ ("test 1: add throws IllegalArgException for wrong perm type");
+ try {
+ perms.add(new SecurityPermission("createAccessControlContext"));
+ System.err.println("Expected IllegalArgumentException");
+ testFail++;
+ } catch (IllegalArgumentException iae) {}
+
+ // test 2
+ System.out.println("test 2: implies returns false for wrong perm type");
+ if (perms.implies(new SecurityPermission("getPolicy"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 3
+ System.out.println("test 3: implies returns true for match on name");
+ perms.add(new DelegationPermission(FOO + " " + TGT));
+ if (!perms.implies(new DelegationPermission(FOO + " " + TGT))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 4
+ System.out.println
+ ("test 4: implies returns false for non-match on name");
+ if (perms.implies(new DelegationPermission(BAR + " " + TGT))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 5
+ System.out.println("test 5: elements returns correct number of perms");
+ int numPerms = 0;
+ Enumeration e = perms.elements();
+ while (e.hasMoreElements()) {
+ numPerms++;
+ System.out.println(e.nextElement());
+ }
+ if (numPerms != 1) {
+ System.err.println("Expected 1, got " + numPerms);
+ testFail++;
+ }
+
+ if (testFail > 0) {
+ throw new Exception(testFail + " test(s) failed");
+ }
+ }
+}
diff --git a/jdk/test/javax/security/auth/kerberos/ServicePermissionCollection.java b/jdk/test/javax/security/auth/kerberos/ServicePermissionCollection.java
new file mode 100644
index 00000000000..bcd2d06289d
--- /dev/null
+++ b/jdk/test/javax/security/auth/kerberos/ServicePermissionCollection.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8056179
+ * @summary Unit test for ServicePermissionCollection subclass
+ */
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.SecurityPermission;
+import java.util.Enumeration;
+import javax.security.auth.kerberos.ServicePermission;
+
+public class ServicePermissionCollection {
+
+ private static final String FOO = "host/foo.example.com@EXAMPLE.COM";
+ private static final String BAR = "host/bar.example.com@EXAMPLE.COM";
+ private static final String BAZ = "host/baz.example.com@EXAMPLE.COM";
+
+ public static void main(String[] args) throws Exception {
+
+ int testFail = 0;
+
+ ServicePermission perm = new ServicePermission(FOO, "accept");
+ PermissionCollection perms = perm.newPermissionCollection();
+
+ // test 1
+ System.out.println
+ ("test 1: add throws IllegalArgExc for wrong permission type");
+ try {
+ perms.add(new SecurityPermission("createAccessControlContext"));
+ System.err.println("Expected IllegalArgumentException");
+ testFail++;
+ } catch (IllegalArgumentException iae) {}
+
+ // test 2
+ System.out.println("test 2: implies returns false for wrong perm type");
+ if (perms.implies(new SecurityPermission("getPolicy"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 3
+ System.out.println
+ ("test 3: implies returns true for match on name and action");
+ perms.add(new ServicePermission(FOO, "accept"));
+ if (!perms.implies(new ServicePermission(FOO, "accept"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 4
+ System.out.println
+ ("test 4: implies returns false for match on name but not action");
+ if (perms.implies(new ServicePermission(FOO, "initiate"))) {
+ System.err.println("Expected false, returned true");
+ testFail++;
+ }
+
+ // test 5
+ System.out.println("test 5: implies returns true for match on " +
+ "name and subset of actions");
+ perms.add(new ServicePermission(BAR, "accept, initiate"));
+ if (!perms.implies(new ServicePermission(BAR, "accept"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 6
+ System.out.println("test 6: implies returns false for aggregate " +
+ "match on name and action");
+ perms.add(new ServicePermission(BAZ, "accept"));
+ perms.add(new ServicePermission(BAZ, "initiate"));
+ if (!perms.implies(new ServicePermission(BAZ, "initiate"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+ if (!perms.implies(new ServicePermission(BAZ, "initiate, accept"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 7
+ System.out.println("test 7: implies returns true for wildcard " +
+ "match on name and action");
+ perms.add(new ServicePermission("*", "initiate"));
+ if (!perms.implies(new ServicePermission("Duke", "initiate"))) {
+ System.err.println("Expected true, returned false");
+ testFail++;
+ }
+
+ // test 8
+ System.out.println("test 8: elements returns correct number of perms");
+ int numPerms = 0;
+ Enumeration e = perms.elements();
+ while (e.hasMoreElements()) {
+ numPerms++;
+ System.out.println(e.nextElement());
+ }
+ // the 2 FOO permissions and the 2 BAZ permisssions
+ // are combined into one
+ if (numPerms != 4) {
+ System.err.println("Expected 4, got " + numPerms);
+ testFail++;
+ }
+
+ if (testFail > 0) {
+ throw new Exception(testFail + " test(s) failed");
+ }
+ }
+}
diff --git a/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java b/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
index 768e6504c69..69fbf206f62 100644
--- a/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
+++ b/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
@@ -21,25 +21,29 @@
* questions.
*/
-/*
- * @test
- * @bug 8042397
- * @summary Unit test for jmap utility test heap configuration reader
- * @library /lib/testlibrary
- * @modules java.management
- * @build jdk.testlibrary.*
- * @build JMapHeapConfigTest LingeredApp TmtoolTestScenario
- * @run main JMapHeapConfigTest
- */
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+
+import jdk.test.lib.apps.LingeredApp;
import jdk.testlibrary.Utils;
import jdk.testlibrary.Platform;
+/*
+ * @test
+ * @bug 8042397
+ * @summary Unit test for jmap utility test heap configuration reader
+ * @library /../../test/lib/share/classes
+ * @library /lib/testlibrary
+ * @modules java.management
+ * @build jdk.testlibrary.*
+ * @build jdk.test.lib.apps.*
+ * @build JMapHeapConfigTest TmtoolTestScenario
+ * @run main JMapHeapConfigTest
+ */
public class JMapHeapConfigTest {
static final String expectedJMapValues[] = {
diff --git a/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java b/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
index 667085f4fe8..049663c86ac 100644
--- a/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
+++ b/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
@@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
+
+import jdk.test.lib.apps.LingeredApp;
import jdk.testlibrary.JDKToolLauncher;
import jdk.testlibrary.Utils;
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 91c24bfd226..c88b1a7021f 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -310,3 +310,4 @@ a28b7f42dae9bd59513beaa5a2d6eb563dc09e08 jdk9-b63
4fcf722b811406a7db8f206d88446c82cda1b5f4 jdk9-b65
fd6bda430d96fc5ab421161de016412f2ddd9082 jdk9-b66
fd782cd69b0497299269952d30a6b88cad960fcf jdk9-b67
+c71857c93f57c63be44258d3d67e656c2bacdb45 jdk9-b68
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index 9c7336af396..892410f9986 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -2175,11 +2175,19 @@ public class Attr extends JCTree.Visitor {
if (isDiamond
&& ((tree.constructorType != null && inferenceContext.free(tree.constructorType))
|| (tree.clazz.type != null && inferenceContext.free(tree.clazz.type)))) {
+ final ResultInfo resultInfoForClassDefinition = this.resultInfo;
inferenceContext.addFreeTypeListener(List.of(tree.constructorType, tree.clazz.type),
instantiatedContext -> {
tree.constructorType = instantiatedContext.asInstType(tree.constructorType);
clazz.type = instantiatedContext.asInstType(clazz.type);
- visitAnonymousClassDefinition(tree, clazz, clazz.type, cdef, localEnv, argtypes, typeargtypes, pkind);
+ ResultInfo prevResult = this.resultInfo;
+ try {
+ this.resultInfo = resultInfoForClassDefinition;
+ visitAnonymousClassDefinition(tree, clazz, clazz.type, cdef,
+ localEnv, argtypes, typeargtypes, pkind);
+ } finally {
+ this.resultInfo = prevResult;
+ }
});
} else {
if (isDiamond && clazztype.hasTag(CLASS)) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java
index 67a2bf86cca..cc9f5706852 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java
@@ -478,22 +478,6 @@ public class Operators {
}
}
- /**
- * Class representing bitwise operator helpers that operate on all primitive types (either boxed or unboxed).
- * Operator lookup is performed after applying binary numeric promotion of the input types.
- */
- class BinaryBitwiseOperator extends BinaryNumericOperator {
-
- BinaryBitwiseOperator(Tag tag) {
- super(tag);
- }
-
- @Override
- public boolean test(Type arg1, Type arg2) {
- return unaryPromotion(arg1).isPrimitive() && unaryPromotion(arg2).isPrimitive();
- }
- }
-
/**
* Class representing bitwise operator helpers that operate on boolean types (either boxed or unboxed).
* Operator lookup is performed assuming both input types are boolean types.
@@ -727,16 +711,19 @@ public class Operators {
.addBinaryOperator(FLOAT, FLOAT, FLOAT, fmod)
.addBinaryOperator(LONG, LONG, LONG, lmod)
.addBinaryOperator(INT, INT, INT, imod),
- new BinaryBitwiseOperator(Tag.BITAND)
- .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, iand)
+ new BinaryBooleanOperator(Tag.BITAND)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, iand),
+ new BinaryNumericOperator(Tag.BITAND)
.addBinaryOperator(LONG, LONG, LONG, land)
.addBinaryOperator(INT, INT, INT, iand),
- new BinaryBitwiseOperator(Tag.BITOR)
- .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ior)
+ new BinaryBooleanOperator(Tag.BITOR)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ior),
+ new BinaryNumericOperator(Tag.BITOR)
.addBinaryOperator(LONG, LONG, LONG, lor)
.addBinaryOperator(INT, INT, INT, ior),
- new BinaryBitwiseOperator(Tag.BITXOR)
- .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ixor)
+ new BinaryBooleanOperator(Tag.BITXOR)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ixor),
+ new BinaryNumericOperator(Tag.BITXOR)
.addBinaryOperator(LONG, LONG, LONG, lxor)
.addBinaryOperator(INT, INT, INT, ixor),
new BinaryShiftOperator(Tag.SL)
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java
index 4b802e013f0..46b9a7313ae 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -26,12 +26,13 @@
package com.sun.tools.sjavac;
import java.io.File;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.sun.tools.javac.util.Assert;
+import com.sun.tools.sjavac.pubapi.PubApi;
/**
* The build state class captures the source code and generated artifacts
@@ -77,7 +78,7 @@ public class BuildState {
*/
Module findModuleFromPackageName(String pkg) {
int cp = pkg.indexOf(':');
- Assert.check(cp != -1);
+ Assert.check(cp != -1, "Could not find package name");
String mod = pkg.substring(0, cp);
return lookupModule(mod);
}
@@ -154,21 +155,28 @@ public class BuildState {
*/
public void calculateDependents() {
dependents = new HashMap<>();
+
for (String s : packages.keySet()) {
Package p = packages.get(s);
- for (String d : p.dependencies()) {
- Set ss = dependents.get(d);
- if (ss == null) {
- ss = new HashSet<>();
- dependents.put(d, ss);
- }
+
+ // Collect all dependencies of the classes in this package
+ Set deps = p.typeDependencies() // maps fqName -> set of dependencies
+ .values()
+ .stream()
+ .reduce(Collections.emptySet(), Util::union);
+
+ // Now reverse the direction
+
+ for (String dep : deps) {
// Add the dependent information to the global dependent map.
- ss.add(s);
- Package dp = packages.get(d);
+ String depPkgStr = ":" + dep.substring(0, dep.lastIndexOf('.'));
+ dependents.merge(depPkgStr, Collections.singleton(s), Util::union);
+
// Also add the dependent information to the package specific map.
// Normally, you do not compile java.lang et al. Therefore
// there are several packages that p depends upon that you
// do not have in your state database. This is perfectly fine.
+ Package dp = packages.get(depPkgStr);
if (dp != null) {
// But this package did exist in the state database.
dp.addDependent(p.name());
@@ -270,11 +278,21 @@ public class BuildState {
public void copyPackagesExcept(BuildState prev, Set recompiled, Set removed) {
for (String pkg : prev.packages().keySet()) {
// Do not copy recompiled or removed packages.
- if (recompiled.contains(pkg) || removed.contains(pkg)) continue;
+ if (recompiled.contains(pkg) || removed.contains(pkg))
+ continue;
+
Module mnew = findModuleFromPackageName(pkg);
Package pprev = prev.packages().get(pkg);
+
+ // Even though we haven't recompiled this package, we may have
+ // information about its public API: It may be a classpath dependency
+ if (packages.containsKey(pkg)) {
+ pprev.setPubapi(PubApi.mergeTypes(pprev.getPubApi(),
+ packages.get(pkg).getPubApi()));
+ }
+
mnew.addPackage(pprev);
- // Do not forget to update the flattened data.
+ // Do not forget to update the flattened data. (See JDK-8071904)
packages.put(pkg, pprev);
}
}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java
index 0a7ae6bf3c2..515beff9ea5 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -25,17 +25,25 @@
package com.sun.tools.sjavac;
-import java.io.*;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.List;
-import java.util.Set;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
import com.sun.tools.sjavac.server.Sjavac;
/**
@@ -63,8 +71,10 @@ public class CleanProperties implements Transformer {
Map> oldPackageDependencies,
URI destRoot,
Map> packageArtifacts,
- Map> packageDependencies,
- Map packagePublicApis,
+ Map>> packageDependencies,
+ Map>> packageCpDependencies,
+ Map packagePublicApis,
+ Map dependencyPublicApis,
int debugLevel,
boolean incremental,
int numCores,
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java
index 8abac1a0475..71151760dc6 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,10 +30,12 @@ import java.io.PrintStream;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Set;
+import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.Sjavac;
import com.sun.tools.sjavac.server.SysInfo;
@@ -73,21 +75,25 @@ public class CompileJavaPackages implements Transformer {
Map> oldPackageDependents,
URI destRoot,
final Map> packageArtifacts,
- final Map> packageDependencies,
- final Map packagePubapis,
+ final Map>> packageDependencies,
+ final Map>> packageCpDependencies,
+ final Map packagePubapis,
+ final Map dependencyPubapis,
int debugLevel,
boolean incremental,
int numCores,
final PrintStream out,
- final PrintStream err)
- {
+ final PrintStream err) {
+
+ Log.debug("Performing CompileJavaPackages transform...");
+
boolean rc = true;
boolean concurrentCompiles = true;
// Fetch the id.
final String id = Util.extractStringOption("id", sjavac.serverSettings());
// Only keep portfile and sjavac settings..
- String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), sjavac.serverSettings());
+ //String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), sjavac.serverSettings());
// Get maximum heap size from the server!
SysInfo sysinfo = sjavac.getSysInfo();
@@ -210,20 +216,44 @@ public class CompileJavaPackages implements Transformer {
final CompileChunk cc = compileChunks[i];
// Pass the num_cores and the id (appended with the chunk number) to the server.
- final String cleanedServerSettings = psServerSettings+",poolsize="+numCores+",id="+id+"-"+i;
-
+ Object lock = new Object();
requests[i] = new Thread() {
@Override
public void run() {
rn[ii] = sjavac.compile("n/a",
- id + "-" + ii,
- args.prepJavacArgs(),
- Collections.emptyList(),
- cc.srcs,
- visibleSources);
- packageArtifacts.putAll(rn[ii].packageArtifacts);
- packageDependencies.putAll(rn[ii].packageDependencies);
- packagePubapis.putAll(rn[ii].packagePubapis);
+ id + "-" + ii,
+ args.prepJavacArgs(),
+ Collections.emptyList(),
+ cc.srcs,
+ visibleSources);
+ // In the code below we have to keep in mind that two
+ // different compilation results may include results for
+ // the same package.
+ synchronized (lock) {
+
+ for (String pkg : rn[ii].packageArtifacts.keySet()) {
+ Set pkgArtifacts = rn[ii].packageArtifacts.get(pkg);
+ packageArtifacts.merge(pkg, pkgArtifacts, Util::union);
+ }
+
+ for (String pkg : rn[ii].packageDependencies.keySet()) {
+ packageDependencies.putIfAbsent(pkg, new HashMap<>());
+ packageDependencies.get(pkg).putAll(rn[ii].packageDependencies.get(pkg));
+ }
+
+ for (String pkg : rn[ii].packageCpDependencies.keySet()) {
+ packageCpDependencies.putIfAbsent(pkg, new HashMap<>());
+ packageCpDependencies.get(pkg).putAll(rn[ii].packageCpDependencies.get(pkg));
+ }
+
+ for (String pkg : rn[ii].packagePubapis.keySet()) {
+ packagePubapis.merge(pkg, rn[ii].packagePubapis.get(pkg), PubApi::mergeTypes);
+ }
+
+ for (String pkg : rn[ii].dependencyPubapis.keySet()) {
+ dependencyPubapis.merge(pkg, rn[ii].dependencyPubapis.get(pkg), PubApi::mergeTypes);
+ }
+ }
}
};
@@ -278,7 +308,6 @@ public class CompileJavaPackages implements Transformer {
return rc;
}
-
/**
* Split up the sources into compile chunks. If old package dependents information
* is available, sort the order of the chunks into the most dependent first!
@@ -294,9 +323,9 @@ public class CompileJavaPackages implements Transformer {
* @return
*/
CompileChunk[] createCompileChunks(Map> pkgSrcs,
- Map> oldPackageDependents,
- int numCompiles,
- int sourcesPerCompile) {
+ Map> oldPackageDependents,
+ int numCompiles,
+ int sourcesPerCompile) {
CompileChunk[] compileChunks = new CompileChunk[numCompiles];
for (int i=0; i> oldPackageDependents,
URI destRoot,
Map> packageArtifacts,
- Map> packageDependencies,
- Map packagePublicApis,
+ Map>> packageDependencies,
+ Map>> packageCpDependencies,
+ Map packagePublicApis,
+ Map dependencyPublicApis,
int debugLevel,
boolean incremental,
int numCores,
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java
index bd4b6f177cb..0dfffb3d79d 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -25,13 +25,20 @@
package com.sun.tools.sjavac;
-import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
import java.net.URI;
-import java.util.Set;
import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import com.sun.tools.sjavac.options.Options;
+import com.sun.tools.sjavac.pubapi.PubApi;
import com.sun.tools.sjavac.server.Sjavac;
/**
@@ -58,8 +65,10 @@ public class CopyFile implements Transformer {
Map